Age Owner Branch data 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
5421 bruce@momjian.us 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 : :
6853 59 : 120 : res = pgp_load_cipher(algo, &ciph);
60 [ - + ]: 120 : if (res < 0)
6853 bruce@momjian.us 61 :UBC 0 : return res;
62 : :
6853 bruce@momjian.us 63 :CBC 120 : res = px_cipher_init(ciph, key, key_len, NULL);
64 [ - + ]: 120 : if (res < 0)
65 : : {
6853 bruce@momjian.us 66 :UBC 0 : px_cipher_free(ciph);
67 : 0 : return res;
68 : : }
69 : :
1297 michael@paquier.xyz 70 :CBC 120 : ctx = palloc0(sizeof(*ctx));
6853 bruce@momjian.us 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
5421 83 : 120 : pgp_cfb_free(PGP_CFB *ctx)
84 : : {
6853 85 : 120 : px_cipher_free(ctx->ciph);
3650 86 : 120 : px_memset(ctx, 0, sizeof(*ctx));
1297 michael@paquier.xyz 87 : 120 : pfree(ctx);
6853 bruce@momjian.us 88 : 120 : }
89 : :
90 : : /*
91 : : * Data processing for normal CFB. (PGP_PKT_SYMENCRYPTED_DATA_MDC)
92 : : */
93 : : static int
5421 94 : 5278 : mix_encrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
95 : : {
96 : : int i;
97 : :
6853 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
5421 105 : 6170 : mix_decrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
106 : : {
107 : : int i;
108 : :
6853 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
5421 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 */
6853 131 [ + + ]: 3 : if (ctx->block_no == 2)
132 : : {
133 : 1 : n = 2 - ctx->pos;
134 [ - + ]: 1 : if (len < n)
6853 bruce@momjian.us 135 :UBC 0 : n = len;
6853 bruce@momjian.us 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
5421 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 */
6853 163 [ + + ]: 18 : if (ctx->block_no == 2)
164 : : {
165 : 2 : n = 2 - ctx->pos;
166 [ - + ]: 2 : if (len < n)
6853 bruce@momjian.us 167 :UBC 0 : n = len;
6853 bruce@momjian.us 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
5421 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 : :
6853 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 : :
754 peter@eisentraut.org 225 : 10813 : px_cipher_encrypt(ctx->ciph, 0, ctx->fr, ctx->block_size, ctx->fre, &rlen);
6853 bruce@momjian.us 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
5421 252 : 54 : pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
253 : : {
6756 254 [ + + ]: 54 : mix_data_t mix = ctx->resync ? mix_encrypt_resync : mix_encrypt_normal;
255 : :
6853 256 : 54 : return cfb_process(ctx, data, len, dst, mix);
257 : : }
258 : :
259 : : int
5421 260 : 738 : pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
261 : : {
6756 262 [ + + ]: 738 : mix_data_t mix = ctx->resync ? mix_decrypt_resync : mix_decrypt_normal;
263 : :
6853 264 : 738 : return cfb_process(ctx, data, len, dst, mix);
265 : : }
|