PostgreSQL Source Code git master
pgp-pubkey.c
Go to the documentation of this file.
1/*
2 * pgp-pubkey.c
3 * Read public or secret key.
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-pubkey.c
30 */
31#include "postgres.h"
32
33#include "mbuf.h"
34#include "pgp.h"
35#include "px.h"
36
37int
39{
40 PGP_PubKey *pk;
41
42 pk = palloc0(sizeof(*pk));
43 *pk_p = pk;
44 return 0;
45}
46
47void
49{
50 if (pk == NULL)
51 return;
52
53 switch (pk->algo)
54 {
56 pgp_mpi_free(pk->pub.elg.p);
57 pgp_mpi_free(pk->pub.elg.g);
58 pgp_mpi_free(pk->pub.elg.y);
59 pgp_mpi_free(pk->sec.elg.x);
60 break;
64 pgp_mpi_free(pk->pub.rsa.n);
65 pgp_mpi_free(pk->pub.rsa.e);
66 pgp_mpi_free(pk->sec.rsa.d);
67 pgp_mpi_free(pk->sec.rsa.p);
68 pgp_mpi_free(pk->sec.rsa.q);
69 pgp_mpi_free(pk->sec.rsa.u);
70 break;
72 pgp_mpi_free(pk->pub.dsa.p);
73 pgp_mpi_free(pk->pub.dsa.q);
74 pgp_mpi_free(pk->pub.dsa.g);
75 pgp_mpi_free(pk->pub.dsa.y);
76 pgp_mpi_free(pk->sec.dsa.x);
77 break;
78 }
79 px_memset(pk, 0, sizeof(*pk));
80 pfree(pk);
81}
82
83static int
85{
86 int res;
87 PX_MD *md;
88 int len;
89 uint8 hdr[3];
90 uint8 hash[20];
91
93 if (res < 0)
94 return res;
95
96 len = 1 + 4 + 1;
97 switch (pk->algo)
98 {
100 len += 2 + pk->pub.elg.p->bytes;
101 len += 2 + pk->pub.elg.g->bytes;
102 len += 2 + pk->pub.elg.y->bytes;
103 break;
104 case PGP_PUB_RSA_SIGN:
107 len += 2 + pk->pub.rsa.n->bytes;
108 len += 2 + pk->pub.rsa.e->bytes;
109 break;
110 case PGP_PUB_DSA_SIGN:
111 len += 2 + pk->pub.dsa.p->bytes;
112 len += 2 + pk->pub.dsa.q->bytes;
113 len += 2 + pk->pub.dsa.g->bytes;
114 len += 2 + pk->pub.dsa.y->bytes;
115 break;
116 }
117
118 hdr[0] = 0x99;
119 hdr[1] = len >> 8;
120 hdr[2] = len & 0xFF;
121 px_md_update(md, hdr, 3);
122
123 px_md_update(md, &pk->ver, 1);
124 px_md_update(md, pk->time, 4);
125 px_md_update(md, &pk->algo, 1);
126
127 switch (pk->algo)
128 {
130 pgp_mpi_hash(md, pk->pub.elg.p);
131 pgp_mpi_hash(md, pk->pub.elg.g);
132 pgp_mpi_hash(md, pk->pub.elg.y);
133 break;
134 case PGP_PUB_RSA_SIGN:
137 pgp_mpi_hash(md, pk->pub.rsa.n);
138 pgp_mpi_hash(md, pk->pub.rsa.e);
139 break;
140 case PGP_PUB_DSA_SIGN:
141 pgp_mpi_hash(md, pk->pub.dsa.p);
142 pgp_mpi_hash(md, pk->pub.dsa.q);
143 pgp_mpi_hash(md, pk->pub.dsa.g);
144 pgp_mpi_hash(md, pk->pub.dsa.y);
145 break;
146 }
147
148 px_md_finish(md, hash);
149 px_md_free(md);
150
151 memcpy(pk->key_id, hash + 12, 8);
152 px_memset(hash, 0, 20);
153
154 return 0;
155}
156
157int
159{
160 int res;
161 PGP_PubKey *pk;
162
163 res = pgp_key_alloc(&pk);
164 if (res < 0)
165 return res;
166
167 /* get version */
168 GETBYTE(pkt, pk->ver);
169 if (pk->ver != 4)
170 {
172 goto out;
173 }
174
175 /* read time */
176 res = pullf_read_fixed(pkt, 4, pk->time);
177 if (res < 0)
178 goto out;
179
180 /* pubkey algorithm */
181 GETBYTE(pkt, pk->algo);
182
183 switch (pk->algo)
184 {
185 case PGP_PUB_DSA_SIGN:
186 res = pgp_mpi_read(pkt, &pk->pub.dsa.p);
187 if (res < 0)
188 break;
189 res = pgp_mpi_read(pkt, &pk->pub.dsa.q);
190 if (res < 0)
191 break;
192 res = pgp_mpi_read(pkt, &pk->pub.dsa.g);
193 if (res < 0)
194 break;
195 res = pgp_mpi_read(pkt, &pk->pub.dsa.y);
196 if (res < 0)
197 break;
198
199 res = calc_key_id(pk);
200 break;
201
202 case PGP_PUB_RSA_SIGN:
205 res = pgp_mpi_read(pkt, &pk->pub.rsa.n);
206 if (res < 0)
207 break;
208 res = pgp_mpi_read(pkt, &pk->pub.rsa.e);
209 if (res < 0)
210 break;
211
212 res = calc_key_id(pk);
213
214 if (pk->algo != PGP_PUB_RSA_SIGN)
215 pk->can_encrypt = 1;
216 break;
217
219 res = pgp_mpi_read(pkt, &pk->pub.elg.p);
220 if (res < 0)
221 break;
222 res = pgp_mpi_read(pkt, &pk->pub.elg.g);
223 if (res < 0)
224 break;
225 res = pgp_mpi_read(pkt, &pk->pub.elg.y);
226 if (res < 0)
227 break;
228
229 res = calc_key_id(pk);
230
231 pk->can_encrypt = 1;
232 break;
233
234 default:
235 px_debug("unknown public algo: %d", pk->algo);
237 }
238
239out:
240 if (res < 0)
241 pgp_key_free(pk);
242 else
243 *pk_p = pk;
244
245 return res;
246}
247
248#define HIDE_CLEAR 0
249#define HIDE_CKSUM 255
250#define HIDE_SHA1 254
251
252static int
254{
255 int res;
256 uint8 got_sha1[20];
257 uint8 my_sha1[20];
258 PX_MD *md;
259
260 res = pullf_read_fixed(src, 20, got_sha1);
261 if (res < 0)
262 return res;
263
265 if (res < 0)
266 goto err;
267 switch (pk->algo)
268 {
270 pgp_mpi_hash(md, pk->sec.elg.x);
271 break;
272 case PGP_PUB_RSA_SIGN:
275 pgp_mpi_hash(md, pk->sec.rsa.d);
276 pgp_mpi_hash(md, pk->sec.rsa.p);
277 pgp_mpi_hash(md, pk->sec.rsa.q);
278 pgp_mpi_hash(md, pk->sec.rsa.u);
279 break;
280 case PGP_PUB_DSA_SIGN:
281 pgp_mpi_hash(md, pk->sec.dsa.x);
282 break;
283 }
284 px_md_finish(md, my_sha1);
285 px_md_free(md);
286
287 if (memcmp(my_sha1, got_sha1, 20) != 0)
288 {
289 px_debug("key sha1 check failed");
291 }
292err:
293 px_memset(got_sha1, 0, 20);
294 px_memset(my_sha1, 0, 20);
295 return res;
296}
297
298static int
300{
301 int res;
302 unsigned got_cksum,
303 my_cksum = 0;
304 uint8 buf[2];
305
306 res = pullf_read_fixed(src, 2, buf);
307 if (res < 0)
308 return res;
309
310 got_cksum = ((unsigned) buf[0] << 8) + buf[1];
311 switch (pk->algo)
312 {
314 my_cksum = pgp_mpi_cksum(0, pk->sec.elg.x);
315 break;
316 case PGP_PUB_RSA_SIGN:
319 my_cksum = pgp_mpi_cksum(0, pk->sec.rsa.d);
320 my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.p);
321 my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.q);
322 my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.u);
323 break;
324 case PGP_PUB_DSA_SIGN:
325 my_cksum = pgp_mpi_cksum(0, pk->sec.dsa.x);
326 break;
327 }
328 if (my_cksum != got_cksum)
329 {
330 px_debug("key cksum check failed");
332 }
333 return 0;
334}
335
336static int
338 const uint8 *key, int key_len)
339{
340 int res;
341 int hide_type;
342 int cipher_algo;
343 int bs;
344 uint8 iv[512];
345 PullFilter *pf_decrypt = NULL,
346 *pf_key;
347 PGP_CFB *cfb = NULL;
348 PGP_S2K s2k;
349 PGP_PubKey *pk;
350
351 /* first read public key part */
352 res = _pgp_read_public_key(pkt, &pk);
353 if (res < 0)
354 return res;
355
356 /*
357 * is secret key encrypted?
358 */
359 GETBYTE(pkt, hide_type);
360 if (hide_type == HIDE_SHA1 || hide_type == HIDE_CKSUM)
361 {
362 if (key == NULL)
364 GETBYTE(pkt, cipher_algo);
365 res = pgp_s2k_read(pkt, &s2k);
366 if (res < 0)
367 return res;
368
369 res = pgp_s2k_process(&s2k, cipher_algo, key, key_len);
370 if (res < 0)
371 return res;
372
373 bs = pgp_get_cipher_block_size(cipher_algo);
374 if (bs == 0)
375 {
376 px_debug("unknown cipher algo=%d", cipher_algo);
378 }
379 res = pullf_read_fixed(pkt, bs, iv);
380 if (res < 0)
381 return res;
382
383 /*
384 * create decrypt filter
385 */
386 res = pgp_cfb_create(&cfb, cipher_algo, s2k.key, s2k.key_len, 0, iv);
387 if (res < 0)
388 return res;
389 res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
390 if (res < 0)
391 return res;
392 pf_key = pf_decrypt;
393 }
394 else if (hide_type == HIDE_CLEAR)
395 {
396 pf_key = pkt;
397 }
398 else
399 {
400 px_debug("unknown hide type");
402 }
403
404 /* read secret key */
405 switch (pk->algo)
406 {
407 case PGP_PUB_RSA_SIGN:
410 res = pgp_mpi_read(pf_key, &pk->sec.rsa.d);
411 if (res < 0)
412 break;
413 res = pgp_mpi_read(pf_key, &pk->sec.rsa.p);
414 if (res < 0)
415 break;
416 res = pgp_mpi_read(pf_key, &pk->sec.rsa.q);
417 if (res < 0)
418 break;
419 res = pgp_mpi_read(pf_key, &pk->sec.rsa.u);
420 if (res < 0)
421 break;
422 break;
424 res = pgp_mpi_read(pf_key, &pk->sec.elg.x);
425 break;
426 case PGP_PUB_DSA_SIGN:
427 res = pgp_mpi_read(pf_key, &pk->sec.dsa.x);
428 break;
429 default:
430 px_debug("unknown public algo: %d", pk->algo);
432 }
433 /* read checksum / sha1 */
434 if (res >= 0)
435 {
436 if (hide_type == HIDE_SHA1)
437 res = check_key_sha1(pf_key, pk);
438 else
439 res = check_key_cksum(pf_key, pk);
440 }
441 if (res >= 0)
442 res = pgp_expect_packet_end(pf_key);
443
444 if (pf_decrypt)
445 pullf_free(pf_decrypt);
446 if (cfb)
447 pgp_cfb_free(cfb);
448
449 if (res < 0)
450 pgp_key_free(pk);
451 else
452 *pk_p = pk;
453
454 return res;
455}
456
457static int
459 const uint8 *psw, int psw_len, int pubtype)
460{
461 PullFilter *pkt = NULL;
462 int res;
463 uint8 tag;
464 int len;
465 PGP_PubKey *enc_key = NULL;
466 PGP_PubKey *pk = NULL;
467 int got_main_key = 0;
468
469 /*
470 * Search for encryption key.
471 *
472 * Error out on anything fancy.
473 */
474 while (1)
475 {
476 res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
477 if (res <= 0)
478 break;
479 res = pgp_create_pkt_reader(&pkt, src, len, res, NULL);
480 if (res < 0)
481 break;
482
483 switch (tag)
484 {
487 if (got_main_key)
488 {
490 break;
491 }
492 got_main_key = 1;
493 res = pgp_skip_packet(pkt);
494 break;
495
497 if (pubtype != 0)
499 else
500 res = _pgp_read_public_key(pkt, &pk);
501 break;
502
504 if (pubtype != 1)
506 else
507 res = process_secret_key(pkt, &pk, psw, psw_len);
508 break;
509
511 case PGP_PKT_MARKER:
512 case PGP_PKT_TRUST:
513 case PGP_PKT_USER_ID:
515 case PGP_PKT_PRIV_61:
516 res = pgp_skip_packet(pkt);
517 break;
518 default:
519 px_debug("unknown/unexpected packet: %d", tag);
521 }
522 pullf_free(pkt);
523 pkt = NULL;
524
525 if (pk != NULL)
526 {
527 if (res >= 0 && pk->can_encrypt)
528 {
529 if (enc_key == NULL)
530 {
531 enc_key = pk;
532 pk = NULL;
533 }
534 else
536 }
537
538 if (pk)
539 pgp_key_free(pk);
540 pk = NULL;
541 }
542
543 if (res < 0)
544 break;
545 }
546
547 if (pkt)
548 pullf_free(pkt);
549
550 if (res < 0)
551 {
552 if (enc_key)
553 pgp_key_free(enc_key);
554 return res;
555 }
556
557 if (!enc_key)
559 else
560 *pk_p = enc_key;
561 return res;
562}
563
564int
566 const uint8 *key, int key_len, int pubtype)
567{
568 int res;
569 PullFilter *src;
570 PGP_PubKey *pk = NULL;
571
572 res = pullf_create_mbuf_reader(&src, keypkt);
573 if (res < 0)
574 return res;
575
576 res = internal_read_key(src, &pk, key, key_len, pubtype);
577 pullf_free(src);
578
579 if (res >= 0)
580 ctx->pub_key = pk;
581
582 return res < 0 ? res : 0;
583}
uint8_t uint8
Definition: c.h:500
void err(int eval, const char *fmt,...)
Definition: err.c:43
#define GETBYTE(x, i)
Definition: hstore_gist.c:40
int pullf_read_fixed(PullFilter *src, int len, uint8 *dst)
Definition: mbuf.c:301
int pullf_create(PullFilter **pf_p, const PullFilterOps *op, void *init_arg, PullFilter *src)
Definition: mbuf.c:191
int pullf_create_mbuf_reader(PullFilter **mp_p, MBuf *src)
Definition: mbuf.c:336
void pullf_free(PullFilter *pf)
Definition: mbuf.c:229
void pfree(void *pointer)
Definition: mcxt.c:1524
void * palloc0(Size size)
Definition: mcxt.c:1347
const void size_t len
static char * buf
Definition: pg_test_fsync.c:72
void pgp_cfb_free(PGP_CFB *ctx)
Definition: pgp-cfb.c:83
int pgp_cfb_create(PGP_CFB **ctx_p, int algo, const uint8 *key, int key_len, int resync, uint8 *iv)
Definition: pgp-cfb.c:52
int pgp_parse_pkt_hdr(PullFilter *src, uint8 *tag, int *len_p, int allow_ctx)
Definition: pgp-decrypt.c:129
int pgp_expect_packet_end(PullFilter *pkt)
Definition: pgp-decrypt.c:1078
struct PullFilterOps pgp_decrypt_filter
Definition: pgp-decrypt.c:314
int pgp_skip_packet(PullFilter *pkt)
Definition: pgp-decrypt.c:1064
int pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len, int pkttype, PGP_Context *ctx)
Definition: pgp-decrypt.c:223
int pgp_mpi_free(PGP_MPI *mpi)
Definition: pgp-mpi.c:70
int pgp_mpi_hash(PX_MD *md, PGP_MPI *n)
Definition: pgp-mpi.c:119
int pgp_mpi_read(PullFilter *src, PGP_MPI **mpi)
Definition: pgp-mpi.c:80
unsigned pgp_mpi_cksum(unsigned cksum, PGP_MPI *n)
Definition: pgp-mpi.c:132
static int calc_key_id(PGP_PubKey *pk)
Definition: pgp-pubkey.c:84
static int process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p, const uint8 *key, int key_len)
Definition: pgp-pubkey.c:337
int pgp_key_alloc(PGP_PubKey **pk_p)
Definition: pgp-pubkey.c:38
static int internal_read_key(PullFilter *src, PGP_PubKey **pk_p, const uint8 *psw, int psw_len, int pubtype)
Definition: pgp-pubkey.c:458
#define HIDE_CLEAR
Definition: pgp-pubkey.c:248
static int check_key_cksum(PullFilter *src, PGP_PubKey *pk)
Definition: pgp-pubkey.c:299
void pgp_key_free(PGP_PubKey *pk)
Definition: pgp-pubkey.c:48
#define HIDE_CKSUM
Definition: pgp-pubkey.c:249
#define HIDE_SHA1
Definition: pgp-pubkey.c:250
int pgp_set_pubkey(PGP_Context *ctx, MBuf *keypkt, const uint8 *key, int key_len, int pubtype)
Definition: pgp-pubkey.c:565
static int check_key_sha1(PullFilter *src, PGP_PubKey *pk)
Definition: pgp-pubkey.c:253
int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p)
Definition: pgp-pubkey.c:158
int pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
Definition: pgp-s2k.c:279
int pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
Definition: pgp-s2k.c:253
int pgp_get_cipher_block_size(int code)
Definition: pgp.c:147
int pgp_load_digest(int code, PX_MD **res)
Definition: pgp.c:173
@ PGP_PKT_TRUST
Definition: pgp.h:57
@ PGP_PKT_USER_ATTR
Definition: pgp.h:60
@ PGP_PKT_PUBLIC_SUBKEY
Definition: pgp.h:59
@ PGP_PKT_SIGNATURE
Definition: pgp.h:48
@ PGP_PKT_SECRET_SUBKEY
Definition: pgp.h:52
@ PGP_PKT_MARKER
Definition: pgp.h:55
@ PGP_PKT_SECRET_KEY
Definition: pgp.h:50
@ PGP_PKT_PUBLIC_KEY
Definition: pgp.h:51
@ PGP_PKT_USER_ID
Definition: pgp.h:58
@ PGP_PKT_PRIV_61
Definition: pgp.h:63
@ PGP_DIGEST_SHA1
Definition: pgp.h:101
@ PGP_PUB_RSA_ENCRYPT_SIGN
Definition: pgp.h:68
@ PGP_PUB_RSA_ENCRYPT
Definition: pgp.h:69
@ PGP_PUB_DSA_SIGN
Definition: pgp.h:72
@ PGP_PUB_RSA_SIGN
Definition: pgp.h:70
@ PGP_PUB_ELG_ENCRYPT
Definition: pgp.h:71
void px_debug(const char *fmt,...)
Definition: px.c:149
void px_memset(void *ptr, int c, size_t len)
Definition: px.c:123
#define PXE_PGP_EXPECT_PUBLIC_KEY
Definition: px.h:82
#define px_md_finish(md, buf)
Definition: px.h:206
#define PXE_PGP_UNEXPECTED_PKT
Definition: px.h:74
#define PXE_PGP_MULTIPLE_KEYS
Definition: px.h:81
#define PXE_PGP_NO_USABLE_KEY
Definition: px.h:86
#define px_md_free(md)
Definition: px.h:207
#define PXE_PGP_EXPECT_SECRET_KEY
Definition: px.h:83
#define PXE_PGP_NEED_SECRET_PSW
Definition: px.h:87
#define PXE_PGP_MULTIPLE_SUBKEYS
Definition: px.h:90
#define px_md_update(md, data, dlen)
Definition: px.h:205
#define PXE_PGP_UNSUPPORTED_CIPHER
Definition: px.h:70
#define PXE_PGP_UNKNOWN_PUBALGO
Definition: px.h:79
#define PXE_PGP_KEYPKT_CORRUPT
Definition: px.h:85
#define PXE_PGP_NOT_V4_KEYPKT
Definition: px.h:84
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715
Definition: mbuf.c:40
PGP_PubKey * pub_key
Definition: pgp.h:164
int bytes
Definition: pgp.h:183
uint8 time[4]
Definition: pgp.h:189
int can_encrypt
Definition: pgp.h:236
uint8 key_id[8]
Definition: pgp.h:235
PGP_MPI * y
Definition: pgp.h:199
PGP_MPI * q
Definition: pgp.h:209
struct PGP_PubKey::@0::@3 rsa
uint8 algo
Definition: pgp.h:190
struct PGP_PubKey::@0::@2 elg
PGP_MPI * d
Definition: pgp.h:224
PGP_MPI * p
Definition: pgp.h:197
uint8 ver
Definition: pgp.h:188
union PGP_PubKey::@1 sec
struct PGP_PubKey::@0::@4 dsa
PGP_MPI * g
Definition: pgp.h:198
PGP_MPI * e
Definition: pgp.h:204
PGP_MPI * u
Definition: pgp.h:227
PGP_MPI * n
Definition: pgp.h:203
PGP_MPI * x
Definition: pgp.h:220
union PGP_PubKey::@0 pub
Definition: pgp.h:123
uint8 key_len
Definition: pgp.h:130
uint8 key[PGP_MAX_KEY]
Definition: pgp.h:129
Definition: px.h:108