1 /** \ingroup rpmio signature
3 * Routines to handle RFC-2440 detached signatures.
10 #include <rpm/rpmstring.h>
11 #include <rpm/rpmlog.h>
13 #include "rpmio/digest.h"
14 #include "rpmio/rpmio_internal.h" /* XXX rpmioSlurp */
19 static int _debug = 0;
21 static int _print = 0;
23 static int _crypto_initialized = 0;
24 static int _new_process = 1;
26 typedef const struct pgpValTbl_s {
28 char const * const str;
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" },
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" },
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" },
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" },
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" },
99 static struct pgpValTbl_s const pgpKeyServerPrefsTbl[] = {
100 { 0x80, "No-modify" },
101 { -1, "Unknown key server preference" },
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" },
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" },
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" },
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" }
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" }
189 static void pgpPrtNL(void)
192 fprintf(stderr, "\n");
195 static void pgpPrtInt(const char *pre, int i)
199 fprintf(stderr, "%s", pre);
200 fprintf(stderr, " %d", i);
203 static void pgpPrtStr(const char *pre, const char *s)
207 fprintf(stderr, "%s", pre);
208 fprintf(stderr, " %s", s);
211 static const char * pgpValStr(pgpValTbl vs, uint8_t val)
216 } while ((++vs)->val != -1);
220 static pgpValTbl pgpValTable(pgpValType 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;
239 const char * pgpValString(pgpValType type, uint8_t val)
241 pgpValTbl tbl = pgpValTable(type);
242 return (tbl != NULL) ? pgpValStr(tbl, val) : NULL;
245 static void pgpPrtHex(const char *pre, const uint8_t *p, size_t plen)
250 fprintf(stderr, "%s", pre);
251 hex = pgpHexStr(p, plen);
252 fprintf(stderr, " %s", hex);
256 static void pgpPrtVal(const char * pre, pgpValTbl vs, uint8_t val)
260 fprintf(stderr, "%s", pre);
261 fprintf(stderr, "%s(%u)", pgpValStr(vs, val), (unsigned)val);
265 * Return no. of bits in a multiprecision integer.
266 * @param p pointer to multiprecision integer
267 * @return no. of bits
270 unsigned int pgpMpiBits(const uint8_t *p)
272 return ((p[0] << 8) | p[1]);
276 * Return no. of bytes in a multiprecision integer.
277 * @param p pointer to multiprecision integer
278 * @return no. of bytes
281 size_t pgpMpiLen(const uint8_t *p)
283 return (2 + ((pgpMpiBits(p)+7)>>3));
287 * Return hex formatted representation of a multiprecision integer.
289 * @return hex formatted string (malloc'ed)
292 char * pgpMpiStr(const uint8_t *p)
295 char *hex = pgpHexStr(p+2, pgpMpiLen(p)-2);
296 rasprintf(&str, "[%4u]: %s", pgpGrab(p, (size_t) 2), hex);
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
309 int pgpValTok(pgpValTbl vs, const char * s, const char * se)
312 size_t vlen = strlen(vs->str);
313 if (vlen <= (se-s) && rstreqn(s, vs->str, vlen))
315 } while ((++vs)->val != -1);
319 * @return 0 on success
321 static int pgpMpiSet(const char * pre, unsigned int lbits,
322 uint8_t *dest, const uint8_t * p, const uint8_t * pend)
324 unsigned int mbits = pgpMpiBits(p);
330 if ((p + ((mbits+7) >> 3)) > pend)
336 nbits = (lbits > mbits ? lbits : mbits);
337 nbytes = ((nbits + 7) >> 3);
338 ix = (nbits - mbits) >> 3;
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);
345 fprintf(stderr, "*** %s %s\n", pre, pgpHexStr(dest, nbytes));
351 * @return NULL on error
353 static SECItem *pgpMpiItem(PRArenaPool *arena, SECItem *item, const uint8_t *p)
355 size_t nbytes = pgpMpiLen(p)-2;
358 if ((item=SECITEM_AllocItem(arena, item, nbytes)) == NULL)
362 item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
364 item->data = PORT_Realloc(item->data, nbytes);
366 if (item->data == NULL) {
368 SECITEM_FreeItem(item, PR_TRUE);
373 memcpy(item->data, p+2, nbytes);
379 static SECKEYPublicKey *pgpNewPublicKey(KeyType type)
382 SECKEYPublicKey *key;
384 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
388 key = PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
391 PORT_FreeArena(arena, PR_FALSE);
396 key->pkcs11ID = CK_INVALID_HANDLE;
397 key->pkcs11Slot = NULL;
403 * Is buffer at beginning of an OpenPGP packet?
405 * @return 1 if an OpenPGP packet, 0 otherwise
408 int pgpIsPkt(const uint8_t * p)
410 unsigned int val = *p++;
414 /* XXX can't deal with these. */
419 tag = (pgpTag)(val & 0x3f);
421 tag = (pgpTag)((val >> 2) & 0xf);
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:
432 case PGPTAG_COMMENT_OLD:
433 case PGPTAG_LITERAL_DATA:
434 case PGPTAG_COMPRESSED_DATA:
435 case PGPTAG_SYMMETRIC_DATA:
438 case PGPTAG_PUBLIC_SUBKEY:
439 case PGPTAG_SECRET_SUBKEY:
441 case PGPTAG_RESERVED:
444 case PGPTAG_ENCRYPTED_MDC:
446 case PGPTAG_PRIVATE_60:
447 case PGPTAG_PRIVATE_62:
457 #define CRC24_INIT 0xb704ce
458 #define CRC24_POLY 0x1864cfb
461 * Return CRC of a buffer.
462 * @param octets bytes
463 * @param len no. of bytes
464 * @return crc of buffer
467 unsigned int pgpCRC(const uint8_t *octets, size_t len)
469 unsigned int crc = CRC24_INIT;
473 crc ^= (*octets++) << 16;
474 for (i = 0; i < 8; i++) {
480 return crc & 0xffffff;
483 static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
486 const uint8_t *p = h;
490 i = pgpLen(p, &plen);
494 pgpPrtVal(" ", pgpSubTypeTbl, (p[0]&(~PGPSUBTYPE_CRITICAL)));
495 if (p[0] & PGPSUBTYPE_CRITICAL)
497 fprintf(stderr, " *CRITICAL*");
499 case PGPSUBTYPE_PREFER_SYMKEY: /* preferred symmetric algorithms */
500 for (i = 1; i < plen; i++)
501 pgpPrtVal(" ", pgpSymkeyTbl, p[i]);
503 case PGPSUBTYPE_PREFER_HASH: /* preferred hash algorithms */
504 for (i = 1; i < plen; i++)
505 pgpPrtVal(" ", pgpHashTbl, p[i]);
507 case PGPSUBTYPE_PREFER_COMPRESS:/* preferred compression algorithms */
508 for (i = 1; i < plen; i++)
509 pgpPrtVal(" ", pgpCompressionTbl, p[i]);
511 case PGPSUBTYPE_KEYSERVER_PREFERS:/* key server preferences */
512 for (i = 1; i < plen; i++)
513 pgpPrtVal(" ", pgpKeyServerPrefsTbl, p[i]);
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))
519 _digp->saved |= PGPDIG_SAVED_TIME;
520 memcpy(_digp->time, p+1, sizeof(_digp->time));
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);
527 fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
529 pgpPrtHex("", p+1, plen-1);
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))
536 _digp->saved |= PGPDIG_SAVED_ID;
537 memcpy(_digp->signid, p+1, sizeof(_digp->signid));
539 case PGPSUBTYPE_EXPORTABLE_CERT:
540 case PGPSUBTYPE_TRUST_SIG:
541 case PGPSUBTYPE_REGEX:
542 case PGPSUBTYPE_REVOCABLE:
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:
566 pgpPrtHex("", p+1, plen-1);
576 static const char * const pgpSigRSA[] = {
581 static const char * const pgpSigDSA[] = {
587 #ifndef DSA_SUBPRIME_LEN
588 #define DSA_SUBPRIME_LEN 20
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)
594 const uint8_t * pend = h + hlen;
597 unsigned char dsabuf[2*DSA_SUBPRIME_LEN];
601 dsaraw.data = dsabuf;
602 dsaraw.len = sizeof(dsabuf);
604 for (i = 0; p < pend; i++, p += pgpMpiLen(p)) {
605 if (pubkey_algo == PGPPUBKEYALGO_RSA) {
608 (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT))
612 _dig->sigdata = pgpMpiItem(NULL, _dig->sigdata, p);
613 if (_dig->sigdata == NULL)
620 pgpPrtStr("", pgpSigRSA[i]);
621 } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
624 (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT))
630 memset(dsaraw.data, '\0', 2*DSA_SUBPRIME_LEN);
632 xx = pgpMpiSet(pgpSigDSA[i], DSA_SUBPRIME_LEN*8, dsaraw.data, p, pend);
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) {
642 if (DSAU_EncodeDerSig(_dig->sigdata, &dsaraw) != SECSuccess)
651 pgpPrtStr("", pgpSigDSA[i]);
654 fprintf(stderr, "%7zd", i);
665 static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
666 pgpDig _dig, pgpDigParams _digp)
668 uint8_t version = h[0];
675 { pgpPktSigV3 v = (pgpPktSigV3)h;
681 pgpPrtVal("V3 ", pgpTagTbl, tag);
682 pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
683 pgpPrtVal(" ", pgpHashTbl, v->hash_algo);
684 pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype);
686 t = pgpGrab(v->time, sizeof(v->time));
688 fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
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));
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));
707 p = ((uint8_t *)v) + sizeof(*v);
708 rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _dig);
711 { pgpPktSigV4 v = (pgpPktSigV4)h;
713 pgpPrtVal("V4 ", pgpTagTbl, tag);
714 pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
715 pgpPrtVal(" ", pgpHashTbl, v->hash_algo);
716 pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype);
720 plen = pgpGrab(v->hashlen, sizeof(v->hashlen));
721 p += sizeof(v->hashlen);
723 if ((p + plen) > (h + hlen))
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);
732 (void) pgpPrtSubType(p, plen, v->sigtype, _digp);
738 if ((p + plen) > (h + hlen))
741 if (_debug && _print)
742 fprintf(stderr, " unhash[%zu] -- %s\n", plen, pgpHexStr(p, plen));
743 (void) pgpPrtSubType(p, plen, v->sigtype, _digp);
747 pgpPrtHex(" signhash16", p, 2);
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));
762 rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _dig);
771 static const char * const pgpPublicRSA[] = {
778 static const char * const pgpSecretRSA[] = {
787 static const char * const pgpPublicDSA[] = {
796 static const char * const pgpSecretDSA[] = {
802 static const char * const pgpPublicELGAMAL[] = {
810 static const char * const pgpSecretELGAMAL[] = {
816 char * pgpHexStr(const uint8_t *p, size_t plen)
819 str = t = xmalloc(plen * 2 + 1);
820 static char const hex[] = "0123456789abcdef";
824 *t++ = hex[ (i >> 4) & 0xf ];
825 *t++ = hex[ (i ) & 0xf ];
831 static const uint8_t * pgpPrtPubkeyParams(uint8_t pubkey_algo,
832 const uint8_t *p, const uint8_t *h, size_t hlen,
837 for (i = 0; p < &h[hlen]; i++, p += pgpMpiLen(p)) {
839 if (pubkey_algo == PGPPUBKEYALGO_RSA) {
842 if (_dig->keydata == NULL) {
843 _dig->keydata = pgpNewPublicKey(rsaKey);
844 if (_dig->keydata == NULL)
845 break; /* error abort? */
849 pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.rsa.modulus, p);
852 pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.rsa.publicExponent, p);
858 pgpPrtStr("", pgpPublicRSA[i]);
859 } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
862 if (_dig->keydata == NULL) {
863 _dig->keydata = pgpNewPublicKey(dsaKey);
864 if (_dig->keydata == NULL)
865 break; /* error abort? */
869 pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.prime, p);
872 pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.subPrime, p);
875 pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.base, p);
878 pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.publicValue, p);
884 pgpPrtStr("", pgpPublicDSA[i]);
885 } else if (pubkey_algo == PGPPUBKEYALGO_ELGAMAL_ENCRYPT) {
887 pgpPrtStr("", pgpPublicELGAMAL[i]);
890 fprintf(stderr, "%7zd", i);
901 static const uint8_t * pgpPrtSeckeyParams(uint8_t pubkey_algo,
902 const uint8_t *p, const uint8_t *h, size_t hlen)
908 pgpPrtVal(" ", pgpSymkeyTbl, *p);
912 pgpPrtVal(" ", pgpSymkeyTbl, *p);
915 pgpPrtVal(" simple ", pgpHashTbl, p[2]);
919 pgpPrtVal(" salted ", pgpHashTbl, p[2]);
920 pgpPrtHex("", p+3, 8);
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);
934 pgpPrtVal(" ", pgpSymkeyTbl, *p);
935 pgpPrtHex(" IV", p+1, 8);
943 #ifdef NOTYET /* XXX encrypted MPI's need to be handled. */
944 for (i = 0; p < &h[hlen]; i++, p += pgpMpiLen(p)) {
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]);
957 fprintf(stderr, "%7d", i);
965 pgpPrtHex(" secret", p, (hlen - (p - h) - 2));
967 p += (hlen - (p - h) - 2);
969 pgpPrtHex(" checksum", p, 2);
975 static int pgpPrtKey(pgpTag tag, const uint8_t *h, size_t hlen,
976 pgpDig _dig, pgpDigParams _digp)
978 uint8_t version = *h;
986 { pgpPktKeyV3 v = (pgpPktKeyV3)h;
987 pgpPrtVal("V3 ", pgpTagTbl, tag);
988 pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
989 t = pgpGrab(v->time, sizeof(v->time));
991 fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
992 plen = pgpGrab(v->valid, sizeof(v->valid));
994 fprintf(stderr, " valid %zu days", plen);
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;
1003 p = ((uint8_t *)v) + sizeof(*v);
1004 p = pgpPrtPubkeyParams(v->pubkey_algo, p, h, hlen, _dig);
1008 { pgpPktKeyV4 v = (pgpPktKeyV4)h;
1009 pgpPrtVal("V4 ", pgpTagTbl, tag);
1010 pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
1011 t = pgpGrab(v->time, sizeof(v->time));
1013 fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
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;
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);
1035 static int pgpPrtUserID(pgpTag tag, const uint8_t *h, size_t hlen,
1038 pgpPrtVal("", pgpTagTbl, tag);
1040 fprintf(stderr, " \"%.*s\"", (int)hlen, (const char *)h);
1044 _digp->userid = t = memcpy(xmalloc(hlen+1), h, hlen);
1050 static int pgpPrtComment(pgpTag tag, const uint8_t *h, size_t hlen)
1054 pgpPrtVal("", pgpTagTbl, tag);
1056 fprintf(stderr, " ");
1059 if (*h >= ' ' && *h <= 'z') {
1061 fprintf(stderr, "%s", (const char *)h);
1062 j = strlen((const char*)h);
1063 while (h[j] == '\0')
1066 pgpPrtHex("", h, i);
1076 int pgpPubkeyFingerprint(const uint8_t * pkt, size_t pktlen, pgpKeyID_t keyid)
1078 unsigned int val = *pkt;
1081 const uint8_t *se, *h;
1083 int rc = -1; /* assume failure. */
1090 plen = pgpLen(pkt+1, &hlen);
1092 tag = (val >> 2) & 0xf;
1093 plen = (1 << (val & 0x3));
1094 hlen = pgpGrab(pkt+1, plen);
1096 if (pktlen > 0 && 1 + plen + hlen > pktlen)
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);
1111 default: /* TODO: md5 of mpi bodies (i.e. no length) */
1116 { pgpPktKeyV4 v = (pgpPktKeyV4) (h);
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);
1128 case PGPPUBKEYALGO_DSA:
1129 for (i = 0; i < 4; i++)
1130 se += pgpMpiLen(se);
1134 ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
1139 (void) rpmDigestUpdate(ctx, in, 3);
1140 (void) rpmDigestUpdate(ctx, h, i);
1141 (void) rpmDigestFinal(ctx, (void **)&d, &dlen, 0);
1144 memmove(keyid, (d + (dlen-8)), 8);
1154 int pgpExtractPubkeyFingerprint(const char * b64pkt, pgpKeyID_t keyid)
1159 if (b64decode(b64pkt, (void **)&pkt, &pktlen))
1160 return -1; /* on error */
1161 (void) pgpPubkeyFingerprint(pkt, pktlen, keyid);
1163 return sizeof(keyid); /* no. of bytes of pubkey signid */
1166 static int pgpPrtPkt(const uint8_t *pkt, size_t pleft,
1167 pgpDig _dig, pgpDigParams _digp)
1169 unsigned int val = *pkt;
1177 /* XXX can't deal with these. */
1183 plen = pgpLen(pkt+1, &hlen);
1185 tag = (val >> 2) & 0xf;
1186 plen = (1 << (val & 0x3));
1187 hlen = pgpGrab(pkt+1, plen);
1190 pktlen = 1 + plen + hlen;
1196 case PGPTAG_SIGNATURE:
1197 rc = pgpPrtSig(tag, h, hlen, _dig, _digp);
1199 case PGPTAG_PUBLIC_KEY:
1200 /* Get the public key fingerprint. */
1202 if (!pgpPubkeyFingerprint(pkt, pktlen, _digp->signid))
1203 _digp->saved |= PGPDIG_SAVED_ID;
1205 memset(_digp->signid, 0, sizeof(_digp->signid));
1207 rc = pgpPrtKey(tag, h, hlen, _dig, _digp);
1209 case PGPTAG_USER_ID:
1210 rc = pgpPrtUserID(tag, h, hlen, _digp);
1212 case PGPTAG_COMMENT:
1213 case PGPTAG_COMMENT_OLD:
1214 rc = pgpPrtComment(tag, h, hlen);
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:
1226 case PGPTAG_LITERAL_DATA:
1228 case PGPTAG_PHOTOID:
1229 case PGPTAG_ENCRYPTED_MDC:
1231 case PGPTAG_PRIVATE_60:
1232 case PGPTAG_PRIVATE_62:
1233 case PGPTAG_CONTROL:
1235 pgpPrtVal("", pgpTagTbl, tag);
1236 pgpPrtHex("", h, hlen);
1241 return (rc ? -1 : pktlen);
1244 pgpDig pgpNewDig(void)
1246 pgpDig dig = xcalloc(1, sizeof(*dig));
1251 void pgpCleanDig(pgpDig dig)
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]);
1265 memset(&dig->signature, 0, sizeof(dig->signature));
1266 memset(&dig->pubkey, 0, sizeof(dig->pubkey));
1268 if (dig->keydata != NULL) {
1269 SECKEY_DestroyPublicKey(dig->keydata);
1270 dig->keydata = NULL;
1273 if (dig->sigdata != NULL) {
1274 SECITEM_ZfreeItem(dig->sigdata, PR_TRUE);
1275 dig->sigdata = NULL;
1281 pgpDig pgpFreeDig(pgpDig dig)
1285 /* DUmp the signature/pubkey data. */
1292 int pgpPrtPkts(const uint8_t * pkts, size_t pktlen, pgpDig dig, int printing)
1294 unsigned int val = *pkts;
1298 pgpDigParams _digp = NULL;
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;
1308 for (p = pkts, pleft = pktlen; p < (pkts + pktlen); p += len, pleft -= len) {
1309 len = pgpPrtPkt(p, pleft, dig, _digp);
1312 if (len > pleft) /* XXX shouldn't happen */
1318 static SECOidTag getSigAlg(pgpDigParams sigp)
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;
1329 case PGPHASHALGO_MD2:
1330 sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1332 case PGPHASHALGO_SHA1:
1333 sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1335 case PGPHASHALGO_SHA256:
1336 sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
1338 case PGPHASHALGO_SHA384:
1339 sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
1341 case PGPHASHALGO_SHA512:
1342 sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
1351 char *pgpIdentItem(pgpDigParams digp)
1356 char *signid = pgpHexStr(digp->signid+4, sizeof(digp->signid)-4);
1357 rasprintf(&id, _("V%d %s/%s %s, key ID %s"),
1359 pgpValStr(pgpPubkeyTbl, digp->pubkey_algo),
1360 pgpValStr(pgpHashTbl, digp->hash_algo),
1361 pgpValStr(pgpTagTbl, digp->tag),
1365 id = xstrdup(_("(none)"));
1370 rpmRC pgpVerifySig(pgpDig dig, DIGEST_CTX hashctx)
1372 DIGEST_CTX ctx = rpmDigestDup(hashctx);
1373 uint8_t *hash = NULL;
1375 rpmRC res = RPMRC_FAIL; /* assume failure */
1376 pgpDigParams sigp = dig ? &dig->signature : NULL;
1378 if (sigp == NULL || ctx == NULL)
1381 if (sigp->hash != NULL)
1382 rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
1384 if (sigp->version == 4) {
1385 /* V4 trailer is six octets long (rfc4880) */
1387 uint32_t nb = sigp->hashlen;
1389 trailer[0] = sigp->version;
1391 memcpy(trailer+2, &nb, 4);
1392 rpmDigestUpdate(ctx, trailer, sizeof(trailer));
1395 rpmDigestFinal(ctx, (void **)&hash, &hashlen, 0);
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;
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) {
1410 memset(sig->data, 0, pad);
1411 memcpy(sig->data+pad, dig->sigdata->data, dig->sigdata->len);
1415 /* XXX VFY_VerifyDigest() is deprecated in NSS 3.12 */
1416 if (VFY_VerifyDigest(&digest, dig->keydata, sig,
1417 getSigAlg(sigp), NULL) == SECSuccess) {
1421 if (sig != dig->sigdata) {
1422 SECITEM_ZfreeItem(sig, 1);
1432 static pgpArmor decodePkts(uint8_t *b, uint8_t **pkt, size_t *pktlen)
1434 const char * enc = NULL;
1435 const char * crcenc = NULL;
1440 uint32_t crcpkt, crc;
1441 const char * armortype = NULL;
1444 pgpArmor ec = PGPARMOR_ERR_NO_BEGIN_PGP; /* XXX assume failure */
1446 #ifdef NOTYET /* XXX ASCII Pubkeys only, please. */
1447 ec = 0; /* XXX fish out pkt type. */
1452 #define TOKEQ(_s, _tok) (rstreqn((_s), (_tok), sizeof(_tok)-1))
1454 for (t = (char *)b; t && *t; t = te) {
1456 if ((te = strchr(t, '\n')) == NULL)
1464 if (!TOKEQ(t, "-----BEGIN PGP "))
1466 t += sizeof("-----BEGIN PGP ")-1;
1468 rc = pgpValTok(pgpArmorTbl, t, te);
1470 ec = PGPARMOR_ERR_UNKNOWN_ARMOR_TYPE;
1473 if (rc != PGPARMOR_PUBKEY) /* XXX ASCII Pubkeys only, please. */
1476 armortype = pgpValStr(pgpArmorTbl, rc);
1477 t += strlen(armortype);
1478 if (!TOKEQ(t, "-----"))
1480 t += sizeof("-----")-1;
1481 if (*t != '\n' && *t != '\r')
1488 rc = pgpValTok(pgpArmorKeyTbl, t, te);
1491 if (*t != '\n' && *t != '\r') {
1495 enc = te; /* Start of encoded packets */
1502 *t++ = '\0'; /* Terminate encoded packets */
1503 crcenc = t; /* Start of encoded crc */
1508 if (!TOKEQ(t, "-----END PGP ")) {
1509 ec = PGPARMOR_ERR_NO_END_PGP;
1512 *t = '\0'; /* Terminate encoded crc */
1513 t += sizeof("-----END PGP ")-1;
1514 if (t >= te) continue;
1516 if (armortype == NULL) /* XXX can't happen */
1518 if (!rstreqn(t, armortype, strlen(armortype)))
1521 t += strlen(armortype);
1522 if (t >= te) continue;
1524 if (!TOKEQ(t, "-----")) {
1525 ec = PGPARMOR_ERR_NO_END_PGP;
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;
1535 if (b64decode(crcenc, (void **)&crcdec, &crclen) != 0) {
1536 ec = PGPARMOR_ERR_CRC_DECODE;
1539 crcpkt = pgpGrab(crcdec, crclen);
1540 crcdec = _free(crcdec);
1543 if (b64decode(enc, (void **)&dec, &declen) != 0) {
1544 ec = PGPARMOR_ERR_BODY_DECODE;
1547 crc = pgpCRC(dec, declen);
1548 if (crcpkt != crc) {
1549 ec = PGPARMOR_ERR_CRC_CHECK;
1552 if (pkt) *pkt = dec;
1553 if (pktlen) *pktlen = declen;
1554 ec = PGPARMOR_PUBKEY; /* XXX ASCII Pubkeys only, please. */
1565 pgpArmor pgpReadPkts(const char * fn, uint8_t ** pkt, size_t * pktlen)
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);
1578 pgpArmor pgpParsePkts(const char *armor, uint8_t ** pkt, size_t * pktlen)
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);
1589 char * pgpArmorWrap(int atype, const unsigned char * s, size_t ns)
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);
1596 if (crc != NULL && enc != NULL) {
1597 rasprintf(&buf, "%s=%s", enc, crc);
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);
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.
1614 static void at_forkchild(void)
1619 int rpmInitCrypto(void) {
1622 /* Lazy NSS shutdown for re-initialization after fork() */
1623 if (_new_process && _crypto_initialized) {
1627 /* Initialize NSS if not already done */
1628 if (!_crypto_initialized) {
1629 if (NSS_NoDB_Init(NULL) != SECSuccess) {
1632 _crypto_initialized = 1;
1636 /* Register one post-fork handler per process */
1638 if (pthread_atfork(NULL, NULL, at_forkchild) != 0) {
1639 rpmlog(RPMLOG_WARNING, _("Failed to register fork handler: %m\n"));
1646 int rpmFreeCrypto(void)
1649 if (_crypto_initialized) {
1650 rc = (NSS_Shutdown() != SECSuccess);
1651 _crypto_initialized = 0;