| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| /* |
| * sessobj.c |
| * |
| * This file contains an NSSCKMDObject implementation for session |
| * objects. The framework uses this implementation to manage |
| * session objects when a Module doesn't wish to be bothered. |
| */ |
| |
| #ifndef CK_T |
| #include "ck.h" |
| #endif /* CK_T */ |
| |
| /* |
| * nssCKMDSessionObject |
| * |
| * -- create -- |
| * nssCKMDSessionObject_Create |
| * |
| * -- EPV calls -- |
| * nss_ckmdSessionObject_Finalize |
| * nss_ckmdSessionObject_IsTokenObject |
| * nss_ckmdSessionObject_GetAttributeCount |
| * nss_ckmdSessionObject_GetAttributeTypes |
| * nss_ckmdSessionObject_GetAttributeSize |
| * nss_ckmdSessionObject_GetAttribute |
| * nss_ckmdSessionObject_SetAttribute |
| * nss_ckmdSessionObject_GetObjectSize |
| */ |
| |
| struct nssCKMDSessionObjectStr { |
| CK_ULONG n; |
| NSSArena *arena; |
| NSSItem *attributes; |
| CK_ATTRIBUTE_TYPE_PTR types; |
| nssCKFWHash *hash; |
| }; |
| typedef struct nssCKMDSessionObjectStr nssCKMDSessionObject; |
| |
| #ifdef DEBUG |
| /* |
| * But first, the pointer-tracking stuff. |
| * |
| * NOTE: the pointer-tracking support in NSS/base currently relies |
| * upon NSPR's CallOnce support. That, however, relies upon NSPR's |
| * locking, which is tied into the runtime. We need a pointer-tracker |
| * implementation that uses the locks supplied through C_Initialize. |
| * That support, however, can be filled in later. So for now, I'll |
| * just do this routines as no-ops. |
| */ |
| |
| static CK_RV |
| nss_ckmdSessionObject_add_pointer( |
| const NSSCKMDObject *mdObject) |
| { |
| return CKR_OK; |
| } |
| |
| static CK_RV |
| nss_ckmdSessionObject_remove_pointer( |
| const NSSCKMDObject *mdObject) |
| { |
| return CKR_OK; |
| } |
| |
| #ifdef NSS_DEBUG |
| static CK_RV |
| nss_ckmdSessionObject_verifyPointer( |
| const NSSCKMDObject *mdObject) |
| { |
| return CKR_OK; |
| } |
| #endif |
| |
| #endif /* DEBUG */ |
| |
| /* |
| * We must forward-declare these routines |
| */ |
| static void |
| nss_ckmdSessionObject_Finalize( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance); |
| |
| static CK_RV |
| nss_ckmdSessionObject_Destroy( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance); |
| |
| static CK_BBOOL |
| nss_ckmdSessionObject_IsTokenObject( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance); |
| |
| static CK_ULONG |
| nss_ckmdSessionObject_GetAttributeCount( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_RV *pError); |
| |
| static CK_RV |
| nss_ckmdSessionObject_GetAttributeTypes( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_ATTRIBUTE_TYPE_PTR typeArray, |
| CK_ULONG ulCount); |
| |
| static CK_ULONG |
| nss_ckmdSessionObject_GetAttributeSize( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_ATTRIBUTE_TYPE attribute, |
| CK_RV *pError); |
| |
| static NSSCKFWItem |
| nss_ckmdSessionObject_GetAttribute( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_ATTRIBUTE_TYPE attribute, |
| CK_RV *pError); |
| |
| static CK_RV |
| nss_ckmdSessionObject_SetAttribute( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_ATTRIBUTE_TYPE attribute, |
| NSSItem *value); |
| |
| static CK_ULONG |
| nss_ckmdSessionObject_GetObjectSize( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_RV *pError); |
| |
| /* |
| * nssCKMDSessionObject_Create |
| * |
| */ |
| NSS_IMPLEMENT NSSCKMDObject * |
| nssCKMDSessionObject_Create( |
| NSSCKFWToken *fwToken, |
| NSSArena *arena, |
| CK_ATTRIBUTE_PTR attributes, |
| CK_ULONG ulCount, |
| CK_RV *pError) |
| { |
| NSSCKMDObject *mdObject = (NSSCKMDObject *)NULL; |
| nssCKMDSessionObject *mdso = (nssCKMDSessionObject *)NULL; |
| CK_ULONG i; |
| nssCKFWHash *hash; |
| |
| *pError = CKR_OK; |
| |
| mdso = nss_ZNEW(arena, nssCKMDSessionObject); |
| if (!mdso) { |
| goto loser; |
| } |
| |
| mdso->arena = arena; |
| mdso->n = ulCount; |
| mdso->attributes = nss_ZNEWARRAY(arena, NSSItem, ulCount); |
| if (!mdso->attributes) { |
| goto loser; |
| } |
| |
| mdso->types = nss_ZNEWARRAY(arena, CK_ATTRIBUTE_TYPE, ulCount); |
| if (!mdso->types) { |
| goto loser; |
| } |
| for (i = 0; i < ulCount; i++) { |
| mdso->types[i] = attributes[i].type; |
| mdso->attributes[i].size = attributes[i].ulValueLen; |
| mdso->attributes[i].data = nss_ZAlloc(arena, attributes[i].ulValueLen); |
| if (!mdso->attributes[i].data) { |
| goto loser; |
| } |
| (void)nsslibc_memcpy(mdso->attributes[i].data, attributes[i].pValue, |
| attributes[i].ulValueLen); |
| } |
| |
| mdObject = nss_ZNEW(arena, NSSCKMDObject); |
| if (!mdObject) { |
| goto loser; |
| } |
| |
| mdObject->etc = (void *)mdso; |
| mdObject->Finalize = nss_ckmdSessionObject_Finalize; |
| mdObject->Destroy = nss_ckmdSessionObject_Destroy; |
| mdObject->IsTokenObject = nss_ckmdSessionObject_IsTokenObject; |
| mdObject->GetAttributeCount = nss_ckmdSessionObject_GetAttributeCount; |
| mdObject->GetAttributeTypes = nss_ckmdSessionObject_GetAttributeTypes; |
| mdObject->GetAttributeSize = nss_ckmdSessionObject_GetAttributeSize; |
| mdObject->GetAttribute = nss_ckmdSessionObject_GetAttribute; |
| mdObject->SetAttribute = nss_ckmdSessionObject_SetAttribute; |
| mdObject->GetObjectSize = nss_ckmdSessionObject_GetObjectSize; |
| |
| hash = nssCKFWToken_GetSessionObjectHash(fwToken); |
| if (!hash) { |
| *pError = CKR_GENERAL_ERROR; |
| goto loser; |
| } |
| |
| mdso->hash = hash; |
| |
| *pError = nssCKFWHash_Add(hash, mdObject, mdObject); |
| if (CKR_OK != *pError) { |
| goto loser; |
| } |
| |
| #ifdef DEBUG |
| if ((*pError = nss_ckmdSessionObject_add_pointer(mdObject)) != CKR_OK) { |
| goto loser; |
| } |
| #endif /* DEBUG */ |
| |
| return mdObject; |
| |
| loser: |
| if (mdso) { |
| if (mdso->attributes) { |
| for (i = 0; i < ulCount; i++) { |
| nss_ZFreeIf(mdso->attributes[i].data); |
| } |
| nss_ZFreeIf(mdso->attributes); |
| } |
| nss_ZFreeIf(mdso->types); |
| nss_ZFreeIf(mdso); |
| } |
| |
| nss_ZFreeIf(mdObject); |
| if (*pError == CKR_OK) { |
| *pError = CKR_HOST_MEMORY; |
| } |
| return (NSSCKMDObject *)NULL; |
| } |
| |
| /* |
| * nss_ckmdSessionObject_Finalize |
| * |
| */ |
| static void |
| nss_ckmdSessionObject_Finalize( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance) |
| { |
| /* This shouldn't ever be called */ |
| return; |
| } |
| |
| /* |
| * nss_ckmdSessionObject_Destroy |
| * |
| */ |
| |
| static CK_RV |
| nss_ckmdSessionObject_Destroy( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance) |
| { |
| #ifdef NSSDEBUG |
| CK_RV error = CKR_OK; |
| #endif /* NSSDEBUG */ |
| nssCKMDSessionObject *mdso; |
| CK_ULONG i; |
| |
| #ifdef NSSDEBUG |
| error = nss_ckmdSessionObject_verifyPointer(mdObject); |
| if (CKR_OK != error) { |
| return error; |
| } |
| #endif /* NSSDEBUG */ |
| |
| mdso = (nssCKMDSessionObject *)mdObject->etc; |
| |
| nssCKFWHash_Remove(mdso->hash, mdObject); |
| |
| for (i = 0; i < mdso->n; i++) { |
| nss_ZFreeIf(mdso->attributes[i].data); |
| } |
| nss_ZFreeIf(mdso->attributes); |
| nss_ZFreeIf(mdso->types); |
| nss_ZFreeIf(mdso); |
| nss_ZFreeIf(mdObject); |
| |
| #ifdef DEBUG |
| (void)nss_ckmdSessionObject_remove_pointer(mdObject); |
| #endif /* DEBUG */ |
| |
| return CKR_OK; |
| } |
| |
| /* |
| * nss_ckmdSessionObject_IsTokenObject |
| * |
| */ |
| |
| static CK_BBOOL |
| nss_ckmdSessionObject_IsTokenObject( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance) |
| { |
| #ifdef NSSDEBUG |
| if (CKR_OK != nss_ckmdSessionObject_verifyPointer(mdObject)) { |
| return CK_FALSE; |
| } |
| #endif /* NSSDEBUG */ |
| |
| /* |
| * This implementation is only ever used for session objects. |
| */ |
| return CK_FALSE; |
| } |
| |
| /* |
| * nss_ckmdSessionObject_GetAttributeCount |
| * |
| */ |
| static CK_ULONG |
| nss_ckmdSessionObject_GetAttributeCount( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_RV *pError) |
| { |
| nssCKMDSessionObject *obj; |
| |
| #ifdef NSSDEBUG |
| if (!pError) { |
| return 0; |
| } |
| |
| *pError = nss_ckmdSessionObject_verifyPointer(mdObject); |
| if (CKR_OK != *pError) { |
| return 0; |
| } |
| |
| /* We could even check all the other arguments, for sanity. */ |
| #endif /* NSSDEBUG */ |
| |
| obj = (nssCKMDSessionObject *)mdObject->etc; |
| |
| return obj->n; |
| } |
| |
| /* |
| * nss_ckmdSessionObject_GetAttributeTypes |
| * |
| */ |
| static CK_RV |
| nss_ckmdSessionObject_GetAttributeTypes( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_ATTRIBUTE_TYPE_PTR typeArray, |
| CK_ULONG ulCount) |
| { |
| #ifdef NSSDEBUG |
| CK_RV error = CKR_OK; |
| #endif /* NSSDEBUG */ |
| nssCKMDSessionObject *obj; |
| |
| #ifdef NSSDEBUG |
| error = nss_ckmdSessionObject_verifyPointer(mdObject); |
| if (CKR_OK != error) { |
| return error; |
| } |
| |
| /* We could even check all the other arguments, for sanity. */ |
| #endif /* NSSDEBUG */ |
| |
| obj = (nssCKMDSessionObject *)mdObject->etc; |
| |
| if (ulCount < obj->n) { |
| return CKR_BUFFER_TOO_SMALL; |
| } |
| |
| (void)nsslibc_memcpy(typeArray, obj->types, |
| sizeof(CK_ATTRIBUTE_TYPE) * |
| obj->n); |
| |
| return CKR_OK; |
| } |
| |
| /* |
| * nss_ckmdSessionObject_GetAttributeSize |
| * |
| */ |
| static CK_ULONG |
| nss_ckmdSessionObject_GetAttributeSize( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_ATTRIBUTE_TYPE attribute, |
| CK_RV *pError) |
| { |
| nssCKMDSessionObject *obj; |
| CK_ULONG i; |
| |
| #ifdef NSSDEBUG |
| if (!pError) { |
| return 0; |
| } |
| |
| *pError = nss_ckmdSessionObject_verifyPointer(mdObject); |
| if (CKR_OK != *pError) { |
| return 0; |
| } |
| |
| /* We could even check all the other arguments, for sanity. */ |
| #endif /* NSSDEBUG */ |
| |
| obj = (nssCKMDSessionObject *)mdObject->etc; |
| |
| for (i = 0; i < obj->n; i++) { |
| if (attribute == obj->types[i]) { |
| return (CK_ULONG)(obj->attributes[i].size); |
| } |
| } |
| |
| *pError = CKR_ATTRIBUTE_TYPE_INVALID; |
| return 0; |
| } |
| |
| /* |
| * nss_ckmdSessionObject_GetAttribute |
| * |
| */ |
| static NSSCKFWItem |
| nss_ckmdSessionObject_GetAttribute( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_ATTRIBUTE_TYPE attribute, |
| CK_RV *pError) |
| { |
| NSSCKFWItem item; |
| nssCKMDSessionObject *obj; |
| CK_ULONG i; |
| |
| item.needsFreeing = PR_FALSE; |
| item.item = NULL; |
| #ifdef NSSDEBUG |
| if (!pError) { |
| return item; |
| } |
| |
| *pError = nss_ckmdSessionObject_verifyPointer(mdObject); |
| if (CKR_OK != *pError) { |
| return item; |
| } |
| |
| /* We could even check all the other arguments, for sanity. */ |
| #endif /* NSSDEBUG */ |
| |
| obj = (nssCKMDSessionObject *)mdObject->etc; |
| |
| for (i = 0; i < obj->n; i++) { |
| if (attribute == obj->types[i]) { |
| item.item = &obj->attributes[i]; |
| return item; |
| } |
| } |
| |
| *pError = CKR_ATTRIBUTE_TYPE_INVALID; |
| return item; |
| } |
| |
| /* |
| * nss_ckmdSessionObject_SetAttribute |
| * |
| */ |
| |
| /* |
| * Okay, so this implementation sucks. It doesn't support removing |
| * an attribute (if value == NULL), and could be more graceful about |
| * memory. It should allow "blank" slots in the arrays, with some |
| * invalid attribute type, and then it could support removal much |
| * more easily. Do this later. |
| */ |
| static CK_RV |
| nss_ckmdSessionObject_SetAttribute( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_ATTRIBUTE_TYPE attribute, |
| NSSItem *value) |
| { |
| nssCKMDSessionObject *obj; |
| CK_ULONG i; |
| NSSItem n; |
| NSSItem *ra; |
| CK_ATTRIBUTE_TYPE_PTR rt; |
| #ifdef NSSDEBUG |
| CK_RV error; |
| #endif /* NSSDEBUG */ |
| |
| #ifdef NSSDEBUG |
| error = nss_ckmdSessionObject_verifyPointer(mdObject); |
| if (CKR_OK != error) { |
| return 0; |
| } |
| |
| /* We could even check all the other arguments, for sanity. */ |
| #endif /* NSSDEBUG */ |
| |
| obj = (nssCKMDSessionObject *)mdObject->etc; |
| |
| n.size = value->size; |
| n.data = nss_ZAlloc(obj->arena, n.size); |
| if (!n.data) { |
| return CKR_HOST_MEMORY; |
| } |
| (void)nsslibc_memcpy(n.data, value->data, n.size); |
| |
| for (i = 0; i < obj->n; i++) { |
| if (attribute == obj->types[i]) { |
| nss_ZFreeIf(obj->attributes[i].data); |
| obj->attributes[i] = n; |
| return CKR_OK; |
| } |
| } |
| |
| /* |
| * It's new. |
| */ |
| |
| ra = (NSSItem *)nss_ZRealloc(obj->attributes, sizeof(NSSItem) * (obj->n + 1)); |
| if (!ra) { |
| nss_ZFreeIf(n.data); |
| return CKR_HOST_MEMORY; |
| } |
| obj->attributes = ra; |
| |
| rt = (CK_ATTRIBUTE_TYPE_PTR)nss_ZRealloc(obj->types, |
| sizeof(CK_ATTRIBUTE_TYPE) * (obj->n + 1)); |
| if (!rt) { |
| nss_ZFreeIf(n.data); |
| return CKR_HOST_MEMORY; |
| } |
| |
| obj->types = rt; |
| obj->attributes[obj->n] = n; |
| obj->types[obj->n] = attribute; |
| obj->n++; |
| |
| return CKR_OK; |
| } |
| |
| /* |
| * nss_ckmdSessionObject_GetObjectSize |
| * |
| */ |
| static CK_ULONG |
| nss_ckmdSessionObject_GetObjectSize( |
| NSSCKMDObject *mdObject, |
| NSSCKFWObject *fwObject, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| CK_RV *pError) |
| { |
| nssCKMDSessionObject *obj; |
| CK_ULONG i; |
| CK_ULONG rv = (CK_ULONG)0; |
| |
| #ifdef NSSDEBUG |
| if (!pError) { |
| return 0; |
| } |
| |
| *pError = nss_ckmdSessionObject_verifyPointer(mdObject); |
| if (CKR_OK != *pError) { |
| return 0; |
| } |
| |
| /* We could even check all the other arguments, for sanity. */ |
| #endif /* NSSDEBUG */ |
| |
| obj = (nssCKMDSessionObject *)mdObject->etc; |
| |
| for (i = 0; i < obj->n; i++) { |
| rv += obj->attributes[i].size; |
| } |
| |
| rv += sizeof(NSSItem) * obj->n; |
| rv += sizeof(CK_ATTRIBUTE_TYPE) * obj->n; |
| rv += sizeof(nssCKMDSessionObject); |
| |
| return rv; |
| } |
| |
| /* |
| * nssCKMDFindSessionObjects |
| * |
| * -- create -- |
| * nssCKMDFindSessionObjects_Create |
| * |
| * -- EPV calls -- |
| * nss_ckmdFindSessionObjects_Final |
| * nss_ckmdFindSessionObjects_Next |
| */ |
| |
| struct nodeStr { |
| struct nodeStr *next; |
| NSSCKMDObject *mdObject; |
| }; |
| |
| struct nssCKMDFindSessionObjectsStr { |
| NSSArena *arena; |
| CK_RV error; |
| CK_ATTRIBUTE_PTR pTemplate; |
| CK_ULONG ulCount; |
| struct nodeStr *list; |
| nssCKFWHash *hash; |
| }; |
| typedef struct nssCKMDFindSessionObjectsStr nssCKMDFindSessionObjects; |
| |
| #ifdef DEBUG |
| /* |
| * But first, the pointer-tracking stuff. |
| * |
| * NOTE: the pointer-tracking support in NSS/base currently relies |
| * upon NSPR's CallOnce support. That, however, relies upon NSPR's |
| * locking, which is tied into the runtime. We need a pointer-tracker |
| * implementation that uses the locks supplied through C_Initialize. |
| * That support, however, can be filled in later. So for now, I'll |
| * just do this routines as no-ops. |
| */ |
| |
| static CK_RV |
| nss_ckmdFindSessionObjects_add_pointer( |
| const NSSCKMDFindObjects *mdFindObjects) |
| { |
| return CKR_OK; |
| } |
| |
| static CK_RV |
| nss_ckmdFindSessionObjects_remove_pointer( |
| const NSSCKMDFindObjects *mdFindObjects) |
| { |
| return CKR_OK; |
| } |
| |
| #ifdef NSS_DEBUG |
| static CK_RV |
| nss_ckmdFindSessionObjects_verifyPointer( |
| const NSSCKMDFindObjects *mdFindObjects) |
| { |
| return CKR_OK; |
| } |
| #endif |
| |
| #endif /* DEBUG */ |
| |
| /* |
| * We must forward-declare these routines. |
| */ |
| static void |
| nss_ckmdFindSessionObjects_Final( |
| NSSCKMDFindObjects *mdFindObjects, |
| NSSCKFWFindObjects *fwFindObjects, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance); |
| |
| static NSSCKMDObject * |
| nss_ckmdFindSessionObjects_Next( |
| NSSCKMDFindObjects *mdFindObjects, |
| NSSCKFWFindObjects *fwFindObjects, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| NSSArena *arena, |
| CK_RV *pError); |
| |
| static CK_BBOOL |
| items_match( |
| NSSItem *a, |
| CK_VOID_PTR pValue, |
| CK_ULONG ulValueLen) |
| { |
| if (a->size != ulValueLen) { |
| return CK_FALSE; |
| } |
| |
| if (PR_TRUE == nsslibc_memequal(a->data, pValue, ulValueLen, (PRStatus *)NULL)) { |
| return CK_TRUE; |
| } else { |
| return CK_FALSE; |
| } |
| } |
| |
| /* |
| * Our hashtable iterator |
| */ |
| static void |
| findfcn( |
| const void *key, |
| void *value, |
| void *closure) |
| { |
| NSSCKMDObject *mdObject = (NSSCKMDObject *)value; |
| nssCKMDSessionObject *mdso = (nssCKMDSessionObject *)mdObject->etc; |
| nssCKMDFindSessionObjects *mdfso = (nssCKMDFindSessionObjects *)closure; |
| CK_ULONG i, j; |
| struct nodeStr *node; |
| |
| if (CKR_OK != mdfso->error) { |
| return; |
| } |
| |
| for (i = 0; i < mdfso->ulCount; i++) { |
| CK_ATTRIBUTE_PTR p = &mdfso->pTemplate[i]; |
| |
| for (j = 0; j < mdso->n; j++) { |
| if (mdso->types[j] == p->type) { |
| if (!items_match(&mdso->attributes[j], p->pValue, p->ulValueLen)) { |
| return; |
| } else { |
| break; |
| } |
| } |
| } |
| |
| if (j == mdso->n) { |
| /* Attribute not found */ |
| return; |
| } |
| } |
| |
| /* Matches */ |
| node = nss_ZNEW(mdfso->arena, struct nodeStr); |
| if ((struct nodeStr *)NULL == node) { |
| mdfso->error = CKR_HOST_MEMORY; |
| return; |
| } |
| |
| node->mdObject = mdObject; |
| node->next = mdfso->list; |
| mdfso->list = node; |
| |
| return; |
| } |
| |
| /* |
| * nssCKMDFindSessionObjects_Create |
| * |
| */ |
| NSS_IMPLEMENT NSSCKMDFindObjects * |
| nssCKMDFindSessionObjects_Create( |
| NSSCKFWToken *fwToken, |
| CK_ATTRIBUTE_PTR pTemplate, |
| CK_ULONG ulCount, |
| CK_RV *pError) |
| { |
| NSSArena *arena; |
| nssCKMDFindSessionObjects *mdfso; |
| nssCKFWHash *hash; |
| NSSCKMDFindObjects *rv; |
| |
| #ifdef NSSDEBUG |
| if (!pError) { |
| return (NSSCKMDFindObjects *)NULL; |
| } |
| |
| *pError = nssCKFWToken_verifyPointer(fwToken); |
| if (CKR_OK != *pError) { |
| return (NSSCKMDFindObjects *)NULL; |
| } |
| |
| if ((CK_ATTRIBUTE_PTR)NULL == pTemplate) { |
| *pError = CKR_ARGUMENTS_BAD; |
| return (NSSCKMDFindObjects *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| *pError = CKR_OK; |
| |
| hash = nssCKFWToken_GetSessionObjectHash(fwToken); |
| if (!hash) { |
| *pError = CKR_GENERAL_ERROR; |
| return (NSSCKMDFindObjects *)NULL; |
| } |
| |
| arena = NSSArena_Create(); |
| if (!arena) { |
| *pError = CKR_HOST_MEMORY; |
| return (NSSCKMDFindObjects *)NULL; |
| } |
| |
| mdfso = nss_ZNEW(arena, nssCKMDFindSessionObjects); |
| if (!mdfso) { |
| goto loser; |
| } |
| |
| rv = nss_ZNEW(arena, NSSCKMDFindObjects); |
| if (rv == NULL) { |
| goto loser; |
| } |
| |
| mdfso->error = CKR_OK; |
| mdfso->pTemplate = pTemplate; |
| mdfso->ulCount = ulCount; |
| mdfso->hash = hash; |
| |
| nssCKFWHash_Iterate(hash, findfcn, mdfso); |
| |
| if (CKR_OK != mdfso->error) { |
| goto loser; |
| } |
| |
| rv->etc = (void *)mdfso; |
| rv->Final = nss_ckmdFindSessionObjects_Final; |
| rv->Next = nss_ckmdFindSessionObjects_Next; |
| |
| #ifdef DEBUG |
| if ((*pError = nss_ckmdFindSessionObjects_add_pointer(rv)) != CKR_OK) { |
| goto loser; |
| } |
| #endif /* DEBUG */ |
| mdfso->arena = arena; |
| |
| return rv; |
| |
| loser: |
| if (arena) { |
| NSSArena_Destroy(arena); |
| } |
| if (*pError == CKR_OK) { |
| *pError = CKR_HOST_MEMORY; |
| } |
| return NULL; |
| } |
| |
| static void |
| nss_ckmdFindSessionObjects_Final( |
| NSSCKMDFindObjects *mdFindObjects, |
| NSSCKFWFindObjects *fwFindObjects, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance) |
| { |
| nssCKMDFindSessionObjects *mdfso; |
| |
| #ifdef NSSDEBUG |
| if (CKR_OK != nss_ckmdFindSessionObjects_verifyPointer(mdFindObjects)) { |
| return; |
| } |
| #endif /* NSSDEBUG */ |
| |
| mdfso = (nssCKMDFindSessionObjects *)mdFindObjects->etc; |
| if (mdfso->arena) |
| NSSArena_Destroy(mdfso->arena); |
| |
| #ifdef DEBUG |
| (void)nss_ckmdFindSessionObjects_remove_pointer(mdFindObjects); |
| #endif /* DEBUG */ |
| |
| return; |
| } |
| |
| static NSSCKMDObject * |
| nss_ckmdFindSessionObjects_Next( |
| NSSCKMDFindObjects *mdFindObjects, |
| NSSCKFWFindObjects *fwFindObjects, |
| NSSCKMDSession *mdSession, |
| NSSCKFWSession *fwSession, |
| NSSCKMDToken *mdToken, |
| NSSCKFWToken *fwToken, |
| NSSCKMDInstance *mdInstance, |
| NSSCKFWInstance *fwInstance, |
| NSSArena *arena, |
| CK_RV *pError) |
| { |
| nssCKMDFindSessionObjects *mdfso; |
| NSSCKMDObject *rv = (NSSCKMDObject *)NULL; |
| |
| #ifdef NSSDEBUG |
| if (CKR_OK != nss_ckmdFindSessionObjects_verifyPointer(mdFindObjects)) { |
| return (NSSCKMDObject *)NULL; |
| } |
| #endif /* NSSDEBUG */ |
| |
| mdfso = (nssCKMDFindSessionObjects *)mdFindObjects->etc; |
| |
| while (!rv) { |
| if ((struct nodeStr *)NULL == mdfso->list) { |
| *pError = CKR_OK; |
| return (NSSCKMDObject *)NULL; |
| } |
| |
| if (nssCKFWHash_Exists(mdfso->hash, mdfso->list->mdObject)) { |
| rv = mdfso->list->mdObject; |
| } |
| |
| mdfso->list = mdfso->list->next; |
| } |
| |
| return rv; |
| } |