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
72 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
73 const uid_t CKMLogic::ADMIN_USER_DB_UID = 5001;
77 CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
79 m_accessControl.updateCCMode();
82 CKMLogic::~CKMLogic() {}
84 void CKMLogic::loadDKEKFile(uid_t user, const Password &password)
86 auto &handle = m_userDataMap[user];
90 auto wrappedDKEK = fs.getDKEK();
92 if (wrappedDKEK.empty()) {
93 wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
94 fs.saveDKEK(wrappedDKEK);
97 handle.keyProvider = KeyProvider(wrappedDKEK, password);
100 void CKMLogic::saveDKEKFile(uid_t user, const Password &password)
102 auto &handle = m_userDataMap[user];
105 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
108 void CKMLogic::migrateSecureStorageData(bool isAdminUser)
110 SsMigration::migrate(isAdminUser, [this](const std::string &name,
111 const Crypto::Data &data,
112 bool adminUserFlag) {
113 LogInfo("Migrate data called with name: " << name);
114 auto ownerId = adminUserFlag ? CLIENT_ID_ADMIN_USER : CLIENT_ID_SYSTEM;
115 auto uid = adminUserFlag ? ADMIN_USER_DB_UID : SYSTEM_DB_UID;
117 int ret = verifyAndSaveDataHelper(Credentials(uid, ownerId), name, ownerId, data,
118 PolicySerializable());
120 if (ret == CKM_API_ERROR_DB_ALIAS_EXISTS)
121 LogWarning("Alias already exist for migrated name: " << name);
122 else if (ret != CKM_API_SUCCESS)
123 LogError("Failed to migrate secure-storage data. name: " << name <<
128 int CKMLogic::unlockDatabase(uid_t user, const Password &password)
130 if (0 < m_userDataMap.count(user) &&
131 m_userDataMap[user].keyProvider.isInitialized())
132 return CKM_API_SUCCESS;
134 int retCode = CKM_API_SUCCESS;
137 auto &handle = m_userDataMap[user];
140 loadDKEKFile(user, password);
142 auto wrappedDatabaseDEK = fs.getDBDEK();
144 if (wrappedDatabaseDEK.empty()) {
145 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
146 fs.saveDBDEK(wrappedDatabaseDEK);
149 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
151 handle.database = DB::Crypto(fs.getLegacyDBPath(), fs.getDBPath(), key);
152 handle.crypto = CryptoLogic();
154 if (!m_accessControl.isSystemService(user)) {
155 // remove data of removed apps during locked state
156 ClientIdVector removedApps = fs.clearRemovedsApps();
158 for (auto &app : removedApps) {
159 handle.crypto.removeKey(app);
160 handle.database.deleteKey(app);
164 if (user == SYSTEM_DB_UID && SsMigration::hasData())
165 migrateSecureStorageData(false);
166 else if (user == ADMIN_USER_DB_UID && SsMigration::hasData())
167 migrateSecureStorageData(true);
168 } catch (const Exc::Exception &e) {
170 } catch (const CKM::Exception &e) {
171 LogError("CKM::Exception: " << e.GetMessage());
172 retCode = CKM_API_ERROR_SERVER_ERROR;
175 if (CKM_API_SUCCESS != retCode)
176 m_userDataMap.erase(user);
181 int CKMLogic::unlockSystemDB()
183 return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
186 UserData &CKMLogic::selectDatabase(const Credentials &cred,
187 const ClientId &explicitOwner)
189 // if user trying to access system service - check:
190 // * if user database is unlocked [mandatory]
191 // * if not - proceed with regular user database
192 // * if explicit system database owner given -> switch to system DB
193 if (!m_accessControl.isSystemService(cred)) {
194 if (0 == m_userDataMap.count(cred.clientUid))
195 ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
197 if (0 != explicitOwner.compare(CLIENT_ID_SYSTEM))
198 return m_userDataMap[cred.clientUid];
201 // system database selected, modify the owner id
202 if (CKM_API_SUCCESS != unlockSystemDB())
203 ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
205 return m_userDataMap[SYSTEM_DB_UID];
208 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
210 int retCode = CKM_API_SUCCESS;
212 if (!m_accessControl.isSystemService(user))
213 retCode = unlockDatabase(user, password);
214 else // do not allow lock/unlock operations for system users
215 retCode = CKM_API_ERROR_INPUT_PARAM;
217 return MessageBuffer::Serialize(retCode).Pop();
220 RawBuffer CKMLogic::updateCCMode()
222 m_accessControl.updateCCMode();
223 return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
226 RawBuffer CKMLogic::lockUserKey(uid_t user)
228 int retCode = CKM_API_SUCCESS;
230 if (!m_accessControl.isSystemService(user))
231 m_userDataMap.erase(user);
232 else // do not allow lock/unlock operations for system users
233 retCode = CKM_API_ERROR_INPUT_PARAM;
235 return MessageBuffer::Serialize(retCode).Pop();
238 RawBuffer CKMLogic::removeUserData(uid_t user)
240 if (m_accessControl.isSystemService(user))
241 user = SYSTEM_DB_UID;
243 m_userDataMap.erase(user);
245 const int retCode = FileSystem(user).removeUserData()
246 ? CKM_API_ERROR_FILE_SYSTEM
249 return MessageBuffer::Serialize(retCode).Pop();
252 int CKMLogic::changeUserPasswordHelper(uid_t user,
253 const Password &oldPassword,
254 const Password &newPassword)
256 // do not allow to change system database password
257 if (m_accessControl.isSystemService(user))
258 return CKM_API_ERROR_INPUT_PARAM;
260 loadDKEKFile(user, oldPassword);
261 saveDKEKFile(user, newPassword);
263 return CKM_API_SUCCESS;
266 RawBuffer CKMLogic::changeUserPassword(
268 const Password &oldPassword,
269 const Password &newPassword)
271 int retCode = CKM_API_SUCCESS;
274 retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
275 } catch (const Exc::Exception &e) {
277 } catch (const CKM::Exception &e) {
278 LogError("CKM::Exception: " << e.GetMessage());
279 retCode = CKM_API_ERROR_SERVER_ERROR;
282 return MessageBuffer::Serialize(retCode).Pop();
285 int CKMLogic::resetUserPasswordHelper(
287 const Password &newPassword)
289 // do not allow to reset system database password
290 if (m_accessControl.isSystemService(user))
291 return CKM_API_ERROR_INPUT_PARAM;
293 int retCode = CKM_API_SUCCESS;
295 if (0 == m_userDataMap.count(user)) {
296 // Check if key exists. If exists we must return error
298 auto wrappedDKEKMain = fs.getDKEK();
300 if (!wrappedDKEKMain.empty())
301 retCode = CKM_API_ERROR_BAD_REQUEST;
303 saveDKEKFile(user, newPassword);
309 RawBuffer CKMLogic::resetUserPassword(
311 const Password &newPassword)
313 int retCode = CKM_API_SUCCESS;
316 retCode = resetUserPasswordHelper(user, newPassword);
317 } catch (const Exc::Exception &e) {
319 } catch (const CKM::Exception &e) {
320 LogError("CKM::Exception: " << e.GetMessage());
321 retCode = CKM_API_ERROR_SERVER_ERROR;
324 return MessageBuffer::Serialize(retCode).Pop();
327 RawBuffer CKMLogic::removeApplicationData(const ClientId &owner)
329 int retCode = CKM_API_SUCCESS;
333 retCode = CKM_API_ERROR_INPUT_PARAM;
335 UidVector uids = FileSystem::getUIDsFromDBFile();
337 for (auto userId : uids) {
338 if (0 == m_userDataMap.count(userId)) {
339 FileSystem fs(userId);
340 fs.addRemovedApp(owner);
342 auto &handle = m_userDataMap[userId];
343 handle.crypto.removeKey(owner);
344 handle.database.deleteKey(owner);
348 } catch (const Exc::Exception &e) {
350 } catch (const CKM::Exception &e) {
351 LogError("CKM::Exception: " << e.GetMessage());
352 retCode = CKM_API_ERROR_SERVER_ERROR;
355 return MessageBuffer::Serialize(retCode).Pop();
358 int CKMLogic::checkSaveConditions(
359 const Credentials &accessorCred,
362 const ClientId &owner)
364 // verify name and client are correct
365 if (!isNameValid(name) || !isClientValid(owner)) {
366 LogDebug("Invalid parameter passed to key-manager");
367 return CKM_API_ERROR_INPUT_PARAM;
370 // check if accessor is allowed to save owner's items
371 int access_ec = m_accessControl.canSave(accessorCred, owner);
373 if (access_ec != CKM_API_SUCCESS) {
374 LogDebug("accessor " << accessorCred.client << " can not save rows owned by " <<
379 // check if not a duplicate
380 if (handler.database.isNameOwnerPresent(name, owner))
381 return CKM_API_ERROR_DB_ALIAS_EXISTS;
383 // encryption section
384 if (!handler.crypto.haveKey(owner)) {
386 auto key_optional = handler.database.getKey(owner);
389 LogDebug("No Key in database found. Generating new one for client: " <<
391 got_key = handler.keyProvider.generateDEK(owner);
392 handler.database.saveKey(owner, got_key);
394 LogDebug("Key from DB");
395 got_key = *key_optional;
398 got_key = handler.keyProvider.getPureDEK(got_key);
399 handler.crypto.pushKey(owner, got_key);
402 return CKM_API_SUCCESS;
405 DB::Row CKMLogic::createEncryptedRow(
408 const ClientId &owner,
409 const Crypto::Data &data,
410 const Policy &policy)
412 Crypto::GStore &store = m_decider.getStore(data.type, policy);
414 // do not encrypt data with password during cc_mode on
415 Token token = store.import(data,
416 m_accessControl.isCCMode() ? "" : policy.password,
417 Crypto::EncryptionParams());
418 DB::Row row(std::move(token), name, owner,
419 static_cast<int>(policy.extractable));
420 crypto.encryptRow(row);
424 int CKMLogic::verifyBinaryData(Crypto::Data &input) const
427 return toBinaryData(input, dummy);
430 int CKMLogic::toBinaryData(const Crypto::Data &input,
431 Crypto::Data &output) const
433 // verify the data integrity
434 if (input.type.isKey()) {
437 if (input.type.isSKey())
438 output_key = CKM::Key::createAES(input.data);
440 output_key = CKM::Key::create(input.data);
442 if (output_key.get() == NULL) {
443 LogDebug("provided binary data is not valid key data");
444 return CKM_API_ERROR_INPUT_PARAM;
447 output = std::move(Crypto::Data(input.type, output_key->getDER()));
448 } else if (input.type.isCertificate() || input.type.isChainCert()) {
449 CertificateShPtr cert = CKM::Certificate::create(input.data,
450 DataFormat::FORM_DER);
452 if (cert.get() == NULL) {
453 LogDebug("provided binary data is not valid certificate data");
454 return CKM_API_ERROR_INPUT_PARAM;
457 output = std::move(Crypto::Data(input.type, cert->getDER()));
462 // TODO: add here BINARY_DATA verification, i.e: max size etc.
463 return CKM_API_SUCCESS;
466 int CKMLogic::verifyAndSaveDataHelper(
467 const Credentials &cred,
469 const ClientId &explicitOwner,
470 const Crypto::Data &data,
471 const PolicySerializable &policy)
473 int retCode = CKM_API_ERROR_UNKNOWN;
476 // check if data is correct
477 Crypto::Data binaryData;
478 retCode = toBinaryData(data, binaryData);
480 if (retCode != CKM_API_SUCCESS)
483 return saveDataHelper(cred, name, explicitOwner, binaryData, policy);
484 } catch (const Exc::Exception &e) {
486 } catch (const CKM::Exception &e) {
487 LogError("CKM::Exception: " << e.GetMessage());
488 return CKM_API_ERROR_SERVER_ERROR;
492 int CKMLogic::getKeyForService(
493 const Credentials &cred,
495 const ClientId &explicitOwner,
496 const Password &pass,
497 Crypto::GObjShPtr &key)
500 // Key is for internal service use. It won't be exported to the client
501 Crypto::GObjUPtr obj;
502 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
505 if (retCode == CKM_API_SUCCESS)
506 key = std::move(obj);
509 } catch (const Exc::Exception &e) {
511 } catch (const CKM::Exception &e) {
512 LogError("CKM::Exception: " << e.GetMessage());
513 return CKM_API_ERROR_SERVER_ERROR;
517 RawBuffer CKMLogic::saveData(
518 const Credentials &cred,
521 const ClientId &explicitOwner,
522 const Crypto::Data &data,
523 const PolicySerializable &policy)
525 int retCode = verifyAndSaveDataHelper(cred, name, explicitOwner, data, policy);
526 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
529 static_cast<int>(data.type));
530 return response.Pop();
533 int CKMLogic::extractPKCS12Data(
536 const ClientId &owner,
537 const PKCS12Serializable &pkcs,
538 const PolicySerializable &keyPolicy,
539 const PolicySerializable &certPolicy,
540 DB::RowVector &output)
542 // private key is mandatory
543 auto key = pkcs.getKey();
546 LogError("Failed to get private key from pkcs");
547 return CKM_API_ERROR_INVALID_FORMAT;
550 Crypto::Data keyData(DataType(key->getType()), key->getDER());
551 int retCode = verifyBinaryData(keyData);
553 if (retCode != CKM_API_SUCCESS)
556 output.push_back(createEncryptedRow(crypto, name, owner, keyData,
559 // certificate is mandatory
560 auto cert = pkcs.getCertificate();
563 LogError("Failed to get certificate from pkcs");
564 return CKM_API_ERROR_INVALID_FORMAT;
567 Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
568 retCode = verifyBinaryData(certData);
570 if (retCode != CKM_API_SUCCESS)
573 output.push_back(createEncryptedRow(crypto, name, owner, certData,
577 unsigned int cert_index = 0;
579 for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
580 Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++),
582 int retCode = verifyBinaryData(caCertData);
584 if (retCode != CKM_API_SUCCESS)
587 output.push_back(createEncryptedRow(crypto, name, owner, caCertData,
591 return CKM_API_SUCCESS;
594 RawBuffer CKMLogic::savePKCS12(
595 const Credentials &cred,
598 const ClientId &explicitOwner,
599 const PKCS12Serializable &pkcs,
600 const PolicySerializable &keyPolicy,
601 const PolicySerializable &certPolicy)
603 int retCode = CKM_API_ERROR_UNKNOWN;
606 retCode = saveDataHelper(cred, name, explicitOwner, pkcs, keyPolicy, certPolicy);
607 } catch (const Exc::Exception &e) {
609 } catch (const CKM::Exception &e) {
610 LogError("CKM::Exception: " << e.GetMessage());
611 retCode = CKM_API_ERROR_SERVER_ERROR;
614 auto response = MessageBuffer::Serialize(static_cast<int>
615 (LogicCommand::SAVE_PKCS12),
618 return response.Pop();
622 int CKMLogic::removeDataHelper(
623 const Credentials &cred,
625 const ClientId &explicitOwner)
627 auto &handler = selectDatabase(cred, explicitOwner);
629 // use client id if not explicitly provided
630 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
632 if (!isNameValid(name) || !isClientValid(owner)) {
633 LogDebug("Invalid owner or name format");
634 return CKM_API_ERROR_INPUT_PARAM;
637 DB::Crypto::Transaction transaction(&handler.database);
639 // read and check permissions
640 PermissionMaskOptional permissionRowOpt =
641 handler.database.getPermissionRow(name, owner, cred.client);
642 int retCode = m_accessControl.canDelete(cred,
643 toPermissionMask(permissionRowOpt));
645 if (retCode != CKM_API_SUCCESS) {
646 LogWarning("access control check result: " << retCode);
650 // get all matching rows
652 handler.database.getRows(name, owner, DataType::DB_FIRST,
653 DataType::DB_LAST, rows);
656 LogDebug("No row for given name and owner");
657 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
660 // load app key if needed
661 retCode = loadAppKey(handler, rows.front().owner);
663 if (CKM_API_SUCCESS != retCode)
666 // destroy it in store
667 for (auto &r : rows) {
669 handler.crypto.decryptRow(Password(), r);
670 m_decider.getStore(r).destroy(r);
671 } catch (const Exc::AuthenticationFailed &) {
672 LogDebug("Authentication failed when removing data. Ignored.");
677 handler.database.deleteRow(name, owner);
678 transaction.commit();
680 return CKM_API_SUCCESS;
683 RawBuffer CKMLogic::removeData(
684 const Credentials &cred,
687 const ClientId &explicitOwner)
689 int retCode = CKM_API_ERROR_UNKNOWN;
692 retCode = removeDataHelper(cred, name, explicitOwner);
693 } catch (const Exc::Exception &e) {
695 } catch (const CKM::Exception &e) {
696 LogError("Error: " << e.GetMessage());
697 retCode = CKM_API_ERROR_DB_ERROR;
700 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
703 return response.Pop();
706 int CKMLogic::readSingleRow(const Name &name,
707 const ClientId &owner,
709 DB::Crypto &database,
712 DB::Crypto::RowOptional row_optional;
714 if (dataType.isKey()) {
715 // read all key types
716 row_optional = database.getRow(name,
718 DataType::DB_KEY_FIRST,
719 DataType::DB_KEY_LAST);
721 // read anything else
722 row_optional = database.getRow(name,
728 LogDebug("No row for given name, owner and type");
729 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
734 return CKM_API_SUCCESS;
738 int CKMLogic::readMultiRow(const Name &name,
739 const ClientId &owner,
741 DB::Crypto &database,
742 DB::RowVector &output)
744 if (dataType.isKey())
745 // read all key types
746 database.getRows(name,
748 DataType::DB_KEY_FIRST,
749 DataType::DB_KEY_LAST,
751 else if (dataType.isChainCert())
752 // read all key types
753 database.getRows(name,
755 DataType::DB_CHAIN_FIRST,
756 DataType::DB_CHAIN_LAST,
759 // read anything else
760 database.getRows(name,
765 if (!output.size()) {
766 LogDebug("No row for given name, owner and type");
767 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
770 return CKM_API_SUCCESS;
773 int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred,
775 const ClientId &owner,
778 DB::Crypto &database)
780 PermissionMaskOptional permissionRowOpt =
781 database.getPermissionRow(name, owner, accessorCred.client);
784 return m_accessControl.canExport(accessorCred,
786 toPermissionMask(permissionRowOpt));
788 return m_accessControl.canRead(accessorCred,
789 toPermissionMask(permissionRowOpt));
792 Crypto::GObjUPtr CKMLogic::rowToObject(
795 const Password &password)
797 Crypto::GStore &store = m_decider.getStore(row);
799 Password pass = m_accessControl.isCCMode() ? "" : password;
802 Crypto::GObjUPtr obj;
804 if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
805 CryptoLogic::ENCRYPTION_V2) {
806 handler.crypto.decryptRow(Password(), row);
808 obj = store.getObject(row, pass);
810 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
811 handler.crypto.decryptRow(pass, row);
812 // destroy it in store
815 // import it to store with new scheme: data -> pass(data)
816 Token token = store.import(Crypto::Data(row.dataType, row.data), pass, Crypto::EncryptionParams());
818 // get it from the store (it can be different than the data we imported into store)
819 obj = store.getObject(token, pass);
821 // update row with new token
822 *static_cast<Token *>(&row) = std::move(token);
824 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
825 handler.crypto.encryptRow(row);
828 handler.database.updateRow(row);
834 int CKMLogic::readDataHelper(
836 const Credentials &cred,
839 const ClientId &explicitOwner,
840 const Password &password,
841 Crypto::GObjUPtrVector &objs)
843 auto &handler = selectDatabase(cred, explicitOwner);
845 // use client id if not explicitly provided
846 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
848 if (!isNameValid(name) || !isClientValid(owner))
849 return CKM_API_ERROR_INPUT_PARAM;
852 DB::Crypto::Transaction transaction(&handler.database);
854 int retCode = readMultiRow(name, owner, dataType, handler.database, rows);
856 if (CKM_API_SUCCESS != retCode)
859 // all read rows belong to the same owner
860 DB::Row &firstRow = rows.at(0);
862 // check access rights
863 retCode = checkDataPermissionsHelper(cred, name, owner, firstRow,
864 exportFlag, handler.database);
866 if (CKM_API_SUCCESS != retCode)
869 // load app key if needed
870 retCode = loadAppKey(handler, firstRow.owner);
872 if (CKM_API_SUCCESS != retCode)
876 for (auto &row : rows)
877 objs.push_back(rowToObject(handler, std::move(row), password));
879 // rowToObject may modify db
880 transaction.commit();
882 return CKM_API_SUCCESS;
885 int CKMLogic::readDataHelper(
887 const Credentials &cred,
890 const ClientId &explicitOwner,
891 const Password &password,
892 Crypto::GObjUPtr &obj)
894 DataType objDataType;
895 return readDataHelper(exportFlag, cred, dataType, name, explicitOwner,
896 password, obj, objDataType);
899 int CKMLogic::readDataHelper(
901 const Credentials &cred,
904 const ClientId &explicitOwner,
905 const Password &password,
906 Crypto::GObjUPtr &obj,
907 DataType &objDataType)
909 auto &handler = selectDatabase(cred, explicitOwner);
911 // use client id if not explicitly provided
912 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
914 if (!isNameValid(name) || !isClientValid(owner))
915 return CKM_API_ERROR_INPUT_PARAM;
918 DB::Crypto::Transaction transaction(&handler.database);
920 int retCode = readSingleRow(name, owner, dataType, handler.database, row);
922 if (CKM_API_SUCCESS != retCode)
925 objDataType = row.dataType;
927 // check access rights
928 retCode = checkDataPermissionsHelper(cred, name, owner, row, exportFlag,
931 if (CKM_API_SUCCESS != retCode)
934 // load app key if needed
935 retCode = loadAppKey(handler, row.owner);
937 if (CKM_API_SUCCESS != retCode)
940 obj = rowToObject(handler, std::move(row), password);
941 // rowToObject may modify db
942 transaction.commit();
944 return CKM_API_SUCCESS;
947 RawBuffer CKMLogic::getData(
948 const Credentials &cred,
952 const ClientId &explicitOwner,
953 const Password &password)
955 int retCode = CKM_API_SUCCESS;
957 DataType objDataType;
960 Crypto::GObjUPtr obj;
961 retCode = readDataHelper(true, cred, dataType, name, explicitOwner,
962 password, obj, objDataType);
964 if (retCode == CKM_API_SUCCESS)
965 rowData = obj->getBinary();
966 } catch (const Exc::Exception &e) {
968 } catch (const CKM::Exception &e) {
969 LogError("CKM::Exception: " << e.GetMessage());
970 retCode = CKM_API_ERROR_SERVER_ERROR;
973 if (CKM_API_SUCCESS != retCode)
976 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
979 static_cast<int>(objDataType),
981 return response.Pop();
984 RawBuffer CKMLogic::getDataProtectionStatus(
985 const Credentials &cred,
989 const ClientId &explicitOwner)
991 int retCode = CKM_API_SUCCESS;
993 DataType objDataType;
997 Crypto::GObjUPtr obj;
998 retCode = readDataHelper(false, cred, dataType, name, explicitOwner,
999 password, obj, objDataType);
1001 } catch (const Exc::Exception &e) {
1002 retCode = e.error();
1003 } catch (const CKM::Exception &e) {
1004 LogError("CKM::Exception: " << e.GetMessage());
1005 retCode = CKM_API_ERROR_SERVER_ERROR;
1008 if (retCode == CKM_API_ERROR_AUTHENTICATION_FAILED) {
1010 retCode = CKM_API_SUCCESS;
1013 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PROTECTION_STATUS),
1016 static_cast<int>(objDataType),
1018 return response.Pop();
1021 int CKMLogic::getPKCS12Helper(
1022 const Credentials &cred,
1024 const ClientId &explicitOwner,
1025 const Password &keyPassword,
1026 const Password &certPassword,
1028 CertificateShPtr &cert,
1029 CertificateShPtrVector &caChain)
1033 // read private key (mandatory)
1034 Crypto::GObjUPtr keyObj;
1035 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
1036 keyPassword, keyObj);
1038 if (retCode != CKM_API_SUCCESS) {
1039 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1042 privKey = CKM::Key::create(keyObj->getBinary());
1045 // read certificate (mandatory)
1046 Crypto::GObjUPtr certObj;
1047 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, explicitOwner,
1048 certPassword, certObj);
1050 if (retCode != CKM_API_SUCCESS) {
1051 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1054 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
1057 // read CA cert chain (optional)
1058 Crypto::GObjUPtrVector caChainObjs;
1059 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, explicitOwner,
1060 certPassword, caChainObjs);
1062 if (retCode != CKM_API_SUCCESS && retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1063 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1066 for (auto &caCertObj : caChainObjs)
1067 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
1068 DataFormat::FORM_DER));
1071 // if anything found, return it
1072 if (privKey || cert || caChain.size() > 0)
1073 retCode = CKM_API_SUCCESS;
1078 RawBuffer CKMLogic::getPKCS12(
1079 const Credentials &cred,
1082 const ClientId &explicitOwner,
1083 const Password &keyPassword,
1084 const Password &certPassword)
1086 int retCode = CKM_API_ERROR_UNKNOWN;
1088 PKCS12Serializable output;
1092 CertificateShPtr cert;
1093 CertificateShPtrVector caChain;
1094 retCode = getPKCS12Helper(cred, name, explicitOwner, keyPassword,
1095 certPassword, privKey, cert, caChain);
1098 if (retCode == CKM_API_SUCCESS)
1099 output = PKCS12Serializable(std::move(privKey), std::move(cert),
1100 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 auto response = MessageBuffer::Serialize(static_cast<int>
1109 (LogicCommand::GET_PKCS12),
1113 return response.Pop();
1116 int CKMLogic::getDataListHelper(const Credentials &cred,
1117 const DataType dataType,
1118 OwnerNameVector &ownerNameVector)
1120 int retCode = CKM_API_ERROR_DB_LOCKED;
1122 if (0 < m_userDataMap.count(cred.clientUid)) {
1123 auto &database = m_userDataMap[cred.clientUid].database;
1126 OwnerNameVector tmpVector;
1128 if (dataType.isKey()) {
1129 // list all key types
1130 database.listNames(cred.client,
1132 DataType::DB_KEY_FIRST,
1133 DataType::DB_KEY_LAST);
1135 // list anything else
1136 database.listNames(cred.client,
1141 ownerNameVector.insert(ownerNameVector.end(), tmpVector.begin(),
1143 retCode = CKM_API_SUCCESS;
1144 } catch (const CKM::Exception &e) {
1145 LogError("Error: " << e.GetMessage());
1146 retCode = CKM_API_ERROR_DB_ERROR;
1147 } catch (const Exc::Exception &e) {
1148 retCode = e.error();
1155 RawBuffer CKMLogic::getDataList(
1156 const Credentials &cred,
1160 OwnerNameVector systemVector;
1161 OwnerNameVector userVector;
1162 OwnerNameVector ownerNameVector;
1164 int retCode = unlockSystemDB();
1166 if (CKM_API_SUCCESS == retCode) {
1168 if (m_accessControl.isSystemService(cred)) {
1170 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1175 // user - lookup system, then client DB
1176 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1182 if (retCode == CKM_API_SUCCESS) {
1183 retCode = getDataListHelper(cred,
1190 if (retCode == CKM_API_SUCCESS) {
1191 ownerNameVector.insert(ownerNameVector.end(), systemVector.begin(),
1192 systemVector.end());
1193 ownerNameVector.insert(ownerNameVector.end(), userVector.begin(),
1197 auto response = MessageBuffer::Serialize(static_cast<int>
1198 (LogicCommand::GET_LIST),
1201 static_cast<int>(dataType),
1203 return response.Pop();
1206 int CKMLogic::importInitialData(
1208 const Crypto::Data &data,
1209 const Crypto::EncryptionParams &encParams,
1210 const Policy &policy)
1213 if (encParams.iv.empty() != encParams.tag.empty()) {
1214 LogError("Both iv and tag must be empty or set");
1215 return CKM_API_ERROR_INPUT_PARAM;
1218 // Inital values are always imported with root credentials. Client id is not important.
1219 Credentials rootCred(0, "");
1221 auto &handler = selectDatabase(rootCred, CLIENT_ID_SYSTEM);
1223 // check if save is possible
1224 DB::Crypto::Transaction transaction(&handler.database);
1225 int retCode = checkSaveConditions(rootCred, handler, name, CLIENT_ID_SYSTEM);
1227 if (retCode != CKM_API_SUCCESS)
1230 Crypto::GStore &store =
1231 m_decider.getStore(data.type, policy, !encParams.iv.empty());
1235 if (encParams.iv.empty()) {
1236 // Data are not encrypted, let's try to verify them
1237 Crypto::Data binaryData;
1239 if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1242 token = store.import(binaryData,
1243 m_accessControl.isCCMode() ? "" : policy.password,
1246 token = store.import(data,
1247 m_accessControl.isCCMode() ? "" : policy.password,
1251 DB::Row row(std::move(token), name, CLIENT_ID_SYSTEM,
1252 static_cast<int>(policy.extractable));
1253 handler.crypto.encryptRow(row);
1255 handler.database.saveRow(row);
1256 transaction.commit();
1257 } catch (const Exc::Exception &e) {
1259 } catch (const CKM::Exception &e) {
1260 LogError("CKM::Exception: " << e.GetMessage());
1261 return CKM_API_ERROR_SERVER_ERROR;
1262 } catch (const std::exception &e) {
1263 LogError("Std::exception: " << e.what());
1264 return CKM_API_ERROR_SERVER_ERROR;
1267 return CKM_API_SUCCESS;
1270 int CKMLogic::saveDataHelper(
1271 const Credentials &cred,
1273 const ClientId &explicitOwner,
1274 const Crypto::Data &data,
1275 const PolicySerializable &policy)
1277 auto &handler = selectDatabase(cred, explicitOwner);
1279 // use client id if not explicitly provided
1280 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1282 if (m_accessControl.isSystemService(cred) &&
1283 owner.compare(CLIENT_ID_SYSTEM) != 0) {
1284 LogError("System services can only use " << CLIENT_ID_SYSTEM << " as owner id") ;
1285 return CKM_API_ERROR_INPUT_PARAM;
1288 // check if save is possible
1289 DB::Crypto::Transaction transaction(&handler.database);
1290 int retCode = checkSaveConditions(cred, handler, name, owner);
1292 if (retCode != CKM_API_SUCCESS)
1296 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, owner,
1298 handler.database.saveRow(encryptedRow);
1300 transaction.commit();
1301 return CKM_API_SUCCESS;
1304 int CKMLogic::saveDataHelper(
1305 const Credentials &cred,
1307 const ClientId &explicitOwner,
1308 const PKCS12Serializable &pkcs,
1309 const PolicySerializable &keyPolicy,
1310 const PolicySerializable &certPolicy)
1312 auto &handler = selectDatabase(cred, explicitOwner);
1314 // use client id if not explicitly provided
1315 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1317 if (m_accessControl.isSystemService(cred) &&
1318 owner.compare(CLIENT_ID_SYSTEM) != 0)
1319 return CKM_API_ERROR_INPUT_PARAM;
1321 // check if save is possible
1322 DB::Crypto::Transaction transaction(&handler.database);
1323 int retCode = checkSaveConditions(cred, handler, name, owner);
1325 if (retCode != CKM_API_SUCCESS)
1328 // extract and encrypt the data
1329 DB::RowVector encryptedRows;
1330 retCode = extractPKCS12Data(handler.crypto, name, owner, pkcs, keyPolicy,
1331 certPolicy, encryptedRows);
1333 if (retCode != CKM_API_SUCCESS)
1337 handler.database.saveRows(name, owner, encryptedRows);
1338 transaction.commit();
1340 return CKM_API_SUCCESS;
1344 int CKMLogic::createKeyAESHelper(
1345 const Credentials &cred,
1348 const ClientId &explicitOwner,
1349 const PolicySerializable &policy)
1351 auto &handler = selectDatabase(cred, explicitOwner);
1353 // use client id if not explicitly provided
1354 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1356 if (m_accessControl.isSystemService(cred) &&
1357 owner.compare(CLIENT_ID_SYSTEM) != 0)
1358 return CKM_API_ERROR_INPUT_PARAM;
1360 // check if save is possible
1361 DB::Crypto::Transaction transaction(&handler.database);
1362 int retCode = checkSaveConditions(cred, handler, name, owner);
1364 if (retCode != CKM_API_SUCCESS)
1367 // create key in store
1368 CryptoAlgorithm keyGenAlgorithm;
1369 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1370 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1371 Token key = m_decider.getStore(DataType::KEY_AES,
1372 policy).generateSKey(keyGenAlgorithm, policy.password);
1375 DB::Row row(std::move(key), name, owner,
1376 static_cast<int>(policy.extractable));
1377 handler.crypto.encryptRow(row);
1379 handler.database.saveRow(row);
1381 transaction.commit();
1382 return CKM_API_SUCCESS;
1385 int CKMLogic::createKeyPairHelper(
1386 const Credentials &cred,
1387 const CryptoAlgorithmSerializable &keyGenParams,
1388 const Name &namePrivate,
1389 const ClientId &explicitOwnerPrivate,
1390 const Name &namePublic,
1391 const ClientId &explicitOwnerPublic,
1392 const PolicySerializable &policyPrivate,
1393 const PolicySerializable &policyPublic)
1395 auto &handlerPriv = selectDatabase(cred, explicitOwnerPrivate);
1396 auto &handlerPub = selectDatabase(cred, explicitOwnerPublic);
1398 AlgoType keyType = AlgoType::RSA_GEN;
1400 if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1401 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1403 const auto dtIt = ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.find(keyType);
1404 if (dtIt == ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.end())
1405 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1406 const DataTypePair& dt = dtIt->second;
1408 if (policyPrivate.backend != policyPublic.backend)
1409 ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend.");
1411 // use client id if not explicitly provided
1412 const ClientId &ownerPrv = explicitOwnerPrivate.empty() ? cred.client :
1413 explicitOwnerPrivate;
1415 if (m_accessControl.isSystemService(cred) &&
1416 ownerPrv.compare(CLIENT_ID_SYSTEM) != 0)
1417 return CKM_API_ERROR_INPUT_PARAM;
1419 const ClientId &ownerPub = explicitOwnerPublic.empty() ? cred.client :
1420 explicitOwnerPublic;
1422 if (m_accessControl.isSystemService(cred) &&
1423 ownerPub.compare(CLIENT_ID_SYSTEM) != 0)
1424 return CKM_API_ERROR_INPUT_PARAM;
1426 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1427 Policy lessRestricted(Password(), exportable, policyPrivate.backend);
1429 TokenPair keys = m_decider.getStore(policyPrivate, dt.first, dt.second).generateAKey(keyGenParams,
1430 policyPrivate.password,
1431 policyPublic.password);
1433 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1434 // in case the same database is used for private and public - the second
1435 // transaction will not be executed
1436 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1439 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerPrv);
1441 if (CKM_API_SUCCESS != retCode)
1444 retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerPub);
1446 if (CKM_API_SUCCESS != retCode)
1450 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerPrv,
1451 static_cast<int>(policyPrivate.extractable));
1452 handlerPriv.crypto.encryptRow(rowPrv);
1453 handlerPriv.database.saveRow(rowPrv);
1455 DB::Row rowPub(std::move(keys.second), namePublic, ownerPub,
1456 static_cast<int>(policyPublic.extractable));
1457 handlerPub.crypto.encryptRow(rowPub);
1458 handlerPub.database.saveRow(rowPub);
1460 transactionPub.commit();
1461 transactionPriv.commit();
1462 return CKM_API_SUCCESS;
1465 RawBuffer CKMLogic::createKeyPair(
1466 const Credentials &cred,
1468 const CryptoAlgorithmSerializable &keyGenParams,
1469 const Name &namePrivate,
1470 const ClientId &explicitOwnerPrivate,
1471 const Name &namePublic,
1472 const ClientId &explicitOwnerPublic,
1473 const PolicySerializable &policyPrivate,
1474 const PolicySerializable &policyPublic)
1476 int retCode = CKM_API_SUCCESS;
1479 retCode = createKeyPairHelper(
1483 explicitOwnerPrivate,
1485 explicitOwnerPublic,
1488 } catch (const Exc::Exception &e) {
1489 retCode = e.error();
1490 } catch (const CKM::Exception &e) {
1491 LogError("CKM::Exception: " << e.GetMessage());
1492 retCode = CKM_API_ERROR_SERVER_ERROR;
1495 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1496 commandId, retCode).Pop();
1499 RawBuffer CKMLogic::createKeyAES(
1500 const Credentials &cred,
1504 const ClientId &explicitOwner,
1505 const PolicySerializable &policy)
1507 int retCode = CKM_API_SUCCESS;
1510 retCode = createKeyAESHelper(cred, size, name, explicitOwner, policy);
1511 } catch (const Exc::Exception &e) {
1512 retCode = e.error();
1513 } catch (std::invalid_argument &e) {
1514 LogDebug("invalid argument error: " << e.what());
1515 retCode = CKM_API_ERROR_INPUT_PARAM;
1516 } catch (const CKM::Exception &e) {
1517 LogError("CKM::Exception: " << e.GetMessage());
1518 retCode = CKM_API_ERROR_SERVER_ERROR;
1521 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1522 commandId, retCode).Pop();
1525 int CKMLogic::readCertificateHelper(
1526 const Credentials &cred,
1527 const OwnerNameVector &ownerNameVector,
1528 CertificateImplVector &certVector)
1530 for (auto &i : ownerNameVector) {
1531 // certificates can't be protected with custom user password
1532 Crypto::GObjUPtr obj;
1534 ec = readDataHelper(true,
1536 DataType::CERTIFICATE,
1542 if (ec != CKM_API_SUCCESS)
1545 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1547 // try to read chain certificates (if present)
1548 Crypto::GObjUPtrVector caChainObjs;
1549 ec = readDataHelper(true,
1551 DataType::DB_CHAIN_FIRST,
1557 if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1560 for (auto &caCertObj : caChainObjs)
1561 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1564 return CKM_API_SUCCESS;
1567 int CKMLogic::getCertificateChainHelper(
1568 const CertificateImpl &cert,
1569 const RawBufferVector &untrustedCertificates,
1570 const RawBufferVector &trustedCertificates,
1571 bool useTrustedSystemCertificates,
1572 RawBufferVector &chainRawVector)
1574 CertificateImplVector untrustedCertVector;
1575 CertificateImplVector trustedCertVector;
1576 CertificateImplVector chainVector;
1579 return CKM_API_ERROR_INPUT_PARAM;
1581 for (auto &e : untrustedCertificates) {
1582 CertificateImpl c(e, DataFormat::FORM_DER);
1585 return CKM_API_ERROR_INPUT_PARAM;
1587 untrustedCertVector.push_back(std::move(c));
1590 for (auto &e : trustedCertificates) {
1591 CertificateImpl c(e, DataFormat::FORM_DER);
1594 return CKM_API_ERROR_INPUT_PARAM;
1596 trustedCertVector.push_back(std::move(c));
1599 CertificateStore store;
1600 int retCode = store.verifyCertificate(cert,
1601 untrustedCertVector,
1603 useTrustedSystemCertificates,
1604 m_accessControl.isCCMode(),
1607 if (retCode != CKM_API_SUCCESS)
1610 for (auto &e : chainVector)
1611 chainRawVector.push_back(e.getDER());
1613 return CKM_API_SUCCESS;
1616 int CKMLogic::getCertificateChainHelper(
1617 const Credentials &cred,
1618 const CertificateImpl &cert,
1619 const OwnerNameVector &untrusted,
1620 const OwnerNameVector &trusted,
1621 bool useTrustedSystemCertificates,
1622 RawBufferVector &chainRawVector)
1624 CertificateImplVector untrustedCertVector;
1625 CertificateImplVector trustedCertVector;
1626 CertificateImplVector chainVector;
1629 return CKM_API_ERROR_INPUT_PARAM;
1631 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1633 if (retCode != CKM_API_SUCCESS)
1636 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1638 if (retCode != CKM_API_SUCCESS)
1641 CertificateStore store;
1642 retCode = store.verifyCertificate(cert,
1643 untrustedCertVector,
1645 useTrustedSystemCertificates,
1646 m_accessControl.isCCMode(),
1649 if (retCode != CKM_API_SUCCESS)
1652 for (auto &i : chainVector)
1653 chainRawVector.push_back(i.getDER());
1655 return CKM_API_SUCCESS;
1658 RawBuffer CKMLogic::getCertificateChain(
1659 const Credentials & /*cred*/,
1661 const RawBuffer &certificate,
1662 const RawBufferVector &untrustedCertificates,
1663 const RawBufferVector &trustedCertificates,
1664 bool useTrustedSystemCertificates)
1666 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1667 RawBufferVector chainRawVector;
1668 int retCode = CKM_API_ERROR_UNKNOWN;
1671 retCode = getCertificateChainHelper(cert,
1672 untrustedCertificates,
1673 trustedCertificates,
1674 useTrustedSystemCertificates,
1676 } catch (const Exc::Exception &e) {
1677 retCode = e.error();
1678 } catch (const std::exception &e) {
1679 LogError("STD exception " << e.what());
1680 retCode = CKM_API_ERROR_SERVER_ERROR;
1682 LogError("Unknown error.");
1685 auto response = MessageBuffer::Serialize(static_cast<int>
1686 (LogicCommand::GET_CHAIN_CERT),
1690 return response.Pop();
1693 RawBuffer CKMLogic::getCertificateChain(
1694 const Credentials &cred,
1696 const RawBuffer &certificate,
1697 const OwnerNameVector &untrustedCertificates,
1698 const OwnerNameVector &trustedCertificates,
1699 bool useTrustedSystemCertificates)
1701 int retCode = CKM_API_ERROR_UNKNOWN;
1702 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1703 RawBufferVector chainRawVector;
1706 retCode = getCertificateChainHelper(cred,
1708 untrustedCertificates,
1709 trustedCertificates,
1710 useTrustedSystemCertificates,
1712 } catch (const Exc::Exception &e) {
1713 retCode = e.error();
1714 } catch (const std::exception &e) {
1715 LogError("STD exception " << e.what());
1716 retCode = CKM_API_ERROR_SERVER_ERROR;
1718 LogError("Unknown error.");
1721 auto response = MessageBuffer::Serialize(static_cast<int>
1722 (LogicCommand::GET_CHAIN_ALIAS),
1726 return response.Pop();
1729 RawBuffer CKMLogic::createSignature(
1730 const Credentials &cred,
1732 const Name &privateKeyName,
1733 const ClientId &explicitOwner,
1734 const Password &password, // password for private_key
1735 const RawBuffer &message,
1736 const CryptoAlgorithm &cryptoAlg)
1738 RawBuffer signature;
1740 int retCode = CKM_API_SUCCESS;
1743 Crypto::GObjUPtr obj;
1744 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
1745 explicitOwner, password, obj);
1747 if (retCode == CKM_API_SUCCESS)
1748 signature = obj->sign(cryptoAlg, message);
1749 } catch (const Exc::Exception &e) {
1750 retCode = e.error();
1751 } catch (const CKM::Exception &e) {
1752 LogError("Unknown CKM::Exception: " << e.GetMessage());
1753 retCode = CKM_API_ERROR_SERVER_ERROR;
1754 } catch (const std::exception &e) {
1755 LogError("STD exception " << e.what());
1756 retCode = CKM_API_ERROR_SERVER_ERROR;
1759 auto response = MessageBuffer::Serialize(static_cast<int>
1760 (LogicCommand::CREATE_SIGNATURE),
1764 return response.Pop();
1767 RawBuffer CKMLogic::verifySignature(
1768 const Credentials &cred,
1770 const Name &publicKeyOrCertName,
1771 const ClientId &explicitOwner,
1772 const Password &password, // password for public_key (optional)
1773 const RawBuffer &message,
1774 const RawBuffer &signature,
1775 const CryptoAlgorithm ¶ms)
1777 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1780 // try certificate first - looking for a public key.
1781 // in case of PKCS, pub key from certificate will be found first
1782 // rather than private key from the same PKCS.
1783 Crypto::GObjUPtr obj;
1784 retCode = readDataHelper(false, cred, DataType::CERTIFICATE,
1785 publicKeyOrCertName, explicitOwner, password, obj);
1787 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1788 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
1789 publicKeyOrCertName, explicitOwner, password, obj);
1791 if (retCode == CKM_API_SUCCESS)
1792 retCode = obj->verify(params, message, signature);
1793 } catch (const Exc::Exception &e) {
1794 retCode = e.error();
1795 } catch (const CKM::Exception &e) {
1796 LogError("Unknown CKM::Exception: " << e.GetMessage());
1797 retCode = CKM_API_ERROR_SERVER_ERROR;
1800 auto response = MessageBuffer::Serialize(static_cast<int>
1801 (LogicCommand::VERIFY_SIGNATURE),
1804 return response.Pop();
1807 int CKMLogic::setPermissionHelper(
1808 const Credentials &cred, // who's the client
1810 const ClientId &explicitOwner, // who's the owner
1811 const ClientId &accessor, // who will get the access
1812 const PermissionMask permissionMask)
1814 auto &handler = selectDatabase(cred, explicitOwner);
1816 // we don't know the client
1817 if (cred.client.empty() || !isClientValid(cred.client))
1818 return CKM_API_ERROR_INPUT_PARAM;
1820 // use client id if not explicitly provided
1821 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1823 // verify name and owner are correct
1824 if (!isNameValid(name) || !isClientValid(owner) ||
1825 !isClientValid(accessor))
1826 return CKM_API_ERROR_INPUT_PARAM;
1828 // currently we don't support modification of owner's permissions to his own rows
1829 if (owner == accessor)
1830 return CKM_API_ERROR_INPUT_PARAM;
1832 // system database does not support write/remove permissions
1833 if ((0 == owner.compare(CLIENT_ID_SYSTEM)) &&
1834 (permissionMask & Permission::REMOVE))
1835 return CKM_API_ERROR_INPUT_PARAM;
1837 // can the client modify permissions to owner's row?
1838 int retCode = m_accessControl.canModify(cred, owner);
1840 if (retCode != CKM_API_SUCCESS)
1843 DB::Crypto::Transaction transaction(&handler.database);
1845 if (!handler.database.isNameOwnerPresent(name, owner))
1846 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1848 // set permissions to the row owned by owner for accessor
1849 handler.database.setPermission(name, owner, accessor, permissionMask);
1850 transaction.commit();
1852 return CKM_API_SUCCESS;
1855 RawBuffer CKMLogic::setPermission(
1856 const Credentials &cred,
1860 const ClientId &explicitOwner,
1861 const ClientId &accessor,
1862 const PermissionMask permissionMask)
1867 retCode = setPermissionHelper(cred, name, explicitOwner, accessor, permissionMask);
1868 } catch (const Exc::Exception &e) {
1869 retCode = e.error();
1870 } catch (const CKM::Exception &e) {
1871 LogError("Error: " << e.GetMessage());
1872 retCode = CKM_API_ERROR_DB_ERROR;
1875 return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1878 int CKMLogic::loadAppKey(UserData &handle, const ClientId &owner)
1880 if (!handle.crypto.haveKey(owner)) {
1882 auto key_optional = handle.database.getKey(owner);
1884 if (!key_optional) {
1885 LogError("No key for given owner in database");
1886 return CKM_API_ERROR_DB_ERROR;
1889 key = *key_optional;
1890 key = handle.keyProvider.getPureDEK(key);
1891 handle.crypto.pushKey(owner, key);
1894 return CKM_API_SUCCESS;