2 * Copyright (c) 2014-2020 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 SYSTEM_DB_PASSWD = "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 int toBinaryData(const Crypto::Data &input, Crypto::Data &output)
76 // verify the data integrity
77 if (input.type.isKey()) {
80 if (input.type.isSKey())
81 output_key = CKM::Key::createAES(input.data);
83 output_key = CKM::Key::create(input.data);
85 if (output_key.get() == NULL) {
86 LogDebug("provided binary data is not valid key data");
87 return CKM_API_ERROR_INPUT_PARAM;
90 output = std::move(Crypto::Data(input.type, output_key->getDER()));
91 } else if (input.type.isCertificate() || input.type.isChainCert()) {
92 CertificateShPtr cert = CKM::Certificate::create(input.data,
93 DataFormat::FORM_DER);
95 if (cert.get() == NULL) {
96 LogDebug("provided binary data is not valid certificate data");
97 return CKM_API_ERROR_INPUT_PARAM;
100 output = std::move(Crypto::Data(input.type, cert->getDER()));
105 // TODO: add here BINARY_DATA verification, i.e: max size etc.
106 return CKM_API_SUCCESS;
109 int verifyBinaryData(Crypto::Data &input)
112 return toBinaryData(input, dummy);
115 int readSingleRow(const Name &name,
116 const ClientId &owner,
118 DB::Crypto &database,
121 DB::Crypto::RowOptional row_optional;
123 if (dataType.isKey()) {
124 // read all key types
125 row_optional = database.getRow(name,
127 DataType::DB_KEY_FIRST,
128 DataType::DB_KEY_LAST);
130 // read anything else
131 row_optional = database.getRow(name,
137 LogDebug("No row for given name, owner and type");
138 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
143 return CKM_API_SUCCESS;
146 int readMultiRow(const Name &name,
147 const ClientId &owner,
149 DB::Crypto &database,
150 DB::RowVector &output)
152 if (dataType.isKey())
153 // read all key types
154 database.getRows(name,
156 DataType::DB_KEY_FIRST,
157 DataType::DB_KEY_LAST,
159 else if (dataType.isChainCert())
160 // read all key types
161 database.getRows(name,
163 DataType::DB_CHAIN_FIRST,
164 DataType::DB_CHAIN_LAST,
167 // read anything else
168 database.getRows(name,
173 if (!output.size()) {
174 LogDebug("No row for given name, owner and type");
175 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
178 return CKM_API_SUCCESS;
181 int loadAppKey(UserData &handle, const ClientId &owner)
183 if (!handle.crypto.haveKey(owner)) {
185 auto key_optional = handle.database.getKey(owner);
188 LogError("No key for given owner in database");
189 return CKM_API_ERROR_DB_ERROR;
193 key = handle.keyProvider.getPureDEK(key);
194 handle.crypto.pushKey(owner, key);
197 return CKM_API_SUCCESS;
202 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
203 const uid_t CKMLogic::ADMIN_USER_DB_UID = 5001;
207 CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
209 m_accessControl.updateCCMode();
212 CKMLogic::~CKMLogic() {}
214 void CKMLogic::loadDKEKFile(uid_t user, const Password &password)
216 auto &handle = m_userDataMap[user];
220 auto wrappedDKEK = fs.getDKEK();
222 if (wrappedDKEK.empty()) {
223 wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
224 fs.saveDKEK(wrappedDKEK);
227 handle.keyProvider = KeyProvider(wrappedDKEK, password);
230 void CKMLogic::saveDKEKFile(uid_t user, const Password &password)
232 auto &handle = m_userDataMap[user];
235 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
238 void CKMLogic::migrateSecureStorageData(bool isAdminUser)
240 SsMigration::migrate(isAdminUser, [this](const std::string &name,
241 const Crypto::Data &data,
242 bool adminUserFlag) {
243 LogInfo("Migrate data called with name: " << name);
244 auto ownerId = adminUserFlag ? CLIENT_ID_ADMIN_USER : CLIENT_ID_SYSTEM;
245 auto uid = adminUserFlag ? ADMIN_USER_DB_UID : SYSTEM_DB_UID;
247 int ret = verifyAndSaveDataHelper(Credentials(uid, ownerId), name, ownerId, data,
248 PolicySerializable());
250 if (ret == CKM_API_ERROR_DB_ALIAS_EXISTS)
251 LogWarning("Alias already exist for migrated name: " << name);
252 else if (ret != CKM_API_SUCCESS)
253 LogError("Failed to migrate secure-storage data. name: " << name <<
258 int CKMLogic::unlockDatabase(uid_t user, const Password &password)
260 if (0 < m_userDataMap.count(user) &&
261 m_userDataMap[user].keyProvider.isInitialized())
262 return CKM_API_SUCCESS;
264 int retCode = CKM_API_SUCCESS;
267 auto &handle = m_userDataMap[user];
270 loadDKEKFile(user, password);
272 auto wrappedDatabaseDEK = fs.getDBDEK();
274 if (wrappedDatabaseDEK.empty()) {
275 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
276 fs.saveDBDEK(wrappedDatabaseDEK);
279 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
281 handle.database = DB::Crypto(fs.getLegacyDBPath(), fs.getDBPath(), key);
282 handle.crypto = CryptoLogic();
284 if (!m_accessControl.isSystemService(user)) {
285 // remove data of removed apps during locked state
286 ClientIdVector removedApps = fs.clearRemovedsApps();
288 for (auto &app : removedApps) {
289 handle.crypto.removeKey(app);
290 handle.database.deleteKey(app);
294 if (user == SYSTEM_DB_UID && SsMigration::hasData())
295 migrateSecureStorageData(false);
296 else if (user == ADMIN_USER_DB_UID && SsMigration::hasData())
297 migrateSecureStorageData(true);
298 } catch (const Exc::Exception &e) {
300 } catch (const CKM::Exception &e) {
301 LogError("CKM::Exception: " << e.GetMessage());
302 retCode = CKM_API_ERROR_SERVER_ERROR;
305 if (CKM_API_SUCCESS != retCode)
306 m_userDataMap.erase(user);
311 int CKMLogic::unlockSystemDB()
313 return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
316 UserData &CKMLogic::selectDatabase(const Credentials &cred,
317 const ClientId &explicitOwner)
319 // if user trying to access system service - check:
320 // * if user database is unlocked [mandatory]
321 // * if not - proceed with regular user database
322 // * if explicit system database owner given -> switch to system DB
323 if (!m_accessControl.isSystemService(cred)) {
324 if (0 == m_userDataMap.count(cred.clientUid))
325 ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
327 if (0 != explicitOwner.compare(CLIENT_ID_SYSTEM))
328 return m_userDataMap[cred.clientUid];
331 // system database selected, modify the owner id
332 if (CKM_API_SUCCESS != unlockSystemDB())
333 ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
335 return m_userDataMap[SYSTEM_DB_UID];
338 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
340 int retCode = CKM_API_SUCCESS;
342 if (!m_accessControl.isSystemService(user))
343 retCode = unlockDatabase(user, password);
344 else // do not allow lock/unlock operations for system users
345 retCode = CKM_API_ERROR_INPUT_PARAM;
347 return SerializeMessage(retCode);
350 RawBuffer CKMLogic::updateCCMode()
352 m_accessControl.updateCCMode();
353 return SerializeMessage(CKM_API_SUCCESS);
356 RawBuffer CKMLogic::lockUserKey(uid_t user)
358 int retCode = CKM_API_SUCCESS;
360 if (!m_accessControl.isSystemService(user))
361 m_userDataMap.erase(user);
362 else // do not allow lock/unlock operations for system users
363 retCode = CKM_API_ERROR_INPUT_PARAM;
365 return SerializeMessage(retCode);
368 RawBuffer CKMLogic::removeUserData(uid_t user)
370 if (m_accessControl.isSystemService(user))
371 user = SYSTEM_DB_UID;
373 m_userDataMap.erase(user);
375 const int retCode = FileSystem(user).removeUserData()
376 ? CKM_API_ERROR_FILE_SYSTEM
379 return SerializeMessage(retCode);
382 int CKMLogic::changeUserPasswordHelper(uid_t user,
383 const Password &oldPassword,
384 const Password &newPassword)
386 // do not allow to change system database password
387 if (m_accessControl.isSystemService(user))
388 return CKM_API_ERROR_INPUT_PARAM;
390 loadDKEKFile(user, oldPassword);
391 saveDKEKFile(user, newPassword);
393 return CKM_API_SUCCESS;
396 RawBuffer CKMLogic::changeUserPassword(
398 const Password &oldPassword,
399 const Password &newPassword)
401 int retCode = CKM_API_SUCCESS;
404 retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
405 } catch (const Exc::Exception &e) {
407 } catch (const CKM::Exception &e) {
408 LogError("CKM::Exception: " << e.GetMessage());
409 retCode = CKM_API_ERROR_SERVER_ERROR;
412 return SerializeMessage(retCode);
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 int retCode = CKM_API_SUCCESS;
446 retCode = resetUserPasswordHelper(user, newPassword);
447 } catch (const Exc::Exception &e) {
449 } catch (const CKM::Exception &e) {
450 LogError("CKM::Exception: " << e.GetMessage());
451 retCode = CKM_API_ERROR_SERVER_ERROR;
454 return SerializeMessage(retCode);
457 RawBuffer CKMLogic::removeApplicationData(const ClientId &owner)
459 int retCode = CKM_API_SUCCESS;
463 retCode = CKM_API_ERROR_INPUT_PARAM;
465 UidVector uids = FileSystem::getUIDsFromDBFile();
467 for (auto userId : uids) {
468 if (0 == m_userDataMap.count(userId)) {
469 FileSystem fs(userId);
470 fs.addRemovedApp(owner);
472 auto &handle = m_userDataMap[userId];
473 handle.crypto.removeKey(owner);
474 handle.database.deleteKey(owner);
478 } catch (const Exc::Exception &e) {
480 } catch (const CKM::Exception &e) {
481 LogError("CKM::Exception: " << e.GetMessage());
482 retCode = CKM_API_ERROR_SERVER_ERROR;
485 return SerializeMessage(retCode);
488 int CKMLogic::checkSaveConditions(
489 const Credentials &accessorCred,
492 const ClientId &owner)
494 // verify name and client are correct
495 if (!isNameValid(name) || !isClientValid(owner)) {
496 LogDebug("Invalid parameter passed to key-manager");
497 return CKM_API_ERROR_INPUT_PARAM;
500 // check if accessor is allowed to save owner's items
501 int access_ec = m_accessControl.canSave(accessorCred, owner);
503 if (access_ec != CKM_API_SUCCESS) {
504 LogDebug("accessor " << accessorCred.client << " can not save rows owned by " <<
509 // check if not a duplicate
510 if (handler.database.isNameOwnerPresent(name, owner))
511 return CKM_API_ERROR_DB_ALIAS_EXISTS;
513 // encryption section
514 if (!handler.crypto.haveKey(owner)) {
516 auto key_optional = handler.database.getKey(owner);
519 LogDebug("No Key in database found. Generating new one for client: " <<
521 got_key = handler.keyProvider.generateDEK(owner);
522 handler.database.saveKey(owner, got_key);
524 LogDebug("Key from DB");
525 got_key = *key_optional;
528 got_key = handler.keyProvider.getPureDEK(got_key);
529 handler.crypto.pushKey(owner, got_key);
532 return CKM_API_SUCCESS;
535 DB::Row CKMLogic::createEncryptedRow(
538 const ClientId &owner,
539 const Crypto::Data &data,
540 const Policy &policy)
542 Crypto::GStore &store = m_decider.getStore(data.type, policy);
544 // do not encrypt data with password during cc_mode on
545 Token token = store.import(data,
546 m_accessControl.isCCMode() ? "" : policy.password,
547 Crypto::EncryptionParams());
548 DB::Row row(std::move(token), name, owner,
549 static_cast<int>(policy.extractable));
550 crypto.encryptRow(row);
554 int CKMLogic::verifyAndSaveDataHelper(
555 const Credentials &cred,
557 const ClientId &explicitOwner,
558 const Crypto::Data &data,
559 const PolicySerializable &policy)
561 int retCode = CKM_API_ERROR_UNKNOWN;
564 // check if data is correct
565 Crypto::Data binaryData;
566 retCode = toBinaryData(data, binaryData);
568 if (retCode != CKM_API_SUCCESS)
571 return saveDataHelper(cred, name, explicitOwner, binaryData, policy);
572 } catch (const Exc::Exception &e) {
574 } catch (const CKM::Exception &e) {
575 LogError("CKM::Exception: " << e.GetMessage());
576 return CKM_API_ERROR_SERVER_ERROR;
580 int CKMLogic::getKeyForService(
581 const Credentials &cred,
583 const ClientId &explicitOwner,
584 const Password &pass,
585 Crypto::GObjShPtr &key)
588 // Key is for internal service use. It won't be exported to the client
589 Crypto::GObjUPtr obj;
590 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
593 if (retCode == CKM_API_SUCCESS)
594 key = std::move(obj);
597 } catch (const Exc::Exception &e) {
599 } catch (const CKM::Exception &e) {
600 LogError("CKM::Exception: " << e.GetMessage());
601 return CKM_API_ERROR_SERVER_ERROR;
605 RawBuffer CKMLogic::saveData(
606 const Credentials &cred,
609 const ClientId &explicitOwner,
610 const Crypto::Data &data,
611 const PolicySerializable &policy)
613 int retCode = verifyAndSaveDataHelper(cred, name, explicitOwner, data, policy);
614 return SerializeMessage(msgId, retCode, data.type);
617 int CKMLogic::extractPKCS12Data(
620 const ClientId &owner,
621 const PKCS12Serializable &pkcs,
622 const PolicySerializable &keyPolicy,
623 const PolicySerializable &certPolicy,
624 DB::RowVector &output)
626 // private key is mandatory
627 auto key = pkcs.getKey();
630 LogError("Failed to get private key from pkcs");
631 return CKM_API_ERROR_INVALID_FORMAT;
634 Crypto::Data keyData(DataType(key->getType()), key->getDER());
635 int retCode = verifyBinaryData(keyData);
637 if (retCode != CKM_API_SUCCESS)
640 output.push_back(createEncryptedRow(crypto, name, owner, keyData,
643 // certificate is mandatory
644 auto cert = pkcs.getCertificate();
647 LogError("Failed to get certificate from pkcs");
648 return CKM_API_ERROR_INVALID_FORMAT;
651 Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
652 retCode = verifyBinaryData(certData);
654 if (retCode != CKM_API_SUCCESS)
657 output.push_back(createEncryptedRow(crypto, name, owner, certData,
661 unsigned int cert_index = 0;
663 for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
664 Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++),
666 int retCode = verifyBinaryData(caCertData);
668 if (retCode != CKM_API_SUCCESS)
671 output.push_back(createEncryptedRow(crypto, name, owner, caCertData,
675 return CKM_API_SUCCESS;
678 RawBuffer CKMLogic::savePKCS12(
679 const Credentials &cred,
682 const ClientId &explicitOwner,
683 const PKCS12Serializable &pkcs,
684 const PolicySerializable &keyPolicy,
685 const PolicySerializable &certPolicy)
687 int retCode = CKM_API_ERROR_UNKNOWN;
690 retCode = saveDataHelper(cred, name, explicitOwner, pkcs, keyPolicy, certPolicy);
691 } catch (const Exc::Exception &e) {
693 } catch (const CKM::Exception &e) {
694 LogError("CKM::Exception: " << e.GetMessage());
695 retCode = CKM_API_ERROR_SERVER_ERROR;
698 return SerializeMessage(msgId, retCode);
702 int CKMLogic::removeDataHelper(
703 const Credentials &cred,
705 const ClientId &explicitOwner)
707 auto &handler = selectDatabase(cred, explicitOwner);
709 // use client id if not explicitly provided
710 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
712 if (!isNameValid(name) || !isClientValid(owner)) {
713 LogDebug("Invalid owner or name format");
714 return CKM_API_ERROR_INPUT_PARAM;
717 DB::Crypto::Transaction transaction(&handler.database);
719 // read and check permissions
720 PermissionMaskOptional permissionRowOpt =
721 handler.database.getPermissionRow(name, owner, cred.client);
722 int retCode = m_accessControl.canDelete(cred,
723 toPermissionMask(permissionRowOpt));
725 if (retCode != CKM_API_SUCCESS) {
726 LogWarning("access control check result: " << retCode);
730 // get all matching rows
732 handler.database.getRows(name, owner, DataType::DB_FIRST,
733 DataType::DB_LAST, rows);
736 LogDebug("No row for given name and owner");
737 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
740 // load app key if needed
741 retCode = loadAppKey(handler, rows.front().owner);
743 if (CKM_API_SUCCESS != retCode)
746 // destroy it in store
747 for (auto &r : rows) {
749 handler.crypto.decryptRow(Password(), r);
750 m_decider.getStore(r).destroy(r);
751 } catch (const Exc::AuthenticationFailed &) {
752 LogDebug("Authentication failed when removing data. Ignored.");
757 handler.database.deleteRow(name, owner);
758 transaction.commit();
760 return CKM_API_SUCCESS;
763 RawBuffer CKMLogic::removeData(
764 const Credentials &cred,
767 const ClientId &explicitOwner)
769 int retCode = CKM_API_ERROR_UNKNOWN;
772 retCode = removeDataHelper(cred, name, explicitOwner);
773 } catch (const Exc::Exception &e) {
775 } catch (const CKM::Exception &e) {
776 LogError("Error: " << e.GetMessage());
777 retCode = CKM_API_ERROR_DB_ERROR;
780 return SerializeMessage(msgId, retCode);
784 int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred,
786 const ClientId &owner,
789 DB::Crypto &database)
791 PermissionMaskOptional permissionRowOpt =
792 database.getPermissionRow(name, owner, accessorCred.client);
795 return m_accessControl.canExport(accessorCred,
797 toPermissionMask(permissionRowOpt));
799 return m_accessControl.canRead(accessorCred,
800 toPermissionMask(permissionRowOpt));
803 Crypto::GObjUPtr CKMLogic::rowToObject(
806 const Password &password)
808 Crypto::GStore &store = m_decider.getStore(row);
810 Password pass = m_accessControl.isCCMode() ? "" : password;
813 Crypto::GObjUPtr obj;
815 if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
816 CryptoLogic::ENCRYPTION_V2) {
817 handler.crypto.decryptRow(Password(), row);
819 obj = store.getObject(row, pass);
821 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
822 handler.crypto.decryptRow(pass, row);
823 // destroy it in store
826 // import it to store with new scheme: data -> pass(data)
827 Token token = store.import(Crypto::Data(row.dataType, row.data), pass, Crypto::EncryptionParams());
829 // get it from the store (it can be different than the data we imported into store)
830 obj = store.getObject(token, pass);
832 // update row with new token
833 *static_cast<Token *>(&row) = std::move(token);
835 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
836 handler.crypto.encryptRow(row);
839 handler.database.updateRow(row);
845 int CKMLogic::readDataHelper(
847 const Credentials &cred,
850 const ClientId &explicitOwner,
851 const Password &password,
852 Crypto::GObjUPtrVector &objs)
854 auto &handler = selectDatabase(cred, explicitOwner);
856 // use client id if not explicitly provided
857 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
859 if (!isNameValid(name) || !isClientValid(owner))
860 return CKM_API_ERROR_INPUT_PARAM;
863 DB::Crypto::Transaction transaction(&handler.database);
865 int retCode = readMultiRow(name, owner, dataType, handler.database, rows);
867 if (CKM_API_SUCCESS != retCode)
870 // all read rows belong to the same owner
871 DB::Row &firstRow = rows.at(0);
873 // check access rights
874 retCode = checkDataPermissionsHelper(cred, name, owner, firstRow,
875 exportFlag, handler.database);
877 if (CKM_API_SUCCESS != retCode)
880 // load app key if needed
881 retCode = loadAppKey(handler, firstRow.owner);
883 if (CKM_API_SUCCESS != retCode)
887 for (auto &row : rows)
888 objs.push_back(rowToObject(handler, std::move(row), password));
890 // rowToObject may modify db
891 transaction.commit();
893 return CKM_API_SUCCESS;
896 int CKMLogic::readDataHelper(
898 const Credentials &cred,
901 const ClientId &explicitOwner,
902 const Password &password,
903 Crypto::GObjUPtr &obj)
905 DataType objDataType;
906 return readDataHelper(exportFlag, cred, dataType, name, explicitOwner,
907 password, obj, objDataType);
910 int CKMLogic::readDataHelper(
912 const Credentials &cred,
915 const ClientId &explicitOwner,
916 const Password &password,
917 Crypto::GObjUPtr &obj,
918 DataType &objDataType)
920 auto &handler = selectDatabase(cred, explicitOwner);
922 // use client id if not explicitly provided
923 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
925 if (!isNameValid(name) || !isClientValid(owner))
926 return CKM_API_ERROR_INPUT_PARAM;
929 DB::Crypto::Transaction transaction(&handler.database);
931 int retCode = readSingleRow(name, owner, dataType, handler.database, row);
933 if (CKM_API_SUCCESS != retCode)
936 objDataType = row.dataType;
938 // check access rights
939 retCode = checkDataPermissionsHelper(cred, name, owner, row, exportFlag,
942 if (CKM_API_SUCCESS != retCode)
945 // load app key if needed
946 retCode = loadAppKey(handler, row.owner);
948 if (CKM_API_SUCCESS != retCode)
951 obj = rowToObject(handler, std::move(row), password);
952 // rowToObject may modify db
953 transaction.commit();
955 return CKM_API_SUCCESS;
958 RawBuffer CKMLogic::getData(
959 const Credentials &cred,
963 const ClientId &explicitOwner,
964 const Password &password)
966 int retCode = CKM_API_SUCCESS;
968 DataType objDataType;
971 Crypto::GObjUPtr obj;
972 retCode = readDataHelper(true, cred, dataType, name, explicitOwner,
973 password, obj, objDataType);
975 if (retCode == CKM_API_SUCCESS)
976 rowData = obj->getBinary();
977 } catch (const Exc::Exception &e) {
979 } catch (const CKM::Exception &e) {
980 LogError("CKM::Exception: " << e.GetMessage());
981 retCode = CKM_API_ERROR_SERVER_ERROR;
984 if (CKM_API_SUCCESS != retCode)
987 return SerializeMessage(msgId, retCode, objDataType, rowData);
990 RawBuffer CKMLogic::getDataProtectionStatus(
991 const Credentials &cred,
995 const ClientId &explicitOwner)
997 int retCode = CKM_API_SUCCESS;
999 DataType objDataType;
1003 Crypto::GObjUPtr obj;
1004 retCode = readDataHelper(false, cred, dataType, name, explicitOwner,
1005 password, obj, objDataType);
1007 } catch (const Exc::Exception &e) {
1008 retCode = e.error();
1009 } catch (const CKM::Exception &e) {
1010 LogError("CKM::Exception: " << e.GetMessage());
1011 retCode = CKM_API_ERROR_SERVER_ERROR;
1014 if (retCode == CKM_API_ERROR_AUTHENTICATION_FAILED) {
1016 retCode = CKM_API_SUCCESS;
1019 return SerializeMessage(msgId, retCode, objDataType, status);
1022 int CKMLogic::getPKCS12Helper(
1023 const Credentials &cred,
1025 const ClientId &explicitOwner,
1026 const Password &keyPassword,
1027 const Password &certPassword,
1029 CertificateShPtr &cert,
1030 CertificateShPtrVector &caChain)
1034 // read private key (mandatory)
1035 Crypto::GObjUPtr keyObj;
1036 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
1037 keyPassword, keyObj);
1039 if (retCode != CKM_API_SUCCESS) {
1040 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1043 privKey = CKM::Key::create(keyObj->getBinary());
1046 // read certificate (mandatory)
1047 Crypto::GObjUPtr certObj;
1048 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, explicitOwner,
1049 certPassword, certObj);
1051 if (retCode != CKM_API_SUCCESS) {
1052 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1055 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
1058 // read CA cert chain (optional)
1059 Crypto::GObjUPtrVector caChainObjs;
1060 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, explicitOwner,
1061 certPassword, caChainObjs);
1063 if (retCode != CKM_API_SUCCESS && retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1064 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1067 for (auto &caCertObj : caChainObjs)
1068 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
1069 DataFormat::FORM_DER));
1072 // if anything found, return it
1073 if (privKey || cert || caChain.size() > 0)
1074 retCode = CKM_API_SUCCESS;
1079 RawBuffer CKMLogic::getPKCS12(
1080 const Credentials &cred,
1083 const ClientId &explicitOwner,
1084 const Password &keyPassword,
1085 const Password &certPassword)
1087 int retCode = CKM_API_ERROR_UNKNOWN;
1089 PKCS12Serializable output;
1093 CertificateShPtr cert;
1094 CertificateShPtrVector caChain;
1095 retCode = getPKCS12Helper(cred, name, explicitOwner, keyPassword,
1096 certPassword, privKey, cert, caChain);
1099 if (retCode == CKM_API_SUCCESS)
1100 output = PKCS12Serializable(std::move(privKey), std::move(cert), std::move(caChain));
1101 } catch (const Exc::Exception &e) {
1102 retCode = e.error();
1103 } catch (const CKM::Exception &e) {
1104 LogError("CKM::Exception: " << e.GetMessage());
1105 retCode = CKM_API_ERROR_SERVER_ERROR;
1108 return SerializeMessage(msgId, retCode, output);
1111 int CKMLogic::getDataListHelper(const Credentials &cred,
1112 const DataType dataType,
1113 OwnerNameVector &ownerNameVector)
1115 int retCode = CKM_API_ERROR_DB_LOCKED;
1117 if (0 < m_userDataMap.count(cred.clientUid)) {
1118 auto &database = m_userDataMap[cred.clientUid].database;
1121 OwnerNameVector tmpVector;
1123 if (dataType.isKey()) {
1124 // list all key types
1125 database.listNames(cred.client,
1127 DataType::DB_KEY_FIRST,
1128 DataType::DB_KEY_LAST);
1130 // list anything else
1131 database.listNames(cred.client,
1136 ownerNameVector.insert(ownerNameVector.end(), tmpVector.begin(),
1138 retCode = CKM_API_SUCCESS;
1139 } catch (const CKM::Exception &e) {
1140 LogError("Error: " << e.GetMessage());
1141 retCode = CKM_API_ERROR_DB_ERROR;
1142 } catch (const Exc::Exception &e) {
1143 retCode = e.error();
1150 RawBuffer CKMLogic::getDataList(
1151 const Credentials &cred,
1155 OwnerNameVector systemVector;
1156 OwnerNameVector userVector;
1157 OwnerNameVector ownerNameVector;
1159 int retCode = unlockSystemDB();
1161 if (CKM_API_SUCCESS == retCode) {
1163 if (m_accessControl.isSystemService(cred)) {
1165 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1170 // user - lookup system, then client DB
1171 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1177 if (retCode == CKM_API_SUCCESS) {
1178 retCode = getDataListHelper(cred,
1185 if (retCode == CKM_API_SUCCESS) {
1186 ownerNameVector.insert(ownerNameVector.end(), systemVector.begin(),
1187 systemVector.end());
1188 ownerNameVector.insert(ownerNameVector.end(), userVector.begin(),
1192 return SerializeMessage(msgId, retCode, dataType, ownerNameVector);
1195 int CKMLogic::importInitialData(
1197 const Crypto::Data &data,
1198 const Crypto::EncryptionParams &encParams,
1199 const Policy &policy)
1202 if (encParams.iv.empty() != encParams.tag.empty()) {
1203 LogError("Both iv and tag must be empty or set");
1204 return CKM_API_ERROR_INPUT_PARAM;
1207 // Inital values are always imported with root credentials. Client id is not important.
1208 Credentials rootCred(0, "");
1210 auto &handler = selectDatabase(rootCred, CLIENT_ID_SYSTEM);
1212 // check if save is possible
1213 DB::Crypto::Transaction transaction(&handler.database);
1214 int retCode = checkSaveConditions(rootCred, handler, name, CLIENT_ID_SYSTEM);
1216 if (retCode != CKM_API_SUCCESS)
1219 Crypto::GStore &store =
1220 m_decider.getStore(data.type, policy, !encParams.iv.empty());
1224 if (encParams.iv.empty()) {
1225 // Data are not encrypted, let's try to verify them
1226 Crypto::Data binaryData;
1228 if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1231 token = store.import(binaryData,
1232 m_accessControl.isCCMode() ? "" : policy.password,
1235 token = store.import(data,
1236 m_accessControl.isCCMode() ? "" : policy.password,
1240 DB::Row row(std::move(token), name, CLIENT_ID_SYSTEM,
1241 static_cast<int>(policy.extractable));
1242 handler.crypto.encryptRow(row);
1244 handler.database.saveRow(row);
1245 transaction.commit();
1246 } catch (const Exc::Exception &e) {
1248 } catch (const CKM::Exception &e) {
1249 LogError("CKM::Exception: " << e.GetMessage());
1250 return CKM_API_ERROR_SERVER_ERROR;
1251 } catch (const std::exception &e) {
1252 LogError("Std::exception: " << e.what());
1253 return CKM_API_ERROR_SERVER_ERROR;
1256 return CKM_API_SUCCESS;
1259 int CKMLogic::saveDataHelper(
1260 const Credentials &cred,
1262 const ClientId &explicitOwner,
1263 const Crypto::Data &data,
1264 const PolicySerializable &policy)
1266 auto &handler = selectDatabase(cred, explicitOwner);
1268 // use client id if not explicitly provided
1269 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1271 if (m_accessControl.isSystemService(cred) &&
1272 owner.compare(CLIENT_ID_SYSTEM) != 0) {
1273 LogError("System services can only use " << CLIENT_ID_SYSTEM << " as owner id") ;
1274 return CKM_API_ERROR_INPUT_PARAM;
1277 // check if save is possible
1278 DB::Crypto::Transaction transaction(&handler.database);
1279 int retCode = checkSaveConditions(cred, handler, name, owner);
1281 if (retCode != CKM_API_SUCCESS)
1285 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, owner,
1287 handler.database.saveRow(encryptedRow);
1289 transaction.commit();
1290 return CKM_API_SUCCESS;
1293 int CKMLogic::saveDataHelper(
1294 const Credentials &cred,
1296 const ClientId &explicitOwner,
1297 const PKCS12Serializable &pkcs,
1298 const PolicySerializable &keyPolicy,
1299 const PolicySerializable &certPolicy)
1301 auto &handler = selectDatabase(cred, explicitOwner);
1303 // use client id if not explicitly provided
1304 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1306 if (m_accessControl.isSystemService(cred) &&
1307 owner.compare(CLIENT_ID_SYSTEM) != 0)
1308 return CKM_API_ERROR_INPUT_PARAM;
1310 // check if save is possible
1311 DB::Crypto::Transaction transaction(&handler.database);
1312 int retCode = checkSaveConditions(cred, handler, name, owner);
1314 if (retCode != CKM_API_SUCCESS)
1317 // extract and encrypt the data
1318 DB::RowVector encryptedRows;
1319 retCode = extractPKCS12Data(handler.crypto, name, owner, pkcs, keyPolicy,
1320 certPolicy, encryptedRows);
1322 if (retCode != CKM_API_SUCCESS)
1326 handler.database.saveRows(name, owner, encryptedRows);
1327 transaction.commit();
1329 return CKM_API_SUCCESS;
1333 int CKMLogic::createKeyAESHelper(
1334 const Credentials &cred,
1337 const ClientId &explicitOwner,
1338 const PolicySerializable &policy)
1340 auto &handler = selectDatabase(cred, explicitOwner);
1342 // use client id if not explicitly provided
1343 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1345 if (m_accessControl.isSystemService(cred) &&
1346 owner.compare(CLIENT_ID_SYSTEM) != 0)
1347 return CKM_API_ERROR_INPUT_PARAM;
1349 // check if save is possible
1350 DB::Crypto::Transaction transaction(&handler.database);
1351 int retCode = checkSaveConditions(cred, handler, name, owner);
1353 if (retCode != CKM_API_SUCCESS)
1356 // create key in store
1357 CryptoAlgorithm keyGenAlgorithm;
1358 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1359 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1360 Token key = m_decider.getStore(DataType::KEY_AES,
1361 policy).generateSKey(keyGenAlgorithm, policy.password);
1364 DB::Row row(std::move(key), name, owner,
1365 static_cast<int>(policy.extractable));
1366 handler.crypto.encryptRow(row);
1368 handler.database.saveRow(row);
1370 transaction.commit();
1371 return CKM_API_SUCCESS;
1374 int CKMLogic::createKeyPairHelper(
1375 const Credentials &cred,
1376 const CryptoAlgorithmSerializable &keyGenParams,
1377 const Name &namePrivate,
1378 const ClientId &explicitOwnerPrivate,
1379 const Name &namePublic,
1380 const ClientId &explicitOwnerPublic,
1381 const PolicySerializable &policyPrivate,
1382 const PolicySerializable &policyPublic)
1384 auto &handlerPriv = selectDatabase(cred, explicitOwnerPrivate);
1385 auto &handlerPub = selectDatabase(cred, explicitOwnerPublic);
1387 AlgoType keyType = AlgoType::RSA_GEN;
1389 if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1390 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1392 const auto dtIt = ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.find(keyType);
1393 if (dtIt == ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.end())
1394 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1395 const DataTypePair& dt = dtIt->second;
1397 if (policyPrivate.backend != policyPublic.backend)
1398 ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend.");
1400 // use client id if not explicitly provided
1401 const ClientId &ownerPrv = explicitOwnerPrivate.empty() ? cred.client :
1402 explicitOwnerPrivate;
1404 if (m_accessControl.isSystemService(cred) &&
1405 ownerPrv.compare(CLIENT_ID_SYSTEM) != 0)
1406 return CKM_API_ERROR_INPUT_PARAM;
1408 const ClientId &ownerPub = explicitOwnerPublic.empty() ? cred.client :
1409 explicitOwnerPublic;
1411 if (m_accessControl.isSystemService(cred) &&
1412 ownerPub.compare(CLIENT_ID_SYSTEM) != 0)
1413 return CKM_API_ERROR_INPUT_PARAM;
1415 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1416 Policy lessRestricted(Password(), exportable, policyPrivate.backend);
1418 TokenPair keys = m_decider.getStore(policyPrivate, dt.first, dt.second).generateAKey(keyGenParams,
1419 policyPrivate.password,
1420 policyPublic.password);
1422 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1423 // in case the same database is used for private and public - the second
1424 // transaction will not be executed
1425 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1428 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerPrv);
1430 if (CKM_API_SUCCESS != retCode)
1433 retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerPub);
1435 if (CKM_API_SUCCESS != retCode)
1439 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerPrv,
1440 static_cast<int>(policyPrivate.extractable));
1441 handlerPriv.crypto.encryptRow(rowPrv);
1442 handlerPriv.database.saveRow(rowPrv);
1444 DB::Row rowPub(std::move(keys.second), namePublic, ownerPub,
1445 static_cast<int>(policyPublic.extractable));
1446 handlerPub.crypto.encryptRow(rowPub);
1447 handlerPub.database.saveRow(rowPub);
1449 transactionPub.commit();
1450 transactionPriv.commit();
1451 return CKM_API_SUCCESS;
1454 RawBuffer CKMLogic::createKeyPair(
1455 const Credentials &cred,
1457 const CryptoAlgorithmSerializable &keyGenParams,
1458 const Name &namePrivate,
1459 const ClientId &explicitOwnerPrivate,
1460 const Name &namePublic,
1461 const ClientId &explicitOwnerPublic,
1462 const PolicySerializable &policyPrivate,
1463 const PolicySerializable &policyPublic)
1465 int retCode = CKM_API_SUCCESS;
1468 retCode = createKeyPairHelper(
1472 explicitOwnerPrivate,
1474 explicitOwnerPublic,
1477 } catch (const Exc::Exception &e) {
1478 retCode = e.error();
1479 } catch (const CKM::Exception &e) {
1480 LogError("CKM::Exception: " << e.GetMessage());
1481 retCode = CKM_API_ERROR_SERVER_ERROR;
1484 return SerializeMessage(msgId, retCode);
1487 RawBuffer CKMLogic::createKeyAES(
1488 const Credentials &cred,
1492 const ClientId &explicitOwner,
1493 const PolicySerializable &policy)
1495 int retCode = CKM_API_SUCCESS;
1498 retCode = createKeyAESHelper(cred, size, name, explicitOwner, policy);
1499 } catch (const Exc::Exception &e) {
1500 retCode = e.error();
1501 } catch (std::invalid_argument &e) {
1502 LogDebug("invalid argument error: " << e.what());
1503 retCode = CKM_API_ERROR_INPUT_PARAM;
1504 } catch (const CKM::Exception &e) {
1505 LogError("CKM::Exception: " << e.GetMessage());
1506 retCode = CKM_API_ERROR_SERVER_ERROR;
1509 return SerializeMessage(msgId, retCode);
1512 int CKMLogic::readCertificateHelper(
1513 const Credentials &cred,
1514 const OwnerNameVector &ownerNameVector,
1515 CertificateImplVector &certVector)
1517 for (auto &i : ownerNameVector) {
1518 // certificates can't be protected with custom user password
1519 Crypto::GObjUPtr obj;
1521 ec = readDataHelper(true,
1523 DataType::CERTIFICATE,
1529 if (ec != CKM_API_SUCCESS)
1532 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1534 // try to read chain certificates (if present)
1535 Crypto::GObjUPtrVector caChainObjs;
1536 ec = readDataHelper(true,
1538 DataType::DB_CHAIN_FIRST,
1544 if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1547 for (auto &caCertObj : caChainObjs)
1548 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1551 return CKM_API_SUCCESS;
1554 int CKMLogic::getCertificateChainHelper(
1555 const CertificateImpl &cert,
1556 const RawBufferVector &untrustedCertificates,
1557 const RawBufferVector &trustedCertificates,
1558 bool useTrustedSystemCertificates,
1559 RawBufferVector &chainRawVector)
1561 CertificateImplVector untrustedCertVector;
1562 CertificateImplVector trustedCertVector;
1563 CertificateImplVector chainVector;
1566 return CKM_API_ERROR_INPUT_PARAM;
1568 for (auto &e : untrustedCertificates) {
1569 CertificateImpl c(e, DataFormat::FORM_DER);
1572 return CKM_API_ERROR_INPUT_PARAM;
1574 untrustedCertVector.push_back(std::move(c));
1577 for (auto &e : trustedCertificates) {
1578 CertificateImpl c(e, DataFormat::FORM_DER);
1581 return CKM_API_ERROR_INPUT_PARAM;
1583 trustedCertVector.push_back(std::move(c));
1586 CertificateStore store;
1587 int retCode = store.verifyCertificate(cert,
1588 untrustedCertVector,
1590 useTrustedSystemCertificates,
1591 m_accessControl.isCCMode(),
1594 if (retCode != CKM_API_SUCCESS)
1597 for (auto &e : chainVector)
1598 chainRawVector.push_back(e.getDER());
1600 return CKM_API_SUCCESS;
1603 int CKMLogic::getCertificateChainHelper(
1604 const Credentials &cred,
1605 const CertificateImpl &cert,
1606 const OwnerNameVector &untrusted,
1607 const OwnerNameVector &trusted,
1608 bool useTrustedSystemCertificates,
1609 RawBufferVector &chainRawVector)
1611 CertificateImplVector untrustedCertVector;
1612 CertificateImplVector trustedCertVector;
1613 CertificateImplVector chainVector;
1616 return CKM_API_ERROR_INPUT_PARAM;
1618 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1620 if (retCode != CKM_API_SUCCESS)
1623 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1625 if (retCode != CKM_API_SUCCESS)
1628 CertificateStore store;
1629 retCode = store.verifyCertificate(cert,
1630 untrustedCertVector,
1632 useTrustedSystemCertificates,
1633 m_accessControl.isCCMode(),
1636 if (retCode != CKM_API_SUCCESS)
1639 for (auto &i : chainVector)
1640 chainRawVector.push_back(i.getDER());
1642 return CKM_API_SUCCESS;
1645 RawBuffer CKMLogic::getCertificateChain(
1646 const Credentials & /*cred*/,
1648 const RawBuffer &certificate,
1649 const RawBufferVector &untrustedCertificates,
1650 const RawBufferVector &trustedCertificates,
1651 bool useTrustedSystemCertificates)
1653 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1654 RawBufferVector chainRawVector;
1655 int retCode = CKM_API_ERROR_UNKNOWN;
1658 retCode = getCertificateChainHelper(cert,
1659 untrustedCertificates,
1660 trustedCertificates,
1661 useTrustedSystemCertificates,
1663 } catch (const Exc::Exception &e) {
1664 retCode = e.error();
1665 } catch (const std::exception &e) {
1666 LogError("STD exception " << e.what());
1667 retCode = CKM_API_ERROR_SERVER_ERROR;
1669 LogError("Unknown error.");
1672 return SerializeMessage(msgId, retCode, chainRawVector);
1675 RawBuffer CKMLogic::getCertificateChain(
1676 const Credentials &cred,
1678 const RawBuffer &certificate,
1679 const OwnerNameVector &untrustedCertificates,
1680 const OwnerNameVector &trustedCertificates,
1681 bool useTrustedSystemCertificates)
1683 int retCode = CKM_API_ERROR_UNKNOWN;
1684 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1685 RawBufferVector chainRawVector;
1688 retCode = getCertificateChainHelper(cred,
1690 untrustedCertificates,
1691 trustedCertificates,
1692 useTrustedSystemCertificates,
1694 } catch (const Exc::Exception &e) {
1695 retCode = e.error();
1696 } catch (const std::exception &e) {
1697 LogError("STD exception " << e.what());
1698 retCode = CKM_API_ERROR_SERVER_ERROR;
1700 LogError("Unknown error.");
1703 return SerializeMessage(msgId, retCode, chainRawVector);
1706 RawBuffer CKMLogic::createSignature(
1707 const Credentials &cred,
1709 const Name &privateKeyName,
1710 const ClientId &explicitOwner,
1711 const Password &password, // password for private_key
1712 const RawBuffer &message,
1713 const CryptoAlgorithm &cryptoAlg)
1715 RawBuffer signature;
1717 int retCode = CKM_API_SUCCESS;
1720 Crypto::GObjUPtr obj;
1721 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
1722 explicitOwner, password, obj);
1724 if (retCode == CKM_API_SUCCESS)
1725 signature = obj->sign(cryptoAlg, message);
1726 } catch (const Exc::Exception &e) {
1727 retCode = e.error();
1728 } catch (const CKM::Exception &e) {
1729 LogError("Unknown CKM::Exception: " << e.GetMessage());
1730 retCode = CKM_API_ERROR_SERVER_ERROR;
1731 } catch (const std::exception &e) {
1732 LogError("STD exception " << e.what());
1733 retCode = CKM_API_ERROR_SERVER_ERROR;
1736 return SerializeMessage(msgId, retCode, signature);
1739 RawBuffer CKMLogic::verifySignature(
1740 const Credentials &cred,
1742 const Name &publicKeyOrCertName,
1743 const ClientId &explicitOwner,
1744 const Password &password, // password for public_key (optional)
1745 const RawBuffer &message,
1746 const RawBuffer &signature,
1747 const CryptoAlgorithm ¶ms)
1749 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1752 // try certificate first - looking for a public key.
1753 // in case of PKCS, pub key from certificate will be found first
1754 // rather than private key from the same PKCS.
1755 Crypto::GObjUPtr obj;
1756 retCode = readDataHelper(false, cred, DataType::CERTIFICATE,
1757 publicKeyOrCertName, explicitOwner, password, obj);
1759 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1760 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
1761 publicKeyOrCertName, explicitOwner, password, obj);
1763 if (retCode == CKM_API_SUCCESS)
1764 retCode = obj->verify(params, message, signature);
1765 } catch (const Exc::Exception &e) {
1766 retCode = e.error();
1767 } catch (const CKM::Exception &e) {
1768 LogError("Unknown CKM::Exception: " << e.GetMessage());
1769 retCode = CKM_API_ERROR_SERVER_ERROR;
1772 return SerializeMessage(msgId, retCode);
1775 int CKMLogic::setPermissionHelper(
1776 const Credentials &cred, // who's the client
1778 const ClientId &explicitOwner, // who's the owner
1779 const ClientId &accessor, // who will get the access
1780 const PermissionMask permissionMask)
1782 auto &handler = selectDatabase(cred, explicitOwner);
1784 // we don't know the client
1785 if (cred.client.empty() || !isClientValid(cred.client))
1786 return CKM_API_ERROR_INPUT_PARAM;
1788 // use client id if not explicitly provided
1789 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1791 // verify name and owner are correct
1792 if (!isNameValid(name) || !isClientValid(owner) ||
1793 !isClientValid(accessor))
1794 return CKM_API_ERROR_INPUT_PARAM;
1796 // currently we don't support modification of owner's permissions to his own rows
1797 if (owner == accessor)
1798 return CKM_API_ERROR_INPUT_PARAM;
1800 // system database does not support write/remove permissions
1801 if ((0 == owner.compare(CLIENT_ID_SYSTEM)) &&
1802 (permissionMask & Permission::REMOVE))
1803 return CKM_API_ERROR_INPUT_PARAM;
1805 // can the client modify permissions to owner's row?
1806 int retCode = m_accessControl.canModify(cred, owner);
1808 if (retCode != CKM_API_SUCCESS)
1811 DB::Crypto::Transaction transaction(&handler.database);
1813 if (!handler.database.isNameOwnerPresent(name, owner))
1814 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1816 // set permissions to the row owned by owner for accessor
1817 handler.database.setPermission(name, owner, accessor, permissionMask);
1818 transaction.commit();
1820 return CKM_API_SUCCESS;
1823 RawBuffer CKMLogic::setPermission(
1824 const Credentials &cred,
1827 const ClientId &explicitOwner,
1828 const ClientId &accessor,
1829 const PermissionMask permissionMask)
1834 retCode = setPermissionHelper(cred, name, explicitOwner, accessor, permissionMask);
1835 } catch (const Exc::Exception &e) {
1836 retCode = e.error();
1837 } catch (const CKM::Exception &e) {
1838 LogError("Error: " << e.GetMessage());
1839 retCode = CKM_API_ERROR_DB_ERROR;
1842 return SerializeMessage(msgID, retCode);