summaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/lib/session_mgr
diff options
context:
space:
mode:
Diffstat (limited to 'SoftHSMv2/src/lib/session_mgr')
-rw-r--r--SoftHSMv2/src/lib/session_mgr/Makefile.am17
-rw-r--r--SoftHSMv2/src/lib/session_mgr/Session.cpp454
-rw-r--r--SoftHSMv2/src/lib/session_mgr/Session.h175
-rw-r--r--SoftHSMv2/src/lib/session_mgr/SessionManager.cpp246
-rw-r--r--SoftHSMv2/src/lib/session_mgr/SessionManager.h66
-rw-r--r--SoftHSMv2/src/lib/session_mgr/test/Makefile.am26
-rw-r--r--SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.cpp260
-rw-r--r--SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.h53
-rw-r--r--SoftHSMv2/src/lib/session_mgr/test/sessionmgrtest.cpp111
9 files changed, 1408 insertions, 0 deletions
diff --git a/SoftHSMv2/src/lib/session_mgr/Makefile.am b/SoftHSMv2/src/lib/session_mgr/Makefile.am
new file mode 100644
index 0000000..5186d33
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_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_sessionmgr.la
+libsofthsm_sessionmgr_la_SOURCES = SessionManager.cpp \
+ Session.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/session_mgr/Session.cpp b/SoftHSMv2/src/lib/session_mgr/Session.cpp
new file mode 100644
index 0000000..5db36fd
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/Session.cpp
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ Session.h
+
+ This class represents a single session
+ *****************************************************************************/
+
+#include "CryptoFactory.h"
+#include "Session.h"
+
+// Constructor
+Session::Session(Slot* inSlot, bool inIsReadWrite, CK_VOID_PTR inPApplication, CK_NOTIFY inNotify)
+{
+ slot = inSlot;
+ token = slot->getToken();
+ isReadWrite = inIsReadWrite;
+ hSession = CK_INVALID_HANDLE;
+ pApplication = inPApplication;
+ notify = inNotify;
+ operation = SESSION_OP_NONE;
+ findOp = NULL;
+ digestOp = NULL;
+ hashAlgo = HashAlgo::Unknown;
+ macOp = NULL;
+ asymmetricCryptoOp = NULL;
+ symmetricCryptoOp = NULL;
+ mechanism = AsymMech::Unknown;
+ reAuthentication = false;
+ allowSinglePartOp = false;
+ allowMultiPartOp = false;
+ publicKey = NULL;
+ privateKey = NULL;
+ symmetricKey = NULL;
+ param = NULL;
+ paramLen = 0;
+}
+
+// Constructor
+Session::Session()
+{
+ slot = NULL;
+ token = NULL;
+ isReadWrite = false;
+ hSession = CK_INVALID_HANDLE;
+ pApplication = NULL;
+ notify = NULL;
+ operation = SESSION_OP_NONE;
+ findOp = NULL;
+ digestOp = NULL;
+ hashAlgo = HashAlgo::Unknown;
+ macOp = NULL;
+ asymmetricCryptoOp = NULL;
+ symmetricCryptoOp = NULL;
+ mechanism = AsymMech::Unknown;
+ reAuthentication = false;
+ allowSinglePartOp = false;
+ allowMultiPartOp = false;
+ publicKey = NULL;
+ privateKey = NULL;
+ symmetricKey = NULL;
+ param = NULL;
+ paramLen = 0;
+}
+
+// Destructor
+Session::~Session()
+{
+ resetOp();
+}
+
+// Get session info
+CK_RV Session::getInfo(CK_SESSION_INFO_PTR pInfo)
+{
+ if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ pInfo->slotID = slot->getSlotID();
+
+ pInfo->state = getState();
+ pInfo->flags = CKF_SERIAL_SESSION;
+ if (isRW())
+ {
+ pInfo->flags |= CKF_RW_SESSION;
+ }
+ pInfo->ulDeviceError = 0;
+
+ return CKR_OK;
+}
+
+// Is a read and write session
+bool Session::isRW()
+{
+ return isReadWrite;
+}
+
+// Get session state
+CK_STATE Session::getState()
+{
+ if (token->isSOLoggedIn())
+ {
+ return CKS_RW_SO_FUNCTIONS;
+ }
+
+ if (token->isUserLoggedIn())
+ {
+ if (isRW())
+ {
+ return CKS_RW_USER_FUNCTIONS;
+ }
+ else
+ {
+ return CKS_RO_USER_FUNCTIONS;
+ }
+ }
+
+ if (isRW())
+ {
+ return CKS_RW_PUBLIC_SESSION;
+ }
+ else
+ {
+ return CKS_RO_PUBLIC_SESSION;
+ }
+}
+
+void Session::setHandle(CK_SESSION_HANDLE inHSession)
+{
+ hSession = inHSession;
+}
+
+CK_SESSION_HANDLE Session::getHandle()
+{
+ return hSession;
+}
+
+// Return the slot that the session is connected to
+Slot* Session::getSlot()
+{
+ return slot;
+}
+
+// Return the token that the session is connected to
+Token* Session::getToken()
+{
+ return token;
+}
+
+// Set the operation type
+void Session::setOpType(int inOperation)
+{
+ operation = inOperation;
+}
+
+// Get the operation type
+int Session::getOpType()
+{
+ return operation;
+}
+
+// Reset the operations
+void Session::resetOp()
+{
+ if (param != NULL)
+ {
+ free(param);
+ param = NULL;
+ paramLen = 0;
+ }
+
+ if (digestOp != NULL)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(digestOp);
+ digestOp = NULL;
+ }
+ else if (findOp != NULL)
+ {
+ findOp->recycle();
+ findOp = NULL;
+ }
+ else if (asymmetricCryptoOp != NULL)
+ {
+ if (publicKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePublicKey(publicKey);
+ publicKey = NULL;
+ }
+ if (privateKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePrivateKey(privateKey);
+ privateKey = NULL;
+ }
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymmetricCryptoOp);
+ asymmetricCryptoOp = NULL;
+ }
+ else if (symmetricCryptoOp != NULL)
+ {
+ if (symmetricKey != NULL)
+ {
+ symmetricCryptoOp->recycleKey(symmetricKey);
+ symmetricKey = NULL;
+ }
+ CryptoFactory::i()->recycleSymmetricAlgorithm(symmetricCryptoOp);
+ symmetricCryptoOp = NULL;
+ }
+ else if (macOp != NULL)
+ {
+ if (symmetricKey != NULL)
+ {
+ macOp->recycleKey(symmetricKey);
+ symmetricKey = NULL;
+ }
+ CryptoFactory::i()->recycleMacAlgorithm(macOp);
+ macOp = NULL;
+ }
+
+ operation = SESSION_OP_NONE;
+ reAuthentication = false;
+}
+
+void Session::setFindOp(FindOperation *inFindOp)
+{
+ if (findOp != NULL) {
+ delete findOp;
+ }
+ findOp = inFindOp;
+}
+
+FindOperation *Session::getFindOp()
+{
+ return findOp;
+}
+
+// Set the digesting operator
+void Session::setDigestOp(HashAlgorithm* inDigestOp)
+{
+ if (digestOp != NULL)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(digestOp);
+ }
+
+ digestOp = inDigestOp;
+}
+
+// Get the digesting operator
+HashAlgorithm* Session::getDigestOp()
+{
+ return digestOp;
+}
+
+void Session::setHashAlgo(HashAlgo::Type inHashAlgo)
+{
+ hashAlgo = inHashAlgo;
+}
+
+HashAlgo::Type Session::getHashAlgo()
+{
+ return hashAlgo;
+}
+
+// Set the MACing operator
+void Session::setMacOp(MacAlgorithm *inMacOp)
+{
+ if (macOp != NULL)
+ {
+ setSymmetricKey(NULL);
+ CryptoFactory::i()->recycleMacAlgorithm(macOp);
+ }
+
+ macOp = inMacOp;
+}
+
+// Get the MACing operator
+MacAlgorithm *Session::getMacOp()
+{
+ return macOp;
+}
+
+void Session::setAsymmetricCryptoOp(AsymmetricAlgorithm *inAsymmetricCryptoOp)
+{
+ if (asymmetricCryptoOp != NULL)
+ {
+ setPublicKey(NULL);
+ setPrivateKey(NULL);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymmetricCryptoOp);
+ }
+
+ asymmetricCryptoOp = inAsymmetricCryptoOp;
+}
+
+AsymmetricAlgorithm *Session::getAsymmetricCryptoOp()
+{
+ return asymmetricCryptoOp;
+}
+
+void Session::setSymmetricCryptoOp(SymmetricAlgorithm *inSymmetricCryptoOp)
+{
+ if (symmetricCryptoOp != NULL)
+ {
+ setSymmetricKey(NULL);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(symmetricCryptoOp);
+ }
+
+ symmetricCryptoOp = inSymmetricCryptoOp;
+}
+
+SymmetricAlgorithm *Session::getSymmetricCryptoOp()
+{
+ return symmetricCryptoOp;
+}
+
+void Session::setMechanism(AsymMech::Type inMechanism)
+{
+ mechanism = inMechanism;
+}
+
+AsymMech::Type Session::getMechanism()
+{
+ return mechanism;
+}
+
+void Session::setParameters(void* inParam, size_t inParamLen)
+{
+ if (inParam == NULL || inParamLen == 0) return;
+
+ if (param != NULL)
+ {
+ free(param);
+ paramLen = 0;
+ }
+
+ param = malloc(inParamLen);
+ if (param != NULL)
+ {
+ memcpy(param, inParam, inParamLen);
+ paramLen = inParamLen;
+ }
+}
+
+void* Session::getParameters(size_t& inParamLen)
+{
+ inParamLen = paramLen;
+ return param;
+}
+
+void Session::setReAuthentication(bool inReAuthentication)
+{
+ reAuthentication = inReAuthentication;
+}
+
+bool Session::getReAuthentication()
+{
+ return reAuthentication;
+}
+
+void Session::setAllowMultiPartOp(bool inAllowMultiPartOp)
+{
+ allowMultiPartOp = inAllowMultiPartOp;
+}
+
+bool Session::getAllowMultiPartOp()
+{
+ return allowMultiPartOp;
+}
+
+void Session::setAllowSinglePartOp(bool inAllowSinglePartOp)
+{
+ allowSinglePartOp = inAllowSinglePartOp;
+}
+
+bool Session::getAllowSinglePartOp()
+{
+ return allowSinglePartOp;
+}
+
+void Session::setPublicKey(PublicKey* inPublicKey)
+{
+ if (asymmetricCryptoOp == NULL)
+ return;
+
+ if (publicKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePublicKey(publicKey);
+ }
+
+ publicKey = inPublicKey;
+}
+
+PublicKey* Session::getPublicKey()
+{
+ return publicKey;
+}
+
+void Session::setPrivateKey(PrivateKey* inPrivateKey)
+{
+ if (asymmetricCryptoOp == NULL)
+ return;
+
+ if (privateKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePrivateKey(privateKey);
+ }
+
+ privateKey = inPrivateKey;
+}
+
+PrivateKey* Session::getPrivateKey()
+{
+ return privateKey;
+}
+
+void Session::setSymmetricKey(SymmetricKey* inSymmetricKey)
+{
+ if (symmetricKey != NULL)
+ {
+ if (macOp) {
+ macOp->recycleKey(symmetricKey);
+ } else if (symmetricCryptoOp) {
+ symmetricCryptoOp->recycleKey(symmetricKey);
+ } else {
+ return;
+ }
+ }
+
+ symmetricKey = inSymmetricKey;
+}
+
+SymmetricKey* Session::getSymmetricKey()
+{
+ return symmetricKey;
+}
diff --git a/SoftHSMv2/src/lib/session_mgr/Session.h b/SoftHSMv2/src/lib/session_mgr/Session.h
new file mode 100644
index 0000000..142aaa5
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/Session.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ Session.h
+
+ This class represents a single session
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSION_H
+#define _SOFTHSM_V2_SESSION_H
+
+#include "Slot.h"
+#include "FindOperation.h"
+#include "HashAlgorithm.h"
+#include "MacAlgorithm.h"
+#include "AsymmetricAlgorithm.h"
+#include "SymmetricAlgorithm.h"
+#include "Token.h"
+#include "cryptoki.h"
+
+#define SESSION_OP_NONE 0x0
+#define SESSION_OP_FIND 0x1
+#define SESSION_OP_ENCRYPT 0x2
+#define SESSION_OP_DECRYPT 0x3
+#define SESSION_OP_DIGEST 0x4
+#define SESSION_OP_SIGN 0x5
+#define SESSION_OP_VERIFY 0x6
+#define SESSION_OP_DIGEST_ENCRYPT 0x7
+#define SESSION_OP_DECRYPT_DIGEST 0x8
+#define SESSION_OP_SIGN_ENCRYPT 0x9
+#define SESSION_OP_DECRYPT_VERIFY 0x10
+
+class Session
+{
+public:
+ Session(Slot* inSlot, bool inIsReadWrite, CK_VOID_PTR inPApplication, CK_NOTIFY inNotify);
+
+ // Destructor
+ virtual ~Session();
+
+ // Slot and token
+ Slot* getSlot();
+ Token* getToken();
+
+ // Session properties
+ CK_RV getInfo(CK_SESSION_INFO_PTR pInfo);
+ bool isRW();
+ CK_STATE getState();
+ void setHandle(CK_SESSION_HANDLE inHSession);
+ CK_SESSION_HANDLE getHandle();
+
+ // Operations
+ int getOpType();
+ void setOpType(int inOperation);
+ void resetOp();
+
+ // Find
+ void setFindOp(FindOperation *inFindOp);
+ FindOperation *getFindOp();
+
+ // Digest
+ void setDigestOp(HashAlgorithm* inDigestOp);
+ HashAlgorithm* getDigestOp();
+ void setHashAlgo(HashAlgo::Type inHashAlgo);
+ HashAlgo::Type getHashAlgo();
+
+ // Mac
+ void setMacOp(MacAlgorithm* inMacOp);
+ MacAlgorithm* getMacOp();
+
+ // Asymmetric Crypto
+ void setAsymmetricCryptoOp(AsymmetricAlgorithm* inAsymmetricCryptoOp);
+ AsymmetricAlgorithm* getAsymmetricCryptoOp();
+
+ // Symmetric Crypto
+ void setSymmetricCryptoOp(SymmetricAlgorithm* inSymmetricCryptoOp);
+ SymmetricAlgorithm* getSymmetricCryptoOp();
+
+ void setMechanism(AsymMech::Type inMechanism);
+ AsymMech::Type getMechanism();
+
+ void setParameters(void* inParam, size_t inParamLen);
+ void* getParameters(size_t& inParamLen);
+
+ void setReAuthentication(bool inReAuthentication);
+ bool getReAuthentication();
+
+ void setAllowMultiPartOp(bool inAllowMultiPartOp);
+ bool getAllowMultiPartOp();
+
+ void setAllowSinglePartOp(bool inAllowSinglePartOp);
+ bool getAllowSinglePartOp();
+
+ void setPublicKey(PublicKey* inPublicKey);
+ PublicKey* getPublicKey();
+
+ void setPrivateKey(PrivateKey* inPrivateKey);
+ PrivateKey* getPrivateKey();
+
+ void setSymmetricKey(SymmetricKey* inSymmetricKey);
+ SymmetricKey* getSymmetricKey();
+
+private:
+ // Constructor
+ Session();
+
+ // Slot and token
+ Slot* slot;
+ Token* token;
+
+ // Application data (not in use)
+ CK_VOID_PTR pApplication;
+ CK_NOTIFY notify;
+
+ // Session properties
+ bool isReadWrite;
+ CK_SESSION_HANDLE hSession;
+
+ // Operations
+ int operation;
+
+ // Find
+ FindOperation *findOp;
+
+ // Digest
+ HashAlgorithm* digestOp;
+ HashAlgo::Type hashAlgo;
+
+ // Mac
+ MacAlgorithm* macOp;
+
+ // Asymmetric Crypto
+ AsymmetricAlgorithm* asymmetricCryptoOp;
+
+ // Symmetric Crypto
+ SymmetricAlgorithm* symmetricCryptoOp;
+
+ AsymMech::Type mechanism;
+ void* param;
+ size_t paramLen;
+ bool reAuthentication;
+ bool allowMultiPartOp;
+ bool allowSinglePartOp;
+ PublicKey* publicKey;
+ PrivateKey* privateKey;
+
+ // Symmetric Crypto
+ SymmetricKey* symmetricKey;
+};
+
+#endif // !_SOFTHSM_V2_SESSION_H
diff --git a/SoftHSMv2/src/lib/session_mgr/SessionManager.cpp b/SoftHSMv2/src/lib/session_mgr/SessionManager.cpp
new file mode 100644
index 0000000..b665210
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/SessionManager.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ SessionManager.cpp
+
+ Keeps track of the sessions within SoftHSM. The sessions are stored in a
+ vector. When a session is closed, its spot in the vector will be replaced
+ with NULL. Because we want to keep track of the session ID which is
+ equal to its location in the vector. New sessions will first fill up the NULL
+ locations and if there is no empty spots, then they are added to the end.
+ *****************************************************************************/
+
+#include "SessionManager.h"
+#include "log.h"
+
+// Constructor
+SessionManager::SessionManager()
+{
+ sessionsMutex = MutexFactory::i()->getMutex();
+}
+
+// Destructor
+SessionManager::~SessionManager()
+{
+ std::vector<Session*> toDelete = sessions;
+ sessions.clear();
+
+ for (std::vector<Session*>::iterator i = toDelete.begin(); i != toDelete.end(); i++)
+ {
+ if (*i != NULL) delete *i;
+ }
+
+ MutexFactory::i()->recycleMutex(sessionsMutex);
+}
+
+// Open a new session
+CK_RV SessionManager::openSession
+(
+ Slot* slot,
+ CK_FLAGS flags,
+ CK_VOID_PTR pApplication,
+ CK_NOTIFY notify,
+ CK_SESSION_HANDLE_PTR phSession
+)
+{
+ if (phSession == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (slot == NULL) return CKR_SLOT_ID_INVALID;
+ if ((flags & CKF_SERIAL_SESSION) == 0) return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // Get the token
+ Token* token = slot->getToken();
+ if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
+ if (!token->isInitialized()) return CKR_TOKEN_NOT_RECOGNIZED;
+
+ // Can not open a Read-Only session when in SO mode
+ if ((flags & CKF_RW_SESSION) == 0 && token->isSOLoggedIn()) return CKR_SESSION_READ_WRITE_SO_EXISTS;
+
+ // TODO: Do we want to check for maximum number of sessions?
+ // return CKR_SESSION_COUNT
+
+ // Create the session
+ bool rwSession = ((flags & CKF_RW_SESSION) == CKF_RW_SESSION) ? true : false;
+ Session* session = new Session(slot, rwSession, pApplication, notify);
+
+ // First fill any empty spot in the list
+ for (size_t i = 0; i < sessions.size(); i++)
+ {
+ if (sessions[i] != NULL)
+ {
+ continue;
+ }
+
+ sessions[i] = session;
+ session->setHandle(i + 1);
+ *phSession = session->getHandle();
+
+ return CKR_OK;
+ }
+
+ // Or add it to the end
+ sessions.push_back(session);
+ session->setHandle(sessions.size());
+ *phSession = session->getHandle();
+
+ return CKR_OK;
+}
+
+// Close a session
+CK_RV SessionManager::closeSession(CK_SESSION_HANDLE hSession)
+{
+ if (hSession == CK_INVALID_HANDLE) return CKR_SESSION_HANDLE_INVALID;
+
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // Check if we are out of range
+ if (hSession > sessions.size()) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if it is a closed session
+ unsigned long sessionID = hSession - 1;
+ if (sessions[sessionID] == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if this is the last session on the token
+ bool lastSession = true;
+ const CK_SLOT_ID slotID( sessions[sessionID]->getSlot()->getSlotID() );
+ for (size_t i = 0; i < sessions.size(); i++)
+ {
+ if (sessions[i] == NULL) continue;
+
+ if (sessions[i]->getSlot()->getSlotID() == slotID && i != sessionID)
+ {
+ lastSession = false;
+ break;
+ }
+ }
+
+ // Logout if this is the last session on the token
+ if (lastSession)
+ {
+ sessions[sessionID]->getSlot()->getToken()->logout();
+ }
+
+ // Close the session
+ delete sessions[sessionID];
+ sessions[sessionID] = NULL;
+
+ return CKR_OK;
+}
+
+// Close all sessions
+CK_RV SessionManager::closeAllSessions(Slot* slot)
+{
+ if (slot == NULL) return CKR_SLOT_ID_INVALID;
+
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // Get the token
+ Token* token = slot->getToken();
+ if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
+
+ // Close all sessions on this slot
+ const CK_SLOT_ID slotID( slot->getSlotID() );
+ for (std::vector<Session*>::iterator i = sessions.begin(); i != sessions.end(); i++)
+ {
+ if (*i == NULL) continue;
+
+ if ((*i)->getSlot()->getSlotID() == slotID)
+ {
+ delete *i;
+ *i = NULL;
+ }
+ }
+
+ // Logout from the token
+ token->logout();
+
+ return CKR_OK;
+}
+
+// Get session info
+CK_RV SessionManager::getSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
+{
+ // Get the session
+ Session* session = getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return session->getInfo(pInfo);
+}
+
+// Get the session
+Session* SessionManager::getSession(CK_SESSION_HANDLE hSession)
+{
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // We do not want to get a negative number below
+ if (hSession == CK_INVALID_HANDLE) return NULL;
+
+ // Check if we are out of range
+ if (hSession > sessions.size()) return NULL;
+
+ return sessions[hSession - 1];
+}
+
+bool SessionManager::haveSession(CK_SLOT_ID slotID)
+{
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ for (std::vector<Session*>::iterator i = sessions.begin(); i != sessions.end(); i++)
+ {
+ if (*i == NULL) continue;
+
+ if ((*i)->getSlot()->getSlotID() == slotID)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool SessionManager::haveROSession(CK_SLOT_ID slotID)
+{
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ for (std::vector<Session*>::iterator i = sessions.begin(); i != sessions.end(); i++)
+ {
+ if (*i == NULL) continue;
+
+ if ((*i)->getSlot()->getSlotID() != slotID) continue;
+
+ if ((*i)->isRW() == false) return true;
+ }
+
+ return false;
+}
diff --git a/SoftHSMv2/src/lib/session_mgr/SessionManager.h b/SoftHSMv2/src/lib/session_mgr/SessionManager.h
new file mode 100644
index 0000000..1091782
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/SessionManager.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ SessionManager.h
+
+ Keeps track of the sessions within SoftHSM
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONMANAGER_H
+#define _SOFTHSM_V2_SESSIONMANAGER_H
+
+#include "Slot.h"
+#include "Session.h"
+#include "MutexFactory.h"
+#include "config.h"
+#include "cryptoki.h"
+#include <memory>
+#include <vector>
+
+class SessionManager
+{
+public:
+ SessionManager();
+
+ virtual ~SessionManager();
+
+ CK_RV openSession(Slot* slot, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession);
+ CK_RV closeSession(CK_SESSION_HANDLE hSession);
+ CK_RV closeAllSessions(Slot* slot);
+ CK_RV getSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo);
+ Session* getSession(CK_SESSION_HANDLE hSession);
+ bool haveSession(CK_SLOT_ID slotID);
+ bool haveROSession(CK_SLOT_ID slotID);
+
+private:
+ // The sessions
+ std::vector<Session*> sessions;
+ Mutex* sessionsMutex;
+};
+
+#endif // !_SOFTHSM_V2_SESSIONMANAGER_H
+
diff --git a/SoftHSMv2/src/lib/session_mgr/test/Makefile.am b/SoftHSMv2/src/lib/session_mgr/test/Makefile.am
new file mode 100644
index 0000000..6395038
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_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@ \
+ @CRYPTO_INCLUDES@
+
+check_PROGRAMS = sessionmgrtest
+
+sessionmgrtest_SOURCES = sessionmgrtest.cpp \
+ SessionManagerTests.cpp
+
+sessionmgrtest_LDADD = ../../libsofthsm_convarch.la
+
+sessionmgrtest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install -pthread
+
+TESTS = sessionmgrtest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.cpp b/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.cpp
new file mode 100644
index 0000000..2c2e51a
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ SessionManagerTests.cpp
+
+ Contains test cases for SessionManager
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SessionManagerTests.h"
+#include "ObjectStore.h"
+#include "SessionManager.h"
+#include "Session.h"
+#include "SlotManager.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionManagerTests);
+
+void SessionManagerTests::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void SessionManagerTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void SessionManagerTests::testOpenClose()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create the managers
+ SlotManager slotManager(&store);
+ SessionManager sessionManager;
+
+ // Get a slot
+ CK_SLOT_ID slotID = 0;
+ Slot* slot = slotManager.getSlot(slotID);
+
+ // Use some bad data
+ CK_SESSION_HANDLE hSession;
+ CK_RV rv = sessionManager.openSession(NULL, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+ rv = sessionManager.openSession(slot, 0, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_PARALLEL_NOT_SUPPORTED);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ // Try open a slot with an uninitialized token
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_TOKEN_NOT_RECOGNIZED);
+
+ // Initialize the token
+ ByteString soPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+ CPPUNIT_ASSERT(slot->initToken(soPIN, label) == CKR_OK);
+
+ // Open a session
+ bool haveSession = sessionManager.haveSession(slotID);
+ CPPUNIT_ASSERT(haveSession == false);
+ bool haveROSession = sessionManager.haveROSession(slotID);
+ CPPUNIT_ASSERT(haveROSession == false);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ haveSession = sessionManager.haveSession(slotID);
+ CPPUNIT_ASSERT(haveSession == true);
+ haveROSession = sessionManager.haveROSession(slotID);
+ CPPUNIT_ASSERT(haveROSession == true);
+
+ // Close session
+ rv = sessionManager.closeSession(CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+ haveSession = sessionManager.haveSession(slotID);
+ CPPUNIT_ASSERT(haveSession == false);
+ haveROSession = sessionManager.haveROSession(slotID);
+ CPPUNIT_ASSERT(haveROSession == false);
+
+ // Try open a Read-Only session when in SO mode
+ rv = slot->getToken()->loginSO(soPIN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_WRITE_SO_EXISTS);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ haveSession = sessionManager.haveSession(slotID);
+ CPPUNIT_ASSERT(haveSession == true);
+ haveROSession = sessionManager.haveROSession(slotID);
+ CPPUNIT_ASSERT(haveROSession == false);
+
+ // Close session and check that we are logged out
+ bool isLoggedIn = slot->getToken()->isSOLoggedIn();
+ CPPUNIT_ASSERT(isLoggedIn == true);
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ isLoggedIn = slot->getToken()->isSOLoggedIn();
+ CPPUNIT_ASSERT(isLoggedIn == false);
+ haveSession = sessionManager.haveSession(slotID);
+ CPPUNIT_ASSERT(haveSession == false);
+ haveROSession = sessionManager.haveROSession(slotID);
+ CPPUNIT_ASSERT(haveROSession == false);
+
+ // Open a new logged in session
+ rv = slot->getToken()->loginSO(soPIN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close all sessions and check that we are logged out
+ isLoggedIn = slot->getToken()->isSOLoggedIn();
+ CPPUNIT_ASSERT(isLoggedIn == true);
+ rv = sessionManager.closeAllSessions(NULL);
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+ rv = sessionManager.closeAllSessions(slot);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ isLoggedIn = slot->getToken()->isSOLoggedIn();
+ CPPUNIT_ASSERT(isLoggedIn == false);
+}
+
+void SessionManagerTests::testSessionInfo()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create the managers
+ SlotManager slotManager(&store);
+ SessionManager sessionManager;
+
+ // Get a slot
+ CK_SLOT_ID slotID = 0;
+ Slot* slot = slotManager.getSlot(slotID);
+
+ // Initialize the token
+ ByteString soPIN((unsigned char*)"1234", 4);
+ ByteString userPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+ CPPUNIT_ASSERT(slot->initToken(soPIN, label) == CKR_OK);
+ CPPUNIT_ASSERT(slot->getToken()->loginSO(soPIN) == CKR_OK);
+ CPPUNIT_ASSERT(slot->getToken()->initUserPIN(userPIN) == CKR_OK);
+ slot->getToken()->logout();
+
+ // Get a session
+ CK_SESSION_HANDLE hSession;
+ CK_RV rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get session info
+ CK_SESSION_INFO info;
+ rv = sessionManager.getSessionInfo(CK_INVALID_HANDLE, &info);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+ rv = sessionManager.getSessionInfo(hSession, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+ rv = sessionManager.getSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Public RO session info
+ CPPUNIT_ASSERT(info.slotID == slotID);
+ CPPUNIT_ASSERT(info.state == CKS_RO_PUBLIC_SESSION);
+ CPPUNIT_ASSERT(info.flags == CKF_SERIAL_SESSION);
+
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Public RW session info
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ Session* session = sessionManager.getSession(CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session == NULL);
+ session = sessionManager.getSession(hSession);
+ CPPUNIT_ASSERT(session != NULL);
+ rv = session->getInfo(&info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(info.state == CKS_RW_PUBLIC_SESSION);
+ CPPUNIT_ASSERT(info.flags == (CKF_SERIAL_SESSION | CKF_RW_SESSION));
+
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // User RO session info
+ rv = slot->getToken()->loginUser(userPIN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.getSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(info.state == CKS_RO_USER_FUNCTIONS);
+ CPPUNIT_ASSERT(info.flags == CKF_SERIAL_SESSION);
+
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // User RW session info
+ rv = slot->getToken()->loginUser(userPIN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.getSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(info.state == CKS_RW_USER_FUNCTIONS);
+ CPPUNIT_ASSERT(info.flags == (CKF_SERIAL_SESSION | CKF_RW_SESSION));
+
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // SO RW session info
+ rv = slot->getToken()->loginSO(soPIN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.getSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(info.state == CKS_RW_SO_FUNCTIONS);
+ CPPUNIT_ASSERT(info.flags == (CKF_SERIAL_SESSION | CKF_RW_SESSION));
+
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.h b/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.h
new file mode 100644
index 0000000..23f9d8c
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ SessionManagerTests.h
+
+ Contains test cases for SessionManager
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONMANAGERTESTS_H
+#define _SOFTHSM_V2_SESSIONMANAGERTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SessionManagerTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SessionManagerTests);
+ CPPUNIT_TEST(testOpenClose);
+ CPPUNIT_TEST(testSessionInfo);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testOpenClose();
+ void testSessionInfo();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONMANAGERTESTS_H
diff --git a/SoftHSMv2/src/lib/session_mgr/test/sessionmgrtest.cpp b/SoftHSMv2/src/lib/session_mgr/test/sessionmgrtest.cpp
new file mode 100644
index 0000000..28eeee8
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/test/sessionmgrtest.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+/*****************************************************************************
+ sessionmgrtest.cpp
+
+ The main test executor for tests on the session manager in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestFailure.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/SourceLine.h>
+#include <cppunit/Message.h>
+#include <cppunit/Exception.h>
+#include <cppunit/XmlOutputter.h>
+#include <fstream>
+#include <stdlib.h>
+#include <iostream>
+
+#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
+
+class MyListener : public CPPUNIT_NS::TestListener {
+ virtual void startTest( CPPUNIT_NS::Test*const pTest ) {
+ std::cout << std::endl << pTest->getName() << ' ' << pTest->countTestCases() << std::endl << std::endl;
+ }
+ virtual void addFailure( const CPPUNIT_NS::TestFailure & failure ) {
+ const CPPUNIT_NS::SourceLine solurceLine( failure.sourceLine() );
+ CPPUNIT_NS::Message message( failure.thrownException()->message() );
+ std::cout << solurceLine.fileName() << ' ' << solurceLine.lineNumber() << ' ' << message.shortDescription() << std::endl;
+ std::cout << message.details() << std::endl << std::endl;
+ }
+};
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ CppUnit::TestResult controller;
+ CppUnit::TestResultCollector result;
+ CppUnit::TextUi::TestRunner runner;
+ controller.addListener(&result);
+ MyListener progress;
+ controller.addListener(&progress);
+ 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;
+}