tor-browser

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

sessobj.c (23738B)


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