diff options
Diffstat (limited to '')
-rw-r--r-- | security/nss/lib/ckfw/instance.c | 1318 |
1 files changed, 1318 insertions, 0 deletions
diff --git a/security/nss/lib/ckfw/instance.c b/security/nss/lib/ckfw/instance.c new file mode 100644 index 0000000000..00d353385f --- /dev/null +++ b/security/nss/lib/ckfw/instance.c @@ -0,0 +1,1318 @@ +/* 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/. */ + +/* + * instance.c + * + * This file implements the NSSCKFWInstance type and methods. + */ + +#ifndef CK_T +#include "ck.h" +#endif /* CK_T */ + +#include <stdint.h> + +/* + * NSSCKFWInstance + * + * -- create/destroy -- + * nssCKFWInstance_Create + * nssCKFWInstance_Destroy + * + * -- public accessors -- + * NSSCKFWInstance_GetMDInstance + * NSSCKFWInstance_GetArena + * NSSCKFWInstance_MayCreatePthreads + * NSSCKFWInstance_CreateMutex + * NSSCKFWInstance_GetConfigurationData + * NSSCKFWInstance_GetInitArgs + * NSSCKFWInstance_DestroySessionHandle + * NSSCKFWInstance_FindSessionHandle + * + * -- implement public accessors -- + * nssCKFWInstance_GetMDInstance + * nssCKFWInstance_GetArena + * nssCKFWInstance_MayCreatePthreads + * nssCKFWInstance_CreateMutex + * nssCKFWInstance_GetConfigurationData + * nssCKFWInstance_GetInitArgs + * nssCKFWInstance_DestroySessionHandle + * nssCKFWInstance_FindSessionHandle + * + * -- private accessors -- + * nssCKFWInstance_CreateSessionHandle + * nssCKFWInstance_ResolveSessionHandle + * nssCKFWInstance_CreateObjectHandle + * nssCKFWInstance_ResolveObjectHandle + * nssCKFWInstance_DestroyObjectHandle + * + * -- module fronts -- + * nssCKFWInstance_GetNSlots + * nssCKFWInstance_GetCryptokiVersion + * nssCKFWInstance_GetManufacturerID + * nssCKFWInstance_GetFlags + * nssCKFWInstance_GetLibraryDescription + * nssCKFWInstance_GetLibraryVersion + * nssCKFWInstance_GetModuleHandlesSessionObjects + * nssCKFWInstance_GetSlots + * nssCKFWInstance_WaitForSlotEvent + * + * -- debugging versions only -- + * nssCKFWInstance_verifyPointer + */ + +struct NSSCKFWInstanceStr { + NSSCKFWMutex *mutex; + NSSArena *arena; + NSSCKMDInstance *mdInstance; + CK_C_INITIALIZE_ARGS_PTR pInitArgs; + CK_C_INITIALIZE_ARGS initArgs; + CryptokiLockingState LockingState; + CK_BBOOL mayCreatePthreads; + NSSUTF8 *configurationData; + CK_ULONG nSlots; + NSSCKFWSlot **fwSlotList; + NSSCKMDSlot **mdSlotList; + CK_BBOOL moduleHandlesSessionObjects; + + /* + * Everything above is set at creation time, and then not modified. + * The invariants the mutex protects are: + * + * 1) Each of the cached descriptions (versions, etc.) are in an + * internally consistant state. + * + * 2) The session handle hashes and count are consistant + * + * 3) The object handle hashes and count are consistant. + * + * I could use multiple locks, but let's wait to see if that's + * really necessary. + * + * Note that the calls accessing the cached descriptions will + * call the NSSCKMDInstance methods with the mutex locked. Those + * methods may then call the public NSSCKFWInstance routines. + * Those public routines only access the constant data above, so + * there's no problem. But be careful if you add to this object; + * mutexes are in general not reentrant, so don't create deadlock + * situations. + */ + + CK_VERSION cryptokiVersion; + NSSUTF8 *manufacturerID; + NSSUTF8 *libraryDescription; + CK_VERSION libraryVersion; + + CK_ULONG lastSessionHandle; + nssCKFWHash *sessionHandleHash; + + CK_ULONG lastObjectHandle; + nssCKFWHash *objectHandleHash; +}; + +#ifdef DEBUG +/* + * But first, the pointer-tracking stuff. + * + * NOTE: the pointer-tracking support in NSS/base currently relies + * upon NSPR's CallOnce support. That, however, relies upon NSPR's + * locking, which is tied into the runtime. We need a pointer-tracker + * implementation that uses the locks supplied through C_Initialize. + * That support, however, can be filled in later. So for now, I'll + * just do this routines as no-ops. + */ + +static CK_RV +instance_add_pointer( + const NSSCKFWInstance *fwInstance) +{ + return CKR_OK; +} + +static CK_RV +instance_remove_pointer( + const NSSCKFWInstance *fwInstance) +{ + return CKR_OK; +} + +NSS_IMPLEMENT CK_RV +nssCKFWInstance_verifyPointer( + const NSSCKFWInstance *fwInstance) +{ + return CKR_OK; +} + +#endif /* DEBUG */ + +/* + * nssCKFWInstance_Create + * + */ +NSS_IMPLEMENT NSSCKFWInstance * +nssCKFWInstance_Create( + CK_C_INITIALIZE_ARGS_PTR pInitArgs, + CryptokiLockingState LockingState, + NSSCKMDInstance *mdInstance, + CK_RV *pError) +{ + NSSCKFWInstance *fwInstance; + NSSArena *arena = (NSSArena *)NULL; + CK_ULONG i; + CK_BBOOL called_Initialize = CK_FALSE; + +#ifdef NSSDEBUG + if ((CK_RV)NULL == pError) { + return (NSSCKFWInstance *)NULL; + } + + if (!mdInstance) { + *pError = CKR_ARGUMENTS_BAD; + return (NSSCKFWInstance *)NULL; + } +#endif /* NSSDEBUG */ + + arena = NSSArena_Create(); + if (!arena) { + *pError = CKR_HOST_MEMORY; + return (NSSCKFWInstance *)NULL; + } + + fwInstance = nss_ZNEW(arena, NSSCKFWInstance); + if (!fwInstance) { + goto nomem; + } + + fwInstance->arena = arena; + fwInstance->mdInstance = mdInstance; + + fwInstance->LockingState = LockingState; + if ((CK_C_INITIALIZE_ARGS_PTR)NULL != pInitArgs) { + fwInstance->initArgs = *pInitArgs; + fwInstance->pInitArgs = &fwInstance->initArgs; + if (pInitArgs->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) { + fwInstance->mayCreatePthreads = CK_FALSE; + } else { + fwInstance->mayCreatePthreads = CK_TRUE; + } + fwInstance->configurationData = (NSSUTF8 *)(pInitArgs->pReserved); + } else { + fwInstance->mayCreatePthreads = CK_TRUE; + } + + fwInstance->mutex = nssCKFWMutex_Create(pInitArgs, LockingState, arena, + pError); + if (!fwInstance->mutex) { + if (CKR_OK == *pError) { + *pError = CKR_GENERAL_ERROR; + } + goto loser; + } + + if (mdInstance->Initialize) { + *pError = mdInstance->Initialize(mdInstance, fwInstance, fwInstance->configurationData); + if (CKR_OK != *pError) { + goto loser; + } + + called_Initialize = CK_TRUE; + } + + if (mdInstance->ModuleHandlesSessionObjects) { + fwInstance->moduleHandlesSessionObjects = + mdInstance->ModuleHandlesSessionObjects(mdInstance, fwInstance); + } else { + fwInstance->moduleHandlesSessionObjects = CK_FALSE; + } + + if (!mdInstance->GetNSlots) { + /* That routine is required */ + *pError = CKR_GENERAL_ERROR; + goto loser; + } + + fwInstance->nSlots = mdInstance->GetNSlots(mdInstance, fwInstance, pError); + if ((CK_ULONG)0 == fwInstance->nSlots) { + if (CKR_OK == *pError) { + /* Zero is not a legitimate answer */ + *pError = CKR_GENERAL_ERROR; + } + goto loser; + } + + fwInstance->fwSlotList = nss_ZNEWARRAY(arena, NSSCKFWSlot *, fwInstance->nSlots); + if ((NSSCKFWSlot **)NULL == fwInstance->fwSlotList) { + goto nomem; + } + + fwInstance->mdSlotList = nss_ZNEWARRAY(arena, NSSCKMDSlot *, fwInstance->nSlots); + if ((NSSCKMDSlot **)NULL == fwInstance->mdSlotList) { + goto nomem; + } + + fwInstance->sessionHandleHash = nssCKFWHash_Create(fwInstance, + fwInstance->arena, pError); + if (!fwInstance->sessionHandleHash) { + goto loser; + } + + fwInstance->objectHandleHash = nssCKFWHash_Create(fwInstance, + fwInstance->arena, pError); + if (!fwInstance->objectHandleHash) { + goto loser; + } + + if (!mdInstance->GetSlots) { + /* That routine is required */ + *pError = CKR_GENERAL_ERROR; + goto loser; + } + + *pError = mdInstance->GetSlots(mdInstance, fwInstance, fwInstance->mdSlotList); + if (CKR_OK != *pError) { + goto loser; + } + + for (i = 0; i < fwInstance->nSlots; i++) { + NSSCKMDSlot *mdSlot = fwInstance->mdSlotList[i]; + + if (!mdSlot) { + *pError = CKR_GENERAL_ERROR; + goto loser; + } + + fwInstance->fwSlotList[i] = nssCKFWSlot_Create(fwInstance, mdSlot, i, pError); + if (CKR_OK != *pError) { + CK_ULONG j; + + for (j = 0; j < i; j++) { + (void)nssCKFWSlot_Destroy(fwInstance->fwSlotList[j]); + } + + for (j = i; j < fwInstance->nSlots; j++) { + NSSCKMDSlot *mds = fwInstance->mdSlotList[j]; + if (mds->Destroy) { + mds->Destroy(mds, (NSSCKFWSlot *)NULL, mdInstance, fwInstance); + } + } + + goto loser; + } + } + +#ifdef DEBUG + *pError = instance_add_pointer(fwInstance); + if (CKR_OK != *pError) { + for (i = 0; i < fwInstance->nSlots; i++) { + (void)nssCKFWSlot_Destroy(fwInstance->fwSlotList[i]); + } + + goto loser; + } +#endif /* DEBUG */ + + *pError = CKR_OK; + return fwInstance; + +nomem: + *pError = CKR_HOST_MEMORY; +/*FALLTHROUGH*/ +loser: + + if (CK_TRUE == called_Initialize) { + if (mdInstance->Finalize) { + mdInstance->Finalize(mdInstance, fwInstance); + } + } + + if (fwInstance && fwInstance->mutex) { + nssCKFWMutex_Destroy(fwInstance->mutex); + } + + if (arena) { + (void)NSSArena_Destroy(arena); + } + return (NSSCKFWInstance *)NULL; +} + +/* + * nssCKFWInstance_Destroy + * + */ +NSS_IMPLEMENT CK_RV +nssCKFWInstance_Destroy( + NSSCKFWInstance *fwInstance) +{ +#ifdef NSSDEBUG + CK_RV error = CKR_OK; +#endif /* NSSDEBUG */ + CK_ULONG i; + +#ifdef NSSDEBUG + error = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != error) { + return error; + } +#endif /* NSSDEBUG */ + + nssCKFWMutex_Destroy(fwInstance->mutex); + + for (i = 0; i < fwInstance->nSlots; i++) { + (void)nssCKFWSlot_Destroy(fwInstance->fwSlotList[i]); + } + + if (fwInstance->mdInstance->Finalize) { + fwInstance->mdInstance->Finalize(fwInstance->mdInstance, fwInstance); + } + + if (fwInstance->sessionHandleHash) { + nssCKFWHash_Destroy(fwInstance->sessionHandleHash); + } + + if (fwInstance->objectHandleHash) { + nssCKFWHash_Destroy(fwInstance->objectHandleHash); + } + +#ifdef DEBUG + (void)instance_remove_pointer(fwInstance); +#endif /* DEBUG */ + + (void)NSSArena_Destroy(fwInstance->arena); + return CKR_OK; +} + +/* + * nssCKFWInstance_GetMDInstance + * + */ +NSS_IMPLEMENT NSSCKMDInstance * +nssCKFWInstance_GetMDInstance( + NSSCKFWInstance *fwInstance) +{ +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return (NSSCKMDInstance *)NULL; + } +#endif /* NSSDEBUG */ + + return fwInstance->mdInstance; +} + +/* + * nssCKFWInstance_GetArena + * + */ +NSS_IMPLEMENT NSSArena * +nssCKFWInstance_GetArena( + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ +#ifdef NSSDEBUG + if (!pError) { + return (NSSArena *)NULL; + } + + *pError = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != *pError) { + return (NSSArena *)NULL; + } +#endif /* NSSDEBUG */ + + *pError = CKR_OK; + return fwInstance->arena; +} + +/* + * nssCKFWInstance_MayCreatePthreads + * + */ +NSS_IMPLEMENT CK_BBOOL +nssCKFWInstance_MayCreatePthreads( + NSSCKFWInstance *fwInstance) +{ +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return CK_FALSE; + } +#endif /* NSSDEBUG */ + + return fwInstance->mayCreatePthreads; +} + +/* + * nssCKFWInstance_CreateMutex + * + */ +NSS_IMPLEMENT NSSCKFWMutex * +nssCKFWInstance_CreateMutex( + NSSCKFWInstance *fwInstance, + NSSArena *arena, + CK_RV *pError) +{ + NSSCKFWMutex *mutex; + +#ifdef NSSDEBUG + if (!pError) { + return (NSSCKFWMutex *)NULL; + } + + *pError = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != *pError) { + return (NSSCKFWMutex *)NULL; + } +#endif /* NSSDEBUG */ + + mutex = nssCKFWMutex_Create(fwInstance->pInitArgs, fwInstance->LockingState, + arena, pError); + if (!mutex) { + if (CKR_OK == *pError) { + *pError = CKR_GENERAL_ERROR; + } + + return (NSSCKFWMutex *)NULL; + } + + return mutex; +} + +/* + * nssCKFWInstance_GetConfigurationData + * + */ +NSS_IMPLEMENT NSSUTF8 * +nssCKFWInstance_GetConfigurationData( + NSSCKFWInstance *fwInstance) +{ +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return (NSSUTF8 *)NULL; + } +#endif /* NSSDEBUG */ + + return fwInstance->configurationData; +} + +/* + * nssCKFWInstance_GetInitArgs + * + */ +CK_C_INITIALIZE_ARGS_PTR +nssCKFWInstance_GetInitArgs( + NSSCKFWInstance *fwInstance) +{ +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return (CK_C_INITIALIZE_ARGS_PTR)NULL; + } +#endif /* NSSDEBUG */ + + return fwInstance->pInitArgs; +} + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4312) +#elif defined(__clang__) || defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" +#endif + +PR_STATIC_ASSERT(sizeof(CK_SESSION_HANDLE) <= sizeof(void *)); + +static inline void * +CKSessionHandleToVoidPtr(CK_SESSION_HANDLE handle) +{ + return (void *)(uintptr_t)handle; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#elif defined(__clang__) || defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +/* + * nssCKFWInstance_CreateSessionHandle + * + */ +NSS_IMPLEMENT CK_SESSION_HANDLE +nssCKFWInstance_CreateSessionHandle( + NSSCKFWInstance *fwInstance, + NSSCKFWSession *fwSession, + CK_RV *pError) +{ + CK_SESSION_HANDLE hSession; + +#ifdef NSSDEBUG + if (!pError) { + return (CK_SESSION_HANDLE)0; + } + + *pError = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != *pError) { + return (CK_SESSION_HANDLE)0; + } +#endif /* NSSDEBUG */ + + *pError = nssCKFWMutex_Lock(fwInstance->mutex); + if (CKR_OK != *pError) { + return (CK_SESSION_HANDLE)0; + } + + hSession = ++(fwInstance->lastSessionHandle); + + /* Alan would say I should unlock for this call. */ + + *pError = nssCKFWSession_SetHandle(fwSession, hSession); + if (CKR_OK != *pError) { + goto done; + } + + *pError = nssCKFWHash_Add(fwInstance->sessionHandleHash, + CKSessionHandleToVoidPtr(hSession), (const void *)fwSession); + if (CKR_OK != *pError) { + hSession = (CK_SESSION_HANDLE)0; + goto done; + } + +done: + nssCKFWMutex_Unlock(fwInstance->mutex); + return hSession; +} + +/* + * nssCKFWInstance_ResolveSessionHandle + * + */ +NSS_IMPLEMENT NSSCKFWSession * +nssCKFWInstance_ResolveSessionHandle( + NSSCKFWInstance *fwInstance, + CK_SESSION_HANDLE hSession) +{ + NSSCKFWSession *fwSession; + +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return (NSSCKFWSession *)NULL; + } +#endif /* NSSDEBUG */ + + if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) { + return (NSSCKFWSession *)NULL; + } + + fwSession = (NSSCKFWSession *)nssCKFWHash_Lookup( + fwInstance->sessionHandleHash, CKSessionHandleToVoidPtr(hSession)); + + /* Assert(hSession == nssCKFWSession_GetHandle(fwSession)) */ + + (void)nssCKFWMutex_Unlock(fwInstance->mutex); + + return fwSession; +} + +/* + * nssCKFWInstance_DestroySessionHandle + * + */ +NSS_IMPLEMENT void +nssCKFWInstance_DestroySessionHandle( + NSSCKFWInstance *fwInstance, + CK_SESSION_HANDLE hSession) +{ + NSSCKFWSession *fwSession; + +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return; + } +#endif /* NSSDEBUG */ + + if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) { + return; + } + + fwSession = (NSSCKFWSession *)nssCKFWHash_Lookup( + fwInstance->sessionHandleHash, CKSessionHandleToVoidPtr(hSession)); + if (fwSession) { + nssCKFWHash_Remove(fwInstance->sessionHandleHash, CKSessionHandleToVoidPtr(hSession)); + nssCKFWSession_SetHandle(fwSession, (CK_SESSION_HANDLE)0); + } + + (void)nssCKFWMutex_Unlock(fwInstance->mutex); + + return; +} + +/* + * nssCKFWInstance_FindSessionHandle + * + */ +NSS_IMPLEMENT CK_SESSION_HANDLE +nssCKFWInstance_FindSessionHandle( + NSSCKFWInstance *fwInstance, + NSSCKFWSession *fwSession) +{ +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return (CK_SESSION_HANDLE)0; + } + + if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { + return (CK_SESSION_HANDLE)0; + } +#endif /* NSSDEBUG */ + + return nssCKFWSession_GetHandle(fwSession); + /* look it up and assert? */ +} + +/* + * nssCKFWInstance_CreateObjectHandle + * + */ +NSS_IMPLEMENT CK_OBJECT_HANDLE +nssCKFWInstance_CreateObjectHandle( + NSSCKFWInstance *fwInstance, + NSSCKFWObject *fwObject, + CK_RV *pError) +{ + CK_OBJECT_HANDLE hObject; + +#ifdef NSSDEBUG + if (!pError) { + return (CK_OBJECT_HANDLE)0; + } + + *pError = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != *pError) { + return (CK_OBJECT_HANDLE)0; + } +#endif /* NSSDEBUG */ + + *pError = nssCKFWMutex_Lock(fwInstance->mutex); + if (CKR_OK != *pError) { + return (CK_OBJECT_HANDLE)0; + } + + hObject = ++(fwInstance->lastObjectHandle); + + *pError = nssCKFWObject_SetHandle(fwObject, hObject); + if (CKR_OK != *pError) { + hObject = (CK_OBJECT_HANDLE)0; + goto done; + } + + *pError = nssCKFWHash_Add(fwInstance->objectHandleHash, + CKSessionHandleToVoidPtr(hObject), (const void *)fwObject); + if (CKR_OK != *pError) { + hObject = (CK_OBJECT_HANDLE)0; + goto done; + } + +done: + (void)nssCKFWMutex_Unlock(fwInstance->mutex); + return hObject; +} + +/* + * nssCKFWInstance_ResolveObjectHandle + * + */ +NSS_IMPLEMENT NSSCKFWObject * +nssCKFWInstance_ResolveObjectHandle( + NSSCKFWInstance *fwInstance, + CK_OBJECT_HANDLE hObject) +{ + NSSCKFWObject *fwObject; + +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return (NSSCKFWObject *)NULL; + } +#endif /* NSSDEBUG */ + + if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) { + return (NSSCKFWObject *)NULL; + } + + fwObject = (NSSCKFWObject *)nssCKFWHash_Lookup( + fwInstance->objectHandleHash, CKSessionHandleToVoidPtr(hObject)); + + /* Assert(hObject == nssCKFWObject_GetHandle(fwObject)) */ + + (void)nssCKFWMutex_Unlock(fwInstance->mutex); + return fwObject; +} + +/* + * nssCKFWInstance_ReassignObjectHandle + * + */ +NSS_IMPLEMENT CK_RV +nssCKFWInstance_ReassignObjectHandle( + NSSCKFWInstance *fwInstance, + CK_OBJECT_HANDLE hObject, + NSSCKFWObject *fwObject) +{ + CK_RV error = CKR_OK; + NSSCKFWObject *oldObject; + +#ifdef NSSDEBUG + error = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != error) { + return error; + } +#endif /* NSSDEBUG */ + + error = nssCKFWMutex_Lock(fwInstance->mutex); + if (CKR_OK != error) { + return error; + } + + oldObject = (NSSCKFWObject *)nssCKFWHash_Lookup( + fwInstance->objectHandleHash, CKSessionHandleToVoidPtr(hObject)); + if (oldObject) { + /* Assert(hObject == nssCKFWObject_GetHandle(oldObject) */ + (void)nssCKFWObject_SetHandle(oldObject, (CK_SESSION_HANDLE)0); + nssCKFWHash_Remove(fwInstance->objectHandleHash, CKSessionHandleToVoidPtr(hObject)); + } + + error = nssCKFWObject_SetHandle(fwObject, hObject); + if (CKR_OK != error) { + goto done; + } + error = nssCKFWHash_Add(fwInstance->objectHandleHash, + CKSessionHandleToVoidPtr(hObject), (const void *)fwObject); + +done: + (void)nssCKFWMutex_Unlock(fwInstance->mutex); + return error; +} + +/* + * nssCKFWInstance_DestroyObjectHandle + * + */ +NSS_IMPLEMENT void +nssCKFWInstance_DestroyObjectHandle( + NSSCKFWInstance *fwInstance, + CK_OBJECT_HANDLE hObject) +{ + NSSCKFWObject *fwObject; + +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return; + } +#endif /* NSSDEBUG */ + + if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) { + return; + } + + fwObject = (NSSCKFWObject *)nssCKFWHash_Lookup( + fwInstance->objectHandleHash, CKSessionHandleToVoidPtr(hObject)); + if (fwObject) { + /* Assert(hObject == nssCKFWObject_GetHandle(fwObject)) */ + nssCKFWHash_Remove(fwInstance->objectHandleHash, CKSessionHandleToVoidPtr(hObject)); + (void)nssCKFWObject_SetHandle(fwObject, (CK_SESSION_HANDLE)0); + } + + (void)nssCKFWMutex_Unlock(fwInstance->mutex); + return; +} + +/* + * nssCKFWInstance_FindObjectHandle + * + */ +NSS_IMPLEMENT CK_OBJECT_HANDLE +nssCKFWInstance_FindObjectHandle( + NSSCKFWInstance *fwInstance, + NSSCKFWObject *fwObject) +{ +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return (CK_OBJECT_HANDLE)0; + } + + if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) { + return (CK_OBJECT_HANDLE)0; + } +#endif /* NSSDEBUG */ + + return nssCKFWObject_GetHandle(fwObject); +} + +/* + * nssCKFWInstance_GetNSlots + * + */ +NSS_IMPLEMENT CK_ULONG +nssCKFWInstance_GetNSlots( + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ +#ifdef NSSDEBUG + if (!pError) { + return (CK_ULONG)0; + } + + *pError = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != *pError) { + return (CK_ULONG)0; + } +#endif /* NSSDEBUG */ + + *pError = CKR_OK; + return fwInstance->nSlots; +} + +/* + * nssCKFWInstance_GetCryptokiVersion + * + */ +NSS_IMPLEMENT CK_VERSION +nssCKFWInstance_GetCryptokiVersion( + NSSCKFWInstance *fwInstance) +{ + CK_VERSION rv; + +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + rv.major = rv.minor = 0; + return rv; + } +#endif /* NSSDEBUG */ + + if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) { + rv.major = rv.minor = 0; + return rv; + } + + if ((0 != fwInstance->cryptokiVersion.major) || + (0 != fwInstance->cryptokiVersion.minor)) { + rv = fwInstance->cryptokiVersion; + goto done; + } + + if (fwInstance->mdInstance->GetCryptokiVersion) { + fwInstance->cryptokiVersion = fwInstance->mdInstance->GetCryptokiVersion( + fwInstance->mdInstance, fwInstance); + } else { + fwInstance->cryptokiVersion.major = 2; + fwInstance->cryptokiVersion.minor = 1; + } + + rv = fwInstance->cryptokiVersion; + +done: + (void)nssCKFWMutex_Unlock(fwInstance->mutex); + return rv; +} + +/* + * nssCKFWInstance_GetManufacturerID + * + */ +NSS_IMPLEMENT CK_RV +nssCKFWInstance_GetManufacturerID( + NSSCKFWInstance *fwInstance, + CK_CHAR manufacturerID[32]) +{ + CK_RV error = CKR_OK; + +#ifdef NSSDEBUG + if ((CK_CHAR_PTR)NULL == manufacturerID) { + return CKR_ARGUMENTS_BAD; + } + + error = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != error) { + return error; + } +#endif /* NSSDEBUG */ + + error = nssCKFWMutex_Lock(fwInstance->mutex); + if (CKR_OK != error) { + return error; + } + + if (!fwInstance->manufacturerID) { + if (fwInstance->mdInstance->GetManufacturerID) { + fwInstance->manufacturerID = fwInstance->mdInstance->GetManufacturerID( + fwInstance->mdInstance, fwInstance, &error); + if ((!fwInstance->manufacturerID) && (CKR_OK != error)) { + goto done; + } + } else { + fwInstance->manufacturerID = (NSSUTF8 *)""; + } + } + + (void)nssUTF8_CopyIntoFixedBuffer(fwInstance->manufacturerID, (char *)manufacturerID, 32, ' '); + error = CKR_OK; + +done: + (void)nssCKFWMutex_Unlock(fwInstance->mutex); + return error; +} + +/* + * nssCKFWInstance_GetFlags + * + */ +NSS_IMPLEMENT CK_ULONG +nssCKFWInstance_GetFlags( + NSSCKFWInstance *fwInstance) +{ +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return (CK_ULONG)0; + } +#endif /* NSSDEBUG */ + + /* No "instance flags" are yet defined by Cryptoki. */ + return (CK_ULONG)0; +} + +/* + * nssCKFWInstance_GetLibraryDescription + * + */ +NSS_IMPLEMENT CK_RV +nssCKFWInstance_GetLibraryDescription( + NSSCKFWInstance *fwInstance, + CK_CHAR libraryDescription[32]) +{ + CK_RV error = CKR_OK; + +#ifdef NSSDEBUG + if ((CK_CHAR_PTR)NULL == libraryDescription) { + return CKR_ARGUMENTS_BAD; + } + + error = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != error) { + return error; + } +#endif /* NSSDEBUG */ + + error = nssCKFWMutex_Lock(fwInstance->mutex); + if (CKR_OK != error) { + return error; + } + + if (!fwInstance->libraryDescription) { + if (fwInstance->mdInstance->GetLibraryDescription) { + fwInstance->libraryDescription = fwInstance->mdInstance->GetLibraryDescription( + fwInstance->mdInstance, fwInstance, &error); + if ((!fwInstance->libraryDescription) && (CKR_OK != error)) { + goto done; + } + } else { + fwInstance->libraryDescription = (NSSUTF8 *)""; + } + } + + (void)nssUTF8_CopyIntoFixedBuffer(fwInstance->libraryDescription, (char *)libraryDescription, 32, ' '); + error = CKR_OK; + +done: + (void)nssCKFWMutex_Unlock(fwInstance->mutex); + return error; +} + +/* + * nssCKFWInstance_GetLibraryVersion + * + */ +NSS_IMPLEMENT CK_VERSION +nssCKFWInstance_GetLibraryVersion( + NSSCKFWInstance *fwInstance) +{ + CK_VERSION rv; + +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + rv.major = rv.minor = 0; + return rv; + } +#endif /* NSSDEBUG */ + + if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) { + rv.major = rv.minor = 0; + return rv; + } + + if ((0 != fwInstance->libraryVersion.major) || + (0 != fwInstance->libraryVersion.minor)) { + rv = fwInstance->libraryVersion; + goto done; + } + + if (fwInstance->mdInstance->GetLibraryVersion) { + fwInstance->libraryVersion = fwInstance->mdInstance->GetLibraryVersion( + fwInstance->mdInstance, fwInstance); + } else { + fwInstance->libraryVersion.major = 0; + fwInstance->libraryVersion.minor = 3; + } + + rv = fwInstance->libraryVersion; +done: + (void)nssCKFWMutex_Unlock(fwInstance->mutex); + return rv; +} + +/* + * nssCKFWInstance_GetModuleHandlesSessionObjects + * + */ +NSS_IMPLEMENT CK_BBOOL +nssCKFWInstance_GetModuleHandlesSessionObjects( + NSSCKFWInstance *fwInstance) +{ +#ifdef NSSDEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return CK_FALSE; + } +#endif /* NSSDEBUG */ + + return fwInstance->moduleHandlesSessionObjects; +} + +/* + * nssCKFWInstance_GetSlots + * + */ +NSS_IMPLEMENT NSSCKFWSlot ** +nssCKFWInstance_GetSlots( + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ +#ifdef NSSDEBUG + if (!pError) { + return (NSSCKFWSlot **)NULL; + } + + *pError = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != *pError) { + return (NSSCKFWSlot **)NULL; + } +#endif /* NSSDEBUG */ + + return fwInstance->fwSlotList; +} + +/* + * nssCKFWInstance_WaitForSlotEvent + * + */ +NSS_IMPLEMENT NSSCKFWSlot * +nssCKFWInstance_WaitForSlotEvent( + NSSCKFWInstance *fwInstance, + CK_BBOOL block, + CK_RV *pError) +{ + NSSCKFWSlot *fwSlot = (NSSCKFWSlot *)NULL; + NSSCKMDSlot *mdSlot; + CK_ULONG i, n; + +#ifdef NSSDEBUG + if (!pError) { + return (NSSCKFWSlot *)NULL; + } + + *pError = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != *pError) { + return (NSSCKFWSlot *)NULL; + } + + switch (block) { + case CK_TRUE: + case CK_FALSE: + break; + default: + *pError = CKR_ARGUMENTS_BAD; + return (NSSCKFWSlot *)NULL; + } +#endif /* NSSDEBUG */ + + if (!fwInstance->mdInstance->WaitForSlotEvent) { + *pError = CKR_NO_EVENT; + return (NSSCKFWSlot *)NULL; + } + + mdSlot = fwInstance->mdInstance->WaitForSlotEvent( + fwInstance->mdInstance, + fwInstance, + block, + pError); + + if (!mdSlot) { + return (NSSCKFWSlot *)NULL; + } + + n = nssCKFWInstance_GetNSlots(fwInstance, pError); + if (((CK_ULONG)0 == n) && (CKR_OK != *pError)) { + return (NSSCKFWSlot *)NULL; + } + + for (i = 0; i < n; i++) { + if (fwInstance->mdSlotList[i] == mdSlot) { + fwSlot = fwInstance->fwSlotList[i]; + break; + } + } + + if (!fwSlot) { + /* Internal error */ + *pError = CKR_GENERAL_ERROR; + return (NSSCKFWSlot *)NULL; + } + + return fwSlot; +} + +/* + * NSSCKFWInstance_GetMDInstance + * + */ +NSS_IMPLEMENT NSSCKMDInstance * +NSSCKFWInstance_GetMDInstance( + NSSCKFWInstance *fwInstance) +{ +#ifdef DEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return (NSSCKMDInstance *)NULL; + } +#endif /* DEBUG */ + + return nssCKFWInstance_GetMDInstance(fwInstance); +} + +/* + * NSSCKFWInstance_GetArena + * + */ +NSS_IMPLEMENT NSSArena * +NSSCKFWInstance_GetArena( + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ +#ifdef DEBUG + if (!pError) { + return (NSSArena *)NULL; + } + + *pError = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != *pError) { + return (NSSArena *)NULL; + } +#endif /* DEBUG */ + + return nssCKFWInstance_GetArena(fwInstance, pError); +} + +/* + * NSSCKFWInstance_MayCreatePthreads + * + */ +NSS_IMPLEMENT CK_BBOOL +NSSCKFWInstance_MayCreatePthreads( + NSSCKFWInstance *fwInstance) +{ +#ifdef DEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return CK_FALSE; + } +#endif /* DEBUG */ + + return nssCKFWInstance_MayCreatePthreads(fwInstance); +} + +/* + * NSSCKFWInstance_CreateMutex + * + */ +NSS_IMPLEMENT NSSCKFWMutex * +NSSCKFWInstance_CreateMutex( + NSSCKFWInstance *fwInstance, + NSSArena *arena, + CK_RV *pError) +{ +#ifdef DEBUG + if (!pError) { + return (NSSCKFWMutex *)NULL; + } + + *pError = nssCKFWInstance_verifyPointer(fwInstance); + if (CKR_OK != *pError) { + return (NSSCKFWMutex *)NULL; + } +#endif /* DEBUG */ + + return nssCKFWInstance_CreateMutex(fwInstance, arena, pError); +} + +/* + * NSSCKFWInstance_GetConfigurationData + * + */ +NSS_IMPLEMENT NSSUTF8 * +NSSCKFWInstance_GetConfigurationData( + NSSCKFWInstance *fwInstance) +{ +#ifdef DEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return (NSSUTF8 *)NULL; + } +#endif /* DEBUG */ + + return nssCKFWInstance_GetConfigurationData(fwInstance); +} + +/* + * NSSCKFWInstance_GetInitArgs + * + */ +NSS_IMPLEMENT CK_C_INITIALIZE_ARGS_PTR +NSSCKFWInstance_GetInitArgs( + NSSCKFWInstance *fwInstance) +{ +#ifdef DEBUG + if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) { + return (CK_C_INITIALIZE_ARGS_PTR)NULL; + } +#endif /* DEBUG */ + + return nssCKFWInstance_GetInitArgs(fwInstance); +} + +/* + * nssCKFWInstance_DestroySessionHandle + * + */ +NSS_IMPLEMENT void +NSSCKFWInstance_DestroySessionHandle( + NSSCKFWInstance *fwInstance, + CK_SESSION_HANDLE hSession) +{ + nssCKFWInstance_DestroySessionHandle(fwInstance, hSession); +} + +/* + * nssCKFWInstance_FindSessionHandle + * + */ +NSS_IMPLEMENT CK_SESSION_HANDLE +NSSCKFWInstance_FindSessionHandle( + NSSCKFWInstance *fwInstance, + NSSCKFWSession *fwSession) +{ + return nssCKFWInstance_FindSessionHandle(fwInstance, fwSession); +} |