static int rpmcdsaVerify(pgpDig dig) { int rc = 0; /* assume failure */ pgpDigParams pubp = pgpGetPubkey(dig); pgpDigParams sigp = pgpGetSignature(dig); dig->pubkey_algoN = rpmcdsaPubkeyAlgo2Name(pubp->pubkey_algo); dig->hash_algoN = rpmcdsaHashAlgo2Name(sigp->hash_algo); switch (pubp->pubkey_algo) { default: break; case PGPPUBKEYALGO_RSA: rc = rpmcdsaVerifyRSA(dig); break; case PGPPUBKEYALGO_DSA: rc = rpmcdsaVerifyDSA(dig); break; case PGPPUBKEYALGO_ELGAMAL: #ifdef NOTYET rc = rpmcdsaVerifyELG(dig); #endif break; case PGPPUBKEYALGO_ECDSA: rc = rpmcdsaVerifyECDSA(dig); break; } SPEW(!rc, rc, dig); return rc; }
/** * Remember current key id. * @param dig container * @return 0 if new keyid, otherwise 1 */ static int pgpStashKeyid(pgpDig dig) /*@globals nextkeyid, nkeyids, keyids @*/ /*@modifies nextkeyid, nkeyids, keyids @*/ { pgpDigParams sigp = pgpGetSignature(dig); const void * sig = pgpGetSig(dig); unsigned int keyid; unsigned int i; if (sig == NULL || dig == NULL || sigp == NULL) return 0; keyid = pgpGrab(sigp->signid+4, 4); if (keyid == 0) return 0; if (keyids != NULL) for (i = 0; i < nkeyids; i++) { if (keyid == keyids[i]) return 1; } if (nkeyids < nkeyids_max) { nkeyids++; keyids = (unsigned int *) xrealloc(keyids, nkeyids * sizeof(*keyids)); } if (keyids) /* XXX can't happen */ keyids[nextkeyid] = keyid; nextkeyid++; nextkeyid %= nkeyids_max; return 0; }
rpmRC rpmnsProbeSignature(void * _ts, const char * fn, const char * sigfn, const char * pubfn, const char * pubid, /*@unused@*/ int flags) { rpmts ts = (rpmts) _ts; pgpDig dig = rpmtsDig(ts); pgpDigParams sigp = pgpGetSignature(dig); pgpDigParams pubp = pgpGetPubkey(dig); rpmuint8_t * sigpkt = NULL; size_t sigpktlen = 0; DIGEST_CTX ctx = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ int xx; rpmhkp hkp = NULL; pgpPkt pp = (pgpPkt) alloca(sizeof(*pp)); size_t pleft; int validate = 1; SPEW((stderr, "==> check(%s, %s, %s, %s)\n", fn, (sigfn ? sigfn : "(null)"), (pubfn ? pubfn : "(null)"), (pubid ? pubid : "(null)"))); /* Choose signature location: clearsign from fn if sigfn is NULL */ assert(fn && *fn); if (!(sigfn && *sigfn)) sigfn = fn; /* Load the signature from the file. */ { const char * _sigfn = rpmExpand(sigfn, NULL); xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen); if (xx != PGPARMOR_SIGNATURE) { SPEW((stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, (unsigned)sigpktlen, xx)); _sigfn = _free(_sigfn); goto exit; } _sigfn = _free(_sigfn); } pleft = sigpktlen; xx = pgpPktLen(sigpkt, pleft, pp); xx = rpmhkpLoadSignature(NULL, dig, pp); if (xx) goto exit; if (sigp->version != (rpmuint8_t)3 && sigp->version != (rpmuint8_t)4) { SPEW((stderr, "==> unverifiable V%u\n", (unsigned)sigp->version)); goto exit; } if (ts->hkp == NULL) ts->hkp = rpmhkpNew(NULL, 0); hkp = rpmhkpLink(ts->hkp); /* Load the pubkey. Use pubfn if specified, otherwise rpmdb keyring. */ if (pubfn && *pubfn) { const char * _pubfn = rpmExpand(pubfn, NULL); /*@-type@*/ hkp->pkt = _free(hkp->pkt); /* XXX memleaks */ hkp->pktlen = 0; xx = pgpReadPkts(_pubfn, &hkp->pkt, &hkp->pktlen); /*@=type@*/ if (xx != PGPARMOR_PUBKEY) { SPEW((stderr, "==> pgpReadPkts(%s) PUB %p[%u] rc %d\n", _pubfn, hkp->pkt, (unsigned)hkp->pktlen, xx)); _pubfn = _free(_pubfn); goto exit; } _pubfn = _free(_pubfn); /* Split the result into packet array. */ hkp->pkts = _free(hkp->pkts); /* XXX memleaks */ hkp->npkts = 0; xx = pgpGrabPkts(hkp->pkt, hkp->pktlen, &hkp->pkts, &hkp->npkts); #ifdef DYING _rpmhkpDumpDig(__FUNCTION__, dig, NULL); #endif if (!xx) (void) pgpPubkeyFingerprint(hkp->pkt, hkp->pktlen, hkp->keyid); memcpy(pubp->signid, hkp->keyid, sizeof(pubp->signid));/* XXX useless */ /* Validate pubkey self-signatures (if any). */ /* XXX TODO: only validate once, then cache using rpmku */ /* XXX need at least 3 packets to validate a pubkey */ if (validate && hkp->npkts >= 3) { #ifdef DYING pgpPrtPkts(hkp->pkt, hkp->pktlen, NULL, 1); #endif xx = rpmhkpValidate(hkp, NULL); switch (xx) { case RPMRC_OK: break; case RPMRC_NOTFOUND: case RPMRC_FAIL: /* XXX remap to NOTFOUND? */ case RPMRC_NOTTRUSTED: case RPMRC_NOKEY: default: SPEW((stderr, "\t<-- rpmhkpValidate() rc %d\n", xx)); rc = (rpmRC)xx; goto exit; } } /* Retrieve parameters from pubkey/subkey packet(s). */ xx = rpmhkpFindKey(hkp, dig, sigp->signid, sigp->pubkey_algo); if (xx) { SPEW((stderr, "\t<-- rpmhkpFindKey() rc %d\n", xx)); goto exit; } } else { rc = (rpmRC)pgpFindPubkey(dig); if (rc != RPMRC_OK) { SPEW((stderr, "\t<-- pgpFindPubkey() rc %d\n", rc)); goto exit; } } /* Is this the requested pubkey? */ if (pubid && *pubid) { size_t ns = strlen(pubid); const char * s; char * t; size_t i; /* At least 8 hex digits please. */ for (i = 0, s = pubid; *s && isxdigit(*s); s++, i++) {}; if (!(*s == '\0' && i > 8 && (i%2) == 0)) { SPEW((stderr, "==> invalid pubid: %s\n", pubid)); goto exit; } /* Truncate to key id size. */ s = pubid; if (ns > 16) { s += (ns - 16); ns = 16; } ns >>= 1; t = (char *) memset(alloca(ns), 0, ns); for (i = 0; i < ns; i++) t[i] = (char)((nibble(s[2*i]) << 4) | nibble(s[2*i+1])); /* Compare the pubkey id. */ s = (const char *)pubp->signid; xx = memcmp(t, s + (8 - ns), ns); #ifdef DYING /* XXX HACK: V4 RSA key id's are wonky atm. */ if (pubp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA) xx = 0; #endif if (xx) { SPEW((stderr, "==> mismatched: pubkey id (%08x %08x) != %s\n", pgpGrab(pubp->signid, 4), pgpGrab(pubp->signid+4, 4), pubid)); goto exit; } }
int main(int argc, char *argv[]) { pgpImplVecs_t * testImplVecs = &rpmnssImplVecs; pgpDig dig; pgpDigParams pubp; rpmbc bc; int printing = -1; int rc; pgpImplVecs = &rpmbcImplVecs; dig = pgpDigNew(RPMVSF_DEFAULT, 0); pubp = pgpGetPubkey(dig); bc = dig->impl; mpbzero(&bc->p); mpbsethex(&bc->p, fips_p); mpbzero(&bc->q); mpbsethex(&bc->q, fips_q); mpnzero(&bc->g); mpnsethex(&bc->g, fips_g); mpnzero(&bc->y); mpnsethex(&bc->y, fips_y); mpnzero(&bc->r); mpnsethex(&bc->r, fips_r); mpnzero(&bc->s); mpnsethex(&bc->s, fips_s); mpnzero(&bc->hm); mpnsethex(&bc->hm, fips_hm); pubp->pubkey_algo = PGPPUBKEYALGO_DSA; /* XXX assert? */ rc = pgpImplVerify(dig); fprintf(stderr, "=============================== DSA FIPS-186-1: rc %d\n", rc); dig = pgpDigFree(dig); pgpImplVecs = testImplVecs; dig = pgpDigNew(RPMVSF_DEFAULT, 0); pubp = pgpGetPubkey(dig); _pgp_debug = 1; _pgp_print = 1; fprintf(stderr, "=============================== DSA Public Key\n"); if ((rc = doit(DSApub, dig, printing)) != 0) fprintf(stderr, "==> FAILED: rc %d\n", rc); fprintf(stderr, "=============================== DSA Signature of \"%s\"\n", str); if ((rc = doit(DSAsig, dig, printing)) != 0) fprintf(stderr, "==> FAILED: rc %d\n", rc); { DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); pgpDigParams dsig = pgpGetSignature(dig); rpmDigestUpdate(ctx, str, strlen(str)); rpmDigestUpdate(ctx, dsig->hash, dsig->hashlen); (void) pgpImplSetDSA(ctx, dig, dsig); } pubp->pubkey_algo = PGPPUBKEYALGO_DSA; /* XXX assert? */ rc = pgpImplVerify(dig); fprintf(stderr, "=============================== DSA verify: rc %d\n", rc); dig = pgpDigFree(dig); pgpImplVecs = testImplVecs; dig = pgpDigNew(RPMVSF_DEFAULT, 0); pubp = pgpGetPubkey(dig); _pgp_debug = 1; _pgp_print = 1; fprintf(stderr, "=============================== RSA Public Key\n"); if ((rc = doit(RSApub, dig, printing)) != 0) fprintf(stderr, "==> FAILED: rc %d\n", rc); fprintf(stderr, "=============================== RSA Signature of \"%s\"\n", str); if ((rc = doit(RSAsig, dig, printing)) != 0) fprintf(stderr, "==> FAILED: rc %d\n", rc); { DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); pgpDigParams dsig = pgpGetSignature(dig); rpmDigestUpdate(ctx, str, strlen(str)); rpmDigestUpdate(ctx, dsig->hash, dsig->hashlen); (void) pgpImplSetRSA(ctx, dig, dsig); } pubp->pubkey_algo = PGPPUBKEYALGO_RSA; /* XXX assert? */ rc = pgpImplVerify(dig); fprintf(stderr, "=============================== RSA verify: rc %d\n", rc); dig = pgpDigFree(dig); pgpImplVecs = testImplVecs; dig = pgpDigNew(RPMVSF_DEFAULT, 0); pubp = pgpGetPubkey(dig); _pgp_debug = 1; _pgp_print = 1; fprintf(stderr, "=============================== ECDSA Public Key\n"); if ((rc = doit(ECDSApub, dig, printing)) != 0) fprintf(stderr, "==> FAILED: rc %d\n", rc); fprintf(stderr, "=============================== ECDSA Signature of \"%s\"\n", str); if ((rc = doit(ECDSAsig, dig, printing)) != 0) fprintf(stderr, "==> FAILED: rc %d\n", rc); { DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA256, RPMDIGEST_NONE); pgpDigParams dsig = pgpGetSignature(dig); rpmDigestUpdate(ctx, str, strlen(str)); rpmDigestUpdate(ctx, dsig->hash, dsig->hashlen); (void) pgpImplSetECDSA(ctx, dig, dsig); } pubp->pubkey_algo = PGPPUBKEYALGO_ECDSA; /* XXX assert? */ rc = pgpImplVerify(dig); fprintf(stderr, "=============================== ECDSA verify: rc %d\n", rc); dig = pgpDigFree(dig); if (pgpImplVecs == &rpmsslImplVecs) NSS_Shutdown(); return rc; }