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