/* 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 /* * 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); }