| /* 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/. */ |
| |
| /* |
| * slot.c |
| * |
| * This file implements the NSSCKFWSlot type and methods. |
| */ |
| |
| #ifndef CK_T |
| #include "ck.h" |
| #endif /* CK_T */ |
| |
| /* |
| * NSSCKFWSlot |
| * |
| * -- create/destroy -- |
| * nssCKFWSlot_Create |
| * nssCKFWSlot_Destroy |
| * |
| * -- public accessors -- |
| * NSSCKFWSlot_GetMDSlot |
| * NSSCKFWSlot_GetFWInstance |
| * NSSCKFWSlot_GetMDInstance |
| * NSSCKFWSlot_GetSlotID |
| * |
| * -- implement public accessors -- |
| * nssCKFWSlot_GetMDSlot |
| * nssCKFWSlot_GetFWInstance |
| * nssCKFWSlot_GetMDInstance |
| * nssCKFWSlot_GetSlotID |
| * |
| * -- private accessors -- |
| * nssCKFWSlot_ClearToken |
| * |
| * -- module fronts -- |
| * nssCKFWSlot_GetSlotDescription |
| * nssCKFWSlot_GetManufacturerID |
| * nssCKFWSlot_GetTokenPresent |
| * nssCKFWSlot_GetRemovableDevice |
| * nssCKFWSlot_GetHardwareSlot |
| * nssCKFWSlot_GetHardwareVersion |
| * nssCKFWSlot_GetFirmwareVersion |
| * nssCKFWSlot_InitToken |
| * nssCKFWSlot_GetToken |
| */ |
| |
| struct NSSCKFWSlotStr { |
| NSSCKFWMutex *mutex; |
| NSSCKMDSlot *mdSlot; |
| NSSCKFWInstance *fwInstance; |
| NSSCKMDInstance *mdInstance; |
| CK_SLOT_ID slotID; |
| |
| /* |
| * 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 fwToken points to the token currently in the slot, and |
| * it is in a consistant state. |
| * |
| * Note that the calls accessing the cached descriptions will |
| * call the NSSCKMDSlot methods with the mutex locked. Those |
| * methods may then call the public NSSCKFWSlot 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. |
| */ |
| |
| NSSUTF8 *slotDescription; |
| NSSUTF8 *manufacturerID; |
| CK_VERSION hardwareVersion; |
| CK_VERSION firmwareVersion; |
| NSSCKFWToken *fwToken; |
| }; |
| |
| #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 |
| slot_add_pointer( |
| const NSSCKFWSlot *fwSlot) |
| { |
| return CKR_OK; |
| } |
| |
| static CK_RV |
| slot_remove_pointer( |
| const NSSCKFWSlot *fwSlot) |
| { |
| return CKR_OK; |
| } |
| |
| NSS_IMPLEMENT CK_RV |
| nssCKFWSlot_verifyPointer( |
| const NSSCKFWSlot *fwSlot) |
| { |
| return CKR_OK; |
| } |
| |
| #endif /* DEBUG */ |
| |
| /* |
| * nssCKFWSlot_Create |
| * |
| */ |
| NSS_IMPLEMENT NSSCKFWSlot * |
| nssCKFWSlot_Create( |
| NSSCKFWInstance *fwInstance, |
| NSSCKMDSlot *mdSlot, |
| CK_SLOT_ID slotID, |
| CK_RV *pError) |
| { |
| NSSCKFWSlot *fwSlot; |
| NSSCKMDInstance *mdInstance; |
| NSSArena *arena; |
| |
| #ifdef NSSDEBUG |
| if (!pError) { |
| return (NSSCKFWSlot *)NULL; |
| } |
| |
| *pError = nssCKFWInstance_verifyPointer(fwInstance); |
| if (CKR_OK != *pError) { |
| return (NSSCKFWSlot *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| mdInstance = nssCKFWInstance_GetMDInstance(fwInstance); |
| if (!mdInstance) { |
| *pError = CKR_GENERAL_ERROR; |
| return (NSSCKFWSlot *)NULL; |
| } |
| |
| arena = nssCKFWInstance_GetArena(fwInstance, pError); |
| if (!arena) { |
| if (CKR_OK == *pError) { |
| *pError = CKR_GENERAL_ERROR; |
| } |
| } |
| |
| fwSlot = nss_ZNEW(arena, NSSCKFWSlot); |
| if (!fwSlot) { |
| *pError = CKR_HOST_MEMORY; |
| return (NSSCKFWSlot *)NULL; |
| } |
| |
| fwSlot->mdSlot = mdSlot; |
| fwSlot->fwInstance = fwInstance; |
| fwSlot->mdInstance = mdInstance; |
| fwSlot->slotID = slotID; |
| |
| fwSlot->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError); |
| if (!fwSlot->mutex) { |
| if (CKR_OK == *pError) { |
| *pError = CKR_GENERAL_ERROR; |
| } |
| (void)nss_ZFreeIf(fwSlot); |
| return (NSSCKFWSlot *)NULL; |
| } |
| |
| if (mdSlot->Initialize) { |
| *pError = CKR_OK; |
| *pError = mdSlot->Initialize(mdSlot, fwSlot, mdInstance, fwInstance); |
| if (CKR_OK != *pError) { |
| (void)nssCKFWMutex_Destroy(fwSlot->mutex); |
| (void)nss_ZFreeIf(fwSlot); |
| return (NSSCKFWSlot *)NULL; |
| } |
| } |
| |
| #ifdef DEBUG |
| *pError = slot_add_pointer(fwSlot); |
| if (CKR_OK != *pError) { |
| if (mdSlot->Destroy) { |
| mdSlot->Destroy(mdSlot, fwSlot, mdInstance, fwInstance); |
| } |
| |
| (void)nssCKFWMutex_Destroy(fwSlot->mutex); |
| (void)nss_ZFreeIf(fwSlot); |
| return (NSSCKFWSlot *)NULL; |
| } |
| #endif /* DEBUG */ |
| |
| return fwSlot; |
| } |
| |
| /* |
| * nssCKFWSlot_Destroy |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWSlot_Destroy( |
| NSSCKFWSlot *fwSlot) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| error = nssCKFWSlot_verifyPointer(fwSlot); |
| if (CKR_OK != error) { |
| return error; |
| } |
| #endif /* NSSDEBUG */ |
| if (fwSlot->fwToken) { |
| nssCKFWToken_Destroy(fwSlot->fwToken); |
| } |
| |
| (void)nssCKFWMutex_Destroy(fwSlot->mutex); |
| |
| if (fwSlot->mdSlot->Destroy) { |
| fwSlot->mdSlot->Destroy(fwSlot->mdSlot, fwSlot, |
| fwSlot->mdInstance, fwSlot->fwInstance); |
| } |
| |
| #ifdef DEBUG |
| error = slot_remove_pointer(fwSlot); |
| #endif /* DEBUG */ |
| (void)nss_ZFreeIf(fwSlot); |
| return error; |
| } |
| |
| /* |
| * nssCKFWSlot_GetMDSlot |
| * |
| */ |
| NSS_IMPLEMENT NSSCKMDSlot * |
| nssCKFWSlot_GetMDSlot( |
| NSSCKFWSlot *fwSlot) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| return (NSSCKMDSlot *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| return fwSlot->mdSlot; |
| } |
| |
| /* |
| * nssCKFWSlot_GetFWInstance |
| * |
| */ |
| |
| NSS_IMPLEMENT NSSCKFWInstance * |
| nssCKFWSlot_GetFWInstance( |
| NSSCKFWSlot *fwSlot) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| return (NSSCKFWInstance *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| return fwSlot->fwInstance; |
| } |
| |
| /* |
| * nssCKFWSlot_GetMDInstance |
| * |
| */ |
| |
| NSS_IMPLEMENT NSSCKMDInstance * |
| nssCKFWSlot_GetMDInstance( |
| NSSCKFWSlot *fwSlot) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| return (NSSCKMDInstance *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| return fwSlot->mdInstance; |
| } |
| |
| /* |
| * nssCKFWSlot_GetSlotID |
| * |
| */ |
| NSS_IMPLEMENT CK_SLOT_ID |
| nssCKFWSlot_GetSlotID( |
| NSSCKFWSlot *fwSlot) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| return (CK_SLOT_ID)0; |
| } |
| #endif /* NSSDEBUG */ |
| |
| return fwSlot->slotID; |
| } |
| |
| /* |
| * nssCKFWSlot_GetSlotDescription |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWSlot_GetSlotDescription( |
| NSSCKFWSlot *fwSlot, |
| CK_CHAR slotDescription[64]) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| if ((CK_CHAR_PTR)NULL == slotDescription) { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| error = nssCKFWSlot_verifyPointer(fwSlot); |
| if (CKR_OK != error) { |
| return error; |
| } |
| #endif /* NSSDEBUG */ |
| |
| error = nssCKFWMutex_Lock(fwSlot->mutex); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| if (!fwSlot->slotDescription) { |
| if (fwSlot->mdSlot->GetSlotDescription) { |
| fwSlot->slotDescription = fwSlot->mdSlot->GetSlotDescription( |
| fwSlot->mdSlot, fwSlot, fwSlot->mdInstance, |
| fwSlot->fwInstance, &error); |
| if ((!fwSlot->slotDescription) && (CKR_OK != error)) { |
| goto done; |
| } |
| } else { |
| fwSlot->slotDescription = (NSSUTF8 *)""; |
| } |
| } |
| |
| (void)nssUTF8_CopyIntoFixedBuffer(fwSlot->slotDescription, (char *)slotDescription, 64, ' '); |
| error = CKR_OK; |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwSlot->mutex); |
| return error; |
| } |
| |
| /* |
| * nssCKFWSlot_GetManufacturerID |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWSlot_GetManufacturerID( |
| NSSCKFWSlot *fwSlot, |
| CK_CHAR manufacturerID[32]) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| if ((CK_CHAR_PTR)NULL == manufacturerID) { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| error = nssCKFWSlot_verifyPointer(fwSlot); |
| if (CKR_OK != error) { |
| return error; |
| } |
| #endif /* NSSDEBUG */ |
| |
| error = nssCKFWMutex_Lock(fwSlot->mutex); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| if (!fwSlot->manufacturerID) { |
| if (fwSlot->mdSlot->GetManufacturerID) { |
| fwSlot->manufacturerID = fwSlot->mdSlot->GetManufacturerID( |
| fwSlot->mdSlot, fwSlot, fwSlot->mdInstance, |
| fwSlot->fwInstance, &error); |
| if ((!fwSlot->manufacturerID) && (CKR_OK != error)) { |
| goto done; |
| } |
| } else { |
| fwSlot->manufacturerID = (NSSUTF8 *)""; |
| } |
| } |
| |
| (void)nssUTF8_CopyIntoFixedBuffer(fwSlot->manufacturerID, (char *)manufacturerID, 32, ' '); |
| error = CKR_OK; |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwSlot->mutex); |
| return error; |
| } |
| |
| /* |
| * nssCKFWSlot_GetTokenPresent |
| * |
| */ |
| NSS_IMPLEMENT CK_BBOOL |
| nssCKFWSlot_GetTokenPresent( |
| NSSCKFWSlot *fwSlot) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwSlot->mdSlot->GetTokenPresent) { |
| return CK_TRUE; |
| } |
| |
| return fwSlot->mdSlot->GetTokenPresent(fwSlot->mdSlot, fwSlot, |
| fwSlot->mdInstance, fwSlot->fwInstance); |
| } |
| |
| /* |
| * nssCKFWSlot_GetRemovableDevice |
| * |
| */ |
| NSS_IMPLEMENT CK_BBOOL |
| nssCKFWSlot_GetRemovableDevice( |
| NSSCKFWSlot *fwSlot) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwSlot->mdSlot->GetRemovableDevice) { |
| return CK_FALSE; |
| } |
| |
| return fwSlot->mdSlot->GetRemovableDevice(fwSlot->mdSlot, fwSlot, |
| fwSlot->mdInstance, fwSlot->fwInstance); |
| } |
| |
| /* |
| * nssCKFWSlot_GetHardwareSlot |
| * |
| */ |
| NSS_IMPLEMENT CK_BBOOL |
| nssCKFWSlot_GetHardwareSlot( |
| NSSCKFWSlot *fwSlot) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwSlot->mdSlot->GetHardwareSlot) { |
| return CK_FALSE; |
| } |
| |
| return fwSlot->mdSlot->GetHardwareSlot(fwSlot->mdSlot, fwSlot, |
| fwSlot->mdInstance, fwSlot->fwInstance); |
| } |
| |
| /* |
| * nssCKFWSlot_GetHardwareVersion |
| * |
| */ |
| NSS_IMPLEMENT CK_VERSION |
| nssCKFWSlot_GetHardwareVersion( |
| NSSCKFWSlot *fwSlot) |
| { |
| CK_VERSION rv; |
| |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| rv.major = rv.minor = 0; |
| return rv; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (CKR_OK != nssCKFWMutex_Lock(fwSlot->mutex)) { |
| rv.major = rv.minor = 0; |
| return rv; |
| } |
| |
| if ((0 != fwSlot->hardwareVersion.major) || |
| (0 != fwSlot->hardwareVersion.minor)) { |
| rv = fwSlot->hardwareVersion; |
| goto done; |
| } |
| |
| if (fwSlot->mdSlot->GetHardwareVersion) { |
| fwSlot->hardwareVersion = fwSlot->mdSlot->GetHardwareVersion( |
| fwSlot->mdSlot, fwSlot, fwSlot->mdInstance, fwSlot->fwInstance); |
| } else { |
| fwSlot->hardwareVersion.major = 0; |
| fwSlot->hardwareVersion.minor = 1; |
| } |
| |
| rv = fwSlot->hardwareVersion; |
| done: |
| (void)nssCKFWMutex_Unlock(fwSlot->mutex); |
| return rv; |
| } |
| |
| /* |
| * nssCKFWSlot_GetFirmwareVersion |
| * |
| */ |
| NSS_IMPLEMENT CK_VERSION |
| nssCKFWSlot_GetFirmwareVersion( |
| NSSCKFWSlot *fwSlot) |
| { |
| CK_VERSION rv; |
| |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| rv.major = rv.minor = 0; |
| return rv; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (CKR_OK != nssCKFWMutex_Lock(fwSlot->mutex)) { |
| rv.major = rv.minor = 0; |
| return rv; |
| } |
| |
| if ((0 != fwSlot->firmwareVersion.major) || |
| (0 != fwSlot->firmwareVersion.minor)) { |
| rv = fwSlot->firmwareVersion; |
| goto done; |
| } |
| |
| if (fwSlot->mdSlot->GetFirmwareVersion) { |
| fwSlot->firmwareVersion = fwSlot->mdSlot->GetFirmwareVersion( |
| fwSlot->mdSlot, fwSlot, fwSlot->mdInstance, fwSlot->fwInstance); |
| } else { |
| fwSlot->firmwareVersion.major = 0; |
| fwSlot->firmwareVersion.minor = 1; |
| } |
| |
| rv = fwSlot->firmwareVersion; |
| done: |
| (void)nssCKFWMutex_Unlock(fwSlot->mutex); |
| return rv; |
| } |
| |
| /* |
| * nssCKFWSlot_GetToken |
| * |
| */ |
| NSS_IMPLEMENT NSSCKFWToken * |
| nssCKFWSlot_GetToken( |
| NSSCKFWSlot *fwSlot, |
| CK_RV *pError) |
| { |
| NSSCKMDToken *mdToken; |
| NSSCKFWToken *fwToken; |
| |
| #ifdef NSSDEBUG |
| if (!pError) { |
| return (NSSCKFWToken *)NULL; |
| } |
| |
| *pError = nssCKFWSlot_verifyPointer(fwSlot); |
| if (CKR_OK != *pError) { |
| return (NSSCKFWToken *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| *pError = nssCKFWMutex_Lock(fwSlot->mutex); |
| if (CKR_OK != *pError) { |
| return (NSSCKFWToken *)NULL; |
| } |
| |
| if (!fwSlot->fwToken) { |
| if (!fwSlot->mdSlot->GetToken) { |
| *pError = CKR_GENERAL_ERROR; |
| fwToken = (NSSCKFWToken *)NULL; |
| goto done; |
| } |
| |
| mdToken = fwSlot->mdSlot->GetToken(fwSlot->mdSlot, fwSlot, |
| fwSlot->mdInstance, fwSlot->fwInstance, pError); |
| if (!mdToken) { |
| if (CKR_OK == *pError) { |
| *pError = CKR_GENERAL_ERROR; |
| } |
| return (NSSCKFWToken *)NULL; |
| } |
| |
| fwToken = nssCKFWToken_Create(fwSlot, mdToken, pError); |
| fwSlot->fwToken = fwToken; |
| } else { |
| fwToken = fwSlot->fwToken; |
| } |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwSlot->mutex); |
| return fwToken; |
| } |
| |
| /* |
| * nssCKFWSlot_ClearToken |
| * |
| */ |
| NSS_IMPLEMENT void |
| nssCKFWSlot_ClearToken( |
| NSSCKFWSlot *fwSlot) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| return; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (CKR_OK != nssCKFWMutex_Lock(fwSlot->mutex)) { |
| /* Now what? */ |
| return; |
| } |
| |
| fwSlot->fwToken = (NSSCKFWToken *)NULL; |
| (void)nssCKFWMutex_Unlock(fwSlot->mutex); |
| return; |
| } |
| |
| /* |
| * NSSCKFWSlot_GetMDSlot |
| * |
| */ |
| |
| NSS_IMPLEMENT NSSCKMDSlot * |
| NSSCKFWSlot_GetMDSlot( |
| NSSCKFWSlot *fwSlot) |
| { |
| #ifdef DEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| return (NSSCKMDSlot *)NULL; |
| } |
| #endif /* DEBUG */ |
| |
| return nssCKFWSlot_GetMDSlot(fwSlot); |
| } |
| |
| /* |
| * NSSCKFWSlot_GetFWInstance |
| * |
| */ |
| |
| NSS_IMPLEMENT NSSCKFWInstance * |
| NSSCKFWSlot_GetFWInstance( |
| NSSCKFWSlot *fwSlot) |
| { |
| #ifdef DEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| return (NSSCKFWInstance *)NULL; |
| } |
| #endif /* DEBUG */ |
| |
| return nssCKFWSlot_GetFWInstance(fwSlot); |
| } |
| |
| /* |
| * NSSCKFWSlot_GetMDInstance |
| * |
| */ |
| |
| NSS_IMPLEMENT NSSCKMDInstance * |
| NSSCKFWSlot_GetMDInstance( |
| NSSCKFWSlot *fwSlot) |
| { |
| #ifdef DEBUG |
| if (CKR_OK != nssCKFWSlot_verifyPointer(fwSlot)) { |
| return (NSSCKMDInstance *)NULL; |
| } |
| #endif /* DEBUG */ |
| |
| return nssCKFWSlot_GetMDInstance(fwSlot); |
| } |
| |
| /* |
| * NSSCKFWSlot_GetSlotID |
| * |
| */ |
| |
| NSS_IMPLEMENT CK_SLOT_ID |
| NSSCKFWSlot_GetSlotID( |
| NSSCKFWSlot *fwSlot) |
| { |
| return nssCKFWSlot_GetSlotID(fwSlot); |
| } |