summaryrefslogtreecommitdiff
path: root/lib/ckfw/sessobj.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ckfw/sessobj.c')
-rw-r--r--lib/ckfw/sessobj.c1079
1 files changed, 1079 insertions, 0 deletions
diff --git a/lib/ckfw/sessobj.c b/lib/ckfw/sessobj.c
new file mode 100644
index 000000000..d94ed7e87
--- /dev/null
+++ b/lib/ckfw/sessobj.c
@@ -0,0 +1,1079 @@
+/* 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/. */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
+#endif /* DEBUG */
+
+/*
+ * 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;
+}