rpm  5.2.1
rpmio/rpmnss.c
Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #include <rpmiotypes.h>
00008 #define _RPMPGP_INTERNAL
00009 #if defined(WITH_NSS)
00010 #define _RPMNSS_INTERNAL
00011 #include <rpmnss.h>
00012 #endif
00013 
00014 #include "debug.h"
00015 
00016 #if defined(WITH_NSS)
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 /*@unchecked@*/
00030 extern int _rpmnss_init;
00031 
00032 static
00033 int rpmnssSetRSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
00034         /*@modifies dig @*/
00035 {
00036     rpmnss nss = dig->impl;
00037     int xx;
00038 
00039 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00040     nss->sigalg = SEC_OID_UNKNOWN;
00041     switch (sigp->hash_algo) {
00042     case PGPHASHALGO_MD5:
00043         nss->sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
00044         break;
00045     case PGPHASHALGO_SHA1:
00046         nss->sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
00047         break;
00048     case PGPHASHALGO_RIPEMD160:
00049         break;
00050     case PGPHASHALGO_MD2:
00051         nss->sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
00052         break;
00053     case PGPHASHALGO_MD4:
00054         nss->sigalg = SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION;
00055         break;
00056     case PGPHASHALGO_TIGER192:
00057         break;
00058     case PGPHASHALGO_HAVAL_5_160:
00059         break;
00060     case PGPHASHALGO_SHA256:
00061         nss->sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
00062         break;
00063     case PGPHASHALGO_SHA384:
00064         nss->sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
00065         break;
00066     case PGPHASHALGO_SHA512:
00067         nss->sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
00068         break;
00069     case PGPHASHALGO_SHA224:
00070         break;
00071     default:
00072         break;
00073     }
00074     if (nss->sigalg == SEC_OID_UNKNOWN)
00075         return 1;
00076 
00077     xx = rpmDigestFinal(ctx, (void **)&dig->md5, &dig->md5len, 0);
00078 
00079     /* Compare leading 16 bits of digest for quick check. */
00080     return memcmp(dig->md5, sigp->signhash16, sizeof(sigp->signhash16));
00081 }
00082 
00083 static
00084 int rpmnssVerifyRSA(pgpDig dig)
00085         /*@*/
00086 {
00087     rpmnss nss = dig->impl;
00088     int rc;
00089 
00090     nss->item.type = siBuffer;
00091     nss->item.data = dig->md5;
00092     nss->item.len = (unsigned) dig->md5len;
00093 
00094 /*@-moduncon -nullstate @*/
00095     rc = (VFY_VerifyDigest(&nss->item, nss->rsa, nss->rsasig, nss->sigalg, NULL) == SECSuccess);
00096 /*@=moduncon =nullstate @*/
00097 
00098     return rc;
00099 }
00100 
00101 static
00102 int rpmnssSetDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
00103         /*@modifies dig @*/
00104 {
00105     rpmnss nss = dig->impl;
00106     int xx;
00107 
00108 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00109     xx = rpmDigestFinal(ctx, (void **)&dig->sha1, &dig->sha1len, 0);
00110 
00111     nss->sigalg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
00112 
00113     /* Compare leading 16 bits of digest for quick check. */
00114     return memcmp(dig->sha1, sigp->signhash16, sizeof(sigp->signhash16));
00115 }
00116 
00117 static
00118 int rpmnssVerifyDSA(pgpDig dig)
00119         /*@*/
00120 {
00121     rpmnss nss = dig->impl;
00122     int rc;
00123 
00124     nss->item.type = siBuffer;
00125     nss->item.data = dig->sha1;
00126     nss->item.len = (unsigned) dig->sha1len;
00127 
00128 /*@-moduncon -nullstate @*/
00129     rc = (VFY_VerifyDigest(&nss->item, nss->dsa, nss->dsasig, nss->sigalg, NULL) == SECSuccess);
00130 /*@=moduncon =nullstate @*/
00131 
00132     return rc;
00133 }
00134 
00135 static
00136 int rpmnssSetECDSA(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp)
00137         /*@*/
00138 {
00139     int rc = 1;         /* XXX always fail. */
00140     int xx;
00141 
00142 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00143     xx = rpmDigestFinal(ctx, (void **)NULL, NULL, 0);
00144 
00145     /* Compare leading 16 bits of digest for quick check. */
00146 
00147     return rc;
00148 }
00149 
00150 static
00151 int rpmnssVerifyECDSA(/*@unused@*/pgpDig dig)
00152         /*@*/
00153 {
00154     int rc = 0;         /* XXX always fail. */
00155 
00156     return rc;
00157 }
00158 
00162 static
00163 int rpmnssMpiSet(const char * pre, unsigned int lbits,
00164                 /*@out@*/ void * dest, const rpmuint8_t * p,
00165                 /*@null@*/ const rpmuint8_t * pend)
00166         /*@modifies *dest @*/
00167 {
00168     unsigned int mbits = pgpMpiBits(p);
00169     unsigned int nbits;
00170     unsigned int nbytes;
00171     char * t = dest;
00172     unsigned int ix;
00173 
00174     if (pend != NULL && (p + ((mbits+7) >> 3)) > pend)
00175         return 1;
00176 
00177     if (mbits > lbits)
00178         return 1;
00179 
00180     nbits = (lbits > mbits ? lbits : mbits);
00181     nbytes = ((nbits + 7) >> 3);
00182     ix = ((nbits - mbits) >> 3);
00183 
00184 /*@-modfilesystem @*/
00185 if (_pgp_debug)
00186 fprintf(stderr, "*** mbits %u nbits %u nbytes %u ix %u\n", mbits, nbits, nbytes, ix);
00187     if (ix > 0) memset(t, (int)'\0', ix);
00188     memcpy(t+ix, p+2, nbytes-ix);
00189 if (_pgp_debug && _pgp_print)
00190 fprintf(stderr, "\t %s %s", pre, pgpHexStr(dest, nbytes));
00191 /*@=modfilesystem @*/
00192     return 0;
00193 }
00194 
00198 static
00199 /*@only@*/ /*@null@*/
00200 SECItem * rpmnssMpiCopy(PRArenaPool * arena, /*@returned@*/ SECItem * item,
00201                 const rpmuint8_t * p)
00202         /*@modifies item @*/
00203 {
00204     unsigned int nbytes = pgpMpiLen(p)-2;
00205 
00206 /*@-moduncon@*/
00207     if (item == NULL) {
00208         if ((item = SECITEM_AllocItem(arena, item, nbytes)) == NULL)
00209             return item;
00210     } else {
00211         if (arena != NULL)
00212             item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
00213         else
00214             item->data = PORT_Realloc(item->data, nbytes);
00215         
00216         if (item->data == NULL) {
00217             if (arena == NULL)
00218                 SECITEM_FreeItem(item, PR_TRUE);
00219             return NULL;
00220         }
00221     }
00222 /*@=moduncon@*/
00223 
00224     memcpy(item->data, p+2, nbytes);
00225     item->len = nbytes;
00226 /*@-temptrans@*/
00227     return item;
00228 /*@=temptrans@*/
00229 }
00230 
00231 static /*@null@*/
00232 SECKEYPublicKey * rpmnssNewPublicKey(KeyType type)
00233         /*@*/
00234 {
00235     PRArenaPool *arena;
00236     SECKEYPublicKey *key;
00237 
00238 /*@-moduncon@*/
00239     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00240     if (arena == NULL)
00241         return NULL;
00242 
00243     key = PORT_ArenaZAlloc(arena, sizeof(*key));
00244 
00245     if (key == NULL) {
00246         PORT_FreeArena(arena, PR_FALSE);
00247         return NULL;
00248     }
00249 /*@=moduncon@*/
00250     
00251     key->keyType = type;
00252     key->pkcs11ID = CK_INVALID_HANDLE;
00253     key->pkcs11Slot = NULL;
00254     key->arena = arena;
00255 /*@-nullret@*/  /* key->pkcs11Slot can be NULL */
00256     return key;
00257 /*@=nullret@*/
00258 }
00259 
00260 static
00261 int rpmnssMpiItem(const char * pre, pgpDig dig, int itemno,
00262                 const rpmuint8_t * p, /*@null@*/ const rpmuint8_t * pend)
00263         /*@*/
00264 {
00265     rpmnss nss = dig->impl;
00266     int rc = 0;
00267 
00268 /*@-moduncon@*/
00269     switch (itemno) {
00270     default:
00271 assert(0);
00272         break;
00273     case 10:            /* RSA m**d */
00274         nss->rsasig = rpmnssMpiCopy(NULL, nss->rsasig, p);
00275         if (nss->rsasig == NULL)
00276             rc = 1;
00277         break;
00278     case 20:            /* DSA r */
00279         nss->item.type = 0;
00280         nss->item.len = 2 * (160/8);
00281         nss->item.data = xcalloc(1, nss->item.len);
00282         rc = rpmnssMpiSet(pre, 160, nss->item.data, p, pend);
00283         break;
00284     case 21:            /* DSA s */
00285         rc = rpmnssMpiSet(pre, 160, nss->item.data + (160/8), p, pend);
00286         if (nss->dsasig != NULL)
00287             SECITEM_FreeItem(nss->dsasig, PR_FALSE);
00288         if ((nss->dsasig = SECITEM_AllocItem(NULL, NULL, 0)) == NULL
00289          || DSAU_EncodeDerSig(nss->dsasig, &nss->item) != SECSuccess)
00290             rc = 1;
00291         nss->item.data = _free(nss->item.data);
00292         break;
00293     case 30:            /* RSA n */
00294         if (nss->rsa == NULL)
00295             nss->rsa = rpmnssNewPublicKey(rsaKey);
00296         if (nss->rsa == NULL)
00297             rc = 1;
00298         else
00299             (void) rpmnssMpiCopy(nss->rsa->arena, &nss->rsa->u.rsa.modulus, p);
00300         break;
00301     case 31:            /* RSA e */
00302         if (nss->rsa == NULL)
00303             nss->rsa = rpmnssNewPublicKey(rsaKey);
00304         if (nss->rsa == NULL)
00305             rc = 1;
00306         else
00307             (void) rpmnssMpiCopy(nss->rsa->arena, &nss->rsa->u.rsa.publicExponent, p);
00308         break;
00309     case 40:            /* DSA p */
00310         if (nss->dsa == NULL)
00311             nss->dsa = rpmnssNewPublicKey(dsaKey);
00312         if (nss->dsa == NULL)
00313             rc = 1;
00314         else
00315             (void) rpmnssMpiCopy(nss->dsa->arena, &nss->dsa->u.dsa.params.prime, p);
00316         break;
00317     case 41:            /* DSA q */
00318         if (nss->dsa == NULL)
00319             nss->dsa = rpmnssNewPublicKey(dsaKey);
00320         if (nss->dsa == NULL)
00321             rc = 1;
00322         else
00323             (void) rpmnssMpiCopy(nss->dsa->arena, &nss->dsa->u.dsa.params.subPrime, p);
00324         break;
00325     case 42:            /* DSA g */
00326         if (nss->dsa == NULL)
00327             nss->dsa = rpmnssNewPublicKey(dsaKey);
00328         if (nss->dsa == NULL)
00329             rc = 1;
00330         else
00331             (void) rpmnssMpiCopy(nss->dsa->arena, &nss->dsa->u.dsa.params.base, p);
00332         break;
00333     case 43:            /* DSA y */
00334         if (nss->dsa == NULL)
00335             nss->dsa = rpmnssNewPublicKey(dsaKey);
00336         if (nss->dsa == NULL)
00337             rc = 1;
00338         else
00339             (void) rpmnssMpiCopy(nss->dsa->arena, &nss->dsa->u.dsa.publicValue, p);
00340         break;
00341     }
00342 /*@=moduncon@*/
00343     return rc;
00344 }
00345 
00346 /*@-mustmod@*/
00347 static
00348 void rpmnssClean(void * impl)
00349         /*@modifies impl @*/
00350 {
00351     rpmnss nss = impl;
00352 /*@-moduncon@*/
00353     if (nss != NULL) {
00354         if (nss->dsa != NULL) {
00355             SECKEY_DestroyPublicKey(nss->dsa);
00356             nss->dsa = NULL;
00357         }
00358         if (nss->dsasig != NULL) {
00359             SECITEM_ZfreeItem(nss->dsasig, PR_TRUE);
00360             nss->dsasig = NULL;
00361         }
00362         if (nss->rsa != NULL) {
00363             SECKEY_DestroyPublicKey(nss->rsa);
00364             nss->rsa = NULL;
00365         }
00366         if (nss->rsasig != NULL) {
00367             SECITEM_ZfreeItem(nss->rsasig, PR_TRUE);
00368             nss->rsasig = NULL;
00369         }
00370 /*@=moduncon@*/
00371     }
00372 }
00373 /*@=mustmod@*/
00374 
00375 static /*@null@*/
00376 void * rpmnssFree(/*@only@*/ void * impl)
00377         /*@*/
00378 {
00379     rpmnss nss = impl;
00380     if (nss != NULL) {
00381         rpmnssClean(impl);
00382         nss = _free(nss);
00383     }
00384     return NULL;
00385 }
00386 
00387 static
00388 void * rpmnssInit(void)
00389         /*@globals _rpmnss_init @*/
00390         /*@modifies _rpmnss_init @*/
00391 {
00392     rpmnss nss = xcalloc(1, sizeof(*nss));
00393 
00394 /*@-moduncon@*/
00395     (void) NSS_NoDB_Init(NULL);
00396 /*@=moduncon@*/
00397     _rpmnss_init = 1;
00398 
00399     return (void *) nss;
00400 }
00401 
00402 struct pgpImplVecs_s rpmnssImplVecs = {
00403         rpmnssSetRSA, rpmnssVerifyRSA,
00404         rpmnssSetDSA, rpmnssVerifyDSA,
00405         rpmnssSetECDSA, rpmnssVerifyECDSA,
00406         rpmnssMpiItem, rpmnssClean,
00407         rpmnssFree, rpmnssInit
00408 };
00409 
00410 #endif
00411