Mercurial > trustbridge > nss-cmake-static
view nss/lib/ckfw/token.c @ 4:b513267f632f tip
Build DBM module
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Tue, 05 Aug 2014 18:58:03 +0200 |
parents | 1e5118fa0cb1 |
children |
line wrap: on
line source
/* 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, z; 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'); z = ((utcTime[14] - '0') * 10) + (utcTime[15] - '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); }