Axe the rpmsq debug code which was never getting built anyway
[platform/upstream/rpm.git] / rpmio / rpmpgp.c
1 /** \ingroup rpmio signature
2  * \file rpmio/rpmpgp.c
3  * Routines to handle RFC-2440 detached signatures.
4  */
5
6 #include "system.h"
7
8 #include <pthread.h>
9
10 #include <rpm/rpmstring.h>
11 #include <rpm/rpmlog.h>
12
13 #include "rpmio/digest.h"
14 #include "rpmio/rpmio_internal.h"       /* XXX rpmioSlurp */
15
16 #include "debug.h"
17
18
19 static int _debug = 0;
20
21 static int _print = 0;
22
23 static int _crypto_initialized = 0;
24 static int _new_process = 1;
25
26 typedef const struct pgpValTbl_s {
27     int val;
28     char const * const str;
29 } * pgpValTbl;
30  
31 static struct pgpValTbl_s const pgpSigTypeTbl[] = {
32     { PGPSIGTYPE_BINARY,        "Binary document signature" },
33     { PGPSIGTYPE_TEXT,          "Text document signature" },
34     { PGPSIGTYPE_STANDALONE,    "Standalone signature" },
35     { PGPSIGTYPE_GENERIC_CERT,  "Generic certification of a User ID and Public Key" },
36     { PGPSIGTYPE_PERSONA_CERT,  "Persona certification of a User ID and Public Key" },
37     { PGPSIGTYPE_CASUAL_CERT,   "Casual certification of a User ID and Public Key" },
38     { PGPSIGTYPE_POSITIVE_CERT, "Positive certification of a User ID and Public Key" },
39     { PGPSIGTYPE_SUBKEY_BINDING,"Subkey Binding Signature" },
40     { PGPSIGTYPE_SIGNED_KEY,    "Signature directly on a key" },
41     { PGPSIGTYPE_KEY_REVOKE,    "Key revocation signature" },
42     { PGPSIGTYPE_SUBKEY_REVOKE, "Subkey revocation signature" },
43     { PGPSIGTYPE_CERT_REVOKE,   "Certification revocation signature" },
44     { PGPSIGTYPE_TIMESTAMP,     "Timestamp signature" },
45     { -1,                       "Unknown signature type" },
46 };
47
48 static struct pgpValTbl_s const pgpPubkeyTbl[] = {
49     { PGPPUBKEYALGO_RSA,        "RSA" },
50     { PGPPUBKEYALGO_RSA_ENCRYPT,"RSA(Encrypt-Only)" },
51     { PGPPUBKEYALGO_RSA_SIGN,   "RSA(Sign-Only)" },
52     { PGPPUBKEYALGO_ELGAMAL_ENCRYPT,"Elgamal(Encrypt-Only)" },
53     { PGPPUBKEYALGO_DSA,        "DSA" },
54     { PGPPUBKEYALGO_EC,         "Elliptic Curve" },
55     { PGPPUBKEYALGO_ECDSA,      "ECDSA" },
56     { PGPPUBKEYALGO_ELGAMAL,    "Elgamal" },
57     { PGPPUBKEYALGO_DH,         "Diffie-Hellman (X9.42)" },
58     { -1,                       "Unknown public key algorithm" },
59 };
60
61 static struct pgpValTbl_s const pgpSymkeyTbl[] = {
62     { PGPSYMKEYALGO_PLAINTEXT,  "Plaintext" },
63     { PGPSYMKEYALGO_IDEA,       "IDEA" },
64     { PGPSYMKEYALGO_TRIPLE_DES, "3DES" },
65     { PGPSYMKEYALGO_CAST5,      "CAST5" },
66     { PGPSYMKEYALGO_BLOWFISH,   "BLOWFISH" },
67     { PGPSYMKEYALGO_SAFER,      "SAFER" },
68     { PGPSYMKEYALGO_DES_SK,     "DES/SK" },
69     { PGPSYMKEYALGO_AES_128,    "AES(128-bit key)" },
70     { PGPSYMKEYALGO_AES_192,    "AES(192-bit key)" },
71     { PGPSYMKEYALGO_AES_256,    "AES(256-bit key)" },
72     { PGPSYMKEYALGO_TWOFISH,    "TWOFISH(256-bit key)" },
73     { PGPSYMKEYALGO_NOENCRYPT,  "no encryption" },
74     { -1,                       "Unknown symmetric key algorithm" },
75 };
76
77 static struct pgpValTbl_s const pgpCompressionTbl[] = {
78     { PGPCOMPRESSALGO_NONE,     "Uncompressed" },
79     { PGPCOMPRESSALGO_ZIP,      "ZIP" },
80     { PGPCOMPRESSALGO_ZLIB,     "ZLIB" },
81     { PGPCOMPRESSALGO_BZIP2,    "BZIP2" },
82     { -1,                       "Unknown compression algorithm" },
83 };
84
85 static struct pgpValTbl_s const pgpHashTbl[] = {
86     { PGPHASHALGO_MD5,          "MD5" },
87     { PGPHASHALGO_SHA1,         "SHA1" },
88     { PGPHASHALGO_RIPEMD160,    "RIPEMD160" },
89     { PGPHASHALGO_MD2,          "MD2" },
90     { PGPHASHALGO_TIGER192,     "TIGER192" },
91     { PGPHASHALGO_HAVAL_5_160,  "HAVAL-5-160" },
92     { PGPHASHALGO_SHA256,       "SHA256" },
93     { PGPHASHALGO_SHA384,       "SHA384" },
94     { PGPHASHALGO_SHA512,       "SHA512" },
95     { PGPHASHALGO_SHA224,       "SHA224" },
96     { -1,                       "Unknown hash algorithm" },
97 };
98
99 static struct pgpValTbl_s const pgpKeyServerPrefsTbl[] = {
100     { 0x80,                     "No-modify" },
101     { -1,                       "Unknown key server preference" },
102 };
103
104 static struct pgpValTbl_s const pgpSubTypeTbl[] = {
105     { PGPSUBTYPE_SIG_CREATE_TIME,"signature creation time" },
106     { PGPSUBTYPE_SIG_EXPIRE_TIME,"signature expiration time" },
107     { PGPSUBTYPE_EXPORTABLE_CERT,"exportable certification" },
108     { PGPSUBTYPE_TRUST_SIG,     "trust signature" },
109     { PGPSUBTYPE_REGEX,         "regular expression" },
110     { PGPSUBTYPE_REVOCABLE,     "revocable" },
111     { PGPSUBTYPE_KEY_EXPIRE_TIME,"key expiration time" },
112     { PGPSUBTYPE_ARR,           "additional recipient request" },
113     { PGPSUBTYPE_PREFER_SYMKEY, "preferred symmetric algorithms" },
114     { PGPSUBTYPE_REVOKE_KEY,    "revocation key" },
115     { PGPSUBTYPE_ISSUER_KEYID,  "issuer key ID" },
116     { PGPSUBTYPE_NOTATION,      "notation data" },
117     { PGPSUBTYPE_PREFER_HASH,   "preferred hash algorithms" },
118     { PGPSUBTYPE_PREFER_COMPRESS,"preferred compression algorithms" },
119     { PGPSUBTYPE_KEYSERVER_PREFERS,"key server preferences" },
120     { PGPSUBTYPE_PREFER_KEYSERVER,"preferred key server" },
121     { PGPSUBTYPE_PRIMARY_USERID,"primary user id" },
122     { PGPSUBTYPE_POLICY_URL,    "policy URL" },
123     { PGPSUBTYPE_KEY_FLAGS,     "key flags" },
124     { PGPSUBTYPE_SIGNER_USERID, "signer's user id" },
125     { PGPSUBTYPE_REVOKE_REASON, "reason for revocation" },
126     { PGPSUBTYPE_FEATURES,      "features" },
127     { PGPSUBTYPE_EMBEDDED_SIG,  "embedded signature" },
128
129     { PGPSUBTYPE_INTERNAL_100,  "internal subpkt type 100" },
130     { PGPSUBTYPE_INTERNAL_101,  "internal subpkt type 101" },
131     { PGPSUBTYPE_INTERNAL_102,  "internal subpkt type 102" },
132     { PGPSUBTYPE_INTERNAL_103,  "internal subpkt type 103" },
133     { PGPSUBTYPE_INTERNAL_104,  "internal subpkt type 104" },
134     { PGPSUBTYPE_INTERNAL_105,  "internal subpkt type 105" },
135     { PGPSUBTYPE_INTERNAL_106,  "internal subpkt type 106" },
136     { PGPSUBTYPE_INTERNAL_107,  "internal subpkt type 107" },
137     { PGPSUBTYPE_INTERNAL_108,  "internal subpkt type 108" },
138     { PGPSUBTYPE_INTERNAL_109,  "internal subpkt type 109" },
139     { PGPSUBTYPE_INTERNAL_110,  "internal subpkt type 110" },
140     { -1,                       "Unknown signature subkey type" },
141 };
142
143 static struct pgpValTbl_s const pgpTagTbl[] = {
144     { PGPTAG_PUBLIC_SESSION_KEY,"Public-Key Encrypted Session Key" },
145     { PGPTAG_SIGNATURE,         "Signature" },
146     { PGPTAG_SYMMETRIC_SESSION_KEY,"Symmetric-Key Encrypted Session Key" },
147     { PGPTAG_ONEPASS_SIGNATURE, "One-Pass Signature" },
148     { PGPTAG_SECRET_KEY,        "Secret Key" },
149     { PGPTAG_PUBLIC_KEY,        "Public Key" },
150     { PGPTAG_SECRET_SUBKEY,     "Secret Subkey" },
151     { PGPTAG_COMPRESSED_DATA,   "Compressed Data" },
152     { PGPTAG_SYMMETRIC_DATA,    "Symmetrically Encrypted Data" },
153     { PGPTAG_MARKER,            "Marker" },
154     { PGPTAG_LITERAL_DATA,      "Literal Data" },
155     { PGPTAG_TRUST,             "Trust" },
156     { PGPTAG_USER_ID,           "User ID" },
157     { PGPTAG_PUBLIC_SUBKEY,     "Public Subkey" },
158     { PGPTAG_COMMENT_OLD,       "Comment (from OpenPGP draft)" },
159     { PGPTAG_PHOTOID,           "PGP's photo ID" },
160     { PGPTAG_ENCRYPTED_MDC,     "Integrity protected encrypted data" },
161     { PGPTAG_MDC,               "Manipulaion detection code packet" },
162     { PGPTAG_PRIVATE_60,        "Private #60" },
163     { PGPTAG_COMMENT,           "Comment" },
164     { PGPTAG_PRIVATE_62,        "Private #62" },
165     { PGPTAG_CONTROL,           "Control (GPG)" },
166     { -1,                       "Unknown packet tag" },
167 };
168
169 static struct pgpValTbl_s const pgpArmorTbl[] = {
170     { PGPARMOR_MESSAGE,         "MESSAGE" },
171     { PGPARMOR_PUBKEY,          "PUBLIC KEY BLOCK" },
172     { PGPARMOR_SIGNATURE,       "SIGNATURE" },
173     { PGPARMOR_SIGNED_MESSAGE,  "SIGNED MESSAGE" },
174     { PGPARMOR_FILE,            "ARMORED FILE" },
175     { PGPARMOR_PRIVKEY,         "PRIVATE KEY BLOCK" },
176     { PGPARMOR_SECKEY,          "SECRET KEY BLOCK" },
177     { -1,                       "Unknown armor block" }
178 };
179
180 static struct pgpValTbl_s const pgpArmorKeyTbl[] = {
181     { PGPARMORKEY_VERSION,      "Version: " },
182     { PGPARMORKEY_COMMENT,      "Comment: " },
183     { PGPARMORKEY_MESSAGEID,    "MessageID: " },
184     { PGPARMORKEY_HASH,         "Hash: " },
185     { PGPARMORKEY_CHARSET,      "Charset: " },
186     { -1,                       "Unknown armor key" }
187 };
188
189 static void pgpPrtNL(void)
190 {
191     if (!_print) return;
192     fprintf(stderr, "\n");
193 }
194
195 static void pgpPrtInt(const char *pre, int i)
196 {
197     if (!_print) return;
198     if (pre && *pre)
199         fprintf(stderr, "%s", pre);
200     fprintf(stderr, " %d", i);
201 }
202
203 static void pgpPrtStr(const char *pre, const char *s)
204 {
205     if (!_print) return;
206     if (pre && *pre)
207         fprintf(stderr, "%s", pre);
208     fprintf(stderr, " %s", s);
209 }
210
211 static const char * pgpValStr(pgpValTbl vs, uint8_t val)
212 {
213     do {
214         if (vs->val == val)
215             break;
216     } while ((++vs)->val != -1);
217     return vs->str;
218 }
219
220 static pgpValTbl pgpValTable(pgpValType type)
221 {
222     switch (type) {
223     case PGPVAL_TAG:            return pgpTagTbl;
224     case PGPVAL_ARMORBLOCK:     return pgpArmorTbl;
225     case PGPVAL_ARMORKEY:       return pgpArmorKeyTbl;
226     case PGPVAL_SIGTYPE:        return pgpSigTypeTbl;
227     case PGPVAL_SUBTYPE:        return pgpSubTypeTbl;
228     case PGPVAL_PUBKEYALGO:     return pgpPubkeyTbl;
229     case PGPVAL_SYMKEYALGO:     return pgpSymkeyTbl;
230     case PGPVAL_COMPRESSALGO:   return pgpCompressionTbl;
231     case PGPVAL_HASHALGO:       return pgpHashTbl;
232     case PGPVAL_SERVERPREFS:    return pgpKeyServerPrefsTbl;
233     default:
234         break;
235     }
236     return NULL;
237 }
238
239 const char * pgpValString(pgpValType type, uint8_t val)
240 {
241     pgpValTbl tbl = pgpValTable(type);
242     return (tbl != NULL) ? pgpValStr(tbl, val) : NULL;
243 }
244
245 static void pgpPrtHex(const char *pre, const uint8_t *p, size_t plen)
246 {
247     char *hex = NULL;
248     if (!_print) return;
249     if (pre && *pre)
250         fprintf(stderr, "%s", pre);
251     hex = pgpHexStr(p, plen);
252     fprintf(stderr, " %s", hex);
253     free(hex);
254 }
255
256 static void pgpPrtVal(const char * pre, pgpValTbl vs, uint8_t val)
257 {
258     if (!_print) return;
259     if (pre && *pre)
260         fprintf(stderr, "%s", pre);
261     fprintf(stderr, "%s(%u)", pgpValStr(vs, val), (unsigned)val);
262 }
263
264 /** \ingroup rpmpgp
265  * Return no. of bits in a multiprecision integer.
266  * @param p             pointer to multiprecision integer
267  * @return              no. of bits
268  */
269 static 
270 unsigned int pgpMpiBits(const uint8_t *p)
271 {
272     return ((p[0] << 8) | p[1]);
273 }
274
275 /** \ingroup rpmpgp
276  * Return no. of bytes in a multiprecision integer.
277  * @param p             pointer to multiprecision integer
278  * @return              no. of bytes
279  */
280 static
281 size_t pgpMpiLen(const uint8_t *p)
282 {
283     return (2 + ((pgpMpiBits(p)+7)>>3));
284 }
285         
286 /** \ingroup rpmpgp
287  * Return hex formatted representation of a multiprecision integer.
288  * @param p             bytes
289  * @return              hex formatted string (malloc'ed)
290  */
291 static inline
292 char * pgpMpiStr(const uint8_t *p)
293 {
294     char *str = NULL;
295     char *hex = pgpHexStr(p+2, pgpMpiLen(p)-2);
296     rasprintf(&str, "[%4u]: %s", pgpGrab(p, (size_t) 2), hex);
297     free(hex);
298     return str;
299 }
300
301 /** \ingroup rpmpgp
302  * Return value of an OpenPGP string.
303  * @param vs            table of (string,value) pairs
304  * @param s             string token to lookup
305  * @param se            end-of-string address
306  * @return              byte value
307  */
308 static inline
309 int pgpValTok(pgpValTbl vs, const char * s, const char * se)
310 {
311     do {
312         size_t vlen = strlen(vs->str);
313         if (vlen <= (se-s) && rstreqn(s, vs->str, vlen))
314             break;
315     } while ((++vs)->val != -1);
316     return vs->val;
317 }
318 /**
319  * @return              0 on success
320  */
321 static int pgpMpiSet(const char * pre, unsigned int lbits,
322                 uint8_t *dest, const uint8_t * p, const uint8_t * pend)
323 {
324     unsigned int mbits = pgpMpiBits(p);
325     unsigned int nbits;
326     size_t nbytes;
327     uint8_t *t = dest;
328     unsigned int ix;
329
330     if ((p + ((mbits+7) >> 3)) > pend)
331         return 1;
332
333     if (mbits > lbits)
334         return 1;
335
336     nbits = (lbits > mbits ? lbits : mbits);
337     nbytes = ((nbits + 7) >> 3);
338     ix = (nbits - mbits) >> 3;
339
340 if (_debug)
341 fprintf(stderr, "*** mbits %u nbits %u nbytes %zu ix %u\n", mbits, nbits, nbytes, ix);
342     if (ix > 0) memset(t, '\0', ix);
343     memcpy(t+ix, p+2, nbytes-ix);
344 if (_debug)
345 fprintf(stderr, "*** %s %s\n", pre, pgpHexStr(dest, nbytes));
346
347     return 0;
348 }
349
350 /**
351  * @return              NULL on error
352  */
353 static SECItem *pgpMpiItem(PRArenaPool *arena, SECItem *item, const uint8_t *p)
354 {
355     size_t nbytes = pgpMpiLen(p)-2;
356
357     if (item == NULL) {
358         if ((item=SECITEM_AllocItem(arena, item, nbytes)) == NULL)
359             return item;
360     } else {
361         if (arena != NULL)
362             item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
363         else
364             item->data = PORT_Realloc(item->data, nbytes);
365         
366         if (item->data == NULL) {
367             if (arena == NULL)
368                 SECITEM_FreeItem(item, PR_TRUE);
369             return NULL;
370         }
371     }
372
373     memcpy(item->data, p+2, nbytes);
374     item->len = nbytes;
375     return item;
376 }
377 /*@=boundswrite@*/
378
379 static SECKEYPublicKey *pgpNewPublicKey(KeyType type)
380 {
381     PRArenaPool *arena;
382     SECKEYPublicKey *key;
383     
384     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
385     if (arena == NULL)
386         return NULL;
387     
388     key = PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
389     
390     if (key == NULL) {
391         PORT_FreeArena(arena, PR_FALSE);
392         return NULL;
393     }
394     
395     key->keyType = type;
396     key->pkcs11ID = CK_INVALID_HANDLE;
397     key->pkcs11Slot = NULL;
398     key->arena = arena;
399     return key;
400 }
401
402 /** \ingroup rpmpgp
403  * Is buffer at beginning of an OpenPGP packet?
404  * @param p             buffer
405  * @return              1 if an OpenPGP packet, 0 otherwise
406  */
407 static inline
408 int pgpIsPkt(const uint8_t * p)
409 {
410     unsigned int val = *p++;
411     pgpTag tag;
412     int rc;
413
414     /* XXX can't deal with these. */
415     if (!(val & 0x80))
416         return 0;
417
418     if (val & 0x40)
419         tag = (pgpTag)(val & 0x3f);
420     else
421         tag = (pgpTag)((val >> 2) & 0xf);
422
423     switch (tag) {
424     case PGPTAG_MARKER:
425     case PGPTAG_SYMMETRIC_SESSION_KEY:
426     case PGPTAG_ONEPASS_SIGNATURE:
427     case PGPTAG_PUBLIC_KEY:
428     case PGPTAG_SECRET_KEY:
429     case PGPTAG_PUBLIC_SESSION_KEY:
430     case PGPTAG_SIGNATURE:
431     case PGPTAG_COMMENT:
432     case PGPTAG_COMMENT_OLD:
433     case PGPTAG_LITERAL_DATA:
434     case PGPTAG_COMPRESSED_DATA:
435     case PGPTAG_SYMMETRIC_DATA:
436         rc = 1;
437         break;
438     case PGPTAG_PUBLIC_SUBKEY:
439     case PGPTAG_SECRET_SUBKEY:
440     case PGPTAG_USER_ID:
441     case PGPTAG_RESERVED:
442     case PGPTAG_TRUST:
443     case PGPTAG_PHOTOID:
444     case PGPTAG_ENCRYPTED_MDC:
445     case PGPTAG_MDC:
446     case PGPTAG_PRIVATE_60:
447     case PGPTAG_PRIVATE_62:
448     case PGPTAG_CONTROL:
449     default:
450         rc = 0;
451         break;
452     }
453
454     return rc;
455 }
456
457 #define CRC24_INIT      0xb704ce
458 #define CRC24_POLY      0x1864cfb
459
460 /** \ingroup rpmpgp
461  * Return CRC of a buffer.
462  * @param octets        bytes
463  * @param len           no. of bytes
464  * @return              crc of buffer
465  */
466 static inline
467 unsigned int pgpCRC(const uint8_t *octets, size_t len)
468 {
469     unsigned int crc = CRC24_INIT;
470     size_t i;
471
472     while (len--) {
473         crc ^= (*octets++) << 16;
474         for (i = 0; i < 8; i++) {
475             crc <<= 1;
476             if (crc & 0x1000000)
477                 crc ^= CRC24_POLY;
478         }
479     }
480     return crc & 0xffffff;
481 }
482
483 static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype, 
484                          pgpDigParams _digp)
485 {
486     const uint8_t *p = h;
487     size_t plen, i;
488
489     while (hlen > 0) {
490         i = pgpLen(p, &plen);
491         p += i;
492         hlen -= i;
493
494         pgpPrtVal("    ", pgpSubTypeTbl, (p[0]&(~PGPSUBTYPE_CRITICAL)));
495         if (p[0] & PGPSUBTYPE_CRITICAL)
496             if (_print)
497                 fprintf(stderr, " *CRITICAL*");
498         switch (*p) {
499         case PGPSUBTYPE_PREFER_SYMKEY:  /* preferred symmetric algorithms */
500             for (i = 1; i < plen; i++)
501                 pgpPrtVal(" ", pgpSymkeyTbl, p[i]);
502             break;
503         case PGPSUBTYPE_PREFER_HASH:    /* preferred hash algorithms */
504             for (i = 1; i < plen; i++)
505                 pgpPrtVal(" ", pgpHashTbl, p[i]);
506             break;
507         case PGPSUBTYPE_PREFER_COMPRESS:/* preferred compression algorithms */
508             for (i = 1; i < plen; i++)
509                 pgpPrtVal(" ", pgpCompressionTbl, p[i]);
510             break;
511         case PGPSUBTYPE_KEYSERVER_PREFERS:/* key server preferences */
512             for (i = 1; i < plen; i++)
513                 pgpPrtVal(" ", pgpKeyServerPrefsTbl, p[i]);
514             break;
515         case PGPSUBTYPE_SIG_CREATE_TIME:
516             if (_digp && !(_digp->saved & PGPDIG_SAVED_TIME) &&
517                 (sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
518             {
519                 _digp->saved |= PGPDIG_SAVED_TIME;
520                 memcpy(_digp->time, p+1, sizeof(_digp->time));
521             }
522         case PGPSUBTYPE_SIG_EXPIRE_TIME:
523         case PGPSUBTYPE_KEY_EXPIRE_TIME:
524             if ((plen - 1) == 4) {
525                 time_t t = pgpGrab(p+1, plen-1);
526                 if (_print)
527                    fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
528             } else
529                 pgpPrtHex("", p+1, plen-1);
530             break;
531
532         case PGPSUBTYPE_ISSUER_KEYID:   /* issuer key ID */
533             if (_digp && !(_digp->saved & PGPDIG_SAVED_ID) &&
534                 (sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
535             {
536                 _digp->saved |= PGPDIG_SAVED_ID;
537                 memcpy(_digp->signid, p+1, sizeof(_digp->signid));
538             }
539         case PGPSUBTYPE_EXPORTABLE_CERT:
540         case PGPSUBTYPE_TRUST_SIG:
541         case PGPSUBTYPE_REGEX:
542         case PGPSUBTYPE_REVOCABLE:
543         case PGPSUBTYPE_ARR:
544         case PGPSUBTYPE_REVOKE_KEY:
545         case PGPSUBTYPE_NOTATION:
546         case PGPSUBTYPE_PREFER_KEYSERVER:
547         case PGPSUBTYPE_PRIMARY_USERID:
548         case PGPSUBTYPE_POLICY_URL:
549         case PGPSUBTYPE_KEY_FLAGS:
550         case PGPSUBTYPE_SIGNER_USERID:
551         case PGPSUBTYPE_REVOKE_REASON:
552         case PGPSUBTYPE_FEATURES:
553         case PGPSUBTYPE_EMBEDDED_SIG:
554         case PGPSUBTYPE_INTERNAL_100:
555         case PGPSUBTYPE_INTERNAL_101:
556         case PGPSUBTYPE_INTERNAL_102:
557         case PGPSUBTYPE_INTERNAL_103:
558         case PGPSUBTYPE_INTERNAL_104:
559         case PGPSUBTYPE_INTERNAL_105:
560         case PGPSUBTYPE_INTERNAL_106:
561         case PGPSUBTYPE_INTERNAL_107:
562         case PGPSUBTYPE_INTERNAL_108:
563         case PGPSUBTYPE_INTERNAL_109:
564         case PGPSUBTYPE_INTERNAL_110:
565         default:
566             pgpPrtHex("", p+1, plen-1);
567             break;
568         }
569         pgpPrtNL();
570         p += plen;
571         hlen -= plen;
572     }
573     return 0;
574 }
575
576 static const char * const pgpSigRSA[] = {
577     " m**d =",
578     NULL,
579 };
580
581 static const char * const pgpSigDSA[] = {
582     "    r =",
583     "    s =",
584     NULL,
585 };
586
587 #ifndef DSA_SUBPRIME_LEN
588 #define DSA_SUBPRIME_LEN 20
589 #endif
590
591 static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
592                 const uint8_t *p, const uint8_t *h, size_t hlen, pgpDig _dig)
593 {
594     const uint8_t * pend = h + hlen;
595     size_t i;
596     SECItem dsaraw;
597     unsigned char dsabuf[2*DSA_SUBPRIME_LEN];
598     char *mpi;
599
600     dsaraw.type = 0;
601     dsaraw.data = dsabuf;
602     dsaraw.len = sizeof(dsabuf);
603     
604     for (i = 0; p < pend; i++, p += pgpMpiLen(p)) {
605         if (pubkey_algo == PGPPUBKEYALGO_RSA) {
606             if (i >= 1) break;
607             if (_dig &&
608         (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT))
609             {
610                 switch (i) {
611                 case 0:         /* m**d */
612                     _dig->sigdata = pgpMpiItem(NULL, _dig->sigdata, p);
613                     if (_dig->sigdata == NULL)
614                         return 1;
615                     break;
616                 default:
617                     break;
618                 }
619             }
620             pgpPrtStr("", pgpSigRSA[i]);
621         } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
622             if (i >= 2) break;
623             if (_dig &&
624         (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT))
625             {
626                 int xx;
627                 xx = 0;
628                 switch (i) {
629                 case 0:
630                     memset(dsaraw.data, '\0', 2*DSA_SUBPRIME_LEN);
631                                 /* r */
632                     xx = pgpMpiSet(pgpSigDSA[i], DSA_SUBPRIME_LEN*8, dsaraw.data, p, pend);
633                     break;
634                 case 1:         /* s */
635                     xx = pgpMpiSet(pgpSigDSA[i], DSA_SUBPRIME_LEN*8, dsaraw.data + DSA_SUBPRIME_LEN, p, pend);
636                     if (_dig->sigdata != NULL)
637                         SECITEM_FreeItem(_dig->sigdata, PR_FALSE);
638                     else if ((_dig->sigdata=SECITEM_AllocItem(NULL, NULL, 0)) == NULL) {
639                         xx = 1;
640                         break;
641                     }
642                     if (DSAU_EncodeDerSig(_dig->sigdata, &dsaraw) != SECSuccess)
643                         xx = 1;
644                     break;
645                 default:
646                     xx = 1;
647                     break;
648                 }
649                 if (xx) return xx;
650             }
651             pgpPrtStr("", pgpSigDSA[i]);
652         } else {
653             if (_print)
654                 fprintf(stderr, "%7zd", i);
655         }
656         mpi = pgpMpiStr(p);
657         pgpPrtStr("", mpi);
658         free(mpi);
659         pgpPrtNL();
660     }
661
662     return 0;
663 }
664
665 static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
666                      pgpDig _dig, pgpDigParams _digp)
667 {
668     uint8_t version = h[0];
669     uint8_t * p;
670     size_t plen;
671     int rc;
672
673     switch (version) {
674     case 3:
675     {   pgpPktSigV3 v = (pgpPktSigV3)h;
676         time_t t;
677
678         if (v->hashlen != 5)
679             return 1;
680
681         pgpPrtVal("V3 ", pgpTagTbl, tag);
682         pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
683         pgpPrtVal(" ", pgpHashTbl, v->hash_algo);
684         pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype);
685         pgpPrtNL();
686         t = pgpGrab(v->time, sizeof(v->time));
687         if (_print)
688             fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
689         pgpPrtNL();
690         pgpPrtHex(" signer keyid", v->signid, sizeof(v->signid));
691         plen = pgpGrab(v->signhash16, sizeof(v->signhash16));
692         pgpPrtHex(" signhash16", v->signhash16, sizeof(v->signhash16));
693         pgpPrtNL();
694
695         if (_digp && _digp->pubkey_algo == 0) {
696             _digp->version = v->version;
697             _digp->hashlen = v->hashlen;
698             _digp->sigtype = v->sigtype;
699             _digp->hash = memcpy(xmalloc(v->hashlen), &v->sigtype, v->hashlen);
700             memcpy(_digp->time, v->time, sizeof(_digp->time));
701             memcpy(_digp->signid, v->signid, sizeof(_digp->signid));
702             _digp->pubkey_algo = v->pubkey_algo;
703             _digp->hash_algo = v->hash_algo;
704             memcpy(_digp->signhash16, v->signhash16, sizeof(_digp->signhash16));
705         }
706
707         p = ((uint8_t *)v) + sizeof(*v);
708         rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _dig);
709     }   break;
710     case 4:
711     {   pgpPktSigV4 v = (pgpPktSigV4)h;
712
713         pgpPrtVal("V4 ", pgpTagTbl, tag);
714         pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
715         pgpPrtVal(" ", pgpHashTbl, v->hash_algo);
716         pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype);
717         pgpPrtNL();
718
719         p = &v->hashlen[0];
720         plen = pgpGrab(v->hashlen, sizeof(v->hashlen));
721         p += sizeof(v->hashlen);
722
723         if ((p + plen) > (h + hlen))
724             return 1;
725
726 if (_debug && _print)
727 fprintf(stderr, "   hash[%zu] -- %s\n", plen, pgpHexStr(p, plen));
728         if (_digp && _digp->pubkey_algo == 0) {
729             _digp->hashlen = sizeof(*v) + plen;
730             _digp->hash = memcpy(xmalloc(_digp->hashlen), v, _digp->hashlen);
731         }
732         (void) pgpPrtSubType(p, plen, v->sigtype, _digp);
733         p += plen;
734
735         plen = pgpGrab(p,2);
736         p += 2;
737
738         if ((p + plen) > (h + hlen))
739             return 1;
740
741 if (_debug && _print)
742 fprintf(stderr, " unhash[%zu] -- %s\n", plen, pgpHexStr(p, plen));
743         (void) pgpPrtSubType(p, plen, v->sigtype, _digp);
744         p += plen;
745
746         plen = pgpGrab(p,2);
747         pgpPrtHex(" signhash16", p, 2);
748         pgpPrtNL();
749
750         if (_digp && _digp->pubkey_algo == 0) {
751             _digp->version = v->version;
752             _digp->sigtype = v->sigtype;
753             _digp->pubkey_algo = v->pubkey_algo;
754             _digp->hash_algo = v->hash_algo;
755             memcpy(_digp->signhash16, p, sizeof(_digp->signhash16));
756         }
757
758         p += 2;
759         if (p > (h + hlen))
760             return 1;
761
762         rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _dig);
763     }   break;
764     default:
765         rc = 1;
766         break;
767     }
768     return rc;
769 }
770
771 static const char * const pgpPublicRSA[] = {
772     "    n =",
773     "    e =",
774     NULL,
775 };
776
777 #ifdef NOTYET
778 static const char * const pgpSecretRSA[] = {
779     "    d =",
780     "    p =",
781     "    q =",
782     "    u =",
783     NULL,
784 };
785 #endif
786
787 static const char * const pgpPublicDSA[] = {
788     "    p =",
789     "    q =",
790     "    g =",
791     "    y =",
792     NULL,
793 };
794
795 #ifdef NOTYET
796 static const char * const pgpSecretDSA[] = {
797     "    x =",
798     NULL,
799 };
800 #endif
801
802 static const char * const pgpPublicELGAMAL[] = {
803     "    p =",
804     "    g =",
805     "    y =",
806     NULL,
807 };
808
809 #ifdef NOTYET
810 static const char * const pgpSecretELGAMAL[] = {
811     "    x =",
812     NULL,
813 };
814 #endif
815
816 char * pgpHexStr(const uint8_t *p, size_t plen)
817 {
818     char *t, *str;
819     str = t = xmalloc(plen * 2 + 1);
820     static char const hex[] = "0123456789abcdef";
821     while (plen-- > 0) {
822         size_t i;
823         i = *p++;
824         *t++ = hex[ (i >> 4) & 0xf ];
825         *t++ = hex[ (i     ) & 0xf ];
826     }
827     *t = '\0';
828     return str;
829 }
830
831 static const uint8_t * pgpPrtPubkeyParams(uint8_t pubkey_algo,
832                 const uint8_t *p, const uint8_t *h, size_t hlen,
833                 pgpDig _dig)
834 {
835     size_t i;
836
837     for (i = 0; p < &h[hlen]; i++, p += pgpMpiLen(p)) {
838         char * mpi;
839         if (pubkey_algo == PGPPUBKEYALGO_RSA) {
840             if (i >= 2) break;
841             if (_dig) {
842                 if (_dig->keydata == NULL) {
843                     _dig->keydata = pgpNewPublicKey(rsaKey);
844                     if (_dig->keydata == NULL)
845                         break; /* error abort? */
846                 }
847                 switch (i) {
848                 case 0:         /* n */
849                     pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.rsa.modulus, p);
850                     break;
851                 case 1:         /* e */
852                     pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.rsa.publicExponent, p);
853                     break;
854                 default:
855                     break;
856                 }
857             }
858             pgpPrtStr("", pgpPublicRSA[i]);
859         } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
860             if (i >= 4) break;
861             if (_dig) {
862                 if (_dig->keydata == NULL) {
863                     _dig->keydata = pgpNewPublicKey(dsaKey);
864                     if (_dig->keydata == NULL)
865                         break; /* error abort? */
866                 }
867                 switch (i) {
868                 case 0:         /* p */
869                     pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.prime, p);
870                     break;
871                 case 1:         /* q */
872                     pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.subPrime, p);
873                     break;
874                 case 2:         /* g */
875                     pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.base, p);
876                     break;
877                 case 3:         /* y */
878                     pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.publicValue, p);
879                     break;
880                 default:
881                     break;
882                 }
883             }
884             pgpPrtStr("", pgpPublicDSA[i]);
885         } else if (pubkey_algo == PGPPUBKEYALGO_ELGAMAL_ENCRYPT) {
886             if (i >= 3) break;
887             pgpPrtStr("", pgpPublicELGAMAL[i]);
888         } else {
889             if (_print)
890                 fprintf(stderr, "%7zd", i);
891         }
892         mpi = pgpMpiStr(p);
893         pgpPrtStr("", mpi);
894         free(mpi);
895         pgpPrtNL();
896     }
897
898     return p;
899 }
900
901 static const uint8_t * pgpPrtSeckeyParams(uint8_t pubkey_algo,
902                 const uint8_t *p, const uint8_t *h, size_t hlen)
903 {
904     size_t i;
905
906     switch (*p) {
907     case 0:
908         pgpPrtVal(" ", pgpSymkeyTbl, *p);
909         break;
910     case 255:
911         p++;
912         pgpPrtVal(" ", pgpSymkeyTbl, *p);
913         switch (p[1]) {
914         case 0x00:
915             pgpPrtVal(" simple ", pgpHashTbl, p[2]);
916             p += 2;
917             break;
918         case 0x01:
919             pgpPrtVal(" salted ", pgpHashTbl, p[2]);
920             pgpPrtHex("", p+3, 8);
921             p += 10;
922             break;
923         case 0x03:
924             pgpPrtVal(" iterated/salted ", pgpHashTbl, p[2]);
925             /* FIX: unsigned cast */
926             i = (16 + (p[11] & 0xf)) << ((p[11] >> 4) + 6);
927             pgpPrtHex("", p+3, 8);
928             pgpPrtInt(" iter", i);
929             p += 11;
930             break;
931         }
932         break;
933     default:
934         pgpPrtVal(" ", pgpSymkeyTbl, *p);
935         pgpPrtHex(" IV", p+1, 8);
936         p += 8;
937         break;
938     }
939     pgpPrtNL();
940
941     p++;
942
943 #ifdef  NOTYET  /* XXX encrypted MPI's need to be handled. */
944     for (i = 0; p < &h[hlen]; i++, p += pgpMpiLen(p)) {
945         char *mpi;
946         if (pubkey_algo == PGPPUBKEYALGO_RSA) {
947             if (pgpSecretRSA[i] == NULL) break;
948             pgpPrtStr("", pgpSecretRSA[i]);
949         } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
950             if (pgpSecretDSA[i] == NULL) break;
951             pgpPrtStr("", pgpSecretDSA[i]);
952         } else if (pubkey_algo == PGPPUBKEYALGO_ELGAMAL_ENCRYPT) {
953             if (pgpSecretELGAMAL[i] == NULL) break;
954             pgpPrtStr("", pgpSecretELGAMAL[i]);
955         } else {
956             if (_print)
957                 fprintf(stderr, "%7d", i);
958         }
959         mpi = pgpMpiStr(p);
960         pgpPrtStr("", mpi);
961         free(mpi);
962         pgpPrtNL();
963     }
964 #else
965     pgpPrtHex(" secret", p, (hlen - (p - h) - 2));
966     pgpPrtNL();
967     p += (hlen - (p - h) - 2);
968 #endif
969     pgpPrtHex(" checksum", p, 2);
970     pgpPrtNL();
971
972     return p;
973 }
974
975 static int pgpPrtKey(pgpTag tag, const uint8_t *h, size_t hlen,
976                      pgpDig _dig, pgpDigParams _digp)
977 {
978     uint8_t version = *h;
979     const uint8_t * p;
980     size_t plen;
981     time_t t;
982     int rc;
983
984     switch (version) {
985     case 3:
986     {   pgpPktKeyV3 v = (pgpPktKeyV3)h;
987         pgpPrtVal("V3 ", pgpTagTbl, tag);
988         pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
989         t = pgpGrab(v->time, sizeof(v->time));
990         if (_print)
991             fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
992         plen = pgpGrab(v->valid, sizeof(v->valid));
993         if (plen != 0)
994             fprintf(stderr, " valid %zu days", plen);
995         pgpPrtNL();
996
997         if (_digp && _digp->tag == tag) {
998             _digp->version = v->version;
999             memcpy(_digp->time, v->time, sizeof(_digp->time));
1000             _digp->pubkey_algo = v->pubkey_algo;
1001         }
1002
1003         p = ((uint8_t *)v) + sizeof(*v);
1004         p = pgpPrtPubkeyParams(v->pubkey_algo, p, h, hlen, _dig);
1005         rc = 0;
1006     }   break;
1007     case 4:
1008     {   pgpPktKeyV4 v = (pgpPktKeyV4)h;
1009         pgpPrtVal("V4 ", pgpTagTbl, tag);
1010         pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
1011         t = pgpGrab(v->time, sizeof(v->time));
1012         if (_print)
1013             fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
1014         pgpPrtNL();
1015
1016         if (_digp && _digp->tag == tag) {
1017             _digp->version = v->version;
1018             memcpy(_digp->time, v->time, sizeof(_digp->time));
1019             _digp->pubkey_algo = v->pubkey_algo;
1020         }
1021
1022         p = ((uint8_t *)v) + sizeof(*v);
1023         p = pgpPrtPubkeyParams(v->pubkey_algo, p, h, hlen, _dig);
1024         if (!(tag == PGPTAG_PUBLIC_KEY || tag == PGPTAG_PUBLIC_SUBKEY))
1025             p = pgpPrtSeckeyParams(v->pubkey_algo, p, h, hlen);
1026         rc = 0;
1027     }   break;
1028     default:
1029         rc = 1;
1030         break;
1031     }
1032     return rc;
1033 }
1034
1035 static int pgpPrtUserID(pgpTag tag, const uint8_t *h, size_t hlen,
1036                         pgpDigParams _digp)
1037 {
1038     pgpPrtVal("", pgpTagTbl, tag);
1039     if (_print)
1040         fprintf(stderr, " \"%.*s\"", (int)hlen, (const char *)h);
1041     pgpPrtNL();
1042     if (_digp) {
1043         char * t;
1044         _digp->userid = t = memcpy(xmalloc(hlen+1), h, hlen);
1045         t[hlen] = '\0';
1046     }
1047     return 0;
1048 }
1049
1050 static int pgpPrtComment(pgpTag tag, const uint8_t *h, size_t hlen)
1051 {
1052     size_t i = hlen;
1053
1054     pgpPrtVal("", pgpTagTbl, tag);
1055     if (_print)
1056         fprintf(stderr, " ");
1057     while (i > 0) {
1058         size_t j;
1059         if (*h >= ' ' && *h <= 'z') {
1060             if (_print)
1061                 fprintf(stderr, "%s", (const char *)h);
1062             j = strlen((const char*)h);
1063             while (h[j] == '\0')
1064                 j++;
1065         } else {
1066             pgpPrtHex("", h, i);
1067             j = i;
1068         }
1069         i -= j;
1070         h += j;
1071     }
1072     pgpPrtNL();
1073     return 0;
1074 }
1075
1076 int pgpPubkeyFingerprint(const uint8_t * pkt, size_t pktlen, pgpKeyID_t keyid)
1077 {
1078     unsigned int val = *pkt;
1079     size_t plen, hlen;
1080     pgpTag tag;
1081     const uint8_t *se, *h;
1082     DIGEST_CTX ctx;
1083     int rc = -1;        /* assume failure. */
1084
1085     if (!(val & 0x80))
1086         return rc;
1087
1088     if (val & 0x40) {
1089         tag = (val & 0x3f);
1090         plen = pgpLen(pkt+1, &hlen);
1091     } else {
1092         tag = (val >> 2) & 0xf;
1093         plen = (1 << (val & 0x3));
1094         hlen = pgpGrab(pkt+1, plen);
1095     }
1096     if (pktlen > 0 && 1 + plen + hlen > pktlen)
1097         return rc;
1098     
1099     h = pkt + 1 + plen;
1100
1101     switch (h[0]) {
1102     case 3:
1103       { pgpPktKeyV3 v = (pgpPktKeyV3) (h);
1104         se = (uint8_t *)(v + 1);
1105         switch (v->pubkey_algo) {
1106         case PGPPUBKEYALGO_RSA:
1107             se += pgpMpiLen(se);
1108             memmove(keyid, (se-8), 8);
1109             rc = 0;
1110             break;
1111         default:        /* TODO: md5 of mpi bodies (i.e. no length) */
1112             break;
1113         }
1114       } break;
1115     case 4:
1116       { pgpPktKeyV4 v = (pgpPktKeyV4) (h);
1117         uint8_t * d = NULL;
1118         uint8_t in[3];
1119         size_t dlen;
1120         int i;
1121
1122         se = (uint8_t *)(v + 1);
1123         switch (v->pubkey_algo) {
1124         case PGPPUBKEYALGO_RSA:
1125             for (i = 0; i < 2; i++)
1126                 se += pgpMpiLen(se);
1127             break;
1128         case PGPPUBKEYALGO_DSA:
1129             for (i = 0; i < 4; i++)
1130                 se += pgpMpiLen(se);
1131             break;
1132         }
1133
1134         ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
1135         i = se - h;
1136         in[0] = 0x99;
1137         in[1] = i >> 8;
1138         in[2] = i;
1139         (void) rpmDigestUpdate(ctx, in, 3);
1140         (void) rpmDigestUpdate(ctx, h, i);
1141         (void) rpmDigestFinal(ctx, (void **)&d, &dlen, 0);
1142
1143         if (d) {
1144             memmove(keyid, (d + (dlen-8)), 8);
1145             free(d);
1146             rc = 0;
1147         }
1148
1149       } break;
1150     }
1151     return rc;
1152 }
1153
1154 int pgpExtractPubkeyFingerprint(const char * b64pkt, pgpKeyID_t keyid)
1155 {
1156     uint8_t * pkt;
1157     size_t pktlen;
1158
1159     if (b64decode(b64pkt, (void **)&pkt, &pktlen))
1160        return -1;      /* on error */
1161     (void) pgpPubkeyFingerprint(pkt, pktlen, keyid);
1162     pkt = _free(pkt);
1163     return sizeof(keyid);  /* no. of bytes of pubkey signid */
1164 }
1165
1166 static int pgpPrtPkt(const uint8_t *pkt, size_t pleft, 
1167                      pgpDig _dig, pgpDigParams _digp)
1168 {
1169     unsigned int val = *pkt;
1170     size_t pktlen;
1171     pgpTag tag;
1172     size_t plen;
1173     const uint8_t *h;
1174     size_t hlen = 0;
1175     int rc = 0;
1176
1177     /* XXX can't deal with these. */
1178     if (!(val & 0x80))
1179         return -1;
1180
1181     if (val & 0x40) {
1182         tag = (val & 0x3f);
1183         plen = pgpLen(pkt+1, &hlen);
1184     } else {
1185         tag = (val >> 2) & 0xf;
1186         plen = (1 << (val & 0x3));
1187         hlen = pgpGrab(pkt+1, plen);
1188     }
1189
1190     pktlen = 1 + plen + hlen;
1191     if (pktlen > pleft)
1192         return -1;
1193
1194     h = pkt + 1 + plen;
1195     switch (tag) {
1196     case PGPTAG_SIGNATURE:
1197         rc = pgpPrtSig(tag, h, hlen, _dig, _digp);
1198         break;
1199     case PGPTAG_PUBLIC_KEY:
1200         /* Get the public key fingerprint. */
1201         if (_digp) {
1202             if (!pgpPubkeyFingerprint(pkt, pktlen, _digp->signid))
1203                 _digp->saved |= PGPDIG_SAVED_ID;
1204             else
1205                 memset(_digp->signid, 0, sizeof(_digp->signid));
1206         }
1207         rc = pgpPrtKey(tag, h, hlen, _dig, _digp);
1208         break;
1209     case PGPTAG_USER_ID:
1210         rc = pgpPrtUserID(tag, h, hlen, _digp);
1211         break;
1212     case PGPTAG_COMMENT:
1213     case PGPTAG_COMMENT_OLD:
1214         rc = pgpPrtComment(tag, h, hlen);
1215         break;
1216
1217     case PGPTAG_PUBLIC_SUBKEY:
1218     case PGPTAG_SECRET_KEY:
1219     case PGPTAG_SECRET_SUBKEY:
1220     case PGPTAG_RESERVED:
1221     case PGPTAG_PUBLIC_SESSION_KEY:
1222     case PGPTAG_SYMMETRIC_SESSION_KEY:
1223     case PGPTAG_COMPRESSED_DATA:
1224     case PGPTAG_SYMMETRIC_DATA:
1225     case PGPTAG_MARKER:
1226     case PGPTAG_LITERAL_DATA:
1227     case PGPTAG_TRUST:
1228     case PGPTAG_PHOTOID:
1229     case PGPTAG_ENCRYPTED_MDC:
1230     case PGPTAG_MDC:
1231     case PGPTAG_PRIVATE_60:
1232     case PGPTAG_PRIVATE_62:
1233     case PGPTAG_CONTROL:
1234     default:
1235         pgpPrtVal("", pgpTagTbl, tag);
1236         pgpPrtHex("", h, hlen);
1237         pgpPrtNL();
1238         break;
1239     }
1240
1241     return (rc ? -1 : pktlen);
1242 }
1243
1244 pgpDig pgpNewDig(void)
1245 {
1246     pgpDig dig = xcalloc(1, sizeof(*dig));
1247
1248     return dig;
1249 }
1250
1251 void pgpCleanDig(pgpDig dig)
1252 {
1253     if (dig != NULL) {
1254         int i;
1255         dig->signature.userid = _free(dig->signature.userid);
1256         dig->pubkey.userid = _free(dig->pubkey.userid);
1257         dig->signature.hash = _free(dig->signature.hash);
1258         dig->pubkey.hash = _free(dig->pubkey.hash);
1259         /* FIX: double indirection */
1260         for (i = 0; i < 4; i++) {
1261             dig->signature.params[i] = _free(dig->signature.params[i]);
1262             dig->pubkey.params[i] = _free(dig->pubkey.params[i]);
1263         }
1264
1265         memset(&dig->signature, 0, sizeof(dig->signature));
1266         memset(&dig->pubkey, 0, sizeof(dig->pubkey));
1267
1268         if (dig->keydata != NULL) {
1269             SECKEY_DestroyPublicKey(dig->keydata);
1270             dig->keydata = NULL;
1271         }
1272
1273         if (dig->sigdata != NULL) {
1274             SECITEM_ZfreeItem(dig->sigdata, PR_TRUE);
1275             dig->sigdata = NULL;
1276         }
1277     }
1278     return;
1279 }
1280
1281 pgpDig pgpFreeDig(pgpDig dig)
1282 {
1283     if (dig != NULL) {
1284
1285         /* DUmp the signature/pubkey data. */
1286         pgpCleanDig(dig);
1287         dig = _free(dig);
1288     }
1289     return dig;
1290 }
1291
1292 int pgpPrtPkts(const uint8_t * pkts, size_t pktlen, pgpDig dig, int printing)
1293 {
1294     unsigned int val = *pkts;
1295     const uint8_t *p;
1296     size_t pleft;
1297     int len;
1298     pgpDigParams _digp = NULL;
1299
1300     _print = printing;
1301     if (dig != NULL && (val & 0x80)) {
1302         pgpTag tag = (val & 0x40) ? (val & 0x3f) : ((val >> 2) & 0xf);
1303         _digp = (tag == PGPTAG_SIGNATURE) ? &dig->signature : &dig->pubkey;
1304         _digp->tag = tag;
1305     } else
1306         _digp = NULL;
1307
1308     for (p = pkts, pleft = pktlen; p < (pkts + pktlen); p += len, pleft -= len) {
1309         len = pgpPrtPkt(p, pleft, dig, _digp);
1310         if (len <= 0)
1311             return len;
1312         if (len > pleft)        /* XXX shouldn't happen */
1313             break;
1314     }
1315     return 0;
1316 }
1317
1318 static SECOidTag getSigAlg(pgpDigParams sigp)
1319 {
1320     SECOidTag sigalg = SEC_OID_UNKNOWN;
1321     if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA) {
1322         /* assume SHA1 for now, NSS doesn't have SECOID's for other types */
1323         sigalg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
1324     } else if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA) {
1325         switch (sigp->hash_algo) {
1326         case PGPHASHALGO_MD5:
1327             sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
1328             break;
1329         case PGPHASHALGO_MD2:
1330             sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1331             break;
1332         case PGPHASHALGO_SHA1:
1333             sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1334             break;
1335         case PGPHASHALGO_SHA256:
1336             sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
1337             break;
1338         case PGPHASHALGO_SHA384:
1339              sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
1340             break;
1341         case PGPHASHALGO_SHA512:
1342             sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
1343             break;
1344         default:
1345             break;
1346         }
1347     }
1348     return sigalg;
1349 }
1350
1351 char *pgpIdentItem(pgpDigParams digp)
1352 {
1353     char *id = NULL;
1354     if (digp) {
1355         
1356         char *signid = pgpHexStr(digp->signid+4, sizeof(digp->signid)-4);
1357         rasprintf(&id, _("V%d %s/%s %s, key ID %s"),
1358                         digp->version,
1359                         pgpValStr(pgpPubkeyTbl, digp->pubkey_algo),
1360                         pgpValStr(pgpHashTbl, digp->hash_algo),
1361                         pgpValStr(pgpTagTbl, digp->tag),
1362                         signid);
1363         free(signid);
1364     } else {
1365         id = xstrdup(_("(none)"));
1366     }
1367     return id;
1368 }
1369
1370 rpmRC pgpVerifySig(pgpDig dig, DIGEST_CTX hashctx)
1371 {
1372     DIGEST_CTX ctx = rpmDigestDup(hashctx);
1373     uint8_t *hash = NULL;
1374     size_t hashlen = 0;
1375     rpmRC res = RPMRC_FAIL; /* assume failure */
1376     pgpDigParams sigp = dig ? &dig->signature : NULL;
1377
1378     if (sigp == NULL || ctx == NULL)
1379         goto exit;
1380
1381     if (sigp->hash != NULL)
1382         rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
1383
1384     if (sigp->version == 4) {
1385         /* V4 trailer is six octets long (rfc4880) */
1386         uint8_t trailer[6];
1387         uint32_t nb = sigp->hashlen;
1388         nb = htonl(nb);
1389         trailer[0] = sigp->version;
1390         trailer[1] = 0xff;
1391         memcpy(trailer+2, &nb, 4);
1392         rpmDigestUpdate(ctx, trailer, sizeof(trailer));
1393     }
1394
1395     rpmDigestFinal(ctx, (void **)&hash, &hashlen, 0);
1396
1397     /* Compare leading 16 bits of digest for quick check. */
1398     if (hash && memcmp(hash, sigp->signhash16, 2) == 0) {
1399         SECItem digest = { .type = siBuffer, .data = hash, .len = hashlen };
1400         SECItem *sig = dig->sigdata;
1401
1402         /* Zero-pad RSA signature to expected size if necessary */
1403         if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA) {
1404             size_t siglen = SECKEY_SignatureLen(dig->keydata);
1405             if (siglen > sig->len) {
1406                 size_t pad = siglen - sig->len;
1407                 if ((sig = SECITEM_AllocItem(NULL, NULL, siglen)) == NULL) {
1408                     goto exit;
1409                 }
1410                 memset(sig->data, 0, pad);
1411                 memcpy(sig->data+pad, dig->sigdata->data, dig->sigdata->len);
1412             }
1413         }
1414
1415         /* XXX VFY_VerifyDigest() is deprecated in NSS 3.12 */ 
1416         if (VFY_VerifyDigest(&digest, dig->keydata, sig,
1417                              getSigAlg(sigp), NULL) == SECSuccess) {
1418             res = RPMRC_OK;
1419         }
1420
1421         if (sig != dig->sigdata) {
1422             SECITEM_ZfreeItem(sig, 1);
1423         }
1424     }
1425
1426 exit:
1427     free(hash);
1428     return res;
1429
1430 }
1431
1432 static pgpArmor decodePkts(uint8_t *b, uint8_t **pkt, size_t *pktlen)
1433 {
1434     const char * enc = NULL;
1435     const char * crcenc = NULL;
1436     uint8_t * dec;
1437     uint8_t * crcdec;
1438     size_t declen;
1439     size_t crclen;
1440     uint32_t crcpkt, crc;
1441     const char * armortype = NULL;
1442     char * t, * te;
1443     int pstate = 0;
1444     pgpArmor ec = PGPARMOR_ERR_NO_BEGIN_PGP;    /* XXX assume failure */
1445     if (pgpIsPkt(b)) {
1446 #ifdef NOTYET   /* XXX ASCII Pubkeys only, please. */
1447         ec = 0; /* XXX fish out pkt type. */
1448 #endif
1449         goto exit;
1450     }
1451
1452 #define TOKEQ(_s, _tok) (rstreqn((_s), (_tok), sizeof(_tok)-1))
1453
1454     for (t = (char *)b; t && *t; t = te) {
1455         int rc;
1456         if ((te = strchr(t, '\n')) == NULL)
1457             te = t + strlen(t);
1458         else
1459             te++;
1460
1461         switch (pstate) {
1462         case 0:
1463             armortype = NULL;
1464             if (!TOKEQ(t, "-----BEGIN PGP "))
1465                 continue;
1466             t += sizeof("-----BEGIN PGP ")-1;
1467
1468             rc = pgpValTok(pgpArmorTbl, t, te);
1469             if (rc < 0) {
1470                 ec = PGPARMOR_ERR_UNKNOWN_ARMOR_TYPE;
1471                 goto exit;
1472             }
1473             if (rc != PGPARMOR_PUBKEY)  /* XXX ASCII Pubkeys only, please. */
1474                 continue;
1475
1476             armortype = pgpValStr(pgpArmorTbl, rc);
1477             t += strlen(armortype);
1478             if (!TOKEQ(t, "-----"))
1479                 continue;
1480             t += sizeof("-----")-1;
1481             if (*t != '\n' && *t != '\r')
1482                 continue;
1483             *t = '\0';
1484             pstate++;
1485             break;
1486         case 1:
1487             enc = NULL;
1488             rc = pgpValTok(pgpArmorKeyTbl, t, te);
1489             if (rc >= 0)
1490                 continue;
1491             if (*t != '\n' && *t != '\r') {
1492                 pstate = 0;
1493                 continue;
1494             }
1495             enc = te;           /* Start of encoded packets */
1496             pstate++;
1497             break;
1498         case 2:
1499             crcenc = NULL;
1500             if (*t != '=')
1501                 continue;
1502             *t++ = '\0';        /* Terminate encoded packets */
1503             crcenc = t;         /* Start of encoded crc */
1504             pstate++;
1505             break;
1506         case 3:
1507             pstate = 0;
1508             if (!TOKEQ(t, "-----END PGP ")) {
1509                 ec = PGPARMOR_ERR_NO_END_PGP;
1510                 goto exit;
1511             }
1512             *t = '\0';          /* Terminate encoded crc */
1513             t += sizeof("-----END PGP ")-1;
1514             if (t >= te) continue;
1515
1516             if (armortype == NULL) /* XXX can't happen */
1517                 continue;
1518             if (!rstreqn(t, armortype, strlen(armortype)))
1519                 continue;
1520
1521             t += strlen(armortype);
1522             if (t >= te) continue;
1523
1524             if (!TOKEQ(t, "-----")) {
1525                 ec = PGPARMOR_ERR_NO_END_PGP;
1526                 goto exit;
1527             }
1528             t += (sizeof("-----")-1);
1529             if (t >= te) continue;
1530             /* XXX permitting \r here is not RFC-2440 compliant <shrug> */
1531             if (!(*t == '\n' || *t == '\r')) continue;
1532
1533             crcdec = NULL;
1534             crclen = 0;
1535             if (b64decode(crcenc, (void **)&crcdec, &crclen) != 0) {
1536                 ec = PGPARMOR_ERR_CRC_DECODE;
1537                 goto exit;
1538             }
1539             crcpkt = pgpGrab(crcdec, crclen);
1540             crcdec = _free(crcdec);
1541             dec = NULL;
1542             declen = 0;
1543             if (b64decode(enc, (void **)&dec, &declen) != 0) {
1544                 ec = PGPARMOR_ERR_BODY_DECODE;
1545                 goto exit;
1546             }
1547             crc = pgpCRC(dec, declen);
1548             if (crcpkt != crc) {
1549                 ec = PGPARMOR_ERR_CRC_CHECK;
1550                 goto exit;
1551             }
1552             if (pkt) *pkt = dec;
1553             if (pktlen) *pktlen = declen;
1554             ec = PGPARMOR_PUBKEY;       /* XXX ASCII Pubkeys only, please. */
1555             goto exit;
1556             break;
1557         }
1558     }
1559     ec = PGPARMOR_NONE;
1560
1561 exit:
1562     return ec;
1563 }
1564
1565 pgpArmor pgpReadPkts(const char * fn, uint8_t ** pkt, size_t * pktlen)
1566 {
1567     uint8_t * b = NULL;
1568     ssize_t blen;
1569     pgpArmor ec = PGPARMOR_ERR_NO_BEGIN_PGP;    /* XXX assume failure */
1570     int rc = rpmioSlurp(fn, &b, &blen);
1571     if (rc == 0 && b != NULL && blen > 0) {
1572         ec = decodePkts(b, pkt, pktlen);
1573     }
1574     free(b);
1575     return ec;
1576 }
1577
1578 pgpArmor pgpParsePkts(const char *armor, uint8_t ** pkt, size_t * pktlen)
1579 {
1580     pgpArmor ec = PGPARMOR_ERR_NO_BEGIN_PGP;    /* XXX assume failure */
1581     if (armor && strlen(armor) > 0) {
1582         uint8_t *b = (uint8_t*) xstrdup(armor);
1583         ec = decodePkts(b, pkt, pktlen);
1584         free(b);
1585     }
1586     return ec;
1587 }
1588
1589 char * pgpArmorWrap(int atype, const unsigned char * s, size_t ns)
1590 {
1591     char *buf = NULL, *val = NULL;
1592     char *enc = b64encode(s, ns, -1);
1593     char *crc = b64crc(s, ns);
1594     const char *valstr = pgpValStr(pgpArmorTbl, atype);
1595
1596     if (crc != NULL && enc != NULL) {
1597         rasprintf(&buf, "%s=%s", enc, crc);
1598     }
1599     free(crc);
1600     free(enc);
1601
1602     rasprintf(&val, "-----BEGIN PGP %s-----\nVersion: rpm-" VERSION " (NSS-3)\n\n"
1603                     "%s\n-----END PGP %s-----\n",
1604                     valstr, buf != NULL ? buf : "", valstr);
1605
1606     free(buf);
1607     return val;
1608 }
1609
1610 /*
1611  * Only flag for re-initialization here, in the common case the child
1612  * exec()'s something else shutting down NSS here would be waste of time.
1613  */
1614 static void at_forkchild(void)
1615 {
1616     _new_process = 1;
1617 }
1618
1619 int rpmInitCrypto(void) {
1620     int rc = 0;
1621
1622     /* Lazy NSS shutdown for re-initialization after fork() */
1623     if (_new_process && _crypto_initialized) {
1624         rpmFreeCrypto();
1625     }
1626
1627     /* Initialize NSS if not already done */
1628     if (!_crypto_initialized) {
1629         if (NSS_NoDB_Init(NULL) != SECSuccess) {
1630             rc = -1;
1631         } else {
1632             _crypto_initialized = 1;
1633         }
1634     }
1635
1636     /* Register one post-fork handler per process */
1637     if (_new_process) {
1638         if (pthread_atfork(NULL, NULL, at_forkchild) != 0) {
1639             rpmlog(RPMLOG_WARNING, _("Failed to register fork handler: %m\n"));
1640         }
1641         _new_process = 0;
1642     }
1643     return rc;
1644 }
1645
1646 int rpmFreeCrypto(void) 
1647 {
1648     int rc = 0;
1649     if (_crypto_initialized) {
1650         rc = (NSS_Shutdown() != SECSuccess);
1651         _crypto_initialized = 0;
1652     }
1653     return rc;
1654 }
1655         
1656