/*
- * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2021 Samsung Electronics Co., Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <key-aes-impl.h>
#include <certificate-config.h>
#include <certificate-store.h>
-#include <dirent.h>
#include <algorithm>
-#include <InitialValuesFile.h>
#include <sw-backend/store.h>
#include <generic-backend/exception.h>
+#include <ss-migrate.h>
namespace {
-const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
-const char * const INIT_VALUES_DIR = "/opt/data/ckm/initial_values/";
-const char * const INIT_VALUES_XSD = "/usr/share/ckm/initial_values.xsd";
-const char * const INIT_VALUES_FILE_SUFFIX = ".xml";
-const char * const SYSTEM_DB_PASSWD = "cAtRugU7";
-
-bool isLabelValid(const CKM::Label &label) {
- // TODO: copy code from libprivilege control (for check smack label)
- if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos)
- return false;
- return true;
+const char *const CERT_SYSTEM_DIR = CA_CERTS_DIR;
+const char *const DEFAULT_UNLOCK_STRING = "cAtRugU7";
+
+bool isClientValid(const CKM::ClientId &client)
+{
+ if (client.find(CKM::ALIAS_SEPARATOR) != CKM::ClientId::npos)
+ return false;
+
+ return true;
}
-bool isNameValid(const CKM::Name &name) {
- if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
- return false;
- return true;
+bool isNameValid(const CKM::Name &name)
+{
+ if (name.find(CKM::ALIAS_SEPARATOR) != CKM::Name::npos)
+ return false;
+
+ return true;
}
+
} // anonymous namespace
namespace CKM {
+namespace {
+
+template <int ERROR_ON_CKM_EXCEPTION = CKM_API_ERROR_SERVER_ERROR, class F>
+int tryRet(F &&f)
+{
+ try {
+ static_assert(std::is_same_v<decltype(std::forward<F>(f)()), int>);
+ return std::forward<F>(f)();
+ } catch (const Exc::Exception &e) {
+ return e.error();
+ } catch (const CKM::Exception &e) {
+ LogError("CKM::Exception: " << e.GetMessage());
+ return ERROR_ON_CKM_EXCEPTION;
+ }
+}
+
+int toBinaryData(const Crypto::Data &input, Crypto::Data &output)
+{
+ // verify the data integrity
+ if (input.type.isKey()) {
+ KeyShPtr output_key;
+
+ if (input.type.isSymmetricKey())
+ output_key = CKM::Key::createAES(input.data);
+ else
+ output_key = CKM::Key::create(input.data);
+
+ if (output_key.get() == NULL) {
+ LogDebug("provided binary data is not valid key data");
+ return CKM_API_ERROR_INPUT_PARAM;
+ }
+
+ output = Crypto::Data(input.type, output_key->getDER());
+ } else if (input.type.isCertificate() || input.type.isChainCert()) {
+ CertificateShPtr cert = CKM::Certificate::create(input.data, DataFormat::FORM_DER);
+
+ if (cert.get() == NULL) {
+ LogDebug("provided binary data is not valid certificate data");
+ return CKM_API_ERROR_INPUT_PARAM;
+ }
+
+ output = Crypto::Data(input.type, cert->getDER());
+ } else {
+ output = input;
+ }
+
+ // TODO: add here BINARY_DATA verification, i.e: max size etc.
+ return CKM_API_SUCCESS;
+}
+
+int verifyBinaryData(const Crypto::Data &input)
+{
+ Crypto::Data dummy;
+ return toBinaryData(input, dummy);
+}
+
+int readSingleRow(const Name &name,
+ const ClientId &owner,
+ DataType dataType,
+ DB::Crypto &database,
+ DB::Row &row)
+{
+ DB::Crypto::RowOptional row_optional;
+
+ if (dataType.isKey()) {
+ // read all key types
+ row_optional = database.getRow(name,
+ owner,
+ DataType::DB_KEY_FIRST,
+ DataType::DB_KEY_LAST);
+ } else {
+ // read anything else
+ row_optional = database.getRow(name,
+ owner,
+ dataType);
+ }
+
+ if (!row_optional) {
+ LogDebug("No row for given name, owner and type");
+ return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+ } else {
+ row = *row_optional;
+ }
+
+ return CKM_API_SUCCESS;
+}
+
+int readMultiRow(const Name &name,
+ const ClientId &owner,
+ DataType dataType,
+ DB::Crypto &database,
+ DB::RowVector &output)
+{
+ if (dataType.isKey())
+ // read all key types
+ database.getRows(name,
+ owner,
+ DataType::DB_KEY_FIRST,
+ DataType::DB_KEY_LAST,
+ output);
+ else if (dataType.isChainCert())
+ // read all key types
+ database.getRows(name,
+ owner,
+ DataType::DB_CHAIN_FIRST,
+ DataType::DB_CHAIN_LAST,
+ output);
+ else
+ // read anything else
+ database.getRows(name,
+ owner,
+ dataType,
+ output);
+
+ if (!output.size()) {
+ LogDebug("No row for given name, owner and type");
+ return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+ }
+
+ return CKM_API_SUCCESS;
+}
+
+} // namespace
+
const uid_t CKMLogic::SYSTEM_DB_UID = 0;
+const uid_t CKMLogic::ADMIN_USER_DB_UID = 5001;
CKMLogic::CKMLogic()
{
- CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
-
- m_accessControl.updateCCMode();
-
- // make initial file list
- std::vector<std::string> filesToParse;
- DIR *dp = opendir(INIT_VALUES_DIR);
- if(dp)
- {
- struct dirent *entry;
- while ((entry = readdir(dp)))
- {
- std::string filename = std::string(entry->d_name);
-
- // check if XML file
- std::string lowercaseFilename = filename;
- std::transform(lowercaseFilename.begin(), lowercaseFilename.end(), lowercaseFilename.begin(), ::tolower);
- if(lowercaseFilename.find(INIT_VALUES_FILE_SUFFIX) == std::string::npos)
- continue;
-
- filesToParse.push_back(std::string(INIT_VALUES_DIR) + filename);
- }
- closedir(dp);
- }
-
- // parse
- for(const auto & file : filesToParse)
- {
- InitialValues::InitialValuesFile xmlFile(file.c_str(), *this);
- int rc = xmlFile.Validate(INIT_VALUES_XSD);
- if(rc == XML::Parser::PARSE_SUCCESS)
- {
- rc = xmlFile.Parse();
- if(rc != XML::Parser::PARSE_SUCCESS)
- LogError("invalid initial values file: " << file << ", parsing code: " << rc);
- }
- else
- LogError("invalid initial values file: " << file << ", validation code: " << rc);
- unlink(file.c_str());
- }
+ CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
+
+ m_accessControl.updateCCMode();
}
-CKMLogic::~CKMLogic(){}
+CKMLogic::~CKMLogic() {}
-void CKMLogic::loadDKEKFile(uid_t user, const Password &password) {
- auto &handle = m_userDataMap[user];
+void CKMLogic::loadDKEKFile(uid_t user, const Password &password)
+{
+ auto &handle = m_userDataMap[user];
- FileSystem fs(user);
+ FileSystem fs(user);
- auto wrappedDKEK = fs.getDKEK();
+ auto wrappedDKEK = fs.getDKEK();
- if (wrappedDKEK.empty()) {
- wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
- fs.saveDKEK(wrappedDKEK);
- }
+ if (wrappedDKEK.empty()) {
+ wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
+ fs.saveDKEK(wrappedDKEK);
+ }
- handle.keyProvider = KeyProvider(wrappedDKEK, password);
+ handle.keyProvider = KeyProvider(wrappedDKEK, password);
+ if (!handle.keyProvider.isInitialized()) {
+ handle.keyProvider.migrateDomainKEK(wrappedDKEK, password);
+ fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
+ LogInfo("DKEK migrated");
+ }
}
-void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
- auto &handle = m_userDataMap[user];
+void CKMLogic::saveDKEKFile(uid_t user, const Password &password)
+{
+ auto &handle = m_userDataMap[user];
- FileSystem fs(user);
- fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
+ FileSystem fs(user);
+ fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
+}
+
+void CKMLogic::migrateSecureStorageData(bool isAdminUser)
+{
+ SsMigration::migrate(isAdminUser, [this](const std::string &name,
+ const Crypto::Data &data,
+ bool adminUserFlag) {
+ LogInfo("Migrate data called with name: " << name);
+ auto ownerId = adminUserFlag ? CLIENT_ID_ADMIN_USER : CLIENT_ID_SYSTEM;
+ auto uid = adminUserFlag ? ADMIN_USER_DB_UID : SYSTEM_DB_UID;
+
+ int ret = verifyAndSaveDataHelper(Credentials(uid, ownerId), name, ownerId, data,
+ PolicySerializable());
+
+ if (ret == CKM_API_ERROR_DB_ALIAS_EXISTS)
+ LogWarning("Alias already exist for migrated name: " << name);
+ else if (ret != CKM_API_SUCCESS)
+ LogError("Failed to migrate secure-storage data. name: " << name <<
+ " ret: " << ret);
+ });
}
-int CKMLogic::unlockDatabase(uid_t user, const Password & password)
+int CKMLogic::unlockDatabase(uid_t user, const Password &password)
{
- if (0<m_userDataMap.count(user) && m_userDataMap[user].keyProvider.isInitialized())
- return CKM_API_SUCCESS;
-
- int retCode = CKM_API_SUCCESS;
- try
- {
- auto &handle = m_userDataMap[user];
-
- FileSystem fs(user);
- loadDKEKFile(user, password);
-
- auto wrappedDatabaseDEK = fs.getDBDEK();
- if (wrappedDatabaseDEK.empty()) {
- wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
- fs.saveDBDEK(wrappedDatabaseDEK);
- }
-
- RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
-
- handle.database = DB::Crypto(fs.getDBPath(), key);
- handle.crypto = CryptoLogic();
-
- if ( !m_accessControl.isSystemService(user) )
- {
- // remove data of removed apps during locked state
- AppLabelVector removedApps = fs.clearRemovedsApps();
- for(auto& appSmackLabel : removedApps) {
- handle.crypto.removeKey(appSmackLabel);
- handle.database.deleteKey(appSmackLabel);
- }
- }
- } catch (const KeyProvider::Exception::PassWordError &e) {
- LogError("Incorrect Password " << e.GetMessage());
- retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
- } catch (const KeyProvider::Exception::Base &e) {
- LogError("Error in KeyProvider " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const CryptoLogic::Exception::Base &e) {
- LogError("CryptoLogic error: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const FileSystem::Exception::Base &e) {
- LogError("FileSystem error: " << e.GetMessage());
- retCode = CKM_API_ERROR_FILE_SYSTEM;
- } catch (const CKM::Exception &e) {
- LogError("CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
-
- if (CKM_API_SUCCESS != retCode)
- m_userDataMap.erase(user);
-
- return retCode;
+ if (0 < m_userDataMap.count(user) &&
+ m_userDataMap[user].keyProvider.isInitialized())
+ return CKM_API_SUCCESS;
+
+ int retCode = tryRet([&] {
+ auto &handle = m_userDataMap[user];
+
+ FileSystem fs(user);
+ loadDKEKFile(user, password);
+
+ auto wrappedDatabaseDEK = fs.getDBDEK();
+
+ if (wrappedDatabaseDEK.empty()) {
+ wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
+ fs.saveDBDEK(wrappedDatabaseDEK);
+ }
+
+ RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
+
+ handle.database = DB::Crypto(fs.getLegacyDBPath(), fs.getDBPath(), key);
+ handle.crypto = CryptoLogic();
+
+ if (!m_accessControl.isSystemService(user)) {
+ // remove data of removed apps during locked state
+ ClientIdVector removedApps = fs.clearRemovedsApps();
+
+ for (auto &app : removedApps) {
+ handle.crypto.removeKey(app);
+ handle.database.deleteKey(app);
+ }
+ }
+
+ if (user == SYSTEM_DB_UID && SsMigration::hasData())
+ migrateSecureStorageData(false);
+ else if (user == ADMIN_USER_DB_UID && SsMigration::hasData())
+ migrateSecureStorageData(true);
+
+ return CKM_API_SUCCESS;
+ });
+
+ if (CKM_API_SUCCESS != retCode)
+ m_userDataMap.erase(user);
+
+ return retCode;
}
int CKMLogic::unlockSystemDB()
{
- return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
+ return unlockDatabase(SYSTEM_DB_UID, DEFAULT_UNLOCK_STRING);
}
-UserData & CKMLogic::selectDatabase(const Credentials &cred, const Label &incoming_label)
+UserData &CKMLogic::selectDatabase(const Credentials &cred,
+ const ClientId &owner)
{
- // if user trying to access system service - check:
- // * if user database is unlocked [mandatory]
- // * if not - proceed with regular user database
- // * if explicit system database label given -> switch to system DB
- if ( !m_accessControl.isSystemService(cred) )
- {
- if (0 == m_userDataMap.count(cred.clientUid))
- ThrowMsg(Exception::DatabaseLocked, "database with UID: " << cred.clientUid << " locked");
-
- if (0 != incoming_label.compare(LABEL_SYSTEM_DB))
- return m_userDataMap[cred.clientUid];
- }
-
- // system database selected, modify the label
- if (CKM_API_SUCCESS != unlockSystemDB() )
- ThrowMsg(Exception::DatabaseLocked, "can not unlock system database");
- return m_userDataMap[SYSTEM_DB_UID];
+ // if user trying to access system service - check:
+ // * if user database is unlocked [mandatory]
+ // * if not - proceed with regular user database
+ // * if explicit system database owner given -> switch to system DB
+ if (!m_accessControl.isSystemService(cred)) {
+ if (0 == m_userDataMap.count(cred.clientUid))
+ ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
+
+ if (0 != owner.compare(CLIENT_ID_SYSTEM))
+ return m_userDataMap[cred.clientUid];
+ }
+
+ // system database selected, modify the owner id
+ if (CKM_API_SUCCESS != unlockSystemDB())
+ ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
+
+ return m_userDataMap[SYSTEM_DB_UID];
}
RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
{
- int retCode = CKM_API_SUCCESS;
-
- if( !m_accessControl.isSystemService(user) )
- {
- retCode = unlockDatabase(user, password);
- }
- else
- {
- // do not allow lock/unlock operations for system users
- retCode = CKM_API_ERROR_INPUT_PARAM;
- }
-
- return MessageBuffer::Serialize(retCode).Pop();
+ int retCode = CKM_API_SUCCESS;
+
+ if (!m_accessControl.isSystemService(user))
+ retCode = unlockDatabase(user, password);
+ else // do not allow lock/unlock operations for system users
+ retCode = CKM_API_ERROR_INPUT_PARAM;
+
+ return SerializeMessage(retCode);
}
-RawBuffer CKMLogic::updateCCMode() {
- m_accessControl.updateCCMode();
- return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
+RawBuffer CKMLogic::updateCCMode()
+{
+ m_accessControl.updateCCMode();
+ return SerializeMessage(CKM_API_SUCCESS);
}
RawBuffer CKMLogic::lockUserKey(uid_t user)
{
- int retCode = CKM_API_SUCCESS;
- if( !m_accessControl.isSystemService(user) )
- {
- m_userDataMap.erase(user);
- }
- else
- {
- // do not allow lock/unlock operations for system users
- retCode = CKM_API_ERROR_INPUT_PARAM;
- }
-
- return MessageBuffer::Serialize(retCode).Pop();
+ int retCode = CKM_API_SUCCESS;
-}
+ if (!m_accessControl.isSystemService(user))
+ m_userDataMap.erase(user);
+ else // do not allow lock/unlock operations for system users
+ retCode = CKM_API_ERROR_INPUT_PARAM;
-RawBuffer CKMLogic::removeUserData(uid_t user) {
- int retCode = CKM_API_SUCCESS;
+ return SerializeMessage(retCode);
+}
- if (m_accessControl.isSystemService(user))
- user = SYSTEM_DB_UID;
+RawBuffer CKMLogic::removeUserData(uid_t user)
+{
+ if (m_accessControl.isSystemService(user))
+ user = SYSTEM_DB_UID;
- m_userDataMap.erase(user);
+ m_userDataMap.erase(user);
- FileSystem fs(user);
- fs.removeUserData();
+ const int retCode = FileSystem(user).removeUserData()
+ ? CKM_API_ERROR_FILE_SYSTEM
+ : CKM_API_SUCCESS;
- return MessageBuffer::Serialize(retCode).Pop();
+ return SerializeMessage(retCode);
}
-int CKMLogic::changeUserPasswordHelper(uid_t user,
- const Password &oldPassword,
- const Password &newPassword)
+RawBuffer CKMLogic::changeUserPassword(
+ uid_t user,
+ const Password &oldPassword,
+ const Password &newPassword)
{
- // do not allow to change system database password
- if( m_accessControl.isSystemService(user) )
- return CKM_API_ERROR_INPUT_PARAM;
+ return SerializeMessage(tryRet([&] {
+ // do not allow to change system database password
+ if (m_accessControl.isSystemService(user))
+ return CKM_API_ERROR_INPUT_PARAM;
- loadDKEKFile(user, oldPassword);
- saveDKEKFile(user, newPassword);
+ loadDKEKFile(user, oldPassword);
+ saveDKEKFile(user, newPassword);
- return CKM_API_SUCCESS;
+ return CKM_API_SUCCESS;
+ }));
}
-RawBuffer CKMLogic::changeUserPassword(
- uid_t user,
- const Password &oldPassword,
- const Password &newPassword)
+RawBuffer CKMLogic::resetUserPassword(
+ uid_t user,
+ const Password &newPassword)
{
- int retCode = CKM_API_SUCCESS;
- try
- {
- retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
- } catch (const KeyProvider::Exception::PassWordError &e) {
- LogError("Incorrect Password " << e.GetMessage());
- retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
- } catch (const KeyProvider::Exception::Base &e) {
- LogError("Error in KeyProvider " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const FileSystem::Exception::Base &e) {
- LogError("Error in FileSystem " << e.GetMessage());
- retCode = CKM_API_ERROR_FILE_SYSTEM;
- } catch (const CKM::Exception &e) {
- LogError("CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
-
- return MessageBuffer::Serialize(retCode).Pop();
+ return SerializeMessage(tryRet([&] {
+ // do not allow to reset system database password
+ if (m_accessControl.isSystemService(user))
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ int retCode = CKM_API_SUCCESS;
+
+ if (0 == m_userDataMap.count(user)) {
+ // Check if key exists. If exists we must return error
+ FileSystem fs(user);
+ auto wrappedDKEKMain = fs.getDKEK();
+
+ if (!wrappedDKEKMain.empty())
+ retCode = CKM_API_ERROR_BAD_REQUEST;
+ } else {
+ saveDKEKFile(user, newPassword);
+ }
+
+ return retCode;
+ }));
}
-int CKMLogic::resetUserPasswordHelper(
- uid_t user,
- const Password &newPassword)
+RawBuffer CKMLogic::removeApplicationData(const ClientId &owner)
{
- // do not allow to reset system database password
- if( m_accessControl.isSystemService(user) )
- return CKM_API_ERROR_INPUT_PARAM;
-
- int retCode = CKM_API_SUCCESS;
- if (0 == m_userDataMap.count(user))
- {
- // Check if key exists. If exists we must return error
- FileSystem fs(user);
- auto wrappedDKEKMain = fs.getDKEK();
- if (!wrappedDKEKMain.empty())
- retCode = CKM_API_ERROR_BAD_REQUEST;
- } else {
- saveDKEKFile(user, newPassword);
- }
-
- return retCode;
+ return SerializeMessage(tryRet([&] {
+ if (owner.empty())
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ UidVector uids = FileSystem::getUIDsFromDBFile();
+
+ for (auto userId : uids) {
+ if (0 == m_userDataMap.count(userId)) {
+ FileSystem fs(userId);
+ fs.addRemovedApp(owner);
+ } else {
+ auto &handle = m_userDataMap[userId];
+ handle.crypto.removeKey(owner);
+ handle.database.deleteKey(owner);
+ }
+ }
+
+ return CKM_API_SUCCESS;
+ }));
}
-RawBuffer CKMLogic::resetUserPassword(
- uid_t user,
- const Password &newPassword)
+int CKMLogic::verifyAndSaveDataHelper(
+ const Credentials &cred,
+ const Name &name,
+ const ClientId &owner,
+ const Crypto::Data &data,
+ const PolicySerializable &policy)
{
- int retCode = CKM_API_SUCCESS;
- try {
- retCode = resetUserPasswordHelper(user, newPassword);
- } catch (const FileSystem::Exception::Base &e) {
- LogError("Error in FileSystem " << e.GetMessage());
- retCode = CKM_API_ERROR_FILE_SYSTEM;
- } catch (const CKM::Exception &e) {
- LogError("CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
-
- return MessageBuffer::Serialize(retCode).Pop();
-}
-
-RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
- int retCode = CKM_API_SUCCESS;
-
- try {
-
- if (smackLabel.empty()) {
- retCode = CKM_API_ERROR_INPUT_PARAM;
- } else {
- UidVector uids = FileSystem::getUIDsFromDBFile();
- for (auto userId : uids) {
- if (0 == m_userDataMap.count(userId)) {
- FileSystem fs(userId);
- fs.addRemovedApp(smackLabel);
- } else {
- auto &handle = m_userDataMap[userId];
- handle.crypto.removeKey(smackLabel);
- handle.database.deleteKey(smackLabel);
- }
- }
- }
-
- } catch (const DB::Crypto::Exception::InternalError &e) {
- LogError("DB::Crypto couldn't remove data: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const DB::Crypto::Exception::TransactionError &e) {
- LogError("DB::Crypto transaction failed with message " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const FileSystem::Exception::Base &e) {
- LogError("Error in FileSystem " << e.GetMessage());
- retCode = CKM_API_ERROR_FILE_SYSTEM;
- } catch (const CKM::Exception &e) {
- LogError("CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
-
- return MessageBuffer::Serialize(retCode).Pop();
+ return tryRet([&] {
+ // check if data is correct
+ Crypto::Data binaryData;
+ int retCode = toBinaryData(data, binaryData);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ auto [dbOp, digest, ret] = beginSaveAndGetHash(cred, name, owner);
+ if (ret != CKM_API_SUCCESS)
+ return ret;
+
+ Crypto::GStore &store = m_decider.getStore(binaryData.type, policy);
+
+ // do not encrypt data with password during cc_mode on
+ Token token = store.import(binaryData,
+ m_accessControl.isCCMode() ? "" : policy.password,
+ Crypto::EncryptionParams(), digest);
+ dbOp.finalize(std::move(token), policy);
+ return CKM_API_SUCCESS;
+ });
}
-int CKMLogic::checkSaveConditions(
- const Credentials &cred,
- UserData &handler,
- const Name &name,
- const Label &ownerLabel)
+int CKMLogic::getKeyForService(
+ const Credentials &cred,
+ const Name &name,
+ const ClientId &owner,
+ const Password &pass,
+ Crypto::GObjShPtr &key)
{
- // verify name and label are correct
- if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
- LogWarning("Invalid parameter passed to key-manager");
- return CKM_API_ERROR_INPUT_PARAM;
- }
-
- // check if allowed to save using ownerLabel
- int access_ec = m_accessControl.canSave(cred, ownerLabel);
- if( access_ec != CKM_API_SUCCESS)
- {
- LogWarning("label " << cred.smackLabel << " can not save rows using label " << ownerLabel);
- return access_ec;
- }
-
- // check if not a duplicate
- if( handler.database.isNameLabelPresent(name, ownerLabel))
- return CKM_API_ERROR_DB_ALIAS_EXISTS;
-
- // encryption section
- if (!handler.crypto.haveKey(ownerLabel))
- {
- RawBuffer got_key;
- auto key_optional = handler.database.getKey(ownerLabel);
- if(!key_optional) {
- LogDebug("No Key in database found. Generating new one for label: " << ownerLabel);
- got_key = handler.keyProvider.generateDEK(ownerLabel);
- handler.database.saveKey(ownerLabel, got_key);
- } else {
- LogDebug("Key from DB");
- got_key = *key_optional;
- }
-
- got_key = handler.keyProvider.getPureDEK(got_key);
- handler.crypto.pushKey(ownerLabel, got_key);
- }
-
- return CKM_API_SUCCESS;
+ return tryRet([&] {
+ // Key is for internal service use. It won't be exported to the client
+ Crypto::GObjUPtr obj;
+ int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, owner, pass, obj);
+ if (retCode == CKM_API_SUCCESS)
+ key = std::move(obj);
+
+ return retCode;
+ });
}
-DB::Row CKMLogic::createEncryptedRow(
- CryptoLogic &crypto,
- const Name &name,
- const Label &label,
- DataType dataType,
- const RawBuffer &data,
- const Policy &policy) const
+RawBuffer CKMLogic::saveData(
+ const Credentials &cred,
+ int msgId,
+ const Name &name,
+ const ClientId &owner,
+ const Crypto::Data &data,
+ const PolicySerializable &policy)
{
- DB::Row row(name, label, static_cast<int>(policy.extractable), dataType, data, static_cast<int>(data.size()));
- row.backendId = m_decider.chooseCryptoBackend(dataType, policy.extractable);
-
- // do not encrypt data with password during cc_mode on
- if(m_accessControl.isCCMode()) {
- crypto.encryptRow("", row);
- } else {
- crypto.encryptRow(policy.password, row);
- }
- return row;
+ int retCode = verifyAndSaveDataHelper(cred, name, owner, data, policy);
+ return SerializeMessage(msgId, retCode, data.type);
}
-int CKMLogic::verifyBinaryData(DataType dataType, RawBuffer &input_data) const
+RawBuffer CKMLogic::savePKCS12(
+ const Credentials &cred,
+ int msgId,
+ const Name &name,
+ const ClientId &owner,
+ const PKCS12Serializable &pkcs,
+ const PolicySerializable &keyPolicy,
+ const PolicySerializable &certPolicy)
{
- RawBuffer dummy;
- return toBinaryData(dataType, input_data, dummy);
+ return SerializeMessage(msgId, tryRet([&] {
+ auto [dbOp, retCode] = beginSave(cred, name, owner);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ // extract and encrypt the data
+ DB::RowVector encryptedRows;
+
+ auto import = [&](const Crypto::Data &data, const Policy& policy){
+ retCode = verifyBinaryData(data);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid, data.type);
+ if (digest.empty())
+ return CKM_API_ERROR_HASH_ERROR;
+
+ Crypto::GStore &store = m_decider.getStore(data.type, policy);
+
+ // do not encrypt data with password during cc_mode on
+ Token token = store.import(data,
+ m_accessControl.isCCMode() ? "" : policy.password,
+ Crypto::EncryptionParams(), digest);
+
+ encryptedRows.push_back(dbOp.encryptOne(std::move(token), policy));
+ return CKM_API_SUCCESS;
+ };
+
+ // private key is mandatory
+ auto key = pkcs.getKey();
+ if (!key) {
+ LogError("Failed to get private key from pkcs");
+ return CKM_API_ERROR_INVALID_FORMAT;
+ }
+
+ Crypto::Data keyData(DataType(key->getType()), key->getDER());
+ retCode = import(keyData, keyPolicy);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ // certificate is mandatory
+ auto cert = pkcs.getCertificate();
+ if (!cert) {
+ LogError("Failed to get certificate from pkcs");
+ return CKM_API_ERROR_INVALID_FORMAT;
+ }
+
+ Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
+ retCode = import(certData, certPolicy);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ // CA cert chain
+ unsigned int cert_index = 0;
+ for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
+ Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++), ca->getDER());
+ retCode = import(caCertData, certPolicy);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+ }
+
+ // save the data
+ dbOp.database().saveRows(name, owner, encryptedRows);
+ dbOp.transaction().commit();
+
+ return CKM_API_SUCCESS;
+ }));
}
-int CKMLogic::toBinaryData(DataType dataType,
- const RawBuffer &input_data,
- RawBuffer &output_data) const
+RawBuffer CKMLogic::removeData(
+ const Credentials &cred,
+ int msgId,
+ const Name &name,
+ const ClientId &owner)
{
- // verify the data integrity
- if (dataType.isKey())
- {
- KeyShPtr output_key;
- if(dataType.isSKey())
- output_key = CKM::Key::createAES(input_data);
- else
- output_key = CKM::Key::create(input_data);
- if(output_key.get() == NULL)
- {
- LogError("provided binary data is not valid key data");
- return CKM_API_ERROR_INPUT_PARAM;
- }
- output_data = output_key->getDER();
- }
- else if (dataType.isCertificate() || dataType.isChainCert())
- {
- CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
- if(cert.get() == NULL)
- {
- LogError("provided binary data is not valid certificate data");
- return CKM_API_ERROR_INPUT_PARAM;
- }
- output_data = cert->getDER();
- }
- else
- output_data = input_data;
- // TODO: add here BINARY_DATA verification, i.e: max size etc.
- return CKM_API_SUCCESS;
+ return SerializeMessage(msgId, tryRet([&] {
+ auto [dbOp, permission, retCode] = beginAndGetPerm(cred, name, owner);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ retCode = m_accessControl.canDelete(cred, permission);
+ if (retCode != CKM_API_SUCCESS) {
+ LogWarning("access control check result: " << retCode);
+ return retCode;
+ }
+
+ // get all matching rows
+ DB::RowVector rows;
+ dbOp.database().getRows(name, owner, DataType::DB_FIRST, DataType::DB_LAST, rows);
+ if (rows.empty()) {
+ LogDebug("No row for given name and owner");
+ return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+ }
+
+ retCode = dbOp.loadAppKey();
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ // destroy it in store
+ for (auto &r : rows) {
+ try {
+ dbOp.handler().crypto.decryptRow(Password(), r);
+ m_decider.getStore(r).destroy(r);
+ } catch (const Exc::AuthenticationFailed &) {
+ LogDebug("Authentication failed when removing data. Ignored.");
+ }
+ }
+
+ // delete row in db
+ dbOp.database().deleteRow(name, owner);
+ dbOp.transaction().commit();
+
+ return CKM_API_SUCCESS;
+ }));
}
-int CKMLogic::verifyAndSaveDataHelper(
- const Credentials &cred,
- const Name &name,
- const Label &label,
- const RawBuffer &data,
- DataType dataType,
- const PolicySerializable &policy)
+
+int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred,
+ const DB::Row &row,
+ bool exportFlag,
+ const PermissionMask& permission)
{
- int retCode = CKM_API_ERROR_UNKNOWN;
-
- try {
- // check if data is correct
- RawBuffer binaryData;
- retCode = toBinaryData(dataType, data, binaryData);
- if(retCode == CKM_API_SUCCESS)
- {
- retCode = saveDataHelper(cred, name, label, dataType, binaryData, policy);
- }
- } catch (const KeyProvider::Exception::Base &e) {
- LogError("KeyProvider failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const CryptoLogic::Exception::Base &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const DB::Crypto::Exception::InternalError &e) {
- LogError("DB::Crypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const DB::Crypto::Exception::TransactionError &e) {
- LogError("DB::Crypto transaction failed with message " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const FileSystem::Exception::Base &e) {
- LogError("Error in FileSystem " << e.GetMessage());
- retCode = CKM_API_ERROR_FILE_SYSTEM;
- } catch (const CKMLogic::Exception::DatabaseLocked &e) {
- LogError("Error " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_LOCKED;
- } catch (const CKM::Exception &e) {
- LogError("CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
- return retCode;
+ if (exportFlag)
+ return m_accessControl.canExport(accessorCred, row, permission);
+
+ return m_accessControl.canRead(accessorCred, permission);
}
-RawBuffer CKMLogic::saveData(
- const Credentials &cred,
- int commandId,
- const Name &name,
- const Label &label,
- const RawBuffer &data,
- DataType dataType,
- const PolicySerializable &policy)
+void CKMLogic::decryptRow(
+ UserData &handler,
+ DB::Row &row,
+ const Password &password,
+ const RawBuffer &hash)
{
- int retCode = verifyAndSaveDataHelper(cred, name, label, data, dataType, policy);
- auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
- commandId,
- retCode,
- static_cast<int>(dataType));
- return response.Pop();
+ if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
+ CryptoLogic::ENCRYPTION_V2) {
+ handler.crypto.decryptRow(Password(), row);
+ } else {
+ Crypto::GStore &store = m_decider.getStore(row);
+
+ Password pass = m_accessControl.isCCMode() ? "" : password;
+
+ // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
+ handler.crypto.decryptRow(pass, row);
+ // destroy it in store
+ store.destroy(row);
+
+ // import it to store with new scheme: data -> pass(data)
+ Token token = store.import(Crypto::Data(row.dataType, row.data),
+ pass,
+ Crypto::EncryptionParams(),
+ hash);
+
+ // update row with new token
+ *static_cast<Token *>(&row) = std::move(token);
+
+ // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
+ auto encryptedRow = handler.crypto.encryptRow(row);
+
+ // update it in db
+ handler.database.updateRow(encryptedRow);
+ }
}
-int CKMLogic::extractPKCS12Data(
- CryptoLogic &crypto,
- const Name &name,
- const Label &ownerLabel,
- const PKCS12Serializable &pkcs,
- const PolicySerializable &keyPolicy,
- const PolicySerializable &certPolicy,
- DB::RowVector &output) const
+Crypto::GObjUPtr CKMLogic::rowToObject(
+ UserData &handler,
+ DB::Row row,
+ const Password &password,
+ const RawBuffer &hash)
{
- // private key is mandatory
- if( !pkcs.getKey() )
- return CKM_API_ERROR_INVALID_FORMAT;
- Key* keyPtr = pkcs.getKey().get();
- DataType keyType = DataType(keyPtr->getType());
- RawBuffer keyData = keyPtr->getDER();
- int retCode = verifyBinaryData(keyType, keyData);
- if(retCode != CKM_API_SUCCESS)
- return retCode;
- output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyType, keyData, keyPolicy));
-
- // certificate is mandatory
- if( !pkcs.getCertificate() )
- return CKM_API_ERROR_INVALID_FORMAT;
- RawBuffer certData = pkcs.getCertificate().get()->getDER();
- retCode = verifyBinaryData(DataType::CERTIFICATE, certData);
- if(retCode != CKM_API_SUCCESS)
- return retCode;
- output.push_back(createEncryptedRow(crypto, name, ownerLabel, DataType::CERTIFICATE, certData, certPolicy));
-
- // CA cert chain
- unsigned int cert_index = 0;
- for(const auto & ca : pkcs.getCaCertificateShPtrVector())
- {
- DataType chainDataType = DataType::getChainDatatype(cert_index ++);
- RawBuffer caCertData = ca->getDER();
- int retCode = verifyBinaryData(chainDataType, caCertData);
- if(retCode != CKM_API_SUCCESS)
- return retCode;
-
- output.push_back(createEncryptedRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy));
- }
-
- return CKM_API_SUCCESS;
+ decryptRow(handler, row, password, hash);
+
+ return decryptedRowToObj(row, password);
}
-RawBuffer CKMLogic::savePKCS12(
- const Credentials &cred,
- int commandId,
- const Name &name,
- const Label &label,
- const PKCS12Serializable &pkcs,
- const PolicySerializable &keyPolicy,
- const PolicySerializable &certPolicy)
+int CKMLogic::readDataHelper(
+ bool exportFlag,
+ const Credentials &cred,
+ DataType dataType,
+ const Name &name,
+ const ClientId &owner,
+ const Password &password,
+ Crypto::GObjUPtrVector &objs)
{
- int retCode = CKM_API_ERROR_UNKNOWN;
- try {
- retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
- } catch (const KeyProvider::Exception::Base &e) {
- LogError("KeyProvider failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const CryptoLogic::Exception::Base &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const DB::Crypto::Exception::InternalError &e) {
- LogError("DB::Crypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const DB::Crypto::Exception::TransactionError &e) {
- LogError("DB::Crypto transaction failed with message " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const CKM::Exception &e) {
- LogError("CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
-
- auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
- commandId,
- retCode);
- return response.Pop();
-}
+ auto [dbOp, permission, retCode] = beginAndGetPerm(cred, name, owner);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+ // read rows
+ DB::RowVector rows;
+ retCode = readMultiRow(name, owner, dataType, dbOp.database(), rows);
+ if (CKM_API_SUCCESS != retCode)
+ return retCode;
-int CKMLogic::removeDataHelper(
- const Credentials &cred,
- const Name &name,
- const Label &label)
-{
- auto &handler = selectDatabase(cred, label);
-
- // use client label if not explicitly provided
- const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
- if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
- LogError("Invalid label or name format");
- return CKM_API_ERROR_INPUT_PARAM;
- }
-
- DB::Crypto::Transaction transaction(&handler.database);
-
- // read and check permissions
- PermissionMaskOptional permissionRowOpt =
- handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel);
- int retCode = m_accessControl.canDelete(cred,
- PermissionForLabel(cred.smackLabel, permissionRowOpt));
- if(retCode != CKM_API_SUCCESS)
- {
- LogWarning("access control check result: " << retCode);
- return retCode;
- }
-
- auto erased = handler.database.deleteRow(name, ownerLabel);
- // check if the data existed or not
- if(erased)
- transaction.commit();
- else {
- LogError("No row for given name and label");
- return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
- }
-
- return CKM_API_SUCCESS;
+ // all read rows belong to the same owner
+ DB::Row &firstRow = rows.at(0);
+
+ // check access rights
+ retCode = checkDataPermissionsHelper(cred, firstRow, exportFlag, permission);
+ if (CKM_API_SUCCESS != retCode)
+ return retCode;
+
+ // for multiple objects add type as hash input (see pkcs12)
+ bool multiple = rows.size() > 1;
+
+ RawBuffer digest;
+
+ retCode = dbOp.loadAppKey();
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ // decrypt row
+ for (auto &row : rows) {
+ if (multiple)
+ digest = CryptoLogic::makeHash(name, owner, cred.clientUid, row.dataType);
+ else
+ digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
+
+ if (digest.empty())
+ return CKM_API_ERROR_HASH_ERROR;
+
+ objs.push_back(rowToObject(dbOp.handler(), std::move(row), password, digest));
+ }
+
+ // rowToObject may modify db
+ dbOp.transaction().commit();
+
+ return CKM_API_SUCCESS;
}
-RawBuffer CKMLogic::removeData(
- const Credentials &cred,
- int commandId,
- const Name &name,
- const Label &label)
+int CKMLogic::readDataHelper(
+ bool exportFlag,
+ const Credentials &cred,
+ DataType dataType,
+ const Name &name,
+ const ClientId &owner,
+ const Password &password,
+ Crypto::GObjUPtr &obj)
{
- int retCode = CKM_API_ERROR_UNKNOWN;
-
- try
- {
- retCode = removeDataHelper(cred, name, label);
- }
- catch (const CKMLogic::Exception::DatabaseLocked &e)
- {
- LogError("Error " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_LOCKED;
- }
- catch (const CKM::Exception &)
- {
- LogError("Error in deleting row!");
- retCode = CKM_API_ERROR_DB_ERROR;
- }
-
- auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
- commandId,
- retCode);
- return response.Pop();
+ DataType objDataType;
+ return readDataHelper(exportFlag, cred, dataType, name, owner,
+ password, obj, objDataType);
}
-int CKMLogic::readSingleRow(const Name &name,
- const Label &ownerLabel,
- DataType dataType,
- DB::Crypto & database,
- DB::Row &row)
+int CKMLogic::readRowHelper(
+ bool exportFlag,
+ const Credentials &cred,
+ DataType dataType,
+ const Name &name,
+ const ClientId &owner,
+ const Password &password,
+ DB::Row &row,
+ DataType &objDataType)
{
- DB::Crypto::RowOptional row_optional;
- if (dataType.isKey())
- {
- // read all key types
- row_optional = database.getRow(name,
- ownerLabel,
- DataType::DB_KEY_FIRST,
- DataType::DB_KEY_LAST);
- } else {
- // read anything else
- row_optional = database.getRow(name,
- ownerLabel,
- dataType);
- }
-
- if(!row_optional) {
- LogError("No row for given name, label and type");
- return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
- } else {
- row = *row_optional;
- }
-
- return CKM_API_SUCCESS;
-}
+ auto [dbOp, permission, retCode] = beginAndGetPerm(cred, name, owner);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+ retCode = readSingleRow(name, owner, dataType, dbOp.database(), row);
+ if (CKM_API_SUCCESS != retCode)
+ return retCode;
-int CKMLogic::readMultiRow(const Name &name,
- const Label &ownerLabel,
- DataType dataType,
- DB::Crypto & database,
- DB::RowVector &output)
-{
- if (dataType.isKey())
- {
- // read all key types
- database.getRows(name,
- ownerLabel,
- DataType::DB_KEY_FIRST,
- DataType::DB_KEY_LAST,
- output);
- }
- else if (dataType.isChainCert())
- {
- // read all key types
- database.getRows(name,
- ownerLabel,
- DataType::DB_CHAIN_FIRST,
- DataType::DB_CHAIN_LAST,
- output);
- }
- else
- {
- // read anything else
- database.getRows(name,
- ownerLabel,
- dataType,
- output);
- }
-
- if(!output.size()) {
- LogError("No row for given name, label and type");
- return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
- }
-
- return CKM_API_SUCCESS;
-}
+ retCode = dbOp.loadAppKey();
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
-int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
- const Name &name,
- const Label &ownerLabel,
- const Label &accessorLabel,
- const DB::Row &row,
- bool exportFlag,
- DB::Crypto & database)
-{
- PermissionMaskOptional permissionRowOpt =
- database.getPermissionRow(name, ownerLabel, accessorLabel);
+ objDataType = row.dataType;
+
+ // check access rights
+ retCode = checkDataPermissionsHelper(cred, row, exportFlag, permission);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
- if(exportFlag)
- return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt));
- return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt));
+ auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
+ if (digest.empty())
+ return CKM_API_ERROR_HASH_ERROR;
+
+ decryptRow(dbOp.handler(), row, password, digest);
+
+ // decryptRow may modify db
+ dbOp.transaction().commit();
+
+ return CKM_API_SUCCESS;
}
-int CKMLogic::readDataHelper(
- bool exportFlag,
- const Credentials &cred,
- DataType dataType,
- const Name &name,
- const Label &label,
- const Password &password,
- DB::RowVector &rows)
+Crypto::GObjUPtr CKMLogic::decryptedRowToObj(const DB::Row& row, const Password &password)
{
- auto &handler = selectDatabase(cred, label);
-
- // use client label if not explicitly provided
- const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
-
- if (!isNameValid(name) || !isLabelValid(ownerLabel))
- return CKM_API_ERROR_INPUT_PARAM;
-
- // read rows
- DB::Crypto::Transaction transaction(&handler.database);
- int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
- if(CKM_API_SUCCESS != retCode)
- return retCode;
-
- // all read rows belong to the same owner
- DB::Row & firstRow = rows.at(0);
-
- // check access rights
- retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database);
- if(CKM_API_SUCCESS != retCode)
- return retCode;
-
- // decrypt row
- if (!handler.crypto.haveKey(firstRow.ownerLabel)) {
- RawBuffer key;
- auto key_optional = handler.database.getKey(firstRow.ownerLabel);
- if(!key_optional) {
- LogError("No key for given label in database");
- return CKM_API_ERROR_DB_ERROR;
- }
- key = *key_optional;
- key = handler.keyProvider.getPureDEK(key);
- handler.crypto.pushKey(firstRow.ownerLabel, key);
- }
- for(auto &row : rows)
- handler.crypto.decryptRow(password, row);
-
- return CKM_API_SUCCESS;
+ Crypto::GStore &store = m_decider.getStore(row);
+
+ Password pass = m_accessControl.isCCMode() ? "" : password;
+ return store.getObject(row, pass);
}
int CKMLogic::readDataHelper(
- bool exportFlag,
- const Credentials &cred,
- DataType dataType,
- const Name &name,
- const Label &label,
- const Password &password,
- DB::Row &row)
+ bool exportFlag,
+ const Credentials &cred,
+ DataType dataType,
+ const Name &name,
+ const ClientId &owner,
+ const Password &password,
+ Crypto::GObjUPtr &obj,
+ DataType &objDataType)
{
- auto &handler = selectDatabase(cred, label);
-
- // use client label if not explicitly provided
- const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
-
- if (!isNameValid(name) || !isLabelValid(ownerLabel))
- return CKM_API_ERROR_INPUT_PARAM;
-
- // read row
- DB::Crypto::Transaction transaction(&handler.database);
- int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
- if(CKM_API_SUCCESS != retCode)
- return retCode;
-
- // check access rights
- retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
- if(CKM_API_SUCCESS != retCode)
- return retCode;
-
- // decrypt row
- if (!handler.crypto.haveKey(row.ownerLabel)) {
- RawBuffer key;
- auto key_optional = handler.database.getKey(row.ownerLabel);
- if(!key_optional) {
- LogError("No key for given label in database");
- return CKM_API_ERROR_DB_ERROR;
- }
- key = *key_optional;
- key = handler.keyProvider.getPureDEK(key);
- handler.crypto.pushKey(row.ownerLabel, key);
- }
- handler.crypto.decryptRow(password, row);
-
- return CKM_API_SUCCESS;
+ DB::Row row;
+ int retCode = readRowHelper(exportFlag, cred, dataType, name, owner, password, row, objDataType);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ obj = decryptedRowToObj(row, password);
+
+ return CKM_API_SUCCESS;
}
RawBuffer CKMLogic::getData(
- const Credentials &cred,
- int commandId,
- DataType dataType,
- const Name &name,
- const Label &label,
- const Password &password)
+ const Credentials &cred,
+ int msgId,
+ DataType dataType,
+ const Name &name,
+ const ClientId &owner,
+ const Password &password)
{
- int retCode = CKM_API_SUCCESS;
- DB::Row row;
-
- try {
- retCode = readDataHelper(true, cred, dataType, name, label, password, row);
- } catch (const KeyProvider::Exception::Base &e) {
- LogError("KeyProvider failed with error: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
- } catch (const CryptoLogic::Exception::Base &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const DB::Crypto::Exception::Base &e) {
- LogError("DB::Crypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const CKMLogic::Exception::DatabaseLocked &e) {
- LogError("Error " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_LOCKED;
- } catch (const CKM::Exception &e) {
- LogError("CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
-
- if (CKM_API_SUCCESS != retCode) {
- row.data.clear();
- row.dataType = dataType;
- }
-
- auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
- commandId,
- retCode,
- static_cast<int>(row.dataType),
- row.data);
- return response.Pop();
+ RawBuffer rowData;
+ DataType objDataType;
+
+ int retCode = tryRet([&] {
+ Crypto::GObjUPtr obj;
+ int retCode2 = readDataHelper(true, cred, dataType, name, owner,
+ password, obj, objDataType);
+
+ if (retCode2 == CKM_API_SUCCESS)
+ rowData = obj->getBinary();
+
+ return retCode2;
+ });
+
+ if (CKM_API_SUCCESS != retCode)
+ rowData.clear();
+
+ return SerializeMessage(msgId, retCode, objDataType, rowData);
}
-int CKMLogic::getPKCS12Helper(
- const Credentials &cred,
- const Name &name,
- const Label &label,
- const Password &keyPassword,
- const Password &certPassword,
- KeyShPtr & privKey,
- CertificateShPtr & cert,
- CertificateShPtrVector & caChain)
+RawBuffer CKMLogic::getDataProtectionStatus(
+ const Credentials &cred,
+ int msgId,
+ DataType dataType,
+ const Name &name,
+ const ClientId &owner)
{
- int retCode;
-
- // read private key (mandatory)
- DB::Row privKeyRow;
- retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, privKeyRow);
- if(retCode != CKM_API_SUCCESS)
- return retCode;
- privKey = CKM::Key::create(privKeyRow.data);
-
- // read certificate (mandatory)
- DB::Row certRow;
- retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certRow);
- if(retCode != CKM_API_SUCCESS)
- return retCode;
- cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER);
-
- // read CA cert chain (optional)
- DB::RowVector rawCaChain;
- retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, rawCaChain);
- if(retCode != CKM_API_SUCCESS &&
- retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
- return retCode;
- for(auto &rawCaCert : rawCaChain)
- caChain.push_back(CKM::Certificate::create(rawCaCert.data, DataFormat::FORM_DER));
-
- // if anything found, return it
- if(privKey || cert || caChain.size()>0)
- retCode = CKM_API_SUCCESS;
-
- return retCode;
+ bool status = false;
+ DataType objDataType;
+ Password password;
+
+ int retCode = tryRet([&] {
+ Crypto::GObjUPtr obj;
+ return readDataHelper(false, cred, dataType, name, owner, password, obj, objDataType);
+ });
+
+ if (retCode == CKM_API_ERROR_AUTHENTICATION_FAILED) {
+ status = true;
+ retCode = CKM_API_SUCCESS;
+ }
+
+ return SerializeMessage(msgId, retCode, objDataType, status);
}
RawBuffer CKMLogic::getPKCS12(
- const Credentials &cred,
- int commandId,
- const Name &name,
- const Label &label,
- const Password &keyPassword,
- const Password &certPassword)
+ const Credentials &cred,
+ int msgId,
+ const Name &name,
+ const ClientId &owner,
+ const Password &keyPassword,
+ const Password &certPassword)
{
- int retCode = CKM_API_ERROR_UNKNOWN;
-
- PKCS12Serializable output;
- try {
- KeyShPtr privKey;
- CertificateShPtr cert;
- CertificateShPtrVector caChain;
- retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey, cert, caChain);
-
- // prepare response
- if(retCode == CKM_API_SUCCESS)
- output = PKCS12Serializable(privKey, cert, caChain);
-
- } catch (const KeyProvider::Exception::Base &e) {
- LogError("KeyProvider failed with error: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
- } catch (const CryptoLogic::Exception::Base &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const DB::Crypto::Exception::Base &e) {
- LogError("DB::Crypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const CKMLogic::Exception::DatabaseLocked &e) {
- LogError("Error " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_LOCKED;
- } catch (const CKM::Exception &e) {
- LogError("CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
-
- auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
- commandId,
- retCode,
- output);
- return response.Pop();
+ PKCS12Serializable output;
+
+ int retCode = tryRet([&] {
+ KeyShPtr privKey;
+ CertificateShPtr cert;
+ CertificateShPtrVector caChain;
+
+ // read private key (mandatory)
+ Crypto::GObjUPtr keyObj;
+ int retCode2 = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, owner,
+ keyPassword, keyObj);
+
+ if (retCode2 != CKM_API_SUCCESS) {
+ if (retCode2 != CKM_API_ERROR_NOT_EXPORTABLE)
+ return retCode2;
+ } else {
+ privKey = CKM::Key::create(keyObj->getBinary());
+ }
+
+ // read certificate (mandatory)
+ Crypto::GObjUPtr certObj;
+ retCode2 = readDataHelper(true, cred, DataType::CERTIFICATE, name, owner,
+ certPassword, certObj);
+
+ if (retCode2 != CKM_API_SUCCESS) {
+ if (retCode2 != CKM_API_ERROR_NOT_EXPORTABLE)
+ return retCode2;
+ } else {
+ cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
+ }
+
+ // read CA cert chain (optional)
+ Crypto::GObjUPtrVector caChainObjs;
+ retCode2 = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, owner,
+ certPassword, caChainObjs);
+
+ if (retCode2 != CKM_API_SUCCESS && retCode2 != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
+ if (retCode2 != CKM_API_ERROR_NOT_EXPORTABLE)
+ return retCode2;
+ } else {
+ for (auto &caCertObj : caChainObjs)
+ caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
+ DataFormat::FORM_DER));
+ }
+
+ // if anything found, return it
+ if (privKey || cert || caChain.size() > 0)
+ retCode2 = CKM_API_SUCCESS;
+
+ // prepare response
+ if (retCode2 != CKM_API_SUCCESS)
+ return retCode2;
+
+ output = PKCS12Serializable(std::move(privKey), std::move(cert), std::move(caChain));
+ return CKM_API_SUCCESS;
+ });
+
+ return SerializeMessage(msgId, retCode, output);
}
-int CKMLogic::getDataListHelper(const Credentials &cred,
- const DataType dataType,
- LabelNameVector &labelNameVector)
+int CKMLogic::getAliasInfoListHelper(const Credentials &cred,
+ const DataType dataType,
+ AliasInfoVector &aliasInfoVector)
{
- int retCode = CKM_API_ERROR_DB_LOCKED;
- if (0 < m_userDataMap.count(cred.clientUid))
- {
- auto &database = m_userDataMap[cred.clientUid].database;
-
- Try {
- LabelNameVector tmpVector;
- if (dataType.isKey()) {
- // list all key types
- database.listNames(cred.smackLabel,
- tmpVector,
- DataType::DB_KEY_FIRST,
- DataType::DB_KEY_LAST);
- } else {
- // list anything else
- database.listNames(cred.smackLabel,
- tmpVector,
- dataType);
- }
- labelNameVector.insert(labelNameVector.end(), tmpVector.begin(), tmpVector.end());
- retCode = CKM_API_SUCCESS;
- }
- Catch (CKM::Exception) {
- LogError("Failed to get names");
- retCode = CKM_API_ERROR_DB_ERROR;
- }
- }
- return retCode;
+ int retCode = CKM_API_ERROR_DB_LOCKED;
+
+ if (0 < m_userDataMap.count(cred.clientUid)) {
+ auto &database = m_userDataMap[cred.clientUid].database;
+
+ retCode = tryRet<CKM_API_ERROR_DB_ERROR>([&] {
+ AliasInfoVector tmpVector;
+
+ if (dataType.isKey()) {
+ // list all key types
+ database.listInfos(cred.client,
+ tmpVector,
+ DataType::DB_KEY_FIRST,
+ DataType::DB_KEY_LAST);
+ } else {
+ // list anything else
+ database.listInfos(cred.client, tmpVector, dataType);
+ }
+
+ aliasInfoVector.insert(aliasInfoVector.end(), tmpVector.begin(), tmpVector.end());
+ return CKM_API_SUCCESS;
+ });
+ }
+
+ return retCode;
}
RawBuffer CKMLogic::getDataList(
- const Credentials &cred,
- int commandId,
- DataType dataType)
+ const Credentials &cred,
+ int msgId,
+ DataType dataType)
{
- LabelNameVector systemVector;
- LabelNameVector userVector;
- LabelNameVector labelNameVector;
-
- int retCode = unlockSystemDB();
- if (CKM_API_SUCCESS == retCode)
- {
- // system database
- if (m_accessControl.isSystemService(cred))
- {
- // lookup system DB
- retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
- LABEL_SYSTEM_DB),
- dataType,
- systemVector);
- }
- else
- {
- // user - lookup system, then client DB
- retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
- cred.smackLabel),
- dataType,
- systemVector);
-
- // private database
- if(retCode == CKM_API_SUCCESS)
- {
- retCode = getDataListHelper(cred,
- dataType,
- userVector);
- }
- }
- }
-
- if(retCode == CKM_API_SUCCESS)
- {
- labelNameVector.insert(labelNameVector.end(), systemVector.begin(), systemVector.end());
- labelNameVector.insert(labelNameVector.end(), userVector.begin(), userVector.end());
- }
- auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
- commandId,
- retCode,
- static_cast<int>(dataType),
- labelNameVector);
- return response.Pop();
+ AliasInfoVector systemVector;
+ AliasInfoVector userVector;
+ AliasInfoVector aliasInfoVector;
+
+ int retCode = unlockSystemDB();
+
+ if (CKM_API_SUCCESS == retCode) {
+ // system database
+ if (m_accessControl.isSystemService(cred)) {
+ // lookup system DB
+ retCode = getAliasInfoListHelper(Credentials(SYSTEM_DB_UID, CLIENT_ID_SYSTEM),
+ dataType,
+ systemVector);
+ } else {
+ // user - lookup system, then client DB
+ retCode = getAliasInfoListHelper(Credentials(SYSTEM_DB_UID, cred.client),
+ dataType,
+ systemVector);
+
+ // private database
+ if (retCode == CKM_API_SUCCESS) {
+ retCode = getAliasInfoListHelper(cred,
+ dataType,
+ userVector);
+ }
+ }
+ }
+
+ if (retCode == CKM_API_SUCCESS) {
+ aliasInfoVector.insert(aliasInfoVector.end(), systemVector.begin(),
+ systemVector.end());
+ aliasInfoVector.insert(aliasInfoVector.end(), userVector.begin(),
+ userVector.end());
+ }
+
+ return SerializeMessage(msgId, retCode, dataType, AliasInfoSerializableVector(aliasInfoVector));
}
-int CKMLogic::saveDataHelper(
- const Credentials &cred,
- const Name &name,
- const Label &label,
- DataType dataType,
- const RawBuffer &data,
- const PolicySerializable &policy)
+int CKMLogic::importInitialData(
+ const Name &name,
+ const Crypto::Data &data,
+ const Crypto::EncryptionParams &encParams,
+ const Policy &policy)
{
- auto &handler = selectDatabase(cred, label);
+ try {
+ return tryRet([&] {
+ if (encParams.iv.empty() != encParams.tag.empty()) {
+ LogError("Both iv and tag must be empty or set");
+ return CKM_API_ERROR_INPUT_PARAM;
+ }
+
+ // Inital values are always imported with root credentials. Client id is not important.
+ Credentials rootCred(0, "whatever");
+ ClientId owner(CLIENT_ID_SYSTEM);
+
+ auto [dbOp, digest, retCode] = beginSaveAndGetHash(rootCred, name, owner);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ Crypto::GStore &store = m_decider.getStore(data.type, policy, true, !encParams.iv.empty());
+
+ Token token;
+ if (encParams.iv.empty()) {
+ // Data are not encrypted, let's try to verify them
+ Crypto::Data binaryData;
+
+ if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
+ return retCode;
+
+ token = store.import(binaryData,
+ m_accessControl.isCCMode() ? "" : policy.password,
+ encParams, digest);
+ } else {
+ token = store.import(data,
+ m_accessControl.isCCMode() ? "" : policy.password,
+ encParams, digest);
+ }
+
+ dbOp.finalize(std::move(token), policy);
+
+ return CKM_API_SUCCESS;
+ });
+ } catch (const std::exception &e) {
+ LogError("Std::exception: " << e.what());
+ return CKM_API_ERROR_SERVER_ERROR;
+ }
+}
- // use client label if not explicitly provided
- const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
- if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
- return CKM_API_ERROR_INPUT_PARAM;
+int CKMLogic::DBOperation::loadAppKey(bool keyRequired)
+{
+ if (!m_handler.crypto.haveKey(m_owner)) {
+ RawBuffer wrappedDEK;
+ auto wrappedDEKOptional = m_handler.database.getKey(m_owner);
+
+ if (!wrappedDEKOptional) {
+ if (keyRequired) {
+ LogError("No key for given owner in database");
+ return CKM_API_ERROR_DB_ERROR;
+ }
+ LogDebug("No Key in database found. Generating new one for client: " << m_owner);
+ wrappedDEK = m_handler.keyProvider.generateDEK(m_owner);
+ m_handler.database.saveKey(m_owner, wrappedDEK);
+ } else {
+ wrappedDEK = *wrappedDEKOptional;
+ }
+
+ m_handler.crypto.pushKey(m_owner, m_handler.keyProvider.getPureDEK(wrappedDEK));
+ }
+
+ return CKM_API_SUCCESS;
+}
- // check if save is possible
- DB::Crypto::Transaction transaction(&handler.database);
- int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
- if(retCode != CKM_API_SUCCESS)
- return retCode;
+std::tuple<CKMLogic::DBOperation, int> CKMLogic::begin(
+ const Credentials &cred,
+ const Name &name,
+ const ClientId &owner)
+{
+ auto &handler = selectDatabase(cred, owner);
+ DBOperation op(handler, name, owner);
- // save the data
- DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, dataType, data, policy);
- handler.database.saveRow(encryptedRow);
+ if (cred.client.empty() || !isClientValid(cred.client) ||
+ !isNameValid(name) || !isClientValid(owner))
+ return std::make_tuple(std::move(op), CKM_API_ERROR_INPUT_PARAM);
- transaction.commit();
- return CKM_API_SUCCESS;
+ return std::make_tuple(std::move(op), CKM_API_SUCCESS);
}
-int CKMLogic::saveDataHelper(
- const Credentials &cred,
- const Name &name,
- const Label &label,
- const PKCS12Serializable &pkcs,
- const PolicySerializable &keyPolicy,
- const PolicySerializable &certPolicy)
+std::tuple<CKMLogic::DBOperation, PermissionMask, int> CKMLogic::beginAndGetPerm(
+ const Credentials &cred,
+ const Name &name,
+ const ClientId &owner)
{
- auto &handler = selectDatabase(cred, label);
-
- // use client label if not explicitly provided
- const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
- if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
- return CKM_API_ERROR_INPUT_PARAM;
-
- // check if save is possible
- DB::Crypto::Transaction transaction(&handler.database);
- int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
- if(retCode != CKM_API_SUCCESS)
- return retCode;
-
- // extract and encrypt the data
- DB::RowVector encryptedRows;
- retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
- if(retCode != CKM_API_SUCCESS)
- return retCode;
-
- // save the data
- handler.database.saveRows(name, ownerLabel, encryptedRows);
- transaction.commit();
-
- return CKM_API_SUCCESS;
-}
+ PermissionMask permission = Permission::NONE;
+ auto [dbOp, retCode] = begin(cred, name, owner);
+ if (retCode == CKM_API_SUCCESS)
+ permission = toPermissionMask(dbOp.database().getPermissionRow(name, owner, cred.client));
+ return std::make_tuple(std::move(dbOp), permission, retCode);
+}
-int CKMLogic::createKeyAESHelper(
- const Credentials &cred,
- const int size,
- const Name &name,
- const Label &label,
- const PolicySerializable &policy)
+std::tuple<CKMLogic::DBOperation, int> CKMLogic::beginSave(
+ const Credentials &cred,
+ const Name &name,
+ const ClientId &owner)
{
- CryptoAlgorithm keyGenAlgorithm;
- keyGenAlgorithm.addParam(ParamName::GEN_KEY_LEN, size);
- Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm);
-
- return saveDataHelper(cred,
- name,
- label,
- DataType::KEY_AES,
- key.data,
- policy);
-}
+ auto [dbOp, retCode] = begin(cred, name, owner);
+ if (retCode != CKM_API_SUCCESS)
+ return std::make_tuple(std::move(dbOp), retCode);
+
+ retCode = dbOp.loadAppKey(false);
+ if (retCode != CKM_API_SUCCESS)
+ return std::make_tuple(std::move(dbOp), retCode);
+ // check if accessor is allowed to save owner's items
+ retCode = m_accessControl.canSave(cred, owner);
+ if (retCode != CKM_API_SUCCESS) {
+ LogDebug("accessor " << cred.client << " can not save rows owned by " << owner);
+ return std::make_tuple(std::move(dbOp), retCode);
+ }
-int CKMLogic::createKeyPairHelper(
- const Credentials &cred,
- const CryptoAlgorithmSerializable & keyGenParams,
- const Name &namePrivate,
- const Label &labelPrivate,
- const Name &namePublic,
- const Label &labelPublic,
- const PolicySerializable &policyPrivate,
- const PolicySerializable &policyPublic)
+ if (dbOp.database().isNameOwnerPresent(name, owner))
+ retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
+
+ return std::make_tuple(std::move(dbOp), retCode);
+}
+
+std::tuple<CKMLogic::DBOperation, RawBuffer, int> CKMLogic::beginSaveAndGetHash(
+ const Credentials &cred,
+ const Name &name,
+ const ClientId &owner)
{
- auto &handlerPriv = selectDatabase(cred, labelPrivate);
- auto &handlerPub = selectDatabase(cred, labelPublic);
-
- AlgoType keyType = AlgoType::RSA_GEN;
- if(!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
- ThrowMsg(Crypto::Exception::InputParam, "Error, parameter ALGO_TYPE not found.");
- DataType dt(keyType);
- if(!dt.isKey())
- ThrowMsg(Crypto::Exception::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
-
- bool exportable = policyPrivate.extractable || policyPublic.extractable;
- TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams);
-
- DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
- // in case the same database is used for private and public - the second
- // transaction will not be executed
- DB::Crypto::Transaction transactionPub(&handlerPub.database);
-
- int retCode = saveDataHelper(cred,
- namePrivate,
- labelPrivate,
- keys.first.dataType,
- keys.first.data,
- policyPrivate);
- if (CKM_API_SUCCESS != retCode)
- return retCode;
-
- retCode = saveDataHelper(cred,
- namePublic,
- labelPublic,
- keys.second.dataType,
- keys.second.data,
- policyPublic);
- if (CKM_API_SUCCESS != retCode)
- return retCode;
-
- transactionPub.commit();
- transactionPriv.commit();
- return CKM_API_SUCCESS;
+ RawBuffer digest;
+ auto [dbOp, retCode] = beginSave(cred, name, owner);
+ if (retCode == CKM_API_SUCCESS) {
+ digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
+ if (digest.empty())
+ retCode = CKM_API_ERROR_HASH_ERROR;
+ }
+
+ return std::make_tuple(std::move(dbOp), std::move(digest), retCode);
}
RawBuffer CKMLogic::createKeyPair(
- const Credentials &cred,
- int commandId,
- const CryptoAlgorithmSerializable & keyGenParams,
- const Name &namePrivate,
- const Label &labelPrivate,
- const Name &namePublic,
- const Label &labelPublic,
- const PolicySerializable &policyPrivate,
- const PolicySerializable &policyPublic)
+ const Credentials &cred,
+ int msgId,
+ const CryptoAlgorithmSerializable &keyGenParams,
+ const Name &namePrv,
+ const ClientId &ownerPrv,
+ const Name &namePub,
+ const ClientId &ownerPub,
+ const PolicySerializable &policyPrv,
+ const PolicySerializable &policyPub)
{
- int retCode = CKM_API_SUCCESS;
-
- try {
- retCode = createKeyPairHelper(
- cred,
- keyGenParams,
- namePrivate,
- labelPrivate,
- namePublic,
- labelPublic,
- policyPrivate,
- policyPublic);
- } catch (const Crypto::Exception::OperationNotSupported &e) {
- LogDebug("GStore error: operation not supported: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const Crypto::Exception::InternalError & e) {
- LogDebug("GStore key generation failed: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch( const Crypto::Exception::InputParam & e) {
- LogDebug("Missing or wrong input parameters: " << e.GetMessage());
- retCode = CKM_API_ERROR_INPUT_PARAM;
- } catch (DB::Crypto::Exception::TransactionError &e) {
- LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (CKM::CryptoLogic::Exception::Base &e) {
- LogDebug("CryptoLogic error: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (DB::Crypto::Exception::InternalError &e) {
- LogDebug("DB::Crypto internal error: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const CKMLogic::Exception::DatabaseLocked &e) {
- LogError("Error " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_LOCKED;
- } catch (const CKM::Exception &e) {
- LogError("CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
-
- return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
- commandId, retCode).Pop();
+ return SerializeMessage(msgId, tryRet([&] {
+ auto [dbOpPrv, digestPrv, retCodePrv] = beginSaveAndGetHash(cred, namePrv, ownerPrv);
+ if (retCodePrv != CKM_API_SUCCESS)
+ return retCodePrv;
+
+ auto [dbOpPub, digestPub, retCodePub] = beginSaveAndGetHash(cred, namePub, ownerPub);
+ if (retCodePub != CKM_API_SUCCESS)
+ return retCodePub;
+
+ if (policyPrv.backend != policyPub.backend)
+ ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend.");
+
+ bool exportable = policyPrv.extractable || policyPub.extractable;
+ Policy lessRestricted(Password(), exportable, policyPrv.backend);
+
+ // For now any asymmetric key will do. If necessary we can extract it from keyGenParams.
+ TokenPair keys = m_decider.getStore(DataType::DB_KEY_FIRST, policyPrv, false).generateAKey(
+ keyGenParams,
+ policyPrv.password,
+ policyPub.password,
+ digestPrv, digestPub);
+
+ dbOpPrv.finalize(std::move(keys.first), policyPrv);
+ dbOpPub.finalize(std::move(keys.second), policyPub);
+
+ return CKM_API_SUCCESS;
+ }));
}
RawBuffer CKMLogic::createKeyAES(
- const Credentials &cred,
- int commandId,
- const int size,
- const Name &name,
- const Label &label,
- const PolicySerializable &policy)
+ const Credentials &cred,
+ int msgId,
+ const int size,
+ const Name &name,
+ const ClientId &owner,
+ const PolicySerializable &policy)
{
- int retCode = CKM_API_SUCCESS;
-
- try {
- retCode = createKeyAESHelper(cred, size, name, label, policy);
- } catch (const Crypto::Exception::OperationNotSupported &e) {
- LogDebug("GStore error: operation not supported: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const Crypto::Exception::InternalError & e) {
- LogDebug("GStore key generation failed: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch( const Crypto::Exception::InputParam & e) {
- LogDebug("Missing or wrong input parameters: " << e.GetMessage());
- retCode = CKM_API_ERROR_INPUT_PARAM;
- } catch (std::invalid_argument &e) {
- LogDebug("invalid argument error: " << e.what());
- retCode = CKM_API_ERROR_INPUT_PARAM;
- } catch (DB::Crypto::Exception::TransactionError &e) {
- LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (CKM::CryptoLogic::Exception::Base &e) {
- LogDebug("CryptoLogic error: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (DB::Crypto::Exception::InternalError &e) {
- LogDebug("DB::Crypto internal error: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const CKMLogic::Exception::DatabaseLocked &e) {
- LogError("Error " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_LOCKED;
- } catch (const CKM::Exception &e) {
- LogError("CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
-
- return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
- commandId, retCode).Pop();
+ int retCode = CKM_API_SUCCESS;
+
+ try {
+ retCode = tryRet([&] {
+ auto [dbOp, digest, retCode2] = beginSaveAndGetHash(cred, name, owner);
+ if (retCode2 != CKM_API_SUCCESS)
+ return retCode2;
+
+ // create key in store
+ CryptoAlgorithm keyGenAlgorithm;
+ keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
+ keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
+
+ auto& store = m_decider.getStore(DataType::KEY_AES, policy, false);
+ Token key = store.generateSKey(keyGenAlgorithm, policy.password, digest);
+
+ dbOp.finalize(std::move(key), policy);
+ return CKM_API_SUCCESS;
+ });
+ } catch (std::invalid_argument &e) {
+ LogDebug("invalid argument error: " << e.what());
+ retCode = CKM_API_ERROR_INPUT_PARAM;
+ }
+
+ return SerializeMessage(msgId, retCode);
}
int CKMLogic::readCertificateHelper(
- const Credentials &cred,
- const LabelNameVector &labelNameVector,
- CertificateImplVector &certVector)
+ const Credentials &cred,
+ const OwnerNameVector &ownerNameVector,
+ CertificateImplVector &certVector)
{
- DB::Row row;
- for (auto &i: labelNameVector) {
- int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), row);
- if (ec != CKM_API_SUCCESS)
- return ec;
- certVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
-
- // try to read chain certificates (if present)
- DB::RowVector rawCaChain;
- ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain);
- if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
- return ec;
- for(auto &rawCaCert : rawCaChain)
- certVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER));
- }
- return CKM_API_SUCCESS;
+ for (auto &i : ownerNameVector) {
+ // certificates can't be protected with custom user password
+ Crypto::GObjUPtr obj;
+ int ec;
+ ec = readDataHelper(true,
+ cred,
+ DataType::CERTIFICATE,
+ i.second,
+ cred.effectiveOwner(i.first),
+ Password(),
+ obj);
+
+ if (ec != CKM_API_SUCCESS)
+ return ec;
+
+ certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
+
+ // try to read chain certificates (if present)
+ Crypto::GObjUPtrVector caChainObjs;
+ ec = readDataHelper(true,
+ cred,
+ DataType::DB_CHAIN_FIRST,
+ i.second,
+ cred.effectiveOwner(i.first),
+ CKM::Password(),
+ caChainObjs);
+
+ if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
+ return ec;
+
+ for (auto &caCertObj : caChainObjs)
+ certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
+ }
+
+ return CKM_API_SUCCESS;
}
int CKMLogic::getCertificateChainHelper(
- const CertificateImpl &cert,
- const RawBufferVector &untrustedCertificates,
- const RawBufferVector &trustedCertificates,
- bool useTrustedSystemCertificates,
- RawBufferVector &chainRawVector)
+ const CertificateImpl &cert,
+ const RawBufferVector &untrustedCertificates,
+ const RawBufferVector &trustedCertificates,
+ bool useTrustedSystemCertificates,
+ RawBufferVector &chainRawVector)
{
- CertificateImplVector untrustedCertVector;
- CertificateImplVector trustedCertVector;
- CertificateImplVector chainVector;
-
- if (cert.empty())
- return CKM_API_ERROR_INPUT_PARAM;
-
- for (auto &e: untrustedCertificates)
- untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
- for (auto &e: trustedCertificates)
- trustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
-
- CertificateStore store;
- int retCode = store.verifyCertificate(cert,
- untrustedCertVector,
- trustedCertVector,
- useTrustedSystemCertificates,
- m_accessControl.isCCMode(),
- chainVector);
- if (retCode != CKM_API_SUCCESS)
- return retCode;
-
- for (auto &e : chainVector)
- chainRawVector.push_back(e.getDER());
- return CKM_API_SUCCESS;
+ CertificateImplVector untrustedCertVector;
+ CertificateImplVector trustedCertVector;
+ CertificateImplVector chainVector;
+
+ if (cert.empty())
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ for (auto &e : untrustedCertificates) {
+ CertificateImpl c(e, DataFormat::FORM_DER);
+
+ if (c.empty())
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ untrustedCertVector.push_back(std::move(c));
+ }
+
+ for (auto &e : trustedCertificates) {
+ CertificateImpl c(e, DataFormat::FORM_DER);
+
+ if (c.empty())
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ trustedCertVector.push_back(std::move(c));
+ }
+
+ CertificateStore store;
+ int retCode = store.verifyCertificate(cert,
+ untrustedCertVector,
+ trustedCertVector,
+ useTrustedSystemCertificates,
+ m_accessControl.isCCMode(),
+ chainVector);
+
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ for (auto &e : chainVector)
+ chainRawVector.push_back(e.getDER());
+
+ return CKM_API_SUCCESS;
}
int CKMLogic::getCertificateChainHelper(
- const Credentials &cred,
- const CertificateImpl &cert,
- const LabelNameVector &untrusted,
- const LabelNameVector &trusted,
- bool useTrustedSystemCertificates,
- RawBufferVector &chainRawVector)
+ const Credentials &cred,
+ const CertificateImpl &cert,
+ const OwnerNameVector &untrusted,
+ const OwnerNameVector &trusted,
+ bool useTrustedSystemCertificates,
+ RawBufferVector &chainRawVector)
{
- CertificateImplVector untrustedCertVector;
- CertificateImplVector trustedCertVector;
- CertificateImplVector chainVector;
- DB::Row row;
-
- if (cert.empty())
- return CKM_API_ERROR_INPUT_PARAM;
-
- int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
- if (retCode != CKM_API_SUCCESS)
- return retCode;
- retCode = readCertificateHelper(cred, trusted, trustedCertVector);
- if (retCode != CKM_API_SUCCESS)
- return retCode;
-
- CertificateStore store;
- retCode = store.verifyCertificate(cert,
- untrustedCertVector,
- trustedCertVector,
- useTrustedSystemCertificates,
- m_accessControl.isCCMode(),
- chainVector);
- if (retCode != CKM_API_SUCCESS)
- return retCode;
-
- for (auto &i: chainVector)
- chainRawVector.push_back(i.getDER());
-
- return CKM_API_SUCCESS;
+ CertificateImplVector untrustedCertVector;
+ CertificateImplVector trustedCertVector;
+ CertificateImplVector chainVector;
+
+ if (cert.empty())
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
+
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ retCode = readCertificateHelper(cred, trusted, trustedCertVector);
+
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ CertificateStore store;
+ retCode = store.verifyCertificate(cert,
+ untrustedCertVector,
+ trustedCertVector,
+ useTrustedSystemCertificates,
+ m_accessControl.isCCMode(),
+ chainVector);
+
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ for (auto &i : chainVector)
+ chainRawVector.push_back(i.getDER());
+
+ return CKM_API_SUCCESS;
}
RawBuffer CKMLogic::getCertificateChain(
- const Credentials & /*cred*/,
- int commandId,
- const RawBuffer &certificate,
- const RawBufferVector &untrustedCertificates,
- const RawBufferVector &trustedCertificates,
- bool useTrustedSystemCertificates)
+ const Credentials & /*cred*/,
+ int msgId,
+ const RawBuffer &certificate,
+ const RawBufferVector &untrustedCertificates,
+ const RawBufferVector &trustedCertificates,
+ bool useTrustedSystemCertificates)
{
- CertificateImpl cert(certificate, DataFormat::FORM_DER);
- RawBufferVector chainRawVector;
- int retCode = CKM_API_ERROR_UNKNOWN;
- try {
- retCode = getCertificateChainHelper(cert,
- untrustedCertificates,
- trustedCertificates,
- useTrustedSystemCertificates,
- chainRawVector);
- } catch (const CryptoLogic::Exception::Base &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const DB::Crypto::Exception::Base &e) {
- LogError("DB::Crypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const std::exception& e) {
- LogError("STD exception " << e.what());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (...) {
- LogError("Unknown error.");
- }
-
- auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
- commandId,
- retCode,
- chainRawVector);
- return response.Pop();
+ CertificateImpl cert(certificate, DataFormat::FORM_DER);
+ RawBufferVector chainRawVector;
+ int retCode = CKM_API_ERROR_UNKNOWN;
+
+ try {
+ retCode = getCertificateChainHelper(cert,
+ untrustedCertificates,
+ trustedCertificates,
+ useTrustedSystemCertificates,
+ chainRawVector);
+ } catch (const Exc::Exception &e) {
+ retCode = e.error();
+ } catch (const std::exception &e) {
+ LogError("STD exception " << e.what());
+ retCode = CKM_API_ERROR_SERVER_ERROR;
+ } catch (...) {
+ LogError("Unknown error.");
+ }
+
+ return SerializeMessage(msgId, retCode, chainRawVector);
}
RawBuffer CKMLogic::getCertificateChain(
- const Credentials &cred,
- int commandId,
- const RawBuffer &certificate,
- const LabelNameVector &untrustedCertificates,
- const LabelNameVector &trustedCertificates,
- bool useTrustedSystemCertificates)
+ const Credentials &cred,
+ int msgId,
+ const RawBuffer &certificate,
+ const OwnerNameVector &untrustedCertificates,
+ const OwnerNameVector &trustedCertificates,
+ bool useTrustedSystemCertificates)
{
- int retCode = CKM_API_ERROR_UNKNOWN;
- CertificateImpl cert(certificate, DataFormat::FORM_DER);
- RawBufferVector chainRawVector;
- try {
- retCode = getCertificateChainHelper(cred,
- cert,
- untrustedCertificates,
- trustedCertificates,
- useTrustedSystemCertificates,
- chainRawVector);
- } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
- } catch (const CryptoLogic::Exception::Base &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const DB::Crypto::Exception::Base &e) {
- LogError("DB::Crypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const CKMLogic::Exception::DatabaseLocked &e) {
- LogError("Error " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_LOCKED;
- } catch (const std::exception& e) {
- LogError("STD exception " << e.what());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (...) {
- LogError("Unknown error.");
- }
-
- auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
- commandId,
- retCode,
- chainRawVector);
- return response.Pop();
+ int retCode = CKM_API_ERROR_UNKNOWN;
+ CertificateImpl cert(certificate, DataFormat::FORM_DER);
+ RawBufferVector chainRawVector;
+
+ try {
+ retCode = getCertificateChainHelper(cred,
+ cert,
+ untrustedCertificates,
+ trustedCertificates,
+ useTrustedSystemCertificates,
+ chainRawVector);
+ } catch (const Exc::Exception &e) {
+ retCode = e.error();
+ } catch (const std::exception &e) {
+ LogError("STD exception " << e.what());
+ retCode = CKM_API_ERROR_SERVER_ERROR;
+ } catch (...) {
+ LogError("Unknown error.");
+ }
+
+ return SerializeMessage(msgId, retCode, chainRawVector);
}
RawBuffer CKMLogic::createSignature(
- const Credentials &cred,
- int commandId,
- const Name &privateKeyName,
- const Label & ownerLabel,
- const Password &password, // password for private_key
- const RawBuffer &message,
- const HashAlgorithm hash,
- const RSAPaddingAlgorithm padding)
+ const Credentials &cred,
+ int msgId,
+ const Name &privateKeyName,
+ const ClientId &owner,
+ const Password &password, // password for private_key
+ const RawBuffer &message,
+ const CryptoAlgorithm &cryptoAlg)
{
- DB::Row row;
- RawBuffer signature;
- CryptoAlgorithm cryptoAlg;
- cryptoAlg.addParam(ParamName::SV_HASH_ALGO, hash);
- cryptoAlg.addParam(ParamName::SV_RSA_PADDING, padding);
-
- int retCode = CKM_API_SUCCESS;
-
- try {
- retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
- if(retCode == CKM_API_SUCCESS) {
- signature = m_decider.getStore(row).getKey(row)->sign(cryptoAlg, message);
- }
- } catch (const KeyProvider::Exception::Base &e) {
- LogError("KeyProvider failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
- } catch (const CryptoLogic::Exception::Base &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const DB::Crypto::Exception::Base &e) {
- LogError("DB::Crypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const CKMLogic::Exception::DatabaseLocked &e) {
- LogError("Error " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_LOCKED;
- } catch (const CKM::Crypto::Exception::InputParam &e) {
- LogError("CKM::Crypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_INPUT_PARAM;
- } catch (const CKM::Crypto::Exception::Base &e) {
- LogError("CKM::Crypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const CKM::Exception &e) {
- LogError("Unknown CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
-
- auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
- commandId,
- retCode,
- signature);
- return response.Pop();
+ RawBuffer signature;
+
+ int retCode = CKM_API_SUCCESS;
+
+ try {
+ retCode = tryRet([&] {
+ Crypto::GObjUPtr obj;
+ int retCode2 = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
+ owner, password, obj);
+
+ if (retCode2 == CKM_API_SUCCESS)
+ signature = obj->sign(cryptoAlg, message);
+
+ return retCode2;
+ });
+ } catch (const std::exception &e) {
+ LogError("STD exception " << e.what());
+ retCode = CKM_API_ERROR_SERVER_ERROR;
+ }
+
+ return SerializeMessage(msgId, retCode, signature);
}
RawBuffer CKMLogic::verifySignature(
- const Credentials &cred,
- int commandId,
- const Name &publicKeyOrCertName,
- const Label & ownerLabel,
- const Password &password, // password for public_key (optional)
- const RawBuffer &message,
- const RawBuffer &signature,
- const HashAlgorithm hash,
- const RSAPaddingAlgorithm padding)
+ const Credentials &cred,
+ int msgId,
+ const Name &publicKeyOrCertName,
+ const ClientId &owner,
+ const Password &password, // password for public_key (optional)
+ const RawBuffer &message,
+ const RawBuffer &signature,
+ const CryptoAlgorithm ¶ms)
{
- int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
-
- try {
- DB::Row row;
-
- CryptoAlgorithm params;
- params.addParam(ParamName::SV_HASH_ALGO, hash);
- params.addParam(ParamName::SV_RSA_PADDING, padding);
-
- // try certificate first - looking for a public key.
- // in case of PKCS, pub key from certificate will be found first
- // rather than private key from the same PKCS.
- retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
- if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
- retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
- }
-
- if (retCode == CKM_API_SUCCESS) {
- retCode = m_decider.getStore(row).getKey(row)->verify(params, message, signature);
- }
- } catch (const Crypto::Exception::Base &e) {
- LogError("GStore failed with error: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const KeyProvider::Exception::Base &e) {
- LogError("KeyProvider failed with error: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
- } catch (const CryptoLogic::Exception::Base &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const DB::Crypto::Exception::Base &e) {
- LogError("DB::Crypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const CKMLogic::Exception::DatabaseLocked &e) {
- LogError("Error " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_LOCKED;
- } catch (const CKM::Exception &e) {
- LogError("Unknown CKM::Exception: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- }
-
- auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
- commandId,
- retCode);
- return response.Pop();
+ return SerializeMessage(msgId, tryRet([&] {
+ // try certificate first - looking for a public key.
+ // in case of PKCS, pub key from certificate will be found first
+ // rather than private key from the same PKCS.
+ Crypto::GObjUPtr obj;
+ int retCode = readDataHelper(false, cred, DataType::CERTIFICATE,
+ publicKeyOrCertName, owner, password, obj);
+
+ if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
+ retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
+ publicKeyOrCertName, owner, password, obj);
+
+ if (retCode == CKM_API_SUCCESS)
+ retCode = obj->verify(params, message, signature);
+
+ return retCode;
+ }));
}
int CKMLogic::setPermissionHelper(
- const Credentials &cred, // who's the client
- const Name &name,
- const Label &label, // who's the owner
- const Label &accessorLabel, // who will get the access
- const PermissionMask permissionMask)
+ const Credentials &cred, // who's the client
+ const Name &name,
+ const ClientId &owner, // who's the owner
+ const ClientId &accessor, // who will get the access
+ const PermissionMask permissionMask)
{
- auto &handler = selectDatabase(cred, label);
+ auto [dbOp, retCode] = beginSave(cred, name, owner);
+ // Normally, saving requires alias to be unoccupied. When changing permissions it's the opposite
+ if (retCode != CKM_API_ERROR_DB_ALIAS_EXISTS) {
+ if (retCode == CKM_API_SUCCESS)
+ retCode = CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+ return retCode;
+ }
+
+ // currently we don't support modification of owner's permissions to his own rows
+ if (owner == accessor)
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ // system database does not support write/remove permissions
+ if ((0 == owner.compare(CLIENT_ID_SYSTEM)) && (permissionMask & Permission::REMOVE))
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ // set permissions to the row owned by owner for accessor
+ dbOp.database().setPermission(name, owner, accessor, permissionMask);
+ dbOp.transaction().commit();
+
+ return CKM_API_SUCCESS;
+}
- // we don't know the client
- if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
- return CKM_API_ERROR_INPUT_PARAM;
+RawBuffer CKMLogic::setPermission(
+ const Credentials &cred,
+ const int msgID,
+ const Name &name,
+ const ClientId &owner,
+ const ClientId &accessor,
+ const PermissionMask permissionMask)
+{
+ return SerializeMessage(msgID, tryRet([&] {
+ return setPermissionHelper(cred, name, owner, accessor, permissionMask);
+ }));
+}
- // use client label if not explicitly provided
- const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
+RawBuffer CKMLogic::deriveKey(
+ const Credentials &cred,
+ const int msgID,
+ const CryptoAlgorithm ¶ms,
+ const Name &secretName,
+ const ClientId &secretOwner,
+ const Password &secretPassword,
+ const Name &newKeyName,
+ const ClientId &newKeyOwner,
+ const Policy &newKeyPolicy)
+{
+ return SerializeMessage(msgID, tryRet([&] {
+ // Get key/secret for internal service use. It won't be exported to the client
+ Crypto::GObjUPtr obj;
+ DataType objType;
+ int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
+ secretName, secretOwner, secretPassword, obj, objType);
+ if (retCode != CKM_API_SUCCESS) {
+ if (retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
+ return retCode;
+
+ retCode = readDataHelper(false, cred, DataType::BINARY_DATA,
+ secretName, secretOwner, secretPassword, obj, objType);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+ }
+
+ auto [dbOp, digest, ret] = beginSaveAndGetHash(cred, newKeyName, newKeyOwner);
+ if (ret != CKM_API_SUCCESS)
+ return ret;
+
+ // ECDH (private key) -> binary secret, KBKDF -> symmetric key
+ DataType newKeyType = objType.isKeyPrivate() ? DataType::BINARY_DATA : DataType::KEY_AES;
+ if (!m_decider.checkStore(obj->backendId(), newKeyType, newKeyPolicy, false)) {
+ LogDebug("Can't import the derived key to backend " <<
+ static_cast<int>(obj->backendId()) << " with given policy");
+ return CKM_API_ERROR_INPUT_PARAM;
+ }
+
+ // derive
+ Token derived = obj->derive(params, newKeyPolicy.password, digest);
+
+ dbOp.finalize(std::move(derived), newKeyPolicy);
+
+ return CKM_API_SUCCESS;
+ }));
+}
- // verify name and label are correct
- if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
- return CKM_API_ERROR_INPUT_PARAM;
+RawBuffer CKMLogic::importWrappedKey(
+ const Credentials &cred,
+ const int msgId,
+ const CryptoAlgorithm ¶ms,
+ const Name &wrappingKeyName,
+ const ClientId &wrappingKeyOwner,
+ const Password &wrappingKeyPassword,
+ const Name &keyName,
+ const ClientId &keyOwner,
+ const RawBuffer &wrappedKey,
+ const CKM::DataType keyType,
+ const PolicySerializable &policy)
+{
+ return SerializeMessage(msgId, tryRet([&] {
+ Crypto::GObjUPtr wrappingKey;
+
+ auto [dbOp, digest, retCode] = beginSaveAndGetHash(cred, keyName, keyOwner);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
- // currently we don't support modification of owner's permissions to his own rows
- if (ownerLabel==accessorLabel)
- return CKM_API_ERROR_INPUT_PARAM;
+ retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, wrappingKeyName,
+ wrappingKeyOwner, wrappingKeyPassword, wrappingKey);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
- // system database does not support write/remove permissions
- if ((0 == ownerLabel.compare(LABEL_SYSTEM_DB)) &&
- (permissionMask & Permission::REMOVE))
- return CKM_API_ERROR_INPUT_PARAM;
+ if (!m_decider.checkStore(wrappingKey->backendId(), keyType, policy, true)) {
+ LogDebug("Can't import the wrapped key to backend " <<
+ static_cast<int>(wrappingKey->backendId()) << " with given policy");
+ return CKM_API_ERROR_INPUT_PARAM;
+ }
- // can the client modify permissions to owner's row?
- int retCode = m_accessControl.canModify(cred, ownerLabel);
- if(retCode != CKM_API_SUCCESS)
- return retCode;
+ Token token = wrappingKey->unwrap(params,
+ Crypto::Data(keyType, std::move(wrappedKey)),
+ policy.password,
+ digest);
- DB::Crypto::Transaction transaction(&handler.database);
+ dbOp.finalize(std::move(token), policy);
- if( !handler.database.isNameLabelPresent(name, ownerLabel) )
- return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+ return retCode;
+ }));
+}
+
+RawBuffer CKMLogic::exportWrappedKey(
+ const Credentials &cred,
+ const int msgID,
+ const CryptoAlgorithm ¶ms,
+ const Name &wrappingKeyName,
+ const ClientId &wrappingKeyOwner,
+ const Password &wrappingKeyPassword,
+ const Name &keyName,
+ const ClientId &keyOwner,
+ const Password &keyPassword)
+{
+ Crypto::GObjUPtr wrappingKey;
+ DB::Row wrappedKeyRow;
+ DataType wrappedKeyType;
+ RawBuffer wrappedKey;
- // removing non-existing permissions: fail
- if(permissionMask == Permission::NONE)
- {
- if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
- return CKM_API_ERROR_INPUT_PARAM;
- }
+ auto retCode = tryRet([&] {
+ auto retCode2 = readDataHelper(false, cred, DataType::DB_KEY_FIRST, wrappingKeyName,
+ wrappingKeyOwner, wrappingKeyPassword, wrappingKey);
+ if (retCode2 != CKM_API_SUCCESS)
+ return retCode2;
- // set permissions to the row owned by ownerLabel for accessorLabel
- handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
- transaction.commit();
+ retCode2 = readRowHelper(false, cred, DataType::DB_KEY_FIRST, keyName,
+ keyOwner, keyPassword, wrappedKeyRow, wrappedKeyType);
+ if (retCode2 != CKM_API_SUCCESS)
+ return retCode2;
- return CKM_API_SUCCESS;
+ wrappedKey = wrappingKey->wrap(params, wrappedKeyRow, keyPassword);
+
+ return retCode2;
+ });
+
+ return SerializeMessage(msgID, retCode, wrappedKeyType, wrappedKey);
}
-RawBuffer CKMLogic::setPermission(
- const Credentials &cred,
- const int command,
- const int msgID,
- const Name &name,
- const Label &label,
- const Label &accessorLabel,
- const PermissionMask permissionMask)
+RawBuffer CKMLogic::getBackendInfo(const int msgID, BackendId backend)
{
- int retCode;
- Try {
- retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
- } catch (const CKMLogic::Exception::DatabaseLocked &e) {
- LogError("Error " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_LOCKED;
- } Catch (CKM::Exception) {
- LogError("Error in set row!");
- retCode = CKM_API_ERROR_DB_ERROR;
- }
-
- return MessageBuffer::Serialize(command, msgID, retCode).Pop();
+ BackendInfo info;
+ auto retCode = tryRet([&] {
+ CryptoBackend cryptoBackend;
+ if (backend == BackendId::SW)
+ cryptoBackend = CryptoBackend::OpenSSL;
+ else if (backend == BackendId::TZ)
+ cryptoBackend = CryptoBackend::TrustZone;
+ else
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ auto store = m_decider.getStore(cryptoBackend);
+ if (store == nullptr) {
+ LogError("Required backend is unavailable");
+ return CKM_API_ERROR_INPUT_PARAM;
+ }
+
+ info.maxChunkSize = store->maxChunkSize();
+ return CKM_API_SUCCESS;
+ });
+
+ return SerializeMessage(msgID, retCode, BackendInfoSerializable(info));
}
} // namespace CKM
-