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