rpm 5.3.12
rpmio/rpmnss.c
Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 #include <rpmio.h>
00007 
00008 #include <rpmiotypes.h>
00009 #define _RPMPGP_INTERNAL
00010 #if defined(WITH_NSS)
00011 #define _RPMNSS_INTERNAL
00012 #include <rpmnss.h>
00013 #endif
00014 #include <rpmmacro.h>
00015 
00016 #include "debug.h"
00017 
00018 #if defined(WITH_NSS)
00019 
00020 /*@access pgpDig @*/
00021 /*@access pgpDigParams @*/
00022 
00023 /*@-redecl@*/
00024 /*@unchecked@*/
00025 extern int _pgp_debug;
00026 
00027 /*@unchecked@*/
00028 extern int _pgp_print;
00029 /*@=redecl@*/
00030 
00031 /*@unchecked@*/
00032 extern int _rpmnss_init;
00033 
00034 /*@unchecked@*/
00035 static int _rpmnss_debug;
00036 
00037 #define SPEW(_t, _rc, _dig)     \
00038   { if ((_t) || _rpmnss_debug || _pgp_debug < 0) \
00039         fprintf(stderr, "<-- %s(%p) %s\t%s\n", __FUNCTION__, (_dig), \
00040                 ((_rc) ? "OK" : "BAD"), (_dig)->pubkey_algoN); \
00041   }
00042 
00043 /*==============================================================*/
00044 
00045 #ifdef  NOTYET
00046 typedef struct key_s {
00047 /*@observer@*/
00048     const char * name;          /* key name */
00049     uint32_t value;
00050 } KEY;
00051 
00052 static int
00053 keyCmp(const void * a, const void * b)
00054 {
00055     return strcmp(((KEY *)a)->name, ((KEY *)b)->name);
00056 }
00057 
00058 static uint32_t
00059 keyValue(KEY * keys, size_t nkeys, /*@null@*/ const char *name)
00060 {
00061     uint32_t keyval = 0;
00062 
00063     if (name && *name) {
00064         /* XXX bsearch is overkill */
00065         KEY needle = { .name = name, .value = 0 };
00066         KEY *k = (KEY *)bsearch(&needle, keys, nkeys, sizeof(*keys), keyCmp);
00067         if (k)
00068             keyval = k->value;
00069     }
00070     return keyval;
00071 }
00072 #endif
00073 
00074 typedef struct keyVN_s {
00075     int V;
00076 /*@observer@*/
00077     const char * N;             /* key name */
00078 } keyVN_t;
00079 
00080 static int
00081 keyVNCmp(const void * a, const void * b)
00082 {
00083     return (((keyVN_t *)a)->V - ((keyVN_t *)b)->V);
00084 }
00085 
00086 static const char *
00087 keyVN(keyVN_t * keys, size_t nkeys, /*@null@*/ int V)
00088 {
00089     const char * N = NULL;
00090 
00091     if (V) {
00092         /* XXX bsearch is overkill */
00093         keyVN_t needle = { .V = V, .N = NULL };
00094         keyVN_t *k = (keyVN_t *)
00095                 bsearch(&needle, keys, nkeys, sizeof(*keys), keyVNCmp);
00096         if (k)
00097             N = k->N;
00098     }
00099     return N;
00100 }
00101 
00102 static const char * _pgpHashAlgo2Name(uint32_t algo)
00103 {
00104     return pgpValStr(pgpHashTbl, (rpmuint8_t)algo);
00105 }
00106 
00107 static const char * _pgpPubkeyAlgo2Name(uint32_t algo)
00108 {
00109     return pgpValStr(pgpPubkeyTbl, (rpmuint8_t)algo);
00110 }
00111 
00112 /*==============================================================*/
00113 
00114 #define _ENTRY(_v)      { SEC_ERROR_##_v, #_v }
00115 /* XXX sorted table */
00116 static keyVN_t rpmnssERRS[] = {
00117     _ENTRY(IO),
00118     _ENTRY(LIBRARY_FAILURE),
00119     _ENTRY(BAD_DATA),
00120     _ENTRY(OUTPUT_LEN),
00121     _ENTRY(INPUT_LEN),
00122     _ENTRY(INVALID_ARGS),
00123     _ENTRY(INVALID_ALGORITHM),
00124     _ENTRY(INVALID_AVA),
00125     _ENTRY(INVALID_TIME),
00126     _ENTRY(BAD_DER),
00127     _ENTRY(BAD_SIGNATURE),
00128     _ENTRY(EXPIRED_CERTIFICATE),
00129     _ENTRY(REVOKED_CERTIFICATE),
00130     _ENTRY(UNKNOWN_ISSUER),
00131     _ENTRY(BAD_KEY),
00132     _ENTRY(BAD_PASSWORD),
00133     _ENTRY(RETRY_PASSWORD),
00134     _ENTRY(NO_NODELOCK),
00135     _ENTRY(BAD_DATABASE),
00136     _ENTRY(NO_MEMORY),
00137     _ENTRY(UNTRUSTED_ISSUER),
00138     _ENTRY(UNTRUSTED_CERT),
00139     _ENTRY(DUPLICATE_CERT),
00140     _ENTRY(DUPLICATE_CERT_NAME),
00141     _ENTRY(ADDING_CERT),
00142     _ENTRY(FILING_KEY),
00143     _ENTRY(NO_KEY),
00144     _ENTRY(CERT_VALID),
00145     _ENTRY(CERT_NOT_VALID),
00146     _ENTRY(CERT_NO_RESPONSE),
00147     _ENTRY(EXPIRED_ISSUER_CERTIFICATE),
00148     _ENTRY(CRL_EXPIRED),
00149     _ENTRY(CRL_BAD_SIGNATURE),
00150     _ENTRY(CRL_INVALID),
00151     _ENTRY(EXTENSION_VALUE_INVALID),
00152     _ENTRY(EXTENSION_NOT_FOUND),
00153     _ENTRY(CA_CERT_INVALID),
00154     _ENTRY(PATH_LEN_CONSTRAINT_INVALID),
00155     _ENTRY(CERT_USAGES_INVALID),
00156 /* SEC_INTERNAL_ONLY */
00157     _ENTRY(INVALID_KEY),
00158     _ENTRY(UNKNOWN_CRITICAL_EXTENSION),
00159     _ENTRY(OLD_CRL),
00160     _ENTRY(NO_EMAIL_CERT),
00161     _ENTRY(NO_RECIPIENT_CERTS_QUERY),
00162     _ENTRY(NOT_A_RECIPIENT),
00163     _ENTRY(PKCS7_KEYALG_MISMATCH),
00164     _ENTRY(PKCS7_BAD_SIGNATURE),
00165     _ENTRY(UNSUPPORTED_KEYALG),
00166     _ENTRY(DECRYPTION_DISALLOWED),
00167 /* Fortezza Alerts */
00168 /* XP_SEC_FORTEZZA_BAD_CARD */
00169 /* XP_SEC_FORTEZZA_NO_CARD */
00170 /* XP_SEC_FORTEZZA_NONE_SELECTED */
00171 /* XP_SEC_FORTEZZA_MORE_INFO */
00172 /* XP_SEC_FORTEZZA_PERSON_NOT_FOUND */
00173 /* XP_SEC_FORTEZZA_NO_MORE_INFO */
00174 /* XP_SEC_FORTEZZA_BAD_PIN */
00175 /* XP_SEC_FORTEZZA_PERSON_ERROR */
00176     _ENTRY(NO_KRL),
00177     _ENTRY(KRL_EXPIRED),
00178     _ENTRY(KRL_BAD_SIGNATURE),
00179     _ENTRY(REVOKED_KEY),
00180     _ENTRY(KRL_INVALID),
00181     _ENTRY(NEED_RANDOM),
00182     _ENTRY(NO_MODULE),
00183     _ENTRY(NO_TOKEN),
00184     _ENTRY(READ_ONLY),
00185     _ENTRY(NO_SLOT_SELECTED),
00186     _ENTRY(CERT_NICKNAME_COLLISION),
00187     _ENTRY(KEY_NICKNAME_COLLISION),
00188     _ENTRY(SAFE_NOT_CREATED),
00189     _ENTRY(BAGGAGE_NOT_CREATED),
00190 /* XP_JAVA_REMOVE_PRINCIPAL_ERROR */
00191 /* XP_JAVA_DELETE_PRIVILEGE_ERROR */
00192 /* XP_JAVA_CERT_NOT_EXISTS_ERROR */
00193     _ENTRY(BAD_EXPORT_ALGORITHM),
00194     _ENTRY(EXPORTING_CERTIFICATES),
00195     _ENTRY(IMPORTING_CERTIFICATES),
00196     _ENTRY(PKCS12_DECODING_PFX),
00197     _ENTRY(PKCS12_INVALID_MAC),
00198     _ENTRY(PKCS12_UNSUPPORTED_MAC_ALGORITHM),
00199     _ENTRY(PKCS12_UNSUPPORTED_TRANSPORT_MODE),
00200     _ENTRY(PKCS12_CORRUPT_PFX_STRUCTURE),
00201     _ENTRY(PKCS12_UNSUPPORTED_PBE_ALGORITHM),
00202     _ENTRY(PKCS12_UNSUPPORTED_VERSION),
00203     _ENTRY(PKCS12_PRIVACY_PASSWORD_INCORRECT),
00204     _ENTRY(PKCS12_CERT_COLLISION),
00205     _ENTRY(USER_CANCELLED),
00206     _ENTRY(PKCS12_DUPLICATE_DATA),
00207     _ENTRY(MESSAGE_SEND_ABORTED),
00208     _ENTRY(INADEQUATE_KEY_USAGE),
00209     _ENTRY(INADEQUATE_CERT_TYPE),
00210     _ENTRY(CERT_ADDR_MISMATCH),
00211     _ENTRY(PKCS12_UNABLE_TO_IMPORT_KEY),
00212     _ENTRY(PKCS12_IMPORTING_CERT_CHAIN),
00213     _ENTRY(PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME),
00214     _ENTRY(PKCS12_UNABLE_TO_EXPORT_KEY),
00215     _ENTRY(PKCS12_UNABLE_TO_WRITE),
00216     _ENTRY(PKCS12_UNABLE_TO_READ),
00217     _ENTRY(PKCS12_KEY_DATABASE_NOT_INITIALIZED),
00218     _ENTRY(KEYGEN_FAIL),
00219     _ENTRY(INVALID_PASSWORD),
00220     _ENTRY(RETRY_OLD_PASSWORD),
00221     _ENTRY(BAD_NICKNAME),
00222     _ENTRY(NOT_FORTEZZA_ISSUER),
00223     _ENTRY(CANNOT_MOVE_SENSITIVE_KEY),
00224     _ENTRY(JS_INVALID_MODULE_NAME),
00225     _ENTRY(JS_INVALID_DLL),
00226     _ENTRY(JS_ADD_MOD_FAILURE),
00227     _ENTRY(JS_DEL_MOD_FAILURE),
00228     _ENTRY(OLD_KRL),
00229     _ENTRY(CKL_CONFLICT),
00230     _ENTRY(CERT_NOT_IN_NAME_SPACE),
00231     _ENTRY(KRL_NOT_YET_VALID),
00232     _ENTRY(CRL_NOT_YET_VALID),
00233     _ENTRY(UNKNOWN_CERT),
00234     _ENTRY(UNKNOWN_SIGNER),
00235     _ENTRY(CERT_BAD_ACCESS_LOCATION),
00236     _ENTRY(OCSP_UNKNOWN_RESPONSE_TYPE),
00237     _ENTRY(OCSP_BAD_HTTP_RESPONSE),
00238     _ENTRY(OCSP_MALFORMED_REQUEST),
00239     _ENTRY(OCSP_SERVER_ERROR),
00240     _ENTRY(OCSP_TRY_SERVER_LATER),
00241     _ENTRY(OCSP_REQUEST_NEEDS_SIG),
00242     _ENTRY(OCSP_UNAUTHORIZED_REQUEST),
00243     _ENTRY(OCSP_UNKNOWN_RESPONSE_STATUS),
00244     _ENTRY(OCSP_UNKNOWN_CERT),
00245     _ENTRY(OCSP_NOT_ENABLED),
00246     _ENTRY(OCSP_NO_DEFAULT_RESPONDER),
00247     _ENTRY(OCSP_MALFORMED_RESPONSE),
00248     _ENTRY(OCSP_UNAUTHORIZED_RESPONSE),
00249     _ENTRY(OCSP_FUTURE_RESPONSE),
00250     _ENTRY(OCSP_OLD_RESPONSE),
00251 /* smime stuff */
00252     _ENTRY(DIGEST_NOT_FOUND),
00253     _ENTRY(UNSUPPORTED_MESSAGE_TYPE),
00254     _ENTRY(MODULE_STUCK),
00255     _ENTRY(BAD_TEMPLATE),
00256     _ENTRY(CRL_NOT_FOUND),
00257     _ENTRY(REUSED_ISSUER_AND_SERIAL),
00258     _ENTRY(BUSY),
00259     _ENTRY(EXTRA_INPUT),
00260 /* error codes used by elliptic curve code */
00261     _ENTRY(UNSUPPORTED_ELLIPTIC_CURVE),
00262     _ENTRY(UNSUPPORTED_EC_POINT_FORM),
00263     _ENTRY(UNRECOGNIZED_OID),
00264     _ENTRY(OCSP_INVALID_SIGNING_CERT),
00265 /* new revocation errors */
00266     _ENTRY(REVOKED_CERTIFICATE_CRL),
00267     _ENTRY(REVOKED_CERTIFICATE_OCSP),
00268     _ENTRY(CRL_INVALID_VERSION),
00269     _ENTRY(CRL_V1_CRITICAL_EXTENSION),
00270     _ENTRY(CRL_UNKNOWN_CRITICAL_EXTENSION),
00271     _ENTRY(UNKNOWN_OBJECT_TYPE),
00272     _ENTRY(INCOMPATIBLE_PKCS11),
00273     _ENTRY(NO_EVENT),
00274     _ENTRY(CRL_ALREADY_EXISTS),
00275     _ENTRY(NOT_INITIALIZED),
00276     _ENTRY(TOKEN_NOT_LOGGED_IN),
00277     _ENTRY(OCSP_RESPONDER_CERT_INVALID),
00278     _ENTRY(OCSP_BAD_SIGNATURE),
00279     _ENTRY(OUT_OF_SEARCH_LIMITS),
00280     _ENTRY(INVALID_POLICY_MAPPING),
00281     _ENTRY(POLICY_VALIDATION_FAILED),
00282     _ENTRY(UNKNOWN_AIA_LOCATION_TYPE),
00283     _ENTRY(BAD_HTTP_RESPONSE),
00284     _ENTRY(BAD_LDAP_RESPONSE),
00285     _ENTRY(FAILED_TO_ENCODE_DATA),
00286     _ENTRY(BAD_INFO_ACCESS_LOCATION),
00287     _ENTRY(LIBPKIX_INTERNAL),
00288     _ENTRY(PKCS11_GENERAL_ERROR),
00289     _ENTRY(PKCS11_FUNCTION_FAILED),
00290     _ENTRY(PKCS11_DEVICE_ERROR),
00291 #if defined(SEC_ERROR_BAD_INFO_ACCESS_METHOD)
00292     _ENTRY(BAD_INFO_ACCESS_METHOD),
00293 #endif
00294 #if defined(SEC_ERROR_CRL_IMPORT_FAILED)
00295     _ENTRY(CRL_IMPORT_FAILED),
00296 #endif
00297 };
00298 static size_t nrpmnssERRS = sizeof(rpmnssERRS) / sizeof(rpmnssERRS[0]);
00299 #undef _ENTRY
00300 
00301 static const char * rpmnssStrerror(int err)
00302 {
00303     static char buf[64];
00304     const char * errN = keyVN(rpmnssERRS, nrpmnssERRS, err);
00305     if (errN == NULL) {
00306         snprintf(buf, sizeof(buf), "SEC_ERROR(%d)", err);
00307         errN = buf;
00308     }
00309     return errN;
00310 }
00311 
00312 static
00313 int rpmnssErr(rpmnss nss, const char * msg, int rc)
00314         /*@*/
00315 {
00316 #ifdef  REFERENCE
00317     /* XXX Don't spew on expected failures ... */
00318     if (err && gcry_err_code(err) != gc->badok)
00319         fprintf (stderr, "rpmgc: %s(0x%0x): %s/%s\n",
00320                 msg, (unsigned)err, gcry_strsource(err), gcry_strerror(err));
00321 #endif
00322     if (rc != SECSuccess) {
00323         int err = PORT_GetError();
00324         fprintf (stderr, "rpmnss: %s rc(%d) err(%d) %s\n",
00325                 msg, rc, err, rpmnssStrerror(err));
00326     }
00327     return rc;
00328 }
00329 
00330 static
00331 int rpmnssSetRSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
00332         /*@modifies dig @*/
00333 {
00334     rpmnss nss = dig->impl;
00335     int rc;
00336     int xx;
00337 pgpDigParams pubp = pgpGetPubkey(dig);
00338 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00339 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00340 
00341 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00342     nss->sigalg = SEC_OID_UNKNOWN;
00343     switch (sigp->hash_algo) {
00344     case PGPHASHALGO_MD5:
00345         nss->sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
00346         break;
00347     case PGPHASHALGO_SHA1:
00348         nss->sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
00349         break;
00350     case PGPHASHALGO_RIPEMD160:
00351         break;
00352     case PGPHASHALGO_MD2:
00353         nss->sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
00354         break;
00355     case PGPHASHALGO_MD4:
00356         nss->sigalg = SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION;
00357         break;
00358     case PGPHASHALGO_TIGER192:
00359         break;
00360     case PGPHASHALGO_HAVAL_5_160:
00361         break;
00362     case PGPHASHALGO_SHA256:
00363         nss->sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
00364         break;
00365     case PGPHASHALGO_SHA384:
00366         nss->sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
00367         break;
00368     case PGPHASHALGO_SHA512:
00369         nss->sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
00370         break;
00371     case PGPHASHALGO_SHA224:
00372         break;
00373     default:
00374         break;
00375     }
00376     if (nss->sigalg == SEC_OID_UNKNOWN)
00377         return 1;
00378 
00379 nss->digest = _free(nss->digest);
00380 nss->digestlen = 0;
00381     xx = rpmDigestFinal(ctx, (void **)&nss->digest, &nss->digestlen, 0);
00382 
00383     /* Compare leading 16 bits of digest for quick check. */
00384     rc = memcmp(nss->digest, sigp->signhash16, sizeof(sigp->signhash16));
00385 SPEW(0, !rc, dig);
00386     return rc;
00387 }
00388 
00389 static
00390 int rpmnssVerifyRSA(pgpDig dig)
00391         /*@*/
00392 {
00393     rpmnss nss = dig->impl;
00394     int rc;
00395 
00396     nss->item.type = siBuffer;
00397     nss->item.data = nss->digest;
00398     nss->item.len = (unsigned) nss->digestlen;
00399 
00400     rc = rpmnssErr(nss, "VFY_VerifyDigest",
00401                 VFY_VerifyDigest(&nss->item, nss->pub_key,
00402                                 nss->sig, nss->sigalg, NULL));
00403     rc = (rc == SECSuccess);
00404 
00405 SPEW(0, !rc, dig);
00406     return rc;
00407 }
00408 
00409 static int rpmnssSignRSA(pgpDig dig)
00410 {
00411     rpmnss nss = dig->impl;
00412 pgpDigParams sigp = pgpGetSignature(dig);
00413     int rc = 0;         /* assume failure. */
00414 
00415 SECOidTag sigalg = SEC_OID_UNKNOWN;
00416     switch (sigp->hash_algo) {
00417     case PGPHASHALGO_MD5:
00418         sigalg = SEC_OID_MD5;
00419         break;
00420     case PGPHASHALGO_SHA1:
00421         sigalg = SEC_OID_SHA1;
00422         break;
00423     case PGPHASHALGO_RIPEMD160:
00424         break;
00425     case PGPHASHALGO_MD2:
00426         sigalg = SEC_OID_MD2;
00427         break;
00428     case PGPHASHALGO_MD4:
00429         sigalg = SEC_OID_MD4;
00430         break;
00431     case PGPHASHALGO_TIGER192:
00432         break;
00433     case PGPHASHALGO_HAVAL_5_160:
00434         break;
00435     case PGPHASHALGO_SHA256:
00436         sigalg = SEC_OID_SHA256;
00437         break;
00438     case PGPHASHALGO_SHA384:
00439         sigalg = SEC_OID_SHA384;
00440         break;
00441     case PGPHASHALGO_SHA512:
00442         sigalg = SEC_OID_SHA512;
00443         break;
00444     case PGPHASHALGO_SHA224:
00445         break;
00446     default:
00447         break;
00448     }
00449     if (sigalg == SEC_OID_UNKNOWN)
00450         goto exit;
00451 
00452     nss->item.type = siBuffer;
00453     nss->item.data = nss->digest;
00454     nss->item.len = (unsigned) nss->digestlen;
00455 
00456 if (nss->sig != NULL) {
00457     SECITEM_ZfreeItem(nss->sig, PR_TRUE);
00458     nss->sig = NULL;
00459 }
00460 nss->sig = SECITEM_AllocItem(NULL, NULL, 0);
00461 nss->sig->type = siBuffer;
00462 
00463     rc = rpmnssErr(nss, "SGN_Digest",
00464             SGN_Digest(nss->sec_key, sigalg, nss->sig, &nss->item));
00465     rc = (rc == SECSuccess);
00466 
00467 exit:
00468 SPEW(!rc, rc, dig);
00469     return rc;
00470 }
00471 
00472 static int rpmnssGenerateRSA(pgpDig dig)
00473 {
00474     rpmnss nss = dig->impl;
00475     int rc = 0;         /* assume failure */
00476 
00477 if (nss->nbits == 0) nss->nbits = 1024; /* XXX FIXME */
00478 assert(nss->nbits);
00479 
00480     {   CK_MECHANISM_TYPE _type = CKM_RSA_PKCS_KEY_PAIR_GEN;
00481         PK11SlotInfo * _slot = PK11_GetBestSlot(_type, NULL);
00482         int _isPerm = PR_FALSE;
00483         int _isSensitive = PR_TRUE;
00484         void * _cx = NULL;
00485 
00486         if (_slot) {
00487             static unsigned _pe = 0x10001;      /* XXX FIXME: pass in e */
00488             PK11RSAGenParams rsaparams =
00489                 { .keySizeInBits = nss->nbits, .pe = _pe };
00490             void * params = &rsaparams;
00491 
00492             nss->sec_key = PK11_GenerateKeyPair(_slot, _type, params,
00493                         &nss->pub_key, _isPerm, _isSensitive, _cx);
00494 
00495             PK11_FreeSlot(_slot);
00496         }
00497     }
00498 
00499     rc = (nss->sec_key && nss->pub_key);
00500 
00501 SPEW(!rc, rc, dig);
00502     return rc;
00503 }
00504 
00505 static
00506 int rpmnssSetDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
00507         /*@modifies dig @*/
00508 {
00509     rpmnss nss = dig->impl;
00510     int rc;
00511     int xx;
00512 pgpDigParams pubp = pgpGetPubkey(dig);
00513 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00514 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00515 
00516 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00517 nss->digest = _free(nss->digest);
00518 nss->digestlen = 0;
00519     xx = rpmDigestFinal(ctx, (void **)&nss->digest, &nss->digestlen, 0);
00520 
00521     nss->sigalg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
00522 
00523     /* Compare leading 16 bits of digest for quick check. */
00524     rc = memcmp(nss->digest, sigp->signhash16, sizeof(sigp->signhash16));
00525 SPEW(0, !rc, dig);
00526     return rc;
00527 }
00528 
00529 static
00530 int rpmnssVerifyDSA(pgpDig dig)
00531         /*@*/
00532 {
00533     rpmnss nss = dig->impl;
00534     int rc;
00535 
00536     nss->item.type = siBuffer;
00537     nss->item.data = nss->digest;
00538     nss->item.len = (unsigned) nss->digestlen;
00539 
00540     rc = rpmnssErr(nss, "VFY_VerifyDigest",
00541                 VFY_VerifyDigest(&nss->item, nss->pub_key,
00542                                 nss->sig, nss->sigalg, NULL));
00543     rc = (rc == SECSuccess);
00544 
00545 SPEW(0, rc, dig);
00546     return rc;
00547 }
00548 
00549 static int rpmnssSignDSA(pgpDig dig)
00550 {
00551     rpmnss nss = dig->impl;
00552 pgpDigParams sigp = pgpGetSignature(dig);
00553     int rc = 0;         /* assume failure. */
00554 SECItem sig = { .type = siBuffer, .len = 0, .data = NULL };
00555 
00556 SECOidTag sigalg = SEC_OID_UNKNOWN;
00557     switch (sigp->hash_algo) {
00558     case PGPHASHALGO_MD5:
00559         break;
00560     case PGPHASHALGO_SHA1:
00561         sigalg = SEC_OID_SHA1;
00562         break;
00563     case PGPHASHALGO_RIPEMD160:
00564         break;
00565     case PGPHASHALGO_MD2:
00566         break;
00567     case PGPHASHALGO_MD4:
00568         break;
00569     case PGPHASHALGO_TIGER192:
00570         break;
00571     case PGPHASHALGO_HAVAL_5_160:
00572         break;
00573     case PGPHASHALGO_SHA256:
00574         break;
00575     case PGPHASHALGO_SHA384:
00576         break;
00577     case PGPHASHALGO_SHA512:
00578         break;
00579     case PGPHASHALGO_SHA224:
00580         break;
00581     default:
00582         break;
00583     }
00584     if (sigalg == SEC_OID_UNKNOWN)
00585         goto exit;
00586 
00587     nss->item.type = siBuffer;
00588     nss->item.data = nss->digest;
00589     nss->item.len = (unsigned) nss->digestlen;
00590 
00591 if (nss->sig != NULL) {
00592     SECITEM_ZfreeItem(nss->sig, PR_TRUE);
00593     nss->sig = NULL;
00594 }
00595 
00596 nss->sig = SECITEM_AllocItem(NULL, NULL, 0);
00597 nss->sig->type = siBuffer;
00598 
00599     rc = rpmnssErr(nss, "SGN_Digest",
00600             SGN_Digest(nss->sec_key, sigalg, &sig, &nss->item));
00601 
00602     if (rc == SECSuccess)
00603         rc = rpmnssErr(nss, "DSAU_EncodeDerSig",
00604                 DSAU_EncodeDerSig(nss->sig, &sig));
00605 
00606     sig.data = _free(sig.data);
00607 
00608     rc = (rc == SECSuccess);
00609 
00610 exit:
00611 SPEW(!rc, rc, dig);
00612     return rc;
00613 }
00614 
00615 static int rpmnssGenerateDSA(pgpDig dig)
00616 {
00617     rpmnss nss = dig->impl;
00618     int rc = 0;         /* assume failure */
00619 
00620 if (nss->nbits == 0) nss->nbits = 1024; /* XXX FIXME */
00621 assert(nss->nbits);
00622 
00623     {   CK_MECHANISM_TYPE _type = CKM_DSA_KEY_PAIR_GEN;
00624         PK11SlotInfo * _slot = PK11_GetBestSlot(_type, NULL);
00625         int _isPerm = PR_FALSE;
00626         int _isSensitive = PR_TRUE;
00627         void * _cx = NULL;
00628 
00629         if (_slot) {
00630             PQGParams *pqgParams = NULL;
00631             PQGVerify *pqgVfy = NULL;
00632             void * params = NULL;
00633 int xx;
00634 
00635             xx = rpmnssErr(nss, "PK11_PQG_ParamGen",
00636                         PK11_PQG_ParamGen(0, &pqgParams, &pqgVfy));
00637             if (xx != SECSuccess)
00638                 goto exit;
00639             params = pqgParams;
00640 
00641             nss->sec_key = PK11_GenerateKeyPair(_slot, _type, params,
00642                         &nss->pub_key, _isPerm, _isSensitive, _cx);
00643 
00644             if (pqgVfy) PK11_PQG_DestroyVerify(pqgVfy);
00645             if (pqgParams) PK11_PQG_DestroyParams(pqgParams);
00646 
00647             PK11_FreeSlot(_slot);
00648         }
00649     }
00650 
00651     rc = (nss->sec_key && nss->pub_key);
00652 
00653 exit:
00654 SPEW(!rc, rc, dig);
00655     return rc;
00656 }
00657 
00658 static
00659 int rpmnssSetELG(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp)
00660         /*@*/
00661 {
00662     rpmnss nss = dig->impl;
00663     int rc = 1;         /* XXX always fail. */
00664     int xx;
00665 
00666 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00667 nss->digest = _free(nss->digest);
00668 nss->digestlen = 0;
00669     xx = rpmDigestFinal(ctx, (void **)&nss->digest, &nss->digestlen, 0);
00670 
00671     /* Compare leading 16 bits of digest for quick check. */
00672 
00673     return rc;
00674 }
00675 
00676 static
00677 int rpmnssSetECDSA(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp)
00678         /*@*/
00679 {
00680     rpmnss nss = dig->impl;
00681     int xx;
00682 
00683 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00684     nss->sigalg = SEC_OID_UNKNOWN;
00685     switch (sigp->hash_algo) {
00686     case PGPHASHALGO_SHA1:
00687         nss->sigalg = SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE;
00688         break;
00689     case PGPHASHALGO_SHA224:
00690         nss->sigalg = SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE;
00691         break;
00692     case PGPHASHALGO_SHA256:
00693         nss->sigalg = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
00694         break;
00695     case PGPHASHALGO_SHA384:
00696         nss->sigalg = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
00697         break;
00698     case PGPHASHALGO_SHA512:
00699         nss->sigalg = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
00700         break;
00701     default:
00702         break;
00703     }
00704     if (nss->sigalg == SEC_OID_UNKNOWN)
00705         return 1;
00706 
00707 nss->digest = _free(nss->digest);
00708 nss->digestlen = 0;
00709     xx = rpmDigestFinal(ctx, (void **)&nss->digest, &nss->digestlen, 0);
00710 
00711     /* Compare leading 16 bits of digest for quick check. */
00712     return memcmp(nss->digest, sigp->signhash16, sizeof(sigp->signhash16));
00713 }
00714 
00715 static
00716 int rpmnssVerifyECDSA(/*@unused@*/pgpDig dig)
00717         /*@*/
00718 {
00719     rpmnss nss = dig->impl;
00720     int rc;
00721 
00722     nss->item.type = siBuffer;
00723     nss->item.data = nss->digest;
00724     nss->item.len = (unsigned) nss->digestlen;
00725 
00726     rc = VFY_VerifyDigest(&nss->item, nss->pub_key, nss->sig, nss->sigalg, NULL);
00727     rc = (rc == SECSuccess);
00728 
00729 SPEW(!rc, rc, dig);
00730     return rc;
00731 }
00732 
00733 static
00734 int rpmnssSignECDSA(/*@unused@*/pgpDig dig)
00735         /*@*/
00736 {
00737     rpmnss nss = dig->impl;
00738 pgpDigParams sigp = pgpGetSignature(dig);
00739     int rc = 0;         /* assume failure. */
00740 
00741 SECOidTag sigalg = SEC_OID_UNKNOWN;
00742     switch (sigp->hash_algo) {
00743     case PGPHASHALGO_MD5:
00744         break;
00745     case PGPHASHALGO_SHA1:
00746         sigalg = SEC_OID_SHA1;
00747         break;
00748     case PGPHASHALGO_RIPEMD160:
00749         break;
00750     case PGPHASHALGO_MD2:
00751         break;
00752     case PGPHASHALGO_MD4:
00753         break;
00754     case PGPHASHALGO_TIGER192:
00755         break;
00756     case PGPHASHALGO_HAVAL_5_160:
00757         break;
00758     case PGPHASHALGO_SHA256:
00759         sigalg = SEC_OID_SHA256;
00760         break;
00761     case PGPHASHALGO_SHA384:
00762         sigalg = SEC_OID_SHA384;
00763         break;
00764     case PGPHASHALGO_SHA512:
00765         sigalg = SEC_OID_SHA512;
00766         break;
00767     case PGPHASHALGO_SHA224:
00768         break;
00769     default:
00770         break;
00771     }
00772     if (sigalg == SEC_OID_UNKNOWN)
00773         goto exit;
00774 
00775 if (nss->sig != NULL) {
00776     SECITEM_ZfreeItem(nss->sig, PR_TRUE);
00777     nss->sig = NULL;
00778 }
00779 nss->sig = SECITEM_AllocItem(NULL, NULL, 0);
00780 nss->sig->type = siBuffer;
00781 
00782     rc = rpmnssErr(nss, "SGN_Digest",
00783             SGN_Digest(nss->sec_key, sigalg, nss->sig, &nss->item));
00784 
00785     rc = (rc == SECSuccess);
00786 
00787 exit:
00788 SPEW(!rc, rc, dig);
00789     return rc;
00790 }
00791 
00792 static
00793 int rpmnssGenerateECDSA(/*@unused@*/pgpDig dig)
00794         /*@*/
00795 {
00796     rpmnss nss = dig->impl;
00797     int rc = 0;         /* assume failure. */
00798 
00799     {   CK_MECHANISM_TYPE _type = CKM_EC_KEY_PAIR_GEN;
00800         PK11SlotInfo * _slot = PK11_GetBestSlot(_type, NULL);
00801         int _isPerm = PR_FALSE;
00802         int _isSensitive = PR_FALSE;
00803         void * _cx = NULL;
00804 
00805         if (_slot) {
00806 
00807             nss->sec_key = PK11_GenerateKeyPair(_slot, _type, nss->ecparams,
00808                         &nss->pub_key, _isPerm, _isSensitive, _cx);
00809 
00810             PK11_FreeSlot(_slot);
00811         }
00812     }
00813 
00814     rc = (nss->sec_key && nss->pub_key);
00815 
00816 SPEW(!rc, rc, dig);
00817 
00818     return rc;
00819 }
00820 
00821 static int rpmnssErrChk(pgpDig dig, const char * msg, int rc, unsigned expected)
00822 {
00823 #ifdef  NOTYET
00824 rpmgc gc = dig->impl;
00825     /* Was the return code the expected result? */
00826     rc = (gcry_err_code(gc->err) != expected);
00827     if (rc)
00828         fail("%s failed: %s\n", msg, gpg_strerror(gc->err));
00829 /* XXX FIXME: rpmnssStrerror */
00830 #else
00831     rc = (rc == 0);     /* XXX impedance match 1 -> 0 on success */
00832 #endif
00833     return rc;  /* XXX 0 on success */
00834 }
00835 
00836 static int rpmnssAvailableCipher(pgpDig dig, int algo)
00837 {
00838     int rc = 0; /* assume available */
00839 #ifdef  NOTYET
00840     rc = rpmgnssvailable(dig->impl, algo,
00841         (gcry_md_test_algo(algo) || algo == PGPHASHALGO_MD5));
00842 #endif
00843     return rc;
00844 }
00845 
00846 static int rpmnssAvailableDigest(pgpDig dig, int algo)
00847 {
00848     int rc = 0; /* assume available */
00849 #ifdef  NOTYET
00850     rc = rpmgnssvailable(dig->impl, algo,
00851         (gcry_md_test_algo(algo) || algo == PGPHASHALGO_MD5));
00852 #endif
00853     return rc;
00854 }
00855 
00856 static int rpmnssAvailablePubkey(pgpDig dig, int algo)
00857 {
00858     int rc = 0; /* assume available */
00859 #ifdef  NOTYET
00860     rc = rpmnssAvailable(dig->impl, algo, gcry_pk_test_algo(algo));
00861 #endif
00862     return rc;
00863 }
00864 
00865 static int rpmnssVerify(pgpDig dig)
00866 {
00867     rpmnss nss = dig->impl;
00868     int rc = 0;         /* assume failure */
00869 pgpDigParams pubp = pgpGetPubkey(dig);
00870 pgpDigParams sigp = pgpGetSignature(dig);
00871 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00872 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00873 
00874     switch (pubp->pubkey_algo) {
00875     default:
00876         break;
00877     case PGPPUBKEYALGO_RSA:
00878         rc = rpmnssVerifyRSA(dig);
00879         break;
00880     case PGPPUBKEYALGO_DSA:
00881         rc = rpmnssVerifyDSA(dig);
00882         break;
00883     case PGPPUBKEYALGO_ELGAMAL:
00884 #ifdef  NOTYET
00885         rc = rpmnssVerifyELG(dig);
00886 #endif
00887         break;
00888     case PGPPUBKEYALGO_ECDSA:
00889         if (nss->sigalg != SEC_OID_UNKNOWN)
00890             rc = rpmnssVerifyECDSA(dig);
00891         break;
00892     }
00893 SPEW(0, rc, dig);
00894     return rc;
00895 }
00896 
00897 static int rpmnssSign(pgpDig dig)
00898 {
00899     rpmnss nss = dig->impl;
00900     int rc = 0;         /* assume failure */
00901 pgpDigParams pubp = pgpGetPubkey(dig);
00902 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00903     switch (pubp->pubkey_algo) {
00904     default:
00905         break;
00906     case PGPPUBKEYALGO_RSA:
00907         rc = rpmnssSignRSA(dig);
00908         break;
00909     case PGPPUBKEYALGO_DSA:
00910         rc = rpmnssSignDSA(dig);
00911         break;
00912     case PGPPUBKEYALGO_ELGAMAL:
00913 #ifdef  NOTYET
00914         rc = rpmnssSignELG(dig);
00915 #endif
00916         break;
00917     case PGPPUBKEYALGO_ECDSA:
00918         if (nss->sigalg != SEC_OID_UNKNOWN)
00919             rc = rpmnssSignECDSA(dig);
00920         break;
00921     }
00922 SPEW(!rc, rc, dig);
00923     return rc;
00924 }
00925 
00926 static int rpmnssLoadParams(pgpDig dig, const char * name)
00927 {
00928     rpmnss nss = dig->impl;
00929 #ifdef  NOTYET
00930     SECOidTag curveOidTag = curve2oid(name);
00931 #else
00932     SECOidTag curveOidTag = !strcmp(name, "nistp256")
00933                 ? SEC_OID_SECG_EC_SECP256R1 : SEC_OID_UNKNOWN;
00934 #endif
00935     SECOidData * oidData = SECOID_FindOIDByTag(curveOidTag);
00936     int rc = 1;         /* assume failure. */
00937     
00938     if (curveOidTag == SEC_OID_UNKNOWN || oidData == NULL) {
00939         nss->sigalg = curveOidTag;
00940         goto exit;
00941     }
00942 
00943     nss->sigalg = curveOidTag;
00944 
00945     nss->ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
00946     nss->ecparams->data[0] = SEC_ASN1_OBJECT_ID;
00947     nss->ecparams->data[1] = oidData->oid.len;
00948     memcpy(nss->ecparams->data + 2, oidData->oid.data, oidData->oid.len);
00949     rc = 0;
00950 
00951 exit:
00952 if (1 || _pgp_debug)
00953 fprintf(stderr, "<-- %s(%p,%s) oid %u params %p\n", __FUNCTION__, dig, name, nss->sigalg, nss->ecparams);
00954     return rc;
00955 }
00956 
00957 static int rpmnssGenerate(pgpDig dig)
00958 {
00959     int rc = 0;         /* assume failure */
00960 pgpDigParams pubp = pgpGetPubkey(dig);
00961 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00962 
00963     switch (pubp->pubkey_algo) {
00964     default:
00965         break;
00966     case PGPPUBKEYALGO_RSA:
00967         rc = rpmnssGenerateRSA(dig);
00968         break;
00969     case PGPPUBKEYALGO_DSA:
00970         rc = rpmnssGenerateDSA(dig);
00971         break;
00972     case PGPPUBKEYALGO_ELGAMAL:
00973 #ifdef  NOTYET
00974         rc = rpmnssGenerateELG(dig);
00975 #endif
00976         break;
00977     case PGPPUBKEYALGO_ECDSA:
00978         rc = rpmnssLoadParams(dig, "nistp256");
00979         if (!rc)
00980             rc = rpmnssGenerateECDSA(dig);
00981         break;
00982     }
00983 SPEW(!rc, rc, dig);
00984     return rc;
00985 }
00986 
00990 static
00991 int rpmnssMpiSet(const char * pre, unsigned int lbits,
00992                 /*@out@*/ void * dest, const rpmuint8_t * p,
00993                 /*@null@*/ const rpmuint8_t * pend)
00994         /*@modifies *dest @*/
00995 {
00996     unsigned int mbits = pgpMpiBits(p);
00997     unsigned int nbits;
00998     unsigned int nbytes;
00999     char * t = dest;
01000     unsigned int ix;
01001 
01002     if (pend != NULL && (p + ((mbits+7) >> 3)) > pend)
01003         return 1;
01004 
01005     if (mbits > lbits)
01006         return 1;
01007 
01008     nbits = (lbits > mbits ? lbits : mbits);
01009     nbytes = ((nbits + 7) >> 3);
01010     ix = ((nbits - mbits) >> 3);
01011 
01012 /*@-modfilesystem @*/
01013 if (_pgp_debug)
01014 fprintf(stderr, "*** mbits %u nbits %u nbytes %u ix %u\n", mbits, nbits, nbytes, ix);
01015     if (ix > 0) memset(t, (int)'\0', ix);
01016     memcpy(t+ix, p+2, nbytes-ix);
01017 if (_pgp_debug && _pgp_print)
01018 fprintf(stderr, "\t %s %s\n", pre, pgpHexStr(dest, nbytes));
01019 /*@=modfilesystem @*/
01020     return 0;
01021 }
01022 
01026 static
01027 /*@only@*/ /*@null@*/
01028 SECItem * rpmnssMpiCopy(PRArenaPool * arena, /*@returned@*/ SECItem * item,
01029                 const rpmuint8_t * p)
01030         /*@modifies item @*/
01031 {
01032     unsigned int nbytes = pgpMpiLen(p)-2;
01033 
01034 /*@-moduncon@*/
01035     if (item == NULL) {
01036         if ((item = SECITEM_AllocItem(arena, item, nbytes)) == NULL)
01037             return item;
01038     } else {
01039         if (arena != NULL)
01040             item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
01041         else
01042             item->data = PORT_Realloc(item->data, nbytes);
01043         
01044         if (item->data == NULL) {
01045             if (arena == NULL)
01046                 SECITEM_FreeItem(item, PR_TRUE);
01047             return NULL;
01048         }
01049     }
01050 /*@=moduncon@*/
01051 
01052     memcpy(item->data, p+2, nbytes);
01053     item->len = nbytes;
01054 /*@-temptrans@*/
01055     return item;
01056 /*@=temptrans@*/
01057 }
01058 
01059 static /*@null@*/
01060 SECKEYPublicKey * rpmnssNewPublicKey(KeyType type)
01061         /*@*/
01062 {
01063     PRArenaPool *arena;
01064     SECKEYPublicKey *key;
01065 
01066 /*@-moduncon@*/
01067     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01068     if (arena == NULL)
01069         return NULL;
01070 
01071     key = PORT_ArenaZAlloc(arena, sizeof(*key));
01072 
01073     if (key == NULL) {
01074         PORT_FreeArena(arena, PR_FALSE);
01075         return NULL;
01076     }
01077 /*@=moduncon@*/
01078     
01079     key->keyType = type;
01080     key->pkcs11ID = CK_INVALID_HANDLE;
01081     key->pkcs11Slot = NULL;
01082     key->arena = arena;
01083 /*@-nullret@*/  /* key->pkcs11Slot can be NULL */
01084     return key;
01085 /*@=nullret@*/
01086 }
01087 
01088 static
01089 int rpmnssMpiItem(const char * pre, pgpDig dig, int itemno,
01090                 const rpmuint8_t * p, /*@null@*/ const rpmuint8_t * pend)
01091         /*@*/
01092 {
01093     rpmnss nss = dig->impl;
01094     unsigned int hbits;
01095     size_t nb = (pend >= p ? (pend - p) : 0);
01096     int rc = 0;
01097 
01098 /*@-moduncon@*/
01099     switch (itemno) {
01100     default:
01101 assert(0);
01102         break;
01103     case 10:            /* RSA m**d */
01104         nss->sig = rpmnssMpiCopy(NULL, nss->sig, p);
01105         if (nss->sig == NULL)
01106             rc = 1;
01107         break;
01108     case 20:            /* DSA r */
01109         hbits = 160;
01110         nss->item.type = 0;
01111         nss->item.len = 2 * (hbits/8);
01112         nss->item.data = xcalloc(1, nss->item.len);
01113         rc = rpmnssMpiSet(pre, hbits, nss->item.data, p, pend);
01114         break;
01115     case 21:            /* DSA s */
01116         hbits = 160;
01117         rc = rpmnssMpiSet(pre, hbits, nss->item.data + (hbits/8), p, pend);
01118         if (nss->sig != NULL)
01119             SECITEM_FreeItem(nss->sig, PR_FALSE);
01120         if ((nss->sig = SECITEM_AllocItem(NULL, NULL, 0)) == NULL
01121          || DSAU_EncodeDerSig(nss->sig, &nss->item) != SECSuccess)
01122             rc = 1;
01123         nss->item.data = _free(nss->item.data);
01124         break;
01125     case 30:            /* RSA n */
01126         if (nss->pub_key == NULL)
01127             nss->pub_key = rpmnssNewPublicKey(rsaKey);
01128         if (nss->pub_key == NULL)
01129             rc = 1;
01130         else
01131             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.rsa.modulus, p);
01132         break;
01133     case 31:            /* RSA e */
01134         if (nss->pub_key == NULL)
01135             nss->pub_key = rpmnssNewPublicKey(rsaKey);
01136         if (nss->pub_key == NULL)
01137             rc = 1;
01138         else
01139             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.rsa.publicExponent, p);
01140         break;
01141     case 40:            /* DSA p */
01142         if (nss->pub_key == NULL)
01143             nss->pub_key = rpmnssNewPublicKey(dsaKey);
01144         if (nss->pub_key == NULL)
01145             rc = 1;
01146         else
01147             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.dsa.params.prime, p);
01148         break;
01149     case 41:            /* DSA q */
01150         if (nss->pub_key == NULL)
01151             nss->pub_key = rpmnssNewPublicKey(dsaKey);
01152         if (nss->pub_key == NULL)
01153             rc = 1;
01154         else
01155             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.dsa.params.subPrime, p);
01156         break;
01157     case 42:            /* DSA g */
01158         if (nss->pub_key == NULL)
01159             nss->pub_key = rpmnssNewPublicKey(dsaKey);
01160         if (nss->pub_key == NULL)
01161             rc = 1;
01162         else
01163             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.dsa.params.base, p);
01164         break;
01165     case 43:            /* DSA y */
01166         if (nss->pub_key == NULL)
01167             nss->pub_key = rpmnssNewPublicKey(dsaKey);
01168         if (nss->pub_key == NULL)
01169             rc = 1;
01170         else
01171             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.dsa.publicValue, p);
01172         break;
01173     case 50:            /* ECDSA r */
01174         hbits = 256;
01175         nss->item.type = 0;
01176         nss->item.len = 2 * (hbits/8);
01177         nss->item.data = xcalloc(1, nss->item.len);
01178         rc = rpmnssMpiSet(pre, hbits, nss->item.data, p, pend);
01179         break;
01180     case 51:            /* ECDSA s */
01181         hbits = 256;
01182         rc = rpmnssMpiSet(pre, hbits, nss->item.data + (hbits/8), p, pend);
01183         if (nss->sig != NULL)
01184             SECITEM_FreeItem(nss->sig, PR_FALSE);
01185         if ((nss->sig = SECITEM_AllocItem(NULL, NULL, 0)) == NULL
01186          || DSAU_EncodeDerSigWithLen(nss->sig, &nss->item, nss->item.len) != SECSuccess)
01187             rc = 1;
01188         nss->item.data = _free(nss->item.data);
01189         break;
01190     case 60:            /* ECDSA curve OID */
01191 assert(pend > p);
01192         if (nss->pub_key == NULL)
01193             nss->pub_key = rpmnssNewPublicKey(ecKey);
01194         if (nss->pub_key == NULL)
01195             rc = 1;
01196         else {
01197             SECKEYECParams * ecp = &nss->pub_key->u.ec.DEREncodedParams;
01198             ecp->data = PORT_ArenaZAlloc(nss->pub_key->arena, nb + 2);
01199             ecp->data[0] = SEC_ASN1_OBJECT_ID;
01200             ecp->data[1] = nb;
01201             memcpy(ecp->data + 2, p, nb);
01202             ecp->len = nb + 2;
01203         }
01204         break;
01205     case 61:            /* ECDSA Q */
01206 assert(nss->pub_key);
01207         /* XXX assumes uncompressed Q as a MPI */
01208         nss->pub_key->u.ec.size = ((nb - (2 + 1)) * 8)/2;
01209         (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.ec.publicValue, p);
01210         break;
01211     }
01212 /*@=moduncon@*/
01213     return rc;
01214 }
01215 
01216 /*@-mustmod@*/
01217 static
01218 void rpmnssClean(void * impl)
01219         /*@modifies impl @*/
01220 {
01221     rpmnss nss = impl;
01222 /*@-moduncon@*/
01223     if (nss != NULL) {
01224         nss->nbits = 0;
01225         nss->err = 0;
01226         nss->badok = 0;
01227         nss->digest = _free(nss->digest);
01228         nss->digestlen = 0;
01229 
01230         if (nss->sec_key != NULL) {
01231             SECKEY_DestroyPrivateKey(nss->sec_key);
01232             nss->sec_key = NULL;
01233         }
01234         if (nss->pub_key != NULL) {
01235             SECKEY_DestroyPublicKey(nss->pub_key);
01236             nss->pub_key = NULL;
01237         }
01238         if (nss->sig != NULL) {
01239             SECITEM_ZfreeItem(nss->sig, PR_TRUE);
01240             nss->sig = NULL;
01241         }
01242 
01243         if (nss->ecparams != NULL) {
01244             SECITEM_FreeItem(nss->ecparams, PR_FALSE);
01245             nss->ecparams = NULL;
01246         }
01247 /*@=moduncon@*/
01248     }
01249 }
01250 /*@=mustmod@*/
01251 
01252 static /*@null@*/
01253 void * rpmnssFree(/*@only@*/ void * impl)
01254         /*@*/
01255 {
01256     rpmnssClean(impl);
01257     impl = _free(impl);
01258     return NULL;
01259 }
01260 
01261 static
01262 void * rpmnssInit(void)
01263         /*@globals _rpmnss_init @*/
01264         /*@modifies _rpmnss_init @*/
01265 {
01266     rpmnss nss = xcalloc(1, sizeof(*nss));
01267     const char * _nssdb_path = rpmExpand("%{?_nssdb_path}", NULL);
01268 
01269 /*@-moduncon@*/
01270     if (_nssdb_path != NULL && *_nssdb_path == '/')
01271         (void) NSS_Init(_nssdb_path);
01272     else
01273     (void) NSS_NoDB_Init(NULL);
01274 /*@=moduncon@*/
01275     _nssdb_path = _free(_nssdb_path);
01276 
01277     _rpmnss_init = 1;
01278 
01279     return (void *) nss;
01280 }
01281 
01282 struct pgpImplVecs_s rpmnssImplVecs = {
01283         rpmnssSetRSA,
01284         rpmnssSetDSA,
01285         rpmnssSetELG,
01286         rpmnssSetECDSA,
01287 
01288         rpmnssErrChk,
01289         rpmnssAvailableCipher, rpmnssAvailableDigest, rpmnssAvailablePubkey,
01290         rpmnssVerify, rpmnssSign, rpmnssGenerate,
01291 
01292         rpmnssMpiItem, rpmnssClean,
01293         rpmnssFree, rpmnssInit
01294 };
01295 
01296 #endif
01297