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