summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/pk11wrap
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/pk11wrap')
-rw-r--r--security/nss/lib/pk11wrap/debug_module.c33
-rw-r--r--security/nss/lib/pk11wrap/pk11akey.c115
-rw-r--r--security/nss/lib/pk11wrap/pk11cert.c97
-rw-r--r--security/nss/lib/pk11wrap/pk11cxt.c2
-rw-r--r--security/nss/lib/pk11wrap/pk11load.c18
-rw-r--r--security/nss/lib/pk11wrap/pk11mech.c15
-rw-r--r--security/nss/lib/pk11wrap/pk11obj.c132
-rw-r--r--security/nss/lib/pk11wrap/pk11pars.c26
-rw-r--r--security/nss/lib/pk11wrap/pk11pbe.c6
-rw-r--r--security/nss/lib/pk11wrap/pk11pk12.c4
-rw-r--r--security/nss/lib/pk11wrap/pk11priv.h1
-rw-r--r--security/nss/lib/pk11wrap/pk11pub.h24
-rw-r--r--security/nss/lib/pk11wrap/pk11skey.c87
-rw-r--r--security/nss/lib/pk11wrap/pk11slot.c107
-rw-r--r--security/nss/lib/pk11wrap/pk11util.c29
-rw-r--r--security/nss/lib/pk11wrap/pk11wrap.gyp2
-rw-r--r--security/nss/lib/pk11wrap/secmodi.h7
-rw-r--r--security/nss/lib/pk11wrap/secmodti.h2
18 files changed, 620 insertions, 87 deletions
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);
@@ -203,6 +205,27 @@ get_obj_class(CK_OBJECT_CLASS objClass, char *str, int len)
}
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)
{
const char *a = NULL;
@@ -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 <limits.h>
+
#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;
@@ -1840,6 +1866,35 @@ loser:
}
/*
+ * 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
* case RandomA is generate, outherwize it is passed.
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 */