tor-browser

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

object.c (24107B)


      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 * object.c
      7 *
      8 * This file implements the NSSCKFWObject type and methods.
      9 */
     10 
     11 #ifndef CK_T
     12 #include "ck.h"
     13 #endif /* CK_T */
     14 
     15 /*
     16 * NSSCKFWObject
     17 *
     18 * -- create/destroy --
     19 *  nssCKFWObject_Create
     20 *  nssCKFWObject_Finalize
     21 *  nssCKFWObject_Destroy
     22 *
     23 * -- public accessors --
     24 *  NSSCKFWObject_GetMDObject
     25 *  NSSCKFWObject_GetArena
     26 *  NSSCKFWObject_IsTokenObject
     27 *  NSSCKFWObject_GetAttributeCount
     28 *  NSSCKFWObject_GetAttributeTypes
     29 *  NSSCKFWObject_GetAttributeSize
     30 *  NSSCKFWObject_GetAttribute
     31 *  NSSCKFWObject_SetAttribute
     32 *  NSSCKFWObject_GetObjectSize
     33 *
     34 * -- implement public accessors --
     35 *  nssCKFWObject_GetMDObject
     36 *  nssCKFWObject_GetArena
     37 *
     38 * -- private accessors --
     39 *  nssCKFWObject_SetHandle
     40 *  nssCKFWObject_GetHandle
     41 *
     42 * -- module fronts --
     43 *  nssCKFWObject_IsTokenObject
     44 *  nssCKFWObject_GetAttributeCount
     45 *  nssCKFWObject_GetAttributeTypes
     46 *  nssCKFWObject_GetAttributeSize
     47 *  nssCKFWObject_GetAttribute
     48 *  nssCKFWObject_SetAttribute
     49 *  nssCKFWObject_GetObjectSize
     50 */
     51 
     52 struct NSSCKFWObjectStr {
     53    NSSCKFWMutex *mutex; /* merely to serialise the MDObject calls */
     54    NSSArena *arena;
     55    NSSArena *localArena;
     56    NSSCKMDObject *mdObject;
     57    NSSCKMDSession *mdSession;
     58    NSSCKFWSession *fwSession;
     59    NSSCKMDToken *mdToken;
     60    NSSCKFWToken *fwToken;
     61    NSSCKMDInstance *mdInstance;
     62    NSSCKFWInstance *fwInstance;
     63    CK_OBJECT_HANDLE hObject;
     64 };
     65 
     66 #ifdef DEBUG
     67 /*
     68 * But first, the pointer-tracking stuff.
     69 *
     70 * NOTE: the pointer-tracking support in NSS/base currently relies
     71 * upon NSPR's CallOnce support.  That, however, relies upon NSPR's
     72 * locking, which is tied into the runtime.  We need a pointer-tracker
     73 * implementation that uses the locks supplied through C_Initialize.
     74 * That support, however, can be filled in later.  So for now, I'll
     75 * just do this routines as no-ops.
     76 */
     77 
     78 static CK_RV
     79 object_add_pointer(
     80    const NSSCKFWObject *fwObject)
     81 {
     82    return CKR_OK;
     83 }
     84 
     85 static CK_RV
     86 object_remove_pointer(
     87    const NSSCKFWObject *fwObject)
     88 {
     89    return CKR_OK;
     90 }
     91 
     92 NSS_IMPLEMENT CK_RV
     93 nssCKFWObject_verifyPointer(
     94    const NSSCKFWObject *fwObject)
     95 {
     96    return CKR_OK;
     97 }
     98 
     99 #endif /* DEBUG */
    100 
    101 /*
    102 * nssCKFWObject_Create
    103 *
    104 */
    105 NSS_IMPLEMENT NSSCKFWObject *
    106 nssCKFWObject_Create(
    107    NSSArena *arena,
    108    NSSCKMDObject *mdObject,
    109    NSSCKFWSession *fwSession,
    110    NSSCKFWToken *fwToken,
    111    NSSCKFWInstance *fwInstance,
    112    CK_RV *pError)
    113 {
    114    NSSArena *objArena = arena;
    115    NSSArena *localArena = NULL;
    116    NSSCKFWObject *fwObject;
    117    nssCKFWHash *mdObjectHash;
    118 
    119 #ifdef NSSDEBUG
    120    if (!pError) {
    121        return (NSSCKFWObject *)NULL;
    122    }
    123 
    124    if (PR_SUCCESS != nssArena_verifyPointer(arena)) {
    125        *pError = CKR_ARGUMENTS_BAD;
    126        return (NSSCKFWObject *)NULL;
    127    }
    128 #endif /* NSSDEBUG */
    129 
    130    if (!fwToken) {
    131        *pError = CKR_ARGUMENTS_BAD;
    132        return (NSSCKFWObject *)NULL;
    133    }
    134    mdObjectHash = nssCKFWToken_GetMDObjectHash(fwToken);
    135    if (!mdObjectHash) {
    136        *pError = CKR_GENERAL_ERROR;
    137        return (NSSCKFWObject *)NULL;
    138    }
    139 
    140    if (nssCKFWHash_Exists(mdObjectHash, mdObject)) {
    141        fwObject = nssCKFWHash_Lookup(mdObjectHash, mdObject);
    142        return fwObject;
    143    }
    144 
    145    /* session objects should have their own arena so they can be destroyed in the end. */
    146    if (arena == NULL) {
    147        localArena = objArena = NSSArena_Create();
    148        if (objArena == NULL) {
    149            *pError = CKR_HOST_MEMORY;
    150            return (NSSCKFWObject *)NULL;
    151        }
    152    }
    153 
    154    fwObject = nss_ZNEW(objArena, NSSCKFWObject);
    155    if (!fwObject) {
    156        *pError = CKR_HOST_MEMORY;
    157        return (NSSCKFWObject *)NULL;
    158    }
    159 
    160    fwObject->arena = objArena;
    161    fwObject->localArena = localArena;
    162    fwObject->mdObject = mdObject;
    163    fwObject->fwSession = fwSession;
    164 
    165    if (fwSession) {
    166        fwObject->mdSession = nssCKFWSession_GetMDSession(fwSession);
    167    }
    168 
    169    fwObject->fwToken = fwToken;
    170    fwObject->mdToken = nssCKFWToken_GetMDToken(fwToken);
    171    fwObject->fwInstance = fwInstance;
    172    fwObject->mdInstance = nssCKFWInstance_GetMDInstance(fwInstance);
    173    fwObject->mutex = nssCKFWInstance_CreateMutex(fwInstance, objArena, pError);
    174    if (!fwObject->mutex) {
    175        if (CKR_OK == *pError) {
    176            *pError = CKR_GENERAL_ERROR;
    177        }
    178        nss_ZFreeIf(fwObject);
    179        if (localArena) {
    180            NSSArena_Destroy(localArena);
    181        }
    182        return (NSSCKFWObject *)NULL;
    183    }
    184 
    185    *pError = nssCKFWHash_Add(mdObjectHash, mdObject, fwObject);
    186    if (CKR_OK != *pError) {
    187        nss_ZFreeIf(fwObject);
    188        if (localArena) {
    189            NSSArena_Destroy(localArena);
    190        }
    191        return (NSSCKFWObject *)NULL;
    192    }
    193 
    194 #ifdef DEBUG
    195    *pError = object_add_pointer(fwObject);
    196    if (CKR_OK != *pError) {
    197        nssCKFWHash_Remove(mdObjectHash, mdObject);
    198        nss_ZFreeIf(fwObject);
    199        if (localArena) {
    200            NSSArena_Destroy(localArena);
    201        }
    202        return (NSSCKFWObject *)NULL;
    203    }
    204 #endif /* DEBUG */
    205 
    206    *pError = CKR_OK;
    207    return fwObject;
    208 }
    209 
    210 /*
    211 * nssCKFWObject_Finalize
    212 *
    213 */
    214 NSS_IMPLEMENT void
    215 nssCKFWObject_Finalize(
    216    NSSCKFWObject *fwObject,
    217    PRBool removeFromHash)
    218 {
    219    nssCKFWHash *mdObjectHash;
    220    NSSArena *arena = NULL;
    221 
    222 #ifdef NSSDEBUG
    223    if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
    224        return;
    225    }
    226 #endif /* NSSDEBUG */
    227 
    228    (void)nssCKFWMutex_Destroy(fwObject->mutex);
    229 
    230    if (fwObject->mdObject->Finalize) {
    231        fwObject->mdObject->Finalize(fwObject->mdObject, fwObject,
    232                                     fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
    233                                     fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance);
    234    }
    235 
    236    if (removeFromHash) {
    237        mdObjectHash = nssCKFWToken_GetMDObjectHash(fwObject->fwToken);
    238        if (mdObjectHash) {
    239            nssCKFWHash_Remove(mdObjectHash, fwObject->mdObject);
    240        }
    241    }
    242 
    243    if (fwObject->fwSession) {
    244        nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject);
    245    }
    246    arena = fwObject->localArena;
    247    nss_ZFreeIf(fwObject);
    248    if (arena) {
    249        NSSArena_Destroy(arena);
    250    }
    251 
    252 #ifdef DEBUG
    253    (void)object_remove_pointer(fwObject);
    254 #endif /* DEBUG */
    255 
    256    return;
    257 }
    258 
    259 /*
    260 * nssCKFWObject_Destroy
    261 *
    262 */
    263 NSS_IMPLEMENT void
    264 nssCKFWObject_Destroy(
    265    NSSCKFWObject *fwObject)
    266 {
    267    nssCKFWHash *mdObjectHash;
    268    NSSArena *arena = NULL;
    269 
    270 #ifdef NSSDEBUG
    271    if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
    272        return;
    273    }
    274 #endif /* NSSDEBUG */
    275 
    276    (void)nssCKFWMutex_Destroy(fwObject->mutex);
    277 
    278    if (fwObject->mdObject->Destroy) {
    279        fwObject->mdObject->Destroy(fwObject->mdObject, fwObject,
    280                                    fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
    281                                    fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance);
    282    }
    283 
    284    mdObjectHash = nssCKFWToken_GetMDObjectHash(fwObject->fwToken);
    285    if (mdObjectHash) {
    286        nssCKFWHash_Remove(mdObjectHash, fwObject->mdObject);
    287    }
    288 
    289    if (fwObject->fwSession) {
    290        nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject);
    291    }
    292    arena = fwObject->localArena;
    293    nss_ZFreeIf(fwObject);
    294    if (arena) {
    295        NSSArena_Destroy(arena);
    296    }
    297 
    298 #ifdef DEBUG
    299    (void)object_remove_pointer(fwObject);
    300 #endif /* DEBUG */
    301 
    302    return;
    303 }
    304 
    305 /*
    306 * nssCKFWObject_GetMDObject
    307 *
    308 */
    309 NSS_IMPLEMENT NSSCKMDObject *
    310 nssCKFWObject_GetMDObject(
    311    NSSCKFWObject *fwObject)
    312 {
    313 #ifdef NSSDEBUG
    314    if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
    315        return (NSSCKMDObject *)NULL;
    316    }
    317 #endif /* NSSDEBUG */
    318 
    319    return fwObject->mdObject;
    320 }
    321 
    322 /*
    323 * nssCKFWObject_GetArena
    324 *
    325 */
    326 NSS_IMPLEMENT NSSArena *
    327 nssCKFWObject_GetArena(
    328    NSSCKFWObject *fwObject,
    329    CK_RV *pError)
    330 {
    331 #ifdef NSSDEBUG
    332    if (!pError) {
    333        return (NSSArena *)NULL;
    334    }
    335 
    336    *pError = nssCKFWObject_verifyPointer(fwObject);
    337    if (CKR_OK != *pError) {
    338        return (NSSArena *)NULL;
    339    }
    340 #endif /* NSSDEBUG */
    341 
    342    return fwObject->arena;
    343 }
    344 
    345 /*
    346 * nssCKFWObject_SetHandle
    347 *
    348 */
    349 NSS_IMPLEMENT CK_RV
    350 nssCKFWObject_SetHandle(
    351    NSSCKFWObject *fwObject,
    352    CK_OBJECT_HANDLE hObject)
    353 {
    354 #ifdef NSSDEBUG
    355    CK_RV error = CKR_OK;
    356 #endif /* NSSDEBUG */
    357 
    358 #ifdef NSSDEBUG
    359    error = nssCKFWObject_verifyPointer(fwObject);
    360    if (CKR_OK != error) {
    361        return error;
    362    }
    363 #endif /* NSSDEBUG */
    364 
    365    if ((CK_OBJECT_HANDLE)0 != fwObject->hObject) {
    366        return CKR_GENERAL_ERROR;
    367    }
    368 
    369    fwObject->hObject = hObject;
    370 
    371    return CKR_OK;
    372 }
    373 
    374 /*
    375 * nssCKFWObject_GetHandle
    376 *
    377 */
    378 NSS_IMPLEMENT CK_OBJECT_HANDLE
    379 nssCKFWObject_GetHandle(
    380    NSSCKFWObject *fwObject)
    381 {
    382 #ifdef NSSDEBUG
    383    if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
    384        return (CK_OBJECT_HANDLE)0;
    385    }
    386 #endif /* NSSDEBUG */
    387 
    388    return fwObject->hObject;
    389 }
    390 
    391 /*
    392 * nssCKFWObject_IsTokenObject
    393 *
    394 */
    395 NSS_IMPLEMENT CK_BBOOL
    396 nssCKFWObject_IsTokenObject(
    397    NSSCKFWObject *fwObject)
    398 {
    399    CK_BBOOL b = CK_FALSE;
    400 
    401 #ifdef NSSDEBUG
    402    if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
    403        return CK_FALSE;
    404    }
    405 #endif /* NSSDEBUG */
    406 
    407    if (!fwObject->mdObject->IsTokenObject) {
    408        NSSItem item;
    409        NSSItem *pItem;
    410        CK_RV rv = CKR_OK;
    411 
    412        item.data = (void *)&b;
    413        item.size = sizeof(b);
    414 
    415        pItem = nssCKFWObject_GetAttribute(fwObject, CKA_TOKEN, &item,
    416                                           (NSSArena *)NULL, &rv);
    417        if (!pItem) {
    418            /* Error of some type */
    419            b = CK_FALSE;
    420            goto done;
    421        }
    422 
    423        goto done;
    424    }
    425 
    426    b = fwObject->mdObject->IsTokenObject(fwObject->mdObject, fwObject,
    427                                          fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
    428                                          fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance);
    429 
    430 done:
    431    return b;
    432 }
    433 
    434 /*
    435 * nssCKFWObject_GetAttributeCount
    436 *
    437 */
    438 NSS_IMPLEMENT CK_ULONG
    439 nssCKFWObject_GetAttributeCount(
    440    NSSCKFWObject *fwObject,
    441    CK_RV *pError)
    442 {
    443    CK_ULONG rv;
    444 
    445 #ifdef NSSDEBUG
    446    if (!pError) {
    447        return (CK_ULONG)0;
    448    }
    449 
    450    *pError = nssCKFWObject_verifyPointer(fwObject);
    451    if (CKR_OK != *pError) {
    452        return (CK_ULONG)0;
    453    }
    454 #endif /* NSSDEBUG */
    455 
    456    if (!fwObject->mdObject->GetAttributeCount) {
    457        *pError = CKR_GENERAL_ERROR;
    458        return (CK_ULONG)0;
    459    }
    460 
    461    *pError = nssCKFWMutex_Lock(fwObject->mutex);
    462    if (CKR_OK != *pError) {
    463        return (CK_ULONG)0;
    464    }
    465 
    466    rv = fwObject->mdObject->GetAttributeCount(fwObject->mdObject, fwObject,
    467                                               fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
    468                                               fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
    469                                               pError);
    470 
    471    (void)nssCKFWMutex_Unlock(fwObject->mutex);
    472    return rv;
    473 }
    474 
    475 /*
    476 * nssCKFWObject_GetAttributeTypes
    477 *
    478 */
    479 NSS_IMPLEMENT CK_RV
    480 nssCKFWObject_GetAttributeTypes(
    481    NSSCKFWObject *fwObject,
    482    CK_ATTRIBUTE_TYPE_PTR typeArray,
    483    CK_ULONG ulCount)
    484 {
    485    CK_RV error = CKR_OK;
    486 
    487 #ifdef NSSDEBUG
    488    error = nssCKFWObject_verifyPointer(fwObject);
    489    if (CKR_OK != error) {
    490        return error;
    491    }
    492 
    493    if ((CK_ATTRIBUTE_TYPE_PTR)NULL == typeArray) {
    494        return CKR_ARGUMENTS_BAD;
    495    }
    496 #endif /* NSSDEBUG */
    497 
    498    if (!fwObject->mdObject->GetAttributeTypes) {
    499        return CKR_GENERAL_ERROR;
    500    }
    501 
    502    error = nssCKFWMutex_Lock(fwObject->mutex);
    503    if (CKR_OK != error) {
    504        return error;
    505    }
    506 
    507    error = fwObject->mdObject->GetAttributeTypes(fwObject->mdObject, fwObject,
    508                                                  fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
    509                                                  fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
    510                                                  typeArray, ulCount);
    511 
    512    (void)nssCKFWMutex_Unlock(fwObject->mutex);
    513    return error;
    514 }
    515 
    516 /*
    517 * nssCKFWObject_GetAttributeSize
    518 *
    519 */
    520 NSS_IMPLEMENT CK_ULONG
    521 nssCKFWObject_GetAttributeSize(
    522    NSSCKFWObject *fwObject,
    523    CK_ATTRIBUTE_TYPE attribute,
    524    CK_RV *pError)
    525 {
    526    CK_ULONG rv;
    527 
    528    if (!pError) {
    529        return (CK_ULONG)0;
    530    }
    531 
    532    if (!fwObject || !fwObject->mdObject || !fwObject->mdObject->GetAttributeSize) {
    533        *pError = CKR_GENERAL_ERROR;
    534        return (CK_ULONG)0;
    535    }
    536 
    537    *pError = nssCKFWMutex_Lock(fwObject->mutex);
    538    if (CKR_OK != *pError) {
    539        return (CK_ULONG)0;
    540    }
    541 
    542    rv = fwObject->mdObject->GetAttributeSize(fwObject->mdObject, fwObject,
    543                                              fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
    544                                              fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
    545                                              attribute, pError);
    546 
    547    (void)nssCKFWMutex_Unlock(fwObject->mutex);
    548    return rv;
    549 }
    550 
    551 /*
    552 * nssCKFWObject_GetAttribute
    553 *
    554 * Usual NSS allocation rules:
    555 * If itemOpt is not NULL, it will be returned; otherwise an NSSItem
    556 * will be allocated.  If itemOpt is not NULL but itemOpt->data is,
    557 * the buffer will be allocated; otherwise, the buffer will be used.
    558 * Any allocations will come from the optional arena, if one is
    559 * specified.
    560 */
    561 NSS_IMPLEMENT NSSItem *
    562 nssCKFWObject_GetAttribute(
    563    NSSCKFWObject *fwObject,
    564    CK_ATTRIBUTE_TYPE attribute,
    565    NSSItem *itemOpt,
    566    NSSArena *arenaOpt,
    567    CK_RV *pError)
    568 {
    569    NSSItem *rv = (NSSItem *)NULL;
    570    NSSCKFWItem mdItem;
    571 
    572 #ifdef NSSDEBUG
    573    if (!pError) {
    574        return (NSSItem *)NULL;
    575    }
    576 
    577    *pError = nssCKFWObject_verifyPointer(fwObject);
    578    if (CKR_OK != *pError) {
    579        return (NSSItem *)NULL;
    580    }
    581 #endif /* NSSDEBUG */
    582 
    583    if (!fwObject->mdObject->GetAttribute) {
    584        *pError = CKR_GENERAL_ERROR;
    585        return (NSSItem *)NULL;
    586    }
    587 
    588    *pError = nssCKFWMutex_Lock(fwObject->mutex);
    589    if (CKR_OK != *pError) {
    590        return (NSSItem *)NULL;
    591    }
    592 
    593    mdItem = fwObject->mdObject->GetAttribute(fwObject->mdObject, fwObject,
    594                                              fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
    595                                              fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
    596                                              attribute, pError);
    597 
    598    if (!mdItem.item) {
    599        if (CKR_OK == *pError) {
    600            *pError = CKR_GENERAL_ERROR;
    601        }
    602 
    603        goto done;
    604    }
    605 
    606    if (!itemOpt) {
    607        rv = nss_ZNEW(arenaOpt, NSSItem);
    608        if (!rv) {
    609            *pError = CKR_HOST_MEMORY;
    610            goto done;
    611        }
    612    } else {
    613        rv = itemOpt;
    614    }
    615 
    616    if (!rv->data) {
    617        rv->size = mdItem.item->size;
    618        rv->data = nss_ZAlloc(arenaOpt, rv->size);
    619        if (!rv->data) {
    620            *pError = CKR_HOST_MEMORY;
    621            if (!itemOpt) {
    622                nss_ZFreeIf(rv);
    623            }
    624            rv = (NSSItem *)NULL;
    625            goto done;
    626        }
    627    } else {
    628        if (rv->size >= mdItem.item->size) {
    629            rv->size = mdItem.item->size;
    630        } else {
    631            *pError = CKR_BUFFER_TOO_SMALL;
    632            /* Should we set rv->size to mdItem->size? */
    633            /* rv can't have been allocated */
    634            rv = (NSSItem *)NULL;
    635            goto done;
    636        }
    637    }
    638 
    639    (void)nsslibc_memcpy(rv->data, mdItem.item->data, rv->size);
    640 
    641    if (PR_TRUE == mdItem.needsFreeing) {
    642        PR_ASSERT(fwObject->mdObject->FreeAttribute);
    643        if (fwObject->mdObject->FreeAttribute) {
    644            *pError = fwObject->mdObject->FreeAttribute(&mdItem);
    645        }
    646    }
    647 
    648 done:
    649    (void)nssCKFWMutex_Unlock(fwObject->mutex);
    650    return rv;
    651 }
    652 
    653 /*
    654 * nssCKFWObject_SetAttribute
    655 *
    656 */
    657 NSS_IMPLEMENT CK_RV
    658 nssCKFWObject_SetAttribute(
    659    NSSCKFWObject *fwObject,
    660    NSSCKFWSession *fwSession,
    661    CK_ATTRIBUTE_TYPE attribute,
    662    NSSItem *value)
    663 {
    664    CK_RV error = CKR_OK;
    665 
    666 #ifdef NSSDEBUG
    667    error = nssCKFWObject_verifyPointer(fwObject);
    668    if (CKR_OK != error) {
    669        return error;
    670    }
    671 #endif /* NSSDEBUG */
    672 
    673    if (CKA_TOKEN == attribute) {
    674        /*
    675         * We're changing from a session object to a token object or
    676         * vice-versa.
    677         */
    678 
    679        CK_ATTRIBUTE a;
    680        NSSCKFWObject *newFwObject;
    681        NSSCKFWObject swab;
    682 
    683        a.type = CKA_TOKEN;
    684        a.pValue = value->data;
    685        a.ulValueLen = value->size;
    686 
    687        newFwObject = nssCKFWSession_CopyObject(fwSession, fwObject,
    688                                                &a, 1, &error);
    689        if (!newFwObject) {
    690            if (CKR_OK == error) {
    691                error = CKR_GENERAL_ERROR;
    692            }
    693            return error;
    694        }
    695 
    696        /*
    697         * Actually, I bet the locking is worse than this.. this part of
    698         * the code could probably use some scrutiny and reworking.
    699         */
    700        error = nssCKFWMutex_Lock(fwObject->mutex);
    701        if (CKR_OK != error) {
    702            nssCKFWObject_Destroy(newFwObject);
    703            return error;
    704        }
    705 
    706        error = nssCKFWMutex_Lock(newFwObject->mutex);
    707        if (CKR_OK != error) {
    708            nssCKFWMutex_Unlock(fwObject->mutex);
    709            nssCKFWObject_Destroy(newFwObject);
    710            return error;
    711        }
    712 
    713        /*
    714         * Now, we have our new object, but it has a new fwObject pointer,
    715         * while we have to keep the existing one.  So quick swap the contents.
    716         */
    717        swab = *fwObject;
    718        *fwObject = *newFwObject;
    719        *newFwObject = swab;
    720 
    721        /* But keep the mutexes the same */
    722        swab.mutex = fwObject->mutex;
    723        fwObject->mutex = newFwObject->mutex;
    724        newFwObject->mutex = swab.mutex;
    725 
    726        (void)nssCKFWMutex_Unlock(newFwObject->mutex);
    727        (void)nssCKFWMutex_Unlock(fwObject->mutex);
    728 
    729        /*
    730         * Either remove or add this to the list of session objects
    731         */
    732 
    733        if (CK_FALSE == *(CK_BBOOL *)value->data) {
    734            /*
    735             * New one is a session object, except since we "stole" the fwObject, it's
    736             * not in the list.  Add it.
    737             */
    738            nssCKFWSession_RegisterSessionObject(fwSession, fwObject);
    739        } else {
    740            /*
    741             * New one is a token object, except since we "stole" the fwObject, it's
    742             * in the list.  Remove it.
    743             */
    744            if (fwObject->fwSession) {
    745                nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject);
    746            }
    747        }
    748 
    749        /*
    750         * Now delete the old object.  Remember the names have changed.
    751         */
    752        nssCKFWObject_Destroy(newFwObject);
    753 
    754        return CKR_OK;
    755    } else {
    756        /*
    757         * An "ordinary" change.
    758         */
    759        if (!fwObject->mdObject->SetAttribute) {
    760            /* We could fake it with copying, like above.. later */
    761            return CKR_ATTRIBUTE_READ_ONLY;
    762        }
    763 
    764        error = nssCKFWMutex_Lock(fwObject->mutex);
    765        if (CKR_OK != error) {
    766            return error;
    767        }
    768 
    769        error = fwObject->mdObject->SetAttribute(fwObject->mdObject, fwObject,
    770                                                 fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
    771                                                 fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
    772                                                 attribute, value);
    773 
    774        (void)nssCKFWMutex_Unlock(fwObject->mutex);
    775 
    776        return error;
    777    }
    778 }
    779 
    780 /*
    781 * nssCKFWObject_GetObjectSize
    782 *
    783 */
    784 NSS_IMPLEMENT CK_ULONG
    785 nssCKFWObject_GetObjectSize(
    786    NSSCKFWObject *fwObject,
    787    CK_RV *pError)
    788 {
    789    CK_ULONG rv;
    790 
    791 #ifdef NSSDEBUG
    792    if (!pError) {
    793        return (CK_ULONG)0;
    794    }
    795 
    796    *pError = nssCKFWObject_verifyPointer(fwObject);
    797    if (CKR_OK != *pError) {
    798        return (CK_ULONG)0;
    799    }
    800 #endif /* NSSDEBUG */
    801 
    802    if (!fwObject->mdObject->GetObjectSize) {
    803        *pError = CKR_INFORMATION_SENSITIVE;
    804        return (CK_ULONG)0;
    805    }
    806 
    807    *pError = nssCKFWMutex_Lock(fwObject->mutex);
    808    if (CKR_OK != *pError) {
    809        return (CK_ULONG)0;
    810    }
    811 
    812    rv = fwObject->mdObject->GetObjectSize(fwObject->mdObject, fwObject,
    813                                           fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
    814                                           fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
    815                                           pError);
    816 
    817    (void)nssCKFWMutex_Unlock(fwObject->mutex);
    818    return rv;
    819 }
    820 
    821 /*
    822 * NSSCKFWObject_GetMDObject
    823 *
    824 */
    825 NSS_IMPLEMENT NSSCKMDObject *
    826 NSSCKFWObject_GetMDObject(
    827    NSSCKFWObject *fwObject)
    828 {
    829 #ifdef DEBUG
    830    if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
    831        return (NSSCKMDObject *)NULL;
    832    }
    833 #endif /* DEBUG */
    834 
    835    return nssCKFWObject_GetMDObject(fwObject);
    836 }
    837 
    838 /*
    839 * NSSCKFWObject_GetArena
    840 *
    841 */
    842 NSS_IMPLEMENT NSSArena *
    843 NSSCKFWObject_GetArena(
    844    NSSCKFWObject *fwObject,
    845    CK_RV *pError)
    846 {
    847 #ifdef DEBUG
    848    if (!pError) {
    849        return (NSSArena *)NULL;
    850    }
    851 
    852    *pError = nssCKFWObject_verifyPointer(fwObject);
    853    if (CKR_OK != *pError) {
    854        return (NSSArena *)NULL;
    855    }
    856 #endif /* DEBUG */
    857 
    858    return nssCKFWObject_GetArena(fwObject, pError);
    859 }
    860 
    861 /*
    862 * NSSCKFWObject_IsTokenObject
    863 *
    864 */
    865 NSS_IMPLEMENT CK_BBOOL
    866 NSSCKFWObject_IsTokenObject(
    867    NSSCKFWObject *fwObject)
    868 {
    869 #ifdef DEBUG
    870    if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
    871        return CK_FALSE;
    872    }
    873 #endif /* DEBUG */
    874 
    875    return nssCKFWObject_IsTokenObject(fwObject);
    876 }
    877 
    878 /*
    879 * NSSCKFWObject_GetAttributeCount
    880 *
    881 */
    882 NSS_IMPLEMENT CK_ULONG
    883 NSSCKFWObject_GetAttributeCount(
    884    NSSCKFWObject *fwObject,
    885    CK_RV *pError)
    886 {
    887 #ifdef DEBUG
    888    if (!pError) {
    889        return (CK_ULONG)0;
    890    }
    891 
    892    *pError = nssCKFWObject_verifyPointer(fwObject);
    893    if (CKR_OK != *pError) {
    894        return (CK_ULONG)0;
    895    }
    896 #endif /* DEBUG */
    897 
    898    return nssCKFWObject_GetAttributeCount(fwObject, pError);
    899 }
    900 
    901 /*
    902 * NSSCKFWObject_GetAttributeTypes
    903 *
    904 */
    905 NSS_IMPLEMENT CK_RV
    906 NSSCKFWObject_GetAttributeTypes(
    907    NSSCKFWObject *fwObject,
    908    CK_ATTRIBUTE_TYPE_PTR typeArray,
    909    CK_ULONG ulCount)
    910 {
    911 #ifdef DEBUG
    912    CK_RV error = CKR_OK;
    913 
    914    error = nssCKFWObject_verifyPointer(fwObject);
    915    if (CKR_OK != error) {
    916        return error;
    917    }
    918 
    919    if ((CK_ATTRIBUTE_TYPE_PTR)NULL == typeArray) {
    920        return CKR_ARGUMENTS_BAD;
    921    }
    922 #endif /* DEBUG */
    923 
    924    return nssCKFWObject_GetAttributeTypes(fwObject, typeArray, ulCount);
    925 }
    926 
    927 /*
    928 * NSSCKFWObject_GetAttributeSize
    929 *
    930 */
    931 NSS_IMPLEMENT CK_ULONG
    932 NSSCKFWObject_GetAttributeSize(
    933    NSSCKFWObject *fwObject,
    934    CK_ATTRIBUTE_TYPE attribute,
    935    CK_RV *pError)
    936 {
    937 #ifdef DEBUG
    938    if (!pError) {
    939        return (CK_ULONG)0;
    940    }
    941 
    942    *pError = nssCKFWObject_verifyPointer(fwObject);
    943    if (CKR_OK != *pError) {
    944        return (CK_ULONG)0;
    945    }
    946 #endif /* DEBUG */
    947 
    948    return nssCKFWObject_GetAttributeSize(fwObject, attribute, pError);
    949 }
    950 
    951 /*
    952 * NSSCKFWObject_GetAttribute
    953 *
    954 */
    955 NSS_IMPLEMENT NSSItem *
    956 NSSCKFWObject_GetAttribute(
    957    NSSCKFWObject *fwObject,
    958    CK_ATTRIBUTE_TYPE attribute,
    959    NSSItem *itemOpt,
    960    NSSArena *arenaOpt,
    961    CK_RV *pError)
    962 {
    963 #ifdef DEBUG
    964    if (!pError) {
    965        return (NSSItem *)NULL;
    966    }
    967 
    968    *pError = nssCKFWObject_verifyPointer(fwObject);
    969    if (CKR_OK != *pError) {
    970        return (NSSItem *)NULL;
    971    }
    972 #endif /* DEBUG */
    973 
    974    return nssCKFWObject_GetAttribute(fwObject, attribute, itemOpt, arenaOpt, pError);
    975 }
    976 
    977 /*
    978 * NSSCKFWObject_GetObjectSize
    979 *
    980 */
    981 NSS_IMPLEMENT CK_ULONG
    982 NSSCKFWObject_GetObjectSize(
    983    NSSCKFWObject *fwObject,
    984    CK_RV *pError)
    985 {
    986 #ifdef DEBUG
    987    if (!pError) {
    988        return (CK_ULONG)0;
    989    }
    990 
    991    *pError = nssCKFWObject_verifyPointer(fwObject);
    992    if (CKR_OK != *pError) {
    993        return (CK_ULONG)0;
    994    }
    995 #endif /* DEBUG */
    996 
    997    return nssCKFWObject_GetObjectSize(fwObject, pError);
    998 }