At update of non-LP_NORMAL TID, fail instead of corrupting page header.
[pgsql.git] / contrib / pgcrypto / pgp-s2k.c
blob81ca1f094a16f5a0e145692d94e96d2f4014976e
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 * contrib/pgcrypto/pgp-s2k.c
32 #include "postgres.h"
34 #include "pgp.h"
35 #include "px.h"
37 static int
38 calc_s2k_simple(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
39 unsigned key_len)
41 unsigned md_rlen;
42 uint8 buf[PGP_MAX_DIGEST];
43 unsigned preload;
44 unsigned remain;
45 uint8 *dst = s2k->key;
47 md_rlen = px_md_result_size(md);
49 remain = s2k->key_len;
50 preload = 0;
51 while (remain > 0)
53 px_md_reset(md);
55 if (preload)
57 memset(buf, 0, preload);
58 px_md_update(md, buf, preload);
60 preload++;
62 px_md_update(md, key, key_len);
63 px_md_finish(md, buf);
65 if (remain > md_rlen)
67 memcpy(dst, buf, md_rlen);
68 dst += md_rlen;
69 remain -= md_rlen;
71 else
73 memcpy(dst, buf, remain);
74 remain = 0;
77 px_memset(buf, 0, sizeof(buf));
78 return 0;
81 static int
82 calc_s2k_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len)
84 unsigned md_rlen;
85 uint8 buf[PGP_MAX_DIGEST];
86 unsigned preload = 0;
87 uint8 *dst;
88 unsigned remain;
90 md_rlen = px_md_result_size(md);
92 dst = s2k->key;
93 remain = s2k->key_len;
94 while (remain > 0)
96 px_md_reset(md);
98 if (preload > 0)
100 memset(buf, 0, preload);
101 px_md_update(md, buf, preload);
103 preload++;
105 px_md_update(md, s2k->salt, PGP_S2K_SALT);
106 px_md_update(md, key, key_len);
107 px_md_finish(md, buf);
109 if (remain > md_rlen)
111 memcpy(dst, buf, md_rlen);
112 remain -= md_rlen;
113 dst += md_rlen;
115 else
117 memcpy(dst, buf, remain);
118 remain = 0;
121 px_memset(buf, 0, sizeof(buf));
122 return 0;
125 static int
126 calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
127 unsigned key_len)
129 unsigned md_rlen;
130 uint8 buf[PGP_MAX_DIGEST];
131 uint8 *dst;
132 unsigned preload = 0;
133 unsigned remain,
135 curcnt,
136 count;
138 count = s2k_decode_count(s2k->iter);
140 md_rlen = px_md_result_size(md);
142 remain = s2k->key_len;
143 dst = s2k->key;
144 while (remain > 0)
146 px_md_reset(md);
148 if (preload)
150 memset(buf, 0, preload);
151 px_md_update(md, buf, preload);
153 preload++;
155 px_md_update(md, s2k->salt, PGP_S2K_SALT);
156 px_md_update(md, key, key_len);
157 curcnt = PGP_S2K_SALT + key_len;
159 while (curcnt < count)
161 if (curcnt + PGP_S2K_SALT < count)
162 c = PGP_S2K_SALT;
163 else
164 c = count - curcnt;
165 px_md_update(md, s2k->salt, c);
166 curcnt += c;
168 if (curcnt + key_len < count)
169 c = key_len;
170 else if (curcnt < count)
171 c = count - curcnt;
172 else
173 break;
174 px_md_update(md, key, c);
175 curcnt += c;
177 px_md_finish(md, buf);
179 if (remain > md_rlen)
181 memcpy(dst, buf, md_rlen);
182 remain -= md_rlen;
183 dst += md_rlen;
185 else
187 memcpy(dst, buf, remain);
188 remain = 0;
191 px_memset(buf, 0, sizeof(buf));
192 return 0;
196 * Decide PGP_S2K_ISALTED iteration count (in OpenPGP one-byte representation)
198 * Too small: weak
199 * Too big: slow
200 * gpg defaults to 96 => 65536 iters
202 * For our default (count=-1) we let it float a bit: 96 + 32 => between 65536
203 * and 262144 iterations.
205 * Otherwise, find the smallest number which provides at least the specified
206 * iteration count.
208 static uint8
209 decide_s2k_iter(unsigned rand_byte, int count)
211 int iter;
213 if (count == -1)
214 return 96 + (rand_byte & 0x1F);
215 /* this is a bit brute-force, but should be quick enough */
216 for (iter = 0; iter <= 255; iter++)
217 if (s2k_decode_count(iter) >= count)
218 return iter;
219 return 255;
223 pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo, int count)
225 int res = 0;
226 uint8 tmp;
228 s2k->mode = mode;
229 s2k->digest_algo = digest_algo;
231 switch (s2k->mode)
233 case PGP_S2K_SIMPLE:
234 break;
235 case PGP_S2K_SALTED:
236 if (!pg_strong_random(s2k->salt, PGP_S2K_SALT))
237 return PXE_NO_RANDOM;
238 break;
239 case PGP_S2K_ISALTED:
240 if (!pg_strong_random(s2k->salt, PGP_S2K_SALT))
241 return PXE_NO_RANDOM;
242 if (!pg_strong_random(&tmp, 1))
243 return PXE_NO_RANDOM;
244 s2k->iter = decide_s2k_iter(tmp, count);
245 break;
246 default:
247 res = PXE_PGP_BAD_S2K_MODE;
249 return res;
253 pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
255 int res = 0;
257 GETBYTE(src, s2k->mode);
258 GETBYTE(src, s2k->digest_algo);
259 switch (s2k->mode)
261 case 0:
262 break;
263 case 1:
264 res = pullf_read_fixed(src, 8, s2k->salt);
265 break;
266 case 3:
267 res = pullf_read_fixed(src, 8, s2k->salt);
268 if (res < 0)
269 break;
270 GETBYTE(src, s2k->iter);
271 break;
272 default:
273 res = PXE_PGP_BAD_S2K_MODE;
275 return res;
279 pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
281 int res;
282 PX_MD *md;
284 s2k->key_len = pgp_get_cipher_key_size(cipher);
285 if (s2k->key_len <= 0)
286 return PXE_PGP_UNSUPPORTED_CIPHER;
288 res = pgp_load_digest(s2k->digest_algo, &md);
289 if (res < 0)
290 return res;
292 switch (s2k->mode)
294 case 0:
295 res = calc_s2k_simple(s2k, md, key, key_len);
296 break;
297 case 1:
298 res = calc_s2k_salted(s2k, md, key, key_len);
299 break;
300 case 3:
301 res = calc_s2k_iter_salted(s2k, md, key, key_len);
302 break;
303 default:
304 res = PXE_PGP_BAD_S2K_MODE;
306 px_md_free(md);
307 return res;