You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
825 lines
26 KiB
825 lines
26 KiB
diff --git a/cmd/manifest.mn b/cmd/manifest.mn |
|
--- a/cmd/manifest.mn |
|
+++ b/cmd/manifest.mn |
|
@@ -76,6 +76,7 @@ |
|
symkeyutil \ |
|
tests \ |
|
tstclnt \ |
|
+ validation \ |
|
vfychain \ |
|
vfyserv \ |
|
modutil \ |
|
diff --git a/cmd/validation/Makefile b/cmd/validation/Makefile |
|
new file mode 100644 |
|
--- /dev/null |
|
+++ b/cmd/validation/Makefile |
|
@@ -0,0 +1,48 @@ |
|
+#! gmake |
|
+# |
|
+# This Source Code Form is subject to the terms of the Mozilla Public |
|
+# License, v. 2.0. If a copy of the MPL was not distributed with this |
|
+# file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
+ |
|
+####################################################################### |
|
+# (1) Include initial platform-independent assignments (MANDATORY). # |
|
+####################################################################### |
|
+ |
|
+include manifest.mn |
|
+ |
|
+####################################################################### |
|
+# (2) Include "global" configuration information. (OPTIONAL) # |
|
+####################################################################### |
|
+ |
|
+include $(CORE_DEPTH)/coreconf/config.mk |
|
+ |
|
+####################################################################### |
|
+# (3) Include "component" configuration information. (OPTIONAL) # |
|
+####################################################################### |
|
+ |
|
+####################################################################### |
|
+# (4) Include "local" platform-dependent assignments (OPTIONAL). # |
|
+####################################################################### |
|
+ |
|
+include ../platlibs.mk |
|
+ |
|
+ |
|
+####################################################################### |
|
+# (5) Execute "global" rules. (OPTIONAL) # |
|
+####################################################################### |
|
+ |
|
+include $(CORE_DEPTH)/coreconf/rules.mk |
|
+ |
|
+####################################################################### |
|
+# (6) Execute "component" rules. (OPTIONAL) # |
|
+####################################################################### |
|
+ |
|
+ |
|
+ |
|
+####################################################################### |
|
+# (7) Execute "local" rules. (OPTIONAL). # |
|
+####################################################################### |
|
+ |
|
+ |
|
+include ../platrules.mk |
|
+ |
|
diff --git a/cmd/validation/manifest.mn b/cmd/validation/manifest.mn |
|
new file mode 100644 |
|
--- /dev/null |
|
+++ b/cmd/validation/manifest.mn |
|
@@ -0,0 +1,23 @@ |
|
+# |
|
+# This Source Code Form is subject to the terms of the Mozilla Public |
|
+# License, v. 2.0. If a copy of the MPL was not distributed with this |
|
+# file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
+ |
|
+CORE_DEPTH = ../.. |
|
+ |
|
+DEFINES += -DNSPR20 |
|
+ |
|
+# MODULE public and private header directories are implicitly REQUIRED. |
|
+MODULE = nss |
|
+ |
|
+CSRCS = \ |
|
+ validation.c \ |
|
+ $(NULL) |
|
+ |
|
+# The MODULE is always implicitly required. |
|
+# Listing it here in REQUIRES makes it appear twice in the cc command line. |
|
+REQUIRES = dbm seccmd |
|
+ |
|
+PROGRAM = validation |
|
+ |
|
+# USE_STATIC_LIBS = 1 |
|
diff --git a/cmd/validation/validation.c b/cmd/validation/validation.c |
|
new file mode 100644 |
|
--- /dev/null |
|
+++ b/cmd/validation/validation.c |
|
@@ -0,0 +1,249 @@ |
|
+/* This Source Code Form is subject to the terms of the Mozilla Public |
|
+ * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
+ |
|
+#ifdef _CRTDBG_MAP_ALLOC |
|
+#include <stdlib.h> |
|
+#include <crtdbg.h> |
|
+#endif |
|
+ |
|
+#include "nspr.h" |
|
+#include "secutil.h" |
|
+#include "pk11func.h" |
|
+#include "nss.h" |
|
+#include "secport.h" |
|
+#include "secpkcs5.h" |
|
+#include "sechash.h" |
|
+#include "certdb.h" |
|
+#include "secmod.h" |
|
+ |
|
+#define PKCS12_IN_BUFFER_SIZE 200 |
|
+ |
|
+static char *progName; |
|
+PRBool debug = PR_FALSE; |
|
+ |
|
+#define ERR_USAGE 2 |
|
+#define ERR_PK11GETSLOT 13 |
|
+ |
|
+static void |
|
+Usage() |
|
+{ |
|
+#define FPS PR_fprintf(PR_STDERR, |
|
+ FPS "Usage: %s [-d certdir] [-P dbprefix] [-h tokenname]\n", |
|
+ progName); |
|
+ FPS "\t\t [-k slotpwfile | -K slotpw] [-v]\n"); |
|
+ |
|
+ exit(ERR_USAGE); |
|
+} |
|
+ |
|
+typedef enum { |
|
+ tagULong, |
|
+ tagVersion, |
|
+ tagUtf8 |
|
+} tagType; |
|
+ |
|
+typedef struct { |
|
+ const char *attributeName; |
|
+ tagType attributeStorageType; |
|
+} attributeTag; |
|
+ |
|
+enum { |
|
+ opt_CertDir = 0, |
|
+ opt_TokenName, |
|
+ opt_SlotPWFile, |
|
+ opt_SlotPW, |
|
+ opt_DBPrefix, |
|
+ opt_Debug |
|
+}; |
|
+ |
|
+static secuCommandFlag validation_options[] = |
|
+ { |
|
+ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE }, |
|
+ { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE }, |
|
+ { /* opt_SlotPWFile */ 'k', PR_TRUE, 0, PR_FALSE }, |
|
+ { /* opt_SlotPW */ 'K', PR_TRUE, 0, PR_FALSE }, |
|
+ { /* opt_DBPrefix */ 'P', PR_TRUE, 0, PR_FALSE }, |
|
+ { /* opt_Debug */ 'v', PR_FALSE, 0, PR_FALSE } |
|
+ }; |
|
+ |
|
+void |
|
+dump_Raw(char *label, CK_ATTRIBUTE *attr) |
|
+{ |
|
+ int i; |
|
+ unsigned char *value = (unsigned char *)attr->pValue; |
|
+ printf("0x"); |
|
+ for (i = 0; i < attr->ulValueLen; i++) { |
|
+ printf("%02x", value[i]); |
|
+ } |
|
+ printf("<%s>\n", label); |
|
+} |
|
+ |
|
+SECStatus |
|
+dump_validations(CK_OBJECT_CLASS objc, CK_ATTRIBUTE *template, int count, |
|
+ attributeTag *tags, PK11SlotInfo *slot) |
|
+{ |
|
+ PK11GenericObject *objs, *obj; |
|
+ |
|
+ objs = PK11_FindGenericObjects(slot, objc); |
|
+ |
|
+ for (obj = objs; obj != NULL; obj = PK11_GetNextGenericObject(obj)) { |
|
+ int i; |
|
+ printf("Validation Object:\n"); |
|
+ PK11_ReadRawAttributes(NULL, PK11_TypeGeneric, obj, template, count); |
|
+ for (i = 0; i < count; i++) { |
|
+ CK_ULONG ulong; |
|
+ CK_VERSION version; |
|
+ int len = template[i].ulValueLen; |
|
+ printf(" %s: ", tags[i].attributeName); |
|
+ if (len < 0) { |
|
+ printf("<failed>\n"); |
|
+ } else if (len == 0) { |
|
+ printf("<empty>\n"); |
|
+ } else |
|
+ switch (tags[i].attributeStorageType) { |
|
+ case tagULong: |
|
+ if (len != sizeof(CK_ULONG)) { |
|
+ dump_Raw("bad ulong", &template[i]); |
|
+ break; |
|
+ } |
|
+ ulong = *(CK_ULONG *)template[i].pValue; |
|
+ printf("%ld\n", ulong); |
|
+ break; |
|
+ case tagVersion: |
|
+ if (len != sizeof(CK_VERSION)) { |
|
+ dump_Raw("bad version", &template[i]); |
|
+ break; |
|
+ } |
|
+ version = *(CK_VERSION *)template[i].pValue; |
|
+ printf("%d.%d\n", version.major, version.minor); |
|
+ break; |
|
+ case tagUtf8: |
|
+ printf("%.*s\n", len, (char *)template[i].pValue); |
|
+ break; |
|
+ default: |
|
+ dump_Raw("unknown tag", &template[i]); |
|
+ break; |
|
+ } |
|
+ PORT_Free(template[i].pValue); |
|
+ template[i].pValue = NULL; |
|
+ template[i].ulValueLen = 0; |
|
+ } |
|
+ } |
|
+ PK11_DestroyGenericObjects(objs); |
|
+ return SECSuccess; |
|
+} |
|
+ |
|
+int |
|
+main(int argc, char **argv) |
|
+{ |
|
+ secuPWData slotPw = { PW_NONE, NULL }; |
|
+ secuPWData p12FilePw = { PW_NONE, NULL }; |
|
+ PK11SlotInfo *slot; |
|
+ char *slotname = NULL; |
|
+ char *dbprefix = ""; |
|
+ char *nssdir = NULL; |
|
+ SECStatus rv; |
|
+ secuCommand validation; |
|
+ int local_errno = 0; |
|
+ |
|
+ CK_ATTRIBUTE validation_template[] = { |
|
+ { CKA_NSS_VALIDATION_TYPE, NULL, 0 }, |
|
+ { CKA_NSS_VALIDATION_VERSION, NULL, 0 }, |
|
+ { CKA_NSS_VALIDATION_LEVEL, NULL, 0 }, |
|
+ { CKA_NSS_VALIDATION_MODULE_ID, NULL, 0 } |
|
+ }; |
|
+ attributeTag validation_tags[] = { |
|
+ { "Validation Type", tagULong }, |
|
+ { "Validation Version", tagVersion }, |
|
+ { "Validation Level", tagULong }, |
|
+ { "Validation Module ID", tagUtf8 }, |
|
+ }; |
|
+ |
|
+#ifdef _CRTDBG_MAP_ALLOC |
|
+ _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); |
|
+#endif |
|
+ |
|
+ validation.numCommands = 0; |
|
+ validation.commands = 0; |
|
+ validation.numOptions = PR_ARRAY_SIZE(validation_options); |
|
+ validation.options = validation_options; |
|
+ |
|
+ progName = strrchr(argv[0], '/'); |
|
+ progName = progName ? progName + 1 : argv[0]; |
|
+ |
|
+ rv = SECU_ParseCommandLine(argc, argv, progName, &validation); |
|
+ |
|
+ if (rv != SECSuccess) |
|
+ Usage(); |
|
+ |
|
+ debug = validation.options[opt_Debug].activated; |
|
+ |
|
+ slotname = SECU_GetOptionArg(&validation, opt_TokenName); |
|
+ |
|
+ if (validation.options[opt_SlotPWFile].activated) { |
|
+ slotPw.source = PW_FROMFILE; |
|
+ slotPw.data = PORT_Strdup(validation.options[opt_SlotPWFile].arg); |
|
+ } |
|
+ |
|
+ if (validation.options[opt_SlotPW].activated) { |
|
+ slotPw.source = PW_PLAINTEXT; |
|
+ slotPw.data = PORT_Strdup(validation.options[opt_SlotPW].arg); |
|
+ } |
|
+ |
|
+ if (validation.options[opt_CertDir].activated) { |
|
+ nssdir = validation.options[opt_CertDir].arg; |
|
+ } |
|
+ if (validation.options[opt_DBPrefix].activated) { |
|
+ dbprefix = validation.options[opt_DBPrefix].arg; |
|
+ } |
|
+ |
|
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
|
+ if (nssdir == NULL && NSS_NoDB_Init("") == SECSuccess) { |
|
+ rv = SECSuccess; |
|
+ /* if the system isn't already in FIPS mode, we need |
|
+ * to switch to FIPS mode */ |
|
+ if (!PK11_IsFIPS()) { |
|
+ /* flip to FIPS mode */ |
|
+ SECMODModule *module = SECMOD_GetInternalModule(); |
|
+ rv = SECMOD_DeleteInternalModule(module->commonName); |
|
+ } |
|
+ } else { |
|
+ rv = NSS_Initialize(nssdir, dbprefix, dbprefix, |
|
+ "secmod.db", 0); |
|
+ } |
|
+ if (rv != SECSuccess) { |
|
+ SECU_PrintPRandOSError(progName); |
|
+ exit(-1); |
|
+ } |
|
+ |
|
+ if (!slotname || PL_strcmp(slotname, "internal") == 0) |
|
+ slot = PK11_GetInternalKeySlot(); |
|
+ else |
|
+ slot = PK11_FindSlotByName(slotname); |
|
+ |
|
+ if (!slot) { |
|
+ SECU_PrintError(progName, "Invalid slot \"%s\"", slotname); |
|
+ local_errno = ERR_PK11GETSLOT; |
|
+ goto done; |
|
+ } |
|
+ |
|
+ rv = dump_validations(CKO_NSS_VALIDATION, |
|
+ validation_template, |
|
+ PR_ARRAY_SIZE(validation_template), |
|
+ validation_tags, |
|
+ slot); |
|
+ |
|
+done: |
|
+ if (slotPw.data != NULL) |
|
+ PORT_ZFree(slotPw.data, PL_strlen(slotPw.data)); |
|
+ if (p12FilePw.data != NULL) |
|
+ PORT_ZFree(p12FilePw.data, PL_strlen(p12FilePw.data)); |
|
+ if (slot) |
|
+ PK11_FreeSlot(slot); |
|
+ if (NSS_Shutdown() != SECSuccess) { |
|
+ local_errno = 1; |
|
+ } |
|
+ PL_ArenaFinish(); |
|
+ PR_Cleanup(); |
|
+ return local_errno; |
|
+} |
|
diff --git a/cmd/validation/validation.gyp b/cmd/validation/validation.gyp |
|
new file mode 100644 |
|
--- /dev/null |
|
+++ b/cmd/validation/validation.gyp |
|
@@ -0,0 +1,30 @@ |
|
+# This Source Code Form is subject to the terms of the Mozilla Public |
|
+# License, v. 2.0. If a copy of the MPL was not distributed with this |
|
+# file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
+{ |
|
+ 'includes': [ |
|
+ '../../coreconf/config.gypi', |
|
+ '../../cmd/platlibs.gypi' |
|
+ ], |
|
+ 'targets': [ |
|
+ { |
|
+ 'target_name': 'validation', |
|
+ 'type': 'executable', |
|
+ 'sources': [ |
|
+ 'validation.c' |
|
+ ], |
|
+ 'dependencies': [ |
|
+ '<(DEPTH)/exports.gyp:dbm_exports', |
|
+ '<(DEPTH)/exports.gyp:nss_exports' |
|
+ ] |
|
+ } |
|
+ ], |
|
+ 'target_defaults': { |
|
+ 'defines': [ |
|
+ 'NSPR20' |
|
+ ] |
|
+ }, |
|
+ 'variables': { |
|
+ 'module': 'nss' |
|
+ } |
|
+} |
|
diff --git a/lib/softoken/config.mk b/lib/softoken/config.mk |
|
--- a/lib/softoken/config.mk |
|
+++ b/lib/softoken/config.mk |
|
@@ -59,3 +59,7 @@ |
|
DEFINES += -DNSS_ENABLE_FIPS_INDICATORS |
|
endif |
|
|
|
+ifdef NSS_FIPS_MODULE_ID |
|
+DEFINES += -DNSS_FIPS_MODULE_ID=\"${NSS_FIPS_MODULE_ID}\" |
|
+endif |
|
+ |
|
diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c |
|
--- a/lib/softoken/pkcs11.c |
|
+++ b/lib/softoken/pkcs11.c |
|
@@ -75,7 +75,6 @@ |
|
* failure so that there are at most 60 login attempts per minute. |
|
*/ |
|
static PRIntervalTime loginWaitTime; |
|
-static PRUint32 minSessionObjectHandle = 1U; |
|
|
|
#define __PASTE(x, y) x##y |
|
|
|
@@ -1672,8 +1671,6 @@ |
|
{ |
|
SFTKSlot *slot = session->slot; |
|
SFTKAttribute *attribute; |
|
- SFTKObject *duplicateObject = NULL; |
|
- CK_OBJECT_HANDLE handle; |
|
CK_BBOOL ckfalse = CK_FALSE; |
|
CK_BBOOL cktrue = CK_TRUE; |
|
CK_RV crv; |
|
@@ -1711,30 +1708,13 @@ |
|
* token objects and will have a token object handle assigned to |
|
* them by a call to sftk_mkHandle in the handler for each object |
|
* class, invoked below. |
|
- * |
|
+ * |
|
* It may be helpful to note/remember that |
|
* sftk_narrowToXxxObject uses sftk_isToken, |
|
* sftk_isToken examines the sign bit of the object's handle, but |
|
* sftk_isTrue(...,CKA_TOKEN) examines the CKA_TOKEN attribute. |
|
*/ |
|
- do { |
|
- PRUint32 wrappedAround; |
|
- |
|
- duplicateObject = NULL; |
|
- PZ_Lock(slot->objectLock); |
|
- wrappedAround = slot->sessionObjectHandleCount & SFTK_TOKEN_MASK; |
|
- handle = slot->sessionObjectHandleCount & ~SFTK_TOKEN_MASK; |
|
- if (!handle) /* don't allow zero handle */ |
|
- handle = minSessionObjectHandle; |
|
- slot->sessionObjectHandleCount = (handle + 1U) | wrappedAround; |
|
- /* Is there already a session object with this handle? */ |
|
- if (wrappedAround) { |
|
- sftkqueue_find(duplicateObject, handle, slot->sessObjHashTable, |
|
- slot->sessObjHashSize); |
|
- } |
|
- PZ_Unlock(slot->objectLock); |
|
- } while (duplicateObject != NULL); |
|
- object->handle = handle; |
|
+ object->handle = sftk_getNextHandle(slot); |
|
|
|
/* get the object class */ |
|
attribute = sftk_FindAttribute(object, CKA_CLASS); |
|
@@ -2875,10 +2855,15 @@ |
|
goto mem_loser; |
|
|
|
slot->sessionIDCount = 0; |
|
- slot->sessionObjectHandleCount = minSessionObjectHandle; |
|
+ slot->sessionObjectHandleCount = NSC_MIN_SESSION_OBJECT_HANDLE; |
|
slot->slotID = slotID; |
|
sftk_setStringName(params->slotdes ? params->slotdes : sftk_getDefSlotName(slotID), slot->slotDescription, |
|
sizeof(slot->slotDescription), PR_TRUE); |
|
+ crv = sftk_InitSession(&slot->moduleObjects, slot, slotID, NULL, NULL, |
|
+ CKF_SERIAL_SESSION); |
|
+ if (crv != CKR_OK) { |
|
+ goto loser; |
|
+ } |
|
|
|
/* call the reinit code to set everything that changes between token |
|
* init calls */ |
|
@@ -2887,6 +2872,12 @@ |
|
if (crv != CKR_OK) { |
|
goto loser; |
|
} |
|
+ if (sftk_isFIPS(slotID)) { |
|
+ crv = sftk_CreateValidationObjects(slot); |
|
+ if (crv != CKR_OK) { |
|
+ goto loser; |
|
+ } |
|
+ } |
|
crv = sftk_RegisterSlot(slot, moduleIndex); |
|
if (crv != CKR_OK) { |
|
goto loser; |
|
@@ -3032,6 +3023,8 @@ |
|
|
|
SFTK_ShutdownSlot(slot); |
|
|
|
+ sftk_ClearSession(&slot->moduleObjects); |
|
+ |
|
if (slot->tokObjHashTable) { |
|
PL_HashTableDestroy(slot->tokObjHashTable); |
|
slot->tokObjHashTable = NULL; |
|
@@ -3262,6 +3255,7 @@ |
|
CK_RV crv = CKR_OK; |
|
SECStatus rv; |
|
CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *)pReserved; |
|
+ PRBool destroy_freelist_on_error = PR_TRUE; |
|
int i; |
|
unsigned int moduleIndex = isFIPS ? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE; |
|
|
|
@@ -3341,7 +3335,14 @@ |
|
"disabled FIPS mode"); |
|
} |
|
} |
|
+ /* if we have a peer open, we don't want to destroy the freelist |
|
+ * from under the peer if we fail, the free list will be |
|
+ * destroyed in that case when the C_Finalize is called for |
|
+ * the peer */ |
|
+ destroy_freelist_on_error = PR_FALSE; |
|
} |
|
+ /* allow us to create objects in SFTK_SlotInit */ |
|
+ sftk_InitFreeLists(); |
|
|
|
for (i = 0; i < paramStrings.token_count; i++) { |
|
crv = SFTK_SlotInit(paramStrings.configdir, |
|
@@ -3355,8 +3356,9 @@ |
|
loser: |
|
sftk_freeParams(¶mStrings); |
|
} |
|
- if (CKR_OK == crv) { |
|
- sftk_InitFreeLists(); |
|
+ if (destroy_freelist_on_error && (CKR_OK != crv)) { |
|
+ /* idempotent. If the list are already freed, this is a noop */ |
|
+ sftk_CleanupFreeLists(); |
|
} |
|
|
|
#ifndef NO_FORK_CHECK |
|
diff --git a/lib/softoken/pkcs11i.h b/lib/softoken/pkcs11i.h |
|
--- a/lib/softoken/pkcs11i.h |
|
+++ b/lib/softoken/pkcs11i.h |
|
@@ -49,6 +49,8 @@ |
|
#define NSC_SEARCH_BLOCK_SIZE 5 |
|
#define NSC_SLOT_LIST_BLOCK_SIZE 10 |
|
|
|
+#define NSC_MIN_SESSION_OBJECT_HANDLE 1U |
|
+ |
|
#define NSC_FIPS_MODULE 1 |
|
#define NSC_NON_FIPS_MODULE 0 |
|
|
|
@@ -375,6 +377,9 @@ |
|
char tokDescription[33]; /* per load */ |
|
char updateTokDescription[33]; /* per load */ |
|
char slotDescription[65]; /* invariant */ |
|
+ SFTKSession moduleObjects; /* global session to hang module specific |
|
+ * objects like profile objects or |
|
+ * validation objects */ |
|
}; |
|
|
|
/* |
|
@@ -766,6 +771,7 @@ |
|
extern void sftk_ReferenceObject(SFTKObject *object); |
|
extern SFTKObject *sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle, |
|
SFTKSession *session); |
|
+extern CK_OBJECT_HANDLE sftk_getNextHandle(SFTKSlot *slot); |
|
extern void sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object); |
|
extern void sftk_AddObject(SFTKSession *session, SFTKObject *object); |
|
/* clear out all the existing object ID to database key mappings. |
|
@@ -787,7 +793,11 @@ |
|
extern CK_SLOT_ID sftk_SlotIDFromSessionHandle(CK_SESSION_HANDLE handle); |
|
extern SFTKSession *sftk_SessionFromHandle(CK_SESSION_HANDLE handle); |
|
extern void sftk_FreeSession(SFTKSession *session); |
|
+extern void sftk_ClearSession(SFTKSession *session); |
|
extern void sftk_DestroySession(SFTKSession *session); |
|
+extern CK_RV sftk_InitSession(SFTKSession *session, SFTKSlot *slot, |
|
+ CK_SLOT_ID slotID, CK_NOTIFY notify, |
|
+ CK_VOID_PTR pApplication, CK_FLAGS flags); |
|
extern SFTKSession *sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, |
|
CK_VOID_PTR pApplication, CK_FLAGS flags); |
|
extern void sftk_update_state(SFTKSlot *slot, SFTKSession *session); |
|
@@ -955,6 +965,9 @@ |
|
* FIPS security policy */ |
|
PRBool sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech, |
|
CK_ATTRIBUTE_TYPE op, SFTKObject *source); |
|
+/* add validation objects to the slot */ |
|
+CK_RV sftk_CreateValidationObjects(SFTKSlot *slot); |
|
+ |
|
SEC_END_PROTOS |
|
|
|
#endif /* _PKCS11I_H_ */ |
|
diff --git a/lib/softoken/pkcs11u.c b/lib/softoken/pkcs11u.c |
|
--- a/lib/softoken/pkcs11u.c |
|
+++ b/lib/softoken/pkcs11u.c |
|
@@ -14,6 +14,7 @@ |
|
#include "sftkdb.h" |
|
#include "softoken.h" |
|
#include "secoid.h" |
|
+#include "softkver.h" |
|
|
|
#if !defined(NSS_FIPS_DISABLED) && defined(NSS_ENABLE_FIPS_INDICATORS) |
|
/* this file should be supplied by the vendor and include all the |
|
@@ -1243,6 +1244,32 @@ |
|
return SFTK_Busy; |
|
} |
|
|
|
+/* find the next available object handle that isn't currently in use */ |
|
+CK_OBJECT_HANDLE |
|
+sftk_getNextHandle(SFTKSlot *slot) |
|
+{ |
|
+ CK_OBJECT_HANDLE handle; |
|
+ SFTKObject *duplicateObject = NULL; |
|
+ do { |
|
+ PRUint32 wrappedAround; |
|
+ |
|
+ duplicateObject = NULL; |
|
+ PZ_Lock(slot->objectLock); |
|
+ wrappedAround = slot->sessionObjectHandleCount & SFTK_TOKEN_MASK; |
|
+ handle = slot->sessionObjectHandleCount & ~SFTK_TOKEN_MASK; |
|
+ if (!handle) /* don't allow zero handle */ |
|
+ handle = NSC_MIN_SESSION_OBJECT_HANDLE; |
|
+ slot->sessionObjectHandleCount = (handle + 1U) | wrappedAround; |
|
+ /* Is there already a session object with this handle? */ |
|
+ if (wrappedAround) { |
|
+ sftkqueue_find(duplicateObject, handle, slot->sessObjHashTable, |
|
+ slot->sessObjHashSize); |
|
+ } |
|
+ PZ_Unlock(slot->objectLock); |
|
+ } while (duplicateObject != NULL); |
|
+ return handle; |
|
+} |
|
+ |
|
/* |
|
* add an object to a slot and session queue. These two functions |
|
* adopt the object. |
|
@@ -1848,23 +1875,13 @@ |
|
} |
|
|
|
/* |
|
- * create a new nession. NOTE: The session handle is not set, and the |
|
+ * Init a new session. NOTE: The session handle is not set, and the |
|
* session is not added to the slot's session queue. |
|
*/ |
|
-SFTKSession * |
|
-sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication, |
|
- CK_FLAGS flags) |
|
+CK_RV |
|
+sftk_InitSession(SFTKSession *session, SFTKSlot *slot, CK_SLOT_ID slotID, |
|
+ CK_NOTIFY notify, CK_VOID_PTR pApplication, CK_FLAGS flags) |
|
{ |
|
- SFTKSession *session; |
|
- SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); |
|
- |
|
- if (slot == NULL) |
|
- return NULL; |
|
- |
|
- session = (SFTKSession *)PORT_Alloc(sizeof(SFTKSession)); |
|
- if (session == NULL) |
|
- return NULL; |
|
- |
|
session->next = session->prev = NULL; |
|
session->enc_context = NULL; |
|
session->hash_context = NULL; |
|
@@ -1873,8 +1890,7 @@ |
|
session->objectIDCount = 1; |
|
session->objectLock = PZ_NewLock(nssILockObject); |
|
if (session->objectLock == NULL) { |
|
- PORT_Free(session); |
|
- return NULL; |
|
+ return CKR_HOST_MEMORY; |
|
} |
|
session->objects[0] = NULL; |
|
|
|
@@ -1887,12 +1903,38 @@ |
|
sftk_update_state(slot, session); |
|
/* no ops completed yet, so the last one couldn't be a FIPS op */ |
|
session->lastOpWasFIPS = PR_FALSE; |
|
+ return CKR_OK; |
|
+} |
|
+ |
|
+/* |
|
+ * Create a new session and init it. |
|
+ */ |
|
+SFTKSession * |
|
+sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication, |
|
+ CK_FLAGS flags) |
|
+{ |
|
+ SFTKSession *session; |
|
+ SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); |
|
+ CK_RV crv; |
|
+ |
|
+ if (slot == NULL) |
|
+ return NULL; |
|
+ |
|
+ session = (SFTKSession *)PORT_Alloc(sizeof(SFTKSession)); |
|
+ if (session == NULL) |
|
+ return NULL; |
|
+ |
|
+ crv = sftk_InitSession(session, slot, slotID, notify, pApplication, flags); |
|
+ if (crv != CKR_OK) { |
|
+ PORT_Free(session); |
|
+ return NULL; |
|
+ } |
|
return session; |
|
} |
|
|
|
/* free all the data associated with a session. */ |
|
void |
|
-sftk_DestroySession(SFTKSession *session) |
|
+sftk_ClearSession(SFTKSession *session) |
|
{ |
|
SFTKObjectList *op, *next; |
|
|
|
@@ -1918,6 +1960,13 @@ |
|
if (session->search) { |
|
sftk_FreeSearch(session->search); |
|
} |
|
+} |
|
+ |
|
+/* free the data associated with the session, and the session */ |
|
+void |
|
+sftk_DestroySession(SFTKSession *session) |
|
+{ |
|
+ sftk_ClearSession(session); |
|
PORT_Free(session); |
|
} |
|
|
|
@@ -2386,3 +2435,70 @@ |
|
return PR_FALSE; |
|
#endif |
|
} |
|
+ |
|
+/* |
|
+ * create the FIPS Validation objects. If the vendor |
|
+ * doesn't supply an NSS_FIPS_MODULE_ID, at compile time, |
|
+ * then we assumethis is an unvalidated module. |
|
+ */ |
|
+CK_RV |
|
+sftk_CreateValidationObjects(SFTKSlot *slot) |
|
+{ |
|
+ const char *module_id; |
|
+ int module_id_len; |
|
+ CK_RV crv = CKR_OK; |
|
+ /* we currently use vendor specific values until the validation |
|
+ * objects are approved for PKCS #11 v3.2. */ |
|
+ CK_OBJECT_CLASS cko_validation = CKO_NSS_VALIDATION; |
|
+ CK_NSS_VALIDATION_TYPE ckv_fips = CKV_NSS_FIPS_140; |
|
+ CK_VERSION fips_version = { 3, 0 }; /* FIPS-140-3 */ |
|
+ CK_ULONG fips_level = 1; /* or 2 if you validated at level 2 */ |
|
+ |
|
+#ifndef NSS_FIPS_MODULE_ID |
|
+#define NSS_FIPS_MODULE_ID "Generic NSS " SOFTOKEN_VERSION " Unvalidated" |
|
+#endif |
|
+ module_id = NSS_FIPS_MODULE_ID; |
|
+ module_id_len = sizeof(NSS_FIPS_MODULE_ID) - 1; |
|
+ SFTKObject *object; |
|
+ |
|
+ object = sftk_NewObject(slot); /* fill in the handle later */ |
|
+ if (object == NULL) { |
|
+ return CKR_HOST_MEMORY; |
|
+ } |
|
+ object->isFIPS = PR_FALSE; |
|
+ |
|
+ crv = sftk_AddAttributeType(object, CKA_CLASS, |
|
+ &cko_validation, sizeof(cko_validation)); |
|
+ if (crv != CKR_OK) { |
|
+ goto loser; |
|
+ } |
|
+ crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_TYPE, |
|
+ &ckv_fips, sizeof(ckv_fips)); |
|
+ if (crv != CKR_OK) { |
|
+ goto loser; |
|
+ } |
|
+ crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_VERSION, |
|
+ &fips_version, sizeof(fips_version)); |
|
+ if (crv != CKR_OK) { |
|
+ goto loser; |
|
+ } |
|
+ crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_LEVEL, |
|
+ &fips_level, sizeof(fips_level)); |
|
+ if (crv != CKR_OK) { |
|
+ goto loser; |
|
+ } |
|
+ crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_MODULE_ID, |
|
+ module_id, module_id_len); |
|
+ if (crv != CKR_OK) { |
|
+ goto loser; |
|
+ } |
|
+ |
|
+ /* future, fill in validation certificate information from a supplied |
|
+ * pointer to a config file */ |
|
+ object->handle = sftk_getNextHandle(slot); |
|
+ object->slot = slot; |
|
+ sftk_AddObject(&slot->moduleObjects, object); |
|
+loser: |
|
+ sftk_FreeObject(object); |
|
+ return crv; |
|
+} |
|
diff --git a/lib/util/pkcs11n.h b/lib/util/pkcs11n.h |
|
--- a/lib/util/pkcs11n.h |
|
+++ b/lib/util/pkcs11n.h |
|
@@ -38,6 +38,9 @@ |
|
#define CKO_NSS_BUILTIN_ROOT_LIST (CKO_NSS + 4) |
|
#define CKO_NSS_NEWSLOT (CKO_NSS + 5) |
|
#define CKO_NSS_DELSLOT (CKO_NSS + 6) |
|
+#define CKO_NSS_VALIDATION (CKO_NSS + 7) |
|
+ |
|
+#define CKV_NSS_FIPS_140 (CKO_NSS + 1) |
|
|
|
/* |
|
* NSS-defined key types |
|
@@ -99,6 +102,11 @@ |
|
#define CKA_NSS_SERVER_DISTRUST_AFTER (CKA_NSS + 35) |
|
#define CKA_NSS_EMAIL_DISTRUST_AFTER (CKA_NSS + 36) |
|
|
|
+#define CKA_NSS_VALIDATION_TYPE (CKA_NSS + 36) |
|
+#define CKA_NSS_VALIDATION_VERSION (CKA_NSS + 37) |
|
+#define CKA_NSS_VALIDATION_LEVEL (CKA_NSS + 38) |
|
+#define CKA_NSS_VALIDATION_MODULE_ID (CKA_NSS + 39) |
|
+ |
|
/* |
|
* Trust attributes: |
|
* |
|
@@ -344,6 +352,9 @@ |
|
#define CKR_NSS_CERTDB_FAILED (CKR_NSS + 1) |
|
#define CKR_NSS_KEYDB_FAILED (CKR_NSS + 2) |
|
|
|
+/* NSS specific types */ |
|
+typedef CK_ULONG CK_NSS_VALIDATION_TYPE; |
|
+ |
|
/* Mandatory parameter for the CKM_NSS_HKDF_* key deriviation mechanisms. |
|
See RFC 5869. |
|
|
|
diff --git a/nss.gyp b/nss.gyp |
|
--- a/nss.gyp |
|
+++ b/nss.gyp |
|
@@ -131,6 +131,7 @@ |
|
'cmd/smimetools/smimetools.gyp:cmsutil', |
|
'cmd/ssltap/ssltap.gyp:ssltap', |
|
'cmd/symkeyutil/symkeyutil.gyp:symkeyutil', |
|
+ 'cmd/validation/validation.gyp:validation', |
|
'nss-tool/nss_tool.gyp:nss', |
|
'nss-tool/nss_tool.gyp:hw-support', |
|
], |
|
|
|
|