RPM Package Manager, CVS Repository http://rpm5.org/cvs/ ____________________________________________________________________________
Server: rpm5.org Name: Jeff Johnson Root: /v/rpm/cvs Email: j...@rpm5.org Module: rpm Date: 07-Jun-2010 22:24:17 Branch: HEAD Handle: 2010060720241402 Modified files: rpm CHANGES rpm/rpmio rpmbc.c rpmbc.h rpm/tests tpgp.c Log: - tests: stub-in generate/sign/verify test cases for RSA/DSA. - bc: use rpmpricrt() for signing, 3x-4x faster. - bc: resurrect RSA verification. RSA breaks my brain every time. Summary: Revision Changes Path 1.3380 +3 -0 rpm/CHANGES 2.29 +105 -78 rpm/rpmio/rpmbc.c 2.11 +5 -7 rpm/rpmio/rpmbc.h 1.2 +64 -5 rpm/tests/tpgp.c ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/CHANGES ============================================================================ $ cvs diff -u -r1.3379 -r1.3380 CHANGES --- rpm/CHANGES 6 Jun 2010 20:33:28 -0000 1.3379 +++ rpm/CHANGES 7 Jun 2010 20:24:14 -0000 1.3380 @@ -1,4 +1,7 @@ 5.3.0 -> 5.4a1: + - jbj: tests: stub-in generate/sign/verify test cases for RSA/DSA. + - jbj: bc: use rpmpricrt() for signing, 3x-4x faster. + - jbj: bc: resurrect RSA verification. RSA breaks my brain every time. - jbj: tests: per-crypto implementation tests for hkp:// retrieval. - jbj: bc: add RSA/DSA sign/generate methods. - jbj: ssl: plug a memory leak. @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/rpmbc.c ============================================================================ $ cvs diff -u -r2.28 -r2.29 rpmbc.c --- rpm/rpmio/rpmbc.c 6 Jun 2010 21:51:54 -0000 2.28 +++ rpm/rpmio/rpmbc.c 7 Jun 2010 20:24:16 -0000 2.29 @@ -19,6 +19,9 @@ extern int _pgp_print; /*...@=redecl@*/ +/*...@unchecked@*/ +static int _rpmbc_debug; + static const char * _pgpHashAlgo2Name(uint32_t algo) { return pgpValStr(pgpHashTbl, (rpmuint8_t)algo); @@ -30,11 +33,30 @@ } #define SPEW(_t, _rc, _dig) \ - { if ((_t) || _pgp_debug < 0) \ + { if ((_t) || _rpmbc_debug || _pgp_debug < 0) \ fprintf(stderr, "<-- %s(%p) %s\t%s\n", __FUNCTION__, (_dig), \ ((_rc) ? "OK" : "BAD"), (_dig)->pubkey_algoN); \ } +#ifdef UNUSED +static void rpmbcDumpRSA(const char * msg, rpmbc bc) +{ +rsakp * kp = &bc->rsa_keypair; +if (msg) fprintf(stderr, "========== %s\n", msg); +fprintf(stderr, "\t n: %s\n", pgpHexStr((rpmuint8_t *)kp->n.modl, kp->n.size)); +fprintf(stderr, "\t e: %s\n", pgpHexStr((rpmuint8_t *)kp->e.data, kp->e.size)); +fprintf(stderr, "\t d: %s\n", pgpHexStr((rpmuint8_t *)kp->d.data, kp->d.size)); +fprintf(stderr, "\t p: %s\n", pgpHexStr((rpmuint8_t *)kp->p.modl, kp->p.size)); +fprintf(stderr, "\t q: %s\n", pgpHexStr((rpmuint8_t *)kp->q.modl, kp->q.size)); +fprintf(stderr, "\tdp: %s\n", pgpHexStr((rpmuint8_t *)kp->dp.data, kp->dp.size)); +fprintf(stderr, "\tdq: %s\n", pgpHexStr((rpmuint8_t *)kp->dq.data, kp->dq.size)); +fprintf(stderr, "\tqi: %s\n", pgpHexStr((rpmuint8_t *)kp->qi.data, kp->qi.size)); +fprintf(stderr, "\thm: %s\n", pgpHexStr((rpmuint8_t *)bc->hm.data, bc->hm.size)); +fprintf(stderr, "\t m: %s\n", pgpHexStr((rpmuint8_t *)bc->m.data, bc->m.size)); +fprintf(stderr, "\t c: %s\n", pgpHexStr((rpmuint8_t *)bc->c.data, bc->c.size)); +} +#endif + /** * Convert hex to binary nibble. * @param c hex character @@ -58,20 +80,39 @@ /*...@modifies dig @*/ { rpmbc bc = dig->impl; - unsigned int nbits = (unsigned) MP_WORDS_TO_BITS(bc->c.size); - unsigned int nb = (nbits + 7) >> 3; + size_t nbits = 0; + size_t nb = 0; const char * prefix = rpmDigestASN1(ctx); const char * hexstr; char * tt; int rc; int xx; +pgpDigParams pubp = pgpGetPubkey(dig); +dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo); +dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo); assert(sigp->hash_algo == rpmDigestAlgo(ctx)); if (prefix == NULL) return 1; -/* XXX FIXME: eliminate bc->digest */ + /* + * The no. of bytes for hash + PKCS1 padding is needed. + * Either n or c can be used as the size, but different code paths + * populate n or c indeterminately. So try c, then n, + * and error if the no. of bytes isn't sane. + */ + if (bc->c.size) + nbits = (unsigned) MP_WORDS_TO_BITS(bc->c.size); + else if (bc->rsa_keypair.n.size) + nbits = (unsigned) MP_WORDS_TO_BITS(bc->rsa_keypair.n.size); + nb = (nbits + 7) >> 3; /* XXX overkill */ + if (nb < 64/8 || nb > 65536/8) /* XXX generous "sanity" check */ + return 1; + /* XXX FIXME: do PKCS1 padding in binary not hex */ +/* XXX FIXME: should this lazy free be done elsewhere? */ +bc->digest = _free(bc->digest); +bc->digestlen = 0; xx = rpmDigestFinal(ctx, (void **)&bc->digest, &bc->digestlen, 1); hexstr = tt = xmalloc(2 * nb + 1); memset(tt, (int) 'f', (2 * nb)); @@ -83,6 +124,7 @@ tt = stpcpy(tt, bc->digest); /*...@-moduncon -noeffectuncon @*/ +mpnfree(&bc->hm); mpnzero(&bc->hm); (void) mpnsethex(&bc->hm, hexstr); /*...@=moduncon =noeffectuncon @*/ @@ -96,6 +138,7 @@ s[1] = (rpmuint8_t) (nibble(str[2]) << 4) | nibble(str[3]); rc = memcmp(s, t, sizeof(sigp->signhash16)); } +SPEW(0, !rc, dig); return rc; } @@ -106,29 +149,9 @@ rpmbc bc = dig->impl; int rc; -#ifndef DYING /* XXX PKCS1 needed. */ - rc = rsavrfy(&bc->rsa_pk.n, &bc->rsa_pk.e, &bc->c, &bc->hm); -#else /* DYING */ - int failures = 0; - int xx; - - mpnzero(&bc->rsa_decipher); - mpnzero(&bc->rsa_cipher); - xx = rsapricrt(&bc->rsa_keypair.n, &bc->rsa_keypair.p, &bc->rsa_keypair.q, - &bc->rsa_keypair.dp, &bc->rsa_keypair.dq, &bc->rsa_keypair.qi, - &bc->rsa_cipher, &bc->rsa_decipher); - if (xx) failures++; - - xx = mpnex(bc->m.size, bc->m.data, - bc->rsa_decipher.size, bc->rsa_decipher.data); - if (xx) failures++; - mpnfree(&bc->rsa_decipher); - mpnfree(&bc->rsa_cipher); - - rc = (failures == 0); - -#endif /* DYING */ + rc = rsavrfy(&bc->rsa_keypair.n, &bc->rsa_keypair.e, &bc->c, &bc->hm); +SPEW(0, rc, dig); return rc; } @@ -141,13 +164,20 @@ int failures = 0; int xx; - mpnzero(&bc->rsa_cipher); - xx = rsapub(&bc->rsa_keypair.n, &bc->rsa_keypair.e, &bc->m, - &bc->rsa_cipher); + mpnzero(&bc->c); +#ifdef SLOWER + xx = rsapri(&bc->rsa_keypair.n, &bc->rsa_keypair.d, &bc->hm, &bc->c); +#else + /* XXX RSA w CRT is ~3x faster for signing. */ + xx = rsapricrt(&bc->rsa_keypair.n, &bc->rsa_keypair.p, &bc->rsa_keypair.q, + &bc->rsa_keypair.dp, &bc->rsa_keypair.dq, &bc->rsa_keypair.qi, + &bc->hm, &bc->c); +#endif if (xx) failures++; rc = (failures == 0); +SPEW(!rc, rc, dig); return rc; } @@ -160,10 +190,11 @@ int failures = 0; int xx; +if (bc->nbits == 0) bc->nbits = 1024; /* XXX FIXME */ + xx = randomGeneratorContextInit(&bc->rngc, randomGeneratorDefault()); - xx = rsakpInit(&bc->rsa_keypair); - if (xx) failures++; +rsakpFree(&bc->rsa_keypair); xx = rsakpMake(&bc->rsa_keypair, &bc->rngc, bc->nbits); if (xx) failures++; @@ -173,6 +204,7 @@ rc = (failures == 0); +SPEW(!rc, rc, dig); return rc; } @@ -182,15 +214,22 @@ { rpmbc bc = dig->impl; rpmuint8_t signhash16[2]; + int rc; int xx; +pgpDigParams pubp = pgpGetPubkey(dig); +dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo); +dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo); assert(sigp->hash_algo == rpmDigestAlgo(ctx)); +bc->digest = _free(bc->digest); +bc->digestlen = 0; xx = rpmDigestFinal(ctx, (void **)&bc->digest, &bc->digestlen, 1); { char * hm = bc->digest; char lastc = hm[40]; /* XXX Truncate to 160bits. */ hm[40] = '\0'; +mpnfree(&bc->hm); mpnzero(&bc->hm); (void) mpnsethex(&bc->hm, hm); hm[40] = lastc; } @@ -198,7 +237,9 @@ /* Compare leading 16 bits of digest for quick check. */ signhash16[0] = (rpmuint8_t)((*bc->hm.data >> 24) & 0xff); signhash16[1] = (rpmuint8_t)((*bc->hm.data >> 16) & 0xff); - return memcmp(signhash16, sigp->signhash16, sizeof(signhash16)); + rc = memcmp(signhash16, sigp->signhash16, sizeof(signhash16)); +SPEW(0, !rc, dig); + return rc; } static @@ -215,10 +256,9 @@ &bc->r, &bc->s); if (!xx) failures++; - mpnfree(&bc->hm); - rc = (failures == 0); +SPEW(0, rc, dig); return rc; } @@ -238,15 +278,14 @@ &bc->dsa_keypair.x, &bc->r, &bc->s); if (xx) failures++; - mpnfree(&bc->hm); - rc = (failures == 0); +SPEW(!rc, rc, dig); return rc; } static -int rpmbcGenerateDSA(/*...@unused@*/pgpDig dig) +int rpmbcGenerateDSA(pgpDig dig) /*...@*/ { rpmbc bc = dig->impl; @@ -254,6 +293,8 @@ int failures = 0; int xx; +if (bc->nbits == 0) bc->nbits = 1024; /* XXX FIXME */ + xx = randomGeneratorContextInit(&bc->rngc, randomGeneratorDefault()); xx = dlkp_pInit(&bc->dsa_keypair); @@ -267,6 +308,7 @@ rc = (failures == 0); +SPEW(!rc, rc, dig); return rc; } @@ -276,12 +318,16 @@ { int rc = 1; /* XXX always fail. */ int xx; +pgpDigParams pubp = pgpGetPubkey(dig); +dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo); +dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo); assert(sigp->hash_algo == rpmDigestAlgo(ctx)); xx = rpmDigestFinal(ctx, (void **)NULL, NULL, 0); /* Compare leading 16 bits of digest for quick check. */ +SPEW(rc, !rc, dig); return rc; } @@ -412,12 +458,16 @@ { int rc = 1; /* XXX always fail. */ int xx; +pgpDigParams pubp = pgpGetPubkey(dig); +dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo); +dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo); assert(sigp->hash_algo == rpmDigestAlgo(ctx)); xx = rpmDigestFinal(ctx, (void **)NULL, NULL, 0); /* Compare leading 16 bits of digest for quick check. */ +SPEW(rc, !rc, dig); return rc; } @@ -430,6 +480,7 @@ assert(bc->hm); /* XXX FIXME: make sure bc->hm is set */ +SPEW(!rc, rc, dig); return rc; } @@ -457,36 +508,6 @@ if (bc->rngc == NULL) xx = randomGeneratorContextInit(&bc->rngc, randomGeneratorDefault()); -#ifdef REFERENCE - rsakpInit(&bc->rsa_keypair); - rsakpMake(&bc->rsa_keypair, &bc->rngc, bc->nbits); - - mpnzero(&bc->rsa_decipher); - mpnzero(&bc->rsa_cipher); - mpnzero(&bc->m); - - /* generate a random m in the range 0 < m < n */ - mpbnrnd(&bc->rsa_keypair.n, &bc->rngc, &bc->m); - - xx = rsapub(&bc->rsa_keypair.n, &bc->rsa_keypair.e, &bc->m, - &bc->rsa_cipher); - if (xx) failures++; - - xx = rsapricrt(&bc->rsa_keypair.n, &bc->rsa_keypair.p, &bc->rsa_keypair.q, - &bc->rsa_keypair.dp, &bc->rsa_keypair.dq, &bc->rsa_keypair.qi, - &bc->rsa_cipher, &bc->rsa_decipher); - if (xx) failures++; - - xx = mpnex(bc->m.size, bc->m.data, bc->rsa_decipher.size, bc->rsa_decipher.data); - if (xx) failures++; - - mpnfree(&bc->rsa_decipher); - mpnfree(&bc->rsa_cipher); - mpnfree(&bc->m); - - rsakpFree(&bc->rsa_keypair); -#endif - rc = (failures == 0); SPEW(!rc, rc, dig); @@ -506,7 +527,6 @@ #else rc = (rc == 0); /* XXX impedance match 1 -> 0 on success */ #endif -SPEW(rc, !rc, dig); return rc; /* XXX 0 on success */ } @@ -573,6 +593,10 @@ { int rc = 0; /* assume failure */ pgpDigParams pubp = pgpGetPubkey(dig); +pgpDigParams sigp = pgpGetSignature(dig); +dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo); +dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo); + switch (pubp->pubkey_algo) { default: break; @@ -599,6 +623,10 @@ { int rc = 0; /* assume failure */ pgpDigParams pubp = pgpGetPubkey(dig); +pgpDigParams sigp = pgpGetSignature(dig); +dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo); +dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo); + switch (pubp->pubkey_algo) { default: break; @@ -707,14 +735,14 @@ rc = pgpMpiSet(pre, 160, &bc->s, p, pend); break; case 30: /* RSA n */ - (void) mpbsethex(&bc->rsa_pk.n, s = pgpMpiHex(p)); + (void) mpbsethex(&bc->rsa_keypair.n, s = pgpMpiHex(p)); if (_pgp_debug && _pgp_print) -fprintf(stderr, "\t %s ", pre), mpfprintln(stderr, bc->rsa_pk.n.size, bc->rsa_pk.n.modl); +fprintf(stderr, "\t %s ", pre), mpfprintln(stderr, bc->rsa_keypair.n.size, bc->rsa_keypair.n.modl); break; case 31: /* RSA e */ - (void) mpnsethex(&bc->rsa_pk.e, s = pgpMpiHex(p)); + (void) mpnsethex(&bc->rsa_keypair.e, s = pgpMpiHex(p)); if (_pgp_debug && _pgp_print) -fprintf(stderr, "\t %s ", pre), mpfprintln(stderr, bc->rsa_pk.e.size, bc->rsa_pk.e.data); +fprintf(stderr, "\t %s ", pre), mpfprintln(stderr, bc->rsa_keypair.e.size, bc->rsa_keypair.e.data); break; case 40: /* DSA p */ (void) mpbsethex(&bc->dsa_keypair.param.p, s = pgpMpiHex(p)); @@ -757,20 +785,19 @@ randomGeneratorContextFree(&bc->rngc); rsakpFree(&bc->rsa_keypair); - mpnfree(&bc->rsa_decipher); - mpnfree(&bc->rsa_cipher); + + dlkp_pFree(&bc->dsa_keypair); dlkp_pFree(&bc->elg_keypair); #ifdef NOTYET dldp_pFree(&bc->elg_params); #endif - dlkp_pFree(&bc->dsa_keypair); - - (void) rsapkFree(&bc->rsa_pk); + mpnfree(&bc->r); + mpnfree(&bc->s); + mpnfree(&bc->hm); mpnfree(&bc->m); mpnfree(&bc->c); - mpnfree(&bc->hm); } } /*...@=mustmod@*/ @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/rpmbc.h ============================================================================ $ cvs diff -u -r2.10 -r2.11 rpmbc.h --- rpm/rpmio/rpmbc.h 6 Jun 2010 20:15:34 -0000 2.10 +++ rpm/rpmio/rpmbc.h 7 Jun 2010 20:24:16 -0000 2.11 @@ -53,23 +53,21 @@ randomGeneratorContext rngc; -rsakp rsa_keypair; -mpnumber rsa_decipher; -mpnumber rsa_cipher; + rsakp rsa_keypair; -dlkp_p elg_keypair; + dsakp dsa_keypair; + + dlkp_p elg_keypair; #ifdef DYING dldp_p elg_params; #endif /* DSA parameters. */ - dsakp dsa_keypair; mpnumber r; mpnumber s; - mpnumber hm; /* RSA parameters. */ - rsapk rsa_pk; + mpnumber hm; mpnumber m; mpnumber c; }; @@ . patch -p0 <<'@@ .' Index: rpm/tests/tpgp.c ============================================================================ $ cvs diff -u -r1.1 -r1.2 tpgp.c --- rpm/tests/tpgp.c 31 Dec 2009 18:38:39 -0000 1.1 +++ rpm/tests/tpgp.c 7 Jun 2010 20:24:15 -0000 1.2 @@ -8,6 +8,7 @@ #include "system.h" +#define _RPMPGP_INTERNAL #include <rpmio.h> #include <rpmns.h> #include <rpmcli.h> @@ -17,7 +18,7 @@ #include "debug.h" static -rpmRC doit(rpmts ts, const char * sigtype) +rpmRC probeTest(rpmts ts, const char * sigtype) { rpmRC rc = RPMRC_FAIL; @@ -45,6 +46,57 @@ return rc; } +static +rpmRC generateTest(rpmts ts, const char * text, int pubkey_algo, int hash_algo) +{ + pgpDig dig = pgpDigNew(0); + pgpDigParams pubp = pgpGetPubkey(dig); + pgpDigParams sigp = pgpGetSignature(dig); + rpmRC rc = RPMRC_OK; /* assume success */ + int xx; + + pubp->pubkey_algo = pubkey_algo; + sigp->hash_algo = hash_algo; + + xx = pgpImplGenerate(dig); + if (xx) { + DIGEST_CTX ctx = rpmDigestInit(sigp->hash_algo, 0); + uint8_t * digest = NULL; + size_t digestlen = 0; + xx = rpmDigestUpdate(ctx, text, strlen(text)); + xx = rpmDigestFinal(rpmDigestDup(ctx), &digest, &digestlen, 0); + switch (pubp->pubkey_algo) { + case PGPPUBKEYALGO_RSA: + sigp->signhash16[0] = digest[0]; + sigp->signhash16[1] = digest[1]; + xx = pgpImplSetRSA(rpmDigestDup(ctx), dig, sigp); + xx = pgpImplSign(dig); + sigp->signhash16[0] = digest[0]; + sigp->signhash16[1] = digest[1]; + xx = pgpImplSetRSA(ctx, dig, sigp); + xx = pgpImplVerify(dig); + break; + case PGPPUBKEYALGO_DSA: + sigp->signhash16[0] = digest[0]; + sigp->signhash16[1] = digest[1]; + xx = pgpImplSetDSA(rpmDigestDup(ctx), dig, sigp); + xx = pgpImplSign(dig); + sigp->signhash16[0] = digest[0]; + sigp->signhash16[1] = digest[1]; + xx = pgpImplSetDSA(ctx, dig, sigp); + xx = pgpImplVerify(dig); + break; + default: + xx = rpmDigestFinal(ctx, NULL, NULL, 0); + break; + } + digest = _free(digest); + } + + dig = pgpDigFree(dig); + return rc; +} + static struct poptOption optionsTable[] = { { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0, N_("Common options:"), @@ -60,12 +112,19 @@ { poptContext optCon = rpmcliInit(argc, argv, optionsTable); rpmts ts = rpmtsCreate(); - int rc = rpmtsOpenDB(ts, O_RDONLY); + int ec = rpmtsOpenDB(ts, O_RDONLY); + int rc; fprintf(stderr, " DSA"); - rc = doit(ts, "DSA"); + rc = probeTest(ts, "DSA"); + if (rc != RPMRC_OK) ec++; + rc = generateTest(ts, "abc", PGPPUBKEYALGO_DSA, PGPHASHALGO_SHA1); + if (rc != RPMRC_OK) ec++; fprintf(stderr, " RSA"); - rc = doit(ts, "RSA"); + rc = probeTest(ts, "RSA"); + if (rc != RPMRC_OK) ec++; + rc = generateTest(ts, "abc", PGPPUBKEYALGO_RSA, PGPHASHALGO_SHA1); + if (rc != RPMRC_OK) ec++; fprintf(stderr, "\n"); (void) rpmtsFree(ts); @@ -73,5 +132,5 @@ optCon = rpmcliFini(optCon); - return rc; + return ec; } @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org