aboutsummaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/lib/slot_mgr
diff options
context:
space:
mode:
Diffstat (limited to 'SoftHSMv2/src/lib/slot_mgr')
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/Makefile.am18
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/Slot.cpp116
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/Slot.h81
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/SlotManager.cpp179
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/SlotManager.h71
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/Token.cpp573
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/Token.h112
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/test/Makefile.am25
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.cpp485
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.h60
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/test/slotmgrtest.cpp91
11 files changed, 1811 insertions, 0 deletions
diff --git a/SoftHSMv2/src/lib/slot_mgr/Makefile.am b/SoftHSMv2/src/lib/slot_mgr/Makefile.am
new file mode 100644
index 0000000..1e8cf33
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/Makefile.am
@@ -0,0 +1,18 @@
+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)/../session_mgr
+
+noinst_LTLIBRARIES = libsofthsm_slotmgr.la
+libsofthsm_slotmgr_la_SOURCES = SlotManager.cpp \
+ Slot.cpp \
+ Token.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/slot_mgr/Slot.cpp b/SoftHSMv2/src/lib/slot_mgr/Slot.cpp
new file mode 100644
index 0000000..fea260b
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/Slot.cpp
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+/*****************************************************************************
+ Slot.h
+
+ This class represents a single PKCS #11 slot
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "SessionManager.h"
+#include "SlotManager.h"
+#include "Token.h"
+#include <stdio.h>
+#include <string.h>
+#include <sstream>
+
+// Constructor
+Slot::Slot(ObjectStore* inObjectStore, CK_SLOT_ID inSlotID, ObjectStoreToken* inToken /* = NULL */)
+{
+ objectStore = inObjectStore;
+ slotID = inSlotID;
+
+ if (inToken != NULL)
+ {
+ token = new Token(inToken);
+ }
+ else
+ {
+ token = new Token();
+ }
+}
+
+// Destructor
+Slot::~Slot()
+{
+ delete token;
+}
+
+// Retrieve the token in the slot
+Token* Slot::getToken()
+{
+ return token;
+}
+
+// Initialise the token in the slot
+CK_RV Slot::initToken(ByteString& soPIN, CK_UTF8CHAR_PTR label)
+{
+ return token->createToken(objectStore, soPIN, label);
+}
+
+// Retrieve slot information for the slot
+CK_RV Slot::getSlotInfo(CK_SLOT_INFO_PTR info)
+{
+ if (info == NULL)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ std::ostringstream osDescription;
+ osDescription << "SoftHSM slot ID 0x" << std::hex << slotID;
+ const std::string sDescription(osDescription.str());
+
+ char mfgID[33];
+ snprintf(mfgID, 33, "SoftHSM project");
+
+ memset(info->slotDescription, ' ', 64);
+ memset(info->manufacturerID, ' ', 32);
+ memcpy(info->slotDescription, sDescription.data(), sDescription.size());
+ memcpy(info->manufacturerID, mfgID, strlen(mfgID));
+
+ info->flags = CKF_TOKEN_PRESENT;
+
+ info->hardwareVersion.major = VERSION_MAJOR;
+ info->hardwareVersion.minor = VERSION_MINOR;
+ info->firmwareVersion.major = VERSION_MAJOR;
+ info->firmwareVersion.minor = VERSION_MINOR;
+
+ return CKR_OK;
+}
+
+// Get the slot ID
+CK_SLOT_ID Slot::getSlotID()
+{
+ return slotID;
+}
+
+// Is a token present?
+bool Slot::isTokenPresent()
+{
+ return true;
+}
diff --git a/SoftHSMv2/src/lib/slot_mgr/Slot.h b/SoftHSMv2/src/lib/slot_mgr/Slot.h
new file mode 100644
index 0000000..6ab07c6
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/Slot.h
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+/*****************************************************************************
+ Slot.h
+
+ This class represents a single PKCS #11 slot
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SLOT_H
+#define _SOFTHSM_V2_SLOT_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "ObjectStore.h"
+#include "ObjectStoreToken.h"
+#include "Token.h"
+#include "cryptoki.h"
+#include <string>
+#include <vector>
+
+class Slot
+{
+public:
+ // Constructor
+ Slot(ObjectStore* inObjectStore, CK_SLOT_ID inSlotID, ObjectStoreToken *inToken = NULL);
+
+ // Destructor
+ virtual ~Slot();
+
+ // Retrieve the token in the slot
+ Token* getToken();
+
+ // Initialise the token in the slot
+ CK_RV initToken(ByteString& pin, CK_UTF8CHAR_PTR label);
+
+ // Retrieve slot information for the slot
+ CK_RV getSlotInfo(CK_SLOT_INFO_PTR info);
+
+ // Get the slot ID
+ CK_SLOT_ID getSlotID();
+
+ // Is a token present?
+ bool isTokenPresent();
+
+private:
+ // A reference to the object store
+ ObjectStore* objectStore;
+
+ // The token in the slot
+ Token* token;
+
+ // The slot ID
+ CK_SLOT_ID slotID;
+};
+
+#endif // !_SOFTHSM_V2_SLOT_H
+
diff --git a/SoftHSMv2/src/lib/slot_mgr/SlotManager.cpp b/SoftHSMv2/src/lib/slot_mgr/SlotManager.cpp
new file mode 100644
index 0000000..1f96909
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/SlotManager.cpp
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+/*****************************************************************************
+ SlotManager.cpp
+
+ The slot manager is a class that forms part of the PKCS #11 core. It manages
+ all the slots that SoftHSM is aware of. To make it possible to add new
+ tokens, SoftHSM always has one slot available that contains an uninitialised
+ token. Users can choose to initialise this token to create a new token.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "SlotManager.h"
+#include <cassert>
+#include <stdexcept>
+typedef std::pair<CK_SLOT_ID, Slot*> SlotMapElement;
+typedef std::pair<SlotMap::iterator, bool> InsertResult;
+
+// Constructor
+SlotManager::SlotManager(ObjectStore*const objectStore)
+{
+ // Add a slot for each token that already exists
+ for (size_t i = 0; i < objectStore->getTokenCount(); i++)
+ {
+ ObjectStoreToken*const pToken(objectStore->getToken(i));
+ ByteString bs;
+ pToken->getTokenSerial(bs);
+ const std::string s((const char*)bs.const_byte_str(), bs.size());
+
+ // parse serial string that is expected to have only hex digits.
+ CK_SLOT_ID l;
+ if (s.size() < 8)
+ {
+ l = strtoul(s.c_str(), NULL, 16);
+ }
+ else
+ {
+ l = strtoul(s.substr(s.size() - 8).c_str(), NULL, 16);
+ }
+
+ // mask for 31 bits.
+ // this since sunpkcs11 java wrapper is parsing the slot ID to a java int that needs to be positive.
+ // java int is 32 bit and the the sign bit is removed.
+ const CK_SLOT_ID mask( ((CK_SLOT_ID)1<<31)-1 );
+ const CK_SLOT_ID slotID(mask&l);
+
+ insertToken(objectStore, slotID, pToken);
+ }
+
+ // Add an empty slot
+ insertToken(objectStore, objectStore->getTokenCount(), NULL);
+}
+
+void SlotManager::insertToken(ObjectStore*const objectStore, const CK_SLOT_ID slotID, ObjectStoreToken*const pToken) {
+ Slot*const newSlot( new Slot(objectStore, slotID, pToken) );
+ const InsertResult result( slots.insert(SlotMapElement(slotID, newSlot)) );
+ assert(result.second);// fails if there is already a token on this slot
+}
+
+// Destructor
+SlotManager::~SlotManager()
+{
+ SlotMap toDelete = slots;
+ slots.clear();
+
+ for (SlotMap::iterator i = toDelete.begin(); i != toDelete.end(); i++)
+ {
+ delete i->second;
+ }
+}
+
+// Get the slot list
+CK_RV SlotManager::getSlotList(ObjectStore* objectStore, CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
+{
+ size_t size( 0 );
+
+ if (pulCount == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Calculate the size of the list
+ bool uninitialized = false;
+ for (SlotMap::iterator i = slots.begin(); i != slots.end(); i++)
+ {
+ if ((tokenPresent == CK_FALSE) || i->second->isTokenPresent())
+ {
+ size++;
+ }
+
+ if (i->second->getToken() != NULL && i->second->getToken()->isInitialized() == false)
+ {
+ uninitialized = true;
+ }
+ }
+
+ // The user wants the size of the list
+ if (pSlotList == NULL)
+ {
+ // Always have an uninitialized token
+ if (uninitialized == false)
+ {
+ insertToken(objectStore, objectStore->getTokenCount(), NULL);
+ size++;
+ }
+
+ *pulCount = size;
+
+ return CKR_OK;
+ }
+
+ // Is the given buffer too small?
+ if (*pulCount < size)
+ {
+ *pulCount = size;
+
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ size_t startIx( 0 );
+ size_t endIx( size-1 );
+
+ for (SlotMap::iterator i = slots.begin(); i != slots.end(); i++)
+ {
+ if ((tokenPresent == CK_TRUE) && !i->second->isTokenPresent())
+ {// only show token if present on slot. But this slot has no token so we continue
+ continue;
+ }
+ // put uninitialized last. After all initialized or slots without tokens.
+ if ( i->second->isTokenPresent() && !i->second->getToken()->isInitialized() ) {
+ pSlotList[endIx--] = i->second->getSlotID();
+ } else {
+ pSlotList[startIx++] = i->second->getSlotID();
+ }
+ }
+ assert(startIx==endIx+1);
+ *pulCount = size;
+
+ return CKR_OK;
+}
+
+// Get the slots
+SlotMap SlotManager::getSlots()
+{
+ return slots;
+}
+
+// Get one slot
+Slot* SlotManager::getSlot(CK_SLOT_ID slotID)
+{
+ try {
+ return slots.at(slotID);
+ } catch( const std::out_of_range &oor) {
+ DEBUG_MSG("slotID is out of range: %s", oor.what());
+ return NULL_PTR;
+ }
+}
diff --git a/SoftHSMv2/src/lib/slot_mgr/SlotManager.h b/SoftHSMv2/src/lib/slot_mgr/SlotManager.h
new file mode 100644
index 0000000..04f51c0
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/SlotManager.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+/*****************************************************************************
+ SlotManager.h
+
+ The slot manager is a class that forms part of the PKCS #11 core. It manages
+ all the slots that SoftHSM is aware of. To make it possible to add new
+ tokens, SoftHSM always has one slot available that contains an uninitialised
+ token. Users can choose to initialise this token to create a new token.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SLOTMANAGER_H
+#define _SOFTHSM_V2_SLOTMANAGER_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "ObjectStore.h"
+#include "Slot.h"
+#include <string>
+#include <map>
+typedef std::map<const CK_SLOT_ID, Slot*const> SlotMap;
+
+class SlotManager
+{
+public:
+ // Constructor
+ SlotManager(ObjectStore* objectStore);
+
+ // Destructor
+ virtual ~SlotManager();
+
+ // Get the slots
+ SlotMap getSlots();
+
+ // Get the slot list
+ CK_RV getSlotList(ObjectStore* objectStore, CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount);
+
+ // Get one slot
+ Slot* getSlot(CK_SLOT_ID slotID);
+private:
+ void insertToken(ObjectStore* objectStore, CK_SLOT_ID slotID, ObjectStoreToken* pToken);
+ // The slots
+ SlotMap slots;
+};
+
+#endif // !_SOFTHSM_V2_SLOTMANAGER_H
+
diff --git a/SoftHSMv2/src/lib/slot_mgr/Token.cpp b/SoftHSMv2/src/lib/slot_mgr/Token.cpp
new file mode 100644
index 0000000..b4c9401
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/Token.cpp
@@ -0,0 +1,573 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "log.h"
+#include "ObjectStore.h"
+#include "Token.h"
+#include "OSAttribute.h"
+#include "ByteString.h"
+#include "SecureDataManager.h"
+#include <cstdio>
+
+#ifndef _WIN32
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+
+// Constructor
+Token::Token()
+{
+ tokenMutex = MutexFactory::i()->getMutex();
+
+ token = NULL;
+ sdm = NULL;
+ valid = false;
+}
+
+// Constructor
+Token::Token(ObjectStoreToken* inToken)
+{
+ tokenMutex = MutexFactory::i()->getMutex();
+
+ token = inToken;
+
+ ByteString soPINBlob, userPINBlob;
+
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ sdm = new SecureDataManager(soPINBlob, userPINBlob);
+}
+
+// Destructor
+Token::~Token()
+{
+ if (sdm != NULL) delete sdm;
+
+ MutexFactory::i()->recycleMutex(tokenMutex);
+}
+
+// Check if the token is still valid
+bool Token::isValid()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ return (valid && token->isValid());
+}
+
+// Check if the token is initialized
+bool Token::isInitialized()
+{
+ if (token == NULL) return false;
+
+ return true;
+}
+
+// Check if SO is logged in
+bool Token::isSOLoggedIn()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->isSOLoggedIn();
+}
+
+// Check if user is logged in
+bool Token::isUserLoggedIn()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->isUserLoggedIn();
+}
+
+// Login SO
+CK_RV Token::loginSO(ByteString& pin)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // User cannot be logged in
+ if (sdm->isUserLoggedIn()) return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
+
+ // SO cannot be logged in
+ if (sdm->isSOLoggedIn()) return CKR_USER_ALREADY_LOGGED_IN;
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Login
+ if (!sdm->loginSO(pin))
+ {
+ flags |= CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_OK;
+}
+
+// Login user
+CK_RV Token::loginUser(ByteString& pin)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // SO cannot be logged in
+ if (sdm->isSOLoggedIn()) return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
+
+ // User cannot be logged in
+ if (sdm->isUserLoggedIn()) return CKR_USER_ALREADY_LOGGED_IN;
+
+ // The user PIN has to be initialized;
+ if (sdm->getUserPINBlob().size() == 0) return CKR_USER_PIN_NOT_INITIALIZED;
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Login
+ if (!sdm->loginUser(pin))
+ {
+ flags |= CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+
+ flags &= ~CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_OK;
+}
+
+CK_RV Token::reAuthenticate(ByteString& pin)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (sdm->isSOLoggedIn())
+ {
+ // Login
+ if (!sdm->reAuthenticateSO(pin))
+ {
+ flags |= CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+ else
+ {
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ }
+ }
+ else if (sdm->isUserLoggedIn())
+ {
+ // Login
+ if (!sdm->reAuthenticateUser(pin))
+ {
+ flags |= CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+ else
+ {
+ flags &= ~CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ }
+ }
+ else
+ {
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ return CKR_OK;
+}
+
+// Logout any user on this token;
+void Token::logout()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return;
+
+ sdm->logout();
+}
+
+// Change SO PIN
+CK_RV Token::setSOPIN(ByteString& oldPIN, ByteString& newPIN)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Verify oldPIN
+ SecureDataManager* verifier = new SecureDataManager(sdm->getSOPINBlob(), sdm->getUserPINBlob());
+ bool result = verifier->loginSO(oldPIN);
+ delete verifier;
+ if (result == false)
+ {
+ flags |= CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+
+ if (sdm->setSOPIN(newPIN) == false) return CKR_GENERAL_ERROR;
+
+ // Save PIN to token file
+ if (token->setSOPIN(sdm->getSOPINBlob()) == false) return CKR_GENERAL_ERROR;
+
+ ByteString soPINBlob, userPINBlob;
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+
+ return CKR_OK;
+}
+
+// Change the user PIN
+CK_RV Token::setUserPIN(ByteString& oldPIN, ByteString& newPIN)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // Check if user should stay logged in
+ bool stayLoggedIn = sdm->isUserLoggedIn();
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Verify oldPIN
+ SecureDataManager* newSdm = new SecureDataManager(sdm->getSOPINBlob(), sdm->getUserPINBlob());
+ if (newSdm->loginUser(oldPIN) == false)
+ {
+ flags |= CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ delete newSdm;
+ return CKR_PIN_INCORRECT;
+ }
+
+ // Set the new user PIN
+ if (newSdm->setUserPIN(newPIN) == false)
+ {
+ delete newSdm;
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Save PIN to token file
+ if (token->setUserPIN(newSdm->getUserPINBlob()) == false)
+ {
+ delete newSdm;
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Restore previous login state
+ if (!stayLoggedIn) newSdm->logout();
+
+ // Switch sdm
+ delete sdm;
+ sdm = newSdm;
+
+ ByteString soPINBlob, userPINBlob;
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ flags &= ~CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+
+ return CKR_OK;
+}
+
+// Init the user PIN
+CK_RV Token::initUserPIN(ByteString& pin)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ if (sdm->setUserPIN(pin) == false) return CKR_GENERAL_ERROR;
+
+ // Save PIN to token file
+ if (token->setUserPIN(sdm->getUserPINBlob()) == false) return CKR_GENERAL_ERROR;
+
+ ByteString soPINBlob, userPINBlob;
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ return CKR_OK;
+}
+
+// Create a new token
+CK_RV Token::createToken(ObjectStore* objectStore, ByteString& soPIN, CK_UTF8CHAR_PTR label)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (objectStore == NULL) return CKR_GENERAL_ERROR;
+ if (label == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Convert the label
+ ByteString labelByteStr((const unsigned char*) label, 32);
+
+ if (token != NULL)
+ {
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Verify SO PIN
+ if (sdm->getSOPINBlob().size() > 0 && !sdm->loginSO(soPIN))
+ {
+ flags |= CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+
+ ERROR_MSG("Incorrect SO PIN");
+ return CKR_PIN_INCORRECT;
+ }
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+
+ // Reset the token
+ if (!token->resetToken(labelByteStr))
+ {
+ ERROR_MSG("Could not reset the token");
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ else
+ {
+ // Generate the SO PIN blob
+ SecureDataManager soPINBlobGen;
+
+ if (!soPINBlobGen.setSOPIN(soPIN))
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Create the token
+ ObjectStoreToken* newToken = objectStore->newToken(labelByteStr);
+
+ if (newToken == NULL)
+ {
+ ERROR_MSG("Could not create the token");
+ return CKR_DEVICE_ERROR;
+ }
+
+ // Set the SO PIN on the token
+ if (!newToken->setSOPIN(soPINBlobGen.getSOPINBlob()))
+ {
+ ERROR_MSG("Failed to set SO PIN on new token");
+
+ if (!objectStore->destroyToken(newToken))
+ {
+ ERROR_MSG("Failed to destroy incomplete token");
+ }
+
+ return CKR_DEVICE_ERROR;
+ }
+
+ token = newToken;
+ }
+
+ ByteString soPINBlob, userPINBlob;
+
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ if (sdm != NULL) delete sdm;
+ sdm = new SecureDataManager(soPINBlob, userPINBlob);
+
+ return CKR_OK;
+}
+
+// Retrieve token information for the token
+CK_RV Token::getTokenInfo(CK_TOKEN_INFO_PTR info)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ ByteString label, serial;
+
+ if (info == NULL)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ memset(info->label, ' ', 32);
+ memset(info->serialNumber, ' ', 16);
+
+ // Token specific information
+ if (token)
+ {
+ if (!token->getTokenFlags(info->flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (token->getTokenLabel(label))
+ {
+ strncpy((char*) info->label, (char*) label.byte_str(), label.size());
+ }
+
+ if (token->getTokenSerial(serial))
+ {
+ strncpy((char*) info->serialNumber, (char*) serial.byte_str(), serial.size());
+ }
+ }
+ else
+ {
+ info->flags = CKF_RNG |
+ CKF_LOGIN_REQUIRED |
+ CKF_RESTORE_KEY_NOT_NEEDED |
+ CKF_SO_PIN_LOCKED |
+ CKF_SO_PIN_TO_BE_CHANGED;
+ }
+
+ // Information shared by all tokens
+ char mfgID[33];
+ char model[17];
+
+ snprintf(mfgID, 33, "SoftHSM project");
+ snprintf(model, 17, "SoftHSM v2");
+
+ memset(info->manufacturerID, ' ', 32);
+ memset(info->model, ' ', 16);
+ memcpy(info->manufacturerID, mfgID, strlen(mfgID));
+ memcpy(info->model, model, strlen(model));
+
+ // TODO: Can we set these?
+ info->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
+ info->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
+
+ info->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
+ info->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
+ info->ulMaxPinLen = MAX_PIN_LEN;
+ info->ulMinPinLen = MIN_PIN_LEN;
+ info->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ info->hardwareVersion.major = VERSION_MAJOR;
+ info->hardwareVersion.minor = VERSION_MINOR;
+ info->firmwareVersion.major = VERSION_MAJOR;
+ info->firmwareVersion.minor = VERSION_MINOR;
+
+ // Current time
+ time_t rawtime;
+ time(&rawtime);
+ char dateTime[17];
+ strftime(dateTime, 17, "%Y%m%d%H%M%S00", gmtime(&rawtime));
+ memcpy(info->utcTime, dateTime, 16);
+
+ return CKR_OK;
+}
+
+// Create an object
+OSObject* Token::createObject()
+{
+ return token->createObject();
+}
+
+void Token::getObjects(std::set<OSObject *> &objects)
+{
+ token->getObjects(objects);
+}
+
+bool Token::decrypt(const ByteString &encrypted, ByteString &plaintext)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->decrypt(encrypted,plaintext);
+}
+
+bool Token::encrypt(const ByteString &plaintext, ByteString &encrypted)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->encrypt(plaintext,encrypted);
+}
diff --git a/SoftHSMv2/src/lib/slot_mgr/Token.h b/SoftHSMv2/src/lib/slot_mgr/Token.h
new file mode 100644
index 0000000..8f67433
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/Token.h
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+/*****************************************************************************
+ Token.h
+
+ This class represents a single PKCS #11 token
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_TOKEN_H
+#define _SOFTHSM_V2_TOKEN_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "ObjectStore.h"
+#include "ObjectStoreToken.h"
+#include "SecureDataManager.h"
+#include "cryptoki.h"
+#include <string>
+#include <vector>
+
+class Token
+{
+public:
+ // Constructor
+ Token();
+ Token(ObjectStoreToken *inToken);
+
+ // Destructor
+ virtual ~Token();
+
+ // Create a new token
+ CK_RV createToken(ObjectStore* objectStore, ByteString& soPIN, CK_UTF8CHAR_PTR label);
+
+ // Is the token valid?
+ bool isValid();
+
+ // Is the token initialized?
+ bool isInitialized();
+
+ // Is SO or user logged in?
+ bool isSOLoggedIn();
+ bool isUserLoggedIn();
+
+ // Login
+ CK_RV loginSO(ByteString& pin);
+ CK_RV loginUser(ByteString& pin);
+
+ // Re-authentication
+ CK_RV reAuthenticate(ByteString& pin);
+
+ // Logout any user on this token;
+ void logout();
+
+ // Change PIN
+ CK_RV setSOPIN(ByteString& oldPIN, ByteString& newPIN);
+ CK_RV setUserPIN(ByteString& oldPIN, ByteString& newPIN);
+ CK_RV initUserPIN(ByteString& pin);
+
+ // Retrieve token information for the token
+ CK_RV getTokenInfo(CK_TOKEN_INFO_PTR info);
+
+ // Create object
+ OSObject *createObject();
+
+ // Insert all token objects into the given set.
+ void getObjects(std::set<OSObject *> &objects);
+
+ // Decrypt the supplied data
+ bool decrypt(const ByteString& encrypted, ByteString& plaintext);
+
+ // Encrypt the supplied data
+ bool encrypt(const ByteString& plaintext, ByteString& encrypted);
+
+private:
+ // Token validity
+ bool valid;
+
+ // A reference to the object store token
+ ObjectStoreToken* token;
+
+ // The secure data manager for this token
+ SecureDataManager* sdm;
+
+ Mutex* tokenMutex;
+};
+
+#endif // !_SOFTHSM_V2_TOKEN_H
+
diff --git a/SoftHSMv2/src/lib/slot_mgr/test/Makefile.am b/SoftHSMv2/src/lib/slot_mgr/test/Makefile.am
new file mode 100644
index 0000000..8e2d161
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/test/Makefile.am
@@ -0,0 +1,25 @@
+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 \
+ @CPPUNIT_CFLAGS@ \
+ @CRYPTO_INCLUDES@
+
+check_PROGRAMS = slotmgrtest
+
+slotmgrtest_SOURCES = slotmgrtest.cpp \
+ SlotManagerTests.cpp
+
+slotmgrtest_LDADD = ../../libsofthsm_convarch.la
+
+slotmgrtest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install -pthread
+
+TESTS = slotmgrtest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.cpp b/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.cpp
new file mode 100644
index 0000000..c5f6687
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.cpp
@@ -0,0 +1,485 @@
+/*
+ * 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.
+ */
+
+/*****************************************************************************
+ SlotManagerTests.cpp
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SlotManagerTests.h"
+#include "SlotManager.h"
+#include "Token.h"
+#include "ObjectStore.h"
+#include "ObjectFile.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "CryptoFactory.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SlotManagerTests);
+
+void SlotManagerTests::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void SlotManagerTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void SlotManagerTests::testNoExistingTokens()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 1);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotID() == testList[0]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+}
+
+void SlotManagerTests::testExistingTokens()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create two tokens
+ ByteString label1 = "DEADBEEF";
+ ByteString label2 = "DEADC0FFEE";
+
+ CPPUNIT_ASSERT(store.newToken(label1) != NULL);
+ CPPUNIT_ASSERT(store.newToken(label2) != NULL);
+
+ // Now attach the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 3);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotID() == testList[0]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotID() == testList[1]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getSlotID() == testList[2]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+}
+
+void SlotManagerTests::testInitialiseTokenInLastSlot()
+{
+ {
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 1);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotID() == testList[0]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+
+ // Now initialise the token in the first slot
+ ByteString soPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->initToken(soPIN, label) == CKR_OK);
+
+ // Retrieve slot information about the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, label, 32));
+ }
+
+ // Attach a fresh slot manager
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 2);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotID() == testList[0]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotID() == testList[1]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+
+ CK_UTF8CHAR label[33] = "My test token ";
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, label, 32));
+
+ // Retrieve slot information about the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+}
+
+void SlotManagerTests::testReinitialiseExistingToken()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create two tokens
+ ByteString label1 = "DEADBEEF";
+ ByteString label2 = "DEADC0FFEE";
+
+ CPPUNIT_ASSERT(store.newToken(label1) != NULL);
+ CPPUNIT_ASSERT(store.newToken(label2) != NULL);
+
+ // Now attach the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 3);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotID() == testList[0]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotID() == testList[1]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getSlotID() == testList[2]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+
+ // Now reinitialise the token in the second slot
+ ByteString soPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->initToken(soPIN, label) == CKR_OK);
+
+ // Retrieve slot information about the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, label, 32));
+}
+
+void SlotManagerTests::testUninitialisedToken()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Now attach the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 1);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+
+ // Initialise the token in the first slot
+ ByteString soPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->initToken(soPIN, label) == CKR_OK);
+
+ // Check if a new slot is added
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, NULL_PTR, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, NULL_PTR, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+
+ // get new list
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+
+ // Retrieve token information about the tokens
+ CK_TOKEN_INFO tokenInfo;
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+
+ // Initialise the token in the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->initToken(soPIN, label) == CKR_OK);
+
+ // Check if a new slot is added
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, NULL_PTR, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, NULL_PTR, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+
+ // get new list
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+
+ // Retrieve token information about the tokens
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+}
+
diff --git a/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.h b/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.h
new file mode 100644
index 0000000..8d4e57f
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+/*****************************************************************************
+ SlotManagerTests.h
+
+ Contains test cases to test the slot manager implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SLOTMANAGERTESTS_H
+#define _SOFTHSM_V2_SLOTMANAGERTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SlotManagerTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SlotManagerTests);
+ CPPUNIT_TEST(testNoExistingTokens);
+ CPPUNIT_TEST(testExistingTokens);
+ CPPUNIT_TEST(testInitialiseTokenInLastSlot);
+ CPPUNIT_TEST(testReinitialiseExistingToken);
+ CPPUNIT_TEST(testUninitialisedToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testNoExistingTokens();
+ void testExistingTokens();
+ void testInitialiseTokenInLastSlot();
+ void testReinitialiseExistingToken();
+ void testUninitialisedToken();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SLOTMANAGERTESTS_H
+
diff --git a/SoftHSMv2/src/lib/slot_mgr/test/slotmgrtest.cpp b/SoftHSMv2/src/lib/slot_mgr/test/slotmgrtest.cpp
new file mode 100644
index 0000000..4172b63
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/test/slotmgrtest.cpp
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+/*****************************************************************************
+ slotmgrtest.cpp
+
+ The main test executor for tests on the slot 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"
+#include "SecureMemoryRegistry.h"
+
+#if defined(WITH_OPENSSL)
+#include "OSSLCryptoFactory.h"
+#else
+#include "BotanCryptoFactory.h"
+#endif
+
+// Initialise the one-and-only instance
+#ifdef HAVE_CXX11
+
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
+#if defined(WITH_OPENSSL)
+std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
+#else
+std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
+#endif
+
+#else
+
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
+#if defined(WITH_OPENSSL)
+std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
+#else
+std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
+#endif
+
+#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();
+
+ CryptoFactory::reset();
+
+ return result.wasSuccessful() ? 0 : 1;
+}