1 /** \ingroup rpmio signature
3 * Routines to handle RFC-2440 detached signatures.
9 #include <netinet/in.h>
10 #include <rpm/rpmstring.h>
11 #include <rpm/rpmlog.h>
12 #include <rpm/rpmbase64.h>
14 #include "rpmio/digest.h"
15 #include "rpmio/rpmio_internal.h" /* XXX rpmioSlurp */
19 static int _print = 0;
22 * Container for values parsed from an OpenPGP signature and public key.
25 struct pgpDigParams_s * signature;
26 struct pgpDigParams_s * pubkey;
29 typedef const struct pgpValTbl_s {
31 char const * const str;
34 static struct pgpValTbl_s const pgpSigTypeTbl[] = {
35 { PGPSIGTYPE_BINARY, "Binary document signature" },
36 { PGPSIGTYPE_TEXT, "Text document signature" },
37 { PGPSIGTYPE_STANDALONE, "Standalone signature" },
38 { PGPSIGTYPE_GENERIC_CERT, "Generic certification of a User ID and Public Key" },
39 { PGPSIGTYPE_PERSONA_CERT, "Persona certification of a User ID and Public Key" },
40 { PGPSIGTYPE_CASUAL_CERT, "Casual certification of a User ID and Public Key" },
41 { PGPSIGTYPE_POSITIVE_CERT, "Positive certification of a User ID and Public Key" },
42 { PGPSIGTYPE_SUBKEY_BINDING,"Subkey Binding Signature" },
43 { PGPSIGTYPE_SIGNED_KEY, "Signature directly on a key" },
44 { PGPSIGTYPE_KEY_REVOKE, "Key revocation signature" },
45 { PGPSIGTYPE_SUBKEY_REVOKE, "Subkey revocation signature" },
46 { PGPSIGTYPE_CERT_REVOKE, "Certification revocation signature" },
47 { PGPSIGTYPE_TIMESTAMP, "Timestamp signature" },
48 { -1, "Unknown signature type" },
51 static struct pgpValTbl_s const pgpPubkeyTbl[] = {
52 { PGPPUBKEYALGO_RSA, "RSA" },
53 { PGPPUBKEYALGO_RSA_ENCRYPT,"RSA(Encrypt-Only)" },
54 { PGPPUBKEYALGO_RSA_SIGN, "RSA(Sign-Only)" },
55 { PGPPUBKEYALGO_ELGAMAL_ENCRYPT,"Elgamal(Encrypt-Only)" },
56 { PGPPUBKEYALGO_DSA, "DSA" },
57 { PGPPUBKEYALGO_EC, "Elliptic Curve" },
58 { PGPPUBKEYALGO_ECDSA, "ECDSA" },
59 { PGPPUBKEYALGO_ELGAMAL, "Elgamal" },
60 { PGPPUBKEYALGO_DH, "Diffie-Hellman (X9.42)" },
61 { -1, "Unknown public key algorithm" },
64 static struct pgpValTbl_s const pgpSymkeyTbl[] = {
65 { PGPSYMKEYALGO_PLAINTEXT, "Plaintext" },
66 { PGPSYMKEYALGO_IDEA, "IDEA" },
67 { PGPSYMKEYALGO_TRIPLE_DES, "3DES" },
68 { PGPSYMKEYALGO_CAST5, "CAST5" },
69 { PGPSYMKEYALGO_BLOWFISH, "BLOWFISH" },
70 { PGPSYMKEYALGO_SAFER, "SAFER" },
71 { PGPSYMKEYALGO_DES_SK, "DES/SK" },
72 { PGPSYMKEYALGO_AES_128, "AES(128-bit key)" },
73 { PGPSYMKEYALGO_AES_192, "AES(192-bit key)" },
74 { PGPSYMKEYALGO_AES_256, "AES(256-bit key)" },
75 { PGPSYMKEYALGO_TWOFISH, "TWOFISH(256-bit key)" },
76 { PGPSYMKEYALGO_NOENCRYPT, "no encryption" },
77 { -1, "Unknown symmetric key algorithm" },
80 static struct pgpValTbl_s const pgpCompressionTbl[] = {
81 { PGPCOMPRESSALGO_NONE, "Uncompressed" },
82 { PGPCOMPRESSALGO_ZIP, "ZIP" },
83 { PGPCOMPRESSALGO_ZLIB, "ZLIB" },
84 { PGPCOMPRESSALGO_BZIP2, "BZIP2" },
85 { -1, "Unknown compression algorithm" },
88 static struct pgpValTbl_s const pgpHashTbl[] = {
89 { PGPHASHALGO_MD5, "MD5" },
90 { PGPHASHALGO_SHA1, "SHA1" },
91 { PGPHASHALGO_RIPEMD160, "RIPEMD160" },
92 { PGPHASHALGO_MD2, "MD2" },
93 { PGPHASHALGO_TIGER192, "TIGER192" },
94 { PGPHASHALGO_HAVAL_5_160, "HAVAL-5-160" },
95 { PGPHASHALGO_SHA256, "SHA256" },
96 { PGPHASHALGO_SHA384, "SHA384" },
97 { PGPHASHALGO_SHA512, "SHA512" },
98 { PGPHASHALGO_SHA224, "SHA224" },
99 { -1, "Unknown hash algorithm" },
102 static struct pgpValTbl_s const pgpKeyServerPrefsTbl[] = {
103 { 0x80, "No-modify" },
104 { -1, "Unknown key server preference" },
107 static struct pgpValTbl_s const pgpSubTypeTbl[] = {
108 { PGPSUBTYPE_SIG_CREATE_TIME,"signature creation time" },
109 { PGPSUBTYPE_SIG_EXPIRE_TIME,"signature expiration time" },
110 { PGPSUBTYPE_EXPORTABLE_CERT,"exportable certification" },
111 { PGPSUBTYPE_TRUST_SIG, "trust signature" },
112 { PGPSUBTYPE_REGEX, "regular expression" },
113 { PGPSUBTYPE_REVOCABLE, "revocable" },
114 { PGPSUBTYPE_KEY_EXPIRE_TIME,"key expiration time" },
115 { PGPSUBTYPE_ARR, "additional recipient request" },
116 { PGPSUBTYPE_PREFER_SYMKEY, "preferred symmetric algorithms" },
117 { PGPSUBTYPE_REVOKE_KEY, "revocation key" },
118 { PGPSUBTYPE_ISSUER_KEYID, "issuer key ID" },
119 { PGPSUBTYPE_NOTATION, "notation data" },
120 { PGPSUBTYPE_PREFER_HASH, "preferred hash algorithms" },
121 { PGPSUBTYPE_PREFER_COMPRESS,"preferred compression algorithms" },
122 { PGPSUBTYPE_KEYSERVER_PREFERS,"key server preferences" },
123 { PGPSUBTYPE_PREFER_KEYSERVER,"preferred key server" },
124 { PGPSUBTYPE_PRIMARY_USERID,"primary user id" },
125 { PGPSUBTYPE_POLICY_URL, "policy URL" },
126 { PGPSUBTYPE_KEY_FLAGS, "key flags" },
127 { PGPSUBTYPE_SIGNER_USERID, "signer's user id" },
128 { PGPSUBTYPE_REVOKE_REASON, "reason for revocation" },
129 { PGPSUBTYPE_FEATURES, "features" },
130 { PGPSUBTYPE_EMBEDDED_SIG, "embedded signature" },
132 { PGPSUBTYPE_INTERNAL_100, "internal subpkt type 100" },
133 { PGPSUBTYPE_INTERNAL_101, "internal subpkt type 101" },
134 { PGPSUBTYPE_INTERNAL_102, "internal subpkt type 102" },
135 { PGPSUBTYPE_INTERNAL_103, "internal subpkt type 103" },
136 { PGPSUBTYPE_INTERNAL_104, "internal subpkt type 104" },
137 { PGPSUBTYPE_INTERNAL_105, "internal subpkt type 105" },
138 { PGPSUBTYPE_INTERNAL_106, "internal subpkt type 106" },
139 { PGPSUBTYPE_INTERNAL_107, "internal subpkt type 107" },
140 { PGPSUBTYPE_INTERNAL_108, "internal subpkt type 108" },
141 { PGPSUBTYPE_INTERNAL_109, "internal subpkt type 109" },
142 { PGPSUBTYPE_INTERNAL_110, "internal subpkt type 110" },
143 { -1, "Unknown signature subkey type" },
146 static struct pgpValTbl_s const pgpTagTbl[] = {
147 { PGPTAG_PUBLIC_SESSION_KEY,"Public-Key Encrypted Session Key" },
148 { PGPTAG_SIGNATURE, "Signature" },
149 { PGPTAG_SYMMETRIC_SESSION_KEY,"Symmetric-Key Encrypted Session Key" },
150 { PGPTAG_ONEPASS_SIGNATURE, "One-Pass Signature" },
151 { PGPTAG_SECRET_KEY, "Secret Key" },
152 { PGPTAG_PUBLIC_KEY, "Public Key" },
153 { PGPTAG_SECRET_SUBKEY, "Secret Subkey" },
154 { PGPTAG_COMPRESSED_DATA, "Compressed Data" },
155 { PGPTAG_SYMMETRIC_DATA, "Symmetrically Encrypted Data" },
156 { PGPTAG_MARKER, "Marker" },
157 { PGPTAG_LITERAL_DATA, "Literal Data" },
158 { PGPTAG_TRUST, "Trust" },
159 { PGPTAG_USER_ID, "User ID" },
160 { PGPTAG_PUBLIC_SUBKEY, "Public Subkey" },
161 { PGPTAG_COMMENT_OLD, "Comment (from OpenPGP draft)" },
162 { PGPTAG_PHOTOID, "PGP's photo ID" },
163 { PGPTAG_ENCRYPTED_MDC, "Integrity protected encrypted data" },
164 { PGPTAG_MDC, "Manipulaion detection code packet" },
165 { PGPTAG_PRIVATE_60, "Private #60" },
166 { PGPTAG_COMMENT, "Comment" },
167 { PGPTAG_PRIVATE_62, "Private #62" },
168 { PGPTAG_CONTROL, "Control (GPG)" },
169 { -1, "Unknown packet tag" },
172 static struct pgpValTbl_s const pgpArmorTbl[] = {
173 { PGPARMOR_MESSAGE, "MESSAGE" },
174 { PGPARMOR_PUBKEY, "PUBLIC KEY BLOCK" },
175 { PGPARMOR_SIGNATURE, "SIGNATURE" },
176 { PGPARMOR_SIGNED_MESSAGE, "SIGNED MESSAGE" },
177 { PGPARMOR_FILE, "ARMORED FILE" },
178 { PGPARMOR_PRIVKEY, "PRIVATE KEY BLOCK" },
179 { PGPARMOR_SECKEY, "SECRET KEY BLOCK" },
180 { -1, "Unknown armor block" }
183 static struct pgpValTbl_s const pgpArmorKeyTbl[] = {
184 { PGPARMORKEY_VERSION, "Version: " },
185 { PGPARMORKEY_COMMENT, "Comment: " },
186 { PGPARMORKEY_MESSAGEID, "MessageID: " },
187 { PGPARMORKEY_HASH, "Hash: " },
188 { PGPARMORKEY_CHARSET, "Charset: " },
189 { -1, "Unknown armor key" }
192 static void pgpPrtNL(void)
195 fprintf(stderr, "\n");
198 static const char * pgpValStr(pgpValTbl vs, uint8_t val)
203 } while ((++vs)->val != -1);
207 static pgpValTbl pgpValTable(pgpValType type)
210 case PGPVAL_TAG: return pgpTagTbl;
211 case PGPVAL_ARMORBLOCK: return pgpArmorTbl;
212 case PGPVAL_ARMORKEY: return pgpArmorKeyTbl;
213 case PGPVAL_SIGTYPE: return pgpSigTypeTbl;
214 case PGPVAL_SUBTYPE: return pgpSubTypeTbl;
215 case PGPVAL_PUBKEYALGO: return pgpPubkeyTbl;
216 case PGPVAL_SYMKEYALGO: return pgpSymkeyTbl;
217 case PGPVAL_COMPRESSALGO: return pgpCompressionTbl;
218 case PGPVAL_HASHALGO: return pgpHashTbl;
219 case PGPVAL_SERVERPREFS: return pgpKeyServerPrefsTbl;
226 const char * pgpValString(pgpValType type, uint8_t val)
228 pgpValTbl tbl = pgpValTable(type);
229 return (tbl != NULL) ? pgpValStr(tbl, val) : NULL;
232 static void pgpPrtHex(const char *pre, const uint8_t *p, size_t plen)
237 fprintf(stderr, "%s", pre);
238 hex = pgpHexStr(p, plen);
239 fprintf(stderr, " %s", hex);
243 static void pgpPrtVal(const char * pre, pgpValTbl vs, uint8_t val)
247 fprintf(stderr, "%s", pre);
248 fprintf(stderr, "%s(%u)", pgpValStr(vs, val), (unsigned)val);
252 * Return hex formatted representation of a multiprecision integer.
254 * @return hex formatted string (malloc'ed)
257 char * pgpMpiStr(const uint8_t *p)
260 char *hex = pgpHexStr(p+2, pgpMpiLen(p)-2);
261 rasprintf(&str, "[%4u]: %s", pgpGrab(p, (size_t) 2), hex);
267 * Return value of an OpenPGP string.
268 * @param vs table of (string,value) pairs
269 * @param s string token to lookup
270 * @param se end-of-string address
274 int pgpValTok(pgpValTbl vs, const char * s, const char * se)
277 size_t vlen = strlen(vs->str);
278 if (vlen <= (se-s) && rstreqn(s, vs->str, vlen))
280 } while ((++vs)->val != -1);
285 * Decode length from 1, 2, or 5 octet body length encoding, used in
286 * new format packet headers and V4 signature subpackets.
287 * @param s pointer to length encoding buffer
288 * @param slen buffer size
289 * @retval *lenp decoded length
290 * @return no. of bytes used to encode the length, 0 on error
293 size_t pgpLen(const uint8_t *s, size_t slen, size_t * lenp)
299 * Callers can only ensure we'll always have the first byte, beyond
300 * that the required size is not known until we decode it so we need
301 * to check if we have enough bytes to read the size as we go.
306 } else if (*s < 255 && slen > 2) {
308 dlen = (((s[0]) - 192) << 8) + s[1] + 192;
309 } else if (slen > 5) {
311 dlen = pgpGrab(s+1, 4);
321 uint8_t tag; /* decoded PGP tag */
322 const uint8_t *head; /* pointer to start of packet (header) */
323 const uint8_t *body; /* pointer to packet body */
324 size_t blen; /* length of body in bytes */
327 static int decodePkt(const uint8_t *p, size_t plen, struct pgpPkt *pkt)
329 int rc = -1; /* assume failure */
331 /* Valid PGP packet header must always have two or more bytes in it */
332 if (p && plen >= 2 && p[0] & 0x80) {
337 /* New format packet, body length encoding in second byte */
338 lenlen = pgpLen(p+1, plen-1, &pkt->blen);
339 pkt->tag = (p[0] & 0x3f);
341 /* Old format packet, body length encoding in tag byte */
342 lenlen = (1 << (p[0] & 0x3));
344 pkt->blen = pgpGrab(p+1, lenlen);
346 pkt->tag = (p[0] >> 2) & 0xf;
350 /* Does the packet header and its body fit in our boundaries? */
351 if (lenlen && (hlen + pkt->blen <= plen)) {
353 pkt->body = pkt->head + hlen;
361 #define CRC24_INIT 0xb704ce
362 #define CRC24_POLY 0x1864cfb
365 * Return CRC of a buffer.
366 * @param octets bytes
367 * @param len no. of bytes
368 * @return crc of buffer
371 unsigned int pgpCRC(const uint8_t *octets, size_t len)
373 unsigned int crc = CRC24_INIT;
377 crc ^= (*octets++) << 16;
378 for (i = 0; i < 8; i++) {
384 return crc & 0xffffff;
387 static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
390 const uint8_t *p = h;
394 i = pgpLen(p, hlen, &plen);
395 if (i == 0 || i + plen > hlen)
401 pgpPrtVal(" ", pgpSubTypeTbl, (p[0]&(~PGPSUBTYPE_CRITICAL)));
402 if (p[0] & PGPSUBTYPE_CRITICAL)
404 fprintf(stderr, " *CRITICAL*");
406 case PGPSUBTYPE_PREFER_SYMKEY: /* preferred symmetric algorithms */
407 for (i = 1; i < plen; i++)
408 pgpPrtVal(" ", pgpSymkeyTbl, p[i]);
410 case PGPSUBTYPE_PREFER_HASH: /* preferred hash algorithms */
411 for (i = 1; i < plen; i++)
412 pgpPrtVal(" ", pgpHashTbl, p[i]);
414 case PGPSUBTYPE_PREFER_COMPRESS:/* preferred compression algorithms */
415 for (i = 1; i < plen; i++)
416 pgpPrtVal(" ", pgpCompressionTbl, p[i]);
418 case PGPSUBTYPE_KEYSERVER_PREFERS:/* key server preferences */
419 for (i = 1; i < plen; i++)
420 pgpPrtVal(" ", pgpKeyServerPrefsTbl, p[i]);
422 case PGPSUBTYPE_SIG_CREATE_TIME:
423 if (!(_digp->saved & PGPDIG_SAVED_TIME) &&
424 (sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
426 _digp->saved |= PGPDIG_SAVED_TIME;
427 memcpy(_digp->time, p+1, sizeof(_digp->time));
429 case PGPSUBTYPE_SIG_EXPIRE_TIME:
430 case PGPSUBTYPE_KEY_EXPIRE_TIME:
431 if ((plen - 1) == 4) {
432 time_t t = pgpGrab(p+1, plen-1);
434 fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
436 pgpPrtHex("", p+1, plen-1);
439 case PGPSUBTYPE_ISSUER_KEYID: /* issuer key ID */
440 if (!(_digp->saved & PGPDIG_SAVED_ID) &&
441 (sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
443 _digp->saved |= PGPDIG_SAVED_ID;
444 memcpy(_digp->signid, p+1, sizeof(_digp->signid));
446 case PGPSUBTYPE_EXPORTABLE_CERT:
447 case PGPSUBTYPE_TRUST_SIG:
448 case PGPSUBTYPE_REGEX:
449 case PGPSUBTYPE_REVOCABLE:
451 case PGPSUBTYPE_REVOKE_KEY:
452 case PGPSUBTYPE_NOTATION:
453 case PGPSUBTYPE_PREFER_KEYSERVER:
454 case PGPSUBTYPE_PRIMARY_USERID:
455 case PGPSUBTYPE_POLICY_URL:
456 case PGPSUBTYPE_KEY_FLAGS:
457 case PGPSUBTYPE_SIGNER_USERID:
458 case PGPSUBTYPE_REVOKE_REASON:
459 case PGPSUBTYPE_FEATURES:
460 case PGPSUBTYPE_EMBEDDED_SIG:
461 case PGPSUBTYPE_INTERNAL_100:
462 case PGPSUBTYPE_INTERNAL_101:
463 case PGPSUBTYPE_INTERNAL_102:
464 case PGPSUBTYPE_INTERNAL_103:
465 case PGPSUBTYPE_INTERNAL_104:
466 case PGPSUBTYPE_INTERNAL_105:
467 case PGPSUBTYPE_INTERNAL_106:
468 case PGPSUBTYPE_INTERNAL_107:
469 case PGPSUBTYPE_INTERNAL_108:
470 case PGPSUBTYPE_INTERNAL_109:
471 case PGPSUBTYPE_INTERNAL_110:
473 pgpPrtHex("", p+1, plen-1);
480 return (hlen != 0); /* non-zero hlen is an error */
483 pgpDigAlg pgpDigAlgFree(pgpDigAlg alg)
493 static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
494 const uint8_t *p, const uint8_t *h, size_t hlen,
497 int rc = 1; /* assume failure */
498 const uint8_t * pend = h + hlen;
500 pgpDigAlg sigalg = pgpSignatureNew(pubkey_algo);
502 for (i = 0; p < pend && i < sigalg->mpis; i++, p += pgpMpiLen(p)) {
503 if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) {
504 if (sigalg->setmpi(sigalg, i, p, pend))
509 /* Does the size and number of MPI's match our expectations? */
510 if (p == pend && i == sigalg->mpis)
513 /* We can't handle more than one sig at a time */
514 if (rc == 0 && sigp->alg == NULL && sigp->tag == PGPTAG_SIGNATURE)
517 pgpDigAlgFree(sigalg);
522 static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
525 uint8_t version = h[0];
532 { pgpPktSigV3 v = (pgpPktSigV3)h;
535 if (hlen <= sizeof(*v) || v->hashlen != 5)
538 pgpPrtVal("V3 ", pgpTagTbl, tag);
539 pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
540 pgpPrtVal(" ", pgpHashTbl, v->hash_algo);
541 pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype);
543 t = pgpGrab(v->time, sizeof(v->time));
545 fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
547 pgpPrtHex(" signer keyid", v->signid, sizeof(v->signid));
548 plen = pgpGrab(v->signhash16, sizeof(v->signhash16));
549 pgpPrtHex(" signhash16", v->signhash16, sizeof(v->signhash16));
552 if (_digp->pubkey_algo == 0) {
553 _digp->version = v->version;
554 _digp->hashlen = v->hashlen;
555 _digp->sigtype = v->sigtype;
556 _digp->hash = memcpy(xmalloc(v->hashlen), &v->sigtype, v->hashlen);
557 memcpy(_digp->time, v->time, sizeof(_digp->time));
558 memcpy(_digp->signid, v->signid, sizeof(_digp->signid));
559 _digp->pubkey_algo = v->pubkey_algo;
560 _digp->hash_algo = v->hash_algo;
561 memcpy(_digp->signhash16, v->signhash16, sizeof(_digp->signhash16));
564 p = ((uint8_t *)v) + sizeof(*v);
565 rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
568 { pgpPktSigV4 v = (pgpPktSigV4)h;
570 if (hlen <= sizeof(*v))
573 pgpPrtVal("V4 ", pgpTagTbl, tag);
574 pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
575 pgpPrtVal(" ", pgpHashTbl, v->hash_algo);
576 pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype);
580 plen = pgpGrab(v->hashlen, sizeof(v->hashlen));
581 p += sizeof(v->hashlen);
583 if ((p + plen) > (h + hlen))
586 if (_digp->pubkey_algo == 0) {
587 _digp->hashlen = sizeof(*v) + plen;
588 _digp->hash = memcpy(xmalloc(_digp->hashlen), v, _digp->hashlen);
590 if (pgpPrtSubType(p, plen, v->sigtype, _digp))
597 if ((p + plen) > (h + hlen))
600 if (pgpPrtSubType(p, plen, v->sigtype, _digp))
605 pgpPrtHex(" signhash16", p, 2);
608 if (_digp->pubkey_algo == 0) {
609 _digp->version = v->version;
610 _digp->sigtype = v->sigtype;
611 _digp->pubkey_algo = v->pubkey_algo;
612 _digp->hash_algo = v->hash_algo;
613 memcpy(_digp->signhash16, p, sizeof(_digp->signhash16));
620 rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
629 char * pgpHexStr(const uint8_t *p, size_t plen)
632 str = t = xmalloc(plen * 2 + 1);
633 static char const hex[] = "0123456789abcdef";
637 *t++ = hex[ (i >> 4) & 0xf ];
638 *t++ = hex[ (i ) & 0xf ];
644 static int pgpPrtPubkeyParams(uint8_t pubkey_algo,
645 const uint8_t *p, const uint8_t *h, size_t hlen,
649 const uint8_t *pend = h + hlen;
651 pgpDigAlg keyalg = pgpPubkeyNew(pubkey_algo);
653 for (i = 0; p < pend && i < keyalg->mpis; i++, p += pgpMpiLen(p)) {
654 if (keyalg->setmpi(keyalg, i, p, pend))
658 /* Does the size and number of MPI's match our expectations? */
659 if (p == pend && i == keyalg->mpis)
662 /* We can't handle more than one key at a time */
663 if (rc == 0 && keyp->alg == NULL && keyp->tag == PGPTAG_PUBLIC_KEY)
666 pgpDigAlgFree(keyalg);
671 static int pgpPrtKey(pgpTag tag, const uint8_t *h, size_t hlen,
674 uint8_t version = *h;
675 const uint8_t * p = NULL;
679 /* We only permit V4 keys, V3 keys are long long since deprecated */
682 { pgpPktKeyV4 v = (pgpPktKeyV4)h;
684 if (hlen > sizeof(*v)) {
685 pgpPrtVal("V4 ", pgpTagTbl, tag);
686 pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
687 t = pgpGrab(v->time, sizeof(v->time));
689 fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
692 if (_digp->tag == tag) {
693 _digp->version = v->version;
694 memcpy(_digp->time, v->time, sizeof(_digp->time));
695 _digp->pubkey_algo = v->pubkey_algo;
698 p = ((uint8_t *)v) + sizeof(*v);
699 rc = pgpPrtPubkeyParams(v->pubkey_algo, p, h, hlen, _digp);
706 static int pgpPrtUserID(pgpTag tag, const uint8_t *h, size_t hlen,
709 pgpPrtVal("", pgpTagTbl, tag);
711 fprintf(stderr, " \"%.*s\"", (int)hlen, (const char *)h);
714 _digp->userid = memcpy(xmalloc(hlen+1), h, hlen);
715 _digp->userid[hlen] = '\0';
719 static int getFingerprint(const uint8_t *h, size_t hlen, pgpKeyID_t keyid)
721 int rc = -1; /* assume failure */
723 const uint8_t *pend = h + hlen;
725 /* We only permit V4 keys, V3 keys are long long since deprecated */
728 { pgpPktKeyV4 v = (pgpPktKeyV4) (h);
731 /* Packet must be larger than v to have room for the required MPIs */
732 if (hlen > sizeof(*v)) {
733 switch (v->pubkey_algo) {
734 case PGPPUBKEYALGO_RSA:
737 case PGPPUBKEYALGO_DSA:
743 se = (uint8_t *)(v + 1);
744 while (se < pend && mpis-- > 0)
747 /* Does the size and number of MPI's match our expectations? */
748 if (se == pend && mpis == 0) {
749 DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
753 uint8_t in[3] = { 0x99, (i >> 8), i };
755 (void) rpmDigestUpdate(ctx, in, 3);
756 (void) rpmDigestUpdate(ctx, h, i);
757 (void) rpmDigestFinal(ctx, (void **)&d, &dlen, 0);
760 memcpy(keyid, (d + (dlen-8)), 8);
771 int pgpPubkeyFingerprint(const uint8_t * pkt, size_t pktlen, pgpKeyID_t keyid)
775 if (decodePkt(pkt, pktlen, &p))
778 return getFingerprint(p.body, p.blen, keyid);
781 int pgpExtractPubkeyFingerprint(const char * b64pkt, pgpKeyID_t keyid)
785 int rc = -1; /* assume failure */
787 if (rpmBase64Decode(b64pkt, (void **)&pkt, &pktlen) == 0) {
788 if (pgpPubkeyFingerprint(pkt, pktlen, keyid) == 0) {
789 /* if there ever was a bizarre return code for success... */
797 static int pgpPrtPkt(struct pgpPkt *p, pgpDigParams _digp)
802 case PGPTAG_SIGNATURE:
803 rc = pgpPrtSig(p->tag, p->body, p->blen, _digp);
805 case PGPTAG_PUBLIC_KEY:
806 /* Get the public key fingerprint. */
807 if (!getFingerprint(p->body, p->blen, _digp->signid))
808 _digp->saved |= PGPDIG_SAVED_ID;
810 memset(_digp->signid, 0, sizeof(_digp->signid));
811 rc = pgpPrtKey(p->tag, p->body, p->blen, _digp);
814 rc = pgpPrtUserID(p->tag, p->body, p->blen, _digp);
817 case PGPTAG_COMMENT_OLD:
818 case PGPTAG_PUBLIC_SUBKEY:
819 case PGPTAG_SECRET_KEY:
820 case PGPTAG_SECRET_SUBKEY:
821 case PGPTAG_RESERVED:
822 case PGPTAG_PUBLIC_SESSION_KEY:
823 case PGPTAG_SYMMETRIC_SESSION_KEY:
824 case PGPTAG_COMPRESSED_DATA:
825 case PGPTAG_SYMMETRIC_DATA:
827 case PGPTAG_LITERAL_DATA:
830 case PGPTAG_ENCRYPTED_MDC:
832 case PGPTAG_PRIVATE_60:
833 case PGPTAG_PRIVATE_62:
836 pgpPrtVal("", pgpTagTbl, p->tag);
837 pgpPrtHex("", p->body, p->blen);
845 pgpDig pgpNewDig(void)
847 pgpDig dig = xcalloc(1, sizeof(*dig));
852 pgpDigParams pgpDigParamsFree(pgpDigParams digp)
855 pgpDigAlgFree(digp->alg);
858 memset(digp, 0, sizeof(*digp));
864 void pgpCleanDig(pgpDig dig)
867 pgpDigParamsFree(dig->signature);
868 pgpDigParamsFree(dig->pubkey);
869 memset(dig, 0, sizeof(*dig));
874 pgpDig pgpFreeDig(pgpDig dig)
878 /* DUmp the signature/pubkey data. */
885 pgpDigParams pgpDigGetParams(pgpDig dig, unsigned int pkttype)
887 pgpDigParams params = NULL;
890 case PGPTAG_SIGNATURE:
891 params = dig->signature;
893 case PGPTAG_PUBLIC_KEY:
894 params = dig->pubkey;
901 int pgpDigParamsCmp(pgpDigParams p1, pgpDigParams p2)
903 int rc = 1; /* assume different, eg if either is NULL */
905 /* XXX Should we compare something else too? */
906 if (p1->hash_algo != p2->hash_algo)
908 if (p1->pubkey_algo != p2->pubkey_algo)
910 if (p1->version != p2->version)
912 if (p1->sigtype != p2->sigtype)
914 if (memcmp(p1->signid, p2->signid, sizeof(p1->signid)) != 0)
917 /* Parameters match ... at least for our purposes */
924 unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype)
926 unsigned int algo = 0; /* assume failure */
929 case PGPVAL_PUBKEYALGO:
930 algo = digp->pubkey_algo;
932 case PGPVAL_HASHALGO:
933 algo = digp->hash_algo;
940 int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
943 const uint8_t *p = pkts;
944 const uint8_t *pend = pkts + pktlen;
945 pgpDigParams digp = NULL;
947 int rc = -1; /* assume failure */
950 if (decodePkt(p, (pend - p), &pkt))
954 if (pkttype && pkt.tag != pkttype) {
957 digp = xcalloc(1, sizeof(*digp));
962 if (pgpPrtPkt(&pkt, digp))
965 p += (pkt.body - pkt.head) + pkt.blen;
968 rc = (digp && (p == pend)) ? 0 : -1;
970 if (ret && rc == 0) {
973 pgpDigParamsFree(digp);
978 int pgpPrtPkts(const uint8_t * pkts, size_t pktlen, pgpDig dig, int printing)
981 pgpDigParams digp = NULL;
985 rc = pgpPrtParams(pkts, pktlen, 0, &digp);
987 if (dig && rc == 0) {
988 if (digp->tag == PGPTAG_SIGNATURE) {
989 pgpDigParamsFree(dig->signature);
990 dig->signature = digp;
992 pgpDigParamsFree(dig->pubkey);
996 pgpDigParamsFree(digp);
1002 char *pgpIdentItem(pgpDigParams digp)
1007 char *signid = pgpHexStr(digp->signid+4, sizeof(digp->signid)-4);
1008 rasprintf(&id, _("V%d %s/%s %s, key ID %s"),
1010 pgpValStr(pgpPubkeyTbl, digp->pubkey_algo),
1011 pgpValStr(pgpHashTbl, digp->hash_algo),
1012 pgpValStr(pgpTagTbl, digp->tag),
1016 id = xstrdup(_("(none)"));
1021 rpmRC pgpVerifySignature(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx)
1023 DIGEST_CTX ctx = rpmDigestDup(hashctx);
1024 uint8_t *hash = NULL;
1026 rpmRC res = RPMRC_FAIL; /* assume failure */
1028 if (sig == NULL || ctx == NULL)
1031 if (sig->hash != NULL)
1032 rpmDigestUpdate(ctx, sig->hash, sig->hashlen);
1034 if (sig->version == 4) {
1035 /* V4 trailer is six octets long (rfc4880) */
1037 uint32_t nb = sig->hashlen;
1039 trailer[0] = sig->version;
1041 memcpy(trailer+2, &nb, 4);
1042 rpmDigestUpdate(ctx, trailer, sizeof(trailer));
1045 rpmDigestFinal(ctx, (void **)&hash, &hashlen, 0);
1047 /* Compare leading 16 bits of digest for quick check. */
1048 if (hash == NULL || memcmp(hash, sig->signhash16, 2) != 0)
1052 * If we have a key, verify the signature for real. Otherwise we've
1053 * done all we can, return NOKEY to indicate "looks okay but dunno."
1055 if (key && key->alg) {
1056 pgpDigAlg sa = sig->alg;
1057 pgpDigAlg ka = key->alg;
1058 if (sa && sa->verify) {
1059 if (sa->verify(ka, sa, hash, hashlen, sig->hash_algo) == 0) {
1073 rpmRC pgpVerifySig(pgpDig dig, DIGEST_CTX hashctx)
1075 if (dig == NULL || hashctx == NULL)
1078 return pgpVerifySignature(pgpDigGetParams(dig, PGPTAG_PUBLIC_KEY),
1079 pgpDigGetParams(dig, PGPTAG_SIGNATURE), hashctx);
1082 static pgpArmor decodePkts(uint8_t *b, uint8_t **pkt, size_t *pktlen)
1084 const char * enc = NULL;
1085 const char * crcenc = NULL;
1090 uint32_t crcpkt, crc;
1091 const char * armortype = NULL;
1094 pgpArmor ec = PGPARMOR_ERR_NO_BEGIN_PGP; /* XXX assume failure */
1096 #define TOKEQ(_s, _tok) (rstreqn((_s), (_tok), sizeof(_tok)-1))
1098 for (t = (char *)b; t && *t; t = te) {
1100 if ((te = strchr(t, '\n')) == NULL)
1108 if (!TOKEQ(t, "-----BEGIN PGP "))
1110 t += sizeof("-----BEGIN PGP ")-1;
1112 rc = pgpValTok(pgpArmorTbl, t, te);
1114 ec = PGPARMOR_ERR_UNKNOWN_ARMOR_TYPE;
1117 if (rc != PGPARMOR_PUBKEY) /* XXX ASCII Pubkeys only, please. */
1120 armortype = pgpValStr(pgpArmorTbl, rc);
1121 t += strlen(armortype);
1122 if (!TOKEQ(t, "-----"))
1124 t += sizeof("-----")-1;
1125 if (*t != '\n' && *t != '\r')
1132 rc = pgpValTok(pgpArmorKeyTbl, t, te);
1135 if (*t != '\n' && *t != '\r') {
1139 enc = te; /* Start of encoded packets */
1146 *t++ = '\0'; /* Terminate encoded packets */
1147 crcenc = t; /* Start of encoded crc */
1152 if (!TOKEQ(t, "-----END PGP ")) {
1153 ec = PGPARMOR_ERR_NO_END_PGP;
1156 *t = '\0'; /* Terminate encoded crc */
1157 t += sizeof("-----END PGP ")-1;
1158 if (t >= te) continue;
1160 if (armortype == NULL) /* XXX can't happen */
1162 if (!rstreqn(t, armortype, strlen(armortype)))
1165 t += strlen(armortype);
1166 if (t >= te) continue;
1168 if (!TOKEQ(t, "-----")) {
1169 ec = PGPARMOR_ERR_NO_END_PGP;
1172 t += (sizeof("-----")-1);
1173 if (t >= te) continue;
1174 /* XXX permitting \r here is not RFC-2440 compliant <shrug> */
1175 if (!(*t == '\n' || *t == '\r')) continue;
1179 if (rpmBase64Decode(crcenc, (void **)&crcdec, &crclen) != 0) {
1180 ec = PGPARMOR_ERR_CRC_DECODE;
1183 crcpkt = pgpGrab(crcdec, crclen);
1184 crcdec = _free(crcdec);
1187 if (rpmBase64Decode(enc, (void **)&dec, &declen) != 0) {
1188 ec = PGPARMOR_ERR_BODY_DECODE;
1191 crc = pgpCRC(dec, declen);
1192 if (crcpkt != crc) {
1193 ec = PGPARMOR_ERR_CRC_CHECK;
1196 if (pkt) *pkt = dec;
1197 if (pktlen) *pktlen = declen;
1198 ec = PGPARMOR_PUBKEY; /* XXX ASCII Pubkeys only, please. */
1209 pgpArmor pgpReadPkts(const char * fn, uint8_t ** pkt, size_t * pktlen)
1213 pgpArmor ec = PGPARMOR_ERR_NO_BEGIN_PGP; /* XXX assume failure */
1214 int rc = rpmioSlurp(fn, &b, &blen);
1215 if (rc == 0 && b != NULL && blen > 0) {
1216 ec = decodePkts(b, pkt, pktlen);
1222 pgpArmor pgpParsePkts(const char *armor, uint8_t ** pkt, size_t * pktlen)
1224 pgpArmor ec = PGPARMOR_ERR_NO_BEGIN_PGP; /* XXX assume failure */
1225 if (armor && strlen(armor) > 0) {
1226 uint8_t *b = (uint8_t*) xstrdup(armor);
1227 ec = decodePkts(b, pkt, pktlen);
1233 char * pgpArmorWrap(int atype, const unsigned char * s, size_t ns)
1235 char *buf = NULL, *val = NULL;
1236 char *enc = rpmBase64Encode(s, ns, -1);
1237 char *crc = rpmBase64CRC(s, ns);
1238 const char *valstr = pgpValStr(pgpArmorTbl, atype);
1240 if (crc != NULL && enc != NULL) {
1241 rasprintf(&buf, "%s=%s", enc, crc);
1246 rasprintf(&val, "-----BEGIN PGP %s-----\nVersion: rpm-" VERSION " (NSS-3)\n\n"
1247 "%s\n-----END PGP %s-----\n",
1248 valstr, buf != NULL ? buf : "", valstr);