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