From 0c89b3ccba7c9b7332ab67ae1936aff51ca62367 Mon Sep 17 00:00:00 2001 From: NingSun Date: Thu, 8 Feb 2018 08:34:03 -0800 Subject: Initial sshsm project structure Issue-ID: AAF-94 Change-Id: I5e82fff418e7567b161acf9b98013a9b85ffc5b4 Signed-off-by: NingSun --- SoftHSMv2/src/lib/slot_mgr/Token.cpp | 573 +++++++++++++++++++++++++++++++++++ 1 file changed, 573 insertions(+) create mode 100644 SoftHSMv2/src/lib/slot_mgr/Token.cpp (limited to 'SoftHSMv2/src/lib/slot_mgr/Token.cpp') 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 + +#ifndef _WIN32 +#include +#else +#include +#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 &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); +} -- cgit 1.2.3-korg