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 +#include +#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("\n"); + } else if (len == 0) { + printf("\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', ],