rpm  5.4.4
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 = 1;         /* assume error */
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         goto exit;
00378 
00379 nss->digest = _free(nss->digest);
00380 nss->digestlen = 0;
00381     xx = rpmDigestFinal(ctx, (void **)&nss->digest, &nss->digestlen, 0);
00382     ctx = NULL;         /* XXX avoid double free */
00383 
00384     /* Compare leading 16 bits of digest for quick check. */
00385     rc = memcmp(nss->digest, sigp->signhash16, sizeof(sigp->signhash16));
00386 
00387 exit:
00388     if (ctx) {          /* XXX Free the context on error returns. */
00389         xx = rpmDigestFinal(ctx, NULL, NULL, 0);
00390         ctx = NULL;
00391     }
00392 SPEW(0, !rc, dig);
00393     return rc;
00394 }
00395 
00396 static
00397 int rpmnssVerifyRSA(pgpDig dig)
00398         /*@*/
00399 {
00400     rpmnss nss = dig->impl;
00401     int rc;
00402 
00403     nss->item.type = siBuffer;
00404     nss->item.data = nss->digest;
00405     nss->item.len = (unsigned) nss->digestlen;
00406 
00407     rc = rpmnssErr(nss, "VFY_VerifyDigest",
00408                 VFY_VerifyDigest(&nss->item, nss->pub_key,
00409                                 nss->sig, nss->sigalg, NULL));
00410     rc = (rc == SECSuccess);
00411 
00412 SPEW(0, !rc, dig);
00413     return rc;
00414 }
00415 
00416 static int rpmnssSignRSA(pgpDig dig)
00417 {
00418     rpmnss nss = dig->impl;
00419 pgpDigParams sigp = pgpGetSignature(dig);
00420     int rc = 0;         /* assume failure. */
00421 
00422 SECOidTag sigalg = SEC_OID_UNKNOWN;
00423     switch (sigp->hash_algo) {
00424     case PGPHASHALGO_MD5:
00425         sigalg = SEC_OID_MD5;
00426         break;
00427     case PGPHASHALGO_SHA1:
00428         sigalg = SEC_OID_SHA1;
00429         break;
00430     case PGPHASHALGO_RIPEMD160:
00431         break;
00432     case PGPHASHALGO_MD2:
00433         sigalg = SEC_OID_MD2;
00434         break;
00435     case PGPHASHALGO_MD4:
00436         sigalg = SEC_OID_MD4;
00437         break;
00438     case PGPHASHALGO_TIGER192:
00439         break;
00440     case PGPHASHALGO_HAVAL_5_160:
00441         break;
00442     case PGPHASHALGO_SHA256:
00443         sigalg = SEC_OID_SHA256;
00444         break;
00445     case PGPHASHALGO_SHA384:
00446         sigalg = SEC_OID_SHA384;
00447         break;
00448     case PGPHASHALGO_SHA512:
00449         sigalg = SEC_OID_SHA512;
00450         break;
00451     case PGPHASHALGO_SHA224:
00452         break;
00453     default:
00454         break;
00455     }
00456     if (sigalg == SEC_OID_UNKNOWN)
00457         goto exit;
00458 
00459     nss->item.type = siBuffer;
00460     nss->item.data = nss->digest;
00461     nss->item.len = (unsigned) nss->digestlen;
00462 
00463 if (nss->sig != NULL) {
00464     SECITEM_ZfreeItem(nss->sig, PR_TRUE);
00465     nss->sig = NULL;
00466 }
00467 nss->sig = SECITEM_AllocItem(NULL, NULL, 0);
00468 nss->sig->type = siBuffer;
00469 
00470     rc = rpmnssErr(nss, "SGN_Digest",
00471             SGN_Digest(nss->sec_key, sigalg, nss->sig, &nss->item));
00472     rc = (rc == SECSuccess);
00473 
00474 exit:
00475 SPEW(!rc, rc, dig);
00476     return rc;
00477 }
00478 
00479 static int rpmnssGenerateRSA(pgpDig dig)
00480 {
00481     rpmnss nss = dig->impl;
00482     int rc = 0;         /* assume failure */
00483 
00484 if (nss->nbits == 0) nss->nbits = 1024; /* XXX FIXME */
00485 assert(nss->nbits);
00486 
00487     {   CK_MECHANISM_TYPE _type = CKM_RSA_PKCS_KEY_PAIR_GEN;
00488         PK11SlotInfo * _slot = PK11_GetBestSlot(_type, NULL);
00489         int _isPerm = PR_FALSE;
00490         int _isSensitive = PR_TRUE;
00491         void * _cx = NULL;
00492 
00493         if (_slot) {
00494             static unsigned _pe = 0x10001;      /* XXX FIXME: pass in e */
00495             PK11RSAGenParams rsaparams =
00496                 { .keySizeInBits = nss->nbits, .pe = _pe };
00497             void * params = &rsaparams;
00498 
00499             nss->sec_key = PK11_GenerateKeyPair(_slot, _type, params,
00500                         &nss->pub_key, _isPerm, _isSensitive, _cx);
00501 
00502             PK11_FreeSlot(_slot);
00503         }
00504     }
00505 
00506     rc = (nss->sec_key && nss->pub_key);
00507 
00508 SPEW(!rc, rc, dig);
00509     return rc;
00510 }
00511 
00512 static
00513 int rpmnssSetDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
00514         /*@modifies dig @*/
00515 {
00516     rpmnss nss = dig->impl;
00517     int rc;
00518     int xx;
00519 pgpDigParams pubp = pgpGetPubkey(dig);
00520 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00521 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00522 
00523 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00524 nss->digest = _free(nss->digest);
00525 nss->digestlen = 0;
00526     xx = rpmDigestFinal(ctx, (void **)&nss->digest, &nss->digestlen, 0);
00527 
00528     nss->sigalg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
00529 
00530     /* Compare leading 16 bits of digest for quick check. */
00531     rc = memcmp(nss->digest, sigp->signhash16, sizeof(sigp->signhash16));
00532 SPEW(0, !rc, dig);
00533     return rc;
00534 }
00535 
00536 static
00537 int rpmnssVerifyDSA(pgpDig dig)
00538         /*@*/
00539 {
00540     rpmnss nss = dig->impl;
00541     int rc;
00542 
00543     nss->item.type = siBuffer;
00544     nss->item.data = nss->digest;
00545     nss->item.len = (unsigned) nss->digestlen;
00546 
00547     rc = rpmnssErr(nss, "VFY_VerifyDigest",
00548                 VFY_VerifyDigest(&nss->item, nss->pub_key,
00549                                 nss->sig, nss->sigalg, NULL));
00550     rc = (rc == SECSuccess);
00551 
00552 SPEW(0, rc, dig);
00553     return rc;
00554 }
00555 
00556 static int rpmnssSignDSA(pgpDig dig)
00557 {
00558     rpmnss nss = dig->impl;
00559 pgpDigParams sigp = pgpGetSignature(dig);
00560     int rc = 0;         /* assume failure. */
00561 SECItem sig = { .type = siBuffer, .len = 0, .data = NULL };
00562 
00563 SECOidTag sigalg = SEC_OID_UNKNOWN;
00564     switch (sigp->hash_algo) {
00565     case PGPHASHALGO_MD5:
00566         break;
00567     case PGPHASHALGO_SHA1:
00568         sigalg = SEC_OID_SHA1;
00569         break;
00570     case PGPHASHALGO_RIPEMD160:
00571         break;
00572     case PGPHASHALGO_MD2:
00573         break;
00574     case PGPHASHALGO_MD4:
00575         break;
00576     case PGPHASHALGO_TIGER192:
00577         break;
00578     case PGPHASHALGO_HAVAL_5_160:
00579         break;
00580     case PGPHASHALGO_SHA256:
00581         break;
00582     case PGPHASHALGO_SHA384:
00583         break;
00584     case PGPHASHALGO_SHA512:
00585         break;
00586     case PGPHASHALGO_SHA224:
00587         break;
00588     default:
00589         break;
00590     }
00591     if (sigalg == SEC_OID_UNKNOWN)
00592         goto exit;
00593 
00594     nss->item.type = siBuffer;
00595     nss->item.data = nss->digest;
00596     nss->item.len = (unsigned) nss->digestlen;
00597 
00598 if (nss->sig != NULL) {
00599     SECITEM_ZfreeItem(nss->sig, PR_TRUE);
00600     nss->sig = NULL;
00601 }
00602 
00603 nss->sig = SECITEM_AllocItem(NULL, NULL, 0);
00604 nss->sig->type = siBuffer;
00605 
00606     rc = rpmnssErr(nss, "SGN_Digest",
00607             SGN_Digest(nss->sec_key, sigalg, &sig, &nss->item));
00608 
00609     if (rc == SECSuccess)
00610         rc = rpmnssErr(nss, "DSAU_EncodeDerSig",
00611                 DSAU_EncodeDerSig(nss->sig, &sig));
00612 
00613     sig.data = _free(sig.data);
00614 
00615     rc = (rc == SECSuccess);
00616 
00617 exit:
00618 SPEW(!rc, rc, dig);
00619     return rc;
00620 }
00621 
00622 static int rpmnssGenerateDSA(pgpDig dig)
00623 {
00624     rpmnss nss = dig->impl;
00625     int rc = 0;         /* assume failure */
00626 
00627 if (nss->nbits == 0) nss->nbits = 1024; /* XXX FIXME */
00628 assert(nss->nbits);
00629 
00630     {   CK_MECHANISM_TYPE _type = CKM_DSA_KEY_PAIR_GEN;
00631         PK11SlotInfo * _slot = PK11_GetBestSlot(_type, NULL);
00632         int _isPerm = PR_FALSE;
00633         int _isSensitive = PR_TRUE;
00634         void * _cx = NULL;
00635 
00636         if (_slot) {
00637             PQGParams *pqgParams = NULL;
00638             PQGVerify *pqgVfy = NULL;
00639             void * params = NULL;
00640 int xx;
00641 
00642             xx = rpmnssErr(nss, "PK11_PQG_ParamGen",
00643                         PK11_PQG_ParamGen(0, &pqgParams, &pqgVfy));
00644             if (xx != SECSuccess)
00645                 goto exit;
00646             params = pqgParams;
00647 
00648             nss->sec_key = PK11_GenerateKeyPair(_slot, _type, params,
00649                         &nss->pub_key, _isPerm, _isSensitive, _cx);
00650 
00651             if (pqgVfy) PK11_PQG_DestroyVerify(pqgVfy);
00652             if (pqgParams) PK11_PQG_DestroyParams(pqgParams);
00653 
00654             PK11_FreeSlot(_slot);
00655         }
00656     }
00657 
00658     rc = (nss->sec_key && nss->pub_key);
00659 
00660 exit:
00661 SPEW(!rc, rc, dig);
00662     return rc;
00663 }
00664 
00665 static
00666 int rpmnssSetELG(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp)
00667         /*@*/
00668 {
00669     rpmnss nss = dig->impl;
00670     int rc = 1;         /* XXX always fail. */
00671     int xx;
00672 
00673 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00674 nss->digest = _free(nss->digest);
00675 nss->digestlen = 0;
00676     xx = rpmDigestFinal(ctx, (void **)&nss->digest, &nss->digestlen, 0);
00677 
00678     /* Compare leading 16 bits of digest for quick check. */
00679 
00680     return rc;
00681 }
00682 
00683 static
00684 int rpmnssSetECDSA(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp)
00685         /*@*/
00686 {
00687     rpmnss nss = dig->impl;
00688     int xx;
00689 
00690 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
00691     nss->sigalg = SEC_OID_UNKNOWN;
00692     switch (sigp->hash_algo) {
00693     case PGPHASHALGO_SHA1:
00694         nss->sigalg = SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE;
00695         break;
00696     case PGPHASHALGO_SHA224:
00697         nss->sigalg = SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE;
00698         break;
00699     case PGPHASHALGO_SHA256:
00700         nss->sigalg = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
00701         break;
00702     case PGPHASHALGO_SHA384:
00703         nss->sigalg = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
00704         break;
00705     case PGPHASHALGO_SHA512:
00706         nss->sigalg = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
00707         break;
00708     default:
00709         break;
00710     }
00711     if (nss->sigalg == SEC_OID_UNKNOWN)
00712         return 1;
00713 
00714 nss->digest = _free(nss->digest);
00715 nss->digestlen = 0;
00716     xx = rpmDigestFinal(ctx, (void **)&nss->digest, &nss->digestlen, 0);
00717 
00718     /* Compare leading 16 bits of digest for quick check. */
00719     return memcmp(nss->digest, sigp->signhash16, sizeof(sigp->signhash16));
00720 }
00721 
00722 static
00723 int rpmnssVerifyECDSA(/*@unused@*/pgpDig dig)
00724         /*@*/
00725 {
00726     rpmnss nss = dig->impl;
00727     int rc;
00728 
00729     nss->item.type = siBuffer;
00730     nss->item.data = nss->digest;
00731     nss->item.len = (unsigned) nss->digestlen;
00732 
00733     rc = VFY_VerifyDigest(&nss->item, nss->pub_key, nss->sig, nss->sigalg, NULL);
00734     rc = (rc == SECSuccess);
00735 
00736 SPEW(!rc, rc, dig);
00737     return rc;
00738 }
00739 
00740 static
00741 int rpmnssSignECDSA(/*@unused@*/pgpDig dig)
00742         /*@*/
00743 {
00744     rpmnss nss = dig->impl;
00745 pgpDigParams sigp = pgpGetSignature(dig);
00746     int rc = 0;         /* assume failure. */
00747 
00748 SECOidTag sigalg = SEC_OID_UNKNOWN;
00749     switch (sigp->hash_algo) {
00750     case PGPHASHALGO_MD5:
00751         break;
00752     case PGPHASHALGO_SHA1:
00753         sigalg = SEC_OID_SHA1;
00754         break;
00755     case PGPHASHALGO_RIPEMD160:
00756         break;
00757     case PGPHASHALGO_MD2:
00758         break;
00759     case PGPHASHALGO_MD4:
00760         break;
00761     case PGPHASHALGO_TIGER192:
00762         break;
00763     case PGPHASHALGO_HAVAL_5_160:
00764         break;
00765     case PGPHASHALGO_SHA256:
00766         sigalg = SEC_OID_SHA256;
00767         break;
00768     case PGPHASHALGO_SHA384:
00769         sigalg = SEC_OID_SHA384;
00770         break;
00771     case PGPHASHALGO_SHA512:
00772         sigalg = SEC_OID_SHA512;
00773         break;
00774     case PGPHASHALGO_SHA224:
00775         break;
00776     default:
00777         break;
00778     }
00779     if (sigalg == SEC_OID_UNKNOWN)
00780         goto exit;
00781 
00782 if (nss->sig != NULL) {
00783     SECITEM_ZfreeItem(nss->sig, PR_TRUE);
00784     nss->sig = NULL;
00785 }
00786 nss->sig = SECITEM_AllocItem(NULL, NULL, 0);
00787 nss->sig->type = siBuffer;
00788 
00789     rc = rpmnssErr(nss, "SGN_Digest",
00790             SGN_Digest(nss->sec_key, sigalg, nss->sig, &nss->item));
00791 
00792     rc = (rc == SECSuccess);
00793 
00794 exit:
00795 SPEW(!rc, rc, dig);
00796     return rc;
00797 }
00798 
00799 static
00800 int rpmnssGenerateECDSA(/*@unused@*/pgpDig dig)
00801         /*@*/
00802 {
00803     rpmnss nss = dig->impl;
00804     int rc = 0;         /* assume failure. */
00805 
00806     {   CK_MECHANISM_TYPE _type = CKM_EC_KEY_PAIR_GEN;
00807         PK11SlotInfo * _slot = PK11_GetBestSlot(_type, NULL);
00808         int _isPerm = PR_FALSE;
00809         int _isSensitive = PR_FALSE;
00810         void * _cx = NULL;
00811 
00812         if (_slot) {
00813 
00814             nss->sec_key = PK11_GenerateKeyPair(_slot, _type, nss->ecparams,
00815                         &nss->pub_key, _isPerm, _isSensitive, _cx);
00816 
00817             PK11_FreeSlot(_slot);
00818         }
00819     }
00820 
00821     rc = (nss->sec_key && nss->pub_key);
00822 
00823 SPEW(!rc, rc, dig);
00824 
00825     return rc;
00826 }
00827 
00828 static int rpmnssErrChk(pgpDig dig, const char * msg, int rc, unsigned expected)
00829 {
00830 #ifdef  NOTYET
00831 rpmgc gc = dig->impl;
00832     /* Was the return code the expected result? */
00833     rc = (gcry_err_code(gc->err) != expected);
00834     if (rc)
00835         fail("%s failed: %s\n", msg, gpg_strerror(gc->err));
00836 /* XXX FIXME: rpmnssStrerror */
00837 #else
00838     rc = (rc == 0);     /* XXX impedance match 1 -> 0 on success */
00839 #endif
00840     return rc;  /* XXX 0 on success */
00841 }
00842 
00843 static int rpmnssAvailableCipher(pgpDig dig, int algo)
00844 {
00845     int rc = 0; /* assume available */
00846 #ifdef  NOTYET
00847     rc = rpmgnssvailable(dig->impl, algo,
00848         (gcry_md_test_algo(algo) || algo == PGPHASHALGO_MD5));
00849 #endif
00850     return rc;
00851 }
00852 
00853 static int rpmnssAvailableDigest(pgpDig dig, int algo)
00854 {
00855     int rc = 0; /* assume available */
00856 #ifdef  NOTYET
00857     rc = rpmgnssvailable(dig->impl, algo,
00858         (gcry_md_test_algo(algo) || algo == PGPHASHALGO_MD5));
00859 #endif
00860     return rc;
00861 }
00862 
00863 static int rpmnssAvailablePubkey(pgpDig dig, int algo)
00864 {
00865     int rc = 0; /* assume available */
00866 #ifdef  NOTYET
00867     rc = rpmnssAvailable(dig->impl, algo, gcry_pk_test_algo(algo));
00868 #endif
00869     return rc;
00870 }
00871 
00872 static int rpmnssVerify(pgpDig dig)
00873 {
00874     rpmnss nss = dig->impl;
00875     int rc = 0;         /* assume failure */
00876 pgpDigParams pubp = pgpGetPubkey(dig);
00877 pgpDigParams sigp = pgpGetSignature(dig);
00878 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00879 dig->hash_algoN = _pgpHashAlgo2Name(sigp->hash_algo);
00880 
00881     switch (pubp->pubkey_algo) {
00882     default:
00883         break;
00884     case PGPPUBKEYALGO_RSA:
00885         rc = rpmnssVerifyRSA(dig);
00886         break;
00887     case PGPPUBKEYALGO_DSA:
00888         rc = rpmnssVerifyDSA(dig);
00889         break;
00890     case PGPPUBKEYALGO_ELGAMAL:
00891 #ifdef  NOTYET
00892         rc = rpmnssVerifyELG(dig);
00893 #endif
00894         break;
00895     case PGPPUBKEYALGO_ECDSA:
00896         if (nss->sigalg != SEC_OID_UNKNOWN)
00897             rc = rpmnssVerifyECDSA(dig);
00898         break;
00899     }
00900 SPEW(0, rc, dig);
00901     return rc;
00902 }
00903 
00904 static int rpmnssSign(pgpDig dig)
00905 {
00906     rpmnss nss = dig->impl;
00907     int rc = 0;         /* assume failure */
00908 pgpDigParams pubp = pgpGetPubkey(dig);
00909 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00910     switch (pubp->pubkey_algo) {
00911     default:
00912         break;
00913     case PGPPUBKEYALGO_RSA:
00914         rc = rpmnssSignRSA(dig);
00915         break;
00916     case PGPPUBKEYALGO_DSA:
00917         rc = rpmnssSignDSA(dig);
00918         break;
00919     case PGPPUBKEYALGO_ELGAMAL:
00920 #ifdef  NOTYET
00921         rc = rpmnssSignELG(dig);
00922 #endif
00923         break;
00924     case PGPPUBKEYALGO_ECDSA:
00925         if (nss->sigalg != SEC_OID_UNKNOWN)
00926             rc = rpmnssSignECDSA(dig);
00927         break;
00928     }
00929 SPEW(!rc, rc, dig);
00930     return rc;
00931 }
00932 
00933 static int rpmnssLoadParams(pgpDig dig, const char * name)
00934 {
00935     rpmnss nss = dig->impl;
00936 #ifdef  NOTYET
00937     SECOidTag curveOidTag = curve2oid(name);
00938 #else
00939     SECOidTag curveOidTag = !strcmp(name, "nistp256")
00940                 ? SEC_OID_SECG_EC_SECP256R1 : SEC_OID_UNKNOWN;
00941 #endif
00942     SECOidData * oidData = SECOID_FindOIDByTag(curveOidTag);
00943     int rc = 1;         /* assume failure. */
00944     
00945     if (curveOidTag == SEC_OID_UNKNOWN || oidData == NULL) {
00946         nss->sigalg = curveOidTag;
00947         goto exit;
00948     }
00949 
00950     nss->sigalg = curveOidTag;
00951 
00952     nss->ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
00953     nss->ecparams->data[0] = SEC_ASN1_OBJECT_ID;
00954     nss->ecparams->data[1] = oidData->oid.len;
00955     memcpy(nss->ecparams->data + 2, oidData->oid.data, oidData->oid.len);
00956     rc = 0;
00957 
00958 exit:
00959 if (1 || _pgp_debug)
00960 fprintf(stderr, "<-- %s(%p,%s) oid %u params %p\n", __FUNCTION__, dig, name, nss->sigalg, nss->ecparams);
00961     return rc;
00962 }
00963 
00964 static int rpmnssGenerate(pgpDig dig)
00965 {
00966     int rc = 0;         /* assume failure */
00967 pgpDigParams pubp = pgpGetPubkey(dig);
00968 dig->pubkey_algoN = _pgpPubkeyAlgo2Name(pubp->pubkey_algo);
00969 
00970     switch (pubp->pubkey_algo) {
00971     default:
00972         break;
00973     case PGPPUBKEYALGO_RSA:
00974         rc = rpmnssGenerateRSA(dig);
00975         break;
00976     case PGPPUBKEYALGO_DSA:
00977         rc = rpmnssGenerateDSA(dig);
00978         break;
00979     case PGPPUBKEYALGO_ELGAMAL:
00980 #ifdef  NOTYET
00981         rc = rpmnssGenerateELG(dig);
00982 #endif
00983         break;
00984     case PGPPUBKEYALGO_ECDSA:
00985         rc = rpmnssLoadParams(dig, "nistp256");
00986         if (!rc)
00987             rc = rpmnssGenerateECDSA(dig);
00988         break;
00989     }
00990 SPEW(!rc, rc, dig);
00991     return rc;
00992 }
00993 
00997 static
00998 int rpmnssMpiSet(const char * pre, unsigned int lbits,
00999                 /*@out@*/ void * dest, const rpmuint8_t * p,
01000                 /*@null@*/ const rpmuint8_t * pend)
01001         /*@modifies *dest @*/
01002 {
01003     unsigned int mbits = pgpMpiBits(p);
01004     unsigned int nbits;
01005     unsigned int nbytes;
01006     char * t = dest;
01007     unsigned int ix;
01008 
01009     if (pend != NULL && (p + ((mbits+7) >> 3)) > pend)
01010         return 1;
01011 
01012     if (mbits > lbits)
01013         return 1;
01014 
01015     nbits = (lbits > mbits ? lbits : mbits);
01016     nbytes = ((nbits + 7) >> 3);
01017     ix = ((nbits - mbits) >> 3);
01018 
01019 /*@-modfilesystem @*/
01020 if (_pgp_debug)
01021 fprintf(stderr, "*** mbits %u nbits %u nbytes %u ix %u\n", mbits, nbits, nbytes, ix);
01022     if (ix > 0) memset(t, (int)'\0', ix);
01023     memcpy(t+ix, p+2, nbytes-ix);
01024 if (_pgp_debug && _pgp_print)
01025 fprintf(stderr, "\t %s %s\n", pre, pgpHexStr(dest, nbytes));
01026 /*@=modfilesystem @*/
01027     return 0;
01028 }
01029 
01033 static
01034 /*@only@*/ /*@null@*/
01035 SECItem * rpmnssMpiCopy(PRArenaPool * arena, /*@returned@*/ SECItem * item,
01036                 const rpmuint8_t * p)
01037         /*@modifies item @*/
01038 {
01039     unsigned int nbytes = pgpMpiLen(p)-2;
01040 
01041 /*@-moduncon@*/
01042     if (item == NULL) {
01043         if ((item = SECITEM_AllocItem(arena, item, nbytes)) == NULL)
01044             return item;
01045     } else {
01046         if (arena != NULL)
01047             item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
01048         else
01049             item->data = PORT_Realloc(item->data, nbytes);
01050         
01051         if (item->data == NULL) {
01052             if (arena == NULL)
01053                 SECITEM_FreeItem(item, PR_TRUE);
01054             return NULL;
01055         }
01056     }
01057 /*@=moduncon@*/
01058 
01059     memcpy(item->data, p+2, nbytes);
01060     item->len = nbytes;
01061 /*@-temptrans@*/
01062     return item;
01063 /*@=temptrans@*/
01064 }
01065 
01066 static /*@null@*/
01067 SECKEYPublicKey * rpmnssNewPublicKey(KeyType type)
01068         /*@*/
01069 {
01070     PRArenaPool *arena;
01071     SECKEYPublicKey *key;
01072 
01073 /*@-moduncon@*/
01074     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01075     if (arena == NULL)
01076         return NULL;
01077 
01078     key = PORT_ArenaZAlloc(arena, sizeof(*key));
01079 
01080     if (key == NULL) {
01081         PORT_FreeArena(arena, PR_FALSE);
01082         return NULL;
01083     }
01084 /*@=moduncon@*/
01085     
01086     key->keyType = type;
01087     key->pkcs11ID = CK_INVALID_HANDLE;
01088     key->pkcs11Slot = NULL;
01089     key->arena = arena;
01090 /*@-nullret@*/  /* key->pkcs11Slot can be NULL */
01091     return key;
01092 /*@=nullret@*/
01093 }
01094 
01095 static
01096 int rpmnssMpiItem(const char * pre, pgpDig dig, int itemno,
01097                 const rpmuint8_t * p, /*@null@*/ const rpmuint8_t * pend)
01098         /*@*/
01099 {
01100     rpmnss nss = dig->impl;
01101     unsigned int hbits;
01102     size_t nb = (pend >= p ? (pend - p) : 0);
01103     int rc = 0;
01104 
01105 /*@-moduncon@*/
01106     switch (itemno) {
01107     default:
01108 assert(0);
01109         break;
01110     case 10:            /* RSA m**d */
01111         nss->sig = rpmnssMpiCopy(NULL, nss->sig, p);
01112         if (nss->sig == NULL)
01113             rc = 1;
01114         break;
01115     case 20:            /* DSA r */
01116         hbits = 160;
01117         nss->item.type = 0;
01118         nss->item.len = 2 * (hbits/8);
01119         nss->item.data = xcalloc(1, nss->item.len);
01120         rc = rpmnssMpiSet(pre, hbits, nss->item.data, p, pend);
01121         break;
01122     case 21:            /* DSA s */
01123         hbits = 160;
01124         rc = rpmnssMpiSet(pre, hbits, nss->item.data + (hbits/8), p, pend);
01125         if (nss->sig != NULL)
01126             SECITEM_FreeItem(nss->sig, PR_FALSE);
01127         if ((nss->sig = SECITEM_AllocItem(NULL, NULL, 0)) == NULL
01128          || DSAU_EncodeDerSig(nss->sig, &nss->item) != SECSuccess)
01129             rc = 1;
01130         nss->item.data = _free(nss->item.data);
01131         break;
01132     case 30:            /* RSA n */
01133         if (nss->pub_key == NULL)
01134             nss->pub_key = rpmnssNewPublicKey(rsaKey);
01135         if (nss->pub_key == NULL)
01136             rc = 1;
01137         else
01138             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.rsa.modulus, p);
01139         break;
01140     case 31:            /* RSA e */
01141         if (nss->pub_key == NULL)
01142             nss->pub_key = rpmnssNewPublicKey(rsaKey);
01143         if (nss->pub_key == NULL)
01144             rc = 1;
01145         else
01146             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.rsa.publicExponent, p);
01147         break;
01148     case 40:            /* DSA p */
01149         if (nss->pub_key == NULL)
01150             nss->pub_key = rpmnssNewPublicKey(dsaKey);
01151         if (nss->pub_key == NULL)
01152             rc = 1;
01153         else
01154             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.dsa.params.prime, p);
01155         break;
01156     case 41:            /* DSA q */
01157         if (nss->pub_key == NULL)
01158             nss->pub_key = rpmnssNewPublicKey(dsaKey);
01159         if (nss->pub_key == NULL)
01160             rc = 1;
01161         else
01162             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.dsa.params.subPrime, p);
01163         break;
01164     case 42:            /* DSA g */
01165         if (nss->pub_key == NULL)
01166             nss->pub_key = rpmnssNewPublicKey(dsaKey);
01167         if (nss->pub_key == NULL)
01168             rc = 1;
01169         else
01170             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.dsa.params.base, p);
01171         break;
01172     case 43:            /* DSA y */
01173         if (nss->pub_key == NULL)
01174             nss->pub_key = rpmnssNewPublicKey(dsaKey);
01175         if (nss->pub_key == NULL)
01176             rc = 1;
01177         else
01178             (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.dsa.publicValue, p);
01179         break;
01180     case 50:            /* ECDSA r */
01181         hbits = 256;
01182         nss->item.type = 0;
01183         nss->item.len = 2 * (hbits/8);
01184         nss->item.data = xcalloc(1, nss->item.len);
01185         rc = rpmnssMpiSet(pre, hbits, nss->item.data, p, pend);
01186         break;
01187     case 51:            /* ECDSA s */
01188         hbits = 256;
01189         rc = rpmnssMpiSet(pre, hbits, nss->item.data + (hbits/8), p, pend);
01190         if (nss->sig != NULL)
01191             SECITEM_FreeItem(nss->sig, PR_FALSE);
01192         if ((nss->sig = SECITEM_AllocItem(NULL, NULL, 0)) == NULL
01193          || DSAU_EncodeDerSigWithLen(nss->sig, &nss->item, nss->item.len) != SECSuccess)
01194             rc = 1;
01195         nss->item.data = _free(nss->item.data);
01196         break;
01197     case 60:            /* ECDSA curve OID */
01198 assert(pend > p);
01199         if (nss->pub_key == NULL)
01200             nss->pub_key = rpmnssNewPublicKey(ecKey);
01201         if (nss->pub_key == NULL)
01202             rc = 1;
01203         else {
01204             SECKEYECParams * ecp = &nss->pub_key->u.ec.DEREncodedParams;
01205             ecp->data = PORT_ArenaZAlloc(nss->pub_key->arena, nb + 2);
01206             ecp->data[0] = SEC_ASN1_OBJECT_ID;
01207             ecp->data[1] = nb;
01208             memcpy(ecp->data + 2, p, nb);
01209             ecp->len = nb + 2;
01210         }
01211         break;
01212     case 61:            /* ECDSA Q */
01213 assert(nss->pub_key);
01214         /* XXX assumes uncompressed Q as a MPI */
01215         nss->pub_key->u.ec.size = ((nb - (2 + 1)) * 8)/2;
01216         (void) rpmnssMpiCopy(nss->pub_key->arena, &nss->pub_key->u.ec.publicValue, p);
01217         break;
01218     }
01219 /*@=moduncon@*/
01220     return rc;
01221 }
01222 
01223 /*@-mustmod@*/
01224 static
01225 void rpmnssClean(void * impl)
01226         /*@modifies impl @*/
01227 {
01228     rpmnss nss = impl;
01229 /*@-moduncon@*/
01230     if (nss != NULL) {
01231         nss->nbits = 0;
01232         nss->err = 0;
01233         nss->badok = 0;
01234         nss->digest = _free(nss->digest);
01235         nss->digestlen = 0;
01236 
01237         if (nss->sec_key != NULL) {
01238             SECKEY_DestroyPrivateKey(nss->sec_key);
01239             nss->sec_key = NULL;
01240         }
01241         if (nss->pub_key != NULL) {
01242             SECKEY_DestroyPublicKey(nss->pub_key);
01243             nss->pub_key = NULL;
01244         }
01245         if (nss->sig != NULL) {
01246             SECITEM_ZfreeItem(nss->sig, PR_TRUE);
01247             nss->sig = NULL;
01248         }
01249 
01250         if (nss->ecparams != NULL) {
01251             SECITEM_FreeItem(nss->ecparams, PR_FALSE);
01252             nss->ecparams = NULL;
01253         }
01254 /*@=moduncon@*/
01255     }
01256 }
01257 /*@=mustmod@*/
01258 
01259 static /*@null@*/
01260 void * rpmnssFree(/*@only@*/ void * impl)
01261         /*@*/
01262 {
01263     rpmnssClean(impl);
01264     impl = _free(impl);
01265     return NULL;
01266 }
01267 
01268 static
01269 void * rpmnssInit(void)
01270         /*@globals _rpmnss_init @*/
01271         /*@modifies _rpmnss_init @*/
01272 {
01273     rpmnss nss = xcalloc(1, sizeof(*nss));
01274     const char * _nssdb_path = rpmExpand("%{?_nssdb_path}", NULL);
01275 
01276 /*@-moduncon@*/
01277     if (_nssdb_path != NULL && *_nssdb_path == '/')
01278         (void) NSS_Init(_nssdb_path);
01279     else
01280     (void) NSS_NoDB_Init(NULL);
01281 /*@=moduncon@*/
01282     _nssdb_path = _free(_nssdb_path);
01283 
01284     _rpmnss_init = 1;
01285 
01286     return (void *) nss;
01287 }
01288 
01289 struct pgpImplVecs_s rpmnssImplVecs = {
01290         rpmnssSetRSA,
01291         rpmnssSetDSA,
01292         rpmnssSetELG,
01293         rpmnssSetECDSA,
01294 
01295         rpmnssErrChk,
01296         rpmnssAvailableCipher, rpmnssAvailableDigest, rpmnssAvailablePubkey,
01297         rpmnssVerify, rpmnssSign, rpmnssGenerate,
01298 
01299         rpmnssMpiItem, rpmnssClean,
01300         rpmnssFree, rpmnssInit
01301 };
01302 
01303 #endif
01304