diff options
Diffstat (limited to 'SoftHSMv2/src/lib/handle_mgr')
-rw-r--r-- | SoftHSMv2/src/lib/handle_mgr/Handle.cpp | 50 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/handle_mgr/Handle.h | 62 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/handle_mgr/HandleManager.cpp | 239 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/handle_mgr/HandleManager.h | 94 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/handle_mgr/Makefile.am | 17 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.cpp | 178 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.h | 58 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/handle_mgr/test/Makefile.am | 26 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/handle_mgr/test/handlemgrtest.cpp | 65 |
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 ®istry = 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; +} |