diff options
Diffstat (limited to 'SoftHSMv2/src/lib/session_mgr')
-rw-r--r-- | SoftHSMv2/src/lib/session_mgr/Makefile.am | 17 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/session_mgr/Session.cpp | 454 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/session_mgr/Session.h | 175 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/session_mgr/SessionManager.cpp | 246 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/session_mgr/SessionManager.h | 66 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/session_mgr/test/Makefile.am | 26 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.cpp | 260 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.h | 53 | ||||
-rw-r--r-- | SoftHSMv2/src/lib/session_mgr/test/sessionmgrtest.cpp | 111 |
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 ®istry = 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; +} |