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);
244 void CKMLogic::saveDKEKFile(uid_t user, const Password &password)
246 auto &handle = m_userDataMap[user];
249 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
252 void CKMLogic::migrateSecureStorageData(bool isAdminUser)
254 SsMigration::migrate(isAdminUser, [this](const std::string &name,
255 const Crypto::Data &data,
256 bool adminUserFlag) {
257 LogInfo("Migrate data called with name: " << name);
258 auto ownerId = adminUserFlag ? CLIENT_ID_ADMIN_USER : CLIENT_ID_SYSTEM;
259 auto uid = adminUserFlag ? ADMIN_USER_DB_UID : SYSTEM_DB_UID;
261 int ret = verifyAndSaveDataHelper(Credentials(uid, ownerId), name, ownerId, data,
262 PolicySerializable());
264 if (ret == CKM_API_ERROR_DB_ALIAS_EXISTS)
265 LogWarning("Alias already exist for migrated name: " << name);
266 else if (ret != CKM_API_SUCCESS)
267 LogError("Failed to migrate secure-storage data. name: " << name <<
272 int CKMLogic::unlockDatabase(uid_t user, const Password &password)
274 if (0 < m_userDataMap.count(user) &&
275 m_userDataMap[user].keyProvider.isInitialized())
276 return CKM_API_SUCCESS;
278 int retCode = tryRet([&] {
279 auto &handle = m_userDataMap[user];
282 loadDKEKFile(user, password);
284 auto wrappedDatabaseDEK = fs.getDBDEK();
286 if (wrappedDatabaseDEK.empty()) {
287 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
288 fs.saveDBDEK(wrappedDatabaseDEK);
291 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
293 handle.database = DB::Crypto(fs.getLegacyDBPath(), fs.getDBPath(), key);
294 handle.crypto = CryptoLogic();
296 if (!m_accessControl.isSystemService(user)) {
297 // remove data of removed apps during locked state
298 ClientIdVector removedApps = fs.clearRemovedsApps();
300 for (auto &app : removedApps) {
301 handle.crypto.removeKey(app);
302 handle.database.deleteKey(app);
306 if (user == SYSTEM_DB_UID && SsMigration::hasData())
307 migrateSecureStorageData(false);
308 else if (user == ADMIN_USER_DB_UID && SsMigration::hasData())
309 migrateSecureStorageData(true);
311 return CKM_API_SUCCESS;
314 if (CKM_API_SUCCESS != retCode)
315 m_userDataMap.erase(user);
320 int CKMLogic::unlockSystemDB()
322 return unlockDatabase(SYSTEM_DB_UID, DEFAULT_UNLOCK_STRING);
325 UserData &CKMLogic::selectDatabase(const Credentials &cred,
326 const ClientId &explicitOwner)
328 // if user trying to access system service - check:
329 // * if user database is unlocked [mandatory]
330 // * if not - proceed with regular user database
331 // * if explicit system database owner given -> switch to system DB
332 if (!m_accessControl.isSystemService(cred)) {
333 if (0 == m_userDataMap.count(cred.clientUid))
334 ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
336 if (0 != explicitOwner.compare(CLIENT_ID_SYSTEM))
337 return m_userDataMap[cred.clientUid];
340 // system database selected, modify the owner id
341 if (CKM_API_SUCCESS != unlockSystemDB())
342 ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
344 return m_userDataMap[SYSTEM_DB_UID];
347 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
349 int retCode = CKM_API_SUCCESS;
351 if (!m_accessControl.isSystemService(user))
352 retCode = unlockDatabase(user, password);
353 else // do not allow lock/unlock operations for system users
354 retCode = CKM_API_ERROR_INPUT_PARAM;
356 return SerializeMessage(retCode);
359 RawBuffer CKMLogic::updateCCMode()
361 m_accessControl.updateCCMode();
362 return SerializeMessage(CKM_API_SUCCESS);
365 RawBuffer CKMLogic::lockUserKey(uid_t user)
367 int retCode = CKM_API_SUCCESS;
369 if (!m_accessControl.isSystemService(user))
370 m_userDataMap.erase(user);
371 else // do not allow lock/unlock operations for system users
372 retCode = CKM_API_ERROR_INPUT_PARAM;
374 return SerializeMessage(retCode);
377 RawBuffer CKMLogic::removeUserData(uid_t user)
379 if (m_accessControl.isSystemService(user))
380 user = SYSTEM_DB_UID;
382 m_userDataMap.erase(user);
384 const int retCode = FileSystem(user).removeUserData()
385 ? CKM_API_ERROR_FILE_SYSTEM
388 return SerializeMessage(retCode);
391 int CKMLogic::changeUserPasswordHelper(uid_t user,
392 const Password &oldPassword,
393 const Password &newPassword)
395 // do not allow to change system database password
396 if (m_accessControl.isSystemService(user))
397 return CKM_API_ERROR_INPUT_PARAM;
399 loadDKEKFile(user, oldPassword);
400 saveDKEKFile(user, newPassword);
402 return CKM_API_SUCCESS;
405 RawBuffer CKMLogic::changeUserPassword(
407 const Password &oldPassword,
408 const Password &newPassword)
410 return SerializeMessage(tryRet([&] {
411 return changeUserPasswordHelper(user, oldPassword, newPassword);
415 int CKMLogic::resetUserPasswordHelper(
417 const Password &newPassword)
419 // do not allow to reset system database password
420 if (m_accessControl.isSystemService(user))
421 return CKM_API_ERROR_INPUT_PARAM;
423 int retCode = CKM_API_SUCCESS;
425 if (0 == m_userDataMap.count(user)) {
426 // Check if key exists. If exists we must return error
428 auto wrappedDKEKMain = fs.getDKEK();
430 if (!wrappedDKEKMain.empty())
431 retCode = CKM_API_ERROR_BAD_REQUEST;
433 saveDKEKFile(user, newPassword);
439 RawBuffer CKMLogic::resetUserPassword(
441 const Password &newPassword)
443 return SerializeMessage(tryRet([&] {
444 return resetUserPasswordHelper(user, newPassword);
448 RawBuffer CKMLogic::removeApplicationData(const ClientId &owner)
450 return SerializeMessage(tryRet([&] {
452 return CKM_API_ERROR_INPUT_PARAM;
454 UidVector uids = FileSystem::getUIDsFromDBFile();
456 for (auto userId : uids) {
457 if (0 == m_userDataMap.count(userId)) {
458 FileSystem fs(userId);
459 fs.addRemovedApp(owner);
461 auto &handle = m_userDataMap[userId];
462 handle.crypto.removeKey(owner);
463 handle.database.deleteKey(owner);
467 return CKM_API_SUCCESS;
471 int CKMLogic::checkSaveConditions(
472 const Credentials &accessorCred,
475 const ClientId &owner)
477 // verify name and client are correct
478 if (!isNameValid(name) || !isClientValid(owner)) {
479 LogDebug("Invalid parameter passed to key-manager");
480 return CKM_API_ERROR_INPUT_PARAM;
483 // check if accessor is allowed to save owner's items
484 int access_ec = m_accessControl.canSave(accessorCred, owner);
486 if (access_ec != CKM_API_SUCCESS) {
487 LogDebug("accessor " << accessorCred.client << " can not save rows owned by " <<
492 // check if not a duplicate
493 if (handler.database.isNameOwnerPresent(name, owner))
494 return CKM_API_ERROR_DB_ALIAS_EXISTS;
496 // encryption section
497 if (!handler.crypto.haveKey(owner)) {
499 auto key_optional = handler.database.getKey(owner);
502 LogDebug("No Key in database found. Generating new one for client: " <<
504 got_key = handler.keyProvider.generateDEK(owner);
505 handler.database.saveKey(owner, got_key);
507 LogDebug("Key from DB");
508 got_key = *key_optional;
511 got_key = handler.keyProvider.getPureDEK(got_key);
512 handler.crypto.pushKey(owner, got_key);
515 return CKM_API_SUCCESS;
518 DB::Row CKMLogic::createEncryptedRow(
521 const ClientId &owner,
522 const Crypto::Data &data,
523 const Policy &policy,
524 const RawBuffer &hash)
526 Crypto::GStore &store = m_decider.getStore(data.type, policy);
528 // do not encrypt data with password during cc_mode on
529 Token token = store.import(data,
530 m_accessControl.isCCMode() ? "" : policy.password,
531 Crypto::EncryptionParams(), hash);
532 DB::Row row(std::move(token), name, owner,
533 static_cast<int>(policy.extractable));
534 crypto.encryptRow(row);
538 int CKMLogic::verifyAndSaveDataHelper(
539 const Credentials &cred,
541 const ClientId &explicitOwner,
542 const Crypto::Data &data,
543 const PolicySerializable &policy)
546 // check if data is correct
547 Crypto::Data binaryData;
548 int retCode = toBinaryData(data, binaryData);
550 return retCode != CKM_API_SUCCESS
552 : saveDataHelper(cred, name, explicitOwner, binaryData, policy);
556 int CKMLogic::getKeyForService(
557 const Credentials &cred,
559 const ClientId &explicitOwner,
560 const Password &pass,
561 Crypto::GObjShPtr &key)
564 // Key is for internal service use. It won't be exported to the client
565 Crypto::GObjUPtr obj;
566 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
569 if (retCode == CKM_API_SUCCESS)
570 key = std::move(obj);
576 RawBuffer CKMLogic::saveData(
577 const Credentials &cred,
580 const ClientId &explicitOwner,
581 const Crypto::Data &data,
582 const PolicySerializable &policy)
584 int retCode = verifyAndSaveDataHelper(cred, name, explicitOwner, data, policy);
585 return SerializeMessage(msgId, retCode, data.type);
588 int CKMLogic::extractPKCS12Data(
591 const ClientId &owner,
592 const PKCS12Serializable &pkcs,
593 const PolicySerializable &keyPolicy,
594 const PolicySerializable &certPolicy,
595 DB::RowVector &output,
596 const Credentials &cred)
598 // private key is mandatory
599 auto key = pkcs.getKey();
602 LogError("Failed to get private key from pkcs");
603 return CKM_API_ERROR_INVALID_FORMAT;
606 auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
608 return CKM_API_ERROR_HASH_ERROR;
610 Crypto::Data keyData(DataType(key->getType()), key->getDER());
611 int retCode = verifyBinaryData(keyData);
613 if (retCode != CKM_API_SUCCESS)
616 output.push_back(createEncryptedRow(crypto, name, owner, keyData,
619 // certificate is mandatory
620 auto cert = pkcs.getCertificate();
623 LogError("Failed to get certificate from pkcs");
624 return CKM_API_ERROR_INVALID_FORMAT;
627 Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
628 retCode = verifyBinaryData(certData);
630 if (retCode != CKM_API_SUCCESS)
633 output.push_back(createEncryptedRow(crypto, name, owner, certData,
634 certPolicy, digest));
637 unsigned int cert_index = 0;
639 for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
640 Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++),
642 int retCode = verifyBinaryData(caCertData);
644 if (retCode != CKM_API_SUCCESS)
647 output.push_back(createEncryptedRow(crypto, name, owner, caCertData,
648 certPolicy, digest));
651 return CKM_API_SUCCESS;
654 RawBuffer CKMLogic::savePKCS12(
655 const Credentials &cred,
658 const ClientId &explicitOwner,
659 const PKCS12Serializable &pkcs,
660 const PolicySerializable &keyPolicy,
661 const PolicySerializable &certPolicy)
663 return SerializeMessage(msgId, tryRet([&] {
664 return saveDataHelper(cred, name, explicitOwner, pkcs, keyPolicy, certPolicy);
669 int CKMLogic::removeDataHelper(
670 const Credentials &cred,
672 const ClientId &explicitOwner)
674 auto &handler = selectDatabase(cred, explicitOwner);
676 // use client id if not explicitly provided
677 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
679 if (!isNameValid(name) || !isClientValid(owner)) {
680 LogDebug("Invalid owner or name format");
681 return CKM_API_ERROR_INPUT_PARAM;
684 DB::Crypto::Transaction transaction(&handler.database);
686 // read and check permissions
687 PermissionMaskOptional permissionRowOpt =
688 handler.database.getPermissionRow(name, owner, cred.client);
689 int retCode = m_accessControl.canDelete(cred,
690 toPermissionMask(permissionRowOpt));
692 if (retCode != CKM_API_SUCCESS) {
693 LogWarning("access control check result: " << retCode);
697 // get all matching rows
699 handler.database.getRows(name, owner, DataType::DB_FIRST,
700 DataType::DB_LAST, rows);
703 LogDebug("No row for given name and owner");
704 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
707 // load app key if needed
708 retCode = loadAppKey(handler, rows.front().owner);
710 if (CKM_API_SUCCESS != retCode)
713 // destroy it in store
714 for (auto &r : rows) {
716 handler.crypto.decryptRow(Password(), r);
717 m_decider.getStore(r).destroy(r);
718 } catch (const Exc::AuthenticationFailed &) {
719 LogDebug("Authentication failed when removing data. Ignored.");
724 handler.database.deleteRow(name, owner);
725 transaction.commit();
727 return CKM_API_SUCCESS;
730 RawBuffer CKMLogic::removeData(
731 const Credentials &cred,
734 const ClientId &explicitOwner)
736 return SerializeMessage(msgId, tryRet([&] {
737 return removeDataHelper(cred, name, explicitOwner);
742 int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred,
744 const ClientId &owner,
747 DB::Crypto &database)
749 PermissionMaskOptional permissionRowOpt =
750 database.getPermissionRow(name, owner, accessorCred.client);
753 return m_accessControl.canExport(accessorCred,
755 toPermissionMask(permissionRowOpt));
757 return m_accessControl.canRead(accessorCred,
758 toPermissionMask(permissionRowOpt));
761 Crypto::GObjUPtr CKMLogic::rowToObject(
764 const Password &password,
765 const RawBuffer &hash)
767 Crypto::GStore &store = m_decider.getStore(row);
769 Password pass = m_accessControl.isCCMode() ? "" : password;
772 Crypto::GObjUPtr obj;
774 if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
775 CryptoLogic::ENCRYPTION_V2) {
776 handler.crypto.decryptRow(Password(), row);
778 obj = store.getObject(row, pass);
780 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
781 handler.crypto.decryptRow(pass, row);
782 // destroy it in store
785 // import it to store with new scheme: data -> pass(data)
786 Token token = store.import(Crypto::Data(row.dataType, row.data), pass, Crypto::EncryptionParams(), hash);
788 // get it from the store (it can be different than the data we imported into store)
789 obj = store.getObject(token, pass);
791 // update row with new token
792 *static_cast<Token *>(&row) = std::move(token);
794 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
795 handler.crypto.encryptRow(row);
798 handler.database.updateRow(row);
804 int CKMLogic::readDataHelper(
806 const Credentials &cred,
809 const ClientId &explicitOwner,
810 const Password &password,
811 Crypto::GObjUPtrVector &objs)
813 auto &handler = selectDatabase(cred, explicitOwner);
815 // use client id if not explicitly provided
816 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
818 if (!isNameValid(name) || !isClientValid(owner))
819 return CKM_API_ERROR_INPUT_PARAM;
822 DB::Crypto::Transaction transaction(&handler.database);
824 int retCode = readMultiRow(name, owner, dataType, handler.database, rows);
826 if (CKM_API_SUCCESS != retCode)
829 // all read rows belong to the same owner
830 DB::Row &firstRow = rows.at(0);
832 // check access rights
833 retCode = checkDataPermissionsHelper(cred, name, owner, firstRow,
834 exportFlag, handler.database);
836 if (CKM_API_SUCCESS != retCode)
839 // load app key if needed
840 retCode = loadAppKey(handler, firstRow.owner);
842 if (CKM_API_SUCCESS != retCode)
845 auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
847 return CKM_API_ERROR_HASH_ERROR;
850 for (auto &row : rows)
851 objs.push_back(rowToObject(handler, std::move(row), password, digest));
853 // rowToObject may modify db
854 transaction.commit();
856 return CKM_API_SUCCESS;
859 int CKMLogic::readDataHelper(
861 const Credentials &cred,
864 const ClientId &explicitOwner,
865 const Password &password,
866 Crypto::GObjUPtr &obj)
868 DataType objDataType;
869 return readDataHelper(exportFlag, cred, dataType, name, explicitOwner,
870 password, obj, objDataType);
873 int CKMLogic::readDataHelper(
875 const Credentials &cred,
878 const ClientId &explicitOwner,
879 const Password &password,
880 Crypto::GObjUPtr &obj,
881 DataType &objDataType)
883 auto &handler = selectDatabase(cred, explicitOwner);
885 // use client id if not explicitly provided
886 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
888 if (!isNameValid(name) || !isClientValid(owner))
889 return CKM_API_ERROR_INPUT_PARAM;
892 DB::Crypto::Transaction transaction(&handler.database);
894 int retCode = readSingleRow(name, owner, dataType, handler.database, row);
896 if (CKM_API_SUCCESS != retCode)
899 objDataType = row.dataType;
901 // check access rights
902 retCode = checkDataPermissionsHelper(cred, name, owner, row, exportFlag,
905 if (CKM_API_SUCCESS != retCode)
908 // load app key if needed
909 retCode = loadAppKey(handler, row.owner);
911 if (CKM_API_SUCCESS != retCode)
914 auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
916 return CKM_API_ERROR_HASH_ERROR;
918 obj = rowToObject(handler, std::move(row), password, digest);
919 // rowToObject may modify db
920 transaction.commit();
922 return CKM_API_SUCCESS;
925 RawBuffer CKMLogic::getData(
926 const Credentials &cred,
930 const ClientId &explicitOwner,
931 const Password &password)
934 DataType objDataType;
936 int retCode = tryRet([&] {
937 Crypto::GObjUPtr obj;
938 int retCode = readDataHelper(true, cred, dataType, name, explicitOwner,
939 password, obj, objDataType);
941 if (retCode == CKM_API_SUCCESS)
942 rowData = obj->getBinary();
947 if (CKM_API_SUCCESS != retCode)
950 return SerializeMessage(msgId, retCode, objDataType, rowData);
953 RawBuffer CKMLogic::getDataProtectionStatus(
954 const Credentials &cred,
958 const ClientId &explicitOwner)
961 DataType objDataType;
964 int retCode = tryRet([&] {
965 Crypto::GObjUPtr obj;
966 return readDataHelper(false, cred, dataType, name, explicitOwner, password, obj, objDataType);
969 if (retCode == CKM_API_ERROR_AUTHENTICATION_FAILED) {
971 retCode = CKM_API_SUCCESS;
974 return SerializeMessage(msgId, retCode, objDataType, status);
977 int CKMLogic::getPKCS12Helper(
978 const Credentials &cred,
980 const ClientId &explicitOwner,
981 const Password &keyPassword,
982 const Password &certPassword,
984 CertificateShPtr &cert,
985 CertificateShPtrVector &caChain)
989 // read private key (mandatory)
990 Crypto::GObjUPtr keyObj;
991 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
992 keyPassword, keyObj);
994 if (retCode != CKM_API_SUCCESS) {
995 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
998 privKey = CKM::Key::create(keyObj->getBinary());
1001 // read certificate (mandatory)
1002 Crypto::GObjUPtr certObj;
1003 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, explicitOwner,
1004 certPassword, certObj);
1006 if (retCode != CKM_API_SUCCESS) {
1007 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1010 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
1013 // read CA cert chain (optional)
1014 Crypto::GObjUPtrVector caChainObjs;
1015 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, explicitOwner,
1016 certPassword, caChainObjs);
1018 if (retCode != CKM_API_SUCCESS && retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1019 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1022 for (auto &caCertObj : caChainObjs)
1023 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
1024 DataFormat::FORM_DER));
1027 // if anything found, return it
1028 if (privKey || cert || caChain.size() > 0)
1029 retCode = CKM_API_SUCCESS;
1034 RawBuffer CKMLogic::getPKCS12(
1035 const Credentials &cred,
1038 const ClientId &explicitOwner,
1039 const Password &keyPassword,
1040 const Password &certPassword)
1042 PKCS12Serializable output;
1044 int retCode = tryRet([&] {
1046 CertificateShPtr cert;
1047 CertificateShPtrVector caChain;
1048 int retCode = getPKCS12Helper(cred, name, explicitOwner, keyPassword,
1049 certPassword, privKey, cert, caChain);
1052 if (retCode == CKM_API_SUCCESS)
1053 output = PKCS12Serializable(std::move(privKey), std::move(cert), std::move(caChain));
1058 return SerializeMessage(msgId, retCode, output);
1061 int CKMLogic::getDataListHelper(const Credentials &cred,
1062 const DataType dataType,
1063 OwnerNameVector &ownerNameVector)
1065 int retCode = CKM_API_ERROR_DB_LOCKED;
1067 if (0 < m_userDataMap.count(cred.clientUid)) {
1068 auto &database = m_userDataMap[cred.clientUid].database;
1070 retCode = tryRet<CKM_API_ERROR_DB_ERROR>([&] {
1071 OwnerNameVector tmpVector;
1073 if (dataType.isKey()) {
1074 // list all key types
1075 database.listNames(cred.client,
1077 DataType::DB_KEY_FIRST,
1078 DataType::DB_KEY_LAST);
1080 // list anything else
1081 database.listNames(cred.client,
1086 ownerNameVector.insert(ownerNameVector.end(), tmpVector.begin(),
1088 return CKM_API_SUCCESS;
1095 RawBuffer CKMLogic::getDataList(
1096 const Credentials &cred,
1100 OwnerNameVector systemVector;
1101 OwnerNameVector userVector;
1102 OwnerNameVector ownerNameVector;
1104 int retCode = unlockSystemDB();
1106 if (CKM_API_SUCCESS == retCode) {
1108 if (m_accessControl.isSystemService(cred)) {
1110 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1115 // user - lookup system, then client DB
1116 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1122 if (retCode == CKM_API_SUCCESS) {
1123 retCode = getDataListHelper(cred,
1130 if (retCode == CKM_API_SUCCESS) {
1131 ownerNameVector.insert(ownerNameVector.end(), systemVector.begin(),
1132 systemVector.end());
1133 ownerNameVector.insert(ownerNameVector.end(), userVector.begin(),
1137 return SerializeMessage(msgId, retCode, dataType, ownerNameVector);
1140 int CKMLogic::importInitialData(
1142 const Crypto::Data &data,
1143 const Crypto::EncryptionParams &encParams,
1144 const Policy &policy)
1148 if (encParams.iv.empty() != encParams.tag.empty()) {
1149 LogError("Both iv and tag must be empty or set");
1150 return CKM_API_ERROR_INPUT_PARAM;
1153 // Inital values are always imported with root credentials. Client id is not important.
1154 Credentials rootCred(0, "");
1155 ClientId owner(CLIENT_ID_SYSTEM);
1156 auto &handler = selectDatabase(rootCred, CLIENT_ID_SYSTEM);
1158 // check if save is possible
1159 DB::Crypto::Transaction transaction(&handler.database);
1160 int retCode = checkSaveConditions(rootCred, handler, name, CLIENT_ID_SYSTEM);
1162 if (retCode != CKM_API_SUCCESS)
1165 Crypto::GStore &store =
1166 m_decider.getStore(data.type, policy, !encParams.iv.empty());
1170 auto digest = CryptoLogic::makeHash(name, owner, rootCred.clientUid);
1172 return CKM_API_ERROR_HASH_ERROR;
1174 if (encParams.iv.empty()) {
1175 // Data are not encrypted, let's try to verify them
1176 Crypto::Data binaryData;
1178 if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1181 token = store.import(binaryData,
1182 m_accessControl.isCCMode() ? "" : policy.password,
1185 token = store.import(data,
1186 m_accessControl.isCCMode() ? "" : policy.password,
1190 DB::Row row(std::move(token), name, CLIENT_ID_SYSTEM,
1191 static_cast<int>(policy.extractable));
1192 handler.crypto.encryptRow(row);
1194 handler.database.saveRow(row);
1195 transaction.commit();
1197 return CKM_API_SUCCESS;
1199 } catch (const std::exception &e) {
1200 LogError("Std::exception: " << e.what());
1201 return CKM_API_ERROR_SERVER_ERROR;
1205 int CKMLogic::saveDataHelper(
1206 const Credentials &cred,
1208 const ClientId &explicitOwner,
1209 const Crypto::Data &data,
1210 const PolicySerializable &policy)
1212 auto &handler = selectDatabase(cred, explicitOwner);
1214 // use client id if not explicitly provided
1215 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1217 if (m_accessControl.isSystemService(cred) &&
1218 owner.compare(CLIENT_ID_SYSTEM) != 0) {
1219 LogError("System services can only use " << CLIENT_ID_SYSTEM << " as owner id") ;
1220 return CKM_API_ERROR_INPUT_PARAM;
1223 // check if save is possible
1224 DB::Crypto::Transaction transaction(&handler.database);
1225 int retCode = checkSaveConditions(cred, handler, name, owner);
1227 if (retCode != CKM_API_SUCCESS)
1230 auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
1232 return CKM_API_ERROR_HASH_ERROR;
1235 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, owner,
1236 data, policy, digest);
1237 handler.database.saveRow(encryptedRow);
1239 transaction.commit();
1240 return CKM_API_SUCCESS;
1243 int CKMLogic::saveDataHelper(
1244 const Credentials &cred,
1246 const ClientId &explicitOwner,
1247 const PKCS12Serializable &pkcs,
1248 const PolicySerializable &keyPolicy,
1249 const PolicySerializable &certPolicy)
1251 auto &handler = selectDatabase(cred, explicitOwner);
1253 // use client id if not explicitly provided
1254 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1256 if (m_accessControl.isSystemService(cred) &&
1257 owner.compare(CLIENT_ID_SYSTEM) != 0)
1258 return CKM_API_ERROR_INPUT_PARAM;
1260 // check if save is possible
1261 DB::Crypto::Transaction transaction(&handler.database);
1262 int retCode = checkSaveConditions(cred, handler, name, owner);
1264 if (retCode != CKM_API_SUCCESS)
1267 // extract and encrypt the data
1268 DB::RowVector encryptedRows;
1269 retCode = extractPKCS12Data(handler.crypto, name, owner, pkcs, keyPolicy,
1270 certPolicy, encryptedRows, cred);
1272 if (retCode != CKM_API_SUCCESS)
1276 handler.database.saveRows(name, owner, encryptedRows);
1277 transaction.commit();
1279 return CKM_API_SUCCESS;
1283 int CKMLogic::createKeyAESHelper(
1284 const Credentials &cred,
1287 const ClientId &explicitOwner,
1288 const PolicySerializable &policy)
1290 auto &handler = selectDatabase(cred, explicitOwner);
1292 // use client id if not explicitly provided
1293 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1295 if (m_accessControl.isSystemService(cred) &&
1296 owner.compare(CLIENT_ID_SYSTEM) != 0)
1297 return CKM_API_ERROR_INPUT_PARAM;
1299 // check if save is possible
1300 DB::Crypto::Transaction transaction(&handler.database);
1301 int retCode = checkSaveConditions(cred, handler, name, owner);
1303 if (retCode != CKM_API_SUCCESS)
1306 auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
1308 return CKM_API_ERROR_HASH_ERROR;
1310 // create key in store
1311 CryptoAlgorithm keyGenAlgorithm;
1312 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1313 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1314 Token key = m_decider.getStore(DataType::KEY_AES,
1315 policy).generateSKey(keyGenAlgorithm, policy.password, digest);
1318 DB::Row row(std::move(key), name, owner,
1319 static_cast<int>(policy.extractable));
1320 handler.crypto.encryptRow(row);
1322 handler.database.saveRow(row);
1324 transaction.commit();
1325 return CKM_API_SUCCESS;
1328 int CKMLogic::createKeyPairHelper(
1329 const Credentials &cred,
1330 const CryptoAlgorithmSerializable &keyGenParams,
1331 const Name &namePrivate,
1332 const ClientId &explicitOwnerPrivate,
1333 const Name &namePublic,
1334 const ClientId &explicitOwnerPublic,
1335 const PolicySerializable &policyPrivate,
1336 const PolicySerializable &policyPublic)
1338 auto &handlerPriv = selectDatabase(cred, explicitOwnerPrivate);
1339 auto &handlerPub = selectDatabase(cred, explicitOwnerPublic);
1341 AlgoType keyType = AlgoType::RSA_GEN;
1343 if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1344 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1346 const auto dtIt = ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.find(keyType);
1347 if (dtIt == ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.end())
1348 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1349 const DataTypePair& dt = dtIt->second;
1351 if (policyPrivate.backend != policyPublic.backend)
1352 ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend.");
1354 // use client id if not explicitly provided
1355 const ClientId &ownerPrv = explicitOwnerPrivate.empty() ? cred.client :
1356 explicitOwnerPrivate;
1358 if (m_accessControl.isSystemService(cred) &&
1359 ownerPrv.compare(CLIENT_ID_SYSTEM) != 0)
1360 return CKM_API_ERROR_INPUT_PARAM;
1362 const ClientId &ownerPub = explicitOwnerPublic.empty() ? cred.client :
1363 explicitOwnerPublic;
1365 if (m_accessControl.isSystemService(cred) &&
1366 ownerPub.compare(CLIENT_ID_SYSTEM) != 0)
1367 return CKM_API_ERROR_INPUT_PARAM;
1369 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1370 Policy lessRestricted(Password(), exportable, policyPrivate.backend);
1372 auto digestPriv = CryptoLogic::makeHash(namePrivate, explicitOwnerPrivate, cred.clientUid);
1373 if (digestPriv.empty())
1374 return CKM_API_ERROR_HASH_ERROR;
1376 auto digestPub = CryptoLogic::makeHash(namePublic, explicitOwnerPublic, cred.clientUid);
1377 if (digestPub.empty())
1378 return CKM_API_ERROR_HASH_ERROR;
1380 TokenPair keys = m_decider.getStore(policyPrivate, dt.first, dt.second).generateAKey(keyGenParams,
1381 policyPrivate.password,
1382 policyPublic.password,
1383 digestPriv, digestPub);
1385 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1386 // in case the same database is used for private and public - the second
1387 // transaction will not be executed
1388 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1391 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerPrv);
1393 if (CKM_API_SUCCESS != retCode)
1396 retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerPub);
1398 if (CKM_API_SUCCESS != retCode)
1402 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerPrv,
1403 static_cast<int>(policyPrivate.extractable));
1404 handlerPriv.crypto.encryptRow(rowPrv);
1405 handlerPriv.database.saveRow(rowPrv);
1407 DB::Row rowPub(std::move(keys.second), namePublic, ownerPub,
1408 static_cast<int>(policyPublic.extractable));
1409 handlerPub.crypto.encryptRow(rowPub);
1410 handlerPub.database.saveRow(rowPub);
1412 transactionPub.commit();
1413 transactionPriv.commit();
1414 return CKM_API_SUCCESS;
1417 RawBuffer CKMLogic::createKeyPair(
1418 const Credentials &cred,
1420 const CryptoAlgorithmSerializable &keyGenParams,
1421 const Name &namePrivate,
1422 const ClientId &explicitOwnerPrivate,
1423 const Name &namePublic,
1424 const ClientId &explicitOwnerPublic,
1425 const PolicySerializable &policyPrivate,
1426 const PolicySerializable &policyPublic)
1428 return SerializeMessage(msgId, tryRet([&] {
1429 return createKeyPairHelper(cred, keyGenParams, namePrivate, explicitOwnerPrivate,
1430 namePublic, explicitOwnerPublic, policyPrivate, policyPublic);
1434 RawBuffer CKMLogic::createKeyAES(
1435 const Credentials &cred,
1439 const ClientId &explicitOwner,
1440 const PolicySerializable &policy)
1442 int retCode = CKM_API_SUCCESS;
1445 retCode = tryRet([&] {
1446 return createKeyAESHelper(cred, size, name, explicitOwner, policy);
1448 } catch (std::invalid_argument &e) {
1449 LogDebug("invalid argument error: " << e.what());
1450 retCode = CKM_API_ERROR_INPUT_PARAM;
1453 return SerializeMessage(msgId, retCode);
1456 int CKMLogic::readCertificateHelper(
1457 const Credentials &cred,
1458 const OwnerNameVector &ownerNameVector,
1459 CertificateImplVector &certVector)
1461 for (auto &i : ownerNameVector) {
1462 // certificates can't be protected with custom user password
1463 Crypto::GObjUPtr obj;
1465 ec = readDataHelper(true,
1467 DataType::CERTIFICATE,
1473 if (ec != CKM_API_SUCCESS)
1476 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1478 // try to read chain certificates (if present)
1479 Crypto::GObjUPtrVector caChainObjs;
1480 ec = readDataHelper(true,
1482 DataType::DB_CHAIN_FIRST,
1488 if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1491 for (auto &caCertObj : caChainObjs)
1492 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1495 return CKM_API_SUCCESS;
1498 int CKMLogic::getCertificateChainHelper(
1499 const CertificateImpl &cert,
1500 const RawBufferVector &untrustedCertificates,
1501 const RawBufferVector &trustedCertificates,
1502 bool useTrustedSystemCertificates,
1503 RawBufferVector &chainRawVector)
1505 CertificateImplVector untrustedCertVector;
1506 CertificateImplVector trustedCertVector;
1507 CertificateImplVector chainVector;
1510 return CKM_API_ERROR_INPUT_PARAM;
1512 for (auto &e : untrustedCertificates) {
1513 CertificateImpl c(e, DataFormat::FORM_DER);
1516 return CKM_API_ERROR_INPUT_PARAM;
1518 untrustedCertVector.push_back(std::move(c));
1521 for (auto &e : trustedCertificates) {
1522 CertificateImpl c(e, DataFormat::FORM_DER);
1525 return CKM_API_ERROR_INPUT_PARAM;
1527 trustedCertVector.push_back(std::move(c));
1530 CertificateStore store;
1531 int retCode = store.verifyCertificate(cert,
1532 untrustedCertVector,
1534 useTrustedSystemCertificates,
1535 m_accessControl.isCCMode(),
1538 if (retCode != CKM_API_SUCCESS)
1541 for (auto &e : chainVector)
1542 chainRawVector.push_back(e.getDER());
1544 return CKM_API_SUCCESS;
1547 int CKMLogic::getCertificateChainHelper(
1548 const Credentials &cred,
1549 const CertificateImpl &cert,
1550 const OwnerNameVector &untrusted,
1551 const OwnerNameVector &trusted,
1552 bool useTrustedSystemCertificates,
1553 RawBufferVector &chainRawVector)
1555 CertificateImplVector untrustedCertVector;
1556 CertificateImplVector trustedCertVector;
1557 CertificateImplVector chainVector;
1560 return CKM_API_ERROR_INPUT_PARAM;
1562 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1564 if (retCode != CKM_API_SUCCESS)
1567 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1569 if (retCode != CKM_API_SUCCESS)
1572 CertificateStore store;
1573 retCode = store.verifyCertificate(cert,
1574 untrustedCertVector,
1576 useTrustedSystemCertificates,
1577 m_accessControl.isCCMode(),
1580 if (retCode != CKM_API_SUCCESS)
1583 for (auto &i : chainVector)
1584 chainRawVector.push_back(i.getDER());
1586 return CKM_API_SUCCESS;
1589 RawBuffer CKMLogic::getCertificateChain(
1590 const Credentials & /*cred*/,
1592 const RawBuffer &certificate,
1593 const RawBufferVector &untrustedCertificates,
1594 const RawBufferVector &trustedCertificates,
1595 bool useTrustedSystemCertificates)
1597 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1598 RawBufferVector chainRawVector;
1599 int retCode = CKM_API_ERROR_UNKNOWN;
1602 retCode = getCertificateChainHelper(cert,
1603 untrustedCertificates,
1604 trustedCertificates,
1605 useTrustedSystemCertificates,
1607 } catch (const Exc::Exception &e) {
1608 retCode = e.error();
1609 } catch (const std::exception &e) {
1610 LogError("STD exception " << e.what());
1611 retCode = CKM_API_ERROR_SERVER_ERROR;
1613 LogError("Unknown error.");
1616 return SerializeMessage(msgId, retCode, chainRawVector);
1619 RawBuffer CKMLogic::getCertificateChain(
1620 const Credentials &cred,
1622 const RawBuffer &certificate,
1623 const OwnerNameVector &untrustedCertificates,
1624 const OwnerNameVector &trustedCertificates,
1625 bool useTrustedSystemCertificates)
1627 int retCode = CKM_API_ERROR_UNKNOWN;
1628 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1629 RawBufferVector chainRawVector;
1632 retCode = getCertificateChainHelper(cred,
1634 untrustedCertificates,
1635 trustedCertificates,
1636 useTrustedSystemCertificates,
1638 } catch (const Exc::Exception &e) {
1639 retCode = e.error();
1640 } catch (const std::exception &e) {
1641 LogError("STD exception " << e.what());
1642 retCode = CKM_API_ERROR_SERVER_ERROR;
1644 LogError("Unknown error.");
1647 return SerializeMessage(msgId, retCode, chainRawVector);
1650 RawBuffer CKMLogic::createSignature(
1651 const Credentials &cred,
1653 const Name &privateKeyName,
1654 const ClientId &explicitOwner,
1655 const Password &password, // password for private_key
1656 const RawBuffer &message,
1657 const CryptoAlgorithm &cryptoAlg)
1659 RawBuffer signature;
1661 int retCode = CKM_API_SUCCESS;
1664 retCode = tryRet([&] {
1665 Crypto::GObjUPtr obj;
1666 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
1667 explicitOwner, password, obj);
1669 if (retCode == CKM_API_SUCCESS)
1670 signature = obj->sign(cryptoAlg, message);
1674 } catch (const std::exception &e) {
1675 LogError("STD exception " << e.what());
1676 retCode = CKM_API_ERROR_SERVER_ERROR;
1679 return SerializeMessage(msgId, retCode, signature);
1682 RawBuffer CKMLogic::verifySignature(
1683 const Credentials &cred,
1685 const Name &publicKeyOrCertName,
1686 const ClientId &explicitOwner,
1687 const Password &password, // password for public_key (optional)
1688 const RawBuffer &message,
1689 const RawBuffer &signature,
1690 const CryptoAlgorithm ¶ms)
1692 return SerializeMessage(msgId, tryRet([&] {
1693 // try certificate first - looking for a public key.
1694 // in case of PKCS, pub key from certificate will be found first
1695 // rather than private key from the same PKCS.
1696 Crypto::GObjUPtr obj;
1697 int retCode = readDataHelper(false, cred, DataType::CERTIFICATE,
1698 publicKeyOrCertName, explicitOwner, password, obj);
1700 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1701 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
1702 publicKeyOrCertName, explicitOwner, password, obj);
1704 if (retCode == CKM_API_SUCCESS)
1705 retCode = obj->verify(params, message, signature);
1711 int CKMLogic::setPermissionHelper(
1712 const Credentials &cred, // who's the client
1714 const ClientId &explicitOwner, // who's the owner
1715 const ClientId &accessor, // who will get the access
1716 const PermissionMask permissionMask)
1718 auto &handler = selectDatabase(cred, explicitOwner);
1720 // we don't know the client
1721 if (cred.client.empty() || !isClientValid(cred.client))
1722 return CKM_API_ERROR_INPUT_PARAM;
1724 // use client id if not explicitly provided
1725 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1727 // verify name and owner are correct
1728 if (!isNameValid(name) || !isClientValid(owner) ||
1729 !isClientValid(accessor))
1730 return CKM_API_ERROR_INPUT_PARAM;
1732 // currently we don't support modification of owner's permissions to his own rows
1733 if (owner == accessor)
1734 return CKM_API_ERROR_INPUT_PARAM;
1736 // system database does not support write/remove permissions
1737 if ((0 == owner.compare(CLIENT_ID_SYSTEM)) &&
1738 (permissionMask & Permission::REMOVE))
1739 return CKM_API_ERROR_INPUT_PARAM;
1741 // can the client modify permissions to owner's row?
1742 int retCode = m_accessControl.canModify(cred, owner);
1744 if (retCode != CKM_API_SUCCESS)
1747 DB::Crypto::Transaction transaction(&handler.database);
1749 if (!handler.database.isNameOwnerPresent(name, owner))
1750 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1752 // set permissions to the row owned by owner for accessor
1753 handler.database.setPermission(name, owner, accessor, permissionMask);
1754 transaction.commit();
1756 return CKM_API_SUCCESS;
1759 RawBuffer CKMLogic::setPermission(
1760 const Credentials &cred,
1763 const ClientId &explicitOwner,
1764 const ClientId &accessor,
1765 const PermissionMask permissionMask)
1767 return SerializeMessage(msgID, tryRet([&] {
1768 return setPermissionHelper(cred, name, explicitOwner, accessor, permissionMask);