- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

# rpmio/rpmpgp.c

Go to the documentation of this file.

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