summaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/lib/handle_mgr
diff options
context:
space:
mode:
Diffstat (limited to 'SoftHSMv2/src/lib/handle_mgr')
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/Handle.cpp50
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/Handle.h62
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/HandleManager.cpp239
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/HandleManager.h94
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/Makefile.am17
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.cpp178
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.h58
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/test/Makefile.am26
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/test/handlemgrtest.cpp65
9 files changed, 789 insertions, 0 deletions
diff --git a/SoftHSMv2/src/lib/handle_mgr/Handle.cpp b/SoftHSMv2/src/lib/handle_mgr/Handle.cpp
new file mode 100644
index 0000000..127b4c7
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/Handle.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Handle.h
+
+ This class represents a single handle
+ *****************************************************************************/
+
+#include "Handle.h"
+
+// Constructor
+Handle::Handle(CK_HANDLE_KIND _kind, CK_SLOT_ID _slotID, CK_SESSION_HANDLE _hSession)
+ : kind(_kind), slotID(_slotID), hSession(_hSession), object(NULL_PTR), isPrivate(false)
+{
+}
+
+Handle::Handle(CK_HANDLE_KIND _kind, CK_SLOT_ID _slotID)
+ : kind(_kind), slotID(_slotID), hSession(CK_INVALID_HANDLE), object(NULL_PTR), isPrivate(false)
+{
+}
+
+Handle::Handle()
+ : kind(CKH_INVALID), slotID(0), hSession(CK_INVALID_HANDLE), object(NULL_PTR), isPrivate(false)
+{
+
+}
diff --git a/SoftHSMv2/src/lib/handle_mgr/Handle.h b/SoftHSMv2/src/lib/handle_mgr/Handle.h
new file mode 100644
index 0000000..94b42f9
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/Handle.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Handle.h
+
+ This class represents a single handle
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HANDLE_H
+#define _SOFTHSM_V2_HANDLE_H
+
+#include "cryptoki.h"
+
+enum {
+ CKH_INVALID,
+ CKH_SESSION,
+ CKH_OBJECT
+};
+
+#define CK_HANDLE_KIND CK_ULONG
+
+class Handle
+{
+public:
+ Handle(CK_HANDLE_KIND kind, CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession);
+ Handle(CK_HANDLE_KIND kind, CK_SLOT_ID slotID);
+ Handle();
+
+ CK_HANDLE_KIND kind;
+ CK_SLOT_ID slotID;
+ CK_SESSION_HANDLE hSession;
+
+ CK_VOID_PTR object;
+ bool isPrivate;
+};
+
+#endif // !_SOFTHSM_V2_HANDLE_H
+
diff --git a/SoftHSMv2/src/lib/handle_mgr/HandleManager.cpp b/SoftHSMv2/src/lib/handle_mgr/HandleManager.cpp
new file mode 100644
index 0000000..ccf42d0
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/HandleManager.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*****************************************************************************
+ HandleManager.cpp
+
+ One of the most difficult problems to track down is when stale cryptoki handles
+ for e.g. keys, objects and sessions get reused by a misbehaving application.
+ Especialy when handles that became invalid have since been reused.
+ A simple solution to this is to never reuse a handle once it has been issued
+ and subsequently invalidated.
+
+ The handle manager tracks issued handles along with what kind of object
+ is presented by the handle and an actual pointer to the object in question.
+
+ Issued handles are unique per application run. All session and object handles
+ use the same handle manager and therefore there will never be e.g. a session
+ with the same handle as an object.
+
+ *****************************************************************************/
+
+#include "HandleManager.h"
+#include "log.h"
+
+// Constructor
+HandleManager::HandleManager()
+{
+ handlesMutex = MutexFactory::i()->getMutex();
+ handleCounter = 0;
+}
+
+// Destructor
+HandleManager::~HandleManager()
+{
+
+ MutexFactory::i()->recycleMutex(handlesMutex);
+}
+
+CK_SESSION_HANDLE HandleManager::addSession(CK_SLOT_ID slotID, CK_VOID_PTR session)
+{
+ MutexLocker lock(handlesMutex);
+
+ Handle h( CKH_SESSION, slotID );
+ h.object = session;
+ handles[++handleCounter] = h;
+ return (CK_SESSION_HANDLE)handleCounter;
+}
+
+CK_VOID_PTR HandleManager::getSession(const CK_SESSION_HANDLE hSession)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hSession);
+ if (it == handles.end() || CKH_SESSION != it->second.kind)
+ return NULL_PTR;
+ return it->second.object;
+}
+
+CK_OBJECT_HANDLE HandleManager::addSessionObject(CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate, CK_VOID_PTR object)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Return existing handle when the object has already been registered.
+ std::map< CK_VOID_PTR, CK_ULONG>::iterator oit = objects.find(object);
+ if (oit != objects.end()) {
+ std::map< CK_ULONG, Handle>::iterator hit = handles.find(oit->second);
+ if (hit == handles.end() || CKH_OBJECT != hit->second.kind || slotID != hit->second.slotID) {
+ objects.erase(oit);
+ return CK_INVALID_HANDLE;
+ } else
+ return oit->second;
+ }
+
+ Handle h( CKH_OBJECT, slotID, hSession );
+ h.isPrivate = isPrivate;
+ h.object = object;
+ handles[++handleCounter] = h;
+ objects[object] = handleCounter;
+ return (CK_OBJECT_HANDLE)handleCounter;
+}
+
+CK_OBJECT_HANDLE HandleManager::addTokenObject(CK_SLOT_ID slotID, bool isPrivate, CK_VOID_PTR object)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Return existing handle when the object has already been registered.
+ std::map< CK_VOID_PTR, CK_ULONG>::iterator oit = objects.find(object);
+ if (oit != objects.end()) {
+ std::map< CK_ULONG, Handle>::iterator hit = handles.find(oit->second);
+ if (hit == handles.end() || CKH_OBJECT != hit->second.kind || slotID != hit->second.slotID) {
+ objects.erase(oit);
+ return CK_INVALID_HANDLE;
+ } else
+ return oit->second;
+ }
+
+ // Token objects are not associated with a specific session.
+ Handle h( CKH_OBJECT, slotID );
+ h.isPrivate = isPrivate;
+ h.object = object;
+ handles[++handleCounter] = h;
+ objects[object] = handleCounter;
+ return (CK_OBJECT_HANDLE)handleCounter;
+}
+
+CK_VOID_PTR HandleManager::getObject(const CK_OBJECT_HANDLE hObject)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hObject);
+ if (it == handles.end() || CKH_OBJECT != it->second.kind )
+ return NULL_PTR;
+ return it->second.object;
+}
+
+CK_OBJECT_HANDLE HandleManager::getObjectHandle(CK_VOID_PTR object)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_VOID_PTR, CK_ULONG>::iterator it = objects.find(object);
+ if (it == objects.end())
+ return CK_INVALID_HANDLE;
+ return it->second;
+}
+
+void HandleManager::destroyObject(const CK_OBJECT_HANDLE hObject)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hObject);
+ if (it != handles.end() && CKH_OBJECT == it->second.kind) {
+ objects.erase(it->second.object);
+ handles.erase(it);
+ }
+}
+
+void HandleManager::sessionClosed(const CK_SESSION_HANDLE hSession)
+{
+ CK_SLOT_ID slotID;
+ {
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hSession);
+ if (it == handles.end() || CKH_SESSION != it->second.kind)
+ return; // Unable to find the specified session.
+
+ slotID = it->second.slotID;
+
+ // session closed, so we can erase information about it.
+ handles.erase(it);
+
+ // Erase all session object handles associated with the given session handle.
+ CK_ULONG openSessionCount = 0;
+ for (it = handles.begin(); it != handles.end(); ) {
+ Handle &h = it->second;
+ if (CKH_SESSION == h.kind && slotID == h.slotID) {
+ ++openSessionCount; // another session is open for this slotID.
+ } else {
+ if (CKH_OBJECT == h.kind && hSession == h.hSession) {
+ // A session object is present for the given session, so erase it.
+ objects.erase(it->second.object);
+ // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
+ handles.erase(it++);
+ continue;
+ }
+ }
+ ++it;
+ }
+
+ // We are done when there are still sessions open.
+ if (openSessionCount)
+ return;
+ }
+
+ // No more sessions open for this token, so remove all object handles that are still valid for the given slotID.
+ allSessionsClosed(slotID);
+}
+
+void HandleManager::allSessionsClosed(const CK_SLOT_ID slotID)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Erase all "session", "session object" and "token object" handles for a given slot id.
+ std::map< CK_ULONG, Handle>::iterator it;
+ for (it = handles.begin(); it != handles.end(); ) {
+ Handle &h = it->second;
+ if (slotID == h.slotID) {
+ if (CKH_OBJECT == it->second.kind)
+ objects.erase(it->second.object);
+ // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
+ handles.erase(it++);
+ continue;
+ }
+ ++it;
+ }
+}
+
+void HandleManager::tokenLoggedOut(const CK_SLOT_ID slotID)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Erase all private "token object" or "session object" handles for a given slot id.
+ std::map< CK_ULONG, Handle>::iterator it;
+ for (it = handles.begin(); it != handles.end(); ) {
+ Handle &h = it->second;
+ if (CKH_OBJECT == h.kind && slotID == h.slotID && h.isPrivate) {
+ // A private object is present for the given slotID so we need to remove it.
+ objects.erase(it->second.object);
+ // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
+ handles.erase(it++);
+ continue;
+ }
+ ++it;
+ }
+}
diff --git a/SoftHSMv2/src/lib/handle_mgr/HandleManager.h b/SoftHSMv2/src/lib/handle_mgr/HandleManager.h
new file mode 100644
index 0000000..e85e628
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/HandleManager.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HandleManager.h
+
+ Keeps track of the issued cryptoki handles within SoftHSM
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HANDLEMANAGER_H
+#define _SOFTHSM_V2_HANDLEMANAGER_H
+
+#include "MutexFactory.h"
+#include "Handle.h"
+#include "cryptoki.h"
+
+#include <map>
+
+#define CK_INTERNAL_SESSION_HANDLE CK_SESSION_HANDLE
+
+class HandleManager
+{
+public:
+ HandleManager();
+
+ virtual ~HandleManager();
+
+ CK_SESSION_HANDLE addSession(CK_SLOT_ID slotID, CK_VOID_PTR session);
+ CK_VOID_PTR getSession(const CK_SESSION_HANDLE hSession);
+
+ // Add the session object and return a handle. For objects that have already been registered, check that the
+ // slotID matches. The hSession may be different as the object may be added as part of a find objects operation.
+ CK_OBJECT_HANDLE addSessionObject(CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate, CK_VOID_PTR object);
+
+ // Add the token object and return a handle. For objects that have already been registered, check that the
+ // slotID mathces.
+ CK_OBJECT_HANDLE addTokenObject(CK_SLOT_ID slotID, bool isPrivate, CK_VOID_PTR object);
+
+ // Get the object pointer associated with the given object handle.
+ CK_VOID_PTR getObject(const CK_OBJECT_HANDLE hObject);
+
+ // Get the object handle for the object pointer that has been previously registered.
+ // When the object is not found CK_INVALID_HANDLE is returned.
+ CK_OBJECT_HANDLE getObjectHandle(CK_VOID_PTR object);
+
+ // Remove the given object handle.
+ void destroyObject(const CK_OBJECT_HANDLE hObject);
+
+ // Remove the given session handle and all session object handles for the session.
+ // The token object handles retrieved using the session will remain valid unless
+ // this is the last session of a token being closed. In that case remove all token
+ // object handles for the slot/token associated with the session.
+ void sessionClosed(const CK_SESSION_HANDLE hSession);
+
+ // Remove all session and object handles for the given slotID.
+ // All handles for the given slotID will become invalid.
+ void allSessionsClosed(const CK_SLOT_ID slotID);
+
+ // Remove all handles to private objects for the given slotID.
+ // All handles to public objects for the given slotID remain valid.
+ void tokenLoggedOut(const CK_SLOT_ID slotID);
+
+private:
+ Mutex* handlesMutex;
+ std::map< CK_ULONG, Handle> handles;
+ std::map< CK_VOID_PTR, CK_ULONG> objects;
+ CK_ULONG handleCounter;
+};
+
+#endif // !_SOFTHSM_V2_HANDLEMANAGER_H
+
diff --git a/SoftHSMv2/src/lib/handle_mgr/Makefile.am b/SoftHSMv2/src/lib/handle_mgr/Makefile.am
new file mode 100644
index 0000000..108f74d
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/Makefile.am
@@ -0,0 +1,17 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/../object_store \
+ -I$(srcdir)/../pkcs11 \
+ -I$(srcdir)/../slot_mgr
+
+noinst_LTLIBRARIES = libsofthsm_handlemgr.la
+libsofthsm_handlemgr_la_SOURCES = HandleManager.cpp \
+ Handle.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.cpp b/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.cpp
new file mode 100644
index 0000000..fbf0403
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HandleManagerTests.cpp
+
+ Contains test cases to test the handle manager implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "HandleManagerTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HandleManagerTests);
+
+void HandleManagerTests::setUp()
+{
+ handleManager = new HandleManager();
+}
+
+void HandleManagerTests::tearDown()
+{
+ delete handleManager;
+}
+
+void HandleManagerTests::testHandleManager()
+{
+ CPPUNIT_ASSERT(handleManager != NULL);
+
+ CK_SLOT_ID slotID = 1234; // we need a unique value
+ CK_SESSION_HANDLE hSession;
+ CK_VOID_PTR session = &hSession; // we need a unique value
+ CK_SESSION_HANDLE hSession2;
+ CK_VOID_PTR session2 = &hSession2; // we need a unique value
+ CK_OBJECT_HANDLE hObject;
+ CK_VOID_PTR object = &hObject; // we need a unique value
+ CK_OBJECT_HANDLE hObject2;
+ CK_VOID_PTR object2 = &hObject2; // we need a unique value
+ CK_OBJECT_HANDLE hObject3;
+ CK_VOID_PTR object3 = &hObject3; // we need a unique value
+ CK_OBJECT_HANDLE hObject4;
+ CK_VOID_PTR object4 = &hObject4; // we need a unique value
+ CK_OBJECT_HANDLE hObject5;
+ CK_VOID_PTR object5 = &hObject5; // we need a unique value
+
+ // Check session object management.
+ hSession = handleManager->addSession(slotID, session);
+ CPPUNIT_ASSERT(hSession != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session == handleManager->getSession(hSession));
+ CPPUNIT_ASSERT_NO_THROW(handleManager->sessionClosed(123124));
+ handleManager->sessionClosed(hSession);
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession));
+
+ // Add an object, hSession doesn't have to exists
+ hObject = handleManager->addSessionObject(slotID, 4412412, true, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+ handleManager->sessionClosed(4412412);
+ // Object still exists as the hSession was invalid
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+ handleManager->allSessionsClosed(slotID);
+ // Object is now gone as all sessions for the given slotID have been removed.
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject));
+
+ // Add an object and then destroy it.
+ hObject = handleManager->addSessionObject(slotID, 4412412, true, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ handleManager->destroyObject(hObject);
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject));
+
+ hObject = handleManager->addTokenObject(slotID, false, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ handleManager->destroyObject(hObject);
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject));
+
+ // Create a valid session again
+ hSession = handleManager->addSession(slotID, session);
+ CPPUNIT_ASSERT(hSession != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session == handleManager->getSession(hSession));
+
+ // Now some magic with a couple of objects
+ // First add a public object
+ hObject = handleManager->addTokenObject(slotID, false, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+
+ // Now add a private object
+ hObject2 = handleManager->addTokenObject(slotID, true, object2);
+ CPPUNIT_ASSERT(hObject2 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object2 == handleManager->getObject(hObject2));
+
+ // Now add another private object
+ hObject3 = handleManager->addTokenObject(slotID, true, object3);
+ CPPUNIT_ASSERT(hObject3 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object3 == handleManager->getObject(hObject3));
+
+ // Adding the same object will return the same handle whether the object is marked private or public.
+ CPPUNIT_ASSERT(hObject2 == handleManager->addTokenObject(slotID, true, object2));
+ // Because the private state of an object cannot be changed it won't be marked as public, it remains private
+ CPPUNIT_ASSERT(hObject2 == handleManager->addTokenObject(slotID, false, object2));
+
+ // It is not allowed to migrate an object from one slot to another, so here we return an invalid handle.
+ CPPUNIT_ASSERT(CK_INVALID_HANDLE == handleManager->addTokenObject(124121, false, object2));
+
+ // Now add another private session object
+ hObject4 = handleManager->addSessionObject(slotID, hSession, true, object4);
+ CPPUNIT_ASSERT(hObject4 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object4 == handleManager->getObject(hObject4));
+
+ // Now add another public session object
+ hObject5 = handleManager->addSessionObject(slotID, hSession, false, object5);
+ CPPUNIT_ASSERT(hObject5 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object5 == handleManager->getObject(hObject5));
+
+ // Logout, now private objects should be gone.
+ handleManager->tokenLoggedOut(slotID);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject2)); // should still be private and removed.
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject3));
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject4));
+ CPPUNIT_ASSERT(object5 == handleManager->getObject(hObject5));
+
+ // Create another valid session for the slot
+ hSession2 = handleManager->addSession(slotID, session2);
+ CPPUNIT_ASSERT(hSession2 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session2 == handleManager->getSession(hSession2));
+
+ handleManager->sessionClosed(hSession);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject)); // token object should still be there.
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject5)); // session object should be gone.
+
+ // Removing the last remaining session should kill the remaining handle.
+ handleManager->sessionClosed(hSession2);
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject)); // should be gone now.
+
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession));
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession2));
+
+
+ // Create a valid session again
+ hSession = handleManager->addSession(slotID, session);
+ CPPUNIT_ASSERT(hSession != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session == handleManager->getSession(hSession));
+
+ // Create another valid session for the slot
+ hSession2 = handleManager->addSession(slotID, session2);
+ CPPUNIT_ASSERT(hSession2 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session2 == handleManager->getSession(hSession2));
+
+ handleManager->allSessionsClosed(slotID);
+
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession));
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession2));
+}
diff --git a/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.h b/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.h
new file mode 100644
index 0000000..02022e4
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HandleManagerTests.h
+
+ Contains test cases to test the handle manager implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HANDLEMANAGERTESTS_H
+#define _SOFTHSM_V2_HANDLEMANAGERTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "RNG.h"
+#include "HandleManager.h"
+
+class HandleManagerTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(HandleManagerTests);
+ CPPUNIT_TEST(testHandleManager);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testHandleManager();
+
+ void setUp();
+ void tearDown();
+
+private:
+ HandleManager *handleManager;
+
+};
+
+#endif // !_SOFTHSM_V2_HANDLEMANAGERTESTS_H
+
diff --git a/SoftHSMv2/src/lib/handle_mgr/test/Makefile.am b/SoftHSMv2/src/lib/handle_mgr/test/Makefile.am
new file mode 100644
index 0000000..8d110b0
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/test/Makefile.am
@@ -0,0 +1,26 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../data_mgr \
+ -I$(srcdir)/../../object_store \
+ -I$(srcdir)/../../pkcs11 \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ @CPPUNIT_CFLAGS@
+
+check_PROGRAMS = handlemgrtest
+
+handlemgrtest_SOURCES = handlemgrtest.cpp \
+ HandleManagerTests.cpp
+
+handlemgrtest_LDADD = ../../libsofthsm_convarch.la
+
+handlemgrtest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install
+
+TESTS = handlemgrtest
+
+EXTRA_DIST = $(srcdir)/*.h
+
diff --git a/SoftHSMv2/src/lib/handle_mgr/test/handlemgrtest.cpp b/SoftHSMv2/src/lib/handle_mgr/test/handlemgrtest.cpp
new file mode 100644
index 0000000..eedb407
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/test/handlemgrtest.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ handlemgrtest.cpp
+
+ The main test executor for tests on the handle manager in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/XmlOutputter.h>
+#include <fstream>
+
+#include "config.h"
+#include "MutexFactory.h"
+
+#ifdef HAVE_CXX11
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+#else
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+#endif
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ CppUnit::TestResult controller;
+ CppUnit::TestResultCollector result;
+ CppUnit::TextUi::TestRunner runner;
+ controller.addListener(&result);
+ CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ runner.run(controller);
+
+ std::ofstream xmlFileOut("test-results.xml");
+ CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
+ xmlOut.write();
+
+ return result.wasSuccessful() ? 0 : 1;
+}