rpm 5.3.12
rpmio/rpmpgp.c
Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #define _RPMIOB_INTERNAL
00009 #include <rpmiotypes.h>
00010 
00011 #include <rpmio.h>
00012 
00013 #define _RPMPGP_INTERNAL
00014 #include <rpmbc.h>      /* XXX still needs base64 goop */
00015 #if defined(WITH_NSS)
00016 #include <rpmnss.h>
00017 #endif
00018 #include "debug.h"
00019 
00020 /*@access pgpDig @*/
00021 /*@access pgpDigParams @*/
00022 /*@access pgpPkt @*/
00023 /*@access rpmiob @*/
00024 
00025 /*@unchecked@*/
00026 int _pgp_debug;
00027 
00028 /*@unchecked@*/
00029 int _pgp_print;
00030 
00031 /*@unchecked@*/
00032 int _pgp_error_count;
00033 
00034 /*@unchecked@*/
00035 pgpImplVecs_t * pgpImplVecs =
00036     /* explicit selection (order DOES NOT matter here) */
00037 #if defined(USE_CRYPTO_BEECRYPT) && defined(WITH_BEECRYPT)
00038         &rpmbcImplVecs;
00039 #elif defined(USE_CRYPTO_GCRYPT) && defined(WITH_GCRYPT)
00040         &rpmgcImplVecs;
00041 #elif defined(USE_CRYPTO_NSS) && defined(WITH_NSS)
00042         &rpmnssImplVecs;
00043 #elif defined(USE_CRYPTO_OPENSSL) && defined(WITH_SSL)
00044         &rpmsslImplVecs;
00045 #elif defined(USE_CRYPTO_CDSA) && defined(WITH_CDSA)
00046         &rpmcdsaImplVecs;
00047 #elif defined(USE_CRYPTO_TOMCRYPT) && defined(WITH_TOMCRYPT)
00048         &rpmltcImplVecs;
00049     /* implict selection (order DOES matter) */
00050 #elif defined(WITH_BEECRYPT)
00051         &rpmbcImplVecs;
00052 #elif defined(WITH_NSS)
00053         &rpmnssImplVecs;
00054 #elif defined(WITH_GCRYPT)
00055         &rpmgcImplVecs;
00056 #elif defined(WITH_SSL)
00057         &rpmsslImplVecs;
00058 #elif defined(WITH_CDSA)
00059         &rpmcdsaImplVecs;
00060 #elif defined(WITH_TOMCRYPT)
00061         &rpmltcImplVecs;
00062 #else
00063 #error INTERNAL ERROR: no suitable Cryptography library available
00064 #endif
00065 
00066 /*@unchecked@*/ /*@refcounted@*/ /*@relnull@*/
00067 static pgpDig _dig = NULL;
00068 
00069 /*@unchecked@*/ /*@null@*/
00070 static pgpDigParams _digp = NULL;
00071 
00072 #ifdef  DYING
00073 struct pgpPkt_s {
00074     pgpTag tag;
00075     unsigned int pktlen;
00076     const rpmuint8_t * h;
00077     unsigned int hlen;
00078 };
00079 #endif
00080 
00081 struct pgpValTbl_s pgpSigTypeTbl[] = {
00082     { PGPSIGTYPE_BINARY,        "BINARY" },
00083     { PGPSIGTYPE_TEXT,          "TEXT" },
00084     { PGPSIGTYPE_STANDALONE,    "STANDALONE" },
00085     { PGPSIGTYPE_GENERIC_CERT,  "GENERIC" },
00086     { PGPSIGTYPE_PERSONA_CERT,  "PERSONA" },
00087     { PGPSIGTYPE_CASUAL_CERT,   "CASUAL" },
00088     { PGPSIGTYPE_POSITIVE_CERT, "POSITIVE" },
00089     { PGPSIGTYPE_SUBKEY_BINDING,"SUBKEY_BIND" },
00090     { PGPSIGTYPE_KEY_BINDING,   "KEY_BIND" },
00091     { PGPSIGTYPE_SIGNED_KEY,    "KEY" },
00092     { PGPSIGTYPE_KEY_REVOKE,    "KEY_REVOKE" },
00093     { PGPSIGTYPE_SUBKEY_REVOKE, "SUBKEY_REVOKE" },
00094     { PGPSIGTYPE_CERT_REVOKE,   "CERT_REVOKE" },
00095     { PGPSIGTYPE_TIMESTAMP,     "TIMESTAMP" },
00096     { PGPSIGTYPE_CONFIRM,       "CONFIRM" },
00097     { -1,                       "SIG_UNKNOWN" },
00098 };
00099 
00100 struct pgpValTbl_s pgpPubkeyTbl[] = {
00101     { PGPPUBKEYALGO_RSA,        "RSA" },
00102     { PGPPUBKEYALGO_RSA_ENCRYPT,"RSA(Encrypt-Only)" },
00103     { PGPPUBKEYALGO_RSA_SIGN,   "RSA(Sign-Only)" },
00104     { PGPPUBKEYALGO_ELGAMAL_ENCRYPT,"ELG(Encrypt-Only)" },
00105     { PGPPUBKEYALGO_DSA,        "DSA" },
00106     { PGPPUBKEYALGO_EC,         "ECC" },
00107     { PGPPUBKEYALGO_ECDSA,      "ECDSA" },
00108     { PGPPUBKEYALGO_ELGAMAL,    "ELG" },
00109     { PGPPUBKEYALGO_DH,         "DH" },
00110     { PGPPUBKEYALGO_ECDH,       "ECDH" },
00111     { -1,                       "KEY_UNKNOWN" },
00112 };
00113 
00114 struct pgpValTbl_s pgpSymkeyTbl[] = {
00115     { PGPSYMKEYALGO_PLAINTEXT,  "Plaintext" },
00116     { PGPSYMKEYALGO_IDEA,       "IDEA" },
00117     { PGPSYMKEYALGO_TRIPLE_DES, "3DES" },
00118     { PGPSYMKEYALGO_CAST5,      "CAST5" },
00119     { PGPSYMKEYALGO_BLOWFISH,   "BLOWFISH" },
00120     { PGPSYMKEYALGO_SAFER,      "SAFER" },
00121     { PGPSYMKEYALGO_DES_SK,     "DES/SK" },
00122     { PGPSYMKEYALGO_AES_128,    "AES(128-bit key)" },
00123     { PGPSYMKEYALGO_AES_192,    "AES(192-bit key)" },
00124     { PGPSYMKEYALGO_AES_256,    "AES(256-bit key)" },
00125     { PGPSYMKEYALGO_TWOFISH,    "TWOFISH(256-bit key)" },
00126     { PGPSYMKEYALGO_CAMELLIA_128, "CAMELLIA(128-bit key)" },
00127     { PGPSYMKEYALGO_CAMELLIA_192, "CAMELLIA(192-bit key)" },
00128     { PGPSYMKEYALGO_CAMELLIA_256, "CAMELLIA(256-bit key)" },
00129     { PGPSYMKEYALGO_NOENCRYPT,  "no encryption" },
00130     { -1,                       "SYM_UNKNOWN" },
00131 };
00132 
00133 struct pgpValTbl_s pgpCompressionTbl[] = {
00134     { PGPCOMPRESSALGO_NONE,     "Uncompressed" },
00135     { PGPCOMPRESSALGO_ZIP,      "ZIP" },
00136     { PGPCOMPRESSALGO_ZLIB,     "ZLIB" },
00137     { PGPCOMPRESSALGO_BZIP2,    "BZIP2" },
00138     { -1,                       "Unknown compression algorithm" },
00139 };
00140 
00141 struct pgpValTbl_s pgpHashTbl[] = {
00142     { PGPHASHALGO_MD5,          "MD5" },
00143     { PGPHASHALGO_SHA1,         "SHA1" },
00144     { PGPHASHALGO_RIPEMD160,    "RIPEMD160" },
00145     { PGPHASHALGO_MD2,          "MD2" },
00146     { PGPHASHALGO_TIGER192,     "TIGER192" },
00147     { PGPHASHALGO_HAVAL_5_160,  "HAVAL-5-160" },
00148     { PGPHASHALGO_SHA224,       "SHA224" },
00149     { PGPHASHALGO_SHA256,       "SHA256" },
00150     { PGPHASHALGO_SHA384,       "SHA384" },
00151     { PGPHASHALGO_SHA512,       "SHA512" },
00152     { -1,                       "MD_UNKNOWN" },
00153 };
00154 
00155 /*@-exportlocal -exportheadervar@*/
00156 /*@observer@*/ /*@unchecked@*/
00157 struct pgpValTbl_s pgpKeyServerPrefsTbl[] = {
00158     { 0x80,                     "No-modify" },
00159     { -1,                       "Unknown key server preference" },
00160 };
00161 /*@=exportlocal =exportheadervar@*/
00162 
00163 struct pgpValTbl_s pgpSubTypeTbl[] = {
00164     { PGPSUBTYPE_SIG_CREATE_TIME,"created" },
00165     { PGPSUBTYPE_SIG_EXPIRE_TIME,"expires" },
00166     { PGPSUBTYPE_EXPORTABLE_CERT,"exportable" },
00167     { PGPSUBTYPE_TRUST_SIG,     "trust signature" },
00168     { PGPSUBTYPE_REGEX,         "regular expression" },
00169     { PGPSUBTYPE_REVOCABLE,     "revocable" },
00170     { PGPSUBTYPE_KEY_EXPIRE_TIME,"key expiration time" },
00171     { PGPSUBTYPE_ARR,           "additional recipient request" },
00172     { PGPSUBTYPE_PREFER_SYMKEY, "preferred symmetric algorithms" },
00173     { PGPSUBTYPE_REVOKE_KEY,    "revocation key" },
00174     { PGPSUBTYPE_ISSUER_KEYID,  "issuer" },
00175     { PGPSUBTYPE_NOTATION,      "notation data" },
00176     { PGPSUBTYPE_PREFER_HASH,   "preferred hash algorithms" },
00177     { PGPSUBTYPE_PREFER_COMPRESS,"preferred compression algorithms" },
00178     { PGPSUBTYPE_KEYSERVER_PREFERS,"key server preferences" },
00179     { PGPSUBTYPE_PREFER_KEYSERVER,"preferred key server" },
00180     { PGPSUBTYPE_PRIMARY_USERID,"primary user id" },
00181     { PGPSUBTYPE_POLICY_URL,    "policy URL" },
00182     { PGPSUBTYPE_KEY_FLAGS,     "key flags" },
00183     { PGPSUBTYPE_SIGNER_USERID, "signer's user id" },
00184     { PGPSUBTYPE_REVOKE_REASON, "reason for revocation" },
00185     { PGPSUBTYPE_FEATURES,      "features" },
00186     { PGPSUBTYPE_SIG_TARGET,    "signature target" },
00187     { PGPSUBTYPE_EMBEDDED_SIG,  "embedded signature" },
00188 
00189     { PGPSUBTYPE_INTERNAL_100,  "internal subpkt type 100" },
00190     { PGPSUBTYPE_INTERNAL_101,  "internal subpkt type 101" },
00191     { PGPSUBTYPE_INTERNAL_102,  "internal subpkt type 102" },
00192     { PGPSUBTYPE_INTERNAL_103,  "internal subpkt type 103" },
00193     { PGPSUBTYPE_INTERNAL_104,  "internal subpkt type 104" },
00194     { PGPSUBTYPE_INTERNAL_105,  "internal subpkt type 105" },
00195     { PGPSUBTYPE_INTERNAL_106,  "internal subpkt type 106" },
00196     { PGPSUBTYPE_INTERNAL_107,  "internal subpkt type 107" },
00197     { PGPSUBTYPE_INTERNAL_108,  "internal subpkt type 108" },
00198     { PGPSUBTYPE_INTERNAL_109,  "internal subpkt type 109" },
00199     { PGPSUBTYPE_INTERNAL_110,  "internal subpkt type 110" },
00200     { -1,                       "Unknown signature subkey type" },
00201 };
00202 
00203 struct pgpValTbl_s pgpTagTbl[] = {
00204     { PGPTAG_PUBLIC_SESSION_KEY,"Public-Key Encrypted Session Key" },
00205     { PGPTAG_SIGNATURE,         "Signature" },
00206     { PGPTAG_SYMMETRIC_SESSION_KEY,"Symmetric-Key Encrypted Session Key" },
00207     { PGPTAG_ONEPASS_SIGNATURE, "One-Pass Signature" },
00208     { PGPTAG_SECRET_KEY,        "Secret Key" },
00209     { PGPTAG_PUBLIC_KEY,        "Public Key" },
00210     { PGPTAG_SECRET_SUBKEY,     "Secret Subkey" },
00211     { PGPTAG_COMPRESSED_DATA,   "Compressed Data" },
00212     { PGPTAG_SYMMETRIC_DATA,    "Symmetrically Encrypted Data" },
00213     { PGPTAG_MARKER,            "Marker" },
00214     { PGPTAG_LITERAL_DATA,      "Literal Data" },
00215     { PGPTAG_TRUST,             "Trust" },
00216     { PGPTAG_USER_ID,           "User ID" },
00217     { PGPTAG_PUBLIC_SUBKEY,     "Public Subkey" },
00218     { PGPTAG_COMMENT_OLD,       "Comment (from OpenPGP draft)" },
00219     { PGPTAG_PHOTOID,           "PGP's photo ID" },
00220     { PGPTAG_ENCRYPTED_MDC,     "Integrity protected encrypted data" },
00221     { PGPTAG_MDC,               "Manipulaion detection code packet" },
00222     { PGPTAG_PRIVATE_60,        "Private #60" },
00223     { PGPTAG_COMMENT,           "Comment" },
00224     { PGPTAG_PRIVATE_62,        "Private #62" },
00225     { PGPTAG_CONTROL,           "Control (GPG)" },
00226     { -1,                       "TAG_UNKNOWN" },
00227 };
00228 
00229 struct pgpValTbl_s pgpArmorTbl[] = {
00230     { PGPARMOR_MESSAGE,         "MESSAGE" },
00231     { PGPARMOR_PUBKEY,          "PUBLIC KEY BLOCK" },
00232     { PGPARMOR_SIGNATURE,       "SIGNATURE" },
00233     { PGPARMOR_SIGNED_MESSAGE,  "SIGNED MESSAGE" },
00234     { PGPARMOR_FILE,            "ARMORED FILE" },
00235     { PGPARMOR_PRIVKEY,         "PRIVATE KEY BLOCK" },
00236     { PGPARMOR_SECKEY,          "SECRET KEY BLOCK" },
00237     { -1,                       "Unknown armor block" }
00238 };
00239 
00240 struct pgpValTbl_s pgpArmorKeyTbl[] = {
00241     { PGPARMORKEY_VERSION,      "Version: " },
00242     { PGPARMORKEY_COMMENT,      "Comment: " },
00243     { PGPARMORKEY_MESSAGEID,    "MessageID: " },
00244     { PGPARMORKEY_HASH,         "Hash: " },
00245     { PGPARMORKEY_CHARSET,      "Charset: " },
00246     { -1,                       "Unknown armor key" }
00247 };
00248 
00249 static void pgpPrtNL(void)
00250         /*@globals fileSystem @*/
00251         /*@modifies fileSystem @*/
00252 {
00253     if (!_pgp_print) return;
00254     fprintf(stderr, "\n");
00255 }
00256 
00257 static void pgpPrtInt(const char *pre, int i)
00258         /*@globals fileSystem @*/
00259         /*@modifies fileSystem @*/
00260 {
00261     if (!_pgp_print) return;
00262     if (pre && *pre)
00263         fprintf(stderr, "%s", pre);
00264     fprintf(stderr, " %d", i);
00265 }
00266 
00267 static void pgpPrtStr(const char *pre, const char *s)
00268         /*@globals fileSystem @*/
00269         /*@modifies fileSystem @*/
00270 {
00271     if (!_pgp_print) return;
00272     if (pre && *pre)
00273         fprintf(stderr, "%s", pre);
00274     fprintf(stderr, " %s", s);
00275 }
00276 
00277 static void pgpPrtHex(const char *pre, const rpmuint8_t * p, size_t plen)
00278         /*@globals fileSystem @*/
00279         /*@modifies fileSystem @*/
00280 {
00281     if (!_pgp_print) return;
00282     if (pre && *pre)
00283         fprintf(stderr, "%s", pre);
00284     fprintf(stderr, " %s", pgpHexStr(p, plen));
00285 }
00286 
00287 void pgpPrtVal(const char * pre, pgpValTbl vs, rpmuint8_t val)
00288         /*@globals fileSystem @*/
00289         /*@modifies fileSystem @*/
00290 {
00291     if (!_pgp_print) return;
00292     if (pre && *pre)
00293         fprintf(stderr, "%s", pre);
00294     fprintf(stderr, "%s(%u)", pgpValStr(vs, val), (unsigned)val);
00295 }
00296 
00297 int pgpPrtSubType(const rpmuint8_t * h, size_t hlen, pgpSigType sigtype)
00298 {
00299     const rpmuint8_t * p = h;
00300     unsigned plen;
00301     unsigned i;
00302 
00303     while (hlen > 0) {
00304         i = pgpLen(p, &plen);
00305         p += i;
00306         hlen -= i;
00307 
00308         pgpPrtVal("    ", pgpSubTypeTbl, (p[0]&(~PGPSUBTYPE_CRITICAL)));
00309         if ((p[0] & PGPSUBTYPE_CRITICAL) != (rpmuint8_t)0)
00310             if (_pgp_print)
00311                 fprintf(stderr, " *CRITICAL*");
00312         switch (*p) {
00313         case PGPSUBTYPE_PREFER_SYMKEY:  /* preferred symmetric algorithms */
00314             for (i = 1; i < plen; i++)
00315                 pgpPrtVal(" ", pgpSymkeyTbl, p[i]);
00316             /*@switchbreak@*/ break;
00317         case PGPSUBTYPE_PREFER_HASH:    /* preferred hash algorithms */
00318             for (i = 1; i < plen; i++)
00319                 pgpPrtVal(" ", pgpHashTbl, p[i]);
00320             /*@switchbreak@*/ break;
00321         case PGPSUBTYPE_PREFER_COMPRESS:/* preferred compression algorithms */
00322             for (i = 1; i < plen; i++)
00323                 pgpPrtVal(" ", pgpCompressionTbl, p[i]);
00324             /*@switchbreak@*/ break;
00325         case PGPSUBTYPE_KEYSERVER_PREFERS:/* key server preferences */
00326             for (i = 1; i < plen; i++)
00327                 pgpPrtVal(" ", pgpKeyServerPrefsTbl, p[i]);
00328             /*@switchbreak@*/ break;
00329         case PGPSUBTYPE_SIG_CREATE_TIME:
00330 /*@-mods -mayaliasunique @*/
00331             if (_digp && !(_digp->saved & PGPDIG_SAVED_TIME) &&
00332                 (sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
00333             {
00334                 _digp->saved |= PGPDIG_SAVED_TIME;
00335                 memcpy(_digp->time, p+1, sizeof(_digp->time));
00336             }
00337 /*@=mods =mayaliasunique @*/
00338             if ((plen - 1) == 4) {
00339                 time_t t = pgpGrab(p+1, plen-1);
00340                 if (_pgp_print)
00341                    fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
00342             } else
00343                 pgpPrtHex("", p+1, plen-1);
00344             /*@switchbreak@*/ break;
00345         case PGPSUBTYPE_SIG_EXPIRE_TIME:
00346         case PGPSUBTYPE_KEY_EXPIRE_TIME:        /* XXX only on self-signature */
00347             if ((plen - 1) == 4) {
00348                 time_t t = pgpGrab(p+1, plen-1);
00349                 if (_digp->saved & PGPDIG_SAVED_TIME)
00350                     t += pgpGrab(_digp->time, sizeof(_digp->time));
00351                 if (_pgp_print)
00352                    fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
00353             } else
00354                 pgpPrtHex("", p+1, plen-1);
00355             /*@switchbreak@*/ break;
00356 
00357         case PGPSUBTYPE_ISSUER_KEYID:   /* issuer key ID */
00358 /*@-mods -mayaliasunique @*/
00359             if (_digp && !(_digp->saved & PGPDIG_SAVED_ID) &&
00360                 (sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
00361             {
00362                 _digp->saved |= PGPDIG_SAVED_ID;
00363                 memcpy(_digp->signid, p+1, sizeof(_digp->signid));
00364             }
00365 /*@=mods =mayaliasunique @*/
00366             /*@fallthrough@*/
00367         case PGPSUBTYPE_EXPORTABLE_CERT:
00368         case PGPSUBTYPE_TRUST_SIG:
00369         case PGPSUBTYPE_REGEX:
00370         case PGPSUBTYPE_REVOCABLE:
00371         case PGPSUBTYPE_ARR:
00372         case PGPSUBTYPE_REVOKE_KEY:
00373         case PGPSUBTYPE_NOTATION:
00374         case PGPSUBTYPE_PREFER_KEYSERVER:
00375         case PGPSUBTYPE_PRIMARY_USERID:
00376         case PGPSUBTYPE_POLICY_URL:
00377         case PGPSUBTYPE_KEY_FLAGS:
00378         case PGPSUBTYPE_SIGNER_USERID:
00379         case PGPSUBTYPE_REVOKE_REASON:
00380         case PGPSUBTYPE_FEATURES:
00381         case PGPSUBTYPE_SIG_TARGET:
00382         case PGPSUBTYPE_EMBEDDED_SIG:
00383         case PGPSUBTYPE_INTERNAL_100:
00384         case PGPSUBTYPE_INTERNAL_101:
00385         case PGPSUBTYPE_INTERNAL_102:
00386         case PGPSUBTYPE_INTERNAL_103:
00387         case PGPSUBTYPE_INTERNAL_104:
00388         case PGPSUBTYPE_INTERNAL_105:
00389         case PGPSUBTYPE_INTERNAL_106:
00390         case PGPSUBTYPE_INTERNAL_107:
00391         case PGPSUBTYPE_INTERNAL_108:
00392         case PGPSUBTYPE_INTERNAL_109:
00393         case PGPSUBTYPE_INTERNAL_110:
00394         default:
00395             pgpPrtHex("", p+1, plen-1);
00396             /*@switchbreak@*/ break;
00397         }
00398         pgpPrtNL();
00399         p += plen;
00400         hlen -= plen;
00401     }
00402     return 0;
00403 }
00404 
00405 /*@-varuse =readonlytrans -nullassign @*/
00406 /*@observer@*/ /*@unchecked@*/
00407 static const char * pgpSigRSA[] = {
00408     " m**d =",
00409     NULL,
00410 };
00411 
00412 /*@observer@*/ /*@unchecked@*/
00413 static const char * pgpSigDSA[] = {
00414     "    r =",
00415     "    s =",
00416     NULL,
00417 };
00418 
00419 /*@observer@*/ /*@unchecked@*/
00420 static const char * pgpSigECDSA[] = {
00421     "    r =",
00422     "    s =",
00423     NULL,
00424 };
00425 /*@=varuse =readonlytrans =nullassign @*/
00426 
00427 int pgpPrtSigParams(pgpDig dig, const pgpPkt pp, pgpPubkeyAlgo pubkey_algo,
00428                 pgpSigType sigtype, const rpmuint8_t * p)
00429 {
00430     const rpmuint8_t * pend = pp->u.h + pp->hlen;
00431     int xx;
00432     int i;
00433 
00434     for (i = 0; p < pend; i++, p += pgpMpiLen(p)) {
00435         if (pubkey_algo == PGPPUBKEYALGO_RSA) {
00436             if (i >= 1) break;
00437             if (dig &&
00438         (dig != _dig || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT))
00439             {
00440                 xx = 0;
00441                 switch (i) {
00442                 case 0:         /* m**d */
00443                     xx = pgpImplMpiItem(pgpSigRSA[i], dig, 10+i, p, pend);
00444                     /*@switchbreak@*/ break;
00445                 default:
00446                     xx = 1;
00447                     /*@switchbreak@*/ break;
00448                 }
00449                 if (xx) return xx;
00450             }
00451             pgpPrtStr("", pgpSigRSA[i]);
00452         } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
00453             if (i >= 2) break;
00454             if (dig &&
00455         (dig != _dig || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT))
00456             {
00457                 xx = 0;
00458                 switch (i) {
00459                 case 0:         /* r */
00460                     xx = pgpImplMpiItem(pgpSigDSA[i], dig, 20+i, p, pend);
00461                     /*@switchbreak@*/ break;
00462                 case 1:         /* s */
00463                     xx = pgpImplMpiItem(pgpSigDSA[i], dig, 20+i, p, pend);
00464                     /*@switchbreak@*/ break;
00465                 default:
00466                     xx = 1;
00467                     /*@switchbreak@*/ break;
00468                 }
00469                 if (xx) return xx;
00470             }
00471             pgpPrtStr("", pgpSigDSA[i]);
00472         } else if (pubkey_algo == PGPPUBKEYALGO_ECDSA) {
00473             if (i >= 2) break;
00474             if (dig &&
00475         (dig != _dig || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT))
00476             {
00477                 xx = 0;
00478                 switch (i) {
00479                 case 0:         /* r */
00480                     xx = pgpImplMpiItem(pgpSigECDSA[i], dig, 50+i, p, pend);
00481                     /*@switchbreak@*/ break;
00482                 case 1:         /* s */
00483                     xx = pgpImplMpiItem(pgpSigECDSA[i], dig, 50+i, p, pend);
00484                     /*@switchbreak@*/ break;
00485                 default:
00486                     xx = 1;
00487                     /*@switchbreak@*/ break;
00488                 }
00489                 if (xx) return xx;
00490             }
00491             pgpPrtStr("", pgpSigECDSA[i]);
00492         } else {
00493             if (_pgp_print)
00494                 fprintf(stderr, "%7d", i);
00495         }
00496         pgpPrtStr("", pgpMpiStr(p));
00497         pgpPrtNL();
00498     }
00499 
00500     return 0;
00501 }
00502 
00503 int pgpPrtSig(const pgpPkt pp)
00504         /*@globals _digp @*/
00505         /*@modifies *_digp @*/
00506 {
00507     rpmuint8_t version = pp->u.h[0];
00508     rpmuint8_t * p;
00509     unsigned plen;
00510     int rc;
00511 
00512     switch (version) {
00513     case 3:
00514     {   pgpPktSigV3 v = (pgpPktSigV3)pp->u.h;
00515         time_t t;
00516 
00517         if (v->hashlen != (rpmuint8_t)5)
00518             return 1;
00519 
00520         pgpPrtVal("V3 ", pgpTagTbl, (rpmuint8_t)pp->tag);
00521         pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
00522         pgpPrtVal(" ", pgpHashTbl, v->hash_algo);
00523         pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype);
00524         pgpPrtNL();
00525         t = pgpGrab(v->time, sizeof(v->time));
00526         if (_pgp_print)
00527             fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
00528         pgpPrtNL();
00529         pgpPrtHex(" signer keyid", v->signid, sizeof(v->signid));
00530         plen = pgpGrab(v->signhash16, sizeof(v->signhash16));
00531         pgpPrtHex(" signhash16", v->signhash16, sizeof(v->signhash16));
00532         pgpPrtNL();
00533 
00534         if (_digp && _digp->pubkey_algo == (rpmuint8_t)0) {
00535             _digp->version = v->version;
00536             _digp->hashlen = (size_t) v->hashlen;
00537             _digp->sigtype = v->sigtype;
00538             _digp->hash = &v->sigtype;
00539             memcpy(_digp->time, v->time, sizeof(_digp->time));
00540             memcpy(_digp->signid, v->signid, sizeof(_digp->signid));
00541             _digp->pubkey_algo = v->pubkey_algo;
00542             _digp->hash_algo = v->hash_algo;
00543             memcpy(_digp->signhash16, v->signhash16, sizeof(_digp->signhash16));
00544         }
00545 
00546         p = ((rpmuint8_t *)v) + sizeof(*v);
00547         rc = pgpPrtSigParams(_dig, pp, (pgpPubkeyAlgo)v->pubkey_algo,
00548                         (pgpSigType)v->sigtype, p);
00549     }   break;
00550     case 4:
00551     {   pgpPktSigV4 v = (pgpPktSigV4)pp->u.h;
00552 
00553         pgpPrtVal("V4 ", pgpTagTbl, (rpmuint8_t)pp->tag);
00554         pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
00555         pgpPrtVal(" ", pgpHashTbl, v->hash_algo);
00556         pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype);
00557         pgpPrtNL();
00558 
00559         p = &v->hashlen[0];
00560         plen = pgpGrab(v->hashlen, sizeof(v->hashlen));
00561         p += sizeof(v->hashlen);
00562 
00563         if ((p + plen) > (pp->u.h + pp->hlen))
00564             return 1;
00565 
00566 if (_pgp_debug && _pgp_print)
00567 fprintf(stderr, "   hash[%u] -- %s\n", plen, pgpHexStr(p, plen));
00568         if (_digp && _digp->pubkey_algo == (rpmuint8_t)0) {
00569             _digp->hashlen = sizeof(*v) + plen;
00570             _digp->hash = pp->u.h;
00571         }
00572         (void) pgpPrtSubType(p, plen, (pgpSigType)v->sigtype);
00573         p += plen;
00574 
00575         plen = pgpGrab(p, 2);
00576         p += 2;
00577 
00578         if ((p + plen) > (pp->u.h + pp->hlen))
00579             return 1;
00580 
00581 if (_pgp_debug && _pgp_print)
00582 fprintf(stderr, " unhash[%u] -- %s\n", plen, pgpHexStr(p, plen));
00583         (void) pgpPrtSubType(p, plen, (pgpSigType)v->sigtype);
00584         p += plen;
00585 
00586         plen = pgpGrab(p,2);
00587         pgpPrtHex(" signhash16", p, 2);
00588         pgpPrtNL();
00589 
00590         if (_digp && _digp->pubkey_algo == (rpmuint8_t)0) {
00591             _digp->version = v->version;
00592             _digp->sigtype = v->sigtype;
00593             _digp->pubkey_algo = v->pubkey_algo;
00594             _digp->hash_algo = v->hash_algo;
00595             memcpy(_digp->signhash16, p, sizeof(_digp->signhash16));
00596         }
00597 
00598         p += 2;
00599         if (p > (pp->u.h + pp->hlen))
00600             return 1;
00601 
00602         rc = pgpPrtSigParams(_dig, pp, (pgpPubkeyAlgo)v->pubkey_algo,
00603                         (pgpSigType)v->sigtype, p);
00604     }   break;
00605     default:
00606         rc = 1;
00607         break;
00608     }
00609     return rc;
00610 }
00611 
00612 /*@-varuse =readonlytrans -nullassign @*/
00613 /*@observer@*/ /*@unchecked@*/
00614 static const char * pgpPublicRSA[] = {
00615     "    n =",
00616     "    e =",
00617     NULL,
00618 };
00619 
00620 #ifdef NOTYET
00621 /*@observer@*/ /*@unchecked@*/
00622 static const char * pgpSecretRSA[] = {
00623     "    d =",
00624     "    p =",
00625     "    q =",
00626     "    u =",
00627     NULL,
00628 };
00629 #endif
00630 
00631 /*@observer@*/ /*@unchecked@*/
00632 static const char * pgpPublicDSA[] = {
00633     "    p =",
00634     "    q =",
00635     "    g =",
00636     "    y =",
00637     NULL,
00638 };
00639 
00640 #ifdef  NOTYET
00641 /*@observer@*/ /*@unchecked@*/
00642 static const char * pgpSecretDSA[] = {
00643     "    x =",
00644     NULL,
00645 };
00646 #endif
00647 
00648 /*@observer@*/ /*@unchecked@*/
00649 static const char * pgpPublicECDSA[] = {
00650     "    Q =",
00651     NULL,
00652 };
00653 
00654 #ifdef  NOTYET
00655 /*@observer@*/ /*@unchecked@*/
00656 static const char * pgpSecretECDSA[] = {
00657     "    d =",
00658     NULL,
00659 };
00660 #endif
00661 
00662 /*@observer@*/ /*@unchecked@*/
00663 static const char * pgpPublicELGAMAL[] = {
00664     "    p =",
00665     "    g =",
00666     "    y =",
00667     NULL,
00668 };
00669 
00670 #ifdef  NOTYET
00671 /*@observer@*/ /*@unchecked@*/
00672 static const char * pgpSecretELGAMAL[] = {
00673     "    x =",
00674     NULL,
00675 };
00676 #endif
00677 /*@=varuse =readonlytrans =nullassign @*/
00678 
00679 const rpmuint8_t * pgpPrtPubkeyParams(pgpDig dig, const pgpPkt pp,
00680                 pgpPubkeyAlgo pubkey_algo, /*@returned@*/ const rpmuint8_t * p)
00681 {
00682     const rpmuint8_t * pend = pp->u.h + pp->hlen;
00683     int i;
00684 
00685     for (i = 0; p < pend; i++, p += pgpMpiLen(p)) {
00686         if (pubkey_algo == PGPPUBKEYALGO_RSA) {
00687             if (i >= 2) break;
00688             if (dig) {
00689                 switch (i) {
00690                 case 0:         /* n */
00691                     (void) pgpImplMpiItem(pgpPublicRSA[i], dig, 30+i, p, NULL);
00692                     /*@switchbreak@*/ break;
00693                 case 1:         /* e */
00694                     (void) pgpImplMpiItem(pgpPublicRSA[i], dig, 30+i, p, NULL);
00695                     /*@switchbreak@*/ break;
00696                 default:
00697                     /*@switchbreak@*/ break;
00698                 }
00699             }
00700             pgpPrtStr("", pgpPublicRSA[i]);
00701         } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
00702             if (i >= 4) break;
00703             if (dig) {
00704                 switch (i) {
00705                 case 0:         /* p */
00706                     (void) pgpImplMpiItem(pgpPublicDSA[i], dig, 40+i, p, NULL);
00707                     /*@switchbreak@*/ break;
00708                 case 1:         /* q */
00709                     (void) pgpImplMpiItem(pgpPublicDSA[i], dig, 40+i, p, NULL);
00710                     /*@switchbreak@*/ break;
00711                 case 2:         /* g */
00712                     (void) pgpImplMpiItem(pgpPublicDSA[i], dig, 40+i, p, NULL);
00713                     /*@switchbreak@*/ break;
00714                 case 3:         /* y */
00715                     (void) pgpImplMpiItem(pgpPublicDSA[i], dig, 40+i, p, NULL);
00716                     /*@switchbreak@*/ break;
00717                 default:
00718                     /*@switchbreak@*/ break;
00719                 }
00720             }
00721             pgpPrtStr("", pgpPublicDSA[i]);
00722         } else if (pubkey_algo == PGPPUBKEYALGO_ECDSA) {
00723             if (i >= 1) break;
00724             if (dig) {
00725                 switch (i) {
00726                 case 0:         /* curve & Q */
00727                     (void) pgpImplMpiItem(pgpPublicECDSA[i], dig, 60, p+1, p+1+p[0]);
00728                     (void) pgpImplMpiItem(pgpPublicECDSA[i], dig, 61, p+1+p[0], NULL);
00729                     /*@switchbreak@*/ break;
00730                 default:
00731                     /*@switchbreak@*/ break;
00732                 }
00733             }
00734             if (i == 0) {
00735                 pgpPrtHex(" Curve = [ OID]:", p+1, p[0]);
00736                 p += 1 + p[0];
00737                 pgpPrtNL();
00738             }
00739             pgpPrtStr("", pgpPublicECDSA[i]);
00740         } else if (pubkey_algo == PGPPUBKEYALGO_ELGAMAL_ENCRYPT) {
00741             if (i >= 3) break;
00742             pgpPrtStr("", pgpPublicELGAMAL[i]);
00743         } else {
00744             if (_pgp_print)
00745                 fprintf(stderr, "%7d", i);
00746         }
00747         pgpPrtStr("", pgpMpiStr(p));
00748         pgpPrtNL();
00749     }
00750 
00751     return p;
00752 }
00753 
00754 static const rpmuint8_t * pgpPrtSeckeyParams(const pgpPkt pp,
00755                 /*@unused@*/ rpmuint8_t pubkey_algo,
00756                 /*@returned@*/ const rpmuint8_t *p)
00757         /*@globals fileSystem @*/
00758         /*@modifies fileSystem @*/
00759 {
00760     int i;
00761 
00762     switch (*p) {
00763     case 0:
00764         pgpPrtVal(" ", pgpSymkeyTbl, *p);
00765         break;
00766     case 255:
00767         p++;
00768         pgpPrtVal(" ", pgpSymkeyTbl, *p);
00769         switch (p[1]) {
00770         case 0x00:
00771             pgpPrtVal(" simple ", pgpHashTbl, p[2]);
00772             p += 2;
00773             /*@innerbreak@*/ break;
00774         case 0x01:
00775             pgpPrtVal(" salted ", pgpHashTbl, p[2]);
00776             pgpPrtHex("", p+3, 8);
00777             p += 10;
00778             /*@innerbreak@*/ break;
00779         case 0x03:
00780             pgpPrtVal(" iterated/salted ", pgpHashTbl, p[2]);
00781             i = (16 + ((unsigned)p[11] & 0xf)) << (((unsigned)p[11] >> 4U) + 6);
00782             pgpPrtHex("", p+3, 8);
00783             pgpPrtInt(" iter", i);
00784             p += 11;
00785             /*@innerbreak@*/ break;
00786         }
00787         break;
00788     default:
00789         pgpPrtVal(" ", pgpSymkeyTbl, *p);
00790         pgpPrtHex(" IV", p+1, 8);
00791         p += 8;
00792         break;
00793     }
00794     pgpPrtNL();
00795 
00796     p++;
00797 
00798 #ifdef  NOTYET  /* XXX encrypted MPI's need to be handled. */
00799     for (i = 0; p < &pp->u.h[pp->hlen]; i++, p += pgpMpiLen(p)) {
00800         if (pubkey_algo == PGPPUBKEYALGO_RSA) {
00801             if (pgpSecretRSA[i] == NULL) break;
00802             pgpPrtStr("", pgpSecretRSA[i]);
00803         } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
00804             if (pgpSecretDSA[i] == NULL) break;
00805             pgpPrtStr("", pgpSecretDSA[i]);
00806         } else if (pubkey_algo == PGPPUBKEYALGO_ECDSA) {
00807             if (pgpSecretECDSA[i] == NULL) break;
00808             pgpPrtStr("", pgpSecretECDSA[i]);
00809         } else if (pubkey_algo == PGPPUBKEYALGO_ELGAMAL_ENCRYPT) {
00810             if (pgpSecretELGAMAL[i] == NULL) break;
00811             pgpPrtStr("", pgpSecretELGAMAL[i]);
00812         } else {
00813             if (_pgp_print)
00814                 fprintf(stderr, "%7d", i);
00815         }
00816         pgpPrtStr("", pgpMpiStr(p));
00817         pgpPrtNL();
00818     }
00819 #else
00820     pgpPrtHex(" secret", p, (pp->hlen - (p - pp->u.h) - 2));
00821     pgpPrtNL();
00822     p += (pp->hlen - (p - pp->u.h) - 2);
00823 #endif
00824     pgpPrtHex(" checksum", p, 2);
00825     pgpPrtNL();
00826 
00827     return p;
00828 }
00829 
00830 int pgpPrtKey(const pgpPkt pp)
00831         /*@globals _digp @*/
00832         /*@modifies *_digp @*/
00833 {
00834     rpmuint8_t version = pp->u.h[0];
00835     const rpmuint8_t * p;
00836     unsigned plen;
00837     time_t t;
00838     int rc;
00839 
00840     switch (version) {
00841     case 3:
00842     {   pgpPktKeyV3 v = (pgpPktKeyV3)pp->u.h;
00843         pgpPrtVal("V3 ", pgpTagTbl, (rpmuint8_t)pp->tag);
00844         pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
00845         t = pgpGrab(v->time, sizeof(v->time));
00846         if (_pgp_print)
00847             fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
00848         plen = pgpGrab(v->valid, sizeof(v->valid));
00849         if (plen != 0)
00850             fprintf(stderr, " valid %u days", plen);
00851         pgpPrtNL();
00852 
00853         if (_digp && _digp->tag == (rpmuint8_t)pp->tag) {
00854             _digp->version = v->version;
00855             memcpy(_digp->time, v->time, sizeof(_digp->time));
00856             _digp->pubkey_algo = v->pubkey_algo;
00857         }
00858 
00859         p = ((rpmuint8_t *)v) + sizeof(*v);
00860         p = pgpPrtPubkeyParams(_dig, pp, (pgpPubkeyAlgo)v->pubkey_algo, p);
00861         rc = 0;
00862     }   break;
00863     case 4:
00864     {   pgpPktKeyV4 v = (pgpPktKeyV4)pp->u.h;
00865         pgpPrtVal("V4 ", pgpTagTbl, (rpmuint8_t)pp->tag);
00866         pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
00867         t = pgpGrab(v->time, sizeof(v->time));
00868         if (_pgp_print)
00869             fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
00870         pgpPrtNL();
00871 
00872         if (_digp && _digp->tag == (rpmuint8_t)pp->tag) {
00873             _digp->version = v->version;
00874             memcpy(_digp->time, v->time, sizeof(_digp->time));
00875             _digp->pubkey_algo = v->pubkey_algo;
00876         }
00877 
00878         p = ((rpmuint8_t *)v) + sizeof(*v);
00879         p = pgpPrtPubkeyParams(_dig, pp, (pgpPubkeyAlgo)v->pubkey_algo, p);
00880         if (!(pp->tag == PGPTAG_PUBLIC_KEY || pp->tag == PGPTAG_PUBLIC_SUBKEY))
00881             p = pgpPrtSeckeyParams(pp, v->pubkey_algo, p);
00882         rc = 0;
00883     }   break;
00884     default:
00885         rc = 1;
00886         break;
00887     }
00888     return rc;
00889 }
00890 
00891 int pgpPrtUserID(const pgpPkt pp)
00892         /*@globals _digp @*/
00893         /*@modifies *_digp @*/
00894 {
00895     pgpPrtVal("", pgpTagTbl, (rpmuint8_t)pp->tag);
00896     if (_pgp_print)
00897         fprintf(stderr, " \"%.*s\"", (int)pp->hlen, (const char *)pp->u.h);
00898     pgpPrtNL();
00899     if (_digp) {
00900         char * t = memcpy(xmalloc(pp->hlen+1), pp->u.h, pp->hlen);
00901         t[pp->hlen] = '\0';
00902         _digp->userid = _free(_digp->userid);
00903         _digp->userid = t;
00904     }
00905     return 0;
00906 }
00907 
00908 int pgpPrtComment(const pgpPkt pp)
00909 {
00910     const rpmuint8_t * h = pp->u.h;
00911     int i = pp->hlen;
00912 
00913     pgpPrtVal("", pgpTagTbl, (rpmuint8_t)pp->tag);
00914     if (_pgp_print)
00915         fprintf(stderr, " ");
00916     while (i > 0) {
00917         int j;
00918         if (*h >= (rpmuint8_t)' ' && *h <= (rpmuint8_t)'z') {
00919             j = 0;
00920             while (j < i && h[j] != (rpmuint8_t)'\0')
00921                 j++;
00922             while (j < i && h[j] == (rpmuint8_t)'\0')
00923                 j++;
00924             if (_pgp_print && j)
00925                 fprintf(stderr, "%.*s", (int)strlen((const char *)h), (const char *)h);
00926         } else {
00927             pgpPrtHex("", h, i);
00928             j = i;
00929         }
00930         i -= j;
00931         h += j;
00932     }
00933     pgpPrtNL();
00934     return 0;
00935 }
00936 
00937 int pgpPktLen(const rpmuint8_t *pkt, size_t pleft, pgpPkt pp)
00938 {
00939     unsigned int val = (unsigned int)*pkt;
00940     unsigned int plen;
00941 
00942     memset(pp, 0, sizeof(*pp));
00943     /* XXX can't deal with these. */
00944     if (!(val & 0x80))
00945         return -1;
00946 
00947     if (val & 0x40) {
00948         pp->tag = (val & 0x3f);
00949         plen = pgpLen(pkt+1, &pp->hlen);
00950     } else {
00951         pp->tag = (val >> 2) & 0xf;
00952         plen = (1 << (val & 0x3));
00953         pp->hlen = pgpGrab(pkt+1, plen);
00954     }
00955 
00956     pp->pktlen = 1 + plen + pp->hlen;
00957     if (pleft > 0 && pp->pktlen > (unsigned)pleft)
00958         return -1;
00959 
00960 /*@-assignexpose -temptrans @*/
00961     pp->u.h = pkt + 1 + plen;
00962 /*@=assignexpose =temptrans @*/
00963 
00964     return pp->pktlen;
00965 }
00966 
00967 int pgpPubkeyFingerprint(const rpmuint8_t * pkt, size_t pktlen, rpmuint8_t * keyid)
00968 {
00969     pgpPkt pp = alloca(sizeof(*pp));
00970     int rc = pgpPktLen(pkt, pktlen, pp);
00971     const rpmuint8_t * se;
00972     int i;
00973 
00974     if (!(pp->tag == PGPTAG_PUBLIC_KEY || pp->tag == PGPTAG_PUBLIC_SUBKEY))
00975         return -1;
00976 
00977     /* Choose the correct keyid. */
00978     switch (pp->u.h[0]) {
00979     default:    return -1;
00980     case 3:
00981       { pgpPktKeyV3 v = (pgpPktKeyV3) (pp->u.h);
00982         se = (rpmuint8_t *)(v + 1);
00983         switch (v->pubkey_algo) {
00984         default:        return -1;
00985         case PGPPUBKEYALGO_RSA:
00986             se += pgpMpiLen(se);
00987             memmove(keyid, (se-8), 8);
00988             /*@innerbreak@*/ break;
00989         }
00990       } break;
00991     case 4:
00992       { pgpPktKeyV4 v = (pgpPktKeyV4) (pp->u.h);
00993         rpmuint8_t * d = NULL;
00994         size_t dlen = 0;
00995 
00996         se = (rpmuint8_t *)(v + 1);
00997         switch (v->pubkey_algo) {
00998         default:        return -1;
00999         case PGPPUBKEYALGO_RSA:
01000             for (i = 0; i < 2; i++)
01001                 se += pgpMpiLen(se);
01002             /*@innerbreak@*/ break;
01003         case PGPPUBKEYALGO_DSA:
01004             for (i = 0; i < 4; i++)
01005                 se += pgpMpiLen(se);
01006             /*@innerbreak@*/ break;
01007         case PGPPUBKEYALGO_ECDSA:
01008             se += 1 + se[0];
01009             for (i = 0; i < 1; i++)
01010                 se += pgpMpiLen(se);
01011             /*@innerbreak@*/ break;
01012         }
01013         {   DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
01014             (void) rpmDigestUpdate(ctx, pkt, (se-pkt));
01015             (void) rpmDigestFinal(ctx, &d, &dlen, 0);
01016         }
01017 
01018         memmove(keyid, (d + (dlen-8)), 8);
01019         d = _free(d);
01020       } break;
01021     }
01022     rc = 0;
01023     return rc;
01024 }
01025 
01026 int pgpExtractPubkeyFingerprint(const char * b64pkt, rpmuint8_t * keyid)
01027 {
01028     const rpmuint8_t * pkt;
01029     size_t pktlen;
01030 
01031     if (b64decode(b64pkt, (void *)&pkt, &pktlen))
01032         return -1;      /* on error */
01033     (void) pgpPubkeyFingerprint(pkt, (unsigned int)pktlen, keyid);
01034     pkt = _free(pkt);
01035     return 8;   /* no. of bytes of pubkey signid */
01036 }
01037 
01038 int pgpPrtPkt(const rpmuint8_t * pkt, size_t pleft)
01039 {
01040     pgpPkt pp = alloca(sizeof(*pp));
01041     int rc = pgpPktLen(pkt, pleft, pp);
01042 
01043     if (rc < 0)
01044         return rc;
01045 
01046     switch (pp->tag) {
01047     case PGPTAG_SIGNATURE:
01048         rc = pgpPrtSig(pp);
01049         break;
01050     case PGPTAG_PUBLIC_KEY:
01051         /* Get the public key fingerprint. */
01052         if (_digp) {
01053 /*@-mods@*/
01054             if (!pgpPubkeyFingerprint(pkt, pp->pktlen, _digp->signid))
01055                 _digp->saved |= PGPDIG_SAVED_ID;
01056             else
01057                 memset(_digp->signid, 0, sizeof(_digp->signid));
01058 /*@=mods@*/
01059         }
01060         /*@fallthrough@*/
01061     case PGPTAG_PUBLIC_SUBKEY:
01062         rc = pgpPrtKey(pp);
01063         break;
01064     case PGPTAG_SECRET_KEY:
01065     case PGPTAG_SECRET_SUBKEY:
01066         rc = pgpPrtKey(pp);
01067         break;
01068     case PGPTAG_USER_ID:
01069         rc = pgpPrtUserID(pp);
01070         break;
01071     case PGPTAG_COMMENT:
01072     case PGPTAG_COMMENT_OLD:
01073         rc = pgpPrtComment(pp);
01074         break;
01075 
01076     case PGPTAG_RESERVED:
01077     case PGPTAG_PUBLIC_SESSION_KEY:
01078     case PGPTAG_SYMMETRIC_SESSION_KEY:
01079     case PGPTAG_COMPRESSED_DATA:
01080     case PGPTAG_SYMMETRIC_DATA:
01081     case PGPTAG_MARKER:
01082     case PGPTAG_LITERAL_DATA:
01083     case PGPTAG_TRUST:
01084     case PGPTAG_PHOTOID:
01085     case PGPTAG_ENCRYPTED_MDC:
01086     case PGPTAG_MDC:
01087     case PGPTAG_PRIVATE_60:
01088     case PGPTAG_PRIVATE_62:
01089     case PGPTAG_CONTROL:
01090     default:
01091         pgpPrtVal("", pgpTagTbl, (rpmuint8_t)pp->tag);
01092         pgpPrtHex("", pp->u.h, pp->hlen);
01093         pgpPrtNL();
01094         rc = 0;
01095         break;
01096     }
01097 
01098     return (rc ? -1 : (int)pp->pktlen);
01099 }
01100 
01101 /*@unchecked@*/
01102 pgpVSFlags pgpDigVSFlags;
01103 
01104 void pgpDigClean(pgpDig dig)
01105 {
01106     if (dig != NULL) {
01107         dig->signature.userid = _free(dig->signature.userid);
01108         dig->pubkey.userid = _free(dig->pubkey.userid);
01109         dig->pubkey_algoN = NULL;
01110         dig->hash_algoN = NULL;
01111         memset(&dig->dops, 0, sizeof(dig->dops));
01112         memset(&dig->sops, 0, sizeof(dig->sops));
01113         dig->ppkts = _free(dig->ppkts);
01114         dig->npkts = 0;
01115         dig->signature.hash = NULL;
01116         dig->signature.hashlen = 0;
01117         dig->pubkey.hash = NULL;
01118         dig->pubkey.hashlen = 0;
01119 
01120         memset(&dig->signature, 0, sizeof(dig->signature));
01121         memset(&dig->pubkey, 0, sizeof(dig->pubkey));
01122 
01123         dig->md5 = _free(dig->md5);
01124         dig->md5len = 0;
01125         dig->sha1 = _free(dig->sha1);
01126         dig->sha1len = 0;
01127 
01128         pgpImplClean(dig->impl);
01129 
01130     }
01131 /*@-nullstate@*/
01132     return;
01133 /*@=nullstate@*/
01134 }
01135 
01136 static void pgpDigFini(void * __dig)
01137         /*@globals fileSystem, internalState @*/
01138         /*@modifies __dig, fileSystem, internalState @*/
01139 {
01140     pgpDig dig = __dig;
01141 
01142     dig->sig = _free(dig->sig);
01143     dig->siglen = 0;
01144     dig->pub = _free(dig->pub);
01145     dig->publen = 0;
01146 
01147     /* XXX there's a recursion here ... release and reacquire the lock */
01148 #ifndef BUGGY
01149     yarnRelease(dig->_item.use);
01150 #endif
01151     /* Dump the signature/pubkey data. */
01152     pgpDigClean(dig);
01153 #ifndef BUGGY
01154     yarnPossess(dig->_item.use);
01155 #endif
01156 
01157     if (dig->hdrctx != NULL)
01158         (void) rpmDigestFinal(dig->hdrctx, NULL, NULL, 0);
01159     dig->hdrctx = NULL;
01160 
01161     if (dig->hdrsha1ctx != NULL)
01162         (void) rpmDigestFinal(dig->hdrsha1ctx, NULL, NULL, 0);
01163     dig->hdrsha1ctx = NULL;
01164 
01165     if (dig->sha1ctx != NULL)
01166         (void) rpmDigestFinal(dig->sha1ctx, NULL, NULL, 0);
01167     dig->sha1ctx = NULL;
01168 
01169 #ifdef  NOTYET
01170     if (dig->hdrmd5ctx != NULL)
01171         (void) rpmDigestFinal(dig->hdrmd5ctx, NULL, NULL, 0);
01172     dig->hdrmd5ctx = NULL;
01173 #endif
01174 
01175     if (dig->md5ctx != NULL)
01176         (void) rpmDigestFinal(dig->md5ctx, NULL, NULL, 0);
01177     dig->md5ctx = NULL;
01178 
01179     dig->impl = pgpImplFree(dig->impl);
01180 
01181 }
01182 
01183 /*@unchecked@*/ /*@only@*/ /*@null@*/
01184 rpmioPool _digPool;
01185 
01186 static pgpDig digGetPool(/*@null@*/ rpmioPool pool)
01187         /*@globals _digPool, fileSystem @*/
01188         /*@modifies pool, _digPool, fileSystem @*/
01189 {
01190     pgpDig dig;
01191 
01192     if (_digPool == NULL) {
01193         _digPool = rpmioNewPool("dig", sizeof(*dig), -1, _pgp_debug,
01194                         NULL, NULL, pgpDigFini);
01195         pool = _digPool;
01196     }
01197     
01198     dig = (pgpDig) rpmioGetPool(pool, sizeof(*dig));
01199     memset(((char *)dig)+sizeof(dig->_item), 0, sizeof(*dig)-sizeof(dig->_item));
01200     return dig;
01201 }
01202 
01203 pgpDig pgpDigNew(pgpVSFlags vsflags, pgpPubkeyAlgo pubkey_algo)
01204 {
01205     pgpDig dig = pgpDigLink( digGetPool(_digPool) );
01206     pgpDigParams pubp = pgpGetPubkey(dig);
01207 
01208     /* XXX FIXME: always set default flags, ignore the arg. */
01209     dig->vsflags = (vsflags != RPMVSF_DEFAULT ? vsflags : pgpDigVSFlags);
01210     dig->impl = pgpImplInit();
01211     /* XXX FIXME: always set default pubkey_algo, ignore the arg. */
01212     pubp->pubkey_algo = pubkey_algo;
01213 
01214     if (pubp->pubkey_algo) {
01215         int xx = pgpImplGenerate(dig);
01216 assert(xx == 1);
01217         /* XXX FIXME: limited to DSA from BeeCrypt for now. */
01218         if (pgpImplVecs == &rpmbcImplVecs)
01219             xx = rpmbcExportPubkey(dig);
01220     }
01221     return dig;
01222 }
01223 
01224 pgpDigParams pgpGetSignature(pgpDig dig)
01225 {
01226     return (dig ? &dig->signature : NULL);
01227 }
01228 
01229 pgpDigParams pgpGetPubkey(pgpDig dig)
01230 {
01231     return (dig ? &dig->pubkey : NULL);
01232 }
01233 
01234 rpmuint32_t pgpGetSigtag(pgpDig dig)
01235 {
01236     return (dig ? dig->sigtag : 0);
01237 }
01238 
01239 rpmuint32_t pgpGetSigtype(pgpDig dig)
01240 {
01241     return (dig ? dig->sigtype : 0);
01242 }
01243 
01244 const void * pgpGetSig(pgpDig dig)
01245 {
01246     return (dig ? dig->sig : NULL);
01247 }
01248 
01249 rpmuint32_t pgpGetSiglen(pgpDig dig)
01250 {
01251     return (dig ? dig->siglen : 0);
01252 }
01253 
01254 int pgpSetSig(pgpDig dig,
01255         rpmuint32_t sigtag, rpmuint32_t sigtype, const void * sig, rpmuint32_t siglen)
01256 {
01257     if (dig != NULL) {
01258         dig->sigtag = sigtag;
01259         dig->sigtype = (sig ? sigtype : 0);
01260 /*@-assignexpose -kepttrans@*/
01261         dig->sig = sig;
01262 /*@=assignexpose =kepttrans@*/
01263         dig->siglen = siglen;
01264     }
01265     return 0;
01266 }
01267 
01268 void * pgpStatsAccumulator(pgpDig dig, int opx)
01269 {
01270     void * sw = NULL;
01271     switch (opx) {
01272     case 10:    /* RPMTS_OP_DIGEST */
01273         sw = &dig->dops;
01274         break;
01275     case 11:    /* RPMTS_OP_SIGNATURE */
01276         sw = &dig->sops;
01277         break;
01278     }
01279     return sw;
01280 }
01281 
01282 int pgpSetFindPubkey(pgpDig dig,
01283                 int (*findPubkey) (void *ts, /*@null@*/ void *dig), void * _ts)
01284 {
01285     if (dig) {
01286 /*@-assignexpose@*/
01287         dig->findPubkey = findPubkey;
01288 /*@=assignexpose@*/
01289 /*@-dependenttrans@*/
01290         dig->_ts = _ts;
01291 /*@=dependenttrans@*/
01292     }
01293     return 0;
01294 }
01295 
01296 int pgpFindPubkey(pgpDig dig)
01297 {
01298     int rc = 1; /* XXX RPMRC_NOTFOUND */
01299     if (dig && dig->findPubkey && dig->_ts)
01300         rc = (*dig->findPubkey) (dig->_ts, dig);
01301     return rc;
01302 }
01303 
01304 int pgpGrabPkts(const rpmuint8_t * pkts, size_t pktlen,
01305                 /*@out@*/ rpmuint8_t *** pppkts, /*@out@*/ int * pnpkts)
01306         /*@modifies *pppkts, *pnpkts @*/
01307 {
01308     pgpPkt pp = alloca(sizeof(*pp));
01309     const rpmuint8_t * p;
01310     size_t pleft;
01311     size_t len;
01312     int npkts = 0;
01313     rpmuint8_t ** ppkts;
01314 
01315     for (p = pkts, pleft = pktlen; p < (pkts + pktlen); p += len, pleft -= len) {
01316         if (pgpPktLen(p, pleft, pp) < 0)
01317             return -1;
01318         len = pp->pktlen;
01319         npkts++;
01320     }
01321     if (npkts <= 0)
01322         return -2;
01323 
01324     ppkts = xcalloc(npkts+1, sizeof(*ppkts));
01325 
01326     npkts = 0;
01327     for (p = pkts, pleft = pktlen; p < (pkts + pktlen); p += len, pleft -= len) {
01328   
01329         if (pgpPktLen(p, pleft, pp) < 0)
01330             return -1;
01331         len = pp->pktlen;
01332         ppkts[npkts++] = (rpmuint8_t *) p;
01333     }
01334     ppkts[npkts] = NULL;
01335 
01336     if (pppkts != NULL)
01337         *pppkts = ppkts;
01338    else
01339         ppkts = _free(ppkts);
01340 
01341     if (pnpkts != NULL)
01342         *pnpkts = npkts;
01343 
01344     return 0;
01345 }
01346 
01347 /*@-globstate -incondefs -nullderef @*/ /* _dig annotations are not correct. */
01348 int pgpPrtPkts(const rpmuint8_t * pkts, size_t pktlen, pgpDig dig, int printing)
01349         /*@globals _dig, _digp, _pgp_print @*/
01350         /*@modifies _dig, _digp, *_digp, _pgp_print @*/
01351 {
01352     pgpPkt pp = alloca(sizeof(*pp));
01353     unsigned int val = (unsigned int)*pkts;
01354     size_t pleft;
01355     int len;
01356     rpmuint8_t ** ppkts = NULL;
01357     int npkts;
01358     int i;
01359 
01360     _pgp_print = printing;
01361     _dig = pgpDigLink(dig);
01362     if (dig != NULL && (val & 0x80)) {
01363         pgpTag tag = (val & 0x40) ? (val & 0x3f) : ((val >> 2) & 0xf);
01364         _digp = (tag == PGPTAG_SIGNATURE) ? &_dig->signature : &_dig->pubkey;
01365         _digp->tag = (rpmuint8_t)tag;
01366     } else
01367         _digp = NULL;
01368 
01369     if (pgpGrabPkts(pkts, pktlen, &ppkts, &npkts) || ppkts == NULL) {
01370         _dig = pgpDigFree(_dig);
01371         return -1;
01372     }
01373 
01374     if (ppkts != NULL)
01375     for (i = 0, pleft = pktlen; i < npkts; i++, pleft -= len) {
01376         len = pgpPktLen(ppkts[i], pleft, pp);
01377         len = pgpPrtPkt(ppkts[i], pp->pktlen);
01378     }
01379 
01380     if (dig != NULL) {
01381         dig->ppkts = _free(dig->ppkts);         /* XXX memory leak plugged. */
01382         dig->ppkts = ppkts;
01383         dig->npkts = npkts;
01384     } else
01385         ppkts = _free(ppkts);
01386 
01387     (void) pgpDigFree(_dig);
01388     _dig = NULL;
01389 
01390     return 0;
01391 }
01392 /*@=globstate =incondefs =nullderef @*/
01393 
01394 pgpArmor pgpArmorUnwrap(rpmiob iob, rpmuint8_t ** pkt, size_t * pktlen)
01395 {
01396     const char * enc = NULL;
01397     const char * crcenc = NULL;
01398     rpmuint8_t * dec;
01399     rpmuint8_t * crcdec;
01400     size_t declen;
01401     size_t crclen;
01402     rpmuint32_t crcpkt, crc;
01403     const char * armortype = NULL;
01404     char * t, * te;
01405     int pstate = 0;
01406     pgpArmor ec = PGPARMOR_ERR_NO_BEGIN_PGP;    /* XXX assume failure */
01407     pgpTag tag = 0;
01408     int rc;
01409 
01410     if (iob == NULL)
01411         goto exit;
01412 
01413     /* Read unarmored packets. */
01414     if (pgpIsPkt(iob->b, &tag)) {
01415         switch (tag) {
01416         default:                ec = PGPARMOR_NONE;     break;
01417         case PGPTAG_PUBLIC_KEY: ec = PGPARMOR_PUBKEY;   break;
01418         case PGPTAG_SIGNATURE:  ec = PGPARMOR_SIGNATURE;        break;
01419 #ifdef  NOTYET
01420         case PGPTAG_SECRET_KEY: ec = PGPARMOR_SECKEY;   break;
01421         case PGPTAG_FOO:        ec = PGPARMOR_MESSAGE;  break;
01422         case PGPTAG_FOO:        ec = PGPARMOR_SIGNED_MESSAGE;   break;
01423         case PGPTAG_FOO:        ec = PGPARMOR_FILE;     break;
01424         case PGPTAG_FOO:        ec = PGPARMOR_PRIVKEY;  break;
01425 #endif
01426         }
01427         /* Truncate blen to actual no. of octets in packet. */
01428         if (ec != PGPARMOR_NONE) {
01429             pgpPkt pp = alloca(sizeof(*pp));
01430             iob->blen = pgpPktLen(iob->b, iob->blen, pp);
01431         }
01432         goto exit;
01433     }
01434 
01435 #define TOKEQ(_s, _tok) (!strncmp((_s), (_tok), sizeof(_tok)-1))
01436 
01437     /* Read armored packets, converting to binary. */
01438     for (t = (char *)iob->b; t && *t; t = te) {
01439         if ((te = strchr(t, '\n')) == NULL)
01440             te = t + strlen(t);
01441         else
01442             te++;
01443 
01444         switch (pstate) {
01445         case 0:
01446             armortype = NULL;
01447             if (!TOKEQ(t, "-----BEGIN PGP "))
01448                 continue;
01449             t += sizeof("-----BEGIN PGP ")-1;
01450 
01451             rc = pgpValTok(pgpArmorTbl, t, te);
01452             if (rc < 0) {
01453                 ec = PGPARMOR_ERR_UNKNOWN_ARMOR_TYPE;
01454                 goto exit;
01455             }
01456             /* XXX Ignore clear signed message start. */
01457             if (rc == PGPARMOR_SIGNED_MESSAGE)
01458                 continue;
01459             ec = rc;    /* Save the packet type as exit code. */
01460             armortype = t;
01461 
01462             t = strchr(t, '\n');
01463             if (t == NULL)
01464                 continue;
01465             if (t[-1] == '\r')
01466                 --t;
01467             t -= (sizeof("-----")-1);
01468             if (!TOKEQ(t, "-----"))
01469                 continue;
01470             *t = '\0';
01471             pstate++;
01472             /*@switchbreak@*/ break;
01473         case 1:
01474             enc = NULL;
01475             rc = pgpValTok(pgpArmorKeyTbl, t, te);
01476             if (rc >= 0)
01477                 continue;
01478             if (!(*t == '\n' || *t == '\r')) {
01479                 pstate = 0;
01480                 continue;
01481             }
01482             enc = te;           /* Start of encoded packets */
01483             pstate++;
01484             /*@switchbreak@*/ break;
01485         case 2:
01486             crcenc = NULL;
01487             if (*t != '=')
01488                 continue;
01489             *t++ = '\0';        /* Terminate encoded packets */
01490             crcenc = t;         /* Start of encoded crc */
01491             pstate++;
01492             /*@switchbreak@*/ break;
01493         case 3:
01494             pstate = 0;
01495             if (!TOKEQ(t, "-----END PGP ")) {
01496                 ec = PGPARMOR_ERR_NO_END_PGP;
01497                 goto exit;
01498             }
01499             *t = '\0';          /* Terminate encoded crc */
01500             t += sizeof("-----END PGP ")-1;
01501             if (t >= te) continue;
01502 
01503             if (armortype == NULL) /* XXX can't happen */
01504                 continue;
01505             rc = strncmp(t, armortype, strlen(armortype));
01506             if (rc)
01507                 continue;
01508 
01509             t += strlen(armortype);
01510             if (t >= te) continue;
01511 
01512             if (!TOKEQ(t, "-----")) {
01513                 ec = PGPARMOR_ERR_NO_END_PGP;
01514                 goto exit;
01515             }
01516             t += (sizeof("-----")-1);
01517             if (t >= te) continue;
01518             /* XXX permitting \r here is not RFC-2440 compliant <shrug> */
01519             if (!(*t == '\n' || *t == '\r')) continue;
01520 
01521             crcdec = NULL;
01522             crclen = 0;
01523             if (b64decode(crcenc, (void *)&crcdec, &crclen) != 0) {
01524                 ec = PGPARMOR_ERR_CRC_DECODE;
01525                 goto exit;
01526             }
01527             crcpkt = pgpGrab(crcdec, crclen);
01528             crcdec = _free(crcdec);
01529             dec = NULL;
01530             declen = 0;
01531             if (b64decode(enc, (void *)&dec, &declen) != 0) {
01532                 ec = PGPARMOR_ERR_BODY_DECODE;
01533                 goto exit;
01534             }
01535             crc = pgpCRC(dec, declen);
01536             if (crcpkt != crc) {
01537                 ec = PGPARMOR_ERR_CRC_CHECK;
01538                 goto exit;
01539             }
01540             iob->b = _free(iob->b);
01541             iob->b = dec;
01542             iob->blen = declen;
01543             goto exit;
01544             /*@notreached@*/ /*@switchbreak@*/ break;
01545         }
01546     }
01547     ec = PGPARMOR_NONE;
01548 
01549 exit:
01550     if (ec > PGPARMOR_NONE) {
01551         if (pkt)        *pkt = iob->b;
01552         if (pktlen)     *pktlen = iob->blen;
01553         iob->b = NULL;  /* XXX iob->b has been stolen */
01554     } else {
01555         if (pkt)        *pkt = NULL;
01556         if (pktlen)     *pktlen = 0;
01557     }
01558     return ec;
01559 }
01560 
01561 pgpArmor pgpReadPkts(const char * fn, rpmuint8_t ** pkt, size_t * pktlen)
01562 {
01563     rpmiob iob = NULL;
01564     pgpArmor ec = !rpmiobSlurp(fn, &iob)
01565         ? pgpArmorUnwrap(iob, pkt, pktlen)
01566         : PGPARMOR_ERR_NO_BEGIN_PGP;
01567     iob = rpmiobFree(iob);
01568     return ec;
01569 }
01570 
01571 char * pgpArmorWrap(rpmuint8_t atype, const unsigned char * s, size_t ns)
01572 {
01573     const char * enc;
01574     char * t;
01575     size_t nt;
01576     char * val;
01577     int lc;
01578 
01579     nt = ((ns + 2) / 3) * 4;
01580     /*@-globs@*/
01581     /* Add additional bytes necessary for eol string(s). */
01582     if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) {
01583         lc = (nt + b64encode_chars_per_line - 1) / b64encode_chars_per_line;
01584        if (((nt + b64encode_chars_per_line - 1) % b64encode_chars_per_line) != 0)
01585         ++lc;
01586         nt += lc * strlen(b64encode_eolstr);
01587     }
01588     /*@=globs@*/
01589 
01590     nt += 512;  /* XXX slop for armor and crc */
01591 
01592     val = t = xmalloc(nt + 1);
01593     *t = '\0';
01594     t = stpcpy(t, "-----BEGIN PGP ");
01595     t = stpcpy(t, pgpValStr(pgpArmorTbl, atype));
01596     /*@-globs@*/
01597     t = stpcpy( stpcpy(t, "-----\nVersion: RPM "), VERSION);
01598     /*@=globs@*/
01599     t = stpcpy(t, " (BeeCrypt)\n\n");
01600 
01601     if ((enc = b64encode(s, ns)) != NULL) {
01602         t = stpcpy(t, enc);
01603         enc = _free(enc);
01604         if ((enc = b64crc(s, ns)) != NULL) {
01605             *t++ = '=';
01606             t = stpcpy(t, enc);
01607             enc = _free(enc);
01608         }
01609     }
01610         
01611     t = stpcpy(t, "-----END PGP ");
01612     t = stpcpy(t, pgpValStr(pgpArmorTbl, atype));
01613     t = stpcpy(t, "-----\n");
01614 
01615 /*@-globstate@*/        /* XXX b64encode_eolstr needs annotation. */
01616     return val;
01617 /*@=globstate@*/
01618 }
01619 
01620 pgpHashAlgo pgpHashAlgoStringToNumber(const char *name, size_t name_len)
01621 {
01622     size_t i;
01623 
01624     if (name == NULL)
01625         return -1;
01626     if (name_len == 0)
01627         name_len = strlen(name);
01628     for (i = 0; i < sizeof(pgpHashTbl)/sizeof(pgpHashTbl[0]); i++)
01629         if (xstrncasecmp(name, pgpHashTbl[i].str, name_len) == 0)
01630             return pgpHashTbl[i].val;
01631     return PGPHASHALGO_ERROR;
01632 }
01633