PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 "px.h"
34 #include "mbuf.h"
35 #include "pgp.h"
36 
37 int
39 {
40  PGP_PubKey *pk;
41 
42  pk = px_alloc(sizeof(*pk));
43  memset(pk, 0, sizeof(*pk));
44  *pk_p = pk;
45  return 0;
46 }
47 
48 void
50 {
51  if (pk == NULL)
52  return;
53 
54  switch (pk->algo)
55  {
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:
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;
79  }
80  px_memset(pk, 0, sizeof(*pk));
81  px_free(pk);
82 }
83 
84 static int
86 {
87  int res;
88  PX_MD *md;
89  int len;
90  uint8 hdr[3];
91  uint8 hash[20];
92 
93  res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
94  if (res < 0)
95  return res;
96 
97  len = 1 + 4 + 1;
98  switch (pk->algo)
99  {
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:
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;
117  }
118 
119  hdr[0] = 0x99;
120  hdr[1] = len >> 8;
121  hdr[2] = len & 0xFF;
122  px_md_update(md, hdr, 3);
123 
124  px_md_update(md, &pk->ver, 1);
125  px_md_update(md, pk->time, 4);
126  px_md_update(md, &pk->algo, 1);
127 
128  switch (pk->algo)
129  {
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:
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;
147  }
148 
149  px_md_finish(md, hash);
150  px_md_free(md);
151 
152  memcpy(pk->key_id, hash + 12, 8);
153  px_memset(hash, 0, 20);
154 
155  return 0;
156 }
157 
158 int
160 {
161  int res;
162  PGP_PubKey *pk;
163 
164  res = pgp_key_alloc(&pk);
165  if (res < 0)
166  return res;
167 
168  /* get version */
169  GETBYTE(pkt, pk->ver);
170  if (pk->ver != 4)
171  {
172  res = PXE_PGP_NOT_V4_KEYPKT;
173  goto out;
174  }
175 
176  /* read time */
177  res = pullf_read_fixed(pkt, 4, pk->time);
178  if (res < 0)
179  goto out;
180 
181  /* pubkey algorithm */
182  GETBYTE(pkt, pk->algo);
183 
184  switch (pk->algo)
185  {
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;
199 
200  res = calc_key_id(pk);
201  break;
202 
203  case PGP_PUB_RSA_SIGN:
204  case PGP_PUB_RSA_ENCRYPT:
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;
212 
213  res = calc_key_id(pk);
214 
215  if (pk->algo != PGP_PUB_RSA_SIGN)
216  pk->can_encrypt = 1;
217  break;
218 
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;
229 
230  res = calc_key_id(pk);
231 
232  pk->can_encrypt = 1;
233  break;
234 
235  default:
236  px_debug("unknown public algo: %d", pk->algo);
238  }
239 
240 out:
241  if (res < 0)
242  pgp_key_free(pk);
243  else
244  *pk_p = pk;
245 
246  return res;
247 }
248 
249 #define HIDE_CLEAR 0
250 #define HIDE_CKSUM 255
251 #define HIDE_SHA1 254
252 
253 static int
255 {
256  int res;
257  uint8 got_sha1[20];
258  uint8 my_sha1[20];
259  PX_MD *md;
260 
261  res = pullf_read_fixed(src, 20, got_sha1);
262  if (res < 0)
263  return res;
264 
265  res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
266  if (res < 0)
267  goto err;
268  switch (pk->algo)
269  {
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:
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;
284  }
285  px_md_finish(md, my_sha1);
286  px_md_free(md);
287 
288  if (memcmp(my_sha1, got_sha1, 20) != 0)
289  {
290  px_debug("key sha1 check failed");
292  }
293 err:
294  px_memset(got_sha1, 0, 20);
295  px_memset(my_sha1, 0, 20);
296  return res;
297 }
298 
299 static int
301 {
302  int res;
303  unsigned got_cksum,
304  my_cksum = 0;
305  uint8 buf[2];
306 
307  res = pullf_read_fixed(src, 2, buf);
308  if (res < 0)
309  return res;
310 
311  got_cksum = ((unsigned) buf[0] << 8) + buf[1];
312  switch (pk->algo)
313  {
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:
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;
328  }
329  if (my_cksum != got_cksum)
330  {
331  px_debug("key cksum check failed");
332  return PXE_PGP_KEYPKT_CORRUPT;
333  }
334  return 0;
335 }
336 
337 static int
339  const uint8 *key, int key_len)
340 {
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;
351 
352  /* first read public key part */
353  res = _pgp_read_public_key(pkt, &pk);
354  if (res < 0)
355  return res;
356 
357  /*
358  * is secret key encrypted?
359  */
360  GETBYTE(pkt, hide_type);
361  if (hide_type == HIDE_SHA1 || hide_type == HIDE_CKSUM)
362  {
363  if (key == NULL)
365  GETBYTE(pkt, cipher_algo);
366  res = pgp_s2k_read(pkt, &s2k);
367  if (res < 0)
368  return res;
369 
370  res = pgp_s2k_process(&s2k, cipher_algo, key, key_len);
371  if (res < 0)
372  return res;
373 
374  bs = pgp_get_cipher_block_size(cipher_algo);
375  if (bs == 0)
376  {
377  px_debug("unknown cipher algo=%d", cipher_algo);
379  }
380  res = pullf_read_fixed(pkt, bs, iv);
381  if (res < 0)
382  return res;
383 
384  /*
385  * create decrypt filter
386  */
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;
394  }
395  else if (hide_type == HIDE_CLEAR)
396  {
397  pf_key = pkt;
398  }
399  else
400  {
401  px_debug("unknown hide type");
402  return PXE_PGP_KEYPKT_CORRUPT;
403  }
404 
405  /* read secret key */
406  switch (pk->algo)
407  {
408  case PGP_PUB_RSA_SIGN:
409  case PGP_PUB_RSA_ENCRYPT:
411  res = pgp_mpi_read(pf_key, &pk->sec.rsa.d);
412  if (res < 0)
413  break;
414  res = pgp_mpi_read(pf_key, &pk->sec.rsa.p);
415  if (res < 0)
416  break;
417  res = pgp_mpi_read(pf_key, &pk->sec.rsa.q);
418  if (res < 0)
419  break;
420  res = pgp_mpi_read(pf_key, &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);
433  }
434  /* read checksum / sha1 */
435  if (res >= 0)
436  {
437  if (hide_type == HIDE_SHA1)
438  res = check_key_sha1(pf_key, pk);
439  else
440  res = check_key_cksum(pf_key, pk);
441  }
442  if (res >= 0)
443  res = pgp_expect_packet_end(pf_key);
444 
445  if (pf_decrypt)
446  pullf_free(pf_decrypt);
447  if (cfb)
448  pgp_cfb_free(cfb);
449 
450  if (res < 0)
451  pgp_key_free(pk);
452  else
453  *pk_p = pk;
454 
455  return res;
456 }
457 
458 static int
460  const uint8 *psw, int psw_len, int pubtype)
461 {
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;
469 
470  /*
471  * Search for encryption key.
472  *
473  * Error out on anything fancy.
474  */
475  while (1)
476  {
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;
483 
484  switch (tag)
485  {
486  case PGP_PKT_PUBLIC_KEY:
487  case PGP_PKT_SECRET_KEY:
488  if (got_main_key)
489  {
490  res = PXE_PGP_MULTIPLE_KEYS;
491  break;
492  }
493  got_main_key = 1;
494  res = pgp_skip_packet(pkt);
495  break;
496 
498  if (pubtype != 0)
500  else
501  res = _pgp_read_public_key(pkt, &pk);
502  break;
503 
505  if (pubtype != 1)
507  else
508  res = process_secret_key(pkt, &pk, psw, psw_len);
509  break;
510 
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);
522  }
523  pullf_free(pkt);
524  pkt = NULL;
525 
526  if (pk != NULL)
527  {
528  if (res >= 0 && pk->can_encrypt)
529  {
530  if (enc_key == NULL)
531  {
532  enc_key = pk;
533  pk = NULL;
534  }
535  else
537  }
538 
539  if (pk)
540  pgp_key_free(pk);
541  pk = NULL;
542  }
543 
544  if (res < 0)
545  break;
546  }
547 
548  if (pkt)
549  pullf_free(pkt);
550 
551  if (res < 0)
552  {
553  if (enc_key)
554  pgp_key_free(enc_key);
555  return res;
556  }
557 
558  if (!enc_key)
559  res = PXE_PGP_NO_USABLE_KEY;
560  else
561  *pk_p = enc_key;
562  return res;
563 }
564 
565 int
567  const uint8 *key, int key_len, int pubtype)
568 {
569  int res;
570  PullFilter *src;
571  PGP_PubKey *pk = NULL;
572 
573  res = pullf_create_mbuf_reader(&src, keypkt);
574  if (res < 0)
575  return res;
576 
577  res = internal_read_key(src, &pk, key, key_len, pubtype);
578  pullf_free(src);
579 
580  if (res >= 0)
581  ctx->pub_key = pk;
582 
583  return res < 0 ? res : 0;
584 }
#define PXE_PGP_KEYPKT_CORRUPT
Definition: px.h:99
unsigned pgp_mpi_cksum(unsigned cksum, PGP_MPI *n)
Definition: pgp-mpi.c:132
int pgp_mpi_hash(PX_MD *md, PGP_MPI *n)
Definition: pgp-mpi.c:119
struct PGP_PubKey::@5::@7 elg
int pgp_set_pubkey(PGP_Context *ctx, MBuf *keypkt, const uint8 *key, int key_len, int pubtype)
Definition: pgp-pubkey.c:566
uint8 ver
Definition: pgp.h:188
void pullf_free(PullFilter *pf)
Definition: mbuf.c:245
int pullf_create(PullFilter **pf_p, const PullFilterOps *op, void *init_arg, PullFilter *src)
Definition: mbuf.c:206
int pullf_read_fixed(PullFilter *src, int len, uint8 *dst)
Definition: mbuf.c:317
struct PGP_PubKey::@5::@9 dsa
uint8 time[4]
Definition: pgp.h:189
#define PXE_PGP_UNSUPPORTED_CIPHER
Definition: px.h:84
int pgp_parse_pkt_hdr(PullFilter *src, uint8 *tag, int *len_p, int allow_ctx)
Definition: pgp-decrypt.c:129
#define px_free(p)
Definition: px.h:46
#define px_md_update(md, data, dlen)
Definition: px.h:208
#define PXE_PGP_EXPECT_SECRET_KEY
Definition: px.h:97
unsigned char uint8
Definition: c.h:266
static int calc_key_id(PGP_PubKey *pk)
Definition: pgp-pubkey.c:85
#define PXE_PGP_MULTIPLE_SUBKEYS
Definition: px.h:104
int pullf_create_mbuf_reader(PullFilter **mp_p, MBuf *src)
Definition: mbuf.c:352
int pgp_key_alloc(PGP_PubKey **pk_p)
Definition: pgp-pubkey.c:38
int pgp_skip_packet(PullFilter *pkt)
Definition: pgp-decrypt.c:1061
#define px_md_finish(md, buf)
Definition: px.h:209
#define HIDE_CKSUM
Definition: pgp-pubkey.c:250
#define PXE_PGP_NO_USABLE_KEY
Definition: px.h:100
Definition: px.h:113
int cipher_algo
Definition: pgp-pgsql.c:123
struct PGP_PubKey::@5::@8 rsa
static int check_key_cksum(PullFilter *src, PGP_PubKey *pk)
Definition: pgp-pubkey.c:300
#define GETBYTE(x, i)
Definition: hstore_gist.c:32
void pgp_key_free(PGP_PubKey *pk)
Definition: pgp-pubkey.c:49
int pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len, int pkttype, PGP_Context *ctx)
Definition: pgp-decrypt.c:223
static char * buf
Definition: pg_test_fsync.c:66
#define HIDE_SHA1
Definition: pgp-pubkey.c:251
static int internal_read_key(PullFilter *src, PGP_PubKey **pk_p, const uint8 *psw, int psw_len, int pubtype)
Definition: pgp-pubkey.c:459
uint8 key[PGP_MAX_KEY]
Definition: pgp.h:129
#define PXE_PGP_UNEXPECTED_PKT
Definition: px.h:88
Definition: pgp.h:122
int pgp_mpi_read(PullFilter *src, PGP_MPI **mpi)
Definition: pgp-mpi.c:80
int pgp_mpi_free(PGP_MPI *mpi)
Definition: pgp-mpi.c:70
#define PXE_PGP_MULTIPLE_KEYS
Definition: px.h:95
int pgp_expect_packet_end(PullFilter *pkt)
Definition: pgp-decrypt.c:1075
int pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
Definition: pgp-s2k.c:281
static int process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p, const uint8 *key, int key_len)
Definition: pgp-pubkey.c:338
struct PullFilterOps pgp_decrypt_filter
Definition: pgp-decrypt.c:313
#define px_md_free(md)
Definition: px.h:210
void pgp_cfb_free(PGP_CFB *ctx)
Definition: pgp-cfb.c:84
int pgp_load_digest(int code, PX_MD **res)
Definition: pgp.c:184
#define PXE_PGP_EXPECT_PUBLIC_KEY
Definition: px.h:96
#define PXE_PGP_NEED_SECRET_PSW
Definition: px.h:101
union PGP_PubKey::@6 sec
#define NULL
Definition: c.h:229
int pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
Definition: pgp-s2k.c:255
static int check_key_sha1(PullFilter *src, PGP_PubKey *pk)
Definition: pgp-pubkey.c:254
void px_debug(const char *fmt,...)
Definition: px.c:160
int pgp_get_cipher_block_size(int code)
Definition: pgp.c:158
Definition: mbuf.c:39
uint8 key_id[8]
Definition: pgp.h:235
#define PXE_PGP_UNKNOWN_PUBALGO
Definition: px.h:93
union PGP_PubKey::@5 pub
uint8 key_len
Definition: pgp.h:130
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
uint8 algo
Definition: pgp.h:190
#define HIDE_CLEAR
Definition: pgp-pubkey.c:249
#define px_alloc(s)
Definition: px.h:44
PGP_PubKey * pub_key
Definition: pgp.h:164
#define PXE_PGP_NOT_V4_KEYPKT
Definition: px.h:98
int can_encrypt
Definition: pgp.h:236
int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p)
Definition: pgp-pubkey.c:159
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:541
void px_memset(void *ptr, int c, size_t len)
Definition: px.c:134