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