diff options
Diffstat (limited to 'lib/softoken')
-rw-r--r-- | lib/softoken/config.mk | 4 | ||||
-rw-r--r-- | lib/softoken/pkcs11.c | 52 | ||||
-rw-r--r-- | lib/softoken/pkcs11i.h | 13 | ||||
-rw-r--r-- | lib/softoken/pkcs11u.c | 154 |
4 files changed, 181 insertions, 42 deletions
diff --git a/lib/softoken/config.mk b/lib/softoken/config.mk index 771b93a3f..339f80493 100644 --- a/lib/softoken/config.mk +++ b/lib/softoken/config.mk @@ -59,3 +59,7 @@ ifdef NSS_ENABLE_FIPS_INDICATORS 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 index 3f49333f8..dcb0c729d 100644 --- a/lib/softoken/pkcs11.c +++ b/lib/softoken/pkcs11.c @@ -75,7 +75,6 @@ static char libraryDescription_space[33]; * 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 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session) { 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 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session) * 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 @@ SFTK_SlotInit(char *configdir, char *updatedir, char *updateID, 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 @@ SFTK_SlotInit(char *configdir, char *updatedir, char *updateID, 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_DestroySlotData(SFTKSlot *slot) SFTK_ShutdownSlot(slot); + sftk_ClearSession(&slot->moduleObjects); + if (slot->tokObjHashTable) { PL_HashTableDestroy(slot->tokObjHashTable); slot->tokObjHashTable = NULL; @@ -3262,6 +3255,7 @@ nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) 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 @@ nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) "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 @@ nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) 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 index 032e85fee..4365a115c 100644 --- 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 @@ struct SFTKSlotStr { 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 CK_RV sftk_DeleteObject(SFTKSession *session, SFTKObject *object); 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 SFTKSlot *sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle); 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 @@ CK_FLAGS sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE op); * 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 index f37aab92f..5299a700a 100644 --- 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,36 @@ sftk_FreeObject(SFTKObject *object) return SFTK_Busy; } +/* find the next available object handle that isn't currently in use */ +/* NOTE: This function could loop forever if we've exhausted all + * 3^31-1 handles. This is highly unlikely (NSS has been running for + * decades with this code) uless we start increasing the size of the + * SFTK_TOKEN_MASK (which is just the high bit currently). */ +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 +1879,13 @@ sftk_FreeContext(SFTKSessionContext *context) } /* - * 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 +1894,7 @@ sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication, 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 +1907,38 @@ sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication, 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 +1964,13 @@ sftk_DestroySession(SFTKSession *session) 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 +2439,70 @@ sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech, CK_ATTRIBUTE_TYPE op, 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; +} |