return true;
}
-// keypair data type, having private key data type and public key data type
-// private is assumed to be .first, public .second
-using DataTypePair = std::pair<CKM::DataType, CKM::DataType>;
-
-const std::map<CKM::AlgoType, DataTypePair> ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP = {
- { CKM::AlgoType::RSA_GEN, { CKM::DataType(CKM::KeyType::KEY_RSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_RSA_PUBLIC) } },
- { CKM::AlgoType::DSA_GEN, { CKM::DataType(CKM::KeyType::KEY_DSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_DSA_PUBLIC) } },
- { CKM::AlgoType::ECDSA_GEN, { CKM::DataType(CKM::KeyType::KEY_ECDSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_ECDSA_PUBLIC) } },
-};
-
} // anonymous namespace
namespace CKM {
if (input.type.isKey()) {
KeyShPtr output_key;
- if (input.type.isSKey())
+ if (input.type.isSymmetricKey())
output_key = CKM::Key::createAES(input.data);
else
output_key = CKM::Key::create(input.data);
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);
+ 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_SUCCESS;
}
-int verifyBinaryData(Crypto::Data &input)
+int verifyBinaryData(const Crypto::Data &input)
{
Crypto::Data dummy;
return toBinaryData(input, dummy);
return CKM_API_SUCCESS;
}
-int loadAppKey(UserData &handle, const ClientId &owner)
-{
- if (!handle.crypto.haveKey(owner)) {
- RawBuffer key;
- auto key_optional = handle.database.getKey(owner);
-
- if (!key_optional) {
- LogError("No key for given owner in database");
- return CKM_API_ERROR_DB_ERROR;
- }
-
- key = *key_optional;
- key = handle.keyProvider.getPureDEK(key);
- handle.crypto.pushKey(owner, key);
- }
-
- return CKM_API_SUCCESS;
-}
-
} // namespace
const uid_t CKMLogic::SYSTEM_DB_UID = 0;
}
UserData &CKMLogic::selectDatabase(const Credentials &cred,
- const ClientId &explicitOwner)
+ const ClientId &owner)
{
// if user trying to access system service - check:
// * if user database is unlocked [mandatory]
if (0 == m_userDataMap.count(cred.clientUid))
ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
- if (0 != explicitOwner.compare(CLIENT_ID_SYSTEM))
+ if (0 != owner.compare(CLIENT_ID_SYSTEM))
return m_userDataMap[cred.clientUid];
}
return SerializeMessage(retCode);
}
-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)
{
return SerializeMessage(tryRet([&] {
- return changeUserPasswordHelper(user, oldPassword, newPassword);
- }));
-}
-
-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;
-
- if (0 == m_userDataMap.count(user)) {
- // Check if key exists. If exists we must return error
- FileSystem fs(user);
- auto wrappedDKEKMain = fs.getDKEK();
+ // do not allow to change system database password
+ if (m_accessControl.isSystemService(user))
+ return CKM_API_ERROR_INPUT_PARAM;
- if (!wrappedDKEKMain.empty())
- retCode = CKM_API_ERROR_BAD_REQUEST;
- } else {
+ loadDKEKFile(user, oldPassword);
saveDKEKFile(user, newPassword);
- }
- return retCode;
+ return CKM_API_SUCCESS;
+ }));
}
RawBuffer CKMLogic::resetUserPassword(
const Password &newPassword)
{
return SerializeMessage(tryRet([&] {
- return resetUserPasswordHelper(user, 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;
+
+ 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::checkSaveConditions(
- const Credentials &accessorCred,
- UserData &handler,
- const Name &name,
- const ClientId &owner)
-{
- // verify name and client are correct
- if (!isNameValid(name) || !isClientValid(owner)) {
- LogDebug("Invalid parameter passed to key-manager");
- return CKM_API_ERROR_INPUT_PARAM;
- }
-
- // check if accessor is allowed to save owner's items
- int access_ec = m_accessControl.canSave(accessorCred, owner);
-
- if (access_ec != CKM_API_SUCCESS) {
- LogDebug("accessor " << accessorCred.client << " can not save rows owned by " <<
- owner);
- return access_ec;
- }
-
- // check if not a duplicate
- if (handler.database.isNameOwnerPresent(name, owner))
- return CKM_API_ERROR_DB_ALIAS_EXISTS;
-
- // encryption section
- if (!handler.crypto.haveKey(owner)) {
- RawBuffer got_key;
- auto key_optional = handler.database.getKey(owner);
-
- if (!key_optional) {
- LogDebug("No Key in database found. Generating new one for client: " <<
- owner);
- got_key = handler.keyProvider.generateDEK(owner);
- handler.database.saveKey(owner, got_key);
- } else {
- LogDebug("Key from DB");
- got_key = *key_optional;
- }
-
- got_key = handler.keyProvider.getPureDEK(got_key);
- handler.crypto.pushKey(owner, got_key);
- }
-
- return CKM_API_SUCCESS;
-}
-
-DB::Row CKMLogic::createEncryptedRow(
- CryptoLogic &crypto,
- const Name &name,
- const ClientId &owner,
- const Crypto::Data &data,
- const Policy &policy,
- const RawBuffer &hash)
-{
- 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(), hash);
- DB::Row row(std::move(token), name, owner,
- static_cast<int>(policy.extractable));
- crypto.encryptRow(row);
- return row;
-}
-
int CKMLogic::verifyAndSaveDataHelper(
const Credentials &cred,
const Name &name,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const Crypto::Data &data,
const PolicySerializable &policy)
{
// check if data is correct
Crypto::Data binaryData;
int retCode = toBinaryData(data, binaryData);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
- return retCode != CKM_API_SUCCESS
- ? retCode
- : saveDataHelper(cred, name, explicitOwner, binaryData, policy);
+ 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::getKeyForService(
const Credentials &cred,
const Name &name,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const Password &pass,
Crypto::GObjShPtr &key)
{
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, explicitOwner,
- pass, obj);
-
+ int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, owner, pass, obj);
if (retCode == CKM_API_SUCCESS)
key = std::move(obj);
const Credentials &cred,
int msgId,
const Name &name,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const Crypto::Data &data,
const PolicySerializable &policy)
{
- int retCode = verifyAndSaveDataHelper(cred, name, explicitOwner, data, policy);
+ int retCode = verifyAndSaveDataHelper(cred, name, owner, data, policy);
return SerializeMessage(msgId, retCode, data.type);
}
-int CKMLogic::extractPKCS12Data(
- CryptoLogic &crypto,
+RawBuffer CKMLogic::savePKCS12(
+ const Credentials &cred,
+ int msgId,
const Name &name,
const ClientId &owner,
const PKCS12Serializable &pkcs,
const PolicySerializable &keyPolicy,
- const PolicySerializable &certPolicy,
- DB::RowVector &output,
- const Credentials &cred)
+ const PolicySerializable &certPolicy)
{
- // private key is mandatory
- auto key = pkcs.getKey();
-
- if (!key) {
- LogError("Failed to get private key from pkcs");
- return CKM_API_ERROR_INVALID_FORMAT;
- }
-
- auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
- if (digest.empty())
- return CKM_API_ERROR_HASH_ERROR;
-
- Crypto::Data keyData(DataType(key->getType()), key->getDER());
- int retCode = verifyBinaryData(keyData);
+ return SerializeMessage(msgId, tryRet([&] {
+ auto [dbOp, retCode] = beginSave(cred, name, owner);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
- if (retCode != CKM_API_SUCCESS)
- return retCode;
+ // extract and encrypt the data
+ DB::RowVector encryptedRows;
- output.push_back(createEncryptedRow(crypto, name, owner, keyData,
- keyPolicy, digest));
+ auto import = [&](const Crypto::Data &data, const Policy& policy){
+ retCode = verifyBinaryData(data);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
- // certificate is mandatory
- auto cert = pkcs.getCertificate();
+ auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid, data.type);
+ if (digest.empty())
+ return CKM_API_ERROR_HASH_ERROR;
- if (!cert) {
- LogError("Failed to get certificate from pkcs");
- return CKM_API_ERROR_INVALID_FORMAT;
- }
+ Crypto::GStore &store = m_decider.getStore(data.type, policy);
- Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
- retCode = verifyBinaryData(certData);
+ // do not encrypt data with password during cc_mode on
+ Token token = store.import(data,
+ m_accessControl.isCCMode() ? "" : policy.password,
+ Crypto::EncryptionParams(), digest);
- if (retCode != CKM_API_SUCCESS)
- return retCode;
+ encryptedRows.push_back(dbOp.encryptOne(std::move(token), policy));
+ return CKM_API_SUCCESS;
+ };
- output.push_back(createEncryptedRow(crypto, name, owner, certData,
- certPolicy, digest));
+ // private key is mandatory
+ auto key = pkcs.getKey();
+ if (!key) {
+ LogError("Failed to get private key from pkcs");
+ return CKM_API_ERROR_INVALID_FORMAT;
+ }
- // CA cert chain
- unsigned int cert_index = 0;
+ Crypto::Data keyData(DataType(key->getType()), key->getDER());
+ retCode = import(keyData, keyPolicy);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
- for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
- Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++),
- ca->getDER());
- int retCode = verifyBinaryData(caCertData);
+ // 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;
- output.push_back(createEncryptedRow(crypto, name, owner, caCertData,
- certPolicy, digest));
- }
+ // 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;
+ }
- return CKM_API_SUCCESS;
-}
+ // save the data
+ dbOp.database().saveRows(name, owner, encryptedRows);
+ dbOp.transaction().commit();
-RawBuffer CKMLogic::savePKCS12(
- const Credentials &cred,
- int msgId,
- const Name &name,
- const ClientId &explicitOwner,
- const PKCS12Serializable &pkcs,
- const PolicySerializable &keyPolicy,
- const PolicySerializable &certPolicy)
-{
- return SerializeMessage(msgId, tryRet([&] {
- return saveDataHelper(cred, name, explicitOwner, pkcs, keyPolicy, certPolicy);
+ return CKM_API_SUCCESS;
}));
}
-
-int CKMLogic::removeDataHelper(
+RawBuffer CKMLogic::removeData(
const Credentials &cred,
+ int msgId,
const Name &name,
- const ClientId &explicitOwner)
+ const ClientId &owner)
{
- auto &handler = selectDatabase(cred, explicitOwner);
-
- // use client id if not explicitly provided
- const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
-
- if (!isNameValid(name) || !isClientValid(owner)) {
- LogDebug("Invalid owner 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, owner, cred.client);
- int retCode = m_accessControl.canDelete(cred,
- toPermissionMask(permissionRowOpt));
-
- if (retCode != CKM_API_SUCCESS) {
- LogWarning("access control check result: " << retCode);
- return retCode;
- }
-
- // get all matching rows
- DB::RowVector rows;
- handler.database.getRows(name, owner, DataType::DB_FIRST,
- DataType::DB_LAST, rows);
+ return SerializeMessage(msgId, tryRet([&] {
+ auto [dbOp, permission, retCode] = beginAndGetPerm(cred, name, owner);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
- if (rows.empty()) {
- LogDebug("No row for given name and owner");
- return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
- }
+ retCode = m_accessControl.canDelete(cred, permission);
+ if (retCode != CKM_API_SUCCESS) {
+ LogWarning("access control check result: " << retCode);
+ return retCode;
+ }
- // load app key if needed
- retCode = loadAppKey(handler, rows.front().owner);
+ // 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;
+ }
- if (CKM_API_SUCCESS != retCode)
- return retCode;
+ retCode = dbOp.loadAppKey();
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
- // destroy it in store
- for (auto &r : rows) {
- try {
- handler.crypto.decryptRow(Password(), r);
- m_decider.getStore(r).destroy(r);
- } catch (const Exc::AuthenticationFailed &) {
- LogDebug("Authentication failed when removing data. Ignored.");
+ // 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
- handler.database.deleteRow(name, owner);
- transaction.commit();
+ // delete row in db
+ dbOp.database().deleteRow(name, owner);
+ dbOp.transaction().commit();
- return CKM_API_SUCCESS;
-}
-
-RawBuffer CKMLogic::removeData(
- const Credentials &cred,
- int msgId,
- const Name &name,
- const ClientId &explicitOwner)
-{
- return SerializeMessage(msgId, tryRet([&] {
- return removeDataHelper(cred, name, explicitOwner);
+ return CKM_API_SUCCESS;
}));
}
int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred,
- const Name &name,
- const ClientId &owner,
const DB::Row &row,
bool exportFlag,
- DB::Crypto &database)
+ const PermissionMask& permission)
{
- PermissionMaskOptional permissionRowOpt =
- database.getPermissionRow(name, owner, accessorCred.client);
-
if (exportFlag)
- return m_accessControl.canExport(accessorCred,
- row,
- toPermissionMask(permissionRowOpt));
+ return m_accessControl.canExport(accessorCred, row, permission);
- return m_accessControl.canRead(accessorCred,
- toPermissionMask(permissionRowOpt));
+ return m_accessControl.canRead(accessorCred, permission);
}
-Crypto::GObjUPtr CKMLogic::rowToObject(
+void CKMLogic::decryptRow(
UserData &handler,
- DB::Row row,
+ DB::Row &row,
const Password &password,
const RawBuffer &hash)
{
- Crypto::GStore &store = m_decider.getStore(row);
-
- Password pass = m_accessControl.isCCMode() ? "" : password;
-
- // decrypt row
- Crypto::GObjUPtr obj;
-
if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
CryptoLogic::ENCRYPTION_V2) {
handler.crypto.decryptRow(Password(), row);
-
- obj = store.getObject(row, pass);
} 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);
-
- // get it from the store (it can be different than the data we imported into store)
- obj = store.getObject(token, pass);
+ 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))
- handler.crypto.encryptRow(row);
+ auto encryptedRow = handler.crypto.encryptRow(row);
// update it in db
- handler.database.updateRow(row);
+ handler.database.updateRow(encryptedRow);
}
+}
- return obj;
+Crypto::GObjUPtr CKMLogic::rowToObject(
+ UserData &handler,
+ DB::Row row,
+ const Password &password,
+ const RawBuffer &hash)
+{
+ decryptRow(handler, row, password, hash);
+
+ return decryptedRowToObj(row, password);
}
int CKMLogic::readDataHelper(
const Credentials &cred,
DataType dataType,
const Name &name,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const Password &password,
Crypto::GObjUPtrVector &objs)
{
- auto &handler = selectDatabase(cred, explicitOwner);
-
- // use client id if not explicitly provided
- const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
-
- if (!isNameValid(name) || !isClientValid(owner))
- return CKM_API_ERROR_INPUT_PARAM;
+ auto [dbOp, permission, retCode] = beginAndGetPerm(cred, name, owner);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
// read rows
- DB::Crypto::Transaction transaction(&handler.database);
DB::RowVector rows;
- int retCode = readMultiRow(name, owner, dataType, handler.database, rows);
-
+ retCode = readMultiRow(name, owner, dataType, dbOp.database(), rows);
if (CKM_API_SUCCESS != retCode)
return retCode;
DB::Row &firstRow = rows.at(0);
// check access rights
- retCode = checkDataPermissionsHelper(cred, name, owner, firstRow,
- exportFlag, handler.database);
-
+ retCode = checkDataPermissionsHelper(cred, firstRow, exportFlag, permission);
if (CKM_API_SUCCESS != retCode)
return retCode;
- // load app key if needed
- retCode = loadAppKey(handler, firstRow.owner);
+ // for multiple objects add type as hash input (see pkcs12)
+ bool multiple = rows.size() > 1;
- if (CKM_API_SUCCESS != retCode)
- return retCode;
+ RawBuffer digest;
- auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
- if (digest.empty())
- return CKM_API_ERROR_HASH_ERROR;
+ retCode = dbOp.loadAppKey();
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
// decrypt row
- for (auto &row : rows)
- objs.push_back(rowToObject(handler, std::move(row), password, digest));
+ 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
- transaction.commit();
+ dbOp.transaction().commit();
return CKM_API_SUCCESS;
}
const Credentials &cred,
DataType dataType,
const Name &name,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const Password &password,
Crypto::GObjUPtr &obj)
{
DataType objDataType;
- return readDataHelper(exportFlag, cred, dataType, name, explicitOwner,
+ return readDataHelper(exportFlag, cred, dataType, name, owner,
password, obj, objDataType);
}
-int CKMLogic::readDataHelper(
+int CKMLogic::readRowHelper(
bool exportFlag,
const Credentials &cred,
DataType dataType,
const Name &name,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const Password &password,
- Crypto::GObjUPtr &obj,
+ DB::Row &row,
DataType &objDataType)
{
- auto &handler = selectDatabase(cred, explicitOwner);
-
- // use client id if not explicitly provided
- const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
-
- if (!isNameValid(name) || !isClientValid(owner))
- return CKM_API_ERROR_INPUT_PARAM;
-
- // read row
- DB::Crypto::Transaction transaction(&handler.database);
- DB::Row row;
- int retCode = readSingleRow(name, owner, dataType, handler.database, row);
+ 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;
- objDataType = row.dataType;
-
- // check access rights
- retCode = checkDataPermissionsHelper(cred, name, owner, row, exportFlag,
- handler.database);
-
- if (CKM_API_SUCCESS != retCode)
+ retCode = dbOp.loadAppKey();
+ if (retCode != CKM_API_SUCCESS)
return retCode;
- // load app key if needed
- retCode = loadAppKey(handler, row.owner);
+ objDataType = row.dataType;
- if (CKM_API_SUCCESS != retCode)
+ // check access rights
+ retCode = checkDataPermissionsHelper(cred, row, exportFlag, permission);
+ if (retCode != CKM_API_SUCCESS)
return retCode;
auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
if (digest.empty())
return CKM_API_ERROR_HASH_ERROR;
- obj = rowToObject(handler, std::move(row), password, digest);
- // rowToObject may modify db
- transaction.commit();
+ decryptRow(dbOp.handler(), row, password, digest);
+
+ // decryptRow may modify db
+ dbOp.transaction().commit();
+
+ return CKM_API_SUCCESS;
+}
+
+Crypto::GObjUPtr CKMLogic::decryptedRowToObj(const DB::Row& row, const Password &password)
+{
+ 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 ClientId &owner,
+ const Password &password,
+ Crypto::GObjUPtr &obj,
+ DataType &objDataType)
+{
+ 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;
}
int msgId,
DataType dataType,
const Name &name,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const Password &password)
{
RawBuffer rowData;
int retCode = tryRet([&] {
Crypto::GObjUPtr obj;
- int retCode = readDataHelper(true, cred, dataType, name, explicitOwner,
- password, obj, objDataType);
+ int retCode2 = readDataHelper(true, cred, dataType, name, owner,
+ password, obj, objDataType);
- if (retCode == CKM_API_SUCCESS)
+ if (retCode2 == CKM_API_SUCCESS)
rowData = obj->getBinary();
- return retCode;
+ return retCode2;
});
if (CKM_API_SUCCESS != retCode)
int msgId,
DataType dataType,
const Name &name,
- const ClientId &explicitOwner)
+ const ClientId &owner)
{
bool status = false;
DataType objDataType;
int retCode = tryRet([&] {
Crypto::GObjUPtr obj;
- return readDataHelper(false, cred, dataType, name, explicitOwner, password, obj, objDataType);
+ return readDataHelper(false, cred, dataType, name, owner, password, obj, objDataType);
});
if (retCode == CKM_API_ERROR_AUTHENTICATION_FAILED) {
return SerializeMessage(msgId, retCode, objDataType, status);
}
-int CKMLogic::getPKCS12Helper(
- const Credentials &cred,
- const Name &name,
- const ClientId &explicitOwner,
- const Password &keyPassword,
- const Password &certPassword,
- KeyShPtr &privKey,
- CertificateShPtr &cert,
- CertificateShPtrVector &caChain)
-{
- int retCode;
-
- // read private key (mandatory)
- Crypto::GObjUPtr keyObj;
- retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
- keyPassword, keyObj);
-
- if (retCode != CKM_API_SUCCESS) {
- if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
- return retCode;
- } else {
- privKey = CKM::Key::create(keyObj->getBinary());
- }
-
- // read certificate (mandatory)
- Crypto::GObjUPtr certObj;
- retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, explicitOwner,
- certPassword, certObj);
-
- if (retCode != CKM_API_SUCCESS) {
- if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
- return retCode;
- } else {
- cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
- }
-
- // read CA cert chain (optional)
- Crypto::GObjUPtrVector caChainObjs;
- retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, explicitOwner,
- certPassword, caChainObjs);
-
- if (retCode != CKM_API_SUCCESS && retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
- if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
- return retCode;
- } 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)
- retCode = CKM_API_SUCCESS;
-
- return retCode;
-}
-
RawBuffer CKMLogic::getPKCS12(
const Credentials &cred,
int msgId,
const Name &name,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const Password &keyPassword,
const Password &certPassword)
{
KeyShPtr privKey;
CertificateShPtr cert;
CertificateShPtrVector caChain;
- int retCode = getPKCS12Helper(cred, name, explicitOwner, keyPassword,
- certPassword, privKey, cert, 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 (retCode == CKM_API_SUCCESS)
- output = PKCS12Serializable(std::move(privKey), std::move(cert), std::move(caChain));
+ if (retCode2 != CKM_API_SUCCESS)
+ return retCode2;
- return retCode;
+ 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,
- OwnerNameVector &ownerNameVector)
+int CKMLogic::getAliasInfoListHelper(const Credentials &cred,
+ const DataType dataType,
+ AliasInfoVector &aliasInfoVector)
{
int retCode = CKM_API_ERROR_DB_LOCKED;
auto &database = m_userDataMap[cred.clientUid].database;
retCode = tryRet<CKM_API_ERROR_DB_ERROR>([&] {
- OwnerNameVector tmpVector;
+ AliasInfoVector tmpVector;
if (dataType.isKey()) {
// list all key types
- database.listNames(cred.client,
+ database.listInfos(cred.client,
tmpVector,
DataType::DB_KEY_FIRST,
DataType::DB_KEY_LAST);
} else {
// list anything else
- database.listNames(cred.client,
- tmpVector,
- dataType);
+ database.listInfos(cred.client, tmpVector, dataType);
}
- ownerNameVector.insert(ownerNameVector.end(), tmpVector.begin(),
- tmpVector.end());
+ aliasInfoVector.insert(aliasInfoVector.end(), tmpVector.begin(), tmpVector.end());
return CKM_API_SUCCESS;
});
}
int msgId,
DataType dataType)
{
- OwnerNameVector systemVector;
- OwnerNameVector userVector;
- OwnerNameVector ownerNameVector;
+ AliasInfoVector systemVector;
+ AliasInfoVector userVector;
+ AliasInfoVector aliasInfoVector;
int retCode = unlockSystemDB();
// system database
if (m_accessControl.isSystemService(cred)) {
// lookup system DB
- retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
- CLIENT_ID_SYSTEM),
- dataType,
- systemVector);
+ retCode = getAliasInfoListHelper(Credentials(SYSTEM_DB_UID, CLIENT_ID_SYSTEM),
+ dataType,
+ systemVector);
} else {
// user - lookup system, then client DB
- retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
- cred.client),
- dataType,
- systemVector);
+ retCode = getAliasInfoListHelper(Credentials(SYSTEM_DB_UID, cred.client),
+ dataType,
+ systemVector);
// private database
if (retCode == CKM_API_SUCCESS) {
- retCode = getDataListHelper(cred,
- dataType,
- userVector);
+ retCode = getAliasInfoListHelper(cred,
+ dataType,
+ userVector);
}
}
}
if (retCode == CKM_API_SUCCESS) {
- ownerNameVector.insert(ownerNameVector.end(), systemVector.begin(),
+ aliasInfoVector.insert(aliasInfoVector.end(), systemVector.begin(),
systemVector.end());
- ownerNameVector.insert(ownerNameVector.end(), userVector.begin(),
+ aliasInfoVector.insert(aliasInfoVector.end(), userVector.begin(),
userVector.end());
}
- return SerializeMessage(msgId, retCode, dataType, ownerNameVector);
+ return SerializeMessage(msgId, retCode, dataType, AliasInfoSerializableVector(aliasInfoVector));
}
int CKMLogic::importInitialData(
}
// Inital values are always imported with root credentials. Client id is not important.
- Credentials rootCred(0, "");
- ClientId owner(CLIENT_ID_SYSTEM);
- auto &handler = selectDatabase(rootCred, CLIENT_ID_SYSTEM);
+ Credentials rootCred(0, "whatever");
+ ClientId owner(CLIENT_ID_SYSTEM);
- // check if save is possible
- DB::Crypto::Transaction transaction(&handler.database);
- int retCode = checkSaveConditions(rootCred, handler, name, 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,
- !encParams.iv.empty());
+ Crypto::GStore &store = m_decider.getStore(data.type, policy, true, !encParams.iv.empty());
Token token;
-
- auto digest = CryptoLogic::makeHash(name, owner, rootCred.clientUid);
- if (digest.empty())
- return CKM_API_ERROR_HASH_ERROR;
-
if (encParams.iv.empty()) {
// Data are not encrypted, let's try to verify them
Crypto::Data binaryData;
encParams, digest);
}
- DB::Row row(std::move(token), name, CLIENT_ID_SYSTEM,
- static_cast<int>(policy.extractable));
- handler.crypto.encryptRow(row);
-
- handler.database.saveRow(row);
- transaction.commit();
+ dbOp.finalize(std::move(token), policy);
return CKM_API_SUCCESS;
});
}
}
-int CKMLogic::saveDataHelper(
- const Credentials &cred,
- const Name &name,
- const ClientId &explicitOwner,
- const Crypto::Data &data,
- const PolicySerializable &policy)
+int CKMLogic::DBOperation::loadAppKey(bool keyRequired)
{
- auto &handler = selectDatabase(cred, explicitOwner);
-
- // use client id if not explicitly provided
- const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
-
- // check if save is possible
- DB::Crypto::Transaction transaction(&handler.database);
- int retCode = checkSaveConditions(cred, handler, name, owner);
- if (retCode != CKM_API_SUCCESS)
- return retCode;
-
- auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
- if (digest.empty())
- return CKM_API_ERROR_HASH_ERROR;
+ 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;
+ }
- // save the data
- DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, owner,
- data, policy, digest);
- handler.database.saveRow(encryptedRow);
+ m_handler.crypto.pushKey(m_owner, m_handler.keyProvider.getPureDEK(wrappedDEK));
+ }
- transaction.commit();
return CKM_API_SUCCESS;
}
-int CKMLogic::saveDataHelper(
+std::tuple<CKMLogic::DBOperation, int> CKMLogic::begin(
const Credentials &cred,
const Name &name,
- const ClientId &explicitOwner,
- const PKCS12Serializable &pkcs,
- const PolicySerializable &keyPolicy,
- const PolicySerializable &certPolicy)
+ const ClientId &owner)
{
- auto &handler = selectDatabase(cred, explicitOwner);
-
- // use client id if not explicitly provided
- const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
+ auto &handler = selectDatabase(cred, owner);
+ DBOperation op(handler, name, owner);
- // check if save is possible
- DB::Crypto::Transaction transaction(&handler.database);
- int retCode = checkSaveConditions(cred, handler, name, owner);
- if (retCode != CKM_API_SUCCESS)
- return retCode;
-
- // extract and encrypt the data
- DB::RowVector encryptedRows;
- retCode = extractPKCS12Data(handler.crypto, name, owner, pkcs, keyPolicy,
- certPolicy, encryptedRows, cred);
-
- if (retCode != CKM_API_SUCCESS)
- return retCode;
+ if (cred.client.empty() || !isClientValid(cred.client) ||
+ !isNameValid(name) || !isClientValid(owner))
+ return std::make_tuple(std::move(op), CKM_API_ERROR_INPUT_PARAM);
- // save the data
- handler.database.saveRows(name, owner, encryptedRows);
- transaction.commit();
-
- return CKM_API_SUCCESS;
+ return std::make_tuple(std::move(op), CKM_API_SUCCESS);
}
-
-int CKMLogic::createKeyAESHelper(
+std::tuple<CKMLogic::DBOperation, PermissionMask, int> CKMLogic::beginAndGetPerm(
const Credentials &cred,
- const int size,
const Name &name,
- const ClientId &explicitOwner,
- const PolicySerializable &policy)
+ const ClientId &owner)
{
- auto &handler = selectDatabase(cred, explicitOwner);
+ 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));
- // use client id if not explicitly provided
- const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
+ return std::make_tuple(std::move(dbOp), permission, retCode);
+}
- // check if save is possible
- DB::Crypto::Transaction transaction(&handler.database);
- int retCode = checkSaveConditions(cred, handler, name, owner);
+std::tuple<CKMLogic::DBOperation, int> CKMLogic::beginSave(
+ const Credentials &cred,
+ const Name &name,
+ const ClientId &owner)
+{
+ auto [dbOp, retCode] = begin(cred, name, owner);
if (retCode != CKM_API_SUCCESS)
- return retCode;
-
- auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
- if (digest.empty())
- return CKM_API_ERROR_HASH_ERROR;
+ return std::make_tuple(std::move(dbOp), retCode);
- // create key in store
- CryptoAlgorithm keyGenAlgorithm;
- keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
- keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
- Token key = m_decider.getStore(DataType::KEY_AES,
- policy).generateSKey(keyGenAlgorithm, policy.password, digest);
+ retCode = dbOp.loadAppKey(false);
+ if (retCode != CKM_API_SUCCESS)
+ return std::make_tuple(std::move(dbOp), retCode);
- // save the data
- DB::Row row(std::move(key), name, owner,
- static_cast<int>(policy.extractable));
- handler.crypto.encryptRow(row);
+ // 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);
+ }
- handler.database.saveRow(row);
+ if (dbOp.database().isNameOwnerPresent(name, owner))
+ retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
- transaction.commit();
- return CKM_API_SUCCESS;
+ return std::make_tuple(std::move(dbOp), retCode);
}
-int CKMLogic::createKeyPairHelper(
+std::tuple<CKMLogic::DBOperation, RawBuffer, int> CKMLogic::beginSaveAndGetHash(
const Credentials &cred,
- const CryptoAlgorithmSerializable &keyGenParams,
- const Name &namePrivate,
- const ClientId &explicitOwnerPrivate,
- const Name &namePublic,
- const ClientId &explicitOwnerPublic,
- const PolicySerializable &policyPrivate,
- const PolicySerializable &policyPublic)
+ const Name &name,
+ const ClientId &owner)
{
- auto &handlerPriv = selectDatabase(cred, explicitOwnerPrivate);
- auto &handlerPub = selectDatabase(cred, explicitOwnerPublic);
-
- AlgoType keyType = AlgoType::RSA_GEN;
-
- if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
- ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
-
- const auto dtIt = ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.find(keyType);
- if (dtIt == ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.end())
- ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
- const DataTypePair& dt = dtIt->second;
-
- if (policyPrivate.backend != policyPublic.backend)
- ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend.");
-
- // use client id if not explicitly provided
- const ClientId &ownerPrv = explicitOwnerPrivate.empty() ? cred.client :
- explicitOwnerPrivate;
-
- const ClientId &ownerPub = explicitOwnerPublic.empty() ? cred.client :
- explicitOwnerPublic;
-
- bool exportable = policyPrivate.extractable || policyPublic.extractable;
- Policy lessRestricted(Password(), exportable, policyPrivate.backend);
-
- auto digestPriv = CryptoLogic::makeHash(namePrivate, ownerPrv, cred.clientUid);
- if (digestPriv.empty())
- return CKM_API_ERROR_HASH_ERROR;
-
- auto digestPub = CryptoLogic::makeHash(namePublic, ownerPub, cred.clientUid);
- if (digestPub.empty())
- return CKM_API_ERROR_HASH_ERROR;
-
- TokenPair keys = m_decider.getStore(policyPrivate, dt.first, dt.second).generateAKey(keyGenParams,
- policyPrivate.password,
- policyPublic.password,
- digestPriv, digestPub);
-
- 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;
- retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerPrv);
- if (CKM_API_SUCCESS != retCode)
- return retCode;
-
- retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerPub);
- if (CKM_API_SUCCESS != retCode)
- return retCode;
-
- // save the data
- DB::Row rowPrv(std::move(keys.first), namePrivate, ownerPrv,
- static_cast<int>(policyPrivate.extractable));
- handlerPriv.crypto.encryptRow(rowPrv);
- handlerPriv.database.saveRow(rowPrv);
-
- DB::Row rowPub(std::move(keys.second), namePublic, ownerPub,
- static_cast<int>(policyPublic.extractable));
- handlerPub.crypto.encryptRow(rowPub);
- handlerPub.database.saveRow(rowPub);
+ 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;
+ }
- transactionPub.commit();
- transactionPriv.commit();
- return CKM_API_SUCCESS;
+ return std::make_tuple(std::move(dbOp), std::move(digest), retCode);
}
RawBuffer CKMLogic::createKeyPair(
const Credentials &cred,
int msgId,
const CryptoAlgorithmSerializable &keyGenParams,
- const Name &namePrivate,
- const ClientId &explicitOwnerPrivate,
- const Name &namePublic,
- const ClientId &explicitOwnerPublic,
- const PolicySerializable &policyPrivate,
- const PolicySerializable &policyPublic)
+ const Name &namePrv,
+ const ClientId &ownerPrv,
+ const Name &namePub,
+ const ClientId &ownerPub,
+ const PolicySerializable &policyPrv,
+ const PolicySerializable &policyPub)
{
return SerializeMessage(msgId, tryRet([&] {
- return createKeyPairHelper(cred, keyGenParams, namePrivate, explicitOwnerPrivate,
- namePublic, explicitOwnerPublic, policyPrivate, policyPublic);
+ 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;
}));
}
int msgId,
const int size,
const Name &name,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const PolicySerializable &policy)
{
int retCode = CKM_API_SUCCESS;
try {
retCode = tryRet([&] {
- return createKeyAESHelper(cred, size, name, explicitOwner, policy);
+ 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());
cred,
DataType::CERTIFICATE,
i.second,
- i.first,
+ cred.effectiveOwner(i.first),
Password(),
obj);
cred,
DataType::DB_CHAIN_FIRST,
i.second,
- i.first,
+ cred.effectiveOwner(i.first),
CKM::Password(),
caChainObjs);
const Credentials &cred,
int msgId,
const Name &privateKeyName,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const Password &password, // password for private_key
const RawBuffer &message,
const CryptoAlgorithm &cryptoAlg)
try {
retCode = tryRet([&] {
Crypto::GObjUPtr obj;
- int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
- explicitOwner, password, obj);
+ int retCode2 = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
+ owner, password, obj);
- if (retCode == CKM_API_SUCCESS)
+ if (retCode2 == CKM_API_SUCCESS)
signature = obj->sign(cryptoAlg, message);
- return retCode;
+ return retCode2;
});
} catch (const std::exception &e) {
LogError("STD exception " << e.what());
const Credentials &cred,
int msgId,
const Name &publicKeyOrCertName,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const Password &password, // password for public_key (optional)
const RawBuffer &message,
const RawBuffer &signature,
// rather than private key from the same PKCS.
Crypto::GObjUPtr obj;
int retCode = readDataHelper(false, cred, DataType::CERTIFICATE,
- publicKeyOrCertName, explicitOwner, password, obj);
+ publicKeyOrCertName, owner, password, obj);
if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
- publicKeyOrCertName, explicitOwner, password, obj);
+ publicKeyOrCertName, owner, password, obj);
if (retCode == CKM_API_SUCCESS)
retCode = obj->verify(params, message, signature);
int CKMLogic::setPermissionHelper(
const Credentials &cred, // who's the client
const Name &name,
- const ClientId &explicitOwner, // who's the owner
+ const ClientId &owner, // who's the owner
const ClientId &accessor, // who will get the access
const PermissionMask permissionMask)
{
- auto &handler = selectDatabase(cred, explicitOwner);
-
- // we don't know the client
- if (cred.client.empty() || !isClientValid(cred.client))
- return CKM_API_ERROR_INPUT_PARAM;
-
- // use client id if not explicitly provided
- const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
-
- // verify name and owner are correct
- if (!isNameValid(name) || !isClientValid(owner) ||
- !isClientValid(accessor))
- return CKM_API_ERROR_INPUT_PARAM;
+ 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))
+ if ((0 == owner.compare(CLIENT_ID_SYSTEM)) && (permissionMask & Permission::REMOVE))
return CKM_API_ERROR_INPUT_PARAM;
- // can the client modify permissions to owner's row?
- int retCode = m_accessControl.canModify(cred, owner);
-
- if (retCode != CKM_API_SUCCESS)
- return retCode;
-
- DB::Crypto::Transaction transaction(&handler.database);
-
- if (!handler.database.isNameOwnerPresent(name, owner))
- return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
-
// set permissions to the row owned by owner for accessor
- handler.database.setPermission(name, owner, accessor, permissionMask);
- transaction.commit();
+ dbOp.database().setPermission(name, owner, accessor, permissionMask);
+ dbOp.transaction().commit();
return CKM_API_SUCCESS;
}
const Credentials &cred,
const int msgID,
const Name &name,
- const ClientId &explicitOwner,
+ const ClientId &owner,
const ClientId &accessor,
const PermissionMask permissionMask)
{
return SerializeMessage(msgID, tryRet([&] {
- return setPermissionHelper(cred, name, explicitOwner, accessor, permissionMask);
+ return setPermissionHelper(cred, name, owner, accessor, permissionMask);
}));
}
-} // namespace CKM
+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;
+ }));
+}
+
+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;
+
+ retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, wrappingKeyName,
+ wrappingKeyOwner, wrappingKeyPassword, wrappingKey);
+ if (retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ 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;
+ }
+ Token token = wrappingKey->unwrap(params,
+ Crypto::Data(keyType, std::move(wrappedKey)),
+ policy.password,
+ digest);
+
+ dbOp.finalize(std::move(token), policy);
+
+ 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;
+
+ auto retCode = tryRet([&] {
+ auto retCode2 = readDataHelper(false, cred, DataType::DB_KEY_FIRST, wrappingKeyName,
+ wrappingKeyOwner, wrappingKeyPassword, wrappingKey);
+ if (retCode2 != CKM_API_SUCCESS)
+ return retCode2;
+
+ retCode2 = readRowHelper(false, cred, DataType::DB_KEY_FIRST, keyName,
+ keyOwner, keyPassword, wrappedKeyRow, wrappedKeyType);
+ if (retCode2 != CKM_API_SUCCESS)
+ return retCode2;
+
+ wrappedKey = wrappingKey->wrap(params, wrappedKeyRow, keyPassword);
+
+ return retCode2;
+ });
+
+ return SerializeMessage(msgID, retCode, wrappedKeyType, wrappedKey);
+}
+
+RawBuffer CKMLogic::getBackendInfo(const int msgID, BackendId backend)
+{
+ 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