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 
37 int
39 {
40  PGP_PubKey *pk;
41 
42  pk = palloc0(sizeof(*pk));
43  *pk_p = pk;
44  return 0;
45 }
46 
47 void
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;
61  case PGP_PUB_RSA_SIGN:
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;
71  case PGP_PUB_DSA_SIGN:
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 
83 static 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:
105  case PGP_PUB_RSA_ENCRYPT:
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  {
129  case PGP_PUB_ELG_ENCRYPT:
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:
135  case PGP_PUB_RSA_ENCRYPT:
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 
157 int
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:
203  case PGP_PUB_RSA_ENCRYPT:
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 
218  case PGP_PUB_ELG_ENCRYPT:
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 
239 out:
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 
252 static 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  {
269  case PGP_PUB_ELG_ENCRYPT:
270  pgp_mpi_hash(md, pk->sec.elg.x);
271  break;
272  case PGP_PUB_RSA_SIGN:
273  case PGP_PUB_RSA_ENCRYPT:
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  }
292 err:
293  px_memset(got_sha1, 0, 20);
294  px_memset(my_sha1, 0, 20);
295  return res;
296 }
297 
298 static 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  {
313  case PGP_PUB_ELG_ENCRYPT:
314  my_cksum = pgp_mpi_cksum(0, pk->sec.elg.x);
315  break;
316  case PGP_PUB_RSA_SIGN:
317  case PGP_PUB_RSA_ENCRYPT:
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");
331  return PXE_PGP_KEYPKT_CORRUPT;
332  }
333  return 0;
334 }
335 
336 static 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");
401  return PXE_PGP_KEYPKT_CORRUPT;
402  }
403 
404  /* read secret key */
405  switch (pk->algo)
406  {
407  case PGP_PUB_RSA_SIGN:
408  case PGP_PUB_RSA_ENCRYPT:
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;
423  case PGP_PUB_ELG_ENCRYPT:
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 
457 static 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  {
485  case PGP_PKT_PUBLIC_KEY:
486  case PGP_PKT_SECRET_KEY:
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 
510  case PGP_PKT_SIGNATURE:
511  case PGP_PKT_MARKER:
512  case PGP_PKT_TRUST:
513  case PGP_PKT_USER_ID:
514  case PGP_PKT_USER_ATTR:
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 
564 int
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 }
unsigned char uint8
Definition: c.h:491
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:1508
void * palloc0(Size size)
Definition: mcxt.c:1334
const void size_t len
static char * buf
Definition: pg_test_fsync.c:73
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:195
#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:196
#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:194
#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
uint8 time[4]
Definition: pgp.h:189
int can_encrypt
Definition: pgp.h:236
uint8 key_id[8]
Definition: pgp.h:235
struct PGP_PubKey::@0::@3 rsa
uint8 algo
Definition: pgp.h:190
struct PGP_PubKey::@0::@2 elg
uint8 ver
Definition: pgp.h:188
union PGP_PubKey::@1 sec
struct PGP_PubKey::@0::@4 dsa
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:100