1 /*
2 * pgp-s2k.c
3 * OpenPGP string2key functions.
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-s2k.c
30 */
31
32 #include "postgres.h"
33
34 #include "px.h"
35 #include "pgp.h"
36
37 #include "utils/backend_random.h"
38
39 static int
calc_s2k_simple(PGP_S2K * s2k,PX_MD * md,const uint8 * key,unsigned key_len)40 calc_s2k_simple(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
41 unsigned key_len)
42 {
43 unsigned md_rlen;
44 uint8 buf[PGP_MAX_DIGEST];
45 unsigned preload;
46 unsigned remain;
47 uint8 *dst = s2k->key;
48
49 md_rlen = px_md_result_size(md);
50
51 remain = s2k->key_len;
52 preload = 0;
53 while (remain > 0)
54 {
55 px_md_reset(md);
56
57 if (preload)
58 {
59 memset(buf, 0, preload);
60 px_md_update(md, buf, preload);
61 }
62 preload++;
63
64 px_md_update(md, key, key_len);
65 px_md_finish(md, buf);
66
67 if (remain > md_rlen)
68 {
69 memcpy(dst, buf, md_rlen);
70 dst += md_rlen;
71 remain -= md_rlen;
72 }
73 else
74 {
75 memcpy(dst, buf, remain);
76 remain = 0;
77 }
78 }
79 px_memset(buf, 0, sizeof(buf));
80 return 0;
81 }
82
83 static int
calc_s2k_salted(PGP_S2K * s2k,PX_MD * md,const uint8 * key,unsigned key_len)84 calc_s2k_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len)
85 {
86 unsigned md_rlen;
87 uint8 buf[PGP_MAX_DIGEST];
88 unsigned preload = 0;
89 uint8 *dst;
90 unsigned remain;
91
92 md_rlen = px_md_result_size(md);
93
94 dst = s2k->key;
95 remain = s2k->key_len;
96 while (remain > 0)
97 {
98 px_md_reset(md);
99
100 if (preload > 0)
101 {
102 memset(buf, 0, preload);
103 px_md_update(md, buf, preload);
104 }
105 preload++;
106
107 px_md_update(md, s2k->salt, PGP_S2K_SALT);
108 px_md_update(md, key, key_len);
109 px_md_finish(md, buf);
110
111 if (remain > md_rlen)
112 {
113 memcpy(dst, buf, md_rlen);
114 remain -= md_rlen;
115 dst += md_rlen;
116 }
117 else
118 {
119 memcpy(dst, buf, remain);
120 remain = 0;
121 }
122 }
123 px_memset(buf, 0, sizeof(buf));
124 return 0;
125 }
126
127 static int
calc_s2k_iter_salted(PGP_S2K * s2k,PX_MD * md,const uint8 * key,unsigned key_len)128 calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
129 unsigned key_len)
130 {
131 unsigned md_rlen;
132 uint8 buf[PGP_MAX_DIGEST];
133 uint8 *dst;
134 unsigned preload = 0;
135 unsigned remain,
136 c,
137 curcnt,
138 count;
139
140 count = s2k_decode_count(s2k->iter);
141
142 md_rlen = px_md_result_size(md);
143
144 remain = s2k->key_len;
145 dst = s2k->key;
146 while (remain > 0)
147 {
148 px_md_reset(md);
149
150 if (preload)
151 {
152 memset(buf, 0, preload);
153 px_md_update(md, buf, preload);
154 }
155 preload++;
156
157 px_md_update(md, s2k->salt, PGP_S2K_SALT);
158 px_md_update(md, key, key_len);
159 curcnt = PGP_S2K_SALT + key_len;
160
161 while (curcnt < count)
162 {
163 if (curcnt + PGP_S2K_SALT < count)
164 c = PGP_S2K_SALT;
165 else
166 c = count - curcnt;
167 px_md_update(md, s2k->salt, c);
168 curcnt += c;
169
170 if (curcnt + key_len < count)
171 c = key_len;
172 else if (curcnt < count)
173 c = count - curcnt;
174 else
175 break;
176 px_md_update(md, key, c);
177 curcnt += c;
178 }
179 px_md_finish(md, buf);
180
181 if (remain > md_rlen)
182 {
183 memcpy(dst, buf, md_rlen);
184 remain -= md_rlen;
185 dst += md_rlen;
186 }
187 else
188 {
189 memcpy(dst, buf, remain);
190 remain = 0;
191 }
192 }
193 px_memset(buf, 0, sizeof(buf));
194 return 0;
195 }
196
197 /*
198 * Decide PGP_S2K_ISALTED iteration count (in OpenPGP one-byte representation)
199 *
200 * Too small: weak
201 * Too big: slow
202 * gpg defaults to 96 => 65536 iters
203 *
204 * For our default (count=-1) we let it float a bit: 96 + 32 => between 65536
205 * and 262144 iterations.
206 *
207 * Otherwise, find the smallest number which provides at least the specified
208 * iteration count.
209 */
210 static uint8
decide_s2k_iter(unsigned rand_byte,int count)211 decide_s2k_iter(unsigned rand_byte, int count)
212 {
213 int iter;
214
215 if (count == -1)
216 return 96 + (rand_byte & 0x1F);
217 /* this is a bit brute-force, but should be quick enough */
218 for (iter = 0; iter <= 255; iter++)
219 if (s2k_decode_count(iter) >= count)
220 return iter;
221 return 255;
222 }
223
224 int
pgp_s2k_fill(PGP_S2K * s2k,int mode,int digest_algo,int count)225 pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo, int count)
226 {
227 int res = 0;
228 uint8 tmp;
229
230 s2k->mode = mode;
231 s2k->digest_algo = digest_algo;
232
233 switch (s2k->mode)
234 {
235 case PGP_S2K_SIMPLE:
236 break;
237 case PGP_S2K_SALTED:
238 if (!pg_backend_random((char *) s2k->salt, PGP_S2K_SALT))
239 return PXE_NO_RANDOM;
240 break;
241 case PGP_S2K_ISALTED:
242 if (!pg_backend_random((char *) s2k->salt, PGP_S2K_SALT))
243 return PXE_NO_RANDOM;
244 if (!pg_backend_random((char *) &tmp, 1))
245 return PXE_NO_RANDOM;
246 s2k->iter = decide_s2k_iter(tmp, count);
247 break;
248 default:
249 res = PXE_PGP_BAD_S2K_MODE;
250 }
251 return res;
252 }
253
254 int
pgp_s2k_read(PullFilter * src,PGP_S2K * s2k)255 pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
256 {
257 int res = 0;
258
259 GETBYTE(src, s2k->mode);
260 GETBYTE(src, s2k->digest_algo);
261 switch (s2k->mode)
262 {
263 case 0:
264 break;
265 case 1:
266 res = pullf_read_fixed(src, 8, s2k->salt);
267 break;
268 case 3:
269 res = pullf_read_fixed(src, 8, s2k->salt);
270 if (res < 0)
271 break;
272 GETBYTE(src, s2k->iter);
273 break;
274 default:
275 res = PXE_PGP_BAD_S2K_MODE;
276 }
277 return res;
278 }
279
280 int
pgp_s2k_process(PGP_S2K * s2k,int cipher,const uint8 * key,int key_len)281 pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
282 {
283 int res;
284 PX_MD *md;
285
286 s2k->key_len = pgp_get_cipher_key_size(cipher);
287 if (s2k->key_len <= 0)
288 return PXE_PGP_UNSUPPORTED_CIPHER;
289
290 res = pgp_load_digest(s2k->digest_algo, &md);
291 if (res < 0)
292 return res;
293
294 switch (s2k->mode)
295 {
296 case 0:
297 res = calc_s2k_simple(s2k, md, key, key_len);
298 break;
299 case 1:
300 res = calc_s2k_salted(s2k, md, key, key_len);
301 break;
302 case 3:
303 res = calc_s2k_iter_salted(s2k, md, key, key_len);
304 break;
305 default:
306 res = PXE_PGP_BAD_S2K_MODE;
307 }
308 px_md_free(md);
309 return res;
310 }
311