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