rpm 5.2.1

rpmio/rpmgc.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #include <rpmiotypes.h>
00008 #define _RPMGC_INTERNAL
00009 #if defined(WITH_GCRYPT)
00010 #define _RPMPGP_INTERNAL
00011 #include <rpmgc.h>
00012 #endif
00013 
00014 #include "debug.h"
00015 
00016 #if defined(WITH_GCRYPT)
00017 
00018 /*@access pgpDig @*/
00019 /*@access pgpDigParams @*/
00020 
00021 /*@-redecl@*/
00022 /*@unchecked@*/
00023 extern int _pgp_debug;
00024 
00025 /*@unchecked@*/
00026 extern int _pgp_print;
00027 /*@=redecl@*/
00028 
00029 static
00030 void rpmgcDump(const char * msg, gcry_sexp_t sexp)
00031         /*@*/
00032 {
00033     size_t nb = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
00034     char * buf = alloca(nb+1);
00035 
00036 /*@-modunconnomods @*/
00037     nb = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, buf, nb);
00038 /*@=modunconnomods @*/
00039     buf[nb] = '\0';
00040 /*@-modfilesys@*/
00041 if (_pgp_debug)
00042 fprintf(stderr, "========== %s:\n%s", msg, buf);
00043 /*@=modfilesys@*/
00044     return;
00045 }
00046 
00047 static
00048 gcry_error_t rpmgcErr(/*@unused@*/rpmgc gc, const char * msg, gcry_error_t err)
00049         /*@*/
00050 {
00051 /*@-evalorderuncon -modfilesys -moduncon @*/
00052     if (err) {
00053         fprintf (stderr, "rpmgc: %s: %s/%s\n",
00054                 msg, gcry_strsource (err), gcry_strerror (err));
00055     }
00056 /*@=evalorderuncon =modfilesys =moduncon @*/
00057     return err;
00058 }
00059 
00060 static
00061 int rpmgcSetRSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
00062         /*@modifies dig @*/
00063 {
00064     rpmgc gc = dig->impl;
00065     const char * hash_algo_name = NULL;
00066     int rc;
00067     int xx;
00068 
00069     switch (sigp->hash_algo) {
00070     case PGPHASHALGO_MD5:
00071         hash_algo_name = "md5";
00072         break;
00073     case PGPHASHALGO_SHA1:
00074         hash_algo_name = "sha1";
00075         break;
00076     case PGPHASHALGO_RIPEMD160:
00077         hash_algo_name = "ripemd160";
00078         break;
00079     case PGPHASHALGO_MD2:
00080         hash_algo_name = "md2";
00081         break;
00082     case PGPHASHALGO_TIGER192:
00083         hash_algo_name = "tiger";
00084         break;
00085     case PGPHASHALGO_HAVAL_5_160:
00086 #ifdef  NOTYET
00087         hash_algo_name = "haval";
00088 #endif
00089         break;
00090     case PGPHASHALGO_SHA256:
00091         hash_algo_name = "sha256";
00092         break;
00093     case PGPHASHALGO_SHA384:
00094         hash_algo_name = "sha384";
00095         break;
00096     case PGPHASHALGO_SHA512:
00097         hash_algo_name = "sha512";
00098         break;
00099     case PGPHASHALGO_SHA224:
00100 #ifdef  NOTYET
00101         hash_algo_name = "sha224";
00102 #endif
00103         break;
00104     default:
00105         break;
00106     }
00107     if (hash_algo_name == NULL)
00108         return 1;
00109 
00110     xx = rpmDigestFinal(ctx, (void **)&dig->md5, &dig->md5len, 0);
00111 
00112     /* Set RSA hash. */
00113 /*@-moduncon -noeffectuncon @*/
00114     {   gcry_mpi_t c = NULL;
00115         gcry_error_t yy;
00116         xx = gcry_mpi_scan(&c, GCRYMPI_FMT_USG, dig->md5, dig->md5len, NULL);
00117         yy = rpmgcErr(gc, "RSA c",
00118                 gcry_sexp_build(&gc->hash, NULL,
00119                         "(data (flags pkcs1) (hash %s %m))", hash_algo_name, c) );
00120         gcry_mpi_release(c);
00121 if (_pgp_debug < 0) rpmgcDump("gc->hash", gc->hash);
00122     }
00123 /*@=moduncon =noeffectuncon @*/
00124 
00125     /* Compare leading 16 bits of digest for quick check. */
00126     {   const rpmuint8_t *s = dig->md5;
00127         const rpmuint8_t *t = sigp->signhash16;
00128         rc = memcmp(s, t, sizeof(sigp->signhash16));
00129 #ifdef  DYING
00130         if (rc != 0)
00131             fprintf(stderr, "*** hash fails: digest(%02x%02x) != signhash(%02x%02x)\n",
00132                 s[0], s[1], t[0], t[1]);
00133 #endif
00134     }
00135 
00136     return rc;
00137 }
00138 
00139 static
00140 int rpmgcVerifyRSA(pgpDig dig)
00141         /*@*/
00142 {
00143     rpmgc gc = dig->impl;
00144     gcry_error_t err;
00145 
00146 /*@-moduncon@*/
00147     err = rpmgcErr(gc, "RSA gc->sig",
00148                 gcry_sexp_build(&gc->sig, NULL,
00149                         "(sig-val (RSA (s %m)))", gc->c) );
00150 /*@=moduncon@*/
00151 if (_pgp_debug < 0)
00152 rpmgcDump("gc->sig", gc->sig);
00153 /*@-moduncon@*/
00154     err = rpmgcErr(gc, "RSA gc->pkey",
00155                 gcry_sexp_build(&gc->pkey, NULL,
00156                         "(public-key (RSA (n %m) (e %m)))", gc->n, gc->e) );
00157 /*@=moduncon@*/
00158 if (_pgp_debug < 0)
00159 rpmgcDump("gc->pkey", gc->pkey);
00160 
00161     /* Verify RSA signature. */
00162 /*@-moduncon@*/
00163     err = rpmgcErr(gc, "RSA verify",
00164                 gcry_pk_verify (gc->sig, gc->hash, gc->pkey) );
00165 /*@=moduncon@*/
00166 
00167     gcry_sexp_release(gc->pkey);        gc->pkey = NULL;
00168     gcry_sexp_release(gc->hash);        gc->hash = NULL;
00169     gcry_sexp_release(gc->sig);         gc->sig = NULL;
00170 
00171     return (err ? 0 : 1);
00172 }
00173 
00174 static
00175 int rpmgcSetDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
00176         /*@modifies dig @*/
00177 {
00178     rpmgc gc = dig->impl;
00179     gcry_error_t err;
00180     int xx;
00181 
00182 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00183     xx = rpmDigestFinal(ctx, (void **)&dig->sha1, &dig->sha1len, 0);
00184 
00185     /* Set DSA hash. */
00186     err = rpmgcErr(gc, "DSA gc->hash",
00187                 gcry_sexp_build(&gc->hash, NULL,
00188                         "(data (flags raw) (value %b))", dig->sha1len, dig->sha1) );
00189 if (_pgp_debug < 0)
00190 rpmgcDump("gc->hash", gc->hash);
00191 
00192     /* Compare leading 16 bits of digest for quick check. */
00193     return memcmp(dig->sha1, sigp->signhash16, sizeof(sigp->signhash16));
00194 }
00195 
00196 static
00197 int rpmgcVerifyDSA(pgpDig dig)
00198         /*@*/
00199 {
00200     rpmgc gc = dig->impl;
00201     gcry_error_t err;
00202 
00203 /*@-moduncon -noeffectuncon @*/
00204 
00205     err = rpmgcErr(gc, "DSA gc->sig",
00206                 gcry_sexp_build(&gc->sig, NULL,
00207                         "(sig-val (DSA (r %m) (s %m)))", gc->r, gc->s) );
00208 if (_pgp_debug < 0)
00209 rpmgcDump("gc->sig", gc->sig);
00210     err = rpmgcErr(gc, "DSA gc->pkey",
00211                 gcry_sexp_build(&gc->pkey, NULL,
00212                         "(public-key (DSA (p %m) (q %m) (g %m) (y %m)))",
00213                         gc->p, gc->q, gc->g, gc->y) );
00214 if (_pgp_debug < 0)
00215 rpmgcDump("gc->pkey", gc->pkey);
00216 
00217     /* Verify DSA signature. */
00218     err = rpmgcErr(gc, "DSA verify",
00219                 gcry_pk_verify (gc->sig, gc->hash, gc->pkey) );
00220 
00221     gcry_sexp_release(gc->pkey);        gc->pkey = NULL;
00222     gcry_sexp_release(gc->hash);        gc->hash = NULL;
00223     gcry_sexp_release(gc->sig);         gc->sig = NULL;
00224 
00225 /*@=moduncon -noeffectuncon @*/
00226 
00227     return (err ? 0 : 1);
00228 }
00229 
00230 
00231 static
00232 int rpmgcSetECDSA(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp)
00233         /*@*/
00234 {
00235     int rc = 1;         /* XXX always fail. */
00236     int xx;
00237 
00238 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00239     xx = rpmDigestFinal(ctx, (void **)NULL, NULL, 0);
00240 
00241     /* Compare leading 16 bits of digest for quick check. */
00242 
00243     return rc;
00244 }
00245 
00246 static
00247 int rpmgcVerifyECDSA(/*@unused@*/pgpDig dig)
00248         /*@*/
00249 {
00250     int rc = 0;         /* XXX always fail. */
00251 
00252     return rc;
00253 }
00254 
00255 /*@-globuse -mustmod @*/
00256 static
00257 int rpmgcMpiItem(/*@unused@*/ const char * pre, pgpDig dig, int itemno,
00258                 const rpmuint8_t * p,
00259                 /*@unused@*/ /*@null@*/ const rpmuint8_t * pend)
00260         /*@globals fileSystem @*/
00261         /*@modifies dig, fileSystem @*/
00262 {
00263     rpmgc gc = dig->impl;
00264     size_t nb = pgpMpiLen(p);
00265     const char * mpiname = "";
00266     gcry_mpi_t * mpip = NULL;
00267     size_t nscan = 0;
00268     gcry_error_t err;
00269     int rc = 0;
00270 
00271     switch (itemno) {
00272     default:
00273 assert(0);
00274         break;
00275     case 10:            /* RSA m**d */
00276         mpiname ="RSA m**d";    mpip = &gc->c;
00277         break;
00278     case 20:            /* DSA r */
00279         mpiname = "DSA r";      mpip = &gc->r;
00280         break;
00281     case 21:            /* DSA s */
00282         mpiname = "DSA s";      mpip = &gc->s;
00283         break;
00284     case 30:            /* RSA n */
00285         mpiname = "RSA n";      mpip = &gc->n;
00286         break;
00287     case 31:            /* RSA e */
00288         mpiname = "RSA e";      mpip = &gc->e;
00289         break;
00290     case 40:            /* DSA p */
00291         mpiname = "DSA p";      mpip = &gc->p;
00292         break;
00293     case 41:            /* DSA q */
00294         mpiname = "DSA q";      mpip = &gc->q;
00295         break;
00296     case 42:            /* DSA g */
00297         mpiname = "DSA g";      mpip = &gc->g;
00298         break;
00299     case 43:            /* DSA y */
00300         mpiname = "DSA y";      mpip = &gc->y;
00301         break;
00302     }
00303 
00304 /*@-moduncon -noeffectuncon @*/
00305     err = rpmgcErr(gc, mpiname,
00306                 gcry_mpi_scan(mpip, GCRYMPI_FMT_PGP, p, nb, &nscan) );
00307 /*@=moduncon =noeffectuncon @*/
00308 
00309     if (_pgp_debug < 0)
00310     {   size_t nbits = gcry_mpi_get_nbits(*mpip);
00311         unsigned char * hex = NULL;
00312         size_t nhex = 0;
00313         err = rpmgcErr(gc, "MPI print",
00314                 gcry_mpi_aprint(GCRYMPI_FMT_HEX, &hex, &nhex, *mpip) );
00315         fprintf(stderr, "*** %s\t%5d:%s\n", mpiname, (int)nbits, hex);
00316         hex = _free(hex);
00317     }
00318 
00319     return rc;
00320 }
00321 /*@=globuse =mustmod @*/
00322 
00323 /*@-mustmod@*/
00324 static
00325 void rpmgcClean(void * impl)
00326         /*@modifies impl @*/
00327 {
00328     rpmgc gc = impl;
00329 /*@-moduncon -noeffectuncon @*/
00330     if (gc != NULL) {
00331         if (gc->sig) {
00332             gcry_sexp_release(gc->sig);
00333             gc->sig = NULL;
00334         }
00335         if (gc->hash) {
00336             gcry_sexp_release(gc->hash);
00337             gc->hash = NULL;
00338         }
00339         if (gc->pkey) {
00340             gcry_sexp_release(gc->pkey);
00341             gc->pkey = NULL;
00342         }
00343         if (gc->r) {
00344             gcry_mpi_release(gc->r);
00345             gc->r = NULL;
00346         }
00347         if (gc->s) {
00348             gcry_mpi_release(gc->s);
00349             gc->s = NULL;
00350         }
00351         if (gc->n) {
00352             gcry_mpi_release(gc->n);
00353             gc->n = NULL;
00354         }
00355         if (gc->e) {
00356             gcry_mpi_release(gc->e);
00357             gc->e = NULL;
00358         }
00359         if (gc->c) {
00360             gcry_mpi_release(gc->c);
00361             gc->c = NULL;
00362         }
00363         if (gc->p) {
00364             gcry_mpi_release(gc->p);
00365             gc->p = NULL;
00366         }
00367         if (gc->q) {
00368             gcry_mpi_release(gc->q);
00369             gc->q = NULL;
00370         }
00371         if (gc->g) {
00372             gcry_mpi_release(gc->g);
00373             gc->g = NULL;
00374         }
00375         if (gc->y) {
00376             gcry_mpi_release(gc->y);
00377             gc->y = NULL;
00378         }
00379     }
00380 /*@=moduncon =noeffectuncon @*/
00381 }
00382 /*@=mustmod@*/
00383 
00384 /*@unchecked@*/
00385 static int rpmgc_initialized;
00386 
00387 static /*@null@*/
00388 void * rpmgcFree(/*@only@*/ void * impl)
00389         /*@globals rpmgc_initialized @*/
00390         /*@modifies impl, rpmgc_initialized @*/
00391 {
00392     rpmgc gc = impl;
00393 
00394     rpmgcClean(impl);
00395 
00396     if (--rpmgc_initialized == 0 && _pgp_debug < 0) {
00397         gcry_error_t err;
00398         err = rpmgcErr(gc, "CLEAR_DEBUG_FLAGS",
00399                 gcry_control(GCRYCTL_CLEAR_DEBUG_FLAGS, 3));
00400         err = rpmgcErr(gc, "SET_VERBOSITY",
00401                 gcry_control(GCRYCTL_SET_VERBOSITY, 0) );
00402     }
00403 
00404     gc = _free(gc);
00405 
00406     return NULL;
00407 }
00408 
00409 static
00410 void * rpmgcInit(void)
00411         /*@globals rpmgc_initialized @*/
00412         /*@modifies rpmgc_initialized @*/
00413 {
00414     rpmgc gc = xcalloc(1, sizeof(*gc));
00415 
00416     if (rpmgc_initialized++ == 0 && _pgp_debug < 0) {
00417         gcry_error_t err;
00418         err = rpmgcErr(gc, "SET_VERBOSITY",
00419                 gcry_control(GCRYCTL_SET_VERBOSITY, 3) );
00420         err = rpmgcErr(gc, "SET_DEBUG_FLAGS",
00421                 gcry_control(GCRYCTL_SET_DEBUG_FLAGS, 3) );
00422     }
00423 
00424     return (void *) gc;
00425 }
00426 
00427 struct pgpImplVecs_s rpmgcImplVecs = {
00428         rpmgcSetRSA, rpmgcVerifyRSA,
00429         rpmgcSetDSA, rpmgcVerifyDSA,
00430         rpmgcSetECDSA, rpmgcVerifyECDSA,
00431         rpmgcMpiItem, rpmgcClean,
00432         rpmgcFree, rpmgcInit
00433 };
00434 
00435 #endif
00436