| /* 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/. */ |
| |
| /* |
| * token.c |
| * |
| * This file implements the NSSCKFWToken type and methods. |
| */ |
| |
| #ifndef CK_T |
| #include "ck.h" |
| #endif /* CK_T */ |
| |
| /* |
| * NSSCKFWToken |
| * |
| * -- create/destroy -- |
| * nssCKFWToken_Create |
| * nssCKFWToken_Destroy |
| * |
| * -- public accessors -- |
| * NSSCKFWToken_GetMDToken |
| * NSSCKFWToken_GetFWSlot |
| * NSSCKFWToken_GetMDSlot |
| * NSSCKFWToken_GetSessionState |
| * |
| * -- implement public accessors -- |
| * nssCKFWToken_GetMDToken |
| * nssCKFWToken_GetFWSlot |
| * nssCKFWToken_GetMDSlot |
| * nssCKFWToken_GetSessionState |
| * nssCKFWToken_SetSessionState |
| * |
| * -- private accessors -- |
| * nssCKFWToken_SetSessionState |
| * nssCKFWToken_RemoveSession |
| * nssCKFWToken_CloseAllSessions |
| * nssCKFWToken_GetSessionCount |
| * nssCKFWToken_GetRwSessionCount |
| * nssCKFWToken_GetRoSessionCount |
| * nssCKFWToken_GetSessionObjectHash |
| * nssCKFWToken_GetMDObjectHash |
| * nssCKFWToken_GetObjectHandleHash |
| * |
| * -- module fronts -- |
| * nssCKFWToken_InitToken |
| * nssCKFWToken_GetLabel |
| * nssCKFWToken_GetManufacturerID |
| * nssCKFWToken_GetModel |
| * nssCKFWToken_GetSerialNumber |
| * nssCKFWToken_GetHasRNG |
| * nssCKFWToken_GetIsWriteProtected |
| * nssCKFWToken_GetLoginRequired |
| * nssCKFWToken_GetUserPinInitialized |
| * nssCKFWToken_GetRestoreKeyNotNeeded |
| * nssCKFWToken_GetHasClockOnToken |
| * nssCKFWToken_GetHasProtectedAuthenticationPath |
| * nssCKFWToken_GetSupportsDualCryptoOperations |
| * nssCKFWToken_GetMaxSessionCount |
| * nssCKFWToken_GetMaxRwSessionCount |
| * nssCKFWToken_GetMaxPinLen |
| * nssCKFWToken_GetMinPinLen |
| * nssCKFWToken_GetTotalPublicMemory |
| * nssCKFWToken_GetFreePublicMemory |
| * nssCKFWToken_GetTotalPrivateMemory |
| * nssCKFWToken_GetFreePrivateMemory |
| * nssCKFWToken_GetHardwareVersion |
| * nssCKFWToken_GetFirmwareVersion |
| * nssCKFWToken_GetUTCTime |
| * nssCKFWToken_OpenSession |
| * nssCKFWToken_GetMechanismCount |
| * nssCKFWToken_GetMechanismTypes |
| * nssCKFWToken_GetMechanism |
| */ |
| |
| struct NSSCKFWTokenStr { |
| NSSCKFWMutex *mutex; |
| NSSArena *arena; |
| NSSCKMDToken *mdToken; |
| NSSCKFWSlot *fwSlot; |
| NSSCKMDSlot *mdSlot; |
| NSSCKFWInstance *fwInstance; |
| NSSCKMDInstance *mdInstance; |
| |
| /* |
| * 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 counts and hashes are consistant. |
| * |
| * 3) The object hashes are consistant. |
| * |
| * Note that the calls accessing the cached descriptions will call |
| * the NSSCKMDToken methods with the mutex locked. Those methods |
| * may then call the public NSSCKFWToken routines. Those public |
| * routines only access the constant data above and the atomic |
| * CK_STATE session state variable below, 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 *label; |
| NSSUTF8 *manufacturerID; |
| NSSUTF8 *model; |
| NSSUTF8 *serialNumber; |
| CK_VERSION hardwareVersion; |
| CK_VERSION firmwareVersion; |
| |
| CK_ULONG sessionCount; |
| CK_ULONG rwSessionCount; |
| nssCKFWHash *sessions; |
| nssCKFWHash *sessionObjectHash; |
| nssCKFWHash *mdObjectHash; |
| nssCKFWHash *mdMechanismHash; |
| |
| CK_STATE state; |
| }; |
| |
| #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 |
| token_add_pointer( |
| const NSSCKFWToken *fwToken) |
| { |
| return CKR_OK; |
| } |
| |
| static CK_RV |
| token_remove_pointer( |
| const NSSCKFWToken *fwToken) |
| { |
| return CKR_OK; |
| } |
| |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_verifyPointer( |
| const NSSCKFWToken *fwToken) |
| { |
| return CKR_OK; |
| } |
| |
| #endif /* DEBUG */ |
| |
| /* |
| * nssCKFWToken_Create |
| * |
| */ |
| NSS_IMPLEMENT NSSCKFWToken * |
| nssCKFWToken_Create( |
| NSSCKFWSlot *fwSlot, |
| NSSCKMDToken *mdToken, |
| CK_RV *pError) |
| { |
| NSSArena *arena = (NSSArena *)NULL; |
| NSSCKFWToken *fwToken = (NSSCKFWToken *)NULL; |
| CK_BBOOL called_setup = CK_FALSE; |
| |
| /* |
| * We have already verified the arguments in nssCKFWSlot_GetToken. |
| */ |
| |
| arena = NSSArena_Create(); |
| if (!arena) { |
| *pError = CKR_HOST_MEMORY; |
| goto loser; |
| } |
| |
| fwToken = nss_ZNEW(arena, NSSCKFWToken); |
| if (!fwToken) { |
| *pError = CKR_HOST_MEMORY; |
| goto loser; |
| } |
| |
| fwToken->arena = arena; |
| fwToken->mdToken = mdToken; |
| fwToken->fwSlot = fwSlot; |
| fwToken->fwInstance = nssCKFWSlot_GetFWInstance(fwSlot); |
| fwToken->mdInstance = nssCKFWSlot_GetMDInstance(fwSlot); |
| fwToken->state = CKS_RO_PUBLIC_SESSION; /* some default */ |
| fwToken->sessionCount = 0; |
| fwToken->rwSessionCount = 0; |
| |
| fwToken->mutex = nssCKFWInstance_CreateMutex(fwToken->fwInstance, arena, pError); |
| if (!fwToken->mutex) { |
| if (CKR_OK == *pError) { |
| *pError = CKR_GENERAL_ERROR; |
| } |
| goto loser; |
| } |
| |
| fwToken->sessions = nssCKFWHash_Create(fwToken->fwInstance, arena, pError); |
| if (!fwToken->sessions) { |
| if (CKR_OK == *pError) { |
| *pError = CKR_GENERAL_ERROR; |
| } |
| goto loser; |
| } |
| |
| if (CK_TRUE != nssCKFWInstance_GetModuleHandlesSessionObjects( |
| fwToken->fwInstance)) { |
| fwToken->sessionObjectHash = nssCKFWHash_Create(fwToken->fwInstance, |
| arena, pError); |
| if (!fwToken->sessionObjectHash) { |
| if (CKR_OK == *pError) { |
| *pError = CKR_GENERAL_ERROR; |
| } |
| goto loser; |
| } |
| } |
| |
| fwToken->mdObjectHash = nssCKFWHash_Create(fwToken->fwInstance, |
| arena, pError); |
| if (!fwToken->mdObjectHash) { |
| if (CKR_OK == *pError) { |
| *pError = CKR_GENERAL_ERROR; |
| } |
| goto loser; |
| } |
| |
| fwToken->mdMechanismHash = nssCKFWHash_Create(fwToken->fwInstance, |
| arena, pError); |
| if (!fwToken->mdMechanismHash) { |
| if (CKR_OK == *pError) { |
| *pError = CKR_GENERAL_ERROR; |
| } |
| goto loser; |
| } |
| |
| /* More here */ |
| |
| if (mdToken->Setup) { |
| *pError = mdToken->Setup(mdToken, fwToken, fwToken->mdInstance, fwToken->fwInstance); |
| if (CKR_OK != *pError) { |
| goto loser; |
| } |
| } |
| |
| called_setup = CK_TRUE; |
| |
| #ifdef DEBUG |
| *pError = token_add_pointer(fwToken); |
| if (CKR_OK != *pError) { |
| goto loser; |
| } |
| #endif /* DEBUG */ |
| |
| *pError = CKR_OK; |
| return fwToken; |
| |
| loser: |
| |
| if (CK_TRUE == called_setup) { |
| if (mdToken->Invalidate) { |
| mdToken->Invalidate(mdToken, fwToken, fwToken->mdInstance, fwToken->fwInstance); |
| } |
| } |
| |
| if (arena) { |
| (void)NSSArena_Destroy(arena); |
| } |
| |
| return (NSSCKFWToken *)NULL; |
| } |
| |
| static void |
| nss_ckfwtoken_session_iterator( |
| const void *key, |
| void *value, |
| void *closure) |
| { |
| /* |
| * Remember that the fwToken->mutex is locked |
| */ |
| NSSCKFWSession *fwSession = (NSSCKFWSession *)value; |
| (void)nssCKFWSession_Destroy(fwSession, CK_FALSE); |
| return; |
| } |
| |
| static void |
| nss_ckfwtoken_object_iterator( |
| const void *key, |
| void *value, |
| void *closure) |
| { |
| /* |
| * Remember that the fwToken->mutex is locked |
| */ |
| NSSCKFWObject *fwObject = (NSSCKFWObject *)value; |
| (void)nssCKFWObject_Finalize(fwObject, CK_FALSE); |
| return; |
| } |
| |
| /* |
| * nssCKFWToken_Destroy |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_Destroy( |
| NSSCKFWToken *fwToken) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| error = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != error) { |
| return error; |
| } |
| #endif /* NSSDEBUG */ |
| |
| (void)nssCKFWMutex_Destroy(fwToken->mutex); |
| |
| if (fwToken->mdToken->Invalidate) { |
| fwToken->mdToken->Invalidate(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| /* we can destroy the list without locking now because no one else is |
| * referencing us (or _Destroy was invalidly called!) |
| */ |
| nssCKFWHash_Iterate(fwToken->sessions, nss_ckfwtoken_session_iterator, |
| (void *)NULL); |
| nssCKFWHash_Destroy(fwToken->sessions); |
| |
| /* session objects go away when their sessions are removed */ |
| if (fwToken->sessionObjectHash) { |
| nssCKFWHash_Destroy(fwToken->sessionObjectHash); |
| } |
| |
| /* free up the token objects */ |
| if (fwToken->mdObjectHash) { |
| nssCKFWHash_Iterate(fwToken->mdObjectHash, nss_ckfwtoken_object_iterator, |
| (void *)NULL); |
| nssCKFWHash_Destroy(fwToken->mdObjectHash); |
| } |
| if (fwToken->mdMechanismHash) { |
| nssCKFWHash_Destroy(fwToken->mdMechanismHash); |
| } |
| |
| nssCKFWSlot_ClearToken(fwToken->fwSlot); |
| |
| #ifdef DEBUG |
| error = token_remove_pointer(fwToken); |
| #endif /* DEBUG */ |
| |
| (void)NSSArena_Destroy(fwToken->arena); |
| return error; |
| } |
| |
| /* |
| * nssCKFWToken_GetMDToken |
| * |
| */ |
| NSS_IMPLEMENT NSSCKMDToken * |
| nssCKFWToken_GetMDToken( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (NSSCKMDToken *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| return fwToken->mdToken; |
| } |
| |
| /* |
| * nssCKFWToken_GetArena |
| * |
| */ |
| NSS_IMPLEMENT NSSArena * |
| nssCKFWToken_GetArena( |
| NSSCKFWToken *fwToken, |
| CK_RV *pError) |
| { |
| #ifdef NSSDEBUG |
| if (!pError) { |
| return (NSSArena *)NULL; |
| } |
| |
| *pError = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != *pError) { |
| return (NSSArena *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| return fwToken->arena; |
| } |
| |
| /* |
| * nssCKFWToken_GetFWSlot |
| * |
| */ |
| NSS_IMPLEMENT NSSCKFWSlot * |
| nssCKFWToken_GetFWSlot( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (NSSCKFWSlot *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| return fwToken->fwSlot; |
| } |
| |
| /* |
| * nssCKFWToken_GetMDSlot |
| * |
| */ |
| NSS_IMPLEMENT NSSCKMDSlot * |
| nssCKFWToken_GetMDSlot( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (NSSCKMDSlot *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| return fwToken->mdSlot; |
| } |
| |
| /* |
| * nssCKFWToken_GetSessionState |
| * |
| */ |
| NSS_IMPLEMENT CK_STATE |
| nssCKFWToken_GetSessionState( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CKS_RO_PUBLIC_SESSION; /* whatever */ |
| } |
| #endif /* NSSDEBUG */ |
| |
| /* |
| * BTW, do not lock the token in this method. |
| */ |
| |
| /* |
| * Theoretically, there is no state if there aren't any |
| * sessions open. But then we'd need to worry about |
| * reporting an error, etc. What the heck-- let's just |
| * revert to CKR_RO_PUBLIC_SESSION as the "default." |
| */ |
| |
| return fwToken->state; |
| } |
| |
| /* |
| * nssCKFWToken_InitToken |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_InitToken( |
| NSSCKFWToken *fwToken, |
| NSSItem *pin, |
| NSSUTF8 *label) |
| { |
| CK_RV error; |
| |
| #ifdef NSSDEBUG |
| error = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != error) { |
| return CKR_ARGUMENTS_BAD; |
| } |
| #endif /* NSSDEBUG */ |
| |
| error = nssCKFWMutex_Lock(fwToken->mutex); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| if (fwToken->sessionCount > 0) { |
| error = CKR_SESSION_EXISTS; |
| goto done; |
| } |
| |
| if (!fwToken->mdToken->InitToken) { |
| error = CKR_DEVICE_ERROR; |
| goto done; |
| } |
| |
| if (!pin) { |
| if (nssCKFWToken_GetHasProtectedAuthenticationPath(fwToken)) { |
| ; /* okay */ |
| } else { |
| error = CKR_PIN_INCORRECT; |
| goto done; |
| } |
| } |
| |
| if (!label) { |
| label = (NSSUTF8 *)""; |
| } |
| |
| error = fwToken->mdToken->InitToken(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance, pin, label); |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return error; |
| } |
| |
| /* |
| * nssCKFWToken_GetLabel |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_GetLabel( |
| NSSCKFWToken *fwToken, |
| CK_CHAR label[32]) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| if ((CK_CHAR_PTR)NULL == label) { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| error = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != error) { |
| return error; |
| } |
| #endif /* NSSDEBUG */ |
| |
| error = nssCKFWMutex_Lock(fwToken->mutex); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| if (!fwToken->label) { |
| if (fwToken->mdToken->GetLabel) { |
| fwToken->label = fwToken->mdToken->GetLabel(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance, &error); |
| if ((!fwToken->label) && (CKR_OK != error)) { |
| goto done; |
| } |
| } else { |
| fwToken->label = (NSSUTF8 *)""; |
| } |
| } |
| |
| (void)nssUTF8_CopyIntoFixedBuffer(fwToken->label, (char *)label, 32, ' '); |
| error = CKR_OK; |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return error; |
| } |
| |
| /* |
| * nssCKFWToken_GetManufacturerID |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_GetManufacturerID( |
| NSSCKFWToken *fwToken, |
| CK_CHAR manufacturerID[32]) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| if ((CK_CHAR_PTR)NULL == manufacturerID) { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| error = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != error) { |
| return error; |
| } |
| #endif /* NSSDEBUG */ |
| |
| error = nssCKFWMutex_Lock(fwToken->mutex); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| if (!fwToken->manufacturerID) { |
| if (fwToken->mdToken->GetManufacturerID) { |
| fwToken->manufacturerID = fwToken->mdToken->GetManufacturerID(fwToken->mdToken, |
| fwToken, fwToken->mdInstance, fwToken->fwInstance, &error); |
| if ((!fwToken->manufacturerID) && (CKR_OK != error)) { |
| goto done; |
| } |
| } else { |
| fwToken->manufacturerID = (NSSUTF8 *)""; |
| } |
| } |
| |
| (void)nssUTF8_CopyIntoFixedBuffer(fwToken->manufacturerID, (char *)manufacturerID, 32, ' '); |
| error = CKR_OK; |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return error; |
| } |
| |
| /* |
| * nssCKFWToken_GetModel |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_GetModel( |
| NSSCKFWToken *fwToken, |
| CK_CHAR model[16]) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| if ((CK_CHAR_PTR)NULL == model) { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| error = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != error) { |
| return error; |
| } |
| #endif /* NSSDEBUG */ |
| |
| error = nssCKFWMutex_Lock(fwToken->mutex); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| if (!fwToken->model) { |
| if (fwToken->mdToken->GetModel) { |
| fwToken->model = fwToken->mdToken->GetModel(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance, &error); |
| if ((!fwToken->model) && (CKR_OK != error)) { |
| goto done; |
| } |
| } else { |
| fwToken->model = (NSSUTF8 *)""; |
| } |
| } |
| |
| (void)nssUTF8_CopyIntoFixedBuffer(fwToken->model, (char *)model, 16, ' '); |
| error = CKR_OK; |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return error; |
| } |
| |
| /* |
| * nssCKFWToken_GetSerialNumber |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_GetSerialNumber( |
| NSSCKFWToken *fwToken, |
| CK_CHAR serialNumber[16]) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| if ((CK_CHAR_PTR)NULL == serialNumber) { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| error = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != error) { |
| return error; |
| } |
| #endif /* NSSDEBUG */ |
| |
| error = nssCKFWMutex_Lock(fwToken->mutex); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| if (!fwToken->serialNumber) { |
| if (fwToken->mdToken->GetSerialNumber) { |
| fwToken->serialNumber = fwToken->mdToken->GetSerialNumber(fwToken->mdToken, |
| fwToken, fwToken->mdInstance, fwToken->fwInstance, &error); |
| if ((!fwToken->serialNumber) && (CKR_OK != error)) { |
| goto done; |
| } |
| } else { |
| fwToken->serialNumber = (NSSUTF8 *)""; |
| } |
| } |
| |
| (void)nssUTF8_CopyIntoFixedBuffer(fwToken->serialNumber, (char *)serialNumber, 16, ' '); |
| error = CKR_OK; |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return error; |
| } |
| |
| /* |
| * nssCKFWToken_GetHasRNG |
| * |
| */ |
| NSS_IMPLEMENT CK_BBOOL |
| nssCKFWToken_GetHasRNG( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetHasRNG) { |
| return CK_FALSE; |
| } |
| |
| return fwToken->mdToken->GetHasRNG(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetIsWriteProtected |
| * |
| */ |
| NSS_IMPLEMENT CK_BBOOL |
| nssCKFWToken_GetIsWriteProtected( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetIsWriteProtected) { |
| return CK_FALSE; |
| } |
| |
| return fwToken->mdToken->GetIsWriteProtected(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetLoginRequired |
| * |
| */ |
| NSS_IMPLEMENT CK_BBOOL |
| nssCKFWToken_GetLoginRequired( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetLoginRequired) { |
| return CK_FALSE; |
| } |
| |
| return fwToken->mdToken->GetLoginRequired(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetUserPinInitialized |
| * |
| */ |
| NSS_IMPLEMENT CK_BBOOL |
| nssCKFWToken_GetUserPinInitialized( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetUserPinInitialized) { |
| return CK_FALSE; |
| } |
| |
| return fwToken->mdToken->GetUserPinInitialized(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetRestoreKeyNotNeeded |
| * |
| */ |
| NSS_IMPLEMENT CK_BBOOL |
| nssCKFWToken_GetRestoreKeyNotNeeded( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetRestoreKeyNotNeeded) { |
| return CK_FALSE; |
| } |
| |
| return fwToken->mdToken->GetRestoreKeyNotNeeded(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetHasClockOnToken |
| * |
| */ |
| NSS_IMPLEMENT CK_BBOOL |
| nssCKFWToken_GetHasClockOnToken( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetHasClockOnToken) { |
| return CK_FALSE; |
| } |
| |
| return fwToken->mdToken->GetHasClockOnToken(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetHasProtectedAuthenticationPath |
| * |
| */ |
| NSS_IMPLEMENT CK_BBOOL |
| nssCKFWToken_GetHasProtectedAuthenticationPath( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetHasProtectedAuthenticationPath) { |
| return CK_FALSE; |
| } |
| |
| return fwToken->mdToken->GetHasProtectedAuthenticationPath(fwToken->mdToken, |
| fwToken, fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetSupportsDualCryptoOperations |
| * |
| */ |
| NSS_IMPLEMENT CK_BBOOL |
| nssCKFWToken_GetSupportsDualCryptoOperations( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetSupportsDualCryptoOperations) { |
| return CK_FALSE; |
| } |
| |
| return fwToken->mdToken->GetSupportsDualCryptoOperations(fwToken->mdToken, |
| fwToken, fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetMaxSessionCount |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetMaxSessionCount( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetMaxSessionCount) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| |
| return fwToken->mdToken->GetMaxSessionCount(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetMaxRwSessionCount |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetMaxRwSessionCount( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetMaxRwSessionCount) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| |
| return fwToken->mdToken->GetMaxRwSessionCount(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetMaxPinLen |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetMaxPinLen( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetMaxPinLen) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| |
| return fwToken->mdToken->GetMaxPinLen(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetMinPinLen |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetMinPinLen( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetMinPinLen) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| |
| return fwToken->mdToken->GetMinPinLen(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetTotalPublicMemory |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetTotalPublicMemory( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetTotalPublicMemory) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| |
| return fwToken->mdToken->GetTotalPublicMemory(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetFreePublicMemory |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetFreePublicMemory( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetFreePublicMemory) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| |
| return fwToken->mdToken->GetFreePublicMemory(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetTotalPrivateMemory |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetTotalPrivateMemory( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetTotalPrivateMemory) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| |
| return fwToken->mdToken->GetTotalPrivateMemory(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetFreePrivateMemory |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetFreePrivateMemory( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetFreePrivateMemory) { |
| return CK_UNAVAILABLE_INFORMATION; |
| } |
| |
| return fwToken->mdToken->GetFreePrivateMemory(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetHardwareVersion |
| * |
| */ |
| NSS_IMPLEMENT CK_VERSION |
| nssCKFWToken_GetHardwareVersion( |
| NSSCKFWToken *fwToken) |
| { |
| CK_VERSION rv; |
| |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| rv.major = rv.minor = 0; |
| return rv; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (CKR_OK != nssCKFWMutex_Lock(fwToken->mutex)) { |
| rv.major = rv.minor = 0; |
| return rv; |
| } |
| |
| if ((0 != fwToken->hardwareVersion.major) || |
| (0 != fwToken->hardwareVersion.minor)) { |
| rv = fwToken->hardwareVersion; |
| goto done; |
| } |
| |
| if (fwToken->mdToken->GetHardwareVersion) { |
| fwToken->hardwareVersion = fwToken->mdToken->GetHardwareVersion( |
| fwToken->mdToken, fwToken, fwToken->mdInstance, fwToken->fwInstance); |
| } else { |
| fwToken->hardwareVersion.major = 0; |
| fwToken->hardwareVersion.minor = 1; |
| } |
| |
| rv = fwToken->hardwareVersion; |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return rv; |
| } |
| |
| /* |
| * nssCKFWToken_GetFirmwareVersion |
| * |
| */ |
| NSS_IMPLEMENT CK_VERSION |
| nssCKFWToken_GetFirmwareVersion( |
| NSSCKFWToken *fwToken) |
| { |
| CK_VERSION rv; |
| |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| rv.major = rv.minor = 0; |
| return rv; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (CKR_OK != nssCKFWMutex_Lock(fwToken->mutex)) { |
| rv.major = rv.minor = 0; |
| return rv; |
| } |
| |
| if ((0 != fwToken->firmwareVersion.major) || |
| (0 != fwToken->firmwareVersion.minor)) { |
| rv = fwToken->firmwareVersion; |
| goto done; |
| } |
| |
| if (fwToken->mdToken->GetFirmwareVersion) { |
| fwToken->firmwareVersion = fwToken->mdToken->GetFirmwareVersion( |
| fwToken->mdToken, fwToken, fwToken->mdInstance, fwToken->fwInstance); |
| } else { |
| fwToken->firmwareVersion.major = 0; |
| fwToken->firmwareVersion.minor = 1; |
| } |
| |
| rv = fwToken->firmwareVersion; |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return rv; |
| } |
| |
| /* |
| * nssCKFWToken_GetUTCTime |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_GetUTCTime( |
| NSSCKFWToken *fwToken, |
| CK_CHAR utcTime[16]) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| error = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| if ((CK_CHAR_PTR)NULL == utcTime) { |
| return CKR_ARGUMENTS_BAD; |
| } |
| #endif /* DEBUG */ |
| |
| if (CK_TRUE != nssCKFWToken_GetHasClockOnToken(fwToken)) { |
| /* return CKR_DEVICE_ERROR; */ |
| (void)nssUTF8_CopyIntoFixedBuffer((NSSUTF8 *)NULL, (char *)utcTime, 16, ' '); |
| return CKR_OK; |
| } |
| |
| if (!fwToken->mdToken->GetUTCTime) { |
| /* It said it had one! */ |
| return CKR_GENERAL_ERROR; |
| } |
| |
| error = fwToken->mdToken->GetUTCTime(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance, utcTime); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| /* Sanity-check the data */ |
| { |
| /* Format is YYYYMMDDhhmmss00 */ |
| int i; |
| int Y, M, D, h, m, s; |
| static int dims[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| |
| for (i = 0; i < 16; i++) { |
| if ((utcTime[i] < '0') || (utcTime[i] > '9')) { |
| goto badtime; |
| } |
| } |
| |
| Y = ((utcTime[0] - '0') * 1000) + ((utcTime[1] - '0') * 100) + |
| ((utcTime[2] - '0') * 10) + (utcTime[3] - '0'); |
| M = ((utcTime[4] - '0') * 10) + (utcTime[5] - '0'); |
| D = ((utcTime[6] - '0') * 10) + (utcTime[7] - '0'); |
| h = ((utcTime[8] - '0') * 10) + (utcTime[9] - '0'); |
| m = ((utcTime[10] - '0') * 10) + (utcTime[11] - '0'); |
| s = ((utcTime[12] - '0') * 10) + (utcTime[13] - '0'); |
| |
| if ((Y < 1990) || (Y > 3000)) |
| goto badtime; /* Y3K problem. heh heh heh */ |
| if ((M < 1) || (M > 12)) |
| goto badtime; |
| if ((D < 1) || (D > 31)) |
| goto badtime; |
| |
| if (D > dims[M - 1]) |
| goto badtime; /* per-month check */ |
| if ((2 == M) && (((Y % 4) || !(Y % 100)) && |
| (Y % 400)) && |
| (D > 28)) |
| goto badtime; /* leap years */ |
| |
| if ((h < 0) || (h > 23)) |
| goto badtime; |
| if ((m < 0) || (m > 60)) |
| goto badtime; |
| if ((s < 0) || (s > 61)) |
| goto badtime; |
| |
| /* 60m and 60 or 61s is only allowed for leap seconds. */ |
| if ((60 == m) || (s >= 60)) { |
| if ((23 != h) || (60 != m) || (s < 60)) |
| goto badtime; |
| /* leap seconds can only happen on June 30 or Dec 31.. I think */ |
| /* if( ((6 != M) || (30 != D)) && ((12 != M) || (31 != D)) ) goto badtime; */ |
| } |
| } |
| |
| return CKR_OK; |
| |
| badtime: |
| return CKR_GENERAL_ERROR; |
| } |
| |
| /* |
| * nssCKFWToken_OpenSession |
| * |
| */ |
| NSS_IMPLEMENT NSSCKFWSession * |
| nssCKFWToken_OpenSession( |
| NSSCKFWToken *fwToken, |
| CK_BBOOL rw, |
| CK_VOID_PTR pApplication, |
| CK_NOTIFY Notify, |
| CK_RV *pError) |
| { |
| NSSCKFWSession *fwSession = (NSSCKFWSession *)NULL; |
| NSSCKMDSession *mdSession; |
| |
| #ifdef NSSDEBUG |
| if (!pError) { |
| return (NSSCKFWSession *)NULL; |
| } |
| |
| *pError = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != *pError) { |
| return (NSSCKFWSession *)NULL; |
| } |
| |
| switch (rw) { |
| case CK_TRUE: |
| case CK_FALSE: |
| break; |
| default: |
| *pError = CKR_ARGUMENTS_BAD; |
| return (NSSCKFWSession *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| *pError = nssCKFWMutex_Lock(fwToken->mutex); |
| if (CKR_OK != *pError) { |
| return (NSSCKFWSession *)NULL; |
| } |
| |
| if (CK_TRUE == rw) { |
| /* Read-write session desired */ |
| if (CK_TRUE == nssCKFWToken_GetIsWriteProtected(fwToken)) { |
| *pError = CKR_TOKEN_WRITE_PROTECTED; |
| goto done; |
| } |
| } else { |
| /* Read-only session desired */ |
| if (CKS_RW_SO_FUNCTIONS == nssCKFWToken_GetSessionState(fwToken)) { |
| *pError = CKR_SESSION_READ_WRITE_SO_EXISTS; |
| goto done; |
| } |
| } |
| |
| /* We could compare sesion counts to any limits we know of, I guess.. */ |
| |
| if (!fwToken->mdToken->OpenSession) { |
| /* |
| * I'm not sure that the Module actually needs to implement |
| * mdSessions -- the Framework can keep track of everything |
| * needed, really. But I'll sort out that detail later.. |
| */ |
| *pError = CKR_GENERAL_ERROR; |
| goto done; |
| } |
| |
| fwSession = nssCKFWSession_Create(fwToken, rw, pApplication, Notify, pError); |
| if (!fwSession) { |
| if (CKR_OK == *pError) { |
| *pError = CKR_GENERAL_ERROR; |
| } |
| goto done; |
| } |
| |
| mdSession = fwToken->mdToken->OpenSession(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance, fwSession, |
| rw, pError); |
| if (!mdSession) { |
| (void)nssCKFWSession_Destroy(fwSession, CK_FALSE); |
| if (CKR_OK == *pError) { |
| *pError = CKR_GENERAL_ERROR; |
| } |
| goto done; |
| } |
| |
| *pError = nssCKFWSession_SetMDSession(fwSession, mdSession); |
| if (CKR_OK != *pError) { |
| if (mdSession->Close) { |
| mdSession->Close(mdSession, fwSession, fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| (void)nssCKFWSession_Destroy(fwSession, CK_FALSE); |
| goto done; |
| } |
| |
| *pError = nssCKFWHash_Add(fwToken->sessions, fwSession, fwSession); |
| if (CKR_OK != *pError) { |
| (void)nssCKFWSession_Destroy(fwSession, CK_FALSE); |
| fwSession = (NSSCKFWSession *)NULL; |
| goto done; |
| } |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return fwSession; |
| } |
| |
| /* |
| * nssCKFWToken_GetMechanismCount |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetMechanismCount( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return 0; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetMechanismCount) { |
| return 0; |
| } |
| |
| return fwToken->mdToken->GetMechanismCount(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| /* |
| * nssCKFWToken_GetMechanismTypes |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_GetMechanismTypes( |
| NSSCKFWToken *fwToken, |
| CK_MECHANISM_TYPE types[]) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| if (!types) { |
| return CKR_ARGUMENTS_BAD; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (!fwToken->mdToken->GetMechanismTypes) { |
| /* |
| * This should only be called with a sufficiently-large |
| * "types" array, which can only be done if GetMechanismCount |
| * is implemented. If that's implemented (and returns nonzero), |
| * then this should be too. So return an error. |
| */ |
| return CKR_GENERAL_ERROR; |
| } |
| |
| return fwToken->mdToken->GetMechanismTypes(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance, types); |
| } |
| |
| /* |
| * nssCKFWToken_GetMechanism |
| * |
| */ |
| NSS_IMPLEMENT NSSCKFWMechanism * |
| nssCKFWToken_GetMechanism( |
| NSSCKFWToken *fwToken, |
| CK_MECHANISM_TYPE which, |
| CK_RV *pError) |
| { |
| NSSCKMDMechanism *mdMechanism; |
| if (!fwToken->mdMechanismHash) { |
| *pError = CKR_GENERAL_ERROR; |
| return (NSSCKFWMechanism *)NULL; |
| } |
| |
| if (!fwToken->mdToken->GetMechanism) { |
| /* |
| * If we don't implement any GetMechanism function, then we must |
| * not support any. |
| */ |
| *pError = CKR_MECHANISM_INVALID; |
| return (NSSCKFWMechanism *)NULL; |
| } |
| |
| /* lookup in hash table */ |
| mdMechanism = fwToken->mdToken->GetMechanism(fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance, which, pError); |
| if (!mdMechanism) { |
| return (NSSCKFWMechanism *)NULL; |
| } |
| /* store in hash table */ |
| return nssCKFWMechanism_Create(mdMechanism, fwToken->mdToken, fwToken, |
| fwToken->mdInstance, fwToken->fwInstance); |
| } |
| |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_SetSessionState( |
| NSSCKFWToken *fwToken, |
| CK_STATE newState) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| error = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| switch (newState) { |
| case CKS_RO_PUBLIC_SESSION: |
| case CKS_RO_USER_FUNCTIONS: |
| case CKS_RW_PUBLIC_SESSION: |
| case CKS_RW_USER_FUNCTIONS: |
| case CKS_RW_SO_FUNCTIONS: |
| break; |
| default: |
| return CKR_ARGUMENTS_BAD; |
| } |
| #endif /* NSSDEBUG */ |
| |
| error = nssCKFWMutex_Lock(fwToken->mutex); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| fwToken->state = newState; |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return CKR_OK; |
| } |
| |
| /* |
| * nssCKFWToken_RemoveSession |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_RemoveSession( |
| NSSCKFWToken *fwToken, |
| NSSCKFWSession *fwSession) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| error = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| error = nssCKFWSession_verifyPointer(fwSession); |
| if (CKR_OK != error) { |
| return error; |
| } |
| #endif /* NSSDEBUG */ |
| |
| error = nssCKFWMutex_Lock(fwToken->mutex); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| if (CK_TRUE != nssCKFWHash_Exists(fwToken->sessions, fwSession)) { |
| error = CKR_SESSION_HANDLE_INVALID; |
| goto done; |
| } |
| |
| nssCKFWHash_Remove(fwToken->sessions, fwSession); |
| fwToken->sessionCount--; |
| |
| if (nssCKFWSession_IsRWSession(fwSession)) { |
| fwToken->rwSessionCount--; |
| } |
| |
| if (0 == fwToken->sessionCount) { |
| fwToken->rwSessionCount = 0; /* sanity */ |
| fwToken->state = CKS_RO_PUBLIC_SESSION; /* some default */ |
| } |
| |
| error = CKR_OK; |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return error; |
| } |
| |
| /* |
| * nssCKFWToken_CloseAllSessions |
| * |
| */ |
| NSS_IMPLEMENT CK_RV |
| nssCKFWToken_CloseAllSessions( |
| NSSCKFWToken *fwToken) |
| { |
| CK_RV error = CKR_OK; |
| |
| #ifdef NSSDEBUG |
| error = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != error) { |
| return error; |
| } |
| #endif /* NSSDEBUG */ |
| |
| error = nssCKFWMutex_Lock(fwToken->mutex); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| nssCKFWHash_Iterate(fwToken->sessions, nss_ckfwtoken_session_iterator, (void *)NULL); |
| |
| nssCKFWHash_Destroy(fwToken->sessions); |
| |
| fwToken->sessions = nssCKFWHash_Create(fwToken->fwInstance, fwToken->arena, &error); |
| if (!fwToken->sessions) { |
| if (CKR_OK == error) { |
| error = CKR_GENERAL_ERROR; |
| } |
| goto done; |
| } |
| |
| fwToken->state = CKS_RO_PUBLIC_SESSION; /* some default */ |
| fwToken->sessionCount = 0; |
| fwToken->rwSessionCount = 0; |
| |
| error = CKR_OK; |
| |
| done: |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return error; |
| } |
| |
| /* |
| * nssCKFWToken_GetSessionCount |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetSessionCount( |
| NSSCKFWToken *fwToken) |
| { |
| CK_ULONG rv; |
| |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (CK_ULONG)0; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (CKR_OK != nssCKFWMutex_Lock(fwToken->mutex)) { |
| return (CK_ULONG)0; |
| } |
| |
| rv = fwToken->sessionCount; |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return rv; |
| } |
| |
| /* |
| * nssCKFWToken_GetRwSessionCount |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetRwSessionCount( |
| NSSCKFWToken *fwToken) |
| { |
| CK_ULONG rv; |
| |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (CK_ULONG)0; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (CKR_OK != nssCKFWMutex_Lock(fwToken->mutex)) { |
| return (CK_ULONG)0; |
| } |
| |
| rv = fwToken->rwSessionCount; |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return rv; |
| } |
| |
| /* |
| * nssCKFWToken_GetRoSessionCount |
| * |
| */ |
| NSS_IMPLEMENT CK_ULONG |
| nssCKFWToken_GetRoSessionCount( |
| NSSCKFWToken *fwToken) |
| { |
| CK_ULONG rv; |
| |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (CK_ULONG)0; |
| } |
| #endif /* NSSDEBUG */ |
| |
| if (CKR_OK != nssCKFWMutex_Lock(fwToken->mutex)) { |
| return (CK_ULONG)0; |
| } |
| |
| rv = fwToken->sessionCount - fwToken->rwSessionCount; |
| (void)nssCKFWMutex_Unlock(fwToken->mutex); |
| return rv; |
| } |
| |
| /* |
| * nssCKFWToken_GetSessionObjectHash |
| * |
| */ |
| NSS_IMPLEMENT nssCKFWHash * |
| nssCKFWToken_GetSessionObjectHash( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (nssCKFWHash *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| return fwToken->sessionObjectHash; |
| } |
| |
| /* |
| * nssCKFWToken_GetMDObjectHash |
| * |
| */ |
| NSS_IMPLEMENT nssCKFWHash * |
| nssCKFWToken_GetMDObjectHash( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (nssCKFWHash *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| return fwToken->mdObjectHash; |
| } |
| |
| /* |
| * nssCKFWToken_GetObjectHandleHash |
| * |
| */ |
| NSS_IMPLEMENT nssCKFWHash * |
| nssCKFWToken_GetObjectHandleHash( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (nssCKFWHash *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| return fwToken->mdObjectHash; |
| } |
| |
| /* |
| * NSSCKFWToken_GetMDToken |
| * |
| */ |
| |
| NSS_IMPLEMENT NSSCKMDToken * |
| NSSCKFWToken_GetMDToken( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef DEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (NSSCKMDToken *)NULL; |
| } |
| #endif /* DEBUG */ |
| |
| return nssCKFWToken_GetMDToken(fwToken); |
| } |
| |
| /* |
| * NSSCKFWToken_GetArena |
| * |
| */ |
| |
| NSS_IMPLEMENT NSSArena * |
| NSSCKFWToken_GetArena( |
| NSSCKFWToken *fwToken, |
| CK_RV *pError) |
| { |
| #ifdef DEBUG |
| if (!pError) { |
| return (NSSArena *)NULL; |
| } |
| |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| *pError = CKR_ARGUMENTS_BAD; |
| return (NSSArena *)NULL; |
| } |
| #endif /* DEBUG */ |
| |
| return nssCKFWToken_GetArena(fwToken, pError); |
| } |
| |
| /* |
| * NSSCKFWToken_GetFWSlot |
| * |
| */ |
| |
| NSS_IMPLEMENT NSSCKFWSlot * |
| NSSCKFWToken_GetFWSlot( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef DEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (NSSCKFWSlot *)NULL; |
| } |
| #endif /* DEBUG */ |
| |
| return nssCKFWToken_GetFWSlot(fwToken); |
| } |
| |
| /* |
| * NSSCKFWToken_GetMDSlot |
| * |
| */ |
| |
| NSS_IMPLEMENT NSSCKMDSlot * |
| NSSCKFWToken_GetMDSlot( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef DEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return (NSSCKMDSlot *)NULL; |
| } |
| #endif /* DEBUG */ |
| |
| return nssCKFWToken_GetMDSlot(fwToken); |
| } |
| |
| /* |
| * NSSCKFWToken_GetSessionState |
| * |
| */ |
| |
| NSS_IMPLEMENT CK_STATE |
| NSSCKFWSession_GetSessionState( |
| NSSCKFWToken *fwToken) |
| { |
| #ifdef DEBUG |
| if (CKR_OK != nssCKFWToken_verifyPointer(fwToken)) { |
| return CKS_RO_PUBLIC_SESSION; |
| } |
| #endif /* DEBUG */ |
| |
| return nssCKFWToken_GetSessionState(fwToken); |
| } |