rpm  5.4.4
rpmio/rpmbc.c
Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 #define _RPMBC_INTERNAL
00007 #define _RPMPGP_INTERNAL
00008 #include <rpmbc.h>
00009 #include "debug.h"
00010 
00011 /*@access pgpDig @*/
00012 /*@access pgpDigParams @*/
00013 
00014 /*@-redecl@*/
00015 /*@unchecked@*/
00016 extern int _pgp_debug;
00017 
00018 /*@unchecked@*/
00019 extern int _pgp_print;
00020 /*@=redecl@*/
00021 
00022 /*@unchecked@*/
00023 static int _rpmbc_debug;
00024 
00025 #define SPEW(_t, _rc, _dig)     \
00026   { if ((_t) || _rpmbc_debug || _pgp_debug < 0) \
00027         fprintf(stderr, "<-- %s(%p) %s\t%s\n", __FUNCTION__, (_dig), \
00028                 ((_rc) ? "OK" : "BAD"), (_dig)->pubkey_algoN); \
00029   }
00030 
00031 static const char * _pgpHashAlgo2Name(uint32_t algo)
00032 {
00033     return pgpValStr(pgpHashTbl, (rpmuint8_t)algo);
00034 }
00035 
00036 static const char * _pgpPubkeyAlgo2Name(uint32_t algo)
00037 {
00038     return pgpValStr(pgpPubkeyTbl, (rpmuint8_t)algo);
00039 }
00040 
00046 static
00047 unsigned char nibble(char c)
00048         /*@*/
00049 {
00050     if (c >= '0' && c <= '9')
00051         return (unsigned char) (c - '0');
00052     if (c >= 'A' && c <= 'F')
00053         return (unsigned char)((int)(c - 'A') + 10);
00054     if (c >= 'a' && c <= 'f')
00055         return (unsigned char)((int)(c - 'a') + 10);
00056     return (unsigned char) '\0';
00057 }
00058 
00059 #define _spewMPB(_N, _MPB)      \
00060   { mpbarrett * mpb = &(_MPB); \
00061     fprintf(stderr, "\t" _N ": "); mpfprintln(stderr, mpb->size, mpb->modl); \
00062   }
00063 
00064 #define _spewMPN(_N, _MPN)      \
00065   { mpnumber * mpn = &(_MPN); \
00066     fprintf(stderr, "\t" _N ": "); mpfprintln(stderr, mpn->size, mpn->data); \
00067   }
00068 
00069 #ifdef  UNUSED
00070 static void rpmbcDumpRSA(const char * msg, rpmbc bc)
00071 {
00072     if (msg) fprintf(stderr, "========== %s\n", msg);
00073 
00074     {
00075         _spewMPB(" n", bc->rsa_keypair.n);
00076         _spewMPN(" e", bc->rsa_keypair.e);
00077         _spewMPN(" d", bc->rsa_keypair.d);
00078         _spewMPB(" p", bc->rsa_keypair.p);
00079         _spewMPB(" q", bc->rsa_keypair.q);
00080         _spewMPN("dp", bc->rsa_keypair.dp);
00081         _spewMPN("dq", bc->rsa_keypair.dq);
00082         _spewMPN("qi", bc->rsa_keypair.qi);
00083     }
00084 
00085     _spewMPN(" c", bc->c);
00086     _spewMPN("hm", bc->hm);
00087 }
00088 
00089 static void rpmbcDumpDSA(const char * msg, rpmbc bc)
00090 {
00091     if (msg) fprintf(stderr, "========== %s\n", msg);
00092 
00093     {
00094         _spewMPB(" p", bc->dsa_keypair.param.p);
00095         _spewMPB(" q", bc->dsa_keypair.param.q);
00096         _spewMPN(" g", bc->dsa_keypair.param.g);
00097         _spewMPN(" y", bc->dsa_keypair.y);
00098     }
00099 
00100     _spewMPN(" r", bc->r);
00101     _spewMPN(" s", bc->s);
00102 
00103     _spewMPN("hm", bc->hm);
00104 
00105 }
00106 #endif  /* UNUSED */
00107 
00108 static
00109 int rpmbcSetRSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
00110         /*@modifies dig @*/
00111 {
00112     rpmbc bc = dig->impl;
00113     size_t nbits = 0;
00114     size_t nb = 0;
00115     const char * prefix = rpmDigestASN1(ctx);
00116     const char * hexstr;
00117     char * tt;
00118     int rc = 1;         /* assume failure */
00119     int xx;
00120 pgpDigParams pubp = pgpGetPubkey(dig);
00121 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00122 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00123 
00124 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00125 assert(prefix != NULL);
00126 
00127     /*
00128      * The no. of bytes for hash + PKCS1 padding is needed.
00129      * Either n or c can be used as the size, but different code paths
00130      * populate n or c indeterminately. So try c, then n,
00131      * and error if the no. of bytes isn't sane.
00132      */
00133     if (bc->c.size)
00134         nbits = (unsigned) MP_WORDS_TO_BITS(bc->c.size);
00135     else if (bc->rsa_keypair.n.size)
00136         nbits = (unsigned) MP_WORDS_TO_BITS(bc->rsa_keypair.n.size);
00137     nb = (nbits + 7) >> 3;              /* XXX overkill */
00138     if (nb < 64/8 || nb > 65536/8)      /* XXX generous "sanity" check */
00139         goto exit;
00140 
00141 /* XXX FIXME: do PKCS1 padding in binary not hex */
00142 /* XXX FIXME: should this lazy free be done elsewhere? */
00143 bc->digest = _free(bc->digest);
00144 bc->digestlen = 0;
00145     xx = rpmDigestFinal(ctx, (void **)&bc->digest, &bc->digestlen, 1);
00146     ctx = NULL;         /* XXX avoid double free */
00147     hexstr = tt = xmalloc(2 * nb + 1);
00148     memset(tt, (int) 'f', (2 * nb));
00149     tt[0] = '0'; tt[1] = '0';
00150     tt[2] = '0'; tt[3] = '1';
00151     tt += (2 * nb) - strlen(prefix) - strlen(bc->digest) - 2;
00152     *tt++ = '0'; *tt++ = '0';
00153     tt = stpcpy(tt, prefix);
00154     tt = stpcpy(tt, bc->digest);
00155 
00156 /*@-moduncon -noeffectuncon @*/
00157 mpnfree(&bc->hm);
00158     mpnzero(&bc->hm);   (void) mpnsethex(&bc->hm, hexstr);
00159 /*@=moduncon =noeffectuncon @*/
00160 
00161     hexstr = _free(hexstr);
00162 
00163     /* Compare leading 16 bits of digest for quick check. */
00164     {   const char *str = bc->digest;
00165         rpmuint8_t s[2];
00166         const rpmuint8_t *t = sigp->signhash16;
00167         s[0] = (rpmuint8_t) (nibble(str[0]) << 4) | nibble(str[1]);
00168         s[1] = (rpmuint8_t) (nibble(str[2]) << 4) | nibble(str[3]);
00169         rc = memcmp(s, t, sizeof(sigp->signhash16));
00170     }
00171 
00172 exit:
00173     if (ctx) {          /* XXX Free the context on error returns. */
00174         xx = rpmDigestFinal(ctx, NULL, NULL, 0);
00175         ctx = NULL;
00176     }
00177 SPEW(0, !rc, dig);
00178     return rc;
00179 }
00180 
00181 static
00182 int rpmbcVerifyRSA(pgpDig dig)
00183         /*@*/
00184 {
00185     rpmbc bc = dig->impl;
00186     int rc;
00187 
00188     rc = rsavrfy(&bc->rsa_keypair.n, &bc->rsa_keypair.e, &bc->c, &bc->hm);
00189 
00190 SPEW(0, rc, dig);
00191     return rc;
00192 }
00193 
00194 static
00195 int rpmbcSignRSA(/*@unused@*/pgpDig dig)
00196         /*@*/
00197 {
00198     rpmbc bc = dig->impl;
00199     int rc = 0;         /* Assume failure. */
00200     int failures = 0;
00201     int xx;
00202 
00203     mpnzero(&bc->c);
00204 #ifdef  SLOWER
00205     xx = rsapri(&bc->rsa_keypair.n, &bc->rsa_keypair.d, &bc->hm, &bc->c);
00206 #else
00207     /* XXX RSA w CRT is ~3x-4x faster for signing. */
00208     xx = rsapricrt(&bc->rsa_keypair.n, &bc->rsa_keypair.p, &bc->rsa_keypair.q,
00209                 &bc->rsa_keypair.dp, &bc->rsa_keypair.dq, &bc->rsa_keypair.qi,
00210                 &bc->hm, &bc->c);
00211 #endif
00212     if (xx) failures++;
00213 
00214     rc = (failures == 0);
00215 
00216 SPEW(!rc, rc, dig);
00217     return rc;
00218 }
00219 
00220 static
00221 int rpmbcGenerateRSA(/*@unused@*/pgpDig dig)
00222         /*@*/
00223 {
00224     rpmbc bc = dig->impl;
00225     int rc = 0;         /* Assume failure. */
00226     int failures = 0;
00227     int xx;
00228 
00229 if (bc->nbits == 0) bc->nbits = 1024;   /* XXX FIXME */
00230 
00231 xx = randomGeneratorContextInit(&bc->rngc, randomGeneratorDefault());
00232 
00233 rsakpFree(&bc->rsa_keypair);
00234     xx = rsakpMake(&bc->rsa_keypair, &bc->rngc, bc->nbits);
00235     if (xx) failures++;
00236 
00237     /* generate a random m in the range 0 < m < n */
00238     mpnzero(&bc->m);
00239     mpbnrnd(&bc->rsa_keypair.n, &bc->rngc, &bc->m);
00240 
00241     rc = (failures == 0);
00242 
00243 SPEW(!rc, rc, dig);
00244     return rc;
00245 }
00246 
00247 static
00248 int rpmbcSetDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
00249         /*@modifies dig @*/
00250 {
00251     rpmbc bc = dig->impl;
00252     int rc;
00253 pgpDigParams pubp = pgpGetPubkey(dig);
00254 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00255 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00256 
00257 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00258 bc->digest = _free(bc->digest);
00259 bc->digestlen = 0;
00260     rc = rpmDigestFinal(ctx, (void **)&bc->digest, &bc->digestlen, 0);
00261 
00262     /* XXX Truncate to 160bits. */
00263     rc = mpnsetbin(&bc->hm, bc->digest,
00264                 (bc->digestlen > 160/8 ? 160/8 : bc->digestlen));
00265     rc = memcmp(bc->digest, sigp->signhash16, sizeof(sigp->signhash16));
00266 
00267 SPEW(0, !rc, dig);
00268     return rc;
00269 }
00270 
00271 static
00272 int rpmbcVerifyDSA(pgpDig dig)
00273         /*@*/
00274 {
00275     rpmbc bc = dig->impl;
00276     int rc = 0;         /* Assume failure. */
00277     int failures = 0;
00278     int xx;
00279 
00280     xx = dsavrfy(&bc->dsa_keypair.param.p, &bc->dsa_keypair.param.q,
00281                 &bc->dsa_keypair.param.g, &bc->hm, &bc->dsa_keypair.y,
00282                 &bc->r, &bc->s);
00283     if (!xx) failures++;
00284 
00285     rc = (failures == 0);
00286 
00287 SPEW(0, rc, dig);
00288     return rc;
00289 }
00290 
00291 static
00292 int rpmbcSignDSA(pgpDig dig)
00293         /*@*/
00294 {
00295     rpmbc bc = dig->impl;
00296     int rc = 0;         /* Assume failure. */
00297     int failures = 0;
00298     int xx;
00299 
00300     mpnzero(&bc->r);
00301     mpnzero(&bc->s);
00302     xx = dsasign(&bc->dsa_keypair.param.p, &bc->dsa_keypair.param.q,
00303                 &bc->dsa_keypair.param.g, &bc->rngc, &bc->hm,
00304                 &bc->dsa_keypair.x, &bc->r, &bc->s);
00305     if (xx) failures++;
00306 
00307     rc = (failures == 0);
00308 
00309 SPEW(!rc, rc, dig);
00310     return rc;
00311 }
00312 
00313 static
00314 int rpmbcGenerateDSA(pgpDig dig)
00315         /*@*/
00316 {
00317     rpmbc bc = dig->impl;
00318     int rc = 0;         /* Assume failure. */
00319     int failures = 0;
00320     int xx;
00321 
00322 if (bc->nbits == 0) bc->nbits = 1024;   /* XXX FIXME */
00323 
00324 xx = randomGeneratorContextInit(&bc->rngc, randomGeneratorDefault());
00325 
00326     xx = dlkp_pInit(&bc->dsa_keypair);
00327     if (xx) failures++;
00328     xx = dsaparamMake(&bc->dsa_keypair.param, &bc->rngc, bc->nbits);
00329     if (xx) failures++;
00330 
00331     xx = dldp_pPair(&bc->dsa_keypair.param, &bc->rngc, &bc->dsa_keypair.x,
00332                 &bc->dsa_keypair.y);
00333     if (xx) failures++;
00334 
00335     rc = (failures == 0);
00336 
00337 SPEW(!rc, rc, dig);
00338     return rc;
00339 }
00340 
00341 static
00342 int rpmbcSetELG(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp)
00343         /*@*/
00344 {
00345     int rc = 1;         /* XXX always fail. */
00346     int xx;
00347 pgpDigParams pubp = pgpGetPubkey(dig);
00348 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00349 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00350 
00351 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00352     xx = rpmDigestFinal(ctx, (void **)NULL, NULL, 0);
00353 
00354     /* Compare leading 16 bits of digest for quick check. */
00355 
00356 SPEW(rc, !rc, dig);
00357     return rc;
00358 }
00359 
00360 #ifdef  NOTYET
00361 static
00362 int rpmbcVerifyELG(pgpDig dig)
00363         /*@*/
00364 {
00365     rpmbc bc = dig->impl;
00366     int rc = 0;         /* Assume failure. */
00367     int failures = 0;
00368     int xx;
00369 
00370     xx = elgv1vrfy(&bc->elg_keypair.param.p, &bc->elg_keypair.param.n,
00371                 &bc->elg_keypair.param.g, &bc->hm, &bc->elg_keypair.y,
00372                 &bc->r, &bc->s);
00373     if (xx) failures++;
00374 
00375     rc = (failures == 0);
00376 
00377 SPEW(!rc, rc, dig);
00378     return rc;
00379 }
00380 
00381 static
00382 int rpmbcSignELG(/*@unused@*/pgpDig dig)
00383         /*@*/
00384 {
00385     rpmbc bc = dig->impl;
00386     int rc = 0;         /* Assume failure. */
00387     int failures = 0;
00388     int xx;
00389 
00390     mpnzero(&bc->r);
00391     mpnzero(&bc->s);
00392     xx = elgv1sign(&bc->elg_keypair.param.p, &bc->elg_keypair.param.n,
00393                 &bc->elg_keypair.param.g, &bc->rngc, &bc->hm,
00394                 &bc->elg_keypair.x, &bc->r, &bc->s);
00395     if (xx) failures++;
00396 
00397     rc = (failures == 0);
00398 
00399 SPEW(!rc, rc, dig);
00400     return rc;
00401 }
00402 
00403 static
00404 int rpmbcGenerateELG(/*@unused@*/pgpDig dig)
00405         /*@*/
00406 {
00407 static const char P_2048[] = "fd12e8b7e096a28a00fb548035953cf0eba64ceb5dff0f5672d376d59c196da729f6b5586f18e6f3f1a86c73c5b15662f59439613b309e52aa257488619e5f76a7c4c3f7a426bdeac66bf88343482941413cef06256b39c62744dcb97e7b78e36ec6b885b143f6f3ad0a1cd8a5713e338916613892a264d4a47e72b583fbdaf5bce2bbb0097f7e65cbc86d684882e5bb8196d522dcacd6ad00dfbcd8d21613bdb59c485a65a58325d792272c09ad1173e12c98d865adb4c4d676ada79830c58c37c42dff8536e28f148a23f296513816d3dfed0397a3d4d6e1fa24f07e1b01643a68b4274646a3b876e810206eddacea2b9ef7636a1da5880ef654288b857ea3";
00408 static const char P_1024[] = "e64a3deeddb723e2e4db54c2b09567d196367a86b3b302be07e43ffd7f2e016f866de5135e375bdd2fba6ea9b4299010fafa36dc6b02ba3853cceea07ee94bfe30e0cc82a69c73163be26e0c4012dfa0b2839c97d6cd71eee59a303d6177c6a6740ca63bd04c1ba084d6c369dc2fbfaeebe951d58a4824de52b580442d8cae77";
00409 
00410     rpmbc bc = dig->impl;
00411     int rc = 0;         /* Assume failure. */
00412     int failures = 0;
00413     int xx;
00414 
00415 xx = randomGeneratorContextInit(&bc->rngc, randomGeneratorDefault());
00416 
00417     xx = 0;
00418 
00419     xx = dlkp_pInit(&bc->elg_keypair);
00420     if (xx) failures++;
00421 
00422 #ifdef  DYING
00423     xx = dldp_pInit(&bc->elg_keypair.param);
00424     if (xx) failures++;
00425 #endif
00426 
00427     switch (bc->nbits) {
00428 #ifdef  NOTYET
00429     case 2048:
00430         mpbsethex(&bc->elg_keypair.param.p, P_2048);
00431         break;
00432     case 1024:
00433     case 0:
00434         mpbsethex(&bc->elg_keypair.param.p, P_1024);
00435         break;
00436 #endif
00437     default:
00438         xx = dldp_pgonMakeSafe(&bc->elg_keypair.param, &bc->rngc, bc->nbits);
00439         break;
00440     }
00441 #ifdef NOTYET
00442     if (bc->elg_keypair.param.q.size == 0) {
00443         mpnumber q;
00444 
00445         mpnzero(&q);
00446         /* set q to half of P */
00447         mpnset(&q, bc->elg_keypair.param.p.size, bc->elg_keypair.param.p.modl);
00448         mpdivtwo(q.size, q.data);
00449         mpbset(&bc->elg_keypair.param.q, q.size, q.data);
00450         /* set r to 2 */
00451         mpnsetw(&bc->elg_keypair.param.r, 2);
00452 
00453         /* make a generator, order n */
00454         xx = dldp_pgonGenerator(&bc->elg_keypair.param, &bc->rngc);
00455 
00456     }
00457 #endif
00458     if (xx) failures++;
00459 
00460     xx = dldp_pPair(&bc->elg_keypair.param, &bc->rngc,
00461                 &bc->elg_keypair.x, &bc->elg_keypair.y);
00462     if (xx) failures++;
00463 
00464     mpnfree(&bc->r);
00465     mpnfree(&bc->s);
00466     mpnfree(&bc->hm);
00467 
00468 #ifdef  DYING
00469     dldp_pFree(&bc->elg_params);
00470 #endif
00471 
00472     dlkp_pFree(&bc->elg_keypair);
00473 
00474     rc = (failures == 0);
00475 
00476 SPEW(!rc, rc, dig);
00477     return rc;
00478 }
00479 #endif  /* NOTYET */
00480 
00481 static
00482 int rpmbcSetECDSA(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp)
00483         /*@*/
00484 {
00485     int rc = 1;         /* XXX always fail. */
00486     int xx;
00487 pgpDigParams pubp = pgpGetPubkey(dig);
00488 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00489 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00490 
00491 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00492     xx = rpmDigestFinal(ctx, (void **)NULL, NULL, 0);
00493 
00494     /* Compare leading 16 bits of digest for quick check. */
00495 
00496 SPEW(rc, !rc, dig);
00497     return rc;
00498 }
00499 
00500 #ifdef  NOTYET
00501 static
00502 int rpmbcVerifyECDSA(pgpDig dig)
00503         /*@*/
00504 {
00505     int rc = 0;         /* XXX always fail. */
00506 
00507 assert(bc->hm); /* XXX FIXME: make sure bc->hm is set */
00508 
00509 SPEW(!rc, rc, dig);
00510     return rc;
00511 }
00512 
00513 static
00514 int rpmbcSignECDSA(/*@unused@*/pgpDig dig)
00515         /*@*/
00516 {
00517     int rc = 0;         /* XXX always fail. */
00518 
00519 assert(bc->hm); /* XXX FIXME: make sure bc->hm is set */
00520 
00521 SPEW(!rc, rc, dig);
00522     return rc;
00523 }
00524 
00525 static
00526 int rpmbcGenerateECDSA(/*@unused@*/pgpDig dig)
00527         /*@*/
00528 {
00529     rpmbc bc = dig->impl;
00530     int rc = 0;         /* Assume failure. */
00531     int failures = 0;
00532     int xx;
00533 
00534     if (bc->rngc == NULL)
00535         xx = randomGeneratorContextInit(&bc->rngc, randomGeneratorDefault());
00536 
00537     rc = (failures == 0);
00538 
00539 SPEW(!rc, rc, dig);
00540     return rc;
00541 }
00542 #endif  /* NOTYET */
00543 
00544 static int rpmbcErrChk(pgpDig dig, const char * msg, int rc, unsigned expected)
00545 {
00546 #ifdef  REFERENCE
00547 rpmgc gc = dig->impl;
00548     /* Was the return code the expected result? */
00549     rc = (gcry_err_code(gc->err) != expected);
00550     if (rc)
00551         fail("%s failed: %s\n", msg, gpg_strerror(gc->err));
00552 /* XXX FIXME: rpmbcStrerror */
00553 #else
00554     rc = (rc == 0);     /* XXX impedance match 1 -> 0 on success */
00555 #endif
00556     return rc;  /* XXX 0 on success */
00557 }
00558 
00559 static int rpmbcAvailableCipher(pgpDig dig, int algo)
00560 {
00561     int rc = 0; /* assume available */
00562 #ifdef  REFERENCE
00563     rc = rpmgbcvailable(dig->impl, algo,
00564         (gcry_md_test_algo(algo) || algo == PGPHASHALGO_MD5));
00565 #endif
00566     return rc;
00567 }
00568 
00569 static int rpmbcAvailableDigest(pgpDig dig, int algo)
00570 {
00571     int rc = 0; /* assume available */
00572 #ifdef  REFERENCE
00573     rc = rpmgbcvailable(dig->impl, algo,
00574         (gcry_md_test_algo(algo) || algo == PGPHASHALGO_MD5));
00575 #endif
00576     return rc;
00577 }
00578 
00579 static int rpmbcAvailablePubkey(pgpDig dig, int algo)
00580 {
00581     int rc = 0; /* assume available */
00582 #ifdef  REFERENCE
00583     rc = rpmbcAvailable(dig->impl, algo, gcry_pk_test_algo(algo));
00584 #endif
00585     return rc;
00586 }
00587 
00588 static int rpmbcVerify(pgpDig dig)
00589 {
00590     int rc = 0;         /* assume failure */
00591 pgpDigParams pubp = pgpGetPubkey(dig);
00592 pgpDigParams sigp = pgpGetSignature(dig);
00593 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00594 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00595 
00596     switch (pubp->pubkey_algo) {
00597     default:
00598         break;
00599     case PGPPUBKEYALGO_RSA:
00600         rc = rpmbcVerifyRSA(dig);
00601         break;
00602     case PGPPUBKEYALGO_DSA:
00603         rc = rpmbcVerifyDSA(dig);
00604         break;
00605 #ifdef  NOTYET
00606     case PGPPUBKEYALGO_ELGAMAL:
00607         rc = rpmbcVerifyELG(dig);
00608         break;
00609     case PGPPUBKEYALGO_ECDSA:
00610         rc = rpmbcVerifyECDSA(dig);
00611         break;
00612 #endif
00613     }
00614 SPEW(0, rc, dig);       /* XXX FIXME: thkp has known BAD signatures. */
00615     return rc;
00616 }
00617 
00618 static int rpmbcSign(pgpDig dig)
00619 {
00620     int rc = 0;         /* assume failure */
00621 pgpDigParams pubp = pgpGetPubkey(dig);
00622 pgpDigParams sigp = pgpGetSignature(dig);
00623 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00624 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00625 
00626     switch (pubp->pubkey_algo) {
00627     default:
00628         break;
00629     case PGPPUBKEYALGO_RSA:
00630         rc = rpmbcSignRSA(dig);
00631         break;
00632     case PGPPUBKEYALGO_DSA:
00633         rc = rpmbcSignDSA(dig);
00634         break;
00635 #ifdef  NOTYET
00636     case PGPPUBKEYALGO_ELGAMAL:
00637         rc = rpmbcSignELG(dig);
00638         break;
00639     case PGPPUBKEYALGO_ECDSA:
00640         rc = rpmbcSignECDSA(dig);
00641         break;
00642 #endif
00643     }
00644 SPEW(!rc, rc, dig);
00645     return rc;
00646 }
00647 
00648 static int rpmbcGenerate(pgpDig dig)
00649 {
00650     int rc = 0;         /* assume failure */
00651 pgpDigParams pubp = pgpGetPubkey(dig);
00652 pgpDigParams sigp = pgpGetSignature(dig);
00653 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00654 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00655 
00656     switch (pubp->pubkey_algo) {
00657     default:
00658         break;
00659     case PGPPUBKEYALGO_RSA:
00660         rc = rpmbcGenerateRSA(dig);
00661         break;
00662     case PGPPUBKEYALGO_DSA:
00663         rc = rpmbcGenerateDSA(dig);
00664         break;
00665 #ifdef NOTYET
00666     case PGPPUBKEYALGO_ELGAMAL:
00667         rc = rpmbcGenerateELG(dig);
00668         break;
00669     case PGPPUBKEYALGO_ECDSA:
00670         rc = rpmbcGenerateECDSA(dig);
00671         break;
00672 #endif
00673     }
00674 SPEW(!rc, rc, dig);
00675     return rc;
00676 }
00677 
00680 static /*@only@*/
00681 char * pgpMpiHex(const rpmuint8_t *p)
00682         /*@*/
00683 {
00684     size_t nb = pgpMpiLen(p);
00685     char * t = xmalloc(2*nb + 1);
00686     (void) pgpHexCvt(t, p+2, nb-2);
00687     return t;
00688 }
00689 
00693 static
00694 int pgpMpiSet(const char * pre, unsigned int lbits,
00695                 /*@out@*/ void * dest, const rpmuint8_t * p,
00696                 /*@null@*/ const rpmuint8_t * pend)
00697         /*@globals fileSystem @*/
00698         /*@modifies fileSystem @*/
00699 {
00700     mpnumber * mpn = dest;
00701     unsigned int mbits = pgpMpiBits(p);
00702     unsigned int nbits;
00703     unsigned int nbytes;
00704     char * t;
00705     unsigned int ix;
00706 
00707     if (pend != NULL && (p + ((mbits+7) >> 3)) > pend)
00708         return 1;
00709 
00710     if (mbits > lbits)
00711         return 1;
00712 
00713     nbits = (lbits > mbits ? lbits : mbits);
00714     nbytes = ((nbits + 7) >> 3);
00715     t = xmalloc(2*nbytes+1);
00716     ix = 2 * ((nbits - mbits) >> 3);
00717 
00718 if (_pgp_debug)
00719 fprintf(stderr, "*** mbits %u nbits %u nbytes %u t %p[%d] ix %u\n", mbits, nbits, nbytes, t, (2*nbytes+1), ix);
00720     if (ix > 0) memset(t, (int)'0', ix);
00721     {   const char * s = pgpMpiHex(p);
00722         strcpy(t+ix, s);
00723         s = _free(s);
00724     }
00725 if (_pgp_debug)
00726 fprintf(stderr, "*** %s %s\n", pre, t);
00727     (void) mpnsethex(mpn, t);
00728     t = _free(t);
00729     return 0;
00730 }
00731 
00732 static
00733 int rpmbcMpiItem(const char * pre, pgpDig dig, int itemno,
00734                 const rpmuint8_t * p, /*@null@*/ const rpmuint8_t * pend)
00735         /*@globals fileSystem @*/
00736         /*@modifies fileSystem @*/
00737 {
00738     rpmbc bc = dig->impl;
00739     const char * s = NULL;
00740     int rc = 0;
00741 
00742     switch (itemno) {
00743     default:
00744 assert(0);
00745     case 50:            /* ECDSA r */
00746     case 51:            /* ECDSA s */
00747     case 60:            /* ECDSA curve OID */
00748     case 61:            /* ECDSA Q */
00749         break;
00750     case 10:            /* RSA m**d */
00751         (void) mpnsethex(&bc->c, s = pgpMpiHex(p));
00752 if (_pgp_debug && _pgp_print)
00753 _spewMPN(" c", bc->c);
00754         break;
00755     case 20:            /* DSA r */
00756         rc = pgpMpiSet(pre, 160, &bc->r, p, pend);
00757 if (_pgp_debug && _pgp_print)
00758 _spewMPN(" r", bc->r);
00759         break;
00760     case 21:            /* DSA s */
00761         rc = pgpMpiSet(pre, 160, &bc->s, p, pend);
00762 if (_pgp_debug && _pgp_print)
00763 _spewMPN(" s", bc->s);
00764         break;
00765     case 30:            /* RSA n */
00766         (void) mpbsethex(&bc->rsa_keypair.n, s = pgpMpiHex(p));
00767 if (_pgp_debug && _pgp_print)
00768 _spewMPB(" n", bc->dsa_keypair.param.n);
00769         break;
00770     case 31:            /* RSA e */
00771         (void) mpnsethex(&bc->rsa_keypair.e, s = pgpMpiHex(p));
00772 if (_pgp_debug && _pgp_print)
00773 _spewMPN(" e", bc->rsa_keypair.e);
00774         break;
00775     case 40:            /* DSA p */
00776         (void) mpbsethex(&bc->dsa_keypair.param.p, s = pgpMpiHex(p));
00777 if (_pgp_debug && _pgp_print)
00778 _spewMPB(" p", bc->dsa_keypair.param.p);
00779         break;
00780     case 41:            /* DSA q */
00781         (void) mpbsethex(&bc->dsa_keypair.param.q, s = pgpMpiHex(p));
00782 if (_pgp_debug && _pgp_print)
00783 _spewMPB(" q", bc->dsa_keypair.param.q);
00784         break;
00785     case 42:            /* DSA g */
00786         (void) mpnsethex(&bc->dsa_keypair.param.g, s = pgpMpiHex(p));
00787 if (_pgp_debug && _pgp_print)
00788 _spewMPN(" g", bc->dsa_keypair.param.g);
00789         break;
00790     case 43:            /* DSA y */
00791         (void) mpnsethex(&bc->dsa_keypair.y, s = pgpMpiHex(p));
00792 if (_pgp_debug && _pgp_print)
00793 _spewMPN(" y", bc->dsa_keypair.y);
00794         break;
00795     }
00796     s = _free(s);
00797     return rc;
00798 }
00799 
00800 /*@-mustmod@*/
00801 static
00802 void rpmbcClean(void * impl)
00803         /*@modifies impl @*/
00804 {
00805     rpmbc bc = impl;
00806     if (bc != NULL) {
00807         bc->nbits = 0;
00808         bc->err = 0;
00809         bc->badok = 0;
00810         bc->digest = _free(bc->digest);
00811         bc->digestlen = 0;
00812 
00813         randomGeneratorContextFree(&bc->rngc);
00814 
00815         rsakpFree(&bc->rsa_keypair);
00816 
00817         dlkp_pFree(&bc->dsa_keypair);
00818 
00819         dlkp_pFree(&bc->elg_keypair);
00820 #ifdef  NOTYET
00821 dldp_pFree(&bc->elg_params);
00822 #endif
00823 
00824         mpnfree(&bc->r);
00825         mpnfree(&bc->s);
00826         mpnfree(&bc->hm);
00827         mpnfree(&bc->m);
00828         mpnfree(&bc->c);
00829     }
00830 }
00831 /*@=mustmod@*/
00832 
00833 static /*@null@*/
00834 void * rpmbcFree(/*@only@*/ void * impl)
00835         /*@modifies impl @*/
00836 {
00837     rpmbcClean(impl);
00838     impl = _free(impl);
00839     return NULL;
00840 }
00841 
00842 static
00843 void * rpmbcInit(void)
00844         /*@*/
00845 {
00846     rpmbc bc = xcalloc(1, sizeof(*bc));
00847     return (void *) bc;
00848 }
00849 
00850 struct pgpImplVecs_s rpmbcImplVecs = {
00851         rpmbcSetRSA,
00852         rpmbcSetDSA,
00853         rpmbcSetELG,
00854         rpmbcSetECDSA,
00855 
00856         rpmbcErrChk,
00857         rpmbcAvailableCipher, rpmbcAvailableDigest, rpmbcAvailablePubkey,
00858         rpmbcVerify, rpmbcSign, rpmbcGenerate,
00859 
00860         rpmbcMpiItem, rpmbcClean,
00861         rpmbcFree, rpmbcInit
00862 };
00863 
00864 int rpmbcExportPubkey(pgpDig dig)
00865 {
00866     uint8_t pkt[8192];
00867     uint8_t * be = pkt;
00868     size_t pktlen;
00869     time_t now = time(NULL);
00870     uint32_t bt = now;
00871     uint16_t bn;
00872     pgpDigParams pubp = pgpGetPubkey(dig);
00873     rpmbc bc = dig->impl;
00874     int xx;
00875 
00876     *be++ = 0x80 | (PGPTAG_PUBLIC_KEY << 2) | 0x01;
00877     be += 2;
00878 
00879     *be++ = 0x04;
00880     *be++ = (bt >> 24);
00881     *be++ = (bt >> 16);
00882     *be++ = (bt >>  8);
00883     *be++ = (bt      );
00884     *be++ = pubp->pubkey_algo;
00885 
00886     bn = mpbits(bc->dsa_keypair.param.p.size, bc->dsa_keypair.param.p.modl);
00887     bn += 7; bn &= ~7;
00888     *be++ = (bn >> 8);  *be++ = (bn     );
00889     xx = i2osp(be, bn/8, bc->dsa_keypair.param.p.modl, bc->dsa_keypair.param.p.size);
00890     be += bn/8;
00891 
00892     bn = mpbits(bc->dsa_keypair.param.q.size, bc->dsa_keypair.param.q.modl);
00893     bn += 7; bn &= ~7;
00894     *be++ = (bn >> 8);  *be++ = (bn     );
00895     xx = i2osp(be, bn/8, bc->dsa_keypair.param.q.modl, bc->dsa_keypair.param.q.size);
00896     be += bn/8;
00897 
00898     bn = mpbits(bc->dsa_keypair.param.g.size, bc->dsa_keypair.param.g.data);
00899     bn += 7; bn &= ~7;
00900     *be++ = (bn >> 8);  *be++ = (bn     );
00901     xx = i2osp(be, bn/8, bc->dsa_keypair.param.g.data, bc->dsa_keypair.param.g.size);
00902     be += bn/8;
00903 
00904     bn = mpbits(bc->dsa_keypair.y.size, bc->dsa_keypair.y.data);
00905     bn += 7; bn &= ~7;
00906     *be++ = (bn >> 8);  *be++ = (bn     );
00907     xx = i2osp(be, bn/8, bc->dsa_keypair.y.data, bc->dsa_keypair.y.size);
00908     be += bn/8;
00909 
00910     pktlen = (be - pkt);
00911     bn = pktlen - 3;
00912     pkt[1] = (bn >> 8);
00913     pkt[2] = (bn     );
00914 
00915     xx = pgpPubkeyFingerprint(pkt, pktlen, pubp->signid);
00916 
00917     dig->pub = memcpy(xmalloc(pktlen), pkt, pktlen);
00918     dig->publen = pktlen;
00919 
00920     return 0;
00921 }
00922 
00923 int rpmbcExportSignature(pgpDig dig, /*@only@*/ DIGEST_CTX ctx)
00924 {
00925     uint8_t pkt[8192];
00926     uint8_t * be = pkt;
00927     uint8_t * h;
00928     size_t pktlen;
00929     time_t now = time(NULL);
00930     uint32_t bt;
00931     uint16_t bn;
00932     pgpDigParams pubp = pgpGetPubkey(dig);
00933     pgpDigParams sigp = pgpGetSignature(dig);
00934     rpmbc bc = dig->impl;
00935     int xx;
00936 
00937     sigp->tag = PGPTAG_SIGNATURE;
00938     *be++ = 0x80 | (sigp->tag << 2) | 0x01;
00939     be += 2;                            /* pktlen */
00940 
00941     sigp->hash = be;
00942     *be++ = sigp->version = 0x04;               /* version */
00943     *be++ = sigp->sigtype = PGPSIGTYPE_BINARY;  /* sigtype */
00944     *be++ = sigp->pubkey_algo = pubp->pubkey_algo;      /* pubkey_algo */
00945     *be++ = sigp->hash_algo;            /* hash_algo */
00946 
00947     be += 2;                            /* skip hashd length */
00948     h = (uint8_t *) be;
00949 
00950     *be++ = 1 + 4;                      /* signature creation time */
00951     *be++ = PGPSUBTYPE_SIG_CREATE_TIME;
00952     bt = now;
00953     *be++ = sigp->time[0] = (bt >> 24);
00954     *be++ = sigp->time[1] = (bt >> 16);
00955     *be++ = sigp->time[2] = (bt >>  8);
00956     *be++ = sigp->time[3] = (bt      );
00957 
00958     *be++ = 1 + 4;                      /* signature expiration time */
00959     *be++ = PGPSUBTYPE_SIG_EXPIRE_TIME;
00960     bt = 30 * 24 * 60 * 60;             /* XXX 30 days from creation */
00961     *be++ = sigp->expire[0] = (bt >> 24);
00962     *be++ = sigp->expire[1] = (bt >> 16);
00963     *be++ = sigp->expire[2] = (bt >>  8);
00964     *be++ = sigp->expire[3] = (bt      );
00965 
00966 /* key expiration time (only on a self-signature) */
00967 
00968     *be++ = 1 + 1;                      /* exportable certification */
00969     *be++ = PGPSUBTYPE_EXPORTABLE_CERT;
00970     *be++ = 0;
00971 
00972     *be++ = 1 + 1;                      /* revocable */
00973     *be++ = PGPSUBTYPE_REVOCABLE;
00974     *be++ = 0;
00975 
00976 /* notation data */
00977 
00978     sigp->hashlen = (be - h);           /* set hashed length */
00979     h[-2] = (sigp->hashlen >> 8);
00980     h[-1] = (sigp->hashlen     );
00981     sigp->hashlen += sizeof(struct pgpPktSigV4_s);
00982 
00983     if (sigp->hash != NULL)
00984         xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
00985 
00986     if (sigp->version == (rpmuint8_t) 4) {
00987         uint8_t trailer[6];
00988         trailer[0] = sigp->version;
00989         trailer[1] = (rpmuint8_t)0xff;
00990         trailer[2] = (sigp->hashlen >> 24);
00991         trailer[3] = (sigp->hashlen >> 16);
00992         trailer[4] = (sigp->hashlen >>  8);
00993         trailer[5] = (sigp->hashlen      );
00994         xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
00995     }
00996 
00997     sigp->signhash16[0] = 0x00;
00998     sigp->signhash16[1] = 0x00;
00999     xx = pgpImplSetDSA(ctx, dig, sigp); /* XXX signhash16 check always fails */
01000     h = bc->digest;
01001     sigp->signhash16[0] = h[0];
01002     sigp->signhash16[1] = h[1];
01003 
01004     xx = pgpImplSign(dig);
01005 assert(xx == 1);
01006 
01007     be += 2;                            /* skip unhashed length. */
01008     h = be;
01009 
01010     *be++ = 1 + 8;                      /* issuer key ID */
01011     *be++ = PGPSUBTYPE_ISSUER_KEYID;
01012     *be++ = pubp->signid[0];
01013     *be++ = pubp->signid[1];
01014     *be++ = pubp->signid[2];
01015     *be++ = pubp->signid[3];
01016     *be++ = pubp->signid[4];
01017     *be++ = pubp->signid[5];
01018     *be++ = pubp->signid[6];
01019     *be++ = pubp->signid[7];
01020 
01021     bt = (be - h);                      /* set unhashed length */
01022     h[-2] = (bt >> 8);
01023     h[-1] = (bt     );
01024 
01025     *be++ = sigp->signhash16[0];        /* signhash16 */
01026     *be++ = sigp->signhash16[1];
01027 
01028     bn = mpbits(bc->r.size, bc->r.data);
01029     bn += 7;    bn &= ~7;
01030     *be++ = (bn >> 8);
01031     *be++ = (bn     );
01032     xx = i2osp(be, bn/8, bc->r.data, bc->r.size);
01033     be += bn/8;
01034 
01035     bn = mpbits(bc->s.size, bc->s.data);
01036     bn += 7;    bn &= ~7;
01037     *be++ = (bn >> 8);
01038     *be++ = (bn     );
01039     xx = i2osp(be, bn/8, bc->s.data, bc->s.size);
01040     be += bn/8;
01041 
01042     pktlen = (be - pkt);                /* packet length */
01043     bn = pktlen - 3;
01044     pkt[1] = (bn >> 8);
01045     pkt[2] = (bn     );
01046 
01047     dig->sig = memcpy(xmalloc(pktlen), pkt, pktlen);
01048     dig->siglen = pktlen;
01049 
01050     return 0;
01051 
01052 }