2 * Copyright (c) 2014-2021 Samsung Electronics Co., Ltd. All rights reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
18 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
20 * @brief Sample service implementation.
22 #include <dpl/serialization.h>
23 #include <dpl/log/log.h>
24 #include <ckm/ckm-error.h>
25 #include <ckm/ckm-type.h>
26 #include <key-provider.h>
27 #include <file-system.h>
28 #include <ckm-logic.h>
30 #include <key-aes-impl.h>
31 #include <certificate-config.h>
32 #include <certificate-store.h>
34 #include <sw-backend/store.h>
35 #include <generic-backend/exception.h>
36 #include <ss-migrate.h>
39 const char *const CERT_SYSTEM_DIR = CA_CERTS_DIR;
40 const char *const DEFAULT_UNLOCK_STRING = "cAtRugU7";
42 bool isClientValid(const CKM::ClientId &client)
44 if (client.find(CKM::ALIAS_SEPARATOR) != CKM::ClientId::npos)
50 bool isNameValid(const CKM::Name &name)
52 if (name.find(CKM::ALIAS_SEPARATOR) != CKM::Name::npos)
58 // keypair data type, having private key data type and public key data type
59 // private is assumed to be .first, public .second
60 using DataTypePair = std::pair<CKM::DataType, CKM::DataType>;
62 const std::map<CKM::AlgoType, DataTypePair> ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP = {
63 { CKM::AlgoType::RSA_GEN, { CKM::DataType(CKM::KeyType::KEY_RSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_RSA_PUBLIC) } },
64 { CKM::AlgoType::DSA_GEN, { CKM::DataType(CKM::KeyType::KEY_DSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_DSA_PUBLIC) } },
65 { CKM::AlgoType::ECDSA_GEN, { CKM::DataType(CKM::KeyType::KEY_ECDSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_ECDSA_PUBLIC) } },
68 } // anonymous namespace
74 template <int ERROR_ON_CKM_EXCEPTION = CKM_API_ERROR_SERVER_ERROR, class F>
78 static_assert(std::is_same_v<decltype(std::forward<F>(f)()), int>);
79 return std::forward<F>(f)();
80 } catch (const Exc::Exception &e) {
82 } catch (const CKM::Exception &e) {
83 LogError("CKM::Exception: " << e.GetMessage());
84 return ERROR_ON_CKM_EXCEPTION;
88 int toBinaryData(const Crypto::Data &input, Crypto::Data &output)
90 // verify the data integrity
91 if (input.type.isKey()) {
94 if (input.type.isSKey())
95 output_key = CKM::Key::createAES(input.data);
97 output_key = CKM::Key::create(input.data);
99 if (output_key.get() == NULL) {
100 LogDebug("provided binary data is not valid key data");
101 return CKM_API_ERROR_INPUT_PARAM;
104 output = Crypto::Data(input.type, output_key->getDER());
105 } else if (input.type.isCertificate() || input.type.isChainCert()) {
106 CertificateShPtr cert = CKM::Certificate::create(input.data,
107 DataFormat::FORM_DER);
109 if (cert.get() == NULL) {
110 LogDebug("provided binary data is not valid certificate data");
111 return CKM_API_ERROR_INPUT_PARAM;
114 output = Crypto::Data(input.type, cert->getDER());
119 // TODO: add here BINARY_DATA verification, i.e: max size etc.
120 return CKM_API_SUCCESS;
123 int verifyBinaryData(Crypto::Data &input)
126 return toBinaryData(input, dummy);
129 int readSingleRow(const Name &name,
130 const ClientId &owner,
132 DB::Crypto &database,
135 DB::Crypto::RowOptional row_optional;
137 if (dataType.isKey()) {
138 // read all key types
139 row_optional = database.getRow(name,
141 DataType::DB_KEY_FIRST,
142 DataType::DB_KEY_LAST);
144 // read anything else
145 row_optional = database.getRow(name,
151 LogDebug("No row for given name, owner and type");
152 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
157 return CKM_API_SUCCESS;
160 int readMultiRow(const Name &name,
161 const ClientId &owner,
163 DB::Crypto &database,
164 DB::RowVector &output)
166 if (dataType.isKey())
167 // read all key types
168 database.getRows(name,
170 DataType::DB_KEY_FIRST,
171 DataType::DB_KEY_LAST,
173 else if (dataType.isChainCert())
174 // read all key types
175 database.getRows(name,
177 DataType::DB_CHAIN_FIRST,
178 DataType::DB_CHAIN_LAST,
181 // read anything else
182 database.getRows(name,
187 if (!output.size()) {
188 LogDebug("No row for given name, owner and type");
189 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
192 return CKM_API_SUCCESS;
195 int loadAppKey(UserData &handle, const ClientId &owner)
197 if (!handle.crypto.haveKey(owner)) {
199 auto key_optional = handle.database.getKey(owner);
202 LogError("No key for given owner in database");
203 return CKM_API_ERROR_DB_ERROR;
207 key = handle.keyProvider.getPureDEK(key);
208 handle.crypto.pushKey(owner, key);
211 return CKM_API_SUCCESS;
216 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
217 const uid_t CKMLogic::ADMIN_USER_DB_UID = 5001;
221 CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
223 m_accessControl.updateCCMode();
226 CKMLogic::~CKMLogic() {}
228 void CKMLogic::loadDKEKFile(uid_t user, const Password &password)
230 auto &handle = m_userDataMap[user];
234 auto wrappedDKEK = fs.getDKEK();
236 if (wrappedDKEK.empty()) {
237 wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
238 fs.saveDKEK(wrappedDKEK);
241 handle.keyProvider = KeyProvider(wrappedDKEK, password);
242 if (!handle.keyProvider.isInitialized()) {
243 handle.keyProvider.migrateDKEK(wrappedDKEK, password);
244 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
245 LogInfo("DKEK migrated");
249 void CKMLogic::saveDKEKFile(uid_t user, const Password &password)
251 auto &handle = m_userDataMap[user];
254 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
257 void CKMLogic::migrateSecureStorageData(bool isAdminUser)
259 SsMigration::migrate(isAdminUser, [this](const std::string &name,
260 const Crypto::Data &data,
261 bool adminUserFlag) {
262 LogInfo("Migrate data called with name: " << name);
263 auto ownerId = adminUserFlag ? CLIENT_ID_ADMIN_USER : CLIENT_ID_SYSTEM;
264 auto uid = adminUserFlag ? ADMIN_USER_DB_UID : SYSTEM_DB_UID;
266 int ret = verifyAndSaveDataHelper(Credentials(uid, ownerId), name, ownerId, data,
267 PolicySerializable());
269 if (ret == CKM_API_ERROR_DB_ALIAS_EXISTS)
270 LogWarning("Alias already exist for migrated name: " << name);
271 else if (ret != CKM_API_SUCCESS)
272 LogError("Failed to migrate secure-storage data. name: " << name <<
277 int CKMLogic::unlockDatabase(uid_t user, const Password &password)
279 if (0 < m_userDataMap.count(user) &&
280 m_userDataMap[user].keyProvider.isInitialized())
281 return CKM_API_SUCCESS;
283 int retCode = tryRet([&] {
284 auto &handle = m_userDataMap[user];
287 loadDKEKFile(user, password);
289 auto wrappedDatabaseDEK = fs.getDBDEK();
291 if (wrappedDatabaseDEK.empty()) {
292 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
293 fs.saveDBDEK(wrappedDatabaseDEK);
296 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
298 handle.database = DB::Crypto(fs.getLegacyDBPath(), fs.getDBPath(), key);
299 handle.crypto = CryptoLogic();
301 if (!m_accessControl.isSystemService(user)) {
302 // remove data of removed apps during locked state
303 ClientIdVector removedApps = fs.clearRemovedsApps();
305 for (auto &app : removedApps) {
306 handle.crypto.removeKey(app);
307 handle.database.deleteKey(app);
311 if (user == SYSTEM_DB_UID && SsMigration::hasData())
312 migrateSecureStorageData(false);
313 else if (user == ADMIN_USER_DB_UID && SsMigration::hasData())
314 migrateSecureStorageData(true);
316 return CKM_API_SUCCESS;
319 if (CKM_API_SUCCESS != retCode)
320 m_userDataMap.erase(user);
325 int CKMLogic::unlockSystemDB()
327 return unlockDatabase(SYSTEM_DB_UID, DEFAULT_UNLOCK_STRING);
330 UserData &CKMLogic::selectDatabase(const Credentials &cred,
331 const ClientId &explicitOwner)
333 // if user trying to access system service - check:
334 // * if user database is unlocked [mandatory]
335 // * if not - proceed with regular user database
336 // * if explicit system database owner given -> switch to system DB
337 if (!m_accessControl.isSystemService(cred)) {
338 if (0 == m_userDataMap.count(cred.clientUid))
339 ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
341 if (0 != explicitOwner.compare(CLIENT_ID_SYSTEM))
342 return m_userDataMap[cred.clientUid];
345 // system database selected, modify the owner id
346 if (CKM_API_SUCCESS != unlockSystemDB())
347 ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
349 return m_userDataMap[SYSTEM_DB_UID];
352 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
354 int retCode = CKM_API_SUCCESS;
356 if (!m_accessControl.isSystemService(user))
357 retCode = unlockDatabase(user, password);
358 else // do not allow lock/unlock operations for system users
359 retCode = CKM_API_ERROR_INPUT_PARAM;
361 return SerializeMessage(retCode);
364 RawBuffer CKMLogic::updateCCMode()
366 m_accessControl.updateCCMode();
367 return SerializeMessage(CKM_API_SUCCESS);
370 RawBuffer CKMLogic::lockUserKey(uid_t user)
372 int retCode = CKM_API_SUCCESS;
374 if (!m_accessControl.isSystemService(user))
375 m_userDataMap.erase(user);
376 else // do not allow lock/unlock operations for system users
377 retCode = CKM_API_ERROR_INPUT_PARAM;
379 return SerializeMessage(retCode);
382 RawBuffer CKMLogic::removeUserData(uid_t user)
384 if (m_accessControl.isSystemService(user))
385 user = SYSTEM_DB_UID;
387 m_userDataMap.erase(user);
389 const int retCode = FileSystem(user).removeUserData()
390 ? CKM_API_ERROR_FILE_SYSTEM
393 return SerializeMessage(retCode);
396 int CKMLogic::changeUserPasswordHelper(uid_t user,
397 const Password &oldPassword,
398 const Password &newPassword)
400 // do not allow to change system database password
401 if (m_accessControl.isSystemService(user))
402 return CKM_API_ERROR_INPUT_PARAM;
404 loadDKEKFile(user, oldPassword);
405 saveDKEKFile(user, newPassword);
407 return CKM_API_SUCCESS;
410 RawBuffer CKMLogic::changeUserPassword(
412 const Password &oldPassword,
413 const Password &newPassword)
415 return SerializeMessage(tryRet([&] {
416 return changeUserPasswordHelper(user, oldPassword, newPassword);
420 int CKMLogic::resetUserPasswordHelper(
422 const Password &newPassword)
424 // do not allow to reset system database password
425 if (m_accessControl.isSystemService(user))
426 return CKM_API_ERROR_INPUT_PARAM;
428 int retCode = CKM_API_SUCCESS;
430 if (0 == m_userDataMap.count(user)) {
431 // Check if key exists. If exists we must return error
433 auto wrappedDKEKMain = fs.getDKEK();
435 if (!wrappedDKEKMain.empty())
436 retCode = CKM_API_ERROR_BAD_REQUEST;
438 saveDKEKFile(user, newPassword);
444 RawBuffer CKMLogic::resetUserPassword(
446 const Password &newPassword)
448 return SerializeMessage(tryRet([&] {
449 return resetUserPasswordHelper(user, newPassword);
453 RawBuffer CKMLogic::removeApplicationData(const ClientId &owner)
455 return SerializeMessage(tryRet([&] {
457 return CKM_API_ERROR_INPUT_PARAM;
459 UidVector uids = FileSystem::getUIDsFromDBFile();
461 for (auto userId : uids) {
462 if (0 == m_userDataMap.count(userId)) {
463 FileSystem fs(userId);
464 fs.addRemovedApp(owner);
466 auto &handle = m_userDataMap[userId];
467 handle.crypto.removeKey(owner);
468 handle.database.deleteKey(owner);
472 return CKM_API_SUCCESS;
476 int CKMLogic::checkSaveConditions(
477 const Credentials &accessorCred,
480 const ClientId &owner)
482 // verify name and client are correct
483 if (!isNameValid(name) || !isClientValid(owner)) {
484 LogDebug("Invalid parameter passed to key-manager");
485 return CKM_API_ERROR_INPUT_PARAM;
488 // check if accessor is allowed to save owner's items
489 int access_ec = m_accessControl.canSave(accessorCred, owner);
491 if (access_ec != CKM_API_SUCCESS) {
492 LogDebug("accessor " << accessorCred.client << " can not save rows owned by " <<
497 // check if not a duplicate
498 if (handler.database.isNameOwnerPresent(name, owner))
499 return CKM_API_ERROR_DB_ALIAS_EXISTS;
501 // encryption section
502 if (!handler.crypto.haveKey(owner)) {
504 auto key_optional = handler.database.getKey(owner);
507 LogDebug("No Key in database found. Generating new one for client: " <<
509 got_key = handler.keyProvider.generateDEK(owner);
510 handler.database.saveKey(owner, got_key);
512 LogDebug("Key from DB");
513 got_key = *key_optional;
516 got_key = handler.keyProvider.getPureDEK(got_key);
517 handler.crypto.pushKey(owner, got_key);
520 return CKM_API_SUCCESS;
523 DB::Row CKMLogic::createEncryptedRow(
526 const ClientId &owner,
527 const Crypto::Data &data,
528 const Policy &policy,
529 const RawBuffer &hash)
531 Crypto::GStore &store = m_decider.getStore(data.type, policy);
533 // do not encrypt data with password during cc_mode on
534 Token token = store.import(data,
535 m_accessControl.isCCMode() ? "" : policy.password,
536 Crypto::EncryptionParams(), hash);
537 DB::Row row(std::move(token), name, owner,
538 static_cast<int>(policy.extractable));
539 crypto.encryptRow(row);
543 int CKMLogic::verifyAndSaveDataHelper(
544 const Credentials &cred,
546 const ClientId &explicitOwner,
547 const Crypto::Data &data,
548 const PolicySerializable &policy)
551 // check if data is correct
552 Crypto::Data binaryData;
553 int retCode = toBinaryData(data, binaryData);
555 return retCode != CKM_API_SUCCESS
557 : saveDataHelper(cred, name, explicitOwner, binaryData, policy);
561 int CKMLogic::getKeyForService(
562 const Credentials &cred,
564 const ClientId &explicitOwner,
565 const Password &pass,
566 Crypto::GObjShPtr &key)
569 // Key is for internal service use. It won't be exported to the client
570 Crypto::GObjUPtr obj;
571 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
574 if (retCode == CKM_API_SUCCESS)
575 key = std::move(obj);
581 RawBuffer CKMLogic::saveData(
582 const Credentials &cred,
585 const ClientId &explicitOwner,
586 const Crypto::Data &data,
587 const PolicySerializable &policy)
589 int retCode = verifyAndSaveDataHelper(cred, name, explicitOwner, data, policy);
590 return SerializeMessage(msgId, retCode, data.type);
593 int CKMLogic::extractPKCS12Data(
596 const ClientId &owner,
597 const PKCS12Serializable &pkcs,
598 const PolicySerializable &keyPolicy,
599 const PolicySerializable &certPolicy,
600 DB::RowVector &output,
601 const Credentials &cred)
603 // private key is mandatory
604 auto key = pkcs.getKey();
607 LogError("Failed to get private key from pkcs");
608 return CKM_API_ERROR_INVALID_FORMAT;
611 auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
613 return CKM_API_ERROR_HASH_ERROR;
615 Crypto::Data keyData(DataType(key->getType()), key->getDER());
616 int retCode = verifyBinaryData(keyData);
618 if (retCode != CKM_API_SUCCESS)
621 output.push_back(createEncryptedRow(crypto, name, owner, keyData,
624 // certificate is mandatory
625 auto cert = pkcs.getCertificate();
628 LogError("Failed to get certificate from pkcs");
629 return CKM_API_ERROR_INVALID_FORMAT;
632 Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
633 retCode = verifyBinaryData(certData);
635 if (retCode != CKM_API_SUCCESS)
638 output.push_back(createEncryptedRow(crypto, name, owner, certData,
639 certPolicy, digest));
642 unsigned int cert_index = 0;
644 for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
645 Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++),
647 int retCode = verifyBinaryData(caCertData);
649 if (retCode != CKM_API_SUCCESS)
652 output.push_back(createEncryptedRow(crypto, name, owner, caCertData,
653 certPolicy, digest));
656 return CKM_API_SUCCESS;
659 RawBuffer CKMLogic::savePKCS12(
660 const Credentials &cred,
663 const ClientId &explicitOwner,
664 const PKCS12Serializable &pkcs,
665 const PolicySerializable &keyPolicy,
666 const PolicySerializable &certPolicy)
668 return SerializeMessage(msgId, tryRet([&] {
669 return saveDataHelper(cred, name, explicitOwner, pkcs, keyPolicy, certPolicy);
674 int CKMLogic::removeDataHelper(
675 const Credentials &cred,
677 const ClientId &explicitOwner)
679 auto &handler = selectDatabase(cred, explicitOwner);
681 // use client id if not explicitly provided
682 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
684 if (!isNameValid(name) || !isClientValid(owner)) {
685 LogDebug("Invalid owner or name format");
686 return CKM_API_ERROR_INPUT_PARAM;
689 DB::Crypto::Transaction transaction(&handler.database);
691 // read and check permissions
692 PermissionMaskOptional permissionRowOpt =
693 handler.database.getPermissionRow(name, owner, cred.client);
694 int retCode = m_accessControl.canDelete(cred,
695 toPermissionMask(permissionRowOpt));
697 if (retCode != CKM_API_SUCCESS) {
698 LogWarning("access control check result: " << retCode);
702 // get all matching rows
704 handler.database.getRows(name, owner, DataType::DB_FIRST,
705 DataType::DB_LAST, rows);
708 LogDebug("No row for given name and owner");
709 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
712 // load app key if needed
713 retCode = loadAppKey(handler, rows.front().owner);
715 if (CKM_API_SUCCESS != retCode)
718 // destroy it in store
719 for (auto &r : rows) {
721 handler.crypto.decryptRow(Password(), r);
722 m_decider.getStore(r).destroy(r);
723 } catch (const Exc::AuthenticationFailed &) {
724 LogDebug("Authentication failed when removing data. Ignored.");
729 handler.database.deleteRow(name, owner);
730 transaction.commit();
732 return CKM_API_SUCCESS;
735 RawBuffer CKMLogic::removeData(
736 const Credentials &cred,
739 const ClientId &explicitOwner)
741 return SerializeMessage(msgId, tryRet([&] {
742 return removeDataHelper(cred, name, explicitOwner);
747 int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred,
749 const ClientId &owner,
752 DB::Crypto &database)
754 PermissionMaskOptional permissionRowOpt =
755 database.getPermissionRow(name, owner, accessorCred.client);
758 return m_accessControl.canExport(accessorCred,
760 toPermissionMask(permissionRowOpt));
762 return m_accessControl.canRead(accessorCred,
763 toPermissionMask(permissionRowOpt));
766 Crypto::GObjUPtr CKMLogic::rowToObject(
769 const Password &password,
770 const RawBuffer &hash)
772 Crypto::GStore &store = m_decider.getStore(row);
774 Password pass = m_accessControl.isCCMode() ? "" : password;
777 Crypto::GObjUPtr obj;
779 if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
780 CryptoLogic::ENCRYPTION_V2) {
781 handler.crypto.decryptRow(Password(), row);
783 obj = store.getObject(row, pass);
785 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
786 handler.crypto.decryptRow(pass, row);
787 // destroy it in store
790 // import it to store with new scheme: data -> pass(data)
791 Token token = store.import(Crypto::Data(row.dataType, row.data), pass, Crypto::EncryptionParams(), hash);
793 // get it from the store (it can be different than the data we imported into store)
794 obj = store.getObject(token, pass);
796 // update row with new token
797 *static_cast<Token *>(&row) = std::move(token);
799 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
800 handler.crypto.encryptRow(row);
803 handler.database.updateRow(row);
809 int CKMLogic::readDataHelper(
811 const Credentials &cred,
814 const ClientId &explicitOwner,
815 const Password &password,
816 Crypto::GObjUPtrVector &objs)
818 auto &handler = selectDatabase(cred, explicitOwner);
820 // use client id if not explicitly provided
821 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
823 if (!isNameValid(name) || !isClientValid(owner))
824 return CKM_API_ERROR_INPUT_PARAM;
827 DB::Crypto::Transaction transaction(&handler.database);
829 int retCode = readMultiRow(name, owner, dataType, handler.database, rows);
831 if (CKM_API_SUCCESS != retCode)
834 // all read rows belong to the same owner
835 DB::Row &firstRow = rows.at(0);
837 // check access rights
838 retCode = checkDataPermissionsHelper(cred, name, owner, firstRow,
839 exportFlag, handler.database);
841 if (CKM_API_SUCCESS != retCode)
844 // load app key if needed
845 retCode = loadAppKey(handler, firstRow.owner);
847 if (CKM_API_SUCCESS != retCode)
850 auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
852 return CKM_API_ERROR_HASH_ERROR;
855 for (auto &row : rows)
856 objs.push_back(rowToObject(handler, std::move(row), password, digest));
858 // rowToObject may modify db
859 transaction.commit();
861 return CKM_API_SUCCESS;
864 int CKMLogic::readDataHelper(
866 const Credentials &cred,
869 const ClientId &explicitOwner,
870 const Password &password,
871 Crypto::GObjUPtr &obj)
873 DataType objDataType;
874 return readDataHelper(exportFlag, cred, dataType, name, explicitOwner,
875 password, obj, objDataType);
878 int CKMLogic::readDataHelper(
880 const Credentials &cred,
883 const ClientId &explicitOwner,
884 const Password &password,
885 Crypto::GObjUPtr &obj,
886 DataType &objDataType)
888 auto &handler = selectDatabase(cred, explicitOwner);
890 // use client id if not explicitly provided
891 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
893 if (!isNameValid(name) || !isClientValid(owner))
894 return CKM_API_ERROR_INPUT_PARAM;
897 DB::Crypto::Transaction transaction(&handler.database);
899 int retCode = readSingleRow(name, owner, dataType, handler.database, row);
901 if (CKM_API_SUCCESS != retCode)
904 objDataType = row.dataType;
906 // check access rights
907 retCode = checkDataPermissionsHelper(cred, name, owner, row, exportFlag,
910 if (CKM_API_SUCCESS != retCode)
913 // load app key if needed
914 retCode = loadAppKey(handler, row.owner);
916 if (CKM_API_SUCCESS != retCode)
919 auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
921 return CKM_API_ERROR_HASH_ERROR;
923 obj = rowToObject(handler, std::move(row), password, digest);
924 // rowToObject may modify db
925 transaction.commit();
927 return CKM_API_SUCCESS;
930 RawBuffer CKMLogic::getData(
931 const Credentials &cred,
935 const ClientId &explicitOwner,
936 const Password &password)
939 DataType objDataType;
941 int retCode = tryRet([&] {
942 Crypto::GObjUPtr obj;
943 int retCode = readDataHelper(true, cred, dataType, name, explicitOwner,
944 password, obj, objDataType);
946 if (retCode == CKM_API_SUCCESS)
947 rowData = obj->getBinary();
952 if (CKM_API_SUCCESS != retCode)
955 return SerializeMessage(msgId, retCode, objDataType, rowData);
958 RawBuffer CKMLogic::getDataProtectionStatus(
959 const Credentials &cred,
963 const ClientId &explicitOwner)
966 DataType objDataType;
969 int retCode = tryRet([&] {
970 Crypto::GObjUPtr obj;
971 return readDataHelper(false, cred, dataType, name, explicitOwner, password, obj, objDataType);
974 if (retCode == CKM_API_ERROR_AUTHENTICATION_FAILED) {
976 retCode = CKM_API_SUCCESS;
979 return SerializeMessage(msgId, retCode, objDataType, status);
982 int CKMLogic::getPKCS12Helper(
983 const Credentials &cred,
985 const ClientId &explicitOwner,
986 const Password &keyPassword,
987 const Password &certPassword,
989 CertificateShPtr &cert,
990 CertificateShPtrVector &caChain)
994 // read private key (mandatory)
995 Crypto::GObjUPtr keyObj;
996 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
997 keyPassword, keyObj);
999 if (retCode != CKM_API_SUCCESS) {
1000 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1003 privKey = CKM::Key::create(keyObj->getBinary());
1006 // read certificate (mandatory)
1007 Crypto::GObjUPtr certObj;
1008 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, explicitOwner,
1009 certPassword, certObj);
1011 if (retCode != CKM_API_SUCCESS) {
1012 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1015 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
1018 // read CA cert chain (optional)
1019 Crypto::GObjUPtrVector caChainObjs;
1020 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, explicitOwner,
1021 certPassword, caChainObjs);
1023 if (retCode != CKM_API_SUCCESS && retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1024 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1027 for (auto &caCertObj : caChainObjs)
1028 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
1029 DataFormat::FORM_DER));
1032 // if anything found, return it
1033 if (privKey || cert || caChain.size() > 0)
1034 retCode = CKM_API_SUCCESS;
1039 RawBuffer CKMLogic::getPKCS12(
1040 const Credentials &cred,
1043 const ClientId &explicitOwner,
1044 const Password &keyPassword,
1045 const Password &certPassword)
1047 PKCS12Serializable output;
1049 int retCode = tryRet([&] {
1051 CertificateShPtr cert;
1052 CertificateShPtrVector caChain;
1053 int retCode = getPKCS12Helper(cred, name, explicitOwner, keyPassword,
1054 certPassword, privKey, cert, caChain);
1057 if (retCode == CKM_API_SUCCESS)
1058 output = PKCS12Serializable(std::move(privKey), std::move(cert), std::move(caChain));
1063 return SerializeMessage(msgId, retCode, output);
1066 int CKMLogic::getDataListHelper(const Credentials &cred,
1067 const DataType dataType,
1068 OwnerNameVector &ownerNameVector)
1070 int retCode = CKM_API_ERROR_DB_LOCKED;
1072 if (0 < m_userDataMap.count(cred.clientUid)) {
1073 auto &database = m_userDataMap[cred.clientUid].database;
1075 retCode = tryRet<CKM_API_ERROR_DB_ERROR>([&] {
1076 OwnerNameVector tmpVector;
1078 if (dataType.isKey()) {
1079 // list all key types
1080 database.listNames(cred.client,
1082 DataType::DB_KEY_FIRST,
1083 DataType::DB_KEY_LAST);
1085 // list anything else
1086 database.listNames(cred.client,
1091 ownerNameVector.insert(ownerNameVector.end(), tmpVector.begin(),
1093 return CKM_API_SUCCESS;
1100 RawBuffer CKMLogic::getDataList(
1101 const Credentials &cred,
1105 OwnerNameVector systemVector;
1106 OwnerNameVector userVector;
1107 OwnerNameVector ownerNameVector;
1109 int retCode = unlockSystemDB();
1111 if (CKM_API_SUCCESS == retCode) {
1113 if (m_accessControl.isSystemService(cred)) {
1115 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1120 // user - lookup system, then client DB
1121 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1127 if (retCode == CKM_API_SUCCESS) {
1128 retCode = getDataListHelper(cred,
1135 if (retCode == CKM_API_SUCCESS) {
1136 ownerNameVector.insert(ownerNameVector.end(), systemVector.begin(),
1137 systemVector.end());
1138 ownerNameVector.insert(ownerNameVector.end(), userVector.begin(),
1142 return SerializeMessage(msgId, retCode, dataType, ownerNameVector);
1145 int CKMLogic::importInitialData(
1147 const Crypto::Data &data,
1148 const Crypto::EncryptionParams &encParams,
1149 const Policy &policy)
1153 if (encParams.iv.empty() != encParams.tag.empty()) {
1154 LogError("Both iv and tag must be empty or set");
1155 return CKM_API_ERROR_INPUT_PARAM;
1158 // Inital values are always imported with root credentials. Client id is not important.
1159 Credentials rootCred(0, "");
1160 ClientId owner(CLIENT_ID_SYSTEM);
1161 auto &handler = selectDatabase(rootCred, CLIENT_ID_SYSTEM);
1163 // check if save is possible
1164 DB::Crypto::Transaction transaction(&handler.database);
1165 int retCode = checkSaveConditions(rootCred, handler, name, CLIENT_ID_SYSTEM);
1167 if (retCode != CKM_API_SUCCESS)
1170 Crypto::GStore &store =
1171 m_decider.getStore(data.type, policy, !encParams.iv.empty());
1175 auto digest = CryptoLogic::makeHash(name, owner, rootCred.clientUid);
1177 return CKM_API_ERROR_HASH_ERROR;
1179 if (encParams.iv.empty()) {
1180 // Data are not encrypted, let's try to verify them
1181 Crypto::Data binaryData;
1183 if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1186 token = store.import(binaryData,
1187 m_accessControl.isCCMode() ? "" : policy.password,
1190 token = store.import(data,
1191 m_accessControl.isCCMode() ? "" : policy.password,
1195 DB::Row row(std::move(token), name, CLIENT_ID_SYSTEM,
1196 static_cast<int>(policy.extractable));
1197 handler.crypto.encryptRow(row);
1199 handler.database.saveRow(row);
1200 transaction.commit();
1202 return CKM_API_SUCCESS;
1204 } catch (const std::exception &e) {
1205 LogError("Std::exception: " << e.what());
1206 return CKM_API_ERROR_SERVER_ERROR;
1210 int CKMLogic::saveDataHelper(
1211 const Credentials &cred,
1213 const ClientId &explicitOwner,
1214 const Crypto::Data &data,
1215 const PolicySerializable &policy)
1217 auto &handler = selectDatabase(cred, explicitOwner);
1219 // use client id if not explicitly provided
1220 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1222 if (m_accessControl.isSystemService(cred) &&
1223 owner.compare(CLIENT_ID_SYSTEM) != 0) {
1224 LogError("System services can only use " << CLIENT_ID_SYSTEM << " as owner id") ;
1225 return CKM_API_ERROR_INPUT_PARAM;
1228 // check if save is possible
1229 DB::Crypto::Transaction transaction(&handler.database);
1230 int retCode = checkSaveConditions(cred, handler, name, owner);
1232 if (retCode != CKM_API_SUCCESS)
1235 auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
1237 return CKM_API_ERROR_HASH_ERROR;
1240 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, owner,
1241 data, policy, digest);
1242 handler.database.saveRow(encryptedRow);
1244 transaction.commit();
1245 return CKM_API_SUCCESS;
1248 int CKMLogic::saveDataHelper(
1249 const Credentials &cred,
1251 const ClientId &explicitOwner,
1252 const PKCS12Serializable &pkcs,
1253 const PolicySerializable &keyPolicy,
1254 const PolicySerializable &certPolicy)
1256 auto &handler = selectDatabase(cred, explicitOwner);
1258 // use client id if not explicitly provided
1259 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1261 if (m_accessControl.isSystemService(cred) &&
1262 owner.compare(CLIENT_ID_SYSTEM) != 0)
1263 return CKM_API_ERROR_INPUT_PARAM;
1265 // check if save is possible
1266 DB::Crypto::Transaction transaction(&handler.database);
1267 int retCode = checkSaveConditions(cred, handler, name, owner);
1269 if (retCode != CKM_API_SUCCESS)
1272 // extract and encrypt the data
1273 DB::RowVector encryptedRows;
1274 retCode = extractPKCS12Data(handler.crypto, name, owner, pkcs, keyPolicy,
1275 certPolicy, encryptedRows, cred);
1277 if (retCode != CKM_API_SUCCESS)
1281 handler.database.saveRows(name, owner, encryptedRows);
1282 transaction.commit();
1284 return CKM_API_SUCCESS;
1288 int CKMLogic::createKeyAESHelper(
1289 const Credentials &cred,
1292 const ClientId &explicitOwner,
1293 const PolicySerializable &policy)
1295 auto &handler = selectDatabase(cred, explicitOwner);
1297 // use client id if not explicitly provided
1298 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1300 if (m_accessControl.isSystemService(cred) &&
1301 owner.compare(CLIENT_ID_SYSTEM) != 0)
1302 return CKM_API_ERROR_INPUT_PARAM;
1304 // check if save is possible
1305 DB::Crypto::Transaction transaction(&handler.database);
1306 int retCode = checkSaveConditions(cred, handler, name, owner);
1308 if (retCode != CKM_API_SUCCESS)
1311 auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
1313 return CKM_API_ERROR_HASH_ERROR;
1315 // create key in store
1316 CryptoAlgorithm keyGenAlgorithm;
1317 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1318 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1319 Token key = m_decider.getStore(DataType::KEY_AES,
1320 policy).generateSKey(keyGenAlgorithm, policy.password, digest);
1323 DB::Row row(std::move(key), name, owner,
1324 static_cast<int>(policy.extractable));
1325 handler.crypto.encryptRow(row);
1327 handler.database.saveRow(row);
1329 transaction.commit();
1330 return CKM_API_SUCCESS;
1333 int CKMLogic::createKeyPairHelper(
1334 const Credentials &cred,
1335 const CryptoAlgorithmSerializable &keyGenParams,
1336 const Name &namePrivate,
1337 const ClientId &explicitOwnerPrivate,
1338 const Name &namePublic,
1339 const ClientId &explicitOwnerPublic,
1340 const PolicySerializable &policyPrivate,
1341 const PolicySerializable &policyPublic)
1343 auto &handlerPriv = selectDatabase(cred, explicitOwnerPrivate);
1344 auto &handlerPub = selectDatabase(cred, explicitOwnerPublic);
1346 AlgoType keyType = AlgoType::RSA_GEN;
1348 if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1349 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1351 const auto dtIt = ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.find(keyType);
1352 if (dtIt == ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.end())
1353 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1354 const DataTypePair& dt = dtIt->second;
1356 if (policyPrivate.backend != policyPublic.backend)
1357 ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend.");
1359 // use client id if not explicitly provided
1360 const ClientId &ownerPrv = explicitOwnerPrivate.empty() ? cred.client :
1361 explicitOwnerPrivate;
1363 if (m_accessControl.isSystemService(cred) &&
1364 ownerPrv.compare(CLIENT_ID_SYSTEM) != 0)
1365 return CKM_API_ERROR_INPUT_PARAM;
1367 const ClientId &ownerPub = explicitOwnerPublic.empty() ? cred.client :
1368 explicitOwnerPublic;
1370 if (m_accessControl.isSystemService(cred) &&
1371 ownerPub.compare(CLIENT_ID_SYSTEM) != 0)
1372 return CKM_API_ERROR_INPUT_PARAM;
1374 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1375 Policy lessRestricted(Password(), exportable, policyPrivate.backend);
1377 auto digestPriv = CryptoLogic::makeHash(namePrivate, explicitOwnerPrivate, cred.clientUid);
1378 if (digestPriv.empty())
1379 return CKM_API_ERROR_HASH_ERROR;
1381 auto digestPub = CryptoLogic::makeHash(namePublic, explicitOwnerPublic, cred.clientUid);
1382 if (digestPub.empty())
1383 return CKM_API_ERROR_HASH_ERROR;
1385 TokenPair keys = m_decider.getStore(policyPrivate, dt.first, dt.second).generateAKey(keyGenParams,
1386 policyPrivate.password,
1387 policyPublic.password,
1388 digestPriv, digestPub);
1390 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1391 // in case the same database is used for private and public - the second
1392 // transaction will not be executed
1393 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1396 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerPrv);
1398 if (CKM_API_SUCCESS != retCode)
1401 retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerPub);
1403 if (CKM_API_SUCCESS != retCode)
1407 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerPrv,
1408 static_cast<int>(policyPrivate.extractable));
1409 handlerPriv.crypto.encryptRow(rowPrv);
1410 handlerPriv.database.saveRow(rowPrv);
1412 DB::Row rowPub(std::move(keys.second), namePublic, ownerPub,
1413 static_cast<int>(policyPublic.extractable));
1414 handlerPub.crypto.encryptRow(rowPub);
1415 handlerPub.database.saveRow(rowPub);
1417 transactionPub.commit();
1418 transactionPriv.commit();
1419 return CKM_API_SUCCESS;
1422 RawBuffer CKMLogic::createKeyPair(
1423 const Credentials &cred,
1425 const CryptoAlgorithmSerializable &keyGenParams,
1426 const Name &namePrivate,
1427 const ClientId &explicitOwnerPrivate,
1428 const Name &namePublic,
1429 const ClientId &explicitOwnerPublic,
1430 const PolicySerializable &policyPrivate,
1431 const PolicySerializable &policyPublic)
1433 return SerializeMessage(msgId, tryRet([&] {
1434 return createKeyPairHelper(cred, keyGenParams, namePrivate, explicitOwnerPrivate,
1435 namePublic, explicitOwnerPublic, policyPrivate, policyPublic);
1439 RawBuffer CKMLogic::createKeyAES(
1440 const Credentials &cred,
1444 const ClientId &explicitOwner,
1445 const PolicySerializable &policy)
1447 int retCode = CKM_API_SUCCESS;
1450 retCode = tryRet([&] {
1451 return createKeyAESHelper(cred, size, name, explicitOwner, policy);
1453 } catch (std::invalid_argument &e) {
1454 LogDebug("invalid argument error: " << e.what());
1455 retCode = CKM_API_ERROR_INPUT_PARAM;
1458 return SerializeMessage(msgId, retCode);
1461 int CKMLogic::readCertificateHelper(
1462 const Credentials &cred,
1463 const OwnerNameVector &ownerNameVector,
1464 CertificateImplVector &certVector)
1466 for (auto &i : ownerNameVector) {
1467 // certificates can't be protected with custom user password
1468 Crypto::GObjUPtr obj;
1470 ec = readDataHelper(true,
1472 DataType::CERTIFICATE,
1478 if (ec != CKM_API_SUCCESS)
1481 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1483 // try to read chain certificates (if present)
1484 Crypto::GObjUPtrVector caChainObjs;
1485 ec = readDataHelper(true,
1487 DataType::DB_CHAIN_FIRST,
1493 if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1496 for (auto &caCertObj : caChainObjs)
1497 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1500 return CKM_API_SUCCESS;
1503 int CKMLogic::getCertificateChainHelper(
1504 const CertificateImpl &cert,
1505 const RawBufferVector &untrustedCertificates,
1506 const RawBufferVector &trustedCertificates,
1507 bool useTrustedSystemCertificates,
1508 RawBufferVector &chainRawVector)
1510 CertificateImplVector untrustedCertVector;
1511 CertificateImplVector trustedCertVector;
1512 CertificateImplVector chainVector;
1515 return CKM_API_ERROR_INPUT_PARAM;
1517 for (auto &e : untrustedCertificates) {
1518 CertificateImpl c(e, DataFormat::FORM_DER);
1521 return CKM_API_ERROR_INPUT_PARAM;
1523 untrustedCertVector.push_back(std::move(c));
1526 for (auto &e : trustedCertificates) {
1527 CertificateImpl c(e, DataFormat::FORM_DER);
1530 return CKM_API_ERROR_INPUT_PARAM;
1532 trustedCertVector.push_back(std::move(c));
1535 CertificateStore store;
1536 int retCode = store.verifyCertificate(cert,
1537 untrustedCertVector,
1539 useTrustedSystemCertificates,
1540 m_accessControl.isCCMode(),
1543 if (retCode != CKM_API_SUCCESS)
1546 for (auto &e : chainVector)
1547 chainRawVector.push_back(e.getDER());
1549 return CKM_API_SUCCESS;
1552 int CKMLogic::getCertificateChainHelper(
1553 const Credentials &cred,
1554 const CertificateImpl &cert,
1555 const OwnerNameVector &untrusted,
1556 const OwnerNameVector &trusted,
1557 bool useTrustedSystemCertificates,
1558 RawBufferVector &chainRawVector)
1560 CertificateImplVector untrustedCertVector;
1561 CertificateImplVector trustedCertVector;
1562 CertificateImplVector chainVector;
1565 return CKM_API_ERROR_INPUT_PARAM;
1567 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1569 if (retCode != CKM_API_SUCCESS)
1572 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1574 if (retCode != CKM_API_SUCCESS)
1577 CertificateStore store;
1578 retCode = store.verifyCertificate(cert,
1579 untrustedCertVector,
1581 useTrustedSystemCertificates,
1582 m_accessControl.isCCMode(),
1585 if (retCode != CKM_API_SUCCESS)
1588 for (auto &i : chainVector)
1589 chainRawVector.push_back(i.getDER());
1591 return CKM_API_SUCCESS;
1594 RawBuffer CKMLogic::getCertificateChain(
1595 const Credentials & /*cred*/,
1597 const RawBuffer &certificate,
1598 const RawBufferVector &untrustedCertificates,
1599 const RawBufferVector &trustedCertificates,
1600 bool useTrustedSystemCertificates)
1602 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1603 RawBufferVector chainRawVector;
1604 int retCode = CKM_API_ERROR_UNKNOWN;
1607 retCode = getCertificateChainHelper(cert,
1608 untrustedCertificates,
1609 trustedCertificates,
1610 useTrustedSystemCertificates,
1612 } catch (const Exc::Exception &e) {
1613 retCode = e.error();
1614 } catch (const std::exception &e) {
1615 LogError("STD exception " << e.what());
1616 retCode = CKM_API_ERROR_SERVER_ERROR;
1618 LogError("Unknown error.");
1621 return SerializeMessage(msgId, retCode, chainRawVector);
1624 RawBuffer CKMLogic::getCertificateChain(
1625 const Credentials &cred,
1627 const RawBuffer &certificate,
1628 const OwnerNameVector &untrustedCertificates,
1629 const OwnerNameVector &trustedCertificates,
1630 bool useTrustedSystemCertificates)
1632 int retCode = CKM_API_ERROR_UNKNOWN;
1633 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1634 RawBufferVector chainRawVector;
1637 retCode = getCertificateChainHelper(cred,
1639 untrustedCertificates,
1640 trustedCertificates,
1641 useTrustedSystemCertificates,
1643 } catch (const Exc::Exception &e) {
1644 retCode = e.error();
1645 } catch (const std::exception &e) {
1646 LogError("STD exception " << e.what());
1647 retCode = CKM_API_ERROR_SERVER_ERROR;
1649 LogError("Unknown error.");
1652 return SerializeMessage(msgId, retCode, chainRawVector);
1655 RawBuffer CKMLogic::createSignature(
1656 const Credentials &cred,
1658 const Name &privateKeyName,
1659 const ClientId &explicitOwner,
1660 const Password &password, // password for private_key
1661 const RawBuffer &message,
1662 const CryptoAlgorithm &cryptoAlg)
1664 RawBuffer signature;
1666 int retCode = CKM_API_SUCCESS;
1669 retCode = tryRet([&] {
1670 Crypto::GObjUPtr obj;
1671 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
1672 explicitOwner, password, obj);
1674 if (retCode == CKM_API_SUCCESS)
1675 signature = obj->sign(cryptoAlg, message);
1679 } catch (const std::exception &e) {
1680 LogError("STD exception " << e.what());
1681 retCode = CKM_API_ERROR_SERVER_ERROR;
1684 return SerializeMessage(msgId, retCode, signature);
1687 RawBuffer CKMLogic::verifySignature(
1688 const Credentials &cred,
1690 const Name &publicKeyOrCertName,
1691 const ClientId &explicitOwner,
1692 const Password &password, // password for public_key (optional)
1693 const RawBuffer &message,
1694 const RawBuffer &signature,
1695 const CryptoAlgorithm ¶ms)
1697 return SerializeMessage(msgId, tryRet([&] {
1698 // try certificate first - looking for a public key.
1699 // in case of PKCS, pub key from certificate will be found first
1700 // rather than private key from the same PKCS.
1701 Crypto::GObjUPtr obj;
1702 int retCode = readDataHelper(false, cred, DataType::CERTIFICATE,
1703 publicKeyOrCertName, explicitOwner, password, obj);
1705 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1706 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
1707 publicKeyOrCertName, explicitOwner, password, obj);
1709 if (retCode == CKM_API_SUCCESS)
1710 retCode = obj->verify(params, message, signature);
1716 int CKMLogic::setPermissionHelper(
1717 const Credentials &cred, // who's the client
1719 const ClientId &explicitOwner, // who's the owner
1720 const ClientId &accessor, // who will get the access
1721 const PermissionMask permissionMask)
1723 auto &handler = selectDatabase(cred, explicitOwner);
1725 // we don't know the client
1726 if (cred.client.empty() || !isClientValid(cred.client))
1727 return CKM_API_ERROR_INPUT_PARAM;
1729 // use client id if not explicitly provided
1730 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1732 // verify name and owner are correct
1733 if (!isNameValid(name) || !isClientValid(owner) ||
1734 !isClientValid(accessor))
1735 return CKM_API_ERROR_INPUT_PARAM;
1737 // currently we don't support modification of owner's permissions to his own rows
1738 if (owner == accessor)
1739 return CKM_API_ERROR_INPUT_PARAM;
1741 // system database does not support write/remove permissions
1742 if ((0 == owner.compare(CLIENT_ID_SYSTEM)) &&
1743 (permissionMask & Permission::REMOVE))
1744 return CKM_API_ERROR_INPUT_PARAM;
1746 // can the client modify permissions to owner's row?
1747 int retCode = m_accessControl.canModify(cred, owner);
1749 if (retCode != CKM_API_SUCCESS)
1752 DB::Crypto::Transaction transaction(&handler.database);
1754 if (!handler.database.isNameOwnerPresent(name, owner))
1755 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1757 // set permissions to the row owned by owner for accessor
1758 handler.database.setPermission(name, owner, accessor, permissionMask);
1759 transaction.commit();
1761 return CKM_API_SUCCESS;
1764 RawBuffer CKMLogic::setPermission(
1765 const Credentials &cred,
1768 const ClientId &explicitOwner,
1769 const ClientId &accessor,
1770 const PermissionMask permissionMask)
1772 return SerializeMessage(msgID, tryRet([&] {
1773 return setPermissionHelper(cred, name, explicitOwner, accessor, permissionMask);