Fix xslt_process() to ensure that it inserts a NULL terminator after the
[PostgreSQL.git] / contrib / pgcrypto / pgp-s2k.c
blob70a3edc75ad4019b50b46797a3a370e5026b4044
1 /*
2 * pgp-s2k.c
3 * OpenPGP string2key functions.
5 * Copyright (c) 2005 Marko Kreen
6 * All rights reserved.
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.
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.
29 * $PostgreSQL$
32 #include "postgres.h"
34 #include "px.h"
35 #include "mbuf.h"
36 #include "pgp.h"
38 static int
39 calc_s2k_simple(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
40 unsigned key_len)
42 unsigned md_bs,
43 md_rlen;
44 uint8 buf[PGP_MAX_DIGEST];
45 unsigned preload;
46 unsigned remain;
47 uint8 *dst = s2k->key;
49 md_bs = px_md_block_size(md);
50 md_rlen = px_md_result_size(md);
52 remain = s2k->key_len;
53 preload = 0;
54 while (remain > 0)
56 px_md_reset(md);
58 if (preload)
60 memset(buf, 0, preload);
61 px_md_update(md, buf, preload);
63 preload++;
65 px_md_update(md, key, key_len);
66 px_md_finish(md, buf);
68 if (remain > md_rlen)
70 memcpy(dst, buf, md_rlen);
71 dst += md_rlen;
72 remain -= md_rlen;
74 else
76 memcpy(dst, buf, remain);
77 remain = 0;
80 return 0;
83 static int
84 calc_s2k_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len)
86 unsigned md_bs,
87 md_rlen;
88 uint8 buf[PGP_MAX_DIGEST];
89 unsigned preload = 0;
90 uint8 *dst;
91 unsigned remain;
93 md_bs = px_md_block_size(md);
94 md_rlen = px_md_result_size(md);
96 dst = s2k->key;
97 remain = s2k->key_len;
98 while (remain > 0)
100 px_md_reset(md);
102 if (preload > 0)
104 memset(buf, 0, preload);
105 px_md_update(md, buf, preload);
107 preload++;
109 px_md_update(md, s2k->salt, PGP_S2K_SALT);
110 px_md_update(md, key, key_len);
111 px_md_finish(md, buf);
113 if (remain > md_rlen)
115 memcpy(dst, buf, md_rlen);
116 remain -= md_rlen;
117 dst += md_rlen;
119 else
121 memcpy(dst, buf, remain);
122 remain = 0;
125 return 0;
128 static int
129 calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
130 unsigned key_len)
132 unsigned md_bs,
133 md_rlen;
134 uint8 buf[PGP_MAX_DIGEST];
135 uint8 *dst;
136 unsigned preload = 0;
137 unsigned remain,
139 cval,
140 curcnt,
141 count;
143 cval = s2k->iter;
144 count = ((unsigned) 16 + (cval & 15)) << ((cval >> 4) + 6);
146 md_bs = px_md_block_size(md);
147 md_rlen = px_md_result_size(md);
149 remain = s2k->key_len;
150 dst = s2k->key;
151 while (remain > 0)
153 px_md_reset(md);
155 if (preload)
157 memset(buf, 0, preload);
158 px_md_update(md, buf, preload);
160 preload++;
162 px_md_update(md, s2k->salt, PGP_S2K_SALT);
163 px_md_update(md, key, key_len);
164 curcnt = PGP_S2K_SALT + key_len;
166 while (curcnt < count)
168 if (curcnt + PGP_S2K_SALT < count)
169 c = PGP_S2K_SALT;
170 else
171 c = count - curcnt;
172 px_md_update(md, s2k->salt, c);
173 curcnt += c;
175 if (curcnt + key_len < count)
176 c = key_len;
177 else if (curcnt < count)
178 c = count - curcnt;
179 else
180 break;
181 px_md_update(md, key, c);
182 curcnt += c;
184 px_md_finish(md, buf);
186 if (remain > md_rlen)
188 memcpy(dst, buf, md_rlen);
189 remain -= md_rlen;
190 dst += md_rlen;
192 else
194 memcpy(dst, buf, remain);
195 remain = 0;
198 return 0;
202 * Decide S2K_ISALTED iteration count
204 * Too small: weak
205 * Too big: slow
206 * gpg defaults to 96 => 65536 iters
207 * let it float a bit: 96 + 32 => 262144 iters
209 static int
210 decide_count(unsigned rand_byte)
212 return 96 + (rand_byte & 0x1F);
216 pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo)
218 int res = 0;
219 uint8 tmp;
221 s2k->mode = mode;
222 s2k->digest_algo = digest_algo;
224 switch (s2k->mode)
226 case 0:
227 break;
228 case 1:
229 res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT);
230 break;
231 case 3:
232 res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT);
233 if (res < 0)
234 break;
235 res = px_get_pseudo_random_bytes(&tmp, 1);
236 if (res < 0)
237 break;
238 s2k->iter = decide_count(tmp);
239 break;
240 default:
241 res = PXE_PGP_BAD_S2K_MODE;
243 return res;
247 pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
249 int res = 0;
251 GETBYTE(src, s2k->mode);
252 GETBYTE(src, s2k->digest_algo);
253 switch (s2k->mode)
255 case 0:
256 break;
257 case 1:
258 res = pullf_read_fixed(src, 8, s2k->salt);
259 break;
260 case 3:
261 res = pullf_read_fixed(src, 8, s2k->salt);
262 if (res < 0)
263 break;
264 GETBYTE(src, s2k->iter);
265 break;
266 default:
267 res = PXE_PGP_BAD_S2K_MODE;
269 return res;
273 pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
275 int res;
276 PX_MD *md;
278 s2k->key_len = pgp_get_cipher_key_size(cipher);
279 if (s2k->key_len <= 0)
280 return PXE_PGP_UNSUPPORTED_CIPHER;
282 res = pgp_load_digest(s2k->digest_algo, &md);
283 if (res < 0)
284 return res;
286 switch (s2k->mode)
288 case 0:
289 res = calc_s2k_simple(s2k, md, key, key_len);
290 break;
291 case 1:
292 res = calc_s2k_salted(s2k, md, key, key_len);
293 break;
294 case 3:
295 res = calc_s2k_iter_salted(s2k, md, key, key_len);
296 break;
297 default:
298 res = PXE_PGP_BAD_S2K_MODE;
300 px_md_free(md);
301 return res;