From f4a12fc67689a830e9da1c87fd11afe5bc09deb3 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Thu, 2 Jan 2020 21:06:40 +0100 Subject: Issue #1338 - Part 2: Update NSS to 3.48-RTM --- security/nss/lib/pk11wrap/debug_module.c | 33 ++++++++ security/nss/lib/pk11wrap/pk11akey.c | 115 +++++++++++++++++++++++++-- security/nss/lib/pk11wrap/pk11cert.c | 97 ++++++++++++++++++++++- security/nss/lib/pk11wrap/pk11cxt.c | 2 +- security/nss/lib/pk11wrap/pk11load.c | 18 ++--- security/nss/lib/pk11wrap/pk11mech.c | 15 ++++ security/nss/lib/pk11wrap/pk11obj.c | 132 +++++++++++++++++++++++++++---- security/nss/lib/pk11wrap/pk11pars.c | 26 ++++-- security/nss/lib/pk11wrap/pk11pbe.c | 6 +- security/nss/lib/pk11wrap/pk11pk12.c | 4 + security/nss/lib/pk11wrap/pk11priv.h | 1 + security/nss/lib/pk11wrap/pk11pub.h | 24 +++++- security/nss/lib/pk11wrap/pk11skey.c | 87 ++++++++++++++++---- security/nss/lib/pk11wrap/pk11slot.c | 107 ++++++++++++++++++++----- security/nss/lib/pk11wrap/pk11util.c | 29 ++++++- security/nss/lib/pk11wrap/pk11wrap.gyp | 2 +- security/nss/lib/pk11wrap/secmodi.h | 7 ++ security/nss/lib/pk11wrap/secmodti.h | 2 + 18 files changed, 620 insertions(+), 87 deletions(-) (limited to 'security/nss/lib/pk11wrap') diff --git a/security/nss/lib/pk11wrap/debug_module.c b/security/nss/lib/pk11wrap/debug_module.c index 9230c0136..6dddb24b4 100644 --- a/security/nss/lib/pk11wrap/debug_module.c +++ b/security/nss/lib/pk11wrap/debug_module.c @@ -134,6 +134,7 @@ get_attr_type_str(CK_ATTRIBUTE_TYPE atype, char *str, int len) CASE(CKA_RESET_ON_INIT); CASE(CKA_HAS_RESET); CASE(CKA_VENDOR_DEFINED); + CASE(CKA_PROFILE_ID); CASE(CKA_NSS_URL); CASE(CKA_NSS_EMAIL); CASE(CKA_NSS_SMIME_INFO); @@ -189,6 +190,7 @@ get_obj_class(CK_OBJECT_CLASS objClass, char *str, int len) CASE(CKO_SECRET_KEY); CASE(CKO_HW_FEATURE); CASE(CKO_DOMAIN_PARAMETERS); + CASE(CKO_PROFILE); CASE(CKO_NSS_CRL); CASE(CKO_NSS_SMIME); CASE(CKO_NSS_TRUST); @@ -202,6 +204,27 @@ get_obj_class(CK_OBJECT_CLASS objClass, char *str, int len) PR_snprintf(str, len, "0x%p", objClass); } +static void +get_profile_val(CK_PROFILE_ID profile, char *str, int len) +{ + + const char *a = NULL; + + switch (profile) { + CASE(CKP_INVALID_ID); + CASE(CKP_BASELINE_PROVIDER); + CASE(CKP_EXTENDED_PROVIDER); + CASE(CKP_AUTHENTICATION_TOKEN); + CASE(CKP_PUBLIC_CERTIFICATES_TOKEN); + default: + break; + } + if (a) + PR_snprintf(str, len, "%s", a); + else + PR_snprintf(str, len, "0x%p", profile); +} + static void get_trust_val(CK_TRUST trust, char *str, int len) { @@ -376,6 +399,8 @@ print_mechanism(CK_MECHANISM_PTR m) CASE(CKM_AES_KEY_GEN); CASE(CKM_AES_MAC); CASE(CKM_AES_MAC_GENERAL); + CASE(CKM_AES_CMAC); + CASE(CKM_AES_CMAC_GENERAL); CASE(CKM_CAMELLIA_CBC); CASE(CKM_CAMELLIA_CBC_ENCRYPT_DATA); CASE(CKM_CAMELLIA_CBC_PAD); @@ -686,6 +711,14 @@ print_attr_value(CK_ATTRIBUTE_PTR attr) atype, valstr, attr->ulValueLen)); break; } + case CKA_PROFILE_ID: + if (attr->ulValueLen > 0 && attr->pValue) { + CK_PROFILE_ID profile = *((CK_PROFILE_ID *)attr->pValue); + get_profile_val(profile, valstr, sizeof valstr); + PR_LOG(modlog, 4, (fmt_s_s_d, + atype, valstr, attr->ulValueLen)); + break; + } case CKA_ISSUER: case CKA_SUBJECT: if (attr->ulValueLen > 0 && attr->pValue) { diff --git a/security/nss/lib/pk11wrap/pk11akey.c b/security/nss/lib/pk11wrap/pk11akey.c index 9a914272d..03fe48c36 100644 --- a/security/nss/lib/pk11wrap/pk11akey.c +++ b/security/nss/lib/pk11wrap/pk11akey.c @@ -221,7 +221,6 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, PORT_SetError(SEC_ERROR_BAD_KEY); return CK_INVALID_HANDLE; } - templateCount = attrs - theTemplate; PORT_Assert(templateCount <= (sizeof(theTemplate) / sizeof(CK_ATTRIBUTE))); if (pubKey->keyType != ecKey) { @@ -1683,6 +1682,95 @@ PK11_MakeKEAPubKey(unsigned char *keyData, int length) return pubk; } +SECStatus +SECKEY_SetPublicValue(SECKEYPrivateKey *privKey, SECItem *publicValue) +{ + SECStatus rv; + SECKEYPublicKey pubKey; + PLArenaPool *arena; + PK11SlotInfo *slot; + CK_OBJECT_HANDLE privKeyID; + + if (privKey == NULL || publicValue == NULL || + publicValue->data == NULL || publicValue->len == 0) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + pubKey.arena = NULL; + pubKey.keyType = privKey->keyType; + pubKey.pkcs11Slot = NULL; + pubKey.pkcs11ID = CK_INVALID_HANDLE; + /* can't use PORT_InitCheapArena here becase SECKEY_DestroyPublic is used + * to free it, and it uses PORT_FreeArena which not only frees the + * underlying arena, it also frees the allocated arena struct. */ + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + pubKey.arena = arena; + if (arena == NULL) { + return SECFailure; + } + + slot = privKey->pkcs11Slot; + privKeyID = privKey->pkcs11ID; + rv = SECFailure; + switch (privKey->keyType) { + default: + /* error code already set to SECFailure */ + break; + case rsaKey: + pubKey.u.rsa.modulus = *publicValue; + rv = PK11_ReadAttribute(slot, privKeyID, CKA_PUBLIC_EXPONENT, + arena, &pubKey.u.rsa.publicExponent); + break; + case dsaKey: + pubKey.u.dsa.publicValue = *publicValue; + rv = PK11_ReadAttribute(slot, privKeyID, CKA_PRIME, + arena, &pubKey.u.dsa.params.prime); + if (rv != SECSuccess) { + break; + } + rv = PK11_ReadAttribute(slot, privKeyID, CKA_SUBPRIME, + arena, &pubKey.u.dsa.params.subPrime); + if (rv != SECSuccess) { + break; + } + rv = PK11_ReadAttribute(slot, privKeyID, CKA_BASE, + arena, &pubKey.u.dsa.params.base); + break; + case dhKey: + pubKey.u.dh.publicValue = *publicValue; + rv = PK11_ReadAttribute(slot, privKeyID, CKA_PRIME, + arena, &pubKey.u.dh.prime); + if (rv != SECSuccess) { + break; + } + rv = PK11_ReadAttribute(slot, privKeyID, CKA_BASE, + arena, &pubKey.u.dh.base); + break; + case ecKey: + pubKey.u.ec.publicValue = *publicValue; + pubKey.u.ec.encoding = ECPoint_Undefined; + pubKey.u.ec.size = 0; + rv = PK11_ReadAttribute(slot, privKeyID, CKA_EC_PARAMS, + arena, &pubKey.u.ec.DEREncodedParams); + break; + } + if (rv == SECSuccess) { + rv = PK11_ImportPublicKey(slot, &pubKey, PR_TRUE); + } + /* Even though pubKey is stored on the stack, we've allocated + * some of it's data from the arena. SECKEY_DestroyPublicKey + * destroys keys by freeing the arena, so this will clean up all + * the data we allocated specifically for the key above. It will + * also free any slot references which we may have picked up in + * PK11_ImportPublicKey. It won't delete the underlying key if + * its a Token/Permanent key (which it will be if + * PK11_ImportPublicKey succeeds). */ + SECKEY_DestroyPublicKey(&pubKey); + + return rv; +} + /* * NOTE: This function doesn't return a SECKEYPrivateKey struct to represent * the new private key object. If it were to create a session object that @@ -1808,12 +1896,6 @@ try_faulty_3des: nickname, publicValue, isPerm, isPrivate, key_type, usage, usageCount, wincx); if (privKey) { - if (privk) { - *privk = privKey; - } else { - SECKEY_DestroyPrivateKey(privKey); - } - privKey = NULL; rv = SECSuccess; goto done; } @@ -1843,6 +1925,25 @@ try_faulty_3des: rv = SECFailure; done: + if ((rv == SECSuccess) && isPerm) { + /* If we are importing a token object, + * create the corresponding public key. + * If this fails, just continue as the target + * token simply might not support persistant + * public keys. Such tokens are usable, but + * need to be authenticated before searching + * for user certs. */ + (void)SECKEY_SetPublicValue(privKey, publicValue); + } + + if (privKey) { + if (privk) { + *privk = privKey; + } else { + SECKEY_DestroyPrivateKey(privKey); + } + privKey = NULL; + } if (crypto_param != NULL) { SECITEM_ZfreeItem(crypto_param, PR_TRUE); } diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index a880b1ab8..655c5f970 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -245,7 +245,7 @@ pk11_fastCert(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, /* Get the cryptoki object from the handle */ token = PK11Slot_GetNSSToken(slot); - if (token->defaultSession) { + if (token && token->defaultSession) { co = nssCryptokiObject_Create(token, token->defaultSession, certID); } else { PORT_SetError(SEC_ERROR_NO_TOKEN); @@ -307,9 +307,15 @@ PK11_MakeCertFromHandle(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, CERTCertificate *cert = NULL; CERTCertTrust *trust; + if (slot == NULL || certID == CK_INVALID_HANDLE) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } + cert = pk11_fastCert(slot, certID, privateLabel, &nickname); - if (cert == NULL) + if (cert == NULL) { goto loser; + } if (nickname) { if (cert->nickname != NULL) { @@ -406,6 +412,93 @@ PK11_GetCertFromPrivateKey(SECKEYPrivateKey *privKey) return (cert); } +CK_OBJECT_HANDLE * +PK11_FindCertHandlesForKeyHandle(PK11SlotInfo *slot, CK_OBJECT_HANDLE keyHandle, + int *certHandleCountOut) +{ + if (!slot || !certHandleCountOut || keyHandle == CK_INVALID_HANDLE) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } + + PORTCheapArenaPool arena; + PORT_InitCheapArena(&arena, DER_DEFAULT_CHUNKSIZE); + CK_ATTRIBUTE idTemplate[] = { + { CKA_ID, NULL, 0 }, + }; + const int idAttrCount = sizeof(idTemplate) / sizeof(idTemplate[0]); + CK_RV crv = PK11_GetAttributes(&arena.arena, slot, keyHandle, idTemplate, idAttrCount); + if (crv != CKR_OK) { + PORT_DestroyCheapArena(&arena); + PORT_SetError(PK11_MapError(crv)); + return NULL; + } + + if ((idTemplate[0].ulValueLen == 0) || (idTemplate[0].ulValueLen == -1)) { + PORT_DestroyCheapArena(&arena); + PORT_SetError(SEC_ERROR_BAD_KEY); + return NULL; + } + + CK_OBJECT_CLASS searchClass = CKO_CERTIFICATE; + CK_ATTRIBUTE searchTemplate[] = { + idTemplate[0], + { CKA_CLASS, &searchClass, sizeof(searchClass) } + }; + const int searchAttrCount = sizeof(searchTemplate) / sizeof(searchTemplate[0]); + CK_OBJECT_HANDLE *ids = pk11_FindObjectsByTemplate(slot, searchTemplate, searchAttrCount, certHandleCountOut); + + PORT_DestroyCheapArena(&arena); + return ids; +} + +CERTCertList * +PK11_GetCertsMatchingPrivateKey(SECKEYPrivateKey *privKey) +{ + if (!privKey) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } + CERTCertList *certs = CERT_NewCertList(); + if (!certs) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return NULL; + } + PK11SlotInfo *slot = privKey->pkcs11Slot; + CK_OBJECT_HANDLE handle = privKey->pkcs11ID; + CK_OBJECT_HANDLE certID = PK11_MatchItem(slot, handle, CKO_CERTIFICATE); + /* If we can't get a matching certID, there are no matching certificates, + * which is not an error. */ + if (certID == CK_INVALID_HANDLE) { + return certs; + } + int certHandleCount = 0; + CK_OBJECT_HANDLE *certHandles = PK11_FindCertHandlesForKeyHandle(slot, handle, &certHandleCount); + if (!certHandles) { + /* If certHandleCount is 0, there are no matching certificates, which is + * not an error. */ + if (certHandleCount == 0) { + return certs; + } + CERT_DestroyCertList(certs); + return NULL; + } + int i; + for (i = 0; i < certHandleCount; i++) { + CERTCertificate *cert = PK11_MakeCertFromHandle(slot, certHandles[i], NULL); + /* If PK11_MakeCertFromHandle fails for one handle, optimistically + assume other handles may succeed (i.e. this is best-effort). */ + if (!cert) { + continue; + } + if (CERT_AddCertToListTail(certs, cert) != SECSuccess) { + CERT_DestroyCertificate(cert); + } + } + PORT_Free(certHandles); + return certs; +} + /* * delete a cert and it's private key (if no other certs are pointing to the * private key. diff --git a/security/nss/lib/pk11wrap/pk11cxt.c b/security/nss/lib/pk11wrap/pk11cxt.c index e9726d03c..61faeaafc 100644 --- a/security/nss/lib/pk11wrap/pk11cxt.c +++ b/security/nss/lib/pk11wrap/pk11cxt.c @@ -1008,12 +1008,12 @@ PK11_DigestFinal(PK11Context *context, unsigned char *data, } PK11_ExitContextMonitor(context); - *outLen = (unsigned int)len; context->init = PR_FALSE; /* allow Begin to start up again */ if (crv != CKR_OK) { PORT_SetError(PK11_MapError(crv)); return SECFailure; } + *outLen = (unsigned int)len; return SECSuccess; } diff --git a/security/nss/lib/pk11wrap/pk11load.c b/security/nss/lib/pk11wrap/pk11load.c index d1f6ec442..a84070103 100644 --- a/security/nss/lib/pk11wrap/pk11load.c +++ b/security/nss/lib/pk11wrap/pk11load.c @@ -353,7 +353,7 @@ SECMOD_SetRootCerts(PK11SlotInfo *slot, SECMODModule *mod) } } -#ifndef NSS_TEST_BUILD +#ifndef NSS_STATIC_SOFTOKEN static const char *my_shlib_name = SHLIB_PREFIX "nss" SHLIB_VERSION "." SHLIB_SUFFIX; static const char *softoken_shlib_name = @@ -403,7 +403,7 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) /* internal modules get loaded from their internal list */ if (mod->internal && (mod->dllName == NULL)) { -#ifdef NSS_TEST_BUILD +#ifdef NSS_STATIC_SOFTOKEN entry = (CK_C_GetFunctionList)NSC_GetFunctionList; #else /* @@ -430,7 +430,7 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) if (mod->isModuleDB) { mod->moduleDBFunc = (CK_C_GetFunctionList) -#ifdef NSS_TEST_BUILD +#ifdef NSS_STATIC_SOFTOKEN NSC_ModuleDBFunc; #else PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc"); @@ -488,12 +488,10 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) goto fail; #ifdef DEBUG_MODULE - if (PR_TRUE) { - modToDBG = PR_GetEnvSecure("NSS_DEBUG_PKCS11_MODULE"); - if (modToDBG && strcmp(mod->commonName, modToDBG) == 0) { - mod->functionList = (void *)nss_InsertDeviceLog( - (CK_FUNCTION_LIST_PTR)mod->functionList); - } + modToDBG = PR_GetEnvSecure("NSS_DEBUG_PKCS11_MODULE"); + if (modToDBG && strcmp(mod->commonName, modToDBG) == 0) { + mod->functionList = (void *)nss_InsertDeviceLog( + (CK_FUNCTION_LIST_PTR)mod->functionList); } #endif @@ -612,7 +610,7 @@ SECMOD_UnloadModule(SECMODModule *mod) * if not, we should change this to SECFailure and move it above the * mod->loaded = PR_FALSE; */ if (mod->internal && (mod->dllName == NULL)) { -#ifndef NSS_TEST_BUILD +#ifndef NSS_STATIC_SOFTOKEN if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) { if (softokenLib) { disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD"); diff --git a/security/nss/lib/pk11wrap/pk11mech.c b/security/nss/lib/pk11wrap/pk11mech.c index 48e50dff4..cfbe45b22 100644 --- a/security/nss/lib/pk11wrap/pk11mech.c +++ b/security/nss/lib/pk11wrap/pk11mech.c @@ -226,6 +226,7 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type, unsigned long len) return CKK_CAMELLIA; case CKM_NSS_CHACHA20_POLY1305: case CKM_NSS_CHACHA20_KEY_GEN: + case CKM_NSS_CHACHA20_CTR: return CKK_NSS_CHACHA20; case CKM_AES_ECB: case CKM_AES_CBC: @@ -235,10 +236,14 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type, unsigned long len) case CKM_AES_GCM: case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: + case CKM_AES_CMAC: + case CKM_AES_CMAC_GENERAL: case CKM_AES_CBC_PAD: case CKM_AES_KEY_GEN: case CKM_NETSCAPE_AES_KEY_WRAP: case CKM_NETSCAPE_AES_KEY_WRAP_PAD: + case CKM_AES_XCBC_MAC: + case CKM_AES_XCBC_MAC_96: return CKK_AES; case CKM_DES_ECB: case CKM_DES_CBC: @@ -440,6 +445,7 @@ PK11_GetKeyGenWithSize(CK_MECHANISM_TYPE type, int size) case CKM_CAMELLIA_KEY_GEN: return CKM_CAMELLIA_KEY_GEN; case CKM_NSS_CHACHA20_POLY1305: + case CKM_NSS_CHACHA20_CTR: return CKM_NSS_CHACHA20_KEY_GEN; case CKM_AES_ECB: case CKM_AES_CBC: @@ -449,6 +455,8 @@ PK11_GetKeyGenWithSize(CK_MECHANISM_TYPE type, int size) case CKM_AES_GCM: case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: + case CKM_AES_CMAC: + case CKM_AES_CMAC_GENERAL: case CKM_AES_CBC_PAD: case CKM_AES_KEY_GEN: return CKM_AES_KEY_GEN; @@ -730,6 +738,9 @@ PK11_GetBlockSize(CK_MECHANISM_TYPE type, SECItem *params) case CKM_RSA_X_509: /*actually it's the modulus length of the key!*/ return -1; /* failure */ + case CKM_NSS_CHACHA20_POLY1305: + case CKM_NSS_CHACHA20_CTR: + return 64; default: return pk11_lookup(type)->blockSize; } @@ -784,12 +795,16 @@ PK11_GetIVLength(CK_MECHANISM_TYPE type) case CKM_CAST3_CBC_PAD: case CKM_CAST5_CBC_PAD: return 8; + case CKM_AES_GCM: + case CKM_NSS_CHACHA20_POLY1305: + return 12; case CKM_SEED_CBC: case CKM_SEED_CBC_PAD: case CKM_CAMELLIA_CBC: case CKM_CAMELLIA_CBC_PAD: case CKM_AES_CBC: case CKM_AES_CBC_PAD: + case CKM_NSS_CHACHA20_CTR: return 16; case CKM_SKIPJACK_CBC64: case CKM_SKIPJACK_ECB64: diff --git a/security/nss/lib/pk11wrap/pk11obj.c b/security/nss/lib/pk11wrap/pk11obj.c index 937ac654a..bc9e93454 100644 --- a/security/nss/lib/pk11wrap/pk11obj.c +++ b/security/nss/lib/pk11wrap/pk11obj.c @@ -4,6 +4,8 @@ /* * This file manages object type indepentent functions. */ +#include + #include "seccomon.h" #include "secmod.h" #include "secmodi.h" @@ -933,11 +935,11 @@ PK11_Decrypt(PK11SymKey *symKey, if (haslock) PK11_ExitSlotMonitor(slot); pk11_CloseSession(slot, session, owner); - *outLen = len; if (crv != CKR_OK) { PORT_SetError(PK11_MapError(crv)); return SECFailure; } + *outLen = len; return SECSuccess; } @@ -979,11 +981,11 @@ PK11_Encrypt(PK11SymKey *symKey, if (haslock) PK11_ExitSlotMonitor(slot); pk11_CloseSession(slot, session, owner); - *outLen = len; if (crv != CKR_OK) { PORT_SetError(PK11_MapError(crv)); return SECFailure; } + *outLen = len; return SECSuccess; } @@ -1665,10 +1667,10 @@ pk11_CreateGenericObjectHelper(PK11SlotInfo *slot, /* This is the classic interface. Applications would call this function to * create new object that would not be destroyed later. This lead to resource * leaks (and thus memory leaks in the PKCS #11 module). To solve this we have - * a new interface that automatically marks objects created on the fly to be - * destroyed later. + * a new interface that automatically marks objects created on the fly to be + * destroyed later. * The old interface is preserved because applications like Mozilla purposefully - * leak the reference to be found later with PK11_FindGenericObjects. New + * leak the reference to be found later with PK11_FindGenericObjects. New * applications should use the new interface PK11_CreateManagedGenericObject */ PK11GenericObject * PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate, @@ -1678,8 +1680,8 @@ PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate, PR_FALSE); } -/* Use this interface. It will automatically destroy any temporary objects - * (token = PR_FALSE) when the PK11GenericObject is freed. Permanent objects still +/* Use this interface. It will automatically destroy any temporary objects + * (token = PR_FALSE) when the PK11GenericObject is freed. Permanent objects still * need to be destroyed by hand with PK11_DestroyTokenObject. */ PK11GenericObject * @@ -1828,15 +1830,24 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, { CK_OBJECT_HANDLE *objID = NULL; CK_ULONG returned_count = 0; + PRBool owner = PR_TRUE; + CK_SESSION_HANDLE session; + PRBool haslock = PR_FALSE; CK_RV crv = CKR_SESSION_HANDLE_INVALID; - PK11_EnterSlotMonitor(slot); - if (slot->session != CK_INVALID_SESSION) { - crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session, + session = pk11_GetNewSession(slot, &owner); + haslock = (!owner || !(slot->isThreadSafe)); + if (haslock) { + PK11_EnterSlotMonitor(slot); + } + if (session != CK_INVALID_SESSION) { + crv = PK11_GETTAB(slot)->C_FindObjectsInit(session, findTemplate, templCount); } if (crv != CKR_OK) { - PK11_ExitSlotMonitor(slot); + if (haslock) + PK11_ExitSlotMonitor(slot); + pk11_CloseSession(slot, session, owner); PORT_SetError(PK11_MapError(crv)); *object_count = -1; return NULL; @@ -1861,7 +1872,7 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, PORT_Free(oldObjID); break; } - crv = PK11_GETTAB(slot)->C_FindObjects(slot->session, + crv = PK11_GETTAB(slot)->C_FindObjects(session, &objID[*object_count], PK11_SEARCH_CHUNKSIZE, &returned_count); if (crv != CKR_OK) { PORT_SetError(PK11_MapError(crv)); @@ -1872,8 +1883,11 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, *object_count += returned_count; } while (returned_count == PK11_SEARCH_CHUNKSIZE); - PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session); - PK11_ExitSlotMonitor(slot); + PK11_GETTAB(slot)->C_FindObjectsFinal(session); + if (haslock) { + PK11_ExitSlotMonitor(slot); + } + pk11_CloseSession(slot, session, owner); if (objID && (*object_count == 0)) { PORT_Free(objID); @@ -1883,6 +1897,96 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, *object_count = -1; return objID; } + +SECStatus +PK11_FindRawCertsWithSubject(PK11SlotInfo *slot, SECItem *derSubject, + CERTCertificateList **results) +{ + if (!slot || !derSubject || !results) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + *results = NULL; + + // derSubject->data may be null. If so, derSubject->len must be 0. + if (!derSubject->data && derSubject->len != 0) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + CK_CERTIFICATE_TYPE ckc_x_509 = CKC_X_509; + CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE; + CK_ATTRIBUTE subjectTemplate[] = { + { CKA_CERTIFICATE_TYPE, &ckc_x_509, sizeof(ckc_x_509) }, + { CKA_CLASS, &cko_certificate, sizeof(cko_certificate) }, + { CKA_SUBJECT, derSubject->data, derSubject->len }, + }; + int templateCount = sizeof(subjectTemplate) / sizeof(subjectTemplate[0]); + int handleCount = 0; + CK_OBJECT_HANDLE *handles = + pk11_FindObjectsByTemplate(slot, subjectTemplate, templateCount, + &handleCount); + if (!handles) { + // pk11_FindObjectsByTemplate indicates there was an error by setting + // handleCount to -1 (and it has set an error with PORT_SetError). + if (handleCount == -1) { + return SECFailure; + } + return SECSuccess; + } + PORT_Assert(handleCount > 0); + if (handleCount <= 0) { + PORT_Free(handles); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + if (handleCount > INT_MAX / sizeof(SECItem)) { + PORT_Free(handles); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) { + PORT_Free(handles); + return SECFailure; + } + CERTCertificateList *rawCertificates = + PORT_ArenaNew(arena, CERTCertificateList); + if (!rawCertificates) { + PORT_Free(handles); + PORT_FreeArena(arena, PR_FALSE); + return SECFailure; + } + rawCertificates->arena = arena; + rawCertificates->certs = PORT_ArenaNewArray(arena, SECItem, handleCount); + if (!rawCertificates->certs) { + PORT_Free(handles); + PORT_FreeArena(arena, PR_FALSE); + return SECFailure; + } + rawCertificates->len = handleCount; + int handleIndex; + for (handleIndex = 0; handleIndex < handleCount; handleIndex++) { + SECStatus rv = + PK11_ReadAttribute(slot, handles[handleIndex], CKA_VALUE, arena, + &rawCertificates->certs[handleIndex]); + if (rv != SECSuccess) { + PORT_Free(handles); + PORT_FreeArena(arena, PR_FALSE); + return SECFailure; + } + if (!rawCertificates->certs[handleIndex].data) { + PORT_Free(handles); + PORT_FreeArena(arena, PR_FALSE); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + } + PORT_Free(handles); + *results = rawCertificates; + return SECSuccess; +} + /* * given a PKCS #11 object, match it's peer based on the KeyID. searchID * is typically a privateKey or a certificate while the peer is the opposite diff --git a/security/nss/lib/pk11wrap/pk11pars.c b/security/nss/lib/pk11wrap/pk11pars.c index db60f7c9d..c5e21df51 100644 --- a/security/nss/lib/pk11wrap/pk11pars.c +++ b/security/nss/lib/pk11wrap/pk11pars.c @@ -238,6 +238,8 @@ static const oidValDef curveOptList[] = { NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, { CIPHER_NAME("SECP521R1"), SEC_OID_SECG_EC_SECP521R1, NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, + { CIPHER_NAME("CURVE25519"), SEC_OID_CURVE25519, + NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, /* ANSI X9.62 named elliptic curves (characteristic two field) */ { CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1, NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, @@ -384,18 +386,26 @@ static const oidValDef kxOptList[] = { { CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX }, }; +static const oidValDef signOptList[] = { + /* Signatures */ + { CIPHER_NAME("DSA"), SEC_OID_ANSIX9_DSA_SIGNATURE, + NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, +}; + typedef struct { const oidValDef *list; PRUint32 entries; const char *description; + PRBool allowEmpty; } algListsDef; static const algListsDef algOptLists[] = { - { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC" }, - { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH" }, - { macOptList, PR_ARRAY_SIZE(macOptList), "MAC" }, - { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER" }, - { kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX" }, + { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC", PR_FALSE }, + { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH", PR_FALSE }, + { macOptList, PR_ARRAY_SIZE(macOptList), "MAC", PR_FALSE }, + { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER", PR_FALSE }, + { kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX", PR_FALSE }, + { signOptList, PR_ARRAY_SIZE(signOptList), "OTHER-SIGN", PR_TRUE }, }; static const optionFreeDef sslOptList[] = { @@ -718,7 +728,7 @@ secmod_sanityCheckCryptoPolicy(void) for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { const algListsDef *algOptList = &algOptLists[i]; fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s: %u\n", enabledCount[i] ? sInfo : sWarn, algOptList->description, enabledCount[i]); - if (!enabledCount[i]) { + if (!enabledCount[i] && !algOptList->allowEmpty) { haveWarning = PR_TRUE; } } @@ -807,6 +817,10 @@ SECMOD_CreateModuleEx(const char *library, const char *moduleName, mod->internal = NSSUTIL_ArgHasFlag("flags", "internal", nssc); mod->isFIPS = NSSUTIL_ArgHasFlag("flags", "FIPS", nssc); + /* if the system FIPS mode is enabled, force FIPS to be on */ + if (secmod_GetSystemFIPSEnabled()) { + mod->isFIPS = PR_TRUE; + } mod->isCritical = NSSUTIL_ArgHasFlag("flags", "critical", nssc); slotParams = NSSUTIL_ArgGetParamValue("slotParams", nssc); mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena, slotParams, diff --git a/security/nss/lib/pk11wrap/pk11pbe.c b/security/nss/lib/pk11wrap/pk11pbe.c index 4b6645578..1e2fabd24 100644 --- a/security/nss/lib/pk11wrap/pk11pbe.c +++ b/security/nss/lib/pk11wrap/pk11pbe.c @@ -654,17 +654,17 @@ sec_pkcs5CreateAlgorithmID(SECOidTag algorithm, pbeAlgorithm = SEC_OID_PKCS5_PBKDF2; /* * 'algorithm' is the overall algorithm oid tag used to wrap the - * entire algoithm ID block. For PKCS5v1 and PKCS12, this + * entire algorithm ID block. For PKCS5v1 and PKCS12, this * algorithm OID has encoded in it both the PBE KDF function * and the encryption algorithm. For PKCS 5v2, PBE KDF and * encryption/macing oids are encoded as parameters in * the algorithm ID block. * * Thus in PKCS5 v1 and PKCS12, this algorithm maps to a pkcs #11 - * mechanism, where as in PKCS 5v2, this alogithm tag does not map + * mechanism, where as in PKCS 5v2, this algorithm tag does not map * directly to a PKCS #11 mechanim, instead the 2 oids in the * algorithm ID block map the the actual PKCS #11 mechanism. - * gorithm is). We use choose this algorithm oid based on the + * algorithm is). We use choose this algorithm oid based on the * cipherAlgorithm to determine what this should be (MAC1 or PBES2). */ if (algorithm == SEC_OID_PKCS5_PBKDF2) { diff --git a/security/nss/lib/pk11wrap/pk11pk12.c b/security/nss/lib/pk11wrap/pk11pk12.c index 9888ace69..360c03bd4 100644 --- a/security/nss/lib/pk11wrap/pk11pk12.c +++ b/security/nss/lib/pk11wrap/pk11pk12.c @@ -499,6 +499,10 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, PK11_SETATTRS(attrs, CKA_DERIVE, (keyUsage & KU_KEY_AGREEMENT) ? &cktrue : &ckfalse, sizeof(CK_BBOOL)); attrs++; + if (nickname) { + PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); + attrs++; + } ck_id = PK11_MakeIDFromPubKey(&lpk->u.ec.publicValue); if (ck_id == NULL) { goto loser; diff --git a/security/nss/lib/pk11wrap/pk11priv.h b/security/nss/lib/pk11wrap/pk11priv.h index 8848c81ec..13fc74c3a 100644 --- a/security/nss/lib/pk11wrap/pk11priv.h +++ b/security/nss/lib/pk11wrap/pk11priv.h @@ -111,6 +111,7 @@ CK_OBJECT_HANDLE PK11_FindObjectForCert(CERTCertificate *cert, PK11SymKey *pk11_CopyToSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey); unsigned int pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType); +CK_OBJECT_HANDLE PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey); /********************************************************************** * Certs diff --git a/security/nss/lib/pk11wrap/pk11pub.h b/security/nss/lib/pk11wrap/pk11pub.h index 8db969e4c..30e4cbd89 100644 --- a/security/nss/lib/pk11wrap/pk11pub.h +++ b/security/nss/lib/pk11wrap/pk11pub.h @@ -275,12 +275,9 @@ PK11SymKey *PK11_ImportSymKeyWithFlags(PK11SlotInfo *slot, PK11SymKey *PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, CK_MECHANISM_TYPE type, CK_OBJECT_HANDLE keyID, PRBool owner, void *wincx); +/* PK11_GetWrapKey and PK11_SetWrapKey are not thread safe. */ PK11SymKey *PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type, int series, void *wincx); -/* - * This function is not thread-safe. It can only be called when only - * one thread has a reference to wrapKey. - */ void PK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey); CK_MECHANISM_TYPE PK11_GetMechanism(PK11SymKey *symKey); /* @@ -875,6 +872,25 @@ SECStatus PK11_WriteRawAttribute(PK11ObjectType type, void *object, PK11SlotList * PK11_GetAllSlotsForCert(CERTCertificate *cert, void *arg); +/* + * Finds all certificates on the given slot with the given subject distinguished + * name and returns them as DER bytes. If no such certificates can be found, + * returns SECSuccess and sets *results to NULL. If a failure is encountered + * while fetching any of the matching certificates, SECFailure is returned and + * *results will be NULL. + */ +SECStatus +PK11_FindRawCertsWithSubject(PK11SlotInfo *slot, SECItem *derSubject, + CERTCertificateList **results); + +/* + * Finds and returns all certificates with a public key that matches the given + * private key. May return an empty list if no certificates match. Returns NULL + * if a failure is encountered. + */ +CERTCertList * +PK11_GetCertsMatchingPrivateKey(SECKEYPrivateKey *privKey); + /********************************************************************** * New functions which are already deprecated.... **********************************************************************/ diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index cf2a40a2f..ad4166017 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -357,7 +357,9 @@ PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, } /* - * turn key handle into an appropriate key object + * Restore a symmetric wrapping key that was saved using PK11_SetWrapKey. + * + * This function is provided for ABI compatibility; see PK11_SetWrapKey below. */ PK11SymKey * PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type, @@ -365,33 +367,51 @@ PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type, { PK11SymKey *symKey = NULL; - if (slot->series != series) - return NULL; - if (slot->refKeys[wrap] == CK_INVALID_HANDLE) + PK11_EnterSlotMonitor(slot); + if (slot->series != series || + slot->refKeys[wrap] == CK_INVALID_HANDLE) { + PK11_ExitSlotMonitor(slot); return NULL; - if (type == CKM_INVALID_MECHANISM) + } + + if (type == CKM_INVALID_MECHANISM) { type = slot->wrapMechanism; + } symKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, slot->wrapMechanism, slot->refKeys[wrap], PR_FALSE, wincx); + PK11_ExitSlotMonitor(slot); return symKey; } /* - * This function is not thread-safe because it sets wrapKey->sessionOwner - * without using a lock or atomic routine. It can only be called when - * only one thread has a reference to wrapKey. + * This function sets an attribute on the current slot with a wrapping key. The + * data saved is ephemeral; it needs to be run every time the program is + * invoked. + * + * Since NSS 3.45, this function is marginally more thread safe. It uses the + * slot lock (if present) and fails silently if a value is already set. Use + * PK11_GetWrapKey() after calling this function to get the current wrapping key + * in case there was an update on another thread. + * + * Either way, using this function is inadvisable. It's provided for ABI + * compatibility only. */ void PK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey) { - /* save the handle and mechanism for the wrapping key */ - /* mark the key and session as not owned by us to they don't get freed - * when the key goes way... that lets us reuse the key later */ - slot->refKeys[wrap] = wrapKey->objectID; - wrapKey->owner = PR_FALSE; - wrapKey->sessionOwner = PR_FALSE; - slot->wrapMechanism = wrapKey->type; + PK11_EnterSlotMonitor(slot); + if (wrap < PR_ARRAY_SIZE(slot->refKeys) && + slot->refKeys[wrap] == CK_INVALID_HANDLE) { + /* save the handle and mechanism for the wrapping key */ + /* mark the key and session as not owned by us so they don't get freed + * when the key goes way... that lets us reuse the key later */ + slot->refKeys[wrap] = wrapKey->objectID; + wrapKey->owner = PR_FALSE; + wrapKey->sessionOwner = PR_FALSE; + slot->wrapMechanism = wrapKey->type; + } + PK11_ExitSlotMonitor(slot); } /* @@ -610,7 +630,7 @@ PK11_GetWindow(PK11SymKey *key) } /* - * extract a symetric key value. NOTE: if the key is sensitive, we will + * extract a symmetric key value. NOTE: if the key is sensitive, we will * not be able to do this operation. This function is used to move * keys from one token to another */ SECStatus @@ -618,6 +638,11 @@ PK11_ExtractKeyValue(PK11SymKey *symKey) { SECStatus rv; + if (symKey == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (symKey->data.data != NULL) { if (symKey->size == 0) { symKey->size = symKey->data.len; @@ -1598,6 +1623,7 @@ PK11_DeriveWithTemplate(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, PK11_FreeSymKey(newBaseKey); if (crv != CKR_OK) { PK11_FreeSymKey(symKey); + PORT_SetError(PK11_MapError(crv)); return NULL; } return symKey; @@ -1839,6 +1865,35 @@ loser: return NULL; } +/* + * This regenerate a public key from a private key. This function is currently + * NSS private. If we want to make it public, we need to add and optional + * template or at least flags (a.la. PK11_DeriveWithFlags). + */ +CK_OBJECT_HANDLE +PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey) +{ + PK11SlotInfo *slot = privKey->pkcs11Slot; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE objectID = CK_INVALID_HANDLE; + CK_RV crv; + + mechanism.mechanism = CKM_NSS_PUB_FROM_PRIV; + mechanism.pParameter = NULL; + mechanism.ulParameterLen = 0; + + PK11_EnterSlotMonitor(slot); + crv = PK11_GETTAB(slot)->C_DeriveKey(slot->session, &mechanism, + privKey->pkcs11ID, NULL, 0, + &objectID); + PK11_ExitSlotMonitor(slot); + if (crv != CKR_OK) { + PORT_SetError(PK11_MapError(crv)); + return CK_INVALID_HANDLE; + } + return objectID; +} + /* * This Generates a wrapping key based on a privateKey, publicKey, and two * random numbers. For Mail usage RandomB should be NULL. In the Sender's diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c index ebe54d495..c44ed9b49 100644 --- a/security/nss/lib/pk11wrap/pk11slot.c +++ b/security/nss/lib/pk11wrap/pk11slot.c @@ -419,6 +419,8 @@ PK11_NewSlotInfo(SECMODModule *mod) slot->hasRootCerts = PR_FALSE; slot->hasRootTrust = PR_FALSE; slot->nssToken = NULL; + slot->profileList = NULL; + slot->profileCount = 0; return slot; } @@ -446,6 +448,9 @@ PK11_DestroySlot(PK11SlotInfo *slot) if (slot->mechanismList) { PORT_Free(slot->mechanismList); } + if (slot->profileList) { + PORT_Free(slot->profileList); + } if (slot->isThreadSafe && slot->sessionLock) { PZ_DestroyLock(slot->sessionLock); } @@ -1170,6 +1175,76 @@ PK11_ReadMechanismList(PK11SlotInfo *slot) return SECSuccess; } +static SECStatus +pk11_ReadProfileList(PK11SlotInfo *slot) +{ + CK_ATTRIBUTE findTemp[2]; + CK_ATTRIBUTE *attrs; + CK_BBOOL cktrue = CK_TRUE; + CK_OBJECT_CLASS oclass = CKO_PROFILE; + int tsize; + int objCount; + CK_OBJECT_HANDLE *handles = NULL; + int i; + + attrs = findTemp; + PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); + attrs++; + PK11_SETATTRS(attrs, CKA_CLASS, &oclass, sizeof(oclass)); + attrs++; + tsize = attrs - findTemp; + PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE)); + + if (slot->profileList) { + PORT_Free(slot->profileList); + slot->profileList = NULL; + } + slot->profileCount = 0; + + objCount = 0; + handles = pk11_FindObjectsByTemplate(slot, findTemp, tsize, &objCount); + if (handles == NULL) { + if (objCount < 0) { + return SECFailure; /* error code is set */ + } + PORT_Assert(objCount == 0); + return SECSuccess; + } + + slot->profileList = (CK_PROFILE_ID *) + PORT_Alloc(objCount * sizeof(CK_PROFILE_ID)); + if (slot->profileList == NULL) { + PORT_Free(handles); + return SECFailure; /* error code is set */ + } + + for (i = 0; i < objCount; i++) { + CK_ULONG value; + + value = PK11_ReadULongAttribute(slot, handles[i], CKA_PROFILE_ID); + if (value == CK_UNAVAILABLE_INFORMATION) { + continue; + } + slot->profileList[slot->profileCount++] = value; + } + + PORT_Free(handles); + return SECSuccess; +} + +static PRBool +pk11_HasProfile(PK11SlotInfo *slot, CK_PROFILE_ID id) +{ + int i; + + for (i = 0; i < slot->profileCount; i++) { + if (slot->profileList[i] == id) { + return PR_TRUE; + } + } + return PR_FALSE; +} + /* * initialize a new token * unlike initialize slot, this can be called multiple times in the lifetime @@ -1291,6 +1366,11 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) if (status != PR_SUCCESS) return SECFailure; + rv = pk11_ReadProfileList(slot); + if (rv != SECSuccess) { + return SECFailure; + } + if (!(slot->isInternal) && (slot->hasRandom)) { /* if this slot has a random number generater, use it to add entropy * to the internal slot. */ @@ -1439,6 +1519,11 @@ PK11_InitSlot(SECMODModule *mod, CK_SLOT_ID slotID, PK11SlotInfo *slot) slot->slotID = slotID; slot->isThreadSafe = mod->isThreadSafe; slot->hasRSAInfo = PR_FALSE; + slot->module = mod; /* NOTE: we don't make a reference here because + * modules have references to their slots. This + * works because modules keep implicit references + * from their slots, and won't unload and disappear + * until all their slots have been freed */ if (PK11_GETTAB(slot)->C_GetSlotInfo(slotID, &slotInfo) != CKR_OK) { slot->disabled = PR_TRUE; @@ -1448,11 +1533,6 @@ PK11_InitSlot(SECMODModule *mod, CK_SLOT_ID slotID, PK11SlotInfo *slot) /* test to make sure claimed mechanism work */ slot->needTest = mod->internal ? PR_FALSE : PR_TRUE; - slot->module = mod; /* NOTE: we don't make a reference here because - * modules have references to their slots. This - * works because modules keep implicit references - * from their slots, and won't unload and disappear - * until all their slots have been freed */ (void)PK11_MakeString(NULL, slot->slot_name, (char *)slotInfo.slotDescription, sizeof(slotInfo.slotDescription)); slot->isHW = (PRBool)((slotInfo.flags & CKF_HW_SLOT) == CKF_HW_SLOT); @@ -1695,6 +1775,7 @@ PK11_IsFriendly(PK11SlotInfo *slot) { /* internal slot always has public readable certs */ return (PRBool)(slot->isInternal || + pk11_HasProfile(slot, CKP_PUBLIC_CERTIFICATES_TOKEN) || ((slot->defaultFlags & SECMOD_FRIENDLY_FLAG) == SECMOD_FRIENDLY_FLAG)); } @@ -2096,10 +2177,6 @@ PK11_GetAllTokens(CK_MECHANISM_TYPE type, PRBool needRW, PRBool loadCerts, SECMODModuleList *modules; SECMODListLock *moduleLock; int i; -#if defined(XP_WIN32) - int j = 0; - PRInt32 waste[16]; -#endif moduleLock = SECMOD_GetDefaultModuleListLock(); if (!moduleLock) { @@ -2124,18 +2201,6 @@ PK11_GetAllTokens(CK_MECHANISM_TYPE type, PRBool needRW, PRBool loadCerts, modules = SECMOD_GetDefaultModuleList(); for (mlp = modules; mlp != NULL; mlp = mlp->next) { - -#if defined(XP_WIN32) - /* This is works around some horrible cache/page thrashing problems - ** on Win32. Without this, this loop can take up to 6 seconds at - ** 100% CPU on a Pentium-Pro 200. The thing this changes is to - ** increase the size of the stack frame and modify it. - ** Moving the loop code itself seems to have no effect. - ** Dunno why this combination makes a difference, but it does. - */ - waste[j & 0xf] = j++; -#endif - for (i = 0; i < mlp->module->slotCount; i++) { PK11SlotInfo *slot = mlp->module->slots[i]; diff --git a/security/nss/lib/pk11wrap/pk11util.c b/security/nss/lib/pk11wrap/pk11util.c index e316f1f1a..502c4d00c 100644 --- a/security/nss/lib/pk11wrap/pk11util.c +++ b/security/nss/lib/pk11wrap/pk11util.c @@ -95,6 +95,31 @@ SECMOD_Shutdown() return SECSuccess; } +int +secmod_GetSystemFIPSEnabled(void) +{ +#ifdef LINUX + FILE *f; + char d; + size_t size; + + f = fopen("/proc/sys/crypto/fips_enabled", "r"); + if (!f) { + return 0; + } + + size = fread(&d, 1, sizeof(d), f); + fclose(f); + if (size != sizeof(d)) { + return 0; + } + if (d == '1') { + return 1; + } +#endif + return 0; +} + /* * retrieve the internal module */ @@ -428,7 +453,7 @@ SECMOD_DeleteInternalModule(const char *name) SECMODModuleList **mlpp; SECStatus rv = SECFailure; - if (pendingModule) { + if (secmod_GetSystemFIPSEnabled() || pendingModule) { PORT_SetError(SEC_ERROR_MODULE_STUCK); return rv; } @@ -963,7 +988,7 @@ SECMOD_CanDeleteInternalModule(void) #ifdef NSS_FIPS_DISABLED return PR_FALSE; #else - return (PRBool)(pendingModule == NULL); + return (PRBool)((pendingModule == NULL) && !secmod_GetSystemFIPSEnabled()); #endif } diff --git a/security/nss/lib/pk11wrap/pk11wrap.gyp b/security/nss/lib/pk11wrap/pk11wrap.gyp index 35fdacef9..17de8add4 100644 --- a/security/nss/lib/pk11wrap/pk11wrap.gyp +++ b/security/nss/lib/pk11wrap/pk11wrap.gyp @@ -10,7 +10,7 @@ 'target_name': 'pk11wrap_static', 'type': 'static_library', 'defines': [ - 'NSS_TEST_BUILD', + 'NSS_STATIC_SOFTOKEN', ], 'dependencies': [ 'pk11wrap_base', diff --git a/security/nss/lib/pk11wrap/secmodi.h b/security/nss/lib/pk11wrap/secmodi.h index 7ec77ced6..634b241bd 100644 --- a/security/nss/lib/pk11wrap/secmodi.h +++ b/security/nss/lib/pk11wrap/secmodi.h @@ -115,6 +115,13 @@ PK11SymKey *pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE pk11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, SECItem *pwd, PRBool faulty3DES); +/* Get the state of the system FIPS mode */ +/* NSS uses this to force FIPS mode if the system bit is on. Applications which + * use the SECMOD_CanDeleteInteral() to check to see if they can switch to or + * from FIPS mode will automatically be told that they can't swith out of FIPS + * mode */ +int secmod_GetSystemFIPSEnabled(); + extern void pk11sdr_Init(void); extern void pk11sdr_Shutdown(void); diff --git a/security/nss/lib/pk11wrap/secmodti.h b/security/nss/lib/pk11wrap/secmodti.h index 260e6387d..4af20100d 100644 --- a/security/nss/lib/pk11wrap/secmodti.h +++ b/security/nss/lib/pk11wrap/secmodti.h @@ -111,6 +111,8 @@ struct PK11SlotInfoStr { CK_TOKEN_INFO tokenInfo; /* fast mechanism lookup */ char mechanismBits[256]; + CK_PROFILE_ID *profileList; + int profileCount; }; /* Symetric Key structure. Reference Counted */ -- cgit v1.2.3