* @version 1.0
* @brief Sample service implementation.
*/
-#include <vconf/vconf.h>
#include <dpl/serialization.h>
#include <dpl/log/log.h>
#include <ckm/ckm-error.h>
#include <ckm/ckm-type.h>
#include <key-provider.h>
#include <file-system.h>
-#include <CryptoService.h>
#include <ckm-logic.h>
#include <key-impl.h>
-
-#ifndef VCONFKEY_SECURITY_MDPP_STATE
-#define VCONFKEY_SECURITY_MDPP_STATE = "file/security_mdpp/security_mdpp_state";
-#endif
+#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>
namespace {
-const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
-
-const char* const MDPP_MODE_ENFORCING = "Enforcing";
-const char* const MDPP_MODE_ENABLED = "Enabled";
+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;
+}
+bool isNameValid(const CKM::Name &name) {
+ if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
+ return false;
+ return true;
+}
} // anonymous namespace
namespace CKM {
-CKMLogic::CKMLogic() : m_ccMode(false)
+const uid_t CKMLogic::SYSTEM_DB_UID = 0;
+
+CKMLogic::CKMLogic()
{
- if (CKM_API_SUCCESS != m_certStore.setSystemCertificateDir(CERT_SYSTEM_DIR)) {
- LogError("Fatal error in CertificateStore::setSystemCertificateDir. Chain creation will not work");
+ 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);
}
- updateCCMode_internal();
+ // 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());
+ }
}
CKMLogic::~CKMLogic(){}
-RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password) {
- // TODO try catch for all errors that should be supported by error code
- int retCode = CKM_API_SUCCESS;
+void CKMLogic::loadDKEKFile(uid_t user, const Password &password) {
+ auto &handle = m_userDataMap[user];
- try {
- if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
- auto &handle = m_userDataMap[user];
- FileSystem fs(user);
- auto wrappedDomainKEK = fs.getDKEK();
-
- if (wrappedDomainKEK.empty()) {
- wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
- fs.saveDKEK(wrappedDomainKEK);
- }
+ FileSystem fs(user);
- handle.keyProvider = KeyProvider(wrappedDomainKEK, password);
+ auto wrappedDKEK = fs.getDKEK();
- auto wrappedDatabaseDEK = fs.getDBDEK();
+ if (wrappedDKEK.empty()) {
+ wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
+ fs.saveDKEK(wrappedDKEK);
+ }
- if (wrappedDatabaseDEK.empty()) {
- wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
- fs.saveDBDEK(wrappedDatabaseDEK);
- }
+ handle.keyProvider = KeyProvider(wrappedDKEK, password);
+}
+
+void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
+ auto &handle = m_userDataMap[user];
+
+ FileSystem fs(user);
+ fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(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 = DBCrypto(fs.getDBPath(), key);
- handle.crypto = CryptoLogic();
+ 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);
}
-
- // TODO wipe key
}
- } 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 Exc::Exception &e) {
+ retCode = e.error();
} catch (const CKM::Exception &e) {
LogError("CKM::Exception: " << e.GetMessage());
retCode = CKM_API_ERROR_SERVER_ERROR;
}
- if(retCode != CKM_API_SUCCESS) {
- // When not successful, UserData in m_userDataMap should be erased.
- // Because other operations make decision based on the existence of UserData in m_userDataMap.
+ if (CKM_API_SUCCESS != retCode)
m_userDataMap.erase(user);
- }
- return MessageBuffer::Serialize(retCode).Pop();
+ return retCode;
}
-void CKMLogic::updateCCMode_internal() {
- int fipsModeStatus = 0;
- int rc = 0;
- bool newMode;
+int CKMLogic::unlockSystemDB()
+{
+ return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
+}
- char *mdppState = vconf_get_str(VCONFKEY_SECURITY_MDPP_STATE);
- newMode = ( mdppState && (!strcmp(mdppState, MDPP_MODE_ENABLED) ||
- !strcmp(mdppState, MDPP_MODE_ENFORCING)) );
- if (newMode == m_ccMode)
- return;
+UserData & CKMLogic::selectDatabase(const Credentials &cred, const Label &incoming_label)
+{
+ // 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))
+ ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
- m_ccMode = newMode;
+ if (0 != incoming_label.compare(LABEL_SYSTEM_DB))
+ return m_userDataMap[cred.clientUid];
+ }
- fipsModeStatus = FIPS_mode();
+ // system database selected, modify the label
+ if (CKM_API_SUCCESS != unlockSystemDB() )
+ ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
+ return m_userDataMap[SYSTEM_DB_UID];
+}
- if(m_ccMode) {
- if(fipsModeStatus == 0) { // If FIPS mode off
- rc = FIPS_mode_set(1); // Change FIPS_mode from off to on
- if(rc == 0) {
- LogError("Error in FIPS_mode_set function");
- }
- }
- } else {
- if(fipsModeStatus == 1) { // If FIPS mode on
- rc = FIPS_mode_set(0); // Change FIPS_mode from on to off
- if(rc == 0) {
- LogError("Error in FIPS_mode_set function");
- }
- }
+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();
}
RawBuffer CKMLogic::updateCCMode() {
- updateCCMode_internal();
+ m_accessControl.updateCCMode();
return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
}
-RawBuffer CKMLogic::lockUserKey(uid_t user) {
+RawBuffer CKMLogic::lockUserKey(uid_t user)
+{
int retCode = CKM_API_SUCCESS;
- // TODO try catch for all errors that should be supported by error code
- m_userDataMap.erase(user);
+ 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();
RawBuffer CKMLogic::removeUserData(uid_t user) {
int retCode = CKM_API_SUCCESS;
- // TODO try catch for all errors that should be supported by error code
+
+ if (m_accessControl.isSystemService(user))
+ user = SYSTEM_DB_UID;
+
m_userDataMap.erase(user);
FileSystem fs(user);
return MessageBuffer::Serialize(retCode).Pop();
}
+int CKMLogic::changeUserPasswordHelper(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;
+
+ loadDKEKFile(user, oldPassword);
+ saveDKEKFile(user, newPassword);
+
+ return CKM_API_SUCCESS;
+}
+
RawBuffer CKMLogic::changeUserPassword(
uid_t user,
const Password &oldPassword,
const Password &newPassword)
{
int retCode = CKM_API_SUCCESS;
- try {
- FileSystem fs(user);
- auto wrappedDomainKEK = fs.getDKEK();
- if (wrappedDomainKEK.empty()) {
- retCode = CKM_API_ERROR_BAD_REQUEST;
- } else {
- wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
- fs.saveDKEK(wrappedDomainKEK);
- }
- } 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;
+ try
+ {
+ retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
+ } catch (const Exc::Exception &e) {
+ retCode = e.error();
} catch (const CKM::Exception &e) {
LogError("CKM::Exception: " << e.GetMessage());
retCode = CKM_API_ERROR_SERVER_ERROR;
return MessageBuffer::Serialize(retCode).Pop();
}
-RawBuffer CKMLogic::resetUserPassword(
+int CKMLogic::resetUserPasswordHelper(
uid_t user,
const Password &newPassword)
{
+ // do not allow to reset system database password
+ if( m_accessControl.isSystemService(user) )
+ return CKM_API_ERROR_INPUT_PARAM;
+
int retCode = CKM_API_SUCCESS;
- // TODO try-catch
- if (0 == m_userDataMap.count(user)) {
- retCode = CKM_API_ERROR_BAD_REQUEST;
- } else {
- auto &handler = m_userDataMap[user];
+ if (0 == m_userDataMap.count(user))
+ {
+ // Check if key exists. If exists we must return error
FileSystem fs(user);
- fs.saveDKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
+ auto wrappedDKEKMain = fs.getDKEK();
+ if (!wrappedDKEKMain.empty())
+ retCode = CKM_API_ERROR_BAD_REQUEST;
+ } else {
+ saveDKEKFile(user, newPassword);
+ }
+
+ return retCode;
+}
+
+RawBuffer CKMLogic::resetUserPassword(
+ uid_t user,
+ const Password &newPassword)
+{
+ int retCode = CKM_API_SUCCESS;
+ try {
+ retCode = resetUserPasswordHelper(user, newPassword);
+ } catch (const Exc::Exception &e) {
+ retCode = e.error();
+ } catch (const CKM::Exception &e) {
+ LogError("CKM::Exception: " << e.GetMessage());
+ retCode = CKM_API_ERROR_SERVER_ERROR;
}
return MessageBuffer::Serialize(retCode).Pop();
fs.addRemovedApp(smackLabel);
} else {
auto &handle = m_userDataMap[userId];
+ handle.crypto.removeKey(smackLabel);
handle.database.deleteKey(smackLabel);
}
}
}
- } catch (const DBCrypto::Exception::InternalError &e) {
- LogError("DBCrypto couldn't remove data: " << e.GetMessage());
+ } catch (const DB::Crypto::Exception::InternalError &e) {
+ LogError("DB::Crypto couldn't remove data: " << e.GetMessage());
retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const DBCrypto::Exception::TransactionError &e) {
- LogError("DBCrypto transaction failed with message " << e.GetMessage());
+ } catch (const DB::Crypto::Exception::TransactionError &e) {
+ LogError("DB::Crypto transaction failed with message " << e.GetMessage());
retCode = CKM_API_ERROR_DB_ERROR;
+ } catch (const Exc::Exception &e) {
+ retCode = e.error();
+ } catch (const CKM::Exception &e) {
+ LogError("CKM::Exception: " << e.GetMessage());
+ retCode = CKM_API_ERROR_SERVER_ERROR;
}
return MessageBuffer::Serialize(retCode).Pop();
}
-int CKMLogic::saveDataHelper(
- Credentials &cred,
- DBDataType dataType,
+int CKMLogic::checkSaveConditions(
+ const Credentials &cred,
+ UserData &handler,
const Name &name,
- const RawBuffer &key,
- const PolicySerializable &policy)
+ const Label &ownerLabel)
{
- if (0 == m_userDataMap.count(cred.uid))
- return CKM_API_ERROR_DB_LOCKED;
+ // verify name and label are correct
+ if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
+ LogWarning("Invalid parameter passed to key-manager");
+ return CKM_API_ERROR_INPUT_PARAM;
+ }
- // proceed to data save
- DBRow row = { name, cred.smackLabel,
- policy.extractable, dataType, DBCMAlgType::NONE,
- 0, RawBuffer(), static_cast<int>(key.size()), key, RawBuffer() };
+ // 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;
+ }
- auto &handler = m_userDataMap[cred.uid];
- DBCrypto::Transaction transaction(&handler.database);
- if (!handler.crypto.haveKey(cred.smackLabel)) {
- RawBuffer key;
- auto key_optional = handler.database.getKey(cred.smackLabel);
+ // 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: "
- << cred.smackLabel);
- key = handler.keyProvider.generateDEK(cred.smackLabel);
- handler.database.saveKey(cred.smackLabel, key);
+ 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");
- key = *key_optional;
+ got_key = *key_optional;
}
- key = handler.keyProvider.getPureDEK(key);
- handler.crypto.pushKey(cred.smackLabel, key);
+ got_key = handler.keyProvider.getPureDEK(got_key);
+ handler.crypto.pushKey(ownerLabel, got_key);
}
- // Do not encrypt data with password during cc_mode on
- if(m_ccMode) {
- handler.crypto.encryptRow("", row);
+ return CKM_API_SUCCESS;
+}
+
+DB::Row CKMLogic::createEncryptedRow(
+ CryptoLogic &crypto,
+ const Name &name,
+ const Label &label,
+ DataType dataType,
+ const RawBuffer &data,
+ const Policy &policy) const
+{
+ 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 {
- handler.crypto.encryptRow(policy.password, row);
+ crypto.encryptRow(policy.password, row);
}
+ return row;
+}
- handler.database.saveDBRow(row);
- transaction.commit();
- return CKM_API_SUCCESS;
+int CKMLogic::verifyBinaryData(DataType dataType, RawBuffer &input_data) const
+{
+ RawBuffer dummy;
+ return toBinaryData(dataType, input_data, dummy);
}
-void CKMLogic::verifyBinaryData(DBDataType dataType, const RawBuffer &input_data) const
+int CKMLogic::toBinaryData(DataType dataType,
+ const RawBuffer &input_data,
+ RawBuffer &output_data) const
{
// verify the data integrity
- switch(dataType)
+ if (dataType.isKey())
{
- case DBDataType::KEY_RSA_PUBLIC:
- case DBDataType::KEY_RSA_PRIVATE:
- case DBDataType::KEY_ECDSA_PUBLIC:
- case DBDataType::KEY_ECDSA_PRIVATE:
- case DBDataType::KEY_DSA_PUBLIC:
- case DBDataType::KEY_DSA_PRIVATE:
- case DBDataType::KEY_AES:
+ 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)
{
- KeyShPtr output_key = CKM::Key::create(input_data);
- if(output_key.get() == NULL)
- ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid key data");
- break;
+ LogError("provided binary data is not valid key data");
+ return CKM_API_ERROR_INPUT_PARAM;
}
-
- case DBDataType::CERTIFICATE:
+ 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)
{
- CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
- if(cert.get() == NULL)
- ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid certificate data");
- break;
+ LogError("provided binary data is not valid certificate data");
+ return CKM_API_ERROR_INPUT_PARAM;
}
-
- // TODO: add here BINARY_DATA verification, i.e: max size etc.
-
- default: break;
+ output_data = cert->getDER();
}
+ else
+ output_data = input_data;
+ // TODO: add here BINARY_DATA verification, i.e: max size etc.
+ return CKM_API_SUCCESS;
}
-RawBuffer CKMLogic::saveData(
- Credentials &cred,
- int commandId,
- DBDataType dataType,
+int CKMLogic::verifyAndSaveDataHelper(
+ const Credentials &cred,
const Name &name,
- const RawBuffer &key,
+ const Label &label,
+ const RawBuffer &data,
+ DataType dataType,
const PolicySerializable &policy)
{
- int retCode = CKM_API_SUCCESS;
- try {
- verifyBinaryData(dataType, key);
+ int retCode = CKM_API_ERROR_UNKNOWN;
- retCode = saveDataHelper(cred, dataType, name, key, policy);
- LogDebug("SaveDataHelper returned: " << retCode);
- } catch (const CKMLogic::Exception::InputDataInvalid &e) {
- LogError("Provided data invalid: " << e.GetMessage());
- retCode = CKM_API_ERROR_INPUT_PARAM;
- } 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 DBCrypto::Exception::InternalError &e) {
- LogError("DBCrypto failed with message: " << e.GetMessage());
+ 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 DB::Crypto::Exception::InternalError &e) {
+ LogError("DB::Crypto failed with message: " << e.GetMessage());
retCode = CKM_API_ERROR_DB_ERROR;
- } catch (const DBCrypto::Exception::NameExists &e) {
- LogError("DBCrypto couldn't save duplicate name");
- retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
- } catch (const DBCrypto::Exception::TransactionError &e) {
- LogError("DBCrypto transaction failed with message " << e.GetMessage());
+ } catch (const DB::Crypto::Exception::TransactionError &e) {
+ LogError("DB::Crypto transaction failed with message " << e.GetMessage());
retCode = CKM_API_ERROR_DB_ERROR;
+ } catch (const Exc::Exception &e) {
+ retCode = e.error();
+ } catch (const CKM::Exception &e) {
+ LogError("CKM::Exception: " << e.GetMessage());
+ retCode = CKM_API_ERROR_SERVER_ERROR;
}
+ return retCode;
+}
+RawBuffer CKMLogic::saveData(
+ const Credentials &cred,
+ int commandId,
+ const Name &name,
+ const Label &label,
+ const RawBuffer &data,
+ DataType dataType,
+ const PolicySerializable &policy)
+{
+ int retCode = verifyAndSaveDataHelper(cred, name, label, data, dataType, policy);
auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
commandId,
retCode,
return response.Pop();
}
-RawBuffer CKMLogic::removeData(
- Credentials &cred,
- int commandId,
- DBDataType dataType,
+int CKMLogic::extractPKCS12Data(
+ CryptoLogic &crypto,
const Name &name,
- const Label &label)
+ const Label &ownerLabel,
+ const PKCS12Serializable &pkcs,
+ const PolicySerializable &keyPolicy,
+ const PolicySerializable &certPolicy,
+ DB::RowVector &output) const
{
- int retCode = CKM_API_SUCCESS;
+ // 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));
- if (0 < m_userDataMap.count(cred.uid)) {
- Try {
- // use client label if not explicitly provided
- const Label & ownerLabel = label.empty() ? cred.smackLabel : label;
+ // 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;
- // verify name and label are correct
- if (true == checkNameAndLabelValid(name, ownerLabel))
- {
- auto erased = m_userDataMap[cred.uid].database.deleteDBRow(name, ownerLabel, cred.smackLabel);
- // check if the data existed or not
- if(!erased) {
- LogError("No row for given name and label");
- retCode = CKM_API_ERROR_DB_ALIAS_UNKNOWN;
- }
- }
- else
- {
- LogError("Invalid label or name format");
- retCode = CKM_API_ERROR_INPUT_PARAM;
- }
- } Catch (DBCrypto::Exception::PermissionDenied) {
- LogError("Error: not enough permissions!");
- retCode = CKM_API_ERROR_ACCESS_DENIED;
- } Catch (CKM::Exception) {
- LogError("Error in deleting row!");
- retCode = CKM_API_ERROR_DB_ERROR;
- }
- } else {
- retCode = CKM_API_ERROR_DB_LOCKED;
+ output.push_back(createEncryptedRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy));
}
- auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
- commandId,
- retCode,
- static_cast<int>(dataType));
- return response.Pop();
+ return CKM_API_SUCCESS;
}
-bool CKMLogic::checkNameAndLabelValid(const Name &name, const Label &label)
+RawBuffer CKMLogic::savePKCS12(
+ const Credentials &cred,
+ int commandId,
+ const Name &name,
+ const Label &label,
+ const PKCS12Serializable &pkcs,
+ const PolicySerializable &keyPolicy,
+ const PolicySerializable &certPolicy)
{
- // verify the name is valid
- if(name.find(':') != Label::npos)
- return false;
-
- // verify the label is valid
- if(label.find(LABEL_NAME_SEPARATOR) != Label::npos)
- return false;
+ int retCode = CKM_API_ERROR_UNKNOWN;
+ try {
+ retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
+ } catch (const Exc::Exception &e) {
+ retCode = e.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;
+ }
- return true;
+ auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
+ commandId,
+ retCode);
+ return response.Pop();
}
-int CKMLogic::getDataHelper(
- Credentials &cred,
- DBDataType dataType,
- const Name &name,
- const Label &label,
- const Password &password,
- DBRow &row)
-{
- if (0 == m_userDataMap.count(cred.uid))
- return CKM_API_ERROR_DB_LOCKED;
- auto &handler = m_userDataMap[cred.uid];
+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;
-
- // verify name and label are correct
- if (true != checkNameAndLabelValid(name, ownerLabel))
+ 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;
-
- DBCrypto::DBRowOptional row_optional;
- if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA)
- {
- row_optional = handler.database.getDBRow(name, ownerLabel, cred.smackLabel, dataType);
- }
- else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST)) &&
- (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
- {
- row_optional = handler.database.getKeyDBRow(name, ownerLabel, cred.smackLabel);
}
- else
+
+ 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)
{
- LogError("Unknown type of requested data" << (int)dataType);
- return CKM_API_ERROR_BAD_REQUEST;
- }
- if(!row_optional) {
- LogError("No row for given name, label and type");
- return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
- } else {
- row = *row_optional;
+ LogWarning("access control check result: " << retCode);
+ return retCode;
}
- if (!handler.crypto.haveKey(row.smackLabel)) {
- RawBuffer key;
- auto key_optional = handler.database.getKey(row.smackLabel);
- 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(cred.smackLabel, key);
+ 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;
}
- handler.crypto.decryptRow(password, row);
return CKM_API_SUCCESS;
}
-RawBuffer CKMLogic::getData(
- Credentials &cred,
+RawBuffer CKMLogic::removeData(
+ const Credentials &cred,
int commandId,
- DBDataType dataType,
const Name &name,
- const Label &label,
- const Password &password)
+ const Label &label)
{
- int retCode = CKM_API_SUCCESS;
- DBRow row;
+ int retCode = CKM_API_ERROR_UNKNOWN;
- try {
- retCode = getDataHelper(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::Base &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const DBCrypto::Exception::PermissionDenied &e) {
- LogError("DBCrypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_ACCESS_DENIED;
- } catch (const DBCrypto::Exception::Base &e) {
- LogError("DBCrypto failed with message: " << e.GetMessage());
+ try
+ {
+ retCode = removeDataHelper(cred, name, label);
+ }
+ catch (const Exc::Exception &e)
+ {
+ retCode = e.error();
+ }
+ catch (const CKM::Exception &)
+ {
+ LogError("Error in deleting row!");
retCode = CKM_API_ERROR_DB_ERROR;
}
- if (CKM_API_SUCCESS != retCode) {
- row.data.clear();
- row.dataType = dataType;
+ auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
+ commandId,
+ retCode);
+ return response.Pop();
+}
+
+int CKMLogic::readSingleRow(const Name &name,
+ const Label &ownerLabel,
+ 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,
+ ownerLabel,
+ DataType::DB_KEY_FIRST,
+ DataType::DB_KEY_LAST);
+ } else {
+ // read anything else
+ row_optional = database.getRow(name,
+ ownerLabel,
+ dataType);
}
- if ((CKM_API_SUCCESS == retCode) && (row.exportable == 0)) {
- row.data.clear();
- retCode = CKM_API_ERROR_NOT_EXPORTABLE;
+ if(!row_optional) {
+ LogError("No row for given name, label and type");
+ return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+ } else {
+ row = *row_optional;
}
- // Prevent extracting private keys during cc-mode on
- if((m_ccMode) && (row.dataType == DBDataType::KEY_RSA_PRIVATE ||
- row.dataType == DBDataType::KEY_ECDSA_PRIVATE ||
- row.dataType == DBDataType::KEY_DSA_PRIVATE))
+ return CKM_API_SUCCESS;
+}
+
+
+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;
+}
+
+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);
+
+ if(exportFlag)
+ return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt));
+ return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt));
+}
+
+int CKMLogic::readDataHelper(
+ bool exportFlag,
+ const Credentials &cred,
+ DataType dataType,
+ const Name &name,
+ const Label &label,
+ const Password &password,
+ DB::RowVector &rows)
+{
+ 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;
+}
+
+int CKMLogic::readDataHelper(
+ bool exportFlag,
+ const Credentials &cred,
+ DataType dataType,
+ const Name &name,
+ const Label &label,
+ const Password &password,
+ DB::Row &row)
+{
+ 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;
+}
+
+RawBuffer CKMLogic::getData(
+ const Credentials &cred,
+ int commandId,
+ DataType dataType,
+ const Name &name,
+ const Label &label,
+ const Password &password)
+{
+ int retCode = CKM_API_SUCCESS;
+ DB::Row row;
+
+ try {
+ retCode = readDataHelper(true, cred, dataType, name, label, password, row);
+ } catch (const DB::Crypto::Exception::Base &e) {
+ LogError("DB::Crypto failed with message: " << e.GetMessage());
+ retCode = CKM_API_ERROR_DB_ERROR;
+ } catch (const Exc::Exception &e) {
+ retCode = e.error();
+ } catch (const CKM::Exception &e) {
+ LogError("CKM::Exception: " << e.GetMessage());
+ retCode = CKM_API_ERROR_SERVER_ERROR;
+ }
+
+ if (CKM_API_SUCCESS != retCode) {
row.data.clear();
- retCode = CKM_API_ERROR_BAD_REQUEST;
+ row.dataType = dataType;
}
auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
return response.Pop();
}
-RawBuffer CKMLogic::getDataList(
- Credentials &cred,
- int commandId,
- DBDataType dataType)
+int CKMLogic::getPKCS12Helper(
+ const Credentials &cred,
+ const Name &name,
+ const Label &label,
+ const Password &keyPassword,
+ const Password &certPassword,
+ KeyShPtr & privKey,
+ CertificateShPtr & cert,
+ CertificateShPtrVector & caChain)
{
- int retCode = CKM_API_SUCCESS;
- LabelNameVector labelNameVector;
+ 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;
+}
+
+RawBuffer CKMLogic::getPKCS12(
+ const Credentials &cred,
+ int commandId,
+ const Name &name,
+ const Label &label,
+ 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 DB::Crypto::Exception::Base &e) {
+ LogError("DB::Crypto failed with message: " << e.GetMessage());
+ retCode = CKM_API_ERROR_DB_ERROR;
+ } catch (const Exc::Exception &e) {
+ retCode = e.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::GET_PKCS12),
+ commandId,
+ retCode,
+ output);
+ return response.Pop();
+}
+
+int CKMLogic::getDataListHelper(const Credentials &cred,
+ const DataType dataType,
+ LabelNameVector &labelNameVector)
+{
+ int retCode = CKM_API_ERROR_DB_LOCKED;
+ if (0 < m_userDataMap.count(cred.clientUid))
+ {
+ auto &database = m_userDataMap[cred.clientUid].database;
- if (0 < m_userDataMap.count(cred.uid)) {
- auto &handler = m_userDataMap[cred.uid];
Try {
- if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
- handler.database.getNames(cred.smackLabel, dataType, labelNameVector);
+ LabelNameVector tmpVector;
+ if (dataType.isKey()) {
+ // list all key types
+ database.listNames(cred.smackLabel,
+ tmpVector,
+ DataType::DB_KEY_FIRST,
+ DataType::DB_KEY_LAST);
} else {
- handler.database.getKeyNames(cred.smackLabel, labelNameVector);
+ // list anything else
+ database.listNames(cred.smackLabel,
+ tmpVector,
+ dataType);
}
- } Catch (CKM::Exception) {
+ 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;
}
- } else {
- retCode = CKM_API_ERROR_DB_LOCKED;
+ }
+ return retCode;
+}
+
+RawBuffer CKMLogic::getDataList(
+ const Credentials &cred,
+ int commandId,
+ 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,
return response.Pop();
}
+int CKMLogic::saveDataHelper(
+ const Credentials &cred,
+ const Name &name,
+ const Label &label,
+ DataType dataType,
+ const RawBuffer &data,
+ const PolicySerializable &policy)
+{
+ 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;
+
+ // save the data
+ DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, dataType, data, policy);
+ handler.database.saveRow(encryptedRow);
+
+ transaction.commit();
+ return CKM_API_SUCCESS;
+}
+
+int CKMLogic::saveDataHelper(
+ const Credentials &cred,
+ const Name &name,
+ const Label &label,
+ const PKCS12Serializable &pkcs,
+ const PolicySerializable &keyPolicy,
+ const PolicySerializable &certPolicy)
+{
+ 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;
+}
+
+
+int CKMLogic::createKeyAESHelper(
+ const Credentials &cred,
+ const int size,
+ const Name &name,
+ const Label &label,
+ const PolicySerializable &policy)
+{
+ CryptoAlgorithm keyGenAlgorithm;
+ keyGenAlgorithm.setParam(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);
+}
+
int CKMLogic::createKeyPairHelper(
- Credentials &cred,
- const KeyType key_type,
- const int additional_param,
+ 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 (0 >= m_userDataMap.count(cred.uid))
- return CKM_API_ERROR_DB_LOCKED;
-
- auto &handler = m_userDataMap[cred.uid];
- KeyImpl prv, pub;
- int retCode;
- switch(key_type)
- {
- case KeyType::KEY_RSA_PUBLIC:
- case KeyType::KEY_RSA_PRIVATE:
- retCode = CryptoService::createKeyPairRSA(additional_param, prv, pub);
- break;
-
- case KeyType::KEY_DSA_PUBLIC:
- case KeyType::KEY_DSA_PRIVATE:
- retCode = CryptoService::createKeyPairDSA(additional_param, prv, pub);
- break;
-
- case KeyType::KEY_ECDSA_PUBLIC:
- case KeyType::KEY_ECDSA_PRIVATE:
- retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(additional_param), prv, pub);
- break;
-
- default:
- return CKM_API_ERROR_INPUT_PARAM;
- }
-
- if (CKM_CRYPTO_CREATEKEY_SUCCESS != retCode)
- {
- LogDebug("CryptoService error with code: " << retCode);
- return CKM_API_ERROR_SERVER_ERROR; // TODO error code
- }
-
- DBCrypto::Transaction transaction(&handler.database);
- retCode = saveDataHelper(cred,
- toDBDataType(prv.getType()),
- namePrivate,
- prv.getDER(),
- policyPrivate);
-
+ auto &handlerPriv = selectDatabase(cred, labelPrivate);
+ auto &handlerPub = selectDatabase(cred, labelPublic);
+
+ AlgoType keyType = AlgoType::RSA_GEN;
+ if(!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
+ ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
+ DataType dt(keyType);
+ if(!dt.isKey())
+ ThrowErr(Exc::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,
- toDBDataType(pub.getType()),
- namePublic,
- pub.getDER(),
- policyPublic);
-
+ namePublic,
+ labelPublic,
+ keys.second.dataType,
+ keys.second.data,
+ policyPublic);
if (CKM_API_SUCCESS != retCode)
return retCode;
- transaction.commit();
-
- return retCode;
+ transactionPub.commit();
+ transactionPriv.commit();
+ return CKM_API_SUCCESS;
}
RawBuffer CKMLogic::createKeyPair(
- Credentials &cred,
- LogicCommand protocol_cmd,
+ const Credentials &cred,
int commandId,
- const int additional_param,
+ const CryptoAlgorithmSerializable & keyGenParams,
const Name &namePrivate,
+ const Label &labelPrivate,
const Name &namePublic,
+ const Label &labelPublic,
const PolicySerializable &policyPrivate,
const PolicySerializable &policyPublic)
{
int retCode = CKM_API_SUCCESS;
- KeyType key_type = KeyType::KEY_NONE;
- switch(protocol_cmd)
- {
- case LogicCommand::CREATE_KEY_PAIR_RSA:
- key_type = KeyType::KEY_RSA_PUBLIC;
- break;
- case LogicCommand::CREATE_KEY_PAIR_DSA:
- key_type = KeyType::KEY_DSA_PUBLIC;
- break;
- case LogicCommand::CREATE_KEY_PAIR_ECDSA:
- key_type = KeyType::KEY_ECDSA_PUBLIC;
- break;
- default:
- break;
- }
-
try {
retCode = createKeyPairHelper(
cred,
- key_type,
- additional_param,
+ keyGenParams,
namePrivate,
+ labelPrivate,
namePublic,
+ labelPublic,
policyPrivate,
policyPublic);
-
- } catch (DBCrypto::Exception::NameExists &e) {
- LogDebug("DBCrypto error: name exists: " << e.GetMessage());
- retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
- } catch (DBCrypto::Exception::TransactionError &e) {
- LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
+ } catch(const Exc::Exception &e) {
+ retCode = e.error();
+ } 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 (DBCrypto::Exception::InternalError &e) {
- LogDebug("DBCrypto internal error: " << e.GetMessage());
+ } catch (DB::Crypto::Exception::InternalError &e) {
+ LogDebug("DB::Crypto internal error: " << e.GetMessage());
retCode = CKM_API_ERROR_DB_ERROR;
+ } catch (const CKM::Exception &e) {
+ LogError("CKM::Exception: " << e.GetMessage());
+ retCode = CKM_API_ERROR_SERVER_ERROR;
}
- return MessageBuffer::Serialize(static_cast<int>(protocol_cmd), commandId, retCode).Pop();
+ return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
+ commandId, retCode).Pop();
}
-RawBuffer CKMLogic::getCertificateChain(
- Credentials &cred,
+RawBuffer CKMLogic::createKeyAES(
+ const Credentials &cred,
int commandId,
- const RawBuffer &certificate,
- const RawBufferVector &untrustedRawCertVector)
+ const int size,
+ const Name &name,
+ const Label &label,
+ const PolicySerializable &policy)
{
- (void)cred;
+ int retCode = CKM_API_SUCCESS;
- CertificateImpl cert(certificate, DataFormat::FORM_DER);
+ try {
+ retCode = createKeyAESHelper(cred, size, name, label, policy);
+ } catch (const Exc::Exception &e) {
+ retCode = e.error();
+ } 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 (DB::Crypto::Exception::InternalError &e) {
+ LogDebug("DB::Crypto internal error: " << e.GetMessage());
+ retCode = CKM_API_ERROR_DB_ERROR;
+ } 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 CKMLogic::readCertificateHelper(
+ const Credentials &cred,
+ const LabelNameVector &labelNameVector,
+ 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;
+}
+
+int CKMLogic::getCertificateChainHelper(
+ const CertificateImpl &cert,
+ const RawBufferVector &untrustedCertificates,
+ const RawBufferVector &trustedCertificates,
+ bool useTrustedSystemCertificates,
+ RawBufferVector &chainRawVector)
+{
CertificateImplVector untrustedCertVector;
+ CertificateImplVector trustedCertVector;
CertificateImplVector chainVector;
- RawBufferVector chainRawVector;
- for (auto &e: untrustedRawCertVector)
+ 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;
- LogDebug("Cert is empty: " << cert.empty());
+ for (auto &e : chainVector)
+ chainRawVector.push_back(e.getDER());
+ return CKM_API_SUCCESS;
+}
- int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
+int CKMLogic::getCertificateChainHelper(
+ const Credentials &cred,
+ const CertificateImpl &cert,
+ const LabelNameVector &untrusted,
+ const LabelNameVector &trusted,
+ bool useTrustedSystemCertificates,
+ RawBufferVector &chainRawVector)
+{
+ CertificateImplVector untrustedCertVector;
+ CertificateImplVector trustedCertVector;
+ CertificateImplVector chainVector;
+ DB::Row row;
- if (retCode == CKM_API_SUCCESS) {
- for (auto &e : chainVector)
- chainRawVector.push_back(e.getDER());
+ 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)
+{
+ 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 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),
}
RawBuffer CKMLogic::getCertificateChain(
- Credentials &cred,
+ const Credentials &cred,
int commandId,
const RawBuffer &certificate,
- const AliasVector &aliasVector)
+ const LabelNameVector &untrustedCertificates,
+ const LabelNameVector &trustedCertificates,
+ bool useTrustedSystemCertificates)
{
- int retCode = CKM_API_SUCCESS;
- std::size_t separator_pos = 0;
+ int retCode = CKM_API_ERROR_UNKNOWN;
+ CertificateImpl cert(certificate, DataFormat::FORM_DER);
RawBufferVector chainRawVector;
try {
- CertificateImpl cert(certificate, DataFormat::FORM_DER);
- CertificateImplVector untrustedCertVector;
- CertificateImplVector chainVector;
- DBRow row;
-
- if (cert.empty()) {
- retCode = CKM_API_ERROR_SERVER_ERROR;
- goto senderror;
- }
-
- for (auto &i: aliasVector) {
- if ((separator_pos = i.rfind(LABEL_NAME_SEPARATOR)) == Alias::npos) {
- // No label prefixed in alias. put empty label
- retCode = getDataHelper(
- cred,
- DBDataType::CERTIFICATE,
- i,
- Label(),
- Password(),
- row);
- }
- else {
- retCode = getDataHelper(
- cred,
- DBDataType::CERTIFICATE,
- i.substr(separator_pos+strlen(LABEL_NAME_SEPARATOR)), // alias
- Label(i.substr(0, separator_pos)), // label
- Password(),
- row);
- }
-
- if (retCode != CKM_API_SUCCESS)
- goto senderror;
-
- untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
- }
-
- retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
-
- if (retCode != CKM_API_SUCCESS)
- goto senderror;
-
- for (auto &i: chainVector)
- chainRawVector.push_back(i.getDER());
-
- } catch (const CryptoLogic::Exception::Base &e) {
- LogError("DBCyptorModule failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const DBCrypto::Exception::PermissionDenied &e) {
- LogError("DBCrypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_ACCESS_DENIED;
- } catch (const DBCrypto::Exception::Base &e) {
- LogError("DBCrypto failed with message: " << e.GetMessage());
+ retCode = getCertificateChainHelper(cred,
+ cert,
+ untrustedCertificates,
+ trustedCertificates,
+ useTrustedSystemCertificates,
+ chainRawVector);
+ } catch (const DB::Crypto::Exception::Base &e) {
+ LogError("DB::Crypto failed with message: " << e.GetMessage());
retCode = CKM_API_ERROR_DB_ERROR;
+ } 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.");
}
-senderror:
auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
commandId,
retCode,
}
RawBuffer CKMLogic::createSignature(
- Credentials &cred,
+ const Credentials &cred,
int commandId,
const Name &privateKeyName,
const Label & ownerLabel,
const HashAlgorithm hash,
const RSAPaddingAlgorithm padding)
{
- DBRow row;
- CryptoService cs;
+ DB::Row row;
RawBuffer signature;
+ CryptoAlgorithm cryptoAlg;
+ cryptoAlg.setParam(ParamName::SV_HASH_ALGO, hash);
+ cryptoAlg.setParam(ParamName::SV_RSA_PADDING, padding);
int retCode = CKM_API_SUCCESS;
try {
- do {
- retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
- if (CKM_API_SUCCESS != retCode) {
- LogError("getDataHelper return error");
- break;
- }
-
- KeyImpl keyParsed(row.data, Password());
- if (keyParsed.empty())
- retCode = CKM_API_ERROR_SERVER_ERROR;
- else
- retCode = cs.createSignature(keyParsed, message, hash, padding, signature);
- } while(0);
- } 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 DBCrypto::Exception::PermissionDenied &e) {
- LogError("DBCrypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_ACCESS_DENIED;
- } catch (const DBCrypto::Exception::Base &e) {
- LogError("DBCrypto failed with message: " << e.GetMessage());
+ 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 DB::Crypto::Exception::Base &e) {
+ LogError("DB::Crypto failed with message: " << e.GetMessage());
retCode = CKM_API_ERROR_DB_ERROR;
+ } catch (const Exc::Exception &e) {
+ retCode = e.error();
} catch (const CKM::Exception &e) {
LogError("Unknown CKM::Exception: " << e.GetMessage());
retCode = CKM_API_ERROR_SERVER_ERROR;
}
RawBuffer CKMLogic::verifySignature(
- Credentials &cred,
+ const Credentials &cred,
int commandId,
const Name &publicKeyOrCertName,
const Label & ownerLabel,
int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
try {
- do {
- CryptoService cs;
- DBRow row;
- KeyImpl key;
-
- retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
-
- if (retCode == CKM_API_SUCCESS) {
- key = KeyImpl(row.data);
- } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
- retCode = getDataHelper(cred, DBDataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
- if (retCode != CKM_API_SUCCESS)
- break;
- CertificateImpl cert(row.data, DataFormat::FORM_DER);
- key = cert.getKeyImpl();
- } else {
- break;
- }
-
- if (key.empty()) {
- retCode = CKM_API_ERROR_SERVER_ERROR;
- break;
- }
+ DB::Row row;
+
+ CryptoAlgorithm params;
+ params.setParam(ParamName::SV_HASH_ALGO, hash);
+ params.setParam(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);
+ }
- retCode = cs.verifySignature(key, message, signature, hash, padding);
- } while(0);
- } catch (const CryptoService::Exception::Crypto_internal &e) {
- LogError("KeyProvider failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const CryptoService::Exception::opensslError &e) {
- LogError("KeyProvider failed with message: " << 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::Base &e) {
- LogError("CryptoLogic failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_SERVER_ERROR;
- } catch (const DBCrypto::Exception::PermissionDenied &e) {
- LogError("DBCrypto failed with message: " << e.GetMessage());
- retCode = CKM_API_ERROR_ACCESS_DENIED;
- } catch (const DBCrypto::Exception::Base &e) {
- LogError("DBCrypto failed with message: " << e.GetMessage());
+ if (retCode == CKM_API_SUCCESS) {
+ retCode = m_decider.getStore(row).getKey(row)->verify(params, message, signature);
+ }
+ } catch (const Exc::Exception &e) {
+ retCode = e.error();
+ } catch (const DB::Crypto::Exception::Base &e) {
+ LogError("DB::Crypto failed with message: " << e.GetMessage());
retCode = CKM_API_ERROR_DB_ERROR;
} catch (const CKM::Exception &e) {
LogError("Unknown CKM::Exception: " << e.GetMessage());
return response.Pop();
}
-RawBuffer CKMLogic::allowAccess(
- Credentials &cred,
- int command,
- int msgID,
+int CKMLogic::setPermissionHelper(
+ const Credentials &cred, // who's the client
const Name &name,
- const Label &accessorLabel,
- const AccessRight reqRights)
+ const Label &label, // who's the owner
+ const Label &accessorLabel, // who will get the access
+ const PermissionMask permissionMask)
{
- int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
+ auto &handler = selectDatabase(cred, label);
- if (cred.smackLabel.empty()) {
- retCode = CKM_API_ERROR_INPUT_PARAM;
- } else if (0 < m_userDataMap.count(cred.uid) && !cred.smackLabel.empty()) {
- Try {
- retCode = m_userDataMap[cred.uid].database.setAccessRights(
- name,
- cred.smackLabel,
- accessorLabel,
- reqRights);
- } Catch (DBCrypto::Exception::InvalidArgs) {
- LogError("Error: invalid args!");
- retCode = CKM_API_ERROR_INPUT_PARAM;
- } Catch (DBCrypto::Exception::PermissionDenied) {
- LogError("Error: not enough permissions!");
- retCode = CKM_API_ERROR_ACCESS_DENIED;
- } Catch (CKM::Exception) {
- LogError("Error in set row!");
- retCode = CKM_API_ERROR_DB_ERROR;
- }
- } else {
- retCode = CKM_API_ERROR_DB_LOCKED;
+ // we don't know the client
+ if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ // use client label if not explicitly provided
+ const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
+
+ // verify name and label are correct
+ if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ // currently we don't support modification of owner's permissions to his own rows
+ if (ownerLabel==accessorLabel)
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ // system database does not support write/remove permissions
+ if ((0 == ownerLabel.compare(LABEL_SYSTEM_DB)) &&
+ (permissionMask & Permission::REMOVE))
+ 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;
+
+ DB::Crypto::Transaction transaction(&handler.database);
+
+ if( !handler.database.isNameLabelPresent(name, ownerLabel) )
+ return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+
+ // removing non-existing permissions: fail
+ if(permissionMask == Permission::NONE)
+ {
+ if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
+ return CKM_API_ERROR_INPUT_PARAM;
}
- return MessageBuffer::Serialize(command, msgID, retCode).Pop();
+ // set permissions to the row owned by ownerLabel for accessorLabel
+ handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
+ transaction.commit();
+
+ return CKM_API_SUCCESS;
}
-RawBuffer CKMLogic::denyAccess(
- Credentials &cred,
- int command,
- int msgID,
+RawBuffer CKMLogic::setPermission(
+ const Credentials &cred,
+ const int command,
+ const int msgID,
const Name &name,
- const Label &accessorLabel)
+ const Label &label,
+ const Label &accessorLabel,
+ const PermissionMask permissionMask)
{
- int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
-
- if (cred.smackLabel.empty()) {
- retCode = CKM_API_ERROR_INPUT_PARAM;
- } else if (0 < m_userDataMap.count(cred.uid)) {
- Try {
- retCode = m_userDataMap[cred.uid].database.clearAccessRights(name, cred.smackLabel, accessorLabel);
- } Catch (DBCrypto::Exception::PermissionDenied) {
- LogError("Error: not enough permissions!");
- retCode = CKM_API_ERROR_ACCESS_DENIED;
- } Catch (DBCrypto::Exception::InvalidArgs) {
- LogError("Error: permission not found!");
- retCode = CKM_API_ERROR_INPUT_PARAM;
- } Catch (CKM::Exception) {
- LogError("Error in deleting row!");
- retCode = CKM_API_ERROR_DB_ERROR;
- }
- } else {
- retCode = CKM_API_ERROR_DB_LOCKED;
+ int retCode;
+ Try {
+ retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
+ } catch (const Exc::Exception &e) {
+ retCode = e.error();
+ } Catch (CKM::Exception) {
+ LogError("Error in set row!");
+ retCode = CKM_API_ERROR_DB_ERROR;
}
return MessageBuffer::Serialize(command, msgID, retCode).Pop();