tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

instance.c (31084B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /*
      6 * instance.c
      7 *
      8 * This file implements the NSSCKFWInstance type and methods.
      9 */
     10 
     11 #ifndef CK_T
     12 #include "ck.h"
     13 #endif /* CK_T */
     14 
     15 #include <stdint.h>
     16 
     17 /*
     18 * NSSCKFWInstance
     19 *
     20 *  -- create/destroy --
     21 *  nssCKFWInstance_Create
     22 *  nssCKFWInstance_Destroy
     23 *
     24 *  -- public accessors --
     25 *  NSSCKFWInstance_GetMDInstance
     26 *  NSSCKFWInstance_GetArena
     27 *  NSSCKFWInstance_MayCreatePthreads
     28 *  NSSCKFWInstance_CreateMutex
     29 *  NSSCKFWInstance_GetConfigurationData
     30 *  NSSCKFWInstance_GetInitArgs
     31 *  NSSCKFWInstance_DestroySessionHandle
     32 *  NSSCKFWInstance_FindSessionHandle
     33 *
     34 *  -- implement public accessors --
     35 *  nssCKFWInstance_GetMDInstance
     36 *  nssCKFWInstance_GetArena
     37 *  nssCKFWInstance_MayCreatePthreads
     38 *  nssCKFWInstance_CreateMutex
     39 *  nssCKFWInstance_GetConfigurationData
     40 *  nssCKFWInstance_GetInitArgs
     41 *  nssCKFWInstance_DestroySessionHandle
     42 *  nssCKFWInstance_FindSessionHandle
     43 *
     44 *  -- private accessors --
     45 *  nssCKFWInstance_CreateSessionHandle
     46 *  nssCKFWInstance_ResolveSessionHandle
     47 *  nssCKFWInstance_CreateObjectHandle
     48 *  nssCKFWInstance_ResolveObjectHandle
     49 *  nssCKFWInstance_DestroyObjectHandle
     50 *
     51 *  -- module fronts --
     52 *  nssCKFWInstance_GetNSlots
     53 *  nssCKFWInstance_GetCryptokiVersion
     54 *  nssCKFWInstance_GetManufacturerID
     55 *  nssCKFWInstance_GetFlags
     56 *  nssCKFWInstance_GetLibraryDescription
     57 *  nssCKFWInstance_GetLibraryVersion
     58 *  nssCKFWInstance_GetModuleHandlesSessionObjects
     59 *  nssCKFWInstance_GetSlots
     60 *  nssCKFWInstance_WaitForSlotEvent
     61 *
     62 *  -- debugging versions only --
     63 *  nssCKFWInstance_verifyPointer
     64 */
     65 
     66 struct NSSCKFWInstanceStr {
     67    NSSCKFWMutex *mutex;
     68    NSSArena *arena;
     69    NSSCKMDInstance *mdInstance;
     70    CK_C_INITIALIZE_ARGS_PTR pInitArgs;
     71    CK_C_INITIALIZE_ARGS initArgs;
     72    CryptokiLockingState LockingState;
     73    CK_BBOOL mayCreatePthreads;
     74    NSSUTF8 *configurationData;
     75    CK_ULONG nSlots;
     76    NSSCKFWSlot **fwSlotList;
     77    NSSCKMDSlot **mdSlotList;
     78    CK_BBOOL moduleHandlesSessionObjects;
     79 
     80    /*
     81     * Everything above is set at creation time, and then not modified.
     82     * The invariants the mutex protects are:
     83     *
     84     *  1) Each of the cached descriptions (versions, etc.) are in an
     85     *     internally consistant state.
     86     *
     87     *  2) The session handle hashes and count are consistant
     88     *
     89     *  3) The object handle hashes and count are consistant.
     90     *
     91     * I could use multiple locks, but let's wait to see if that's
     92     * really necessary.
     93     *
     94     * Note that the calls accessing the cached descriptions will
     95     * call the NSSCKMDInstance methods with the mutex locked.  Those
     96     * methods may then call the public NSSCKFWInstance routines.
     97     * Those public routines only access the constant data above, so
     98     * there's no problem.  But be careful if you add to this object;
     99     * mutexes are in general not reentrant, so don't create deadlock
    100     * situations.
    101     */
    102 
    103    CK_VERSION cryptokiVersion;
    104    NSSUTF8 *manufacturerID;
    105    NSSUTF8 *libraryDescription;
    106    CK_VERSION libraryVersion;
    107 
    108    CK_ULONG lastSessionHandle;
    109    nssCKFWHash *sessionHandleHash;
    110 
    111    CK_ULONG lastObjectHandle;
    112    nssCKFWHash *objectHandleHash;
    113 };
    114 
    115 #ifdef DEBUG
    116 /*
    117 * But first, the pointer-tracking stuff.
    118 *
    119 * NOTE: the pointer-tracking support in NSS/base currently relies
    120 * upon NSPR's CallOnce support.  That, however, relies upon NSPR's
    121 * locking, which is tied into the runtime.  We need a pointer-tracker
    122 * implementation that uses the locks supplied through C_Initialize.
    123 * That support, however, can be filled in later.  So for now, I'll
    124 * just do this routines as no-ops.
    125 */
    126 
    127 static CK_RV
    128 instance_add_pointer(
    129    const NSSCKFWInstance *fwInstance)
    130 {
    131    return CKR_OK;
    132 }
    133 
    134 static CK_RV
    135 instance_remove_pointer(
    136    const NSSCKFWInstance *fwInstance)
    137 {
    138    return CKR_OK;
    139 }
    140 
    141 NSS_IMPLEMENT CK_RV
    142 nssCKFWInstance_verifyPointer(
    143    const NSSCKFWInstance *fwInstance)
    144 {
    145    return CKR_OK;
    146 }
    147 
    148 #endif /* DEBUG */
    149 
    150 /*
    151 * nssCKFWInstance_Create
    152 *
    153 */
    154 NSS_IMPLEMENT NSSCKFWInstance *
    155 nssCKFWInstance_Create(
    156    CK_C_INITIALIZE_ARGS_PTR pInitArgs,
    157    CryptokiLockingState LockingState,
    158    NSSCKMDInstance *mdInstance,
    159    CK_RV *pError)
    160 {
    161    NSSCKFWInstance *fwInstance;
    162    NSSArena *arena = (NSSArena *)NULL;
    163    CK_ULONG i;
    164    CK_BBOOL called_Initialize = CK_FALSE;
    165 
    166 #ifdef NSSDEBUG
    167    if ((CK_RV)NULL == pError) {
    168        return (NSSCKFWInstance *)NULL;
    169    }
    170 
    171    if (!mdInstance) {
    172        *pError = CKR_ARGUMENTS_BAD;
    173        return (NSSCKFWInstance *)NULL;
    174    }
    175 #endif /* NSSDEBUG */
    176 
    177    arena = NSSArena_Create();
    178    if (!arena) {
    179        *pError = CKR_HOST_MEMORY;
    180        return (NSSCKFWInstance *)NULL;
    181    }
    182 
    183    fwInstance = nss_ZNEW(arena, NSSCKFWInstance);
    184    if (!fwInstance) {
    185        goto nomem;
    186    }
    187 
    188    fwInstance->arena = arena;
    189    fwInstance->mdInstance = mdInstance;
    190 
    191    fwInstance->LockingState = LockingState;
    192    if ((CK_C_INITIALIZE_ARGS_PTR)NULL != pInitArgs) {
    193        fwInstance->initArgs = *pInitArgs;
    194        fwInstance->pInitArgs = &fwInstance->initArgs;
    195        if (pInitArgs->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) {
    196            fwInstance->mayCreatePthreads = CK_FALSE;
    197        } else {
    198            fwInstance->mayCreatePthreads = CK_TRUE;
    199        }
    200        fwInstance->configurationData = (NSSUTF8 *)(pInitArgs->pReserved);
    201    } else {
    202        fwInstance->mayCreatePthreads = CK_TRUE;
    203    }
    204 
    205    fwInstance->mutex = nssCKFWMutex_Create(pInitArgs, LockingState, arena,
    206                                            pError);
    207    if (!fwInstance->mutex) {
    208        if (CKR_OK == *pError) {
    209            *pError = CKR_GENERAL_ERROR;
    210        }
    211        goto loser;
    212    }
    213 
    214    if (mdInstance->Initialize) {
    215        *pError = mdInstance->Initialize(mdInstance, fwInstance, fwInstance->configurationData);
    216        if (CKR_OK != *pError) {
    217            goto loser;
    218        }
    219 
    220        called_Initialize = CK_TRUE;
    221    }
    222 
    223    if (mdInstance->ModuleHandlesSessionObjects) {
    224        fwInstance->moduleHandlesSessionObjects =
    225            mdInstance->ModuleHandlesSessionObjects(mdInstance, fwInstance);
    226    } else {
    227        fwInstance->moduleHandlesSessionObjects = CK_FALSE;
    228    }
    229 
    230    if (!mdInstance->GetNSlots) {
    231        /* That routine is required */
    232        *pError = CKR_GENERAL_ERROR;
    233        goto loser;
    234    }
    235 
    236    fwInstance->nSlots = mdInstance->GetNSlots(mdInstance, fwInstance, pError);
    237    if ((CK_ULONG)0 == fwInstance->nSlots) {
    238        if (CKR_OK == *pError) {
    239            /* Zero is not a legitimate answer */
    240            *pError = CKR_GENERAL_ERROR;
    241        }
    242        goto loser;
    243    }
    244 
    245    fwInstance->fwSlotList = nss_ZNEWARRAY(arena, NSSCKFWSlot *, fwInstance->nSlots);
    246    if ((NSSCKFWSlot **)NULL == fwInstance->fwSlotList) {
    247        goto nomem;
    248    }
    249 
    250    fwInstance->mdSlotList = nss_ZNEWARRAY(arena, NSSCKMDSlot *, fwInstance->nSlots);
    251    if ((NSSCKMDSlot **)NULL == fwInstance->mdSlotList) {
    252        goto nomem;
    253    }
    254 
    255    fwInstance->sessionHandleHash = nssCKFWHash_Create(fwInstance,
    256                                                       fwInstance->arena, pError);
    257    if (!fwInstance->sessionHandleHash) {
    258        goto loser;
    259    }
    260 
    261    fwInstance->objectHandleHash = nssCKFWHash_Create(fwInstance,
    262                                                      fwInstance->arena, pError);
    263    if (!fwInstance->objectHandleHash) {
    264        goto loser;
    265    }
    266 
    267    if (!mdInstance->GetSlots) {
    268        /* That routine is required */
    269        *pError = CKR_GENERAL_ERROR;
    270        goto loser;
    271    }
    272 
    273    *pError = mdInstance->GetSlots(mdInstance, fwInstance, fwInstance->mdSlotList);
    274    if (CKR_OK != *pError) {
    275        goto loser;
    276    }
    277 
    278    for (i = 0; i < fwInstance->nSlots; i++) {
    279        NSSCKMDSlot *mdSlot = fwInstance->mdSlotList[i];
    280 
    281        if (!mdSlot) {
    282            *pError = CKR_GENERAL_ERROR;
    283            goto loser;
    284        }
    285 
    286        fwInstance->fwSlotList[i] = nssCKFWSlot_Create(fwInstance, mdSlot, i, pError);
    287        if (CKR_OK != *pError) {
    288            CK_ULONG j;
    289 
    290            for (j = 0; j < i; j++) {
    291                (void)nssCKFWSlot_Destroy(fwInstance->fwSlotList[j]);
    292            }
    293 
    294            for (j = i; j < fwInstance->nSlots; j++) {
    295                NSSCKMDSlot *mds = fwInstance->mdSlotList[j];
    296                if (mds->Destroy) {
    297                    mds->Destroy(mds, (NSSCKFWSlot *)NULL, mdInstance, fwInstance);
    298                }
    299            }
    300 
    301            goto loser;
    302        }
    303    }
    304 
    305 #ifdef DEBUG
    306    *pError = instance_add_pointer(fwInstance);
    307    if (CKR_OK != *pError) {
    308        for (i = 0; i < fwInstance->nSlots; i++) {
    309            (void)nssCKFWSlot_Destroy(fwInstance->fwSlotList[i]);
    310        }
    311 
    312        goto loser;
    313    }
    314 #endif /* DEBUG */
    315 
    316    *pError = CKR_OK;
    317    return fwInstance;
    318 
    319 nomem:
    320    *pError = CKR_HOST_MEMORY;
    321 /*FALLTHROUGH*/
    322 loser:
    323 
    324    if (CK_TRUE == called_Initialize) {
    325        if (mdInstance->Finalize) {
    326            mdInstance->Finalize(mdInstance, fwInstance);
    327        }
    328    }
    329 
    330    if (fwInstance && fwInstance->mutex) {
    331        nssCKFWMutex_Destroy(fwInstance->mutex);
    332    }
    333 
    334    if (arena) {
    335        (void)NSSArena_Destroy(arena);
    336    }
    337    return (NSSCKFWInstance *)NULL;
    338 }
    339 
    340 /*
    341 * nssCKFWInstance_Destroy
    342 *
    343 */
    344 NSS_IMPLEMENT CK_RV
    345 nssCKFWInstance_Destroy(
    346    NSSCKFWInstance *fwInstance)
    347 {
    348 #ifdef NSSDEBUG
    349    CK_RV error = CKR_OK;
    350 #endif /* NSSDEBUG */
    351    CK_ULONG i;
    352 
    353 #ifdef NSSDEBUG
    354    error = nssCKFWInstance_verifyPointer(fwInstance);
    355    if (CKR_OK != error) {
    356        return error;
    357    }
    358 #endif /* NSSDEBUG */
    359 
    360    nssCKFWMutex_Destroy(fwInstance->mutex);
    361 
    362    for (i = 0; i < fwInstance->nSlots; i++) {
    363        (void)nssCKFWSlot_Destroy(fwInstance->fwSlotList[i]);
    364    }
    365 
    366    if (fwInstance->mdInstance->Finalize) {
    367        fwInstance->mdInstance->Finalize(fwInstance->mdInstance, fwInstance);
    368    }
    369 
    370    if (fwInstance->sessionHandleHash) {
    371        nssCKFWHash_Destroy(fwInstance->sessionHandleHash);
    372    }
    373 
    374    if (fwInstance->objectHandleHash) {
    375        nssCKFWHash_Destroy(fwInstance->objectHandleHash);
    376    }
    377 
    378 #ifdef DEBUG
    379    (void)instance_remove_pointer(fwInstance);
    380 #endif /* DEBUG */
    381 
    382    (void)NSSArena_Destroy(fwInstance->arena);
    383    return CKR_OK;
    384 }
    385 
    386 /*
    387 * nssCKFWInstance_GetMDInstance
    388 *
    389 */
    390 NSS_IMPLEMENT NSSCKMDInstance *
    391 nssCKFWInstance_GetMDInstance(
    392    NSSCKFWInstance *fwInstance)
    393 {
    394 #ifdef NSSDEBUG
    395    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    396        return (NSSCKMDInstance *)NULL;
    397    }
    398 #endif /* NSSDEBUG */
    399 
    400    return fwInstance->mdInstance;
    401 }
    402 
    403 /*
    404 * nssCKFWInstance_GetArena
    405 *
    406 */
    407 NSS_IMPLEMENT NSSArena *
    408 nssCKFWInstance_GetArena(
    409    NSSCKFWInstance *fwInstance,
    410    CK_RV *pError)
    411 {
    412 #ifdef NSSDEBUG
    413    if (!pError) {
    414        return (NSSArena *)NULL;
    415    }
    416 
    417    *pError = nssCKFWInstance_verifyPointer(fwInstance);
    418    if (CKR_OK != *pError) {
    419        return (NSSArena *)NULL;
    420    }
    421 #endif /* NSSDEBUG */
    422 
    423    *pError = CKR_OK;
    424    return fwInstance->arena;
    425 }
    426 
    427 /*
    428 * nssCKFWInstance_MayCreatePthreads
    429 *
    430 */
    431 NSS_IMPLEMENT CK_BBOOL
    432 nssCKFWInstance_MayCreatePthreads(
    433    NSSCKFWInstance *fwInstance)
    434 {
    435 #ifdef NSSDEBUG
    436    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    437        return CK_FALSE;
    438    }
    439 #endif /* NSSDEBUG */
    440 
    441    return fwInstance->mayCreatePthreads;
    442 }
    443 
    444 /*
    445 * nssCKFWInstance_CreateMutex
    446 *
    447 */
    448 NSS_IMPLEMENT NSSCKFWMutex *
    449 nssCKFWInstance_CreateMutex(
    450    NSSCKFWInstance *fwInstance,
    451    NSSArena *arena,
    452    CK_RV *pError)
    453 {
    454    NSSCKFWMutex *mutex;
    455 
    456 #ifdef NSSDEBUG
    457    if (!pError) {
    458        return (NSSCKFWMutex *)NULL;
    459    }
    460 
    461    *pError = nssCKFWInstance_verifyPointer(fwInstance);
    462    if (CKR_OK != *pError) {
    463        return (NSSCKFWMutex *)NULL;
    464    }
    465 #endif /* NSSDEBUG */
    466 
    467    mutex = nssCKFWMutex_Create(fwInstance->pInitArgs, fwInstance->LockingState,
    468                                arena, pError);
    469    if (!mutex) {
    470        if (CKR_OK == *pError) {
    471            *pError = CKR_GENERAL_ERROR;
    472        }
    473 
    474        return (NSSCKFWMutex *)NULL;
    475    }
    476 
    477    return mutex;
    478 }
    479 
    480 /*
    481 * nssCKFWInstance_GetConfigurationData
    482 *
    483 */
    484 NSS_IMPLEMENT NSSUTF8 *
    485 nssCKFWInstance_GetConfigurationData(
    486    NSSCKFWInstance *fwInstance)
    487 {
    488 #ifdef NSSDEBUG
    489    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    490        return (NSSUTF8 *)NULL;
    491    }
    492 #endif /* NSSDEBUG */
    493 
    494    return fwInstance->configurationData;
    495 }
    496 
    497 /*
    498 * nssCKFWInstance_GetInitArgs
    499 *
    500 */
    501 CK_C_INITIALIZE_ARGS_PTR
    502 nssCKFWInstance_GetInitArgs(
    503    NSSCKFWInstance *fwInstance)
    504 {
    505 #ifdef NSSDEBUG
    506    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    507        return (CK_C_INITIALIZE_ARGS_PTR)NULL;
    508    }
    509 #endif /* NSSDEBUG */
    510 
    511    return fwInstance->pInitArgs;
    512 }
    513 
    514 #if defined(_MSC_VER)
    515 #pragma warning(push)
    516 #pragma warning(disable : 4312)
    517 #elif defined(__clang__) || defined(__GNUC__)
    518 #pragma GCC diagnostic push
    519 #pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
    520 #endif
    521 
    522 PR_STATIC_ASSERT(sizeof(CK_SESSION_HANDLE) <= sizeof(void *));
    523 
    524 static inline void *
    525 CKSessionHandleToVoidPtr(CK_SESSION_HANDLE handle)
    526 {
    527    return (void *)(uintptr_t)handle;
    528 }
    529 
    530 #if defined(_MSC_VER)
    531 #pragma warning(pop)
    532 #elif defined(__clang__) || defined(__GNUC__)
    533 #pragma GCC diagnostic pop
    534 #endif
    535 
    536 /*
    537 * nssCKFWInstance_CreateSessionHandle
    538 *
    539 */
    540 NSS_IMPLEMENT CK_SESSION_HANDLE
    541 nssCKFWInstance_CreateSessionHandle(
    542    NSSCKFWInstance *fwInstance,
    543    NSSCKFWSession *fwSession,
    544    CK_RV *pError)
    545 {
    546    CK_SESSION_HANDLE hSession;
    547 
    548 #ifdef NSSDEBUG
    549    if (!pError) {
    550        return (CK_SESSION_HANDLE)0;
    551    }
    552 
    553    *pError = nssCKFWInstance_verifyPointer(fwInstance);
    554    if (CKR_OK != *pError) {
    555        return (CK_SESSION_HANDLE)0;
    556    }
    557 #endif /* NSSDEBUG */
    558 
    559    *pError = nssCKFWMutex_Lock(fwInstance->mutex);
    560    if (CKR_OK != *pError) {
    561        return (CK_SESSION_HANDLE)0;
    562    }
    563 
    564    hSession = ++(fwInstance->lastSessionHandle);
    565 
    566    /* Alan would say I should unlock for this call. */
    567 
    568    *pError = nssCKFWSession_SetHandle(fwSession, hSession);
    569    if (CKR_OK != *pError) {
    570        goto done;
    571    }
    572 
    573    *pError = nssCKFWHash_Add(fwInstance->sessionHandleHash,
    574                              CKSessionHandleToVoidPtr(hSession), (const void *)fwSession);
    575    if (CKR_OK != *pError) {
    576        hSession = (CK_SESSION_HANDLE)0;
    577        goto done;
    578    }
    579 
    580 done:
    581    nssCKFWMutex_Unlock(fwInstance->mutex);
    582    return hSession;
    583 }
    584 
    585 /*
    586 * nssCKFWInstance_ResolveSessionHandle
    587 *
    588 */
    589 NSS_IMPLEMENT NSSCKFWSession *
    590 nssCKFWInstance_ResolveSessionHandle(
    591    NSSCKFWInstance *fwInstance,
    592    CK_SESSION_HANDLE hSession)
    593 {
    594    NSSCKFWSession *fwSession;
    595 
    596 #ifdef NSSDEBUG
    597    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    598        return (NSSCKFWSession *)NULL;
    599    }
    600 #endif /* NSSDEBUG */
    601 
    602    if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
    603        return (NSSCKFWSession *)NULL;
    604    }
    605 
    606    fwSession = (NSSCKFWSession *)nssCKFWHash_Lookup(
    607        fwInstance->sessionHandleHash, CKSessionHandleToVoidPtr(hSession));
    608 
    609    /* Assert(hSession == nssCKFWSession_GetHandle(fwSession)) */
    610 
    611    (void)nssCKFWMutex_Unlock(fwInstance->mutex);
    612 
    613    return fwSession;
    614 }
    615 
    616 /*
    617 * nssCKFWInstance_DestroySessionHandle
    618 *
    619 */
    620 NSS_IMPLEMENT void
    621 nssCKFWInstance_DestroySessionHandle(
    622    NSSCKFWInstance *fwInstance,
    623    CK_SESSION_HANDLE hSession)
    624 {
    625    NSSCKFWSession *fwSession;
    626 
    627 #ifdef NSSDEBUG
    628    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    629        return;
    630    }
    631 #endif /* NSSDEBUG */
    632 
    633    if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
    634        return;
    635    }
    636 
    637    fwSession = (NSSCKFWSession *)nssCKFWHash_Lookup(
    638        fwInstance->sessionHandleHash, CKSessionHandleToVoidPtr(hSession));
    639    if (fwSession) {
    640        nssCKFWHash_Remove(fwInstance->sessionHandleHash, CKSessionHandleToVoidPtr(hSession));
    641        nssCKFWSession_SetHandle(fwSession, (CK_SESSION_HANDLE)0);
    642    }
    643 
    644    (void)nssCKFWMutex_Unlock(fwInstance->mutex);
    645 
    646    return;
    647 }
    648 
    649 /*
    650 * nssCKFWInstance_FindSessionHandle
    651 *
    652 */
    653 NSS_IMPLEMENT CK_SESSION_HANDLE
    654 nssCKFWInstance_FindSessionHandle(
    655    NSSCKFWInstance *fwInstance,
    656    NSSCKFWSession *fwSession)
    657 {
    658 #ifdef NSSDEBUG
    659    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    660        return (CK_SESSION_HANDLE)0;
    661    }
    662 
    663    if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
    664        return (CK_SESSION_HANDLE)0;
    665    }
    666 #endif /* NSSDEBUG */
    667 
    668    return nssCKFWSession_GetHandle(fwSession);
    669    /* look it up and assert? */
    670 }
    671 
    672 /*
    673 * nssCKFWInstance_CreateObjectHandle
    674 *
    675 */
    676 NSS_IMPLEMENT CK_OBJECT_HANDLE
    677 nssCKFWInstance_CreateObjectHandle(
    678    NSSCKFWInstance *fwInstance,
    679    NSSCKFWObject *fwObject,
    680    CK_RV *pError)
    681 {
    682    CK_OBJECT_HANDLE hObject;
    683 
    684 #ifdef NSSDEBUG
    685    if (!pError) {
    686        return (CK_OBJECT_HANDLE)0;
    687    }
    688 
    689    *pError = nssCKFWInstance_verifyPointer(fwInstance);
    690    if (CKR_OK != *pError) {
    691        return (CK_OBJECT_HANDLE)0;
    692    }
    693 #endif /* NSSDEBUG */
    694 
    695    *pError = nssCKFWMutex_Lock(fwInstance->mutex);
    696    if (CKR_OK != *pError) {
    697        return (CK_OBJECT_HANDLE)0;
    698    }
    699 
    700    hObject = ++(fwInstance->lastObjectHandle);
    701 
    702    *pError = nssCKFWObject_SetHandle(fwObject, hObject);
    703    if (CKR_OK != *pError) {
    704        hObject = (CK_OBJECT_HANDLE)0;
    705        goto done;
    706    }
    707 
    708    *pError = nssCKFWHash_Add(fwInstance->objectHandleHash,
    709                              CKSessionHandleToVoidPtr(hObject), (const void *)fwObject);
    710    if (CKR_OK != *pError) {
    711        hObject = (CK_OBJECT_HANDLE)0;
    712        goto done;
    713    }
    714 
    715 done:
    716    (void)nssCKFWMutex_Unlock(fwInstance->mutex);
    717    return hObject;
    718 }
    719 
    720 /*
    721 * nssCKFWInstance_ResolveObjectHandle
    722 *
    723 */
    724 NSS_IMPLEMENT NSSCKFWObject *
    725 nssCKFWInstance_ResolveObjectHandle(
    726    NSSCKFWInstance *fwInstance,
    727    CK_OBJECT_HANDLE hObject)
    728 {
    729    NSSCKFWObject *fwObject;
    730 
    731 #ifdef NSSDEBUG
    732    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    733        return (NSSCKFWObject *)NULL;
    734    }
    735 #endif /* NSSDEBUG */
    736 
    737    if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
    738        return (NSSCKFWObject *)NULL;
    739    }
    740 
    741    fwObject = (NSSCKFWObject *)nssCKFWHash_Lookup(
    742        fwInstance->objectHandleHash, CKSessionHandleToVoidPtr(hObject));
    743 
    744    /* Assert(hObject == nssCKFWObject_GetHandle(fwObject)) */
    745 
    746    (void)nssCKFWMutex_Unlock(fwInstance->mutex);
    747    return fwObject;
    748 }
    749 
    750 /*
    751 * nssCKFWInstance_ReassignObjectHandle
    752 *
    753 */
    754 NSS_IMPLEMENT CK_RV
    755 nssCKFWInstance_ReassignObjectHandle(
    756    NSSCKFWInstance *fwInstance,
    757    CK_OBJECT_HANDLE hObject,
    758    NSSCKFWObject *fwObject)
    759 {
    760    CK_RV error = CKR_OK;
    761    NSSCKFWObject *oldObject;
    762 
    763 #ifdef NSSDEBUG
    764    error = nssCKFWInstance_verifyPointer(fwInstance);
    765    if (CKR_OK != error) {
    766        return error;
    767    }
    768 #endif /* NSSDEBUG */
    769 
    770    error = nssCKFWMutex_Lock(fwInstance->mutex);
    771    if (CKR_OK != error) {
    772        return error;
    773    }
    774 
    775    oldObject = (NSSCKFWObject *)nssCKFWHash_Lookup(
    776        fwInstance->objectHandleHash, CKSessionHandleToVoidPtr(hObject));
    777    if (oldObject) {
    778        /* Assert(hObject == nssCKFWObject_GetHandle(oldObject) */
    779        (void)nssCKFWObject_SetHandle(oldObject, (CK_SESSION_HANDLE)0);
    780        nssCKFWHash_Remove(fwInstance->objectHandleHash, CKSessionHandleToVoidPtr(hObject));
    781    }
    782 
    783    error = nssCKFWObject_SetHandle(fwObject, hObject);
    784    if (CKR_OK != error) {
    785        goto done;
    786    }
    787    error = nssCKFWHash_Add(fwInstance->objectHandleHash,
    788                            CKSessionHandleToVoidPtr(hObject), (const void *)fwObject);
    789 
    790 done:
    791    (void)nssCKFWMutex_Unlock(fwInstance->mutex);
    792    return error;
    793 }
    794 
    795 /*
    796 * nssCKFWInstance_DestroyObjectHandle
    797 *
    798 */
    799 NSS_IMPLEMENT void
    800 nssCKFWInstance_DestroyObjectHandle(
    801    NSSCKFWInstance *fwInstance,
    802    CK_OBJECT_HANDLE hObject)
    803 {
    804    NSSCKFWObject *fwObject;
    805 
    806 #ifdef NSSDEBUG
    807    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    808        return;
    809    }
    810 #endif /* NSSDEBUG */
    811 
    812    if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
    813        return;
    814    }
    815 
    816    fwObject = (NSSCKFWObject *)nssCKFWHash_Lookup(
    817        fwInstance->objectHandleHash, CKSessionHandleToVoidPtr(hObject));
    818    if (fwObject) {
    819        /* Assert(hObject == nssCKFWObject_GetHandle(fwObject)) */
    820        nssCKFWHash_Remove(fwInstance->objectHandleHash, CKSessionHandleToVoidPtr(hObject));
    821        (void)nssCKFWObject_SetHandle(fwObject, (CK_SESSION_HANDLE)0);
    822    }
    823 
    824    (void)nssCKFWMutex_Unlock(fwInstance->mutex);
    825    return;
    826 }
    827 
    828 /*
    829 * nssCKFWInstance_FindObjectHandle
    830 *
    831 */
    832 NSS_IMPLEMENT CK_OBJECT_HANDLE
    833 nssCKFWInstance_FindObjectHandle(
    834    NSSCKFWInstance *fwInstance,
    835    NSSCKFWObject *fwObject)
    836 {
    837 #ifdef NSSDEBUG
    838    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    839        return (CK_OBJECT_HANDLE)0;
    840    }
    841 
    842    if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
    843        return (CK_OBJECT_HANDLE)0;
    844    }
    845 #endif /* NSSDEBUG */
    846 
    847    return nssCKFWObject_GetHandle(fwObject);
    848 }
    849 
    850 /*
    851 * nssCKFWInstance_GetNSlots
    852 *
    853 */
    854 NSS_IMPLEMENT CK_ULONG
    855 nssCKFWInstance_GetNSlots(
    856    NSSCKFWInstance *fwInstance,
    857    CK_RV *pError)
    858 {
    859 #ifdef NSSDEBUG
    860    if (!pError) {
    861        return (CK_ULONG)0;
    862    }
    863 
    864    *pError = nssCKFWInstance_verifyPointer(fwInstance);
    865    if (CKR_OK != *pError) {
    866        return (CK_ULONG)0;
    867    }
    868 #endif /* NSSDEBUG */
    869 
    870    *pError = CKR_OK;
    871    return fwInstance->nSlots;
    872 }
    873 
    874 /*
    875 * nssCKFWInstance_GetCryptokiVersion
    876 *
    877 */
    878 NSS_IMPLEMENT CK_VERSION
    879 nssCKFWInstance_GetCryptokiVersion(
    880    NSSCKFWInstance *fwInstance)
    881 {
    882    CK_VERSION rv;
    883 
    884 #ifdef NSSDEBUG
    885    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    886        rv.major = rv.minor = 0;
    887        return rv;
    888    }
    889 #endif /* NSSDEBUG */
    890 
    891    if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
    892        rv.major = rv.minor = 0;
    893        return rv;
    894    }
    895 
    896    if ((0 != fwInstance->cryptokiVersion.major) ||
    897        (0 != fwInstance->cryptokiVersion.minor)) {
    898        rv = fwInstance->cryptokiVersion;
    899        goto done;
    900    }
    901 
    902    if (fwInstance->mdInstance->GetCryptokiVersion) {
    903        fwInstance->cryptokiVersion = fwInstance->mdInstance->GetCryptokiVersion(
    904            fwInstance->mdInstance, fwInstance);
    905    } else {
    906        fwInstance->cryptokiVersion.major = 2;
    907        fwInstance->cryptokiVersion.minor = 1;
    908    }
    909 
    910    rv = fwInstance->cryptokiVersion;
    911 
    912 done:
    913    (void)nssCKFWMutex_Unlock(fwInstance->mutex);
    914    return rv;
    915 }
    916 
    917 /*
    918 * nssCKFWInstance_GetManufacturerID
    919 *
    920 */
    921 NSS_IMPLEMENT CK_RV
    922 nssCKFWInstance_GetManufacturerID(
    923    NSSCKFWInstance *fwInstance,
    924    CK_CHAR manufacturerID[32])
    925 {
    926    CK_RV error = CKR_OK;
    927 
    928 #ifdef NSSDEBUG
    929    if ((CK_CHAR_PTR)NULL == manufacturerID) {
    930        return CKR_ARGUMENTS_BAD;
    931    }
    932 
    933    error = nssCKFWInstance_verifyPointer(fwInstance);
    934    if (CKR_OK != error) {
    935        return error;
    936    }
    937 #endif /* NSSDEBUG */
    938 
    939    error = nssCKFWMutex_Lock(fwInstance->mutex);
    940    if (CKR_OK != error) {
    941        return error;
    942    }
    943 
    944    if (!fwInstance->manufacturerID) {
    945        if (fwInstance->mdInstance->GetManufacturerID) {
    946            fwInstance->manufacturerID = fwInstance->mdInstance->GetManufacturerID(
    947                fwInstance->mdInstance, fwInstance, &error);
    948            if ((!fwInstance->manufacturerID) && (CKR_OK != error)) {
    949                goto done;
    950            }
    951        } else {
    952            fwInstance->manufacturerID = (NSSUTF8 *)"";
    953        }
    954    }
    955 
    956    (void)nssUTF8_CopyIntoFixedBuffer(fwInstance->manufacturerID, (char *)manufacturerID, 32, ' ');
    957    error = CKR_OK;
    958 
    959 done:
    960    (void)nssCKFWMutex_Unlock(fwInstance->mutex);
    961    return error;
    962 }
    963 
    964 /*
    965 * nssCKFWInstance_GetFlags
    966 *
    967 */
    968 NSS_IMPLEMENT CK_ULONG
    969 nssCKFWInstance_GetFlags(
    970    NSSCKFWInstance *fwInstance)
    971 {
    972 #ifdef NSSDEBUG
    973    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
    974        return (CK_ULONG)0;
    975    }
    976 #endif /* NSSDEBUG */
    977 
    978    /* No "instance flags" are yet defined by Cryptoki. */
    979    return (CK_ULONG)0;
    980 }
    981 
    982 /*
    983 * nssCKFWInstance_GetLibraryDescription
    984 *
    985 */
    986 NSS_IMPLEMENT CK_RV
    987 nssCKFWInstance_GetLibraryDescription(
    988    NSSCKFWInstance *fwInstance,
    989    CK_CHAR libraryDescription[32])
    990 {
    991    CK_RV error = CKR_OK;
    992 
    993 #ifdef NSSDEBUG
    994    if ((CK_CHAR_PTR)NULL == libraryDescription) {
    995        return CKR_ARGUMENTS_BAD;
    996    }
    997 
    998    error = nssCKFWInstance_verifyPointer(fwInstance);
    999    if (CKR_OK != error) {
   1000        return error;
   1001    }
   1002 #endif /* NSSDEBUG */
   1003 
   1004    error = nssCKFWMutex_Lock(fwInstance->mutex);
   1005    if (CKR_OK != error) {
   1006        return error;
   1007    }
   1008 
   1009    if (!fwInstance->libraryDescription) {
   1010        if (fwInstance->mdInstance->GetLibraryDescription) {
   1011            fwInstance->libraryDescription = fwInstance->mdInstance->GetLibraryDescription(
   1012                fwInstance->mdInstance, fwInstance, &error);
   1013            if ((!fwInstance->libraryDescription) && (CKR_OK != error)) {
   1014                goto done;
   1015            }
   1016        } else {
   1017            fwInstance->libraryDescription = (NSSUTF8 *)"";
   1018        }
   1019    }
   1020 
   1021    (void)nssUTF8_CopyIntoFixedBuffer(fwInstance->libraryDescription, (char *)libraryDescription, 32, ' ');
   1022    error = CKR_OK;
   1023 
   1024 done:
   1025    (void)nssCKFWMutex_Unlock(fwInstance->mutex);
   1026    return error;
   1027 }
   1028 
   1029 /*
   1030 * nssCKFWInstance_GetLibraryVersion
   1031 *
   1032 */
   1033 NSS_IMPLEMENT CK_VERSION
   1034 nssCKFWInstance_GetLibraryVersion(
   1035    NSSCKFWInstance *fwInstance)
   1036 {
   1037    CK_VERSION rv;
   1038 
   1039 #ifdef NSSDEBUG
   1040    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
   1041        rv.major = rv.minor = 0;
   1042        return rv;
   1043    }
   1044 #endif /* NSSDEBUG */
   1045 
   1046    if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
   1047        rv.major = rv.minor = 0;
   1048        return rv;
   1049    }
   1050 
   1051    if ((0 != fwInstance->libraryVersion.major) ||
   1052        (0 != fwInstance->libraryVersion.minor)) {
   1053        rv = fwInstance->libraryVersion;
   1054        goto done;
   1055    }
   1056 
   1057    if (fwInstance->mdInstance->GetLibraryVersion) {
   1058        fwInstance->libraryVersion = fwInstance->mdInstance->GetLibraryVersion(
   1059            fwInstance->mdInstance, fwInstance);
   1060    } else {
   1061        fwInstance->libraryVersion.major = 0;
   1062        fwInstance->libraryVersion.minor = 3;
   1063    }
   1064 
   1065    rv = fwInstance->libraryVersion;
   1066 done:
   1067    (void)nssCKFWMutex_Unlock(fwInstance->mutex);
   1068    return rv;
   1069 }
   1070 
   1071 /*
   1072 * nssCKFWInstance_GetModuleHandlesSessionObjects
   1073 *
   1074 */
   1075 NSS_IMPLEMENT CK_BBOOL
   1076 nssCKFWInstance_GetModuleHandlesSessionObjects(
   1077    NSSCKFWInstance *fwInstance)
   1078 {
   1079 #ifdef NSSDEBUG
   1080    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
   1081        return CK_FALSE;
   1082    }
   1083 #endif /* NSSDEBUG */
   1084 
   1085    return fwInstance->moduleHandlesSessionObjects;
   1086 }
   1087 
   1088 /*
   1089 * nssCKFWInstance_GetSlots
   1090 *
   1091 */
   1092 NSS_IMPLEMENT NSSCKFWSlot **
   1093 nssCKFWInstance_GetSlots(
   1094    NSSCKFWInstance *fwInstance,
   1095    CK_RV *pError)
   1096 {
   1097 #ifdef NSSDEBUG
   1098    if (!pError) {
   1099        return (NSSCKFWSlot **)NULL;
   1100    }
   1101 
   1102    *pError = nssCKFWInstance_verifyPointer(fwInstance);
   1103    if (CKR_OK != *pError) {
   1104        return (NSSCKFWSlot **)NULL;
   1105    }
   1106 #endif /* NSSDEBUG */
   1107 
   1108    return fwInstance->fwSlotList;
   1109 }
   1110 
   1111 /*
   1112 * nssCKFWInstance_WaitForSlotEvent
   1113 *
   1114 */
   1115 NSS_IMPLEMENT NSSCKFWSlot *
   1116 nssCKFWInstance_WaitForSlotEvent(
   1117    NSSCKFWInstance *fwInstance,
   1118    CK_BBOOL block,
   1119    CK_RV *pError)
   1120 {
   1121    NSSCKFWSlot *fwSlot = (NSSCKFWSlot *)NULL;
   1122    NSSCKMDSlot *mdSlot;
   1123    CK_ULONG i, n;
   1124 
   1125 #ifdef NSSDEBUG
   1126    if (!pError) {
   1127        return (NSSCKFWSlot *)NULL;
   1128    }
   1129 
   1130    *pError = nssCKFWInstance_verifyPointer(fwInstance);
   1131    if (CKR_OK != *pError) {
   1132        return (NSSCKFWSlot *)NULL;
   1133    }
   1134 
   1135    switch (block) {
   1136        case CK_TRUE:
   1137        case CK_FALSE:
   1138            break;
   1139        default:
   1140            *pError = CKR_ARGUMENTS_BAD;
   1141            return (NSSCKFWSlot *)NULL;
   1142    }
   1143 #endif /* NSSDEBUG */
   1144 
   1145    if (!fwInstance->mdInstance->WaitForSlotEvent) {
   1146        *pError = CKR_NO_EVENT;
   1147        return (NSSCKFWSlot *)NULL;
   1148    }
   1149 
   1150    mdSlot = fwInstance->mdInstance->WaitForSlotEvent(
   1151        fwInstance->mdInstance,
   1152        fwInstance,
   1153        block,
   1154        pError);
   1155 
   1156    if (!mdSlot) {
   1157        return (NSSCKFWSlot *)NULL;
   1158    }
   1159 
   1160    n = nssCKFWInstance_GetNSlots(fwInstance, pError);
   1161    if (((CK_ULONG)0 == n) && (CKR_OK != *pError)) {
   1162        return (NSSCKFWSlot *)NULL;
   1163    }
   1164 
   1165    for (i = 0; i < n; i++) {
   1166        if (fwInstance->mdSlotList[i] == mdSlot) {
   1167            fwSlot = fwInstance->fwSlotList[i];
   1168            break;
   1169        }
   1170    }
   1171 
   1172    if (!fwSlot) {
   1173        /* Internal error */
   1174        *pError = CKR_GENERAL_ERROR;
   1175        return (NSSCKFWSlot *)NULL;
   1176    }
   1177 
   1178    return fwSlot;
   1179 }
   1180 
   1181 /*
   1182 * NSSCKFWInstance_GetMDInstance
   1183 *
   1184 */
   1185 NSS_IMPLEMENT NSSCKMDInstance *
   1186 NSSCKFWInstance_GetMDInstance(
   1187    NSSCKFWInstance *fwInstance)
   1188 {
   1189 #ifdef DEBUG
   1190    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
   1191        return (NSSCKMDInstance *)NULL;
   1192    }
   1193 #endif /* DEBUG */
   1194 
   1195    return nssCKFWInstance_GetMDInstance(fwInstance);
   1196 }
   1197 
   1198 /*
   1199 * NSSCKFWInstance_GetArena
   1200 *
   1201 */
   1202 NSS_IMPLEMENT NSSArena *
   1203 NSSCKFWInstance_GetArena(
   1204    NSSCKFWInstance *fwInstance,
   1205    CK_RV *pError)
   1206 {
   1207 #ifdef DEBUG
   1208    if (!pError) {
   1209        return (NSSArena *)NULL;
   1210    }
   1211 
   1212    *pError = nssCKFWInstance_verifyPointer(fwInstance);
   1213    if (CKR_OK != *pError) {
   1214        return (NSSArena *)NULL;
   1215    }
   1216 #endif /* DEBUG */
   1217 
   1218    return nssCKFWInstance_GetArena(fwInstance, pError);
   1219 }
   1220 
   1221 /*
   1222 * NSSCKFWInstance_MayCreatePthreads
   1223 *
   1224 */
   1225 NSS_IMPLEMENT CK_BBOOL
   1226 NSSCKFWInstance_MayCreatePthreads(
   1227    NSSCKFWInstance *fwInstance)
   1228 {
   1229 #ifdef DEBUG
   1230    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
   1231        return CK_FALSE;
   1232    }
   1233 #endif /* DEBUG */
   1234 
   1235    return nssCKFWInstance_MayCreatePthreads(fwInstance);
   1236 }
   1237 
   1238 /*
   1239 * NSSCKFWInstance_CreateMutex
   1240 *
   1241 */
   1242 NSS_IMPLEMENT NSSCKFWMutex *
   1243 NSSCKFWInstance_CreateMutex(
   1244    NSSCKFWInstance *fwInstance,
   1245    NSSArena *arena,
   1246    CK_RV *pError)
   1247 {
   1248 #ifdef DEBUG
   1249    if (!pError) {
   1250        return (NSSCKFWMutex *)NULL;
   1251    }
   1252 
   1253    *pError = nssCKFWInstance_verifyPointer(fwInstance);
   1254    if (CKR_OK != *pError) {
   1255        return (NSSCKFWMutex *)NULL;
   1256    }
   1257 #endif /* DEBUG */
   1258 
   1259    return nssCKFWInstance_CreateMutex(fwInstance, arena, pError);
   1260 }
   1261 
   1262 /*
   1263 * NSSCKFWInstance_GetConfigurationData
   1264 *
   1265 */
   1266 NSS_IMPLEMENT NSSUTF8 *
   1267 NSSCKFWInstance_GetConfigurationData(
   1268    NSSCKFWInstance *fwInstance)
   1269 {
   1270 #ifdef DEBUG
   1271    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
   1272        return (NSSUTF8 *)NULL;
   1273    }
   1274 #endif /* DEBUG */
   1275 
   1276    return nssCKFWInstance_GetConfigurationData(fwInstance);
   1277 }
   1278 
   1279 /*
   1280 * NSSCKFWInstance_GetInitArgs
   1281 *
   1282 */
   1283 NSS_IMPLEMENT CK_C_INITIALIZE_ARGS_PTR
   1284 NSSCKFWInstance_GetInitArgs(
   1285    NSSCKFWInstance *fwInstance)
   1286 {
   1287 #ifdef DEBUG
   1288    if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
   1289        return (CK_C_INITIALIZE_ARGS_PTR)NULL;
   1290    }
   1291 #endif /* DEBUG */
   1292 
   1293    return nssCKFWInstance_GetInitArgs(fwInstance);
   1294 }
   1295 
   1296 /*
   1297 * nssCKFWInstance_DestroySessionHandle
   1298 *
   1299 */
   1300 NSS_IMPLEMENT void
   1301 NSSCKFWInstance_DestroySessionHandle(
   1302    NSSCKFWInstance *fwInstance,
   1303    CK_SESSION_HANDLE hSession)
   1304 {
   1305    nssCKFWInstance_DestroySessionHandle(fwInstance, hSession);
   1306 }
   1307 
   1308 /*
   1309 * nssCKFWInstance_FindSessionHandle
   1310 *
   1311 */
   1312 NSS_IMPLEMENT CK_SESSION_HANDLE
   1313 NSSCKFWInstance_FindSessionHandle(
   1314    NSSCKFWInstance *fwInstance,
   1315    NSSCKFWSession *fwSession)
   1316 {
   1317    return nssCKFWInstance_FindSessionHandle(fwInstance, fwSession);
   1318 }