PostgreSQL Source Code git master
pgp-cfb.c
Go to the documentation of this file.
1/*
2 * pgp-cfb.c
3 * Implements both normal and PGP-specific CFB mode.
4 *
5 * Copyright (c) 2005 Marko Kreen
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * contrib/pgcrypto/pgp-cfb.c
30 */
31
32#include "postgres.h"
33
34#include "pgp.h"
35#include "px.h"
36
37typedef int (*mix_data_t) (PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);
38
39struct PGP_CFB
40{
43 int pos;
45 int resync;
49};
50
51int
52pgp_cfb_create(PGP_CFB **ctx_p, int algo, const uint8 *key, int key_len,
53 int resync, uint8 *iv)
54{
55 int res;
56 PX_Cipher *ciph;
57 PGP_CFB *ctx;
58
59 res = pgp_load_cipher(algo, &ciph);
60 if (res < 0)
61 return res;
62
63 res = px_cipher_init(ciph, key, key_len, NULL);
64 if (res < 0)
65 {
66 px_cipher_free(ciph);
67 return res;
68 }
69
70 ctx = palloc0(sizeof(*ctx));
71 ctx->ciph = ciph;
73 ctx->resync = resync;
74
75 if (iv)
76 memcpy(ctx->fr, iv, ctx->block_size);
77
78 *ctx_p = ctx;
79 return 0;
80}
81
82void
84{
85 px_cipher_free(ctx->ciph);
86 px_memset(ctx, 0, sizeof(*ctx));
87 pfree(ctx);
88}
89
90/*
91 * Data processing for normal CFB. (PGP_PKT_SYMENCRYPTED_DATA_MDC)
92 */
93static int
94mix_encrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
95{
96 int i;
97
98 for (i = ctx->pos; i < ctx->pos + len; i++)
99 *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
100 ctx->pos += len;
101 return len;
102}
103
104static int
106{
107 int i;
108
109 for (i = ctx->pos; i < ctx->pos + len; i++)
110 {
111 ctx->encbuf[i] = *data++;
112 *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
113 }
114 ctx->pos += len;
115 return len;
116}
117
118/*
119 * Data processing for old PGP CFB mode. (PGP_PKT_SYMENCRYPTED_DATA)
120 *
121 * The goal is to hide the horror from the rest of the code,
122 * thus its all concentrated here.
123 */
124static int
126{
127 int i,
128 n;
129
130 /* block #2 is 2 bytes long */
131 if (ctx->block_no == 2)
132 {
133 n = 2 - ctx->pos;
134 if (len < n)
135 n = len;
136 for (i = ctx->pos; i < ctx->pos + n; i++)
137 *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
138
139 ctx->pos += n;
140 len -= n;
141
142 if (ctx->pos == 2)
143 {
144 memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
145 memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
146 ctx->pos = 0;
147 return n;
148 }
149 }
150 for (i = ctx->pos; i < ctx->pos + len; i++)
151 *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
152 ctx->pos += len;
153 return len;
154}
155
156static int
158{
159 int i,
160 n;
161
162 /* block #2 is 2 bytes long */
163 if (ctx->block_no == 2)
164 {
165 n = 2 - ctx->pos;
166 if (len < n)
167 n = len;
168 for (i = ctx->pos; i < ctx->pos + n; i++)
169 {
170 ctx->encbuf[i] = *data++;
171 *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
172 }
173 ctx->pos += n;
174 len -= n;
175
176 if (ctx->pos == 2)
177 {
178 memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
179 memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
180 ctx->pos = 0;
181 return n;
182 }
183 }
184 for (i = ctx->pos; i < ctx->pos + len; i++)
185 {
186 ctx->encbuf[i] = *data++;
187 *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
188 }
189 ctx->pos += len;
190 return len;
191}
192
193/*
194 * common code for both encrypt and decrypt.
195 */
196static int
197cfb_process(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst,
198 mix_data_t mix_data)
199{
200 int n;
201 int res;
202
203 while (len > 0 && ctx->pos > 0)
204 {
205 n = ctx->block_size - ctx->pos;
206 if (len < n)
207 n = len;
208
209 n = mix_data(ctx, data, n, dst);
210 data += n;
211 dst += n;
212 len -= n;
213
214 if (ctx->pos == ctx->block_size)
215 {
216 memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
217 ctx->pos = 0;
218 }
219 }
220
221 while (len > 0)
222 {
223 unsigned rlen;
224
225 px_cipher_encrypt(ctx->ciph, 0, ctx->fr, ctx->block_size, ctx->fre, &rlen);
226 if (ctx->block_no < 5)
227 ctx->block_no++;
228
229 n = ctx->block_size;
230 if (len < n)
231 n = len;
232
233 res = mix_data(ctx, data, n, dst);
234 data += res;
235 dst += res;
236 len -= res;
237
238 if (ctx->pos == ctx->block_size)
239 {
240 memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
241 ctx->pos = 0;
242 }
243 }
244 return 0;
245}
246
247/*
248 * public interface
249 */
250
251int
252pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
253{
255
256 return cfb_process(ctx, data, len, dst, mix);
257}
258
259int
260pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
261{
263
264 return cfb_process(ctx, data, len, dst, mix);
265}
uint8_t uint8
Definition: c.h:500
#define mix(a, b, c)
Definition: hashfn.c:82
int i
Definition: isn.c:74
void pfree(void *pointer)
Definition: mcxt.c:1524
void * palloc0(Size size)
Definition: mcxt.c:1347
const void size_t len
const void * data
static int mix_decrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:157
int pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:252
void pgp_cfb_free(PGP_CFB *ctx)
Definition: pgp-cfb.c:83
static int mix_encrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:125
static int cfb_process(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst, mix_data_t mix_data)
Definition: pgp-cfb.c:197
int(* mix_data_t)(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:37
int pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:260
static int mix_decrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:105
static int mix_encrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:94
int pgp_cfb_create(PGP_CFB **ctx_p, int algo, const uint8 *key, int key_len, int resync, uint8 *iv)
Definition: pgp-cfb.c:52
int pgp_load_cipher(int code, PX_Cipher **res)
Definition: pgp.c:157
#define PGP_MAX_BLOCK
Definition: pgp.h:113
void px_memset(void *ptr, int c, size_t len)
Definition: px.c:123
#define px_cipher_free(c)
Definition: px.h:226
#define px_cipher_block_size(c)
Definition: px.h:219
#define px_cipher_encrypt(c, padding, data, dlen, res, rlen)
Definition: px.h:222
#define px_cipher_init(c, k, klen, iv)
Definition: px.h:221
int block_size
Definition: pgp-cfb.c:42
PX_Cipher * ciph
Definition: pgp-cfb.c:41
int pos
Definition: pgp-cfb.c:43
uint8 fre[PGP_MAX_BLOCK]
Definition: pgp-cfb.c:47
uint8 encbuf[PGP_MAX_BLOCK]
Definition: pgp-cfb.c:48
uint8 fr[PGP_MAX_BLOCK]
Definition: pgp-cfb.c:46
int resync
Definition: pgp-cfb.c:45
int block_no
Definition: pgp-cfb.c:44
Definition: px.h:149