rpm 5.2.1

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