Only skip pages marked as clean in the visibility map, if the last 32
[PostgreSQL.git] / contrib / pgcrypto / pgp-pubkey.c
blob2c1311134d5aae4bc69b3f1b5fd7488c6c906d71
1 /*
2 * pgp-pubkey.c
3 * Read public or secret key.
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$
31 #include "postgres.h"
33 #include "px.h"
34 #include "mbuf.h"
35 #include "pgp.h"
37 int
38 pgp_key_alloc(PGP_PubKey ** pk_p)
40 PGP_PubKey *pk;
42 pk = px_alloc(sizeof(*pk));
43 memset(pk, 0, sizeof(*pk));
44 *pk_p = pk;
45 return 0;
48 void
49 pgp_key_free(PGP_PubKey * pk)
51 if (pk == NULL)
52 return;
54 switch (pk->algo)
56 case PGP_PUB_ELG_ENCRYPT:
57 pgp_mpi_free(pk->pub.elg.p);
58 pgp_mpi_free(pk->pub.elg.g);
59 pgp_mpi_free(pk->pub.elg.y);
60 pgp_mpi_free(pk->sec.elg.x);
61 break;
62 case PGP_PUB_RSA_SIGN:
63 case PGP_PUB_RSA_ENCRYPT:
64 case PGP_PUB_RSA_ENCRYPT_SIGN:
65 pgp_mpi_free(pk->pub.rsa.n);
66 pgp_mpi_free(pk->pub.rsa.e);
67 pgp_mpi_free(pk->sec.rsa.d);
68 pgp_mpi_free(pk->sec.rsa.p);
69 pgp_mpi_free(pk->sec.rsa.q);
70 pgp_mpi_free(pk->sec.rsa.u);
71 break;
72 case PGP_PUB_DSA_SIGN:
73 pgp_mpi_free(pk->pub.dsa.p);
74 pgp_mpi_free(pk->pub.dsa.q);
75 pgp_mpi_free(pk->pub.dsa.g);
76 pgp_mpi_free(pk->pub.dsa.y);
77 pgp_mpi_free(pk->sec.dsa.x);
78 break;
80 memset(pk, 0, sizeof(*pk));
81 px_free(pk);
84 static int
85 calc_key_id(PGP_PubKey * pk)
87 int res;
88 PX_MD *md;
89 int len;
90 uint8 hdr[3];
91 uint8 hash[20];
93 res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
94 if (res < 0)
95 return res;
97 len = 1 + 4 + 1;
98 switch (pk->algo)
100 case PGP_PUB_ELG_ENCRYPT:
101 len += 2 + pk->pub.elg.p->bytes;
102 len += 2 + pk->pub.elg.g->bytes;
103 len += 2 + pk->pub.elg.y->bytes;
104 break;
105 case PGP_PUB_RSA_SIGN:
106 case PGP_PUB_RSA_ENCRYPT:
107 case PGP_PUB_RSA_ENCRYPT_SIGN:
108 len += 2 + pk->pub.rsa.n->bytes;
109 len += 2 + pk->pub.rsa.e->bytes;
110 break;
111 case PGP_PUB_DSA_SIGN:
112 len += 2 + pk->pub.dsa.p->bytes;
113 len += 2 + pk->pub.dsa.q->bytes;
114 len += 2 + pk->pub.dsa.g->bytes;
115 len += 2 + pk->pub.dsa.y->bytes;
116 break;
119 hdr[0] = 0x99;
120 hdr[1] = len >> 8;
121 hdr[2] = len & 0xFF;
122 px_md_update(md, hdr, 3);
124 px_md_update(md, &pk->ver, 1);
125 px_md_update(md, pk->time, 4);
126 px_md_update(md, &pk->algo, 1);
128 switch (pk->algo)
130 case PGP_PUB_ELG_ENCRYPT:
131 pgp_mpi_hash(md, pk->pub.elg.p);
132 pgp_mpi_hash(md, pk->pub.elg.g);
133 pgp_mpi_hash(md, pk->pub.elg.y);
134 break;
135 case PGP_PUB_RSA_SIGN:
136 case PGP_PUB_RSA_ENCRYPT:
137 case PGP_PUB_RSA_ENCRYPT_SIGN:
138 pgp_mpi_hash(md, pk->pub.rsa.n);
139 pgp_mpi_hash(md, pk->pub.rsa.e);
140 break;
141 case PGP_PUB_DSA_SIGN:
142 pgp_mpi_hash(md, pk->pub.dsa.p);
143 pgp_mpi_hash(md, pk->pub.dsa.q);
144 pgp_mpi_hash(md, pk->pub.dsa.g);
145 pgp_mpi_hash(md, pk->pub.dsa.y);
146 break;
149 px_md_finish(md, hash);
150 px_md_free(md);
152 memcpy(pk->key_id, hash + 12, 8);
153 memset(hash, 0, 20);
155 return 0;
159 _pgp_read_public_key(PullFilter * pkt, PGP_PubKey ** pk_p)
161 int res;
162 PGP_PubKey *pk;
164 res = pgp_key_alloc(&pk);
165 if (res < 0)
166 return res;
168 /* get version */
169 GETBYTE(pkt, pk->ver);
170 if (pk->ver != 4)
172 res = PXE_PGP_NOT_V4_KEYPKT;
173 goto out;
176 /* read time */
177 res = pullf_read_fixed(pkt, 4, pk->time);
178 if (res < 0)
179 goto out;
181 /* pubkey algorithm */
182 GETBYTE(pkt, pk->algo);
184 switch (pk->algo)
186 case PGP_PUB_DSA_SIGN:
187 res = pgp_mpi_read(pkt, &pk->pub.dsa.p);
188 if (res < 0)
189 break;
190 res = pgp_mpi_read(pkt, &pk->pub.dsa.q);
191 if (res < 0)
192 break;
193 res = pgp_mpi_read(pkt, &pk->pub.dsa.g);
194 if (res < 0)
195 break;
196 res = pgp_mpi_read(pkt, &pk->pub.dsa.y);
197 if (res < 0)
198 break;
200 res = calc_key_id(pk);
201 break;
203 case PGP_PUB_RSA_SIGN:
204 case PGP_PUB_RSA_ENCRYPT:
205 case PGP_PUB_RSA_ENCRYPT_SIGN:
206 res = pgp_mpi_read(pkt, &pk->pub.rsa.n);
207 if (res < 0)
208 break;
209 res = pgp_mpi_read(pkt, &pk->pub.rsa.e);
210 if (res < 0)
211 break;
213 res = calc_key_id(pk);
215 if (pk->algo != PGP_PUB_RSA_SIGN)
216 pk->can_encrypt = 1;
217 break;
219 case PGP_PUB_ELG_ENCRYPT:
220 res = pgp_mpi_read(pkt, &pk->pub.elg.p);
221 if (res < 0)
222 break;
223 res = pgp_mpi_read(pkt, &pk->pub.elg.g);
224 if (res < 0)
225 break;
226 res = pgp_mpi_read(pkt, &pk->pub.elg.y);
227 if (res < 0)
228 break;
230 res = calc_key_id(pk);
232 pk->can_encrypt = 1;
233 break;
235 default:
236 px_debug("unknown public algo: %d", pk->algo);
237 res = PXE_PGP_UNKNOWN_PUBALGO;
240 out:
241 if (res < 0)
242 pgp_key_free(pk);
243 else
244 *pk_p = pk;
246 return res;
249 #define HIDE_CLEAR 0
250 #define HIDE_CKSUM 255
251 #define HIDE_SHA1 254
253 static int
254 check_key_sha1(PullFilter * src, PGP_PubKey * pk)
256 int res;
257 uint8 got_sha1[20];
258 uint8 my_sha1[20];
259 PX_MD *md;
261 res = pullf_read_fixed(src, 20, got_sha1);
262 if (res < 0)
263 return res;
265 res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
266 if (res < 0)
267 goto err;
268 switch (pk->algo)
270 case PGP_PUB_ELG_ENCRYPT:
271 pgp_mpi_hash(md, pk->sec.elg.x);
272 break;
273 case PGP_PUB_RSA_SIGN:
274 case PGP_PUB_RSA_ENCRYPT:
275 case PGP_PUB_RSA_ENCRYPT_SIGN:
276 pgp_mpi_hash(md, pk->sec.rsa.d);
277 pgp_mpi_hash(md, pk->sec.rsa.p);
278 pgp_mpi_hash(md, pk->sec.rsa.q);
279 pgp_mpi_hash(md, pk->sec.rsa.u);
280 break;
281 case PGP_PUB_DSA_SIGN:
282 pgp_mpi_hash(md, pk->sec.dsa.x);
283 break;
285 px_md_finish(md, my_sha1);
286 px_md_free(md);
288 if (memcmp(my_sha1, got_sha1, 20) != 0)
290 px_debug("key sha1 check failed");
291 res = PXE_PGP_KEYPKT_CORRUPT;
293 err:
294 memset(got_sha1, 0, 20);
295 memset(my_sha1, 0, 20);
296 return res;
299 static int
300 check_key_cksum(PullFilter * src, PGP_PubKey * pk)
302 int res;
303 unsigned got_cksum,
304 my_cksum = 0;
305 uint8 buf[2];
307 res = pullf_read_fixed(src, 2, buf);
308 if (res < 0)
309 return res;
311 got_cksum = ((unsigned) buf[0] << 8) + buf[1];
312 switch (pk->algo)
314 case PGP_PUB_ELG_ENCRYPT:
315 my_cksum = pgp_mpi_cksum(0, pk->sec.elg.x);
316 break;
317 case PGP_PUB_RSA_SIGN:
318 case PGP_PUB_RSA_ENCRYPT:
319 case PGP_PUB_RSA_ENCRYPT_SIGN:
320 my_cksum = pgp_mpi_cksum(0, pk->sec.rsa.d);
321 my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.p);
322 my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.q);
323 my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.u);
324 break;
325 case PGP_PUB_DSA_SIGN:
326 my_cksum = pgp_mpi_cksum(0, pk->sec.dsa.x);
327 break;
329 if (my_cksum != got_cksum)
331 px_debug("key cksum check failed");
332 return PXE_PGP_KEYPKT_CORRUPT;
334 return 0;
337 static int
338 process_secret_key(PullFilter * pkt, PGP_PubKey ** pk_p,
339 const uint8 *key, int key_len)
341 int res;
342 int hide_type;
343 int cipher_algo;
344 int bs;
345 uint8 iv[512];
346 PullFilter *pf_decrypt = NULL,
347 *pf_key;
348 PGP_CFB *cfb = NULL;
349 PGP_S2K s2k;
350 PGP_PubKey *pk;
352 /* first read public key part */
353 res = _pgp_read_public_key(pkt, &pk);
354 if (res < 0)
355 return res;
358 * is secret key encrypted?
360 GETBYTE(pkt, hide_type);
361 if (hide_type == HIDE_SHA1 || hide_type == HIDE_CKSUM)
363 if (key == NULL)
364 return PXE_PGP_NEED_SECRET_PSW;
365 GETBYTE(pkt, cipher_algo);
366 res = pgp_s2k_read(pkt, &s2k);
367 if (res < 0)
368 return res;
370 res = pgp_s2k_process(&s2k, cipher_algo, key, key_len);
371 if (res < 0)
372 return res;
374 bs = pgp_get_cipher_block_size(cipher_algo);
375 if (bs == 0)
377 px_debug("unknown cipher algo=%d", cipher_algo);
378 return PXE_PGP_UNSUPPORTED_CIPHER;
380 res = pullf_read_fixed(pkt, bs, iv);
381 if (res < 0)
382 return res;
385 * create decrypt filter
387 res = pgp_cfb_create(&cfb, cipher_algo, s2k.key, s2k.key_len, 0, iv);
388 if (res < 0)
389 return res;
390 res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
391 if (res < 0)
392 return res;
393 pf_key = pf_decrypt;
395 else if (hide_type == HIDE_CLEAR)
397 pf_key = pkt;
399 else
401 px_debug("unknown hide type");
402 return PXE_PGP_KEYPKT_CORRUPT;
405 /* read secret key */
406 switch (pk->algo)
408 case PGP_PUB_RSA_SIGN:
409 case PGP_PUB_RSA_ENCRYPT:
410 case PGP_PUB_RSA_ENCRYPT_SIGN:
411 res = pgp_mpi_read(pkt, &pk->sec.rsa.d);
412 if (res < 0)
413 break;
414 res = pgp_mpi_read(pkt, &pk->sec.rsa.p);
415 if (res < 0)
416 break;
417 res = pgp_mpi_read(pkt, &pk->sec.rsa.q);
418 if (res < 0)
419 break;
420 res = pgp_mpi_read(pkt, &pk->sec.rsa.u);
421 if (res < 0)
422 break;
423 break;
424 case PGP_PUB_ELG_ENCRYPT:
425 res = pgp_mpi_read(pf_key, &pk->sec.elg.x);
426 break;
427 case PGP_PUB_DSA_SIGN:
428 res = pgp_mpi_read(pf_key, &pk->sec.dsa.x);
429 break;
430 default:
431 px_debug("unknown public algo: %d", pk->algo);
432 res = PXE_PGP_KEYPKT_CORRUPT;
434 /* read checksum / sha1 */
435 if (res >= 0)
437 if (hide_type == HIDE_SHA1)
438 res = check_key_sha1(pf_key, pk);
439 else
440 res = check_key_cksum(pf_key, pk);
442 if (res >= 0)
443 res = pgp_expect_packet_end(pf_key);
445 if (pf_decrypt)
446 pullf_free(pf_decrypt);
447 if (cfb)
448 pgp_cfb_free(cfb);
450 if (res < 0)
451 pgp_key_free(pk);
452 else
453 *pk_p = pk;
455 return res;
458 static int
459 internal_read_key(PullFilter * src, PGP_PubKey ** pk_p,
460 const uint8 *psw, int psw_len, int pubtype)
462 PullFilter *pkt = NULL;
463 int res;
464 uint8 tag;
465 int len;
466 PGP_PubKey *enc_key = NULL;
467 PGP_PubKey *pk = NULL;
468 int got_main_key = 0;
471 * Search for encryption key.
473 * Error out on anything fancy.
475 while (1)
477 res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
478 if (res <= 0)
479 break;
480 res = pgp_create_pkt_reader(&pkt, src, len, res, NULL);
481 if (res < 0)
482 break;
484 switch (tag)
486 case PGP_PKT_PUBLIC_KEY:
487 case PGP_PKT_SECRET_KEY:
488 if (got_main_key)
490 res = PXE_PGP_MULTIPLE_KEYS;
491 break;
493 got_main_key = 1;
494 res = pgp_skip_packet(pkt);
495 break;
497 case PGP_PKT_PUBLIC_SUBKEY:
498 if (pubtype != 0)
499 res = PXE_PGP_EXPECT_SECRET_KEY;
500 else
501 res = _pgp_read_public_key(pkt, &pk);
502 break;
504 case PGP_PKT_SECRET_SUBKEY:
505 if (pubtype != 1)
506 res = PXE_PGP_EXPECT_PUBLIC_KEY;
507 else
508 res = process_secret_key(pkt, &pk, psw, psw_len);
509 break;
511 case PGP_PKT_SIGNATURE:
512 case PGP_PKT_MARKER:
513 case PGP_PKT_TRUST:
514 case PGP_PKT_USER_ID:
515 case PGP_PKT_USER_ATTR:
516 case PGP_PKT_PRIV_61:
517 res = pgp_skip_packet(pkt);
518 break;
519 default:
520 px_debug("unknown/unexpected packet: %d", tag);
521 res = PXE_PGP_UNEXPECTED_PKT;
523 pullf_free(pkt);
524 pkt = NULL;
526 if (pk != NULL)
528 if (res >= 0 && pk->can_encrypt)
530 if (enc_key == NULL)
532 enc_key = pk;
533 pk = NULL;
535 else
536 res = PXE_PGP_MULTIPLE_SUBKEYS;
539 if (pk)
540 pgp_key_free(pk);
541 pk = NULL;
544 if (res < 0)
545 break;
548 if (pkt)
549 pullf_free(pkt);
551 if (res < 0)
553 if (enc_key)
554 pgp_key_free(enc_key);
555 return res;
558 if (!enc_key)
559 res = PXE_PGP_NO_USABLE_KEY;
560 else
561 *pk_p = enc_key;
562 return res;
566 pgp_set_pubkey(PGP_Context * ctx, MBuf * keypkt,
567 const uint8 *key, int key_len, int pubtype)
569 int res;
570 PullFilter *src;
571 PGP_PubKey *pk = NULL;
573 res = pullf_create_mbuf_reader(&src, keypkt);
574 if (res < 0)
575 return res;
577 res = internal_read_key(src, &pk, key, key_len, pubtype);
578 pullf_free(src);
580 if (res >= 0)
581 ctx->pub_key = pk;
583 return res < 0 ? res : 0;