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