Age Owner TLA Line data Source code
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 :
37 : typedef int (*mix_data_t) (PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);
38 :
39 : struct PGP_CFB
40 : {
41 : PX_Cipher *ciph;
42 : int block_size;
43 : int pos;
44 : int block_no;
45 : int resync;
46 : uint8 fr[PGP_MAX_BLOCK];
47 : uint8 fre[PGP_MAX_BLOCK];
48 : uint8 encbuf[PGP_MAX_BLOCK];
49 : };
50 :
51 : int
5050 bruce 52 CBC 120 : pgp_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 :
6482 59 120 : res = pgp_load_cipher(algo, &ciph);
60 120 : if (res < 0)
6482 bruce 61 UBC 0 : return res;
62 :
6482 bruce 63 CBC 120 : res = px_cipher_init(ciph, key, key_len, NULL);
64 120 : if (res < 0)
65 : {
6482 bruce 66 UBC 0 : px_cipher_free(ciph);
67 0 : return res;
68 : }
69 :
926 michael 70 CBC 120 : ctx = palloc0(sizeof(*ctx));
6482 bruce 71 120 : ctx->ciph = ciph;
72 120 : ctx->block_size = px_cipher_block_size(ciph);
73 120 : ctx->resync = resync;
74 :
75 120 : if (iv)
76 4 : memcpy(ctx->fr, iv, ctx->block_size);
77 :
78 120 : *ctx_p = ctx;
79 120 : return 0;
80 : }
81 :
82 : void
5050 83 120 : pgp_cfb_free(PGP_CFB *ctx)
84 : {
6482 85 120 : px_cipher_free(ctx->ciph);
3279 86 120 : px_memset(ctx, 0, sizeof(*ctx));
926 michael 87 120 : pfree(ctx);
6482 bruce 88 120 : }
89 :
90 : /*
91 : * Data processing for normal CFB. (PGP_PKT_SYMENCRYPTED_DATA_MDC)
92 : */
93 : static int
5050 94 5278 : mix_encrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
95 : {
96 : int i;
97 :
6482 98 89241 : for (i = ctx->pos; i < ctx->pos + len; i++)
99 83963 : *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
100 5278 : ctx->pos += len;
101 5278 : return len;
102 : }
103 :
104 : static int
5050 105 6170 : mix_decrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
106 : {
107 : int i;
108 :
6482 109 93776 : for (i = ctx->pos; i < ctx->pos + len; i++)
110 : {
111 87606 : ctx->encbuf[i] = *data++;
112 87606 : *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
113 : }
114 6170 : ctx->pos += len;
115 6170 : 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 : */
124 : static int
5050 125 3 : mix_encrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
126 : {
127 : int i,
128 : n;
129 :
130 : /* block #2 is 2 bytes long */
6482 131 3 : if (ctx->block_no == 2)
132 : {
133 1 : n = 2 - ctx->pos;
134 1 : if (len < n)
6482 bruce 135 UBC 0 : n = len;
6482 bruce 136 CBC 3 : for (i = ctx->pos; i < ctx->pos + n; i++)
137 2 : *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
138 :
139 1 : ctx->pos += n;
140 1 : len -= n;
141 :
142 1 : if (ctx->pos == 2)
143 : {
144 1 : memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
145 1 : memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
146 1 : ctx->pos = 0;
147 1 : return n;
148 : }
149 : }
150 33 : for (i = ctx->pos; i < ctx->pos + len; i++)
151 31 : *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
152 2 : ctx->pos += len;
153 2 : return len;
154 : }
155 :
156 : static int
5050 157 18 : mix_decrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
158 : {
159 : int i,
160 : n;
161 :
162 : /* block #2 is 2 bytes long */
6482 163 18 : if (ctx->block_no == 2)
164 : {
165 2 : n = 2 - ctx->pos;
166 2 : if (len < n)
6482 bruce 167 UBC 0 : n = len;
6482 bruce 168 CBC 6 : for (i = ctx->pos; i < ctx->pos + n; i++)
169 : {
170 4 : ctx->encbuf[i] = *data++;
171 4 : *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
172 : }
173 2 : ctx->pos += n;
174 2 : len -= n;
175 :
176 2 : if (ctx->pos == 2)
177 : {
178 2 : memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
179 2 : memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
180 2 : ctx->pos = 0;
181 2 : return n;
182 : }
183 : }
184 90 : for (i = ctx->pos; i < ctx->pos + len; i++)
185 : {
186 74 : ctx->encbuf[i] = *data++;
187 74 : *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
188 : }
189 16 : ctx->pos += len;
190 16 : return len;
191 : }
192 :
193 : /*
194 : * common code for both encrypt and decrypt.
195 : */
196 : static int
5050 197 792 : cfb_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 :
6482 203 1448 : while (len > 0 && ctx->pos > 0)
204 : {
205 656 : n = ctx->block_size - ctx->pos;
206 656 : if (len < n)
207 484 : n = len;
208 :
209 656 : n = mix_data(ctx, data, n, dst);
210 656 : data += n;
211 656 : dst += n;
212 656 : len -= n;
213 :
214 656 : if (ctx->pos == ctx->block_size)
215 : {
216 172 : memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
217 172 : ctx->pos = 0;
218 : }
219 : }
220 :
221 11605 : while (len > 0)
222 : {
223 : unsigned rlen;
224 :
383 peter 225 10813 : px_cipher_encrypt(ctx->ciph, 0, ctx->fr, ctx->block_size, ctx->fre, &rlen);
6482 bruce 226 10813 : if (ctx->block_no < 5)
227 498 : ctx->block_no++;
228 :
229 10813 : n = ctx->block_size;
230 10813 : if (len < n)
231 294 : n = len;
232 :
233 10813 : res = mix_data(ctx, data, n, dst);
234 10813 : data += res;
235 10813 : dst += res;
236 10813 : len -= res;
237 :
238 10813 : if (ctx->pos == ctx->block_size)
239 : {
240 10518 : memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
241 10518 : ctx->pos = 0;
242 : }
243 : }
244 792 : return 0;
245 : }
246 :
247 : /*
248 : * public interface
249 : */
250 :
251 : int
5050 252 54 : pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
253 : {
6385 254 54 : mix_data_t mix = ctx->resync ? mix_encrypt_resync : mix_encrypt_normal;
255 :
6482 256 54 : return cfb_process(ctx, data, len, dst, mix);
257 : }
258 :
259 : int
5050 260 738 : pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
261 : {
6385 262 738 : mix_data_t mix = ctx->resync ? mix_decrypt_resync : mix_decrypt_normal;
263 :
6482 264 738 : return cfb_process(ctx, data, len, dst, mix);
265 : }
|