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