rpm 5.2.1

- 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