• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

rpmio/rpmssl.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 #include <rpmlog.h>
00007 
00008 #include <rpmiotypes.h>
00009 #define _RPMPGP_INTERNAL
00010 #if defined(WITH_SSL)
00011 
00012 #if defined(__LCLINT__) && !defined(__i386__)
00013 #define __i386__
00014 #endif
00015 
00016 #define _RPMSSL_INTERNAL
00017 #include <rpmssl.h>
00018 #endif
00019 
00020 #include "debug.h"
00021 
00022 #if defined(WITH_SSL)
00023 
00024 /*@access pgpDig @*/
00025 /*@access pgpDigParams @*/
00026 
00027 /*@-redecl@*/
00028 /*@unchecked@*/
00029 extern int _pgp_debug;
00030 
00031 /*@unchecked@*/
00032 extern int _pgp_print;
00033 /*@=redecl@*/
00034 
00040 static
00041 unsigned char nibble(char c)
00042         /*@*/
00043 {
00044     if (c >= '0' && c <= '9')
00045         return (unsigned char) (c - '0');
00046     if (c >= 'A' && c <= 'F')
00047         return (unsigned char)((int)(c - 'A') + 10);
00048     if (c >= 'a' && c <= 'f')
00049         return (unsigned char)((int)(c - 'a') + 10);
00050     return (unsigned char) '\0';
00051 }
00052 
00053 /*@-modfilesys@*/
00054 static
00055 void hexdump(const char * msg, unsigned char * b, size_t blen)
00056         /*@*/
00057 {
00058     static const char hex[] = "0123456789abcdef";
00059 
00060     fprintf(stderr, "*** %s:", msg);
00061     if (b != NULL)
00062     while (blen > 0) {
00063         fprintf(stderr, "%c%c",
00064                 hex[ (unsigned)((*b >> 4) & 0x0f) ],
00065                 hex[ (unsigned)((*b     ) & 0x0f) ]);
00066         blen--;
00067         b++;
00068     }
00069     fprintf(stderr, "\n");
00070     return;
00071 }
00072 /*@=modfilesys@*/
00073 
00074 static
00075 int rpmsslSetRSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
00076         /*@modifies dig @*/
00077 {
00078     rpmssl ssl = dig->impl;
00079     unsigned int nbits = BN_num_bits(ssl->c);
00080     unsigned int nb = (nbits + 7) >> 3;
00081     const char * prefix = rpmDigestASN1(ctx);
00082     const char * hexstr;
00083     const char * s;
00084     rpmuint8_t signhash16[2];
00085     char * tt;
00086     int xx;
00087 
00088 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00089     if (prefix == NULL)
00090         return 1;
00091 
00092     xx = rpmDigestFinal(ctx, (void **)&dig->md5, &dig->md5len, 1);
00093     hexstr = tt = xmalloc(2 * nb + 1);
00094     memset(tt, (int) 'f', (2 * nb));
00095     tt[0] = '0'; tt[1] = '0';
00096     tt[2] = '0'; tt[3] = '1';
00097     tt += (2 * nb) - strlen(prefix) - strlen(dig->md5) - 2;
00098     *tt++ = '0'; *tt++ = '0';
00099     tt = stpcpy(tt, prefix);
00100     tt = stpcpy(tt, dig->md5);
00101 
00102     /* Set RSA hash. */
00103 /*@-moduncon -noeffectuncon @*/
00104     xx = BN_hex2bn(&ssl->rsahm, hexstr);
00105 /*@=moduncon =noeffectuncon @*/
00106 
00107 /*@-modfilesys@*/
00108 if (_pgp_debug < 0) fprintf(stderr, "*** rsahm: %s\n", hexstr);
00109     hexstr = _free(hexstr);
00110 /*@=modfilesys@*/
00111 
00112     /* Compare leading 16 bits of digest for quick check. */
00113     s = dig->md5;
00114 /*@-type@*/
00115     signhash16[0] = (rpmuint8_t) (nibble(s[0]) << 4) | nibble(s[1]);
00116     signhash16[1] = (rpmuint8_t) (nibble(s[2]) << 4) | nibble(s[3]);
00117 /*@=type@*/
00118     return memcmp(signhash16, sigp->signhash16, sizeof(sigp->signhash16));
00119 }
00120 
00121 static unsigned char * rpmsslBN2bin(const char * msg, const BIGNUM * s, size_t maxn)
00122 {
00123     unsigned char * t = xcalloc(1, maxn);
00124 /*@-modunconnomods@*/
00125     size_t nt = BN_bn2bin(s, t);
00126 /*@=modunconnomods@*/
00127 
00128     if (nt < maxn) {
00129         size_t pad = (maxn - nt);
00130 /*@-modfilesys@*/
00131 if (_pgp_debug < 0) fprintf(stderr, "\tmemmove(%p, %p, %u)\n", t+pad, t, (unsigned)nt);
00132 /*@=modfilesys@*/
00133         memmove(t+pad, t, nt);
00134 /*@-modfilesys@*/
00135 if (_pgp_debug < 0) fprintf(stderr, "\tmemset(%p, 0, %u)\n", t, (unsigned)pad);
00136 /*@=modfilesys@*/
00137         memset(t, 0, pad);
00138     }
00139 /*@-modfilesys@*/
00140 if (_pgp_debug < 0) hexdump(msg, t, maxn);
00141 /*@=modfilesys@*/
00142     return t;
00143 }
00144 
00145 static
00146 int rpmsslVerifyRSA(pgpDig dig)
00147         /*@*/
00148 {
00149     rpmssl ssl = dig->impl;
00150 /*@-moduncon@*/
00151     size_t maxn = BN_num_bytes(ssl->rsa->n);
00152     unsigned char * hm = rpmsslBN2bin("hm", ssl->rsahm, maxn);
00153     unsigned char *  c = rpmsslBN2bin(" c", ssl->c, maxn);
00154     size_t nb = RSA_public_decrypt((int)maxn, c, c, ssl->rsa, RSA_PKCS1_PADDING);
00155 /*@=moduncon@*/
00156     size_t i;
00157     int rc = 0;
00158     int xx;
00159 
00160     /* Verify RSA signature. */
00161     /* XXX This is _NOT_ the correct openssl function to use:
00162      *  rc = RSA_verify(type, m, m_len, sigbuf, siglen, ssl->rsa)
00163      *
00164      * Here's what needs doing (from OpenPGP reference sources in 1999):
00165      *  static u32_t checkrsa(BIGNUM * a, RSA * key, u8_t * hash, int hlen)
00166      *  {
00167      *    u8_t dbuf[MAXSIGM];
00168      *    int j, ll;
00169      *
00170      *    j = BN_bn2bin(a, dbuf);
00171      *    ll = BN_num_bytes(key->n);
00172      *    while (j < ll)
00173      *      memmove(&dbuf[1], dbuf, j++), dbuf[0] = 0;
00174      *    j = RSA_public_decrypt(ll, dbuf, dbuf, key, RSA_PKCS1_PADDING);
00175      *    RSA_free(key);
00176      *    return (j != hlen || memcmp(dbuf, hash, j));
00177      *  }
00178      */
00179     for (i = 2; i < maxn; i++) {
00180         if (hm[i] == 0xff)
00181             continue;
00182         i++;
00183 /*@-modfilesys@*/
00184 if (_pgp_debug < 0) hexdump("HM", hm + i, (maxn - i));
00185 /*@=modfilesys@*/
00186         break;
00187     }
00188 
00189 /*@-modfilesys@*/
00190 if (_pgp_debug < 0) hexdump("HM", hm + (maxn - nb), nb);
00191 if (_pgp_debug < 0) hexdump(" C",  c, nb);
00192 /*@=modfilesys@*/
00193 
00194     rc = ((maxn - i) == nb && (xx = memcmp(hm+i, c, nb)) == 0);
00195 
00196     c = _free(c);
00197     hm = _free(hm);
00198 
00199     return rc;
00200 }
00201 
00202 static
00203 int rpmsslSetDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
00204         /*@modifies dig @*/
00205 {
00206     int xx;
00207 
00208 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00209     /* Set DSA hash. */
00210     xx = rpmDigestFinal(ctx, (void **)&dig->sha1, &dig->sha1len, 0);
00211 
00212     /* Compare leading 16 bits of digest for quick check. */
00213     return memcmp(dig->sha1, sigp->signhash16, sizeof(sigp->signhash16));
00214 }
00215 
00216 static
00217 int rpmsslVerifyDSA(pgpDig dig)
00218         /*@*/
00219 {
00220     rpmssl ssl = dig->impl;
00221     int rc;
00222 
00223     /* Verify DSA signature. */
00224 /*@-moduncon@*/
00225     rc = (DSA_do_verify(dig->sha1, (int)dig->sha1len, ssl->dsasig, ssl->dsa) == 1);
00226 /*@=moduncon@*/
00227 
00228     return rc;
00229 }
00230 
00231 
00232 static
00233 int rpmsslSetECDSA(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp)
00234         /*@*/
00235 {
00236     int rc = 1;         /* XXX always fail. */
00237     int xx;
00238 
00239 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00240     xx = rpmDigestFinal(ctx, (void **)NULL, NULL, 0);
00241 
00242     /* Compare leading 16 bits of digest for quick check. */
00243 
00244     return rc;
00245 }
00246 
00247 static
00248 int rpmsslVerifyECDSA(/*@unused@*/pgpDig dig)
00249         /*@*/
00250 {
00251     int rc = 0;         /* XXX always fail. */
00252 
00253     return rc;
00254 }
00255 
00256 static
00257 int rpmsslMpiItem(/*@unused@*/ const char * pre, pgpDig dig, int itemno,
00258                 const rpmuint8_t * p,
00259                 /*@unused@*/ /*@null@*/ const rpmuint8_t * pend)
00260         /*@*/
00261 {
00262     rpmssl ssl = dig->impl;
00263     unsigned int nb = ((pgpMpiBits(p) + 7) >> 3);
00264     int rc = 0;
00265 
00266 /*@-moduncon@*/
00267     switch (itemno) {
00268     default:
00269 assert(0);
00270         break;
00271     case 10:            /* RSA m**d */
00272         ssl->c = BN_bin2bn(p+2, nb, ssl->c);
00273         break;
00274     case 20:            /* DSA r */
00275         if (ssl->dsasig == NULL) ssl->dsasig = DSA_SIG_new();
00276         ssl->dsasig->r = BN_bin2bn(p+2, nb, ssl->dsasig->r);
00277         break;
00278     case 21:            /* DSA s */
00279         if (ssl->dsasig == NULL) ssl->dsasig = DSA_SIG_new();
00280         ssl->dsasig->s = BN_bin2bn(p+2, nb, ssl->dsasig->s);
00281         break;
00282     case 30:            /* RSA n */
00283         if (ssl->rsa == NULL) ssl->rsa = RSA_new();
00284         ssl->rsa->n = BN_bin2bn(p+2, nb, ssl->rsa->n);
00285         break;
00286     case 31:            /* RSA e */
00287         if (ssl->rsa == NULL) ssl->rsa = RSA_new();
00288         ssl->rsa->e = BN_bin2bn(p+2, nb, ssl->rsa->e);
00289         break;
00290     case 40:            /* DSA p */
00291         if (ssl->dsa == NULL) ssl->dsa = DSA_new();
00292         ssl->dsa->p = BN_bin2bn(p+2, nb, ssl->dsa->p);
00293         break;
00294     case 41:            /* DSA q */
00295         if (ssl->dsa == NULL) ssl->dsa = DSA_new();
00296         ssl->dsa->q = BN_bin2bn(p+2, nb, ssl->dsa->q);
00297         break;
00298     case 42:            /* DSA g */
00299         if (ssl->dsa == NULL) ssl->dsa = DSA_new();
00300         ssl->dsa->g = BN_bin2bn(p+2, nb, ssl->dsa->g);
00301         break;
00302     case 43:            /* DSA y */
00303         if (ssl->dsa == NULL) ssl->dsa = DSA_new();
00304         ssl->dsa->pub_key = BN_bin2bn(p+2, nb, ssl->dsa->pub_key);
00305         break;
00306     }
00307 /*@=moduncon@*/
00308     return rc;
00309 }
00310 
00311 /*@-mustmod@*/
00312 static
00313 void rpmsslClean(void * impl)
00314         /*@modifies impl @*/
00315 {
00316     rpmssl ssl = impl;
00317 /*@-moduncon@*/
00318     if (ssl != NULL) {
00319         if (ssl->dsa) {
00320             DSA_free(ssl->dsa);
00321             ssl->dsa = NULL;
00322         }
00323         if (ssl->dsasig) {
00324             DSA_SIG_free(ssl->dsasig);
00325             ssl->dsasig = NULL;
00326         }
00327         if (ssl->rsa) {
00328             RSA_free(ssl->rsa);
00329             ssl->rsa = NULL;
00330         }
00331         if (ssl->c) {
00332             BN_free(ssl->c);
00333             ssl->c = NULL;
00334         }
00335     }
00336 /*@=moduncon@*/
00337 }
00338 /*@=mustmod@*/
00339 
00340 static /*@null@*/
00341 void * rpmsslFree(/*@only@*/ void * impl)
00342         /*@modifies impl @*/
00343 {
00344     rpmssl ssl = impl;
00345     rpmsslClean(impl);
00346     ssl = _free(ssl);
00347     return NULL;
00348 }
00349 
00350 static
00351 void * rpmsslInit(void)
00352         /*@*/
00353 {
00354     rpmssl ssl = xcalloc(1, sizeof(*ssl));
00355 /*@-moduncon@*/
00356     ERR_load_crypto_strings();
00357 /*@=moduncon@*/
00358     return (void *) ssl;
00359 }
00360 
00361 struct pgpImplVecs_s rpmsslImplVecs = {
00362         rpmsslSetRSA, rpmsslVerifyRSA,
00363         rpmsslSetDSA, rpmsslVerifyDSA,
00364         rpmsslSetECDSA, rpmsslVerifyECDSA,
00365         rpmsslMpiItem, rpmsslClean,
00366         rpmsslFree, rpmsslInit
00367 };
00368 
00369 #endif
00370 

Generated on Fri Dec 3 2010 20:54:40 for rpm by  doxygen 1.7.2