Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/lib/ckfw/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 41 kB image not shown  

Quelle  token.c   Sprache: 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);
}

Messung V0.5
C=93 H=83 G=87

¤ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.