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);
98 if (!handle.keyProvider.isInitialized()) {
99 handle.keyProvider.migrateDKEK(wrappedDKEK, password);
100 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
101 LogInfo("DKEK migrated");
105 void CKMLogic::saveDKEKFile(uid_t user, const Password &password)
107 auto &handle = m_userDataMap[user];
110 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
113 void CKMLogic::migrateSecureStorageData(bool isAdminUser)
115 SsMigration::migrate(isAdminUser, [this](const std::string &name,
116 const Crypto::Data &data,
117 bool adminUserFlag) {
118 LogInfo("Migrate data called with name: " << name);
119 auto ownerId = adminUserFlag ? CLIENT_ID_ADMIN_USER : CLIENT_ID_SYSTEM;
120 auto uid = adminUserFlag ? ADMIN_USER_DB_UID : SYSTEM_DB_UID;
122 int ret = verifyAndSaveDataHelper(Credentials(uid, ownerId), name, ownerId, data,
123 PolicySerializable());
125 if (ret == CKM_API_ERROR_DB_ALIAS_EXISTS)
126 LogWarning("Alias already exist for migrated name: " << name);
127 else if (ret != CKM_API_SUCCESS)
128 LogError("Failed to migrate secure-storage data. name: " << name <<
133 int CKMLogic::unlockDatabase(uid_t user, const Password &password)
135 if (0 < m_userDataMap.count(user) &&
136 m_userDataMap[user].keyProvider.isInitialized())
137 return CKM_API_SUCCESS;
139 int retCode = CKM_API_SUCCESS;
142 auto &handle = m_userDataMap[user];
145 loadDKEKFile(user, password);
147 auto wrappedDatabaseDEK = fs.getDBDEK();
149 if (wrappedDatabaseDEK.empty()) {
150 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
151 fs.saveDBDEK(wrappedDatabaseDEK);
154 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
156 handle.database = DB::Crypto(fs.getLegacyDBPath(), fs.getDBPath(), key);
157 handle.crypto = CryptoLogic();
159 if (!m_accessControl.isSystemService(user)) {
160 // remove data of removed apps during locked state
161 ClientIdVector removedApps = fs.clearRemovedsApps();
163 for (auto &app : removedApps) {
164 handle.crypto.removeKey(app);
165 handle.database.deleteKey(app);
169 if (user == SYSTEM_DB_UID && SsMigration::hasData())
170 migrateSecureStorageData(false);
171 else if (user == ADMIN_USER_DB_UID && SsMigration::hasData())
172 migrateSecureStorageData(true);
173 } catch (const Exc::Exception &e) {
175 } catch (const CKM::Exception &e) {
176 LogError("CKM::Exception: " << e.GetMessage());
177 retCode = CKM_API_ERROR_SERVER_ERROR;
180 if (CKM_API_SUCCESS != retCode)
181 m_userDataMap.erase(user);
186 int CKMLogic::unlockSystemDB()
188 return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
191 UserData &CKMLogic::selectDatabase(const Credentials &cred,
192 const ClientId &explicitOwner)
194 // if user trying to access system service - check:
195 // * if user database is unlocked [mandatory]
196 // * if not - proceed with regular user database
197 // * if explicit system database owner given -> switch to system DB
198 if (!m_accessControl.isSystemService(cred)) {
199 if (0 == m_userDataMap.count(cred.clientUid))
200 ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
202 if (0 != explicitOwner.compare(CLIENT_ID_SYSTEM))
203 return m_userDataMap[cred.clientUid];
206 // system database selected, modify the owner id
207 if (CKM_API_SUCCESS != unlockSystemDB())
208 ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
210 return m_userDataMap[SYSTEM_DB_UID];
213 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
215 int retCode = CKM_API_SUCCESS;
217 if (!m_accessControl.isSystemService(user))
218 retCode = unlockDatabase(user, password);
219 else // do not allow lock/unlock operations for system users
220 retCode = CKM_API_ERROR_INPUT_PARAM;
222 return MessageBuffer::Serialize(retCode).Pop();
225 RawBuffer CKMLogic::updateCCMode()
227 m_accessControl.updateCCMode();
228 return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
231 RawBuffer CKMLogic::lockUserKey(uid_t user)
233 int retCode = CKM_API_SUCCESS;
235 if (!m_accessControl.isSystemService(user))
236 m_userDataMap.erase(user);
237 else // do not allow lock/unlock operations for system users
238 retCode = CKM_API_ERROR_INPUT_PARAM;
240 return MessageBuffer::Serialize(retCode).Pop();
243 RawBuffer CKMLogic::removeUserData(uid_t user)
245 if (m_accessControl.isSystemService(user))
246 user = SYSTEM_DB_UID;
248 m_userDataMap.erase(user);
250 const int retCode = FileSystem(user).removeUserData()
251 ? CKM_API_ERROR_FILE_SYSTEM
254 return MessageBuffer::Serialize(retCode).Pop();
257 int CKMLogic::changeUserPasswordHelper(uid_t user,
258 const Password &oldPassword,
259 const Password &newPassword)
261 // do not allow to change system database password
262 if (m_accessControl.isSystemService(user))
263 return CKM_API_ERROR_INPUT_PARAM;
265 loadDKEKFile(user, oldPassword);
266 saveDKEKFile(user, newPassword);
268 return CKM_API_SUCCESS;
271 RawBuffer CKMLogic::changeUserPassword(
273 const Password &oldPassword,
274 const Password &newPassword)
276 int retCode = CKM_API_SUCCESS;
279 retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
280 } catch (const Exc::Exception &e) {
282 } catch (const CKM::Exception &e) {
283 LogError("CKM::Exception: " << e.GetMessage());
284 retCode = CKM_API_ERROR_SERVER_ERROR;
287 return MessageBuffer::Serialize(retCode).Pop();
290 int CKMLogic::resetUserPasswordHelper(
292 const Password &newPassword)
294 // do not allow to reset system database password
295 if (m_accessControl.isSystemService(user))
296 return CKM_API_ERROR_INPUT_PARAM;
298 int retCode = CKM_API_SUCCESS;
300 if (0 == m_userDataMap.count(user)) {
301 // Check if key exists. If exists we must return error
303 auto wrappedDKEKMain = fs.getDKEK();
305 if (!wrappedDKEKMain.empty())
306 retCode = CKM_API_ERROR_BAD_REQUEST;
308 saveDKEKFile(user, newPassword);
314 RawBuffer CKMLogic::resetUserPassword(
316 const Password &newPassword)
318 int retCode = CKM_API_SUCCESS;
321 retCode = resetUserPasswordHelper(user, newPassword);
322 } catch (const Exc::Exception &e) {
324 } catch (const CKM::Exception &e) {
325 LogError("CKM::Exception: " << e.GetMessage());
326 retCode = CKM_API_ERROR_SERVER_ERROR;
329 return MessageBuffer::Serialize(retCode).Pop();
332 RawBuffer CKMLogic::removeApplicationData(const ClientId &owner)
334 int retCode = CKM_API_SUCCESS;
338 retCode = CKM_API_ERROR_INPUT_PARAM;
340 UidVector uids = FileSystem::getUIDsFromDBFile();
342 for (auto userId : uids) {
343 if (0 == m_userDataMap.count(userId)) {
344 FileSystem fs(userId);
345 fs.addRemovedApp(owner);
347 auto &handle = m_userDataMap[userId];
348 handle.crypto.removeKey(owner);
349 handle.database.deleteKey(owner);
353 } catch (const Exc::Exception &e) {
355 } catch (const CKM::Exception &e) {
356 LogError("CKM::Exception: " << e.GetMessage());
357 retCode = CKM_API_ERROR_SERVER_ERROR;
360 return MessageBuffer::Serialize(retCode).Pop();
363 int CKMLogic::checkSaveConditions(
364 const Credentials &accessorCred,
367 const ClientId &owner)
369 // verify name and client are correct
370 if (!isNameValid(name) || !isClientValid(owner)) {
371 LogDebug("Invalid parameter passed to key-manager");
372 return CKM_API_ERROR_INPUT_PARAM;
375 // check if accessor is allowed to save owner's items
376 int access_ec = m_accessControl.canSave(accessorCred, owner);
378 if (access_ec != CKM_API_SUCCESS) {
379 LogDebug("accessor " << accessorCred.client << " can not save rows owned by " <<
384 // check if not a duplicate
385 if (handler.database.isNameOwnerPresent(name, owner))
386 return CKM_API_ERROR_DB_ALIAS_EXISTS;
388 // encryption section
389 if (!handler.crypto.haveKey(owner)) {
391 auto key_optional = handler.database.getKey(owner);
394 LogDebug("No Key in database found. Generating new one for client: " <<
396 got_key = handler.keyProvider.generateDEK(owner);
397 handler.database.saveKey(owner, got_key);
399 LogDebug("Key from DB");
400 got_key = *key_optional;
403 got_key = handler.keyProvider.getPureDEK(got_key);
404 handler.crypto.pushKey(owner, got_key);
407 return CKM_API_SUCCESS;
410 DB::Row CKMLogic::createEncryptedRow(
413 const ClientId &owner,
414 const Crypto::Data &data,
415 const Policy &policy)
417 Crypto::GStore &store = m_decider.getStore(data.type, policy);
419 // do not encrypt data with password during cc_mode on
420 Token token = store.import(data,
421 m_accessControl.isCCMode() ? "" : policy.password,
422 Crypto::EncryptionParams());
423 DB::Row row(std::move(token), name, owner,
424 static_cast<int>(policy.extractable));
425 crypto.encryptRow(row);
429 int CKMLogic::verifyBinaryData(Crypto::Data &input) const
432 return toBinaryData(input, dummy);
435 int CKMLogic::toBinaryData(const Crypto::Data &input,
436 Crypto::Data &output) const
438 // verify the data integrity
439 if (input.type.isKey()) {
442 if (input.type.isSKey())
443 output_key = CKM::Key::createAES(input.data);
445 output_key = CKM::Key::create(input.data);
447 if (output_key.get() == NULL) {
448 LogDebug("provided binary data is not valid key data");
449 return CKM_API_ERROR_INPUT_PARAM;
452 output = std::move(Crypto::Data(input.type, output_key->getDER()));
453 } else if (input.type.isCertificate() || input.type.isChainCert()) {
454 CertificateShPtr cert = CKM::Certificate::create(input.data,
455 DataFormat::FORM_DER);
457 if (cert.get() == NULL) {
458 LogDebug("provided binary data is not valid certificate data");
459 return CKM_API_ERROR_INPUT_PARAM;
462 output = std::move(Crypto::Data(input.type, cert->getDER()));
467 // TODO: add here BINARY_DATA verification, i.e: max size etc.
468 return CKM_API_SUCCESS;
471 int CKMLogic::verifyAndSaveDataHelper(
472 const Credentials &cred,
474 const ClientId &explicitOwner,
475 const Crypto::Data &data,
476 const PolicySerializable &policy)
478 int retCode = CKM_API_ERROR_UNKNOWN;
481 // check if data is correct
482 Crypto::Data binaryData;
483 retCode = toBinaryData(data, binaryData);
485 if (retCode != CKM_API_SUCCESS)
488 return saveDataHelper(cred, name, explicitOwner, binaryData, policy);
489 } catch (const Exc::Exception &e) {
491 } catch (const CKM::Exception &e) {
492 LogError("CKM::Exception: " << e.GetMessage());
493 return CKM_API_ERROR_SERVER_ERROR;
497 int CKMLogic::getKeyForService(
498 const Credentials &cred,
500 const ClientId &explicitOwner,
501 const Password &pass,
502 Crypto::GObjShPtr &key)
505 // Key is for internal service use. It won't be exported to the client
506 Crypto::GObjUPtr obj;
507 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
510 if (retCode == CKM_API_SUCCESS)
511 key = std::move(obj);
514 } catch (const Exc::Exception &e) {
516 } catch (const CKM::Exception &e) {
517 LogError("CKM::Exception: " << e.GetMessage());
518 return CKM_API_ERROR_SERVER_ERROR;
522 RawBuffer CKMLogic::saveData(
523 const Credentials &cred,
526 const ClientId &explicitOwner,
527 const Crypto::Data &data,
528 const PolicySerializable &policy)
530 int retCode = verifyAndSaveDataHelper(cred, name, explicitOwner, data, policy);
531 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
534 static_cast<int>(data.type));
535 return response.Pop();
538 int CKMLogic::extractPKCS12Data(
541 const ClientId &owner,
542 const PKCS12Serializable &pkcs,
543 const PolicySerializable &keyPolicy,
544 const PolicySerializable &certPolicy,
545 DB::RowVector &output)
547 // private key is mandatory
548 auto key = pkcs.getKey();
551 LogError("Failed to get private key from pkcs");
552 return CKM_API_ERROR_INVALID_FORMAT;
555 Crypto::Data keyData(DataType(key->getType()), key->getDER());
556 int retCode = verifyBinaryData(keyData);
558 if (retCode != CKM_API_SUCCESS)
561 output.push_back(createEncryptedRow(crypto, name, owner, keyData,
564 // certificate is mandatory
565 auto cert = pkcs.getCertificate();
568 LogError("Failed to get certificate from pkcs");
569 return CKM_API_ERROR_INVALID_FORMAT;
572 Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
573 retCode = verifyBinaryData(certData);
575 if (retCode != CKM_API_SUCCESS)
578 output.push_back(createEncryptedRow(crypto, name, owner, certData,
582 unsigned int cert_index = 0;
584 for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
585 Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++),
587 int retCode = verifyBinaryData(caCertData);
589 if (retCode != CKM_API_SUCCESS)
592 output.push_back(createEncryptedRow(crypto, name, owner, caCertData,
596 return CKM_API_SUCCESS;
599 RawBuffer CKMLogic::savePKCS12(
600 const Credentials &cred,
603 const ClientId &explicitOwner,
604 const PKCS12Serializable &pkcs,
605 const PolicySerializable &keyPolicy,
606 const PolicySerializable &certPolicy)
608 int retCode = CKM_API_ERROR_UNKNOWN;
611 retCode = saveDataHelper(cred, name, explicitOwner, pkcs, keyPolicy, certPolicy);
612 } catch (const Exc::Exception &e) {
614 } catch (const CKM::Exception &e) {
615 LogError("CKM::Exception: " << e.GetMessage());
616 retCode = CKM_API_ERROR_SERVER_ERROR;
619 auto response = MessageBuffer::Serialize(static_cast<int>
620 (LogicCommand::SAVE_PKCS12),
623 return response.Pop();
627 int CKMLogic::removeDataHelper(
628 const Credentials &cred,
630 const ClientId &explicitOwner)
632 auto &handler = selectDatabase(cred, explicitOwner);
634 // use client id if not explicitly provided
635 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
637 if (!isNameValid(name) || !isClientValid(owner)) {
638 LogDebug("Invalid owner or name format");
639 return CKM_API_ERROR_INPUT_PARAM;
642 DB::Crypto::Transaction transaction(&handler.database);
644 // read and check permissions
645 PermissionMaskOptional permissionRowOpt =
646 handler.database.getPermissionRow(name, owner, cred.client);
647 int retCode = m_accessControl.canDelete(cred,
648 toPermissionMask(permissionRowOpt));
650 if (retCode != CKM_API_SUCCESS) {
651 LogWarning("access control check result: " << retCode);
655 // get all matching rows
657 handler.database.getRows(name, owner, DataType::DB_FIRST,
658 DataType::DB_LAST, rows);
661 LogDebug("No row for given name and owner");
662 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
665 // load app key if needed
666 retCode = loadAppKey(handler, rows.front().owner);
668 if (CKM_API_SUCCESS != retCode)
671 // destroy it in store
672 for (auto &r : rows) {
674 handler.crypto.decryptRow(Password(), r);
675 m_decider.getStore(r).destroy(r);
676 } catch (const Exc::AuthenticationFailed &) {
677 LogDebug("Authentication failed when removing data. Ignored.");
682 handler.database.deleteRow(name, owner);
683 transaction.commit();
685 return CKM_API_SUCCESS;
688 RawBuffer CKMLogic::removeData(
689 const Credentials &cred,
692 const ClientId &explicitOwner)
694 int retCode = CKM_API_ERROR_UNKNOWN;
697 retCode = removeDataHelper(cred, name, explicitOwner);
698 } catch (const Exc::Exception &e) {
700 } catch (const CKM::Exception &e) {
701 LogError("Error: " << e.GetMessage());
702 retCode = CKM_API_ERROR_DB_ERROR;
705 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
708 return response.Pop();
711 int CKMLogic::readSingleRow(const Name &name,
712 const ClientId &owner,
714 DB::Crypto &database,
717 DB::Crypto::RowOptional row_optional;
719 if (dataType.isKey()) {
720 // read all key types
721 row_optional = database.getRow(name,
723 DataType::DB_KEY_FIRST,
724 DataType::DB_KEY_LAST);
726 // read anything else
727 row_optional = database.getRow(name,
733 LogDebug("No row for given name, owner and type");
734 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
739 return CKM_API_SUCCESS;
743 int CKMLogic::readMultiRow(const Name &name,
744 const ClientId &owner,
746 DB::Crypto &database,
747 DB::RowVector &output)
749 if (dataType.isKey())
750 // read all key types
751 database.getRows(name,
753 DataType::DB_KEY_FIRST,
754 DataType::DB_KEY_LAST,
756 else if (dataType.isChainCert())
757 // read all key types
758 database.getRows(name,
760 DataType::DB_CHAIN_FIRST,
761 DataType::DB_CHAIN_LAST,
764 // read anything else
765 database.getRows(name,
770 if (!output.size()) {
771 LogDebug("No row for given name, owner and type");
772 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
775 return CKM_API_SUCCESS;
778 int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred,
780 const ClientId &owner,
783 DB::Crypto &database)
785 PermissionMaskOptional permissionRowOpt =
786 database.getPermissionRow(name, owner, accessorCred.client);
789 return m_accessControl.canExport(accessorCred,
791 toPermissionMask(permissionRowOpt));
793 return m_accessControl.canRead(accessorCred,
794 toPermissionMask(permissionRowOpt));
797 Crypto::GObjUPtr CKMLogic::rowToObject(
800 const Password &password)
802 Crypto::GStore &store = m_decider.getStore(row);
804 Password pass = m_accessControl.isCCMode() ? "" : password;
807 Crypto::GObjUPtr obj;
809 if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
810 CryptoLogic::ENCRYPTION_V2) {
811 handler.crypto.decryptRow(Password(), row);
813 obj = store.getObject(row, pass);
815 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
816 handler.crypto.decryptRow(pass, row);
817 // destroy it in store
820 // import it to store with new scheme: data -> pass(data)
821 Token token = store.import(Crypto::Data(row.dataType, row.data), pass, Crypto::EncryptionParams());
823 // get it from the store (it can be different than the data we imported into store)
824 obj = store.getObject(token, pass);
826 // update row with new token
827 *static_cast<Token *>(&row) = std::move(token);
829 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
830 handler.crypto.encryptRow(row);
833 handler.database.updateRow(row);
839 int CKMLogic::readDataHelper(
841 const Credentials &cred,
844 const ClientId &explicitOwner,
845 const Password &password,
846 Crypto::GObjUPtrVector &objs)
848 auto &handler = selectDatabase(cred, explicitOwner);
850 // use client id if not explicitly provided
851 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
853 if (!isNameValid(name) || !isClientValid(owner))
854 return CKM_API_ERROR_INPUT_PARAM;
857 DB::Crypto::Transaction transaction(&handler.database);
859 int retCode = readMultiRow(name, owner, dataType, handler.database, rows);
861 if (CKM_API_SUCCESS != retCode)
864 // all read rows belong to the same owner
865 DB::Row &firstRow = rows.at(0);
867 // check access rights
868 retCode = checkDataPermissionsHelper(cred, name, owner, firstRow,
869 exportFlag, handler.database);
871 if (CKM_API_SUCCESS != retCode)
874 // load app key if needed
875 retCode = loadAppKey(handler, firstRow.owner);
877 if (CKM_API_SUCCESS != retCode)
881 for (auto &row : rows)
882 objs.push_back(rowToObject(handler, std::move(row), password));
884 // rowToObject may modify db
885 transaction.commit();
887 return CKM_API_SUCCESS;
890 int CKMLogic::readDataHelper(
892 const Credentials &cred,
895 const ClientId &explicitOwner,
896 const Password &password,
897 Crypto::GObjUPtr &obj)
899 DataType objDataType;
900 return readDataHelper(exportFlag, cred, dataType, name, explicitOwner,
901 password, obj, objDataType);
904 int CKMLogic::readDataHelper(
906 const Credentials &cred,
909 const ClientId &explicitOwner,
910 const Password &password,
911 Crypto::GObjUPtr &obj,
912 DataType &objDataType)
914 auto &handler = selectDatabase(cred, explicitOwner);
916 // use client id if not explicitly provided
917 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
919 if (!isNameValid(name) || !isClientValid(owner))
920 return CKM_API_ERROR_INPUT_PARAM;
923 DB::Crypto::Transaction transaction(&handler.database);
925 int retCode = readSingleRow(name, owner, dataType, handler.database, row);
927 if (CKM_API_SUCCESS != retCode)
930 objDataType = row.dataType;
932 // check access rights
933 retCode = checkDataPermissionsHelper(cred, name, owner, row, exportFlag,
936 if (CKM_API_SUCCESS != retCode)
939 // load app key if needed
940 retCode = loadAppKey(handler, row.owner);
942 if (CKM_API_SUCCESS != retCode)
945 obj = rowToObject(handler, std::move(row), password);
946 // rowToObject may modify db
947 transaction.commit();
949 return CKM_API_SUCCESS;
952 RawBuffer CKMLogic::getData(
953 const Credentials &cred,
957 const ClientId &explicitOwner,
958 const Password &password)
960 int retCode = CKM_API_SUCCESS;
962 DataType objDataType;
965 Crypto::GObjUPtr obj;
966 retCode = readDataHelper(true, cred, dataType, name, explicitOwner,
967 password, obj, objDataType);
969 if (retCode == CKM_API_SUCCESS)
970 rowData = obj->getBinary();
971 } catch (const Exc::Exception &e) {
973 } catch (const CKM::Exception &e) {
974 LogError("CKM::Exception: " << e.GetMessage());
975 retCode = CKM_API_ERROR_SERVER_ERROR;
978 if (CKM_API_SUCCESS != retCode)
981 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
984 static_cast<int>(objDataType),
986 return response.Pop();
989 RawBuffer CKMLogic::getDataProtectionStatus(
990 const Credentials &cred,
994 const ClientId &explicitOwner)
996 int retCode = CKM_API_SUCCESS;
998 DataType objDataType;
1002 Crypto::GObjUPtr obj;
1003 retCode = readDataHelper(false, cred, dataType, name, explicitOwner,
1004 password, obj, objDataType);
1006 } catch (const Exc::Exception &e) {
1007 retCode = e.error();
1008 } catch (const CKM::Exception &e) {
1009 LogError("CKM::Exception: " << e.GetMessage());
1010 retCode = CKM_API_ERROR_SERVER_ERROR;
1013 if (retCode == CKM_API_ERROR_AUTHENTICATION_FAILED) {
1015 retCode = CKM_API_SUCCESS;
1018 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PROTECTION_STATUS),
1021 static_cast<int>(objDataType),
1023 return response.Pop();
1026 int CKMLogic::getPKCS12Helper(
1027 const Credentials &cred,
1029 const ClientId &explicitOwner,
1030 const Password &keyPassword,
1031 const Password &certPassword,
1033 CertificateShPtr &cert,
1034 CertificateShPtrVector &caChain)
1038 // read private key (mandatory)
1039 Crypto::GObjUPtr keyObj;
1040 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
1041 keyPassword, keyObj);
1043 if (retCode != CKM_API_SUCCESS) {
1044 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1047 privKey = CKM::Key::create(keyObj->getBinary());
1050 // read certificate (mandatory)
1051 Crypto::GObjUPtr certObj;
1052 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, explicitOwner,
1053 certPassword, certObj);
1055 if (retCode != CKM_API_SUCCESS) {
1056 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1059 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
1062 // read CA cert chain (optional)
1063 Crypto::GObjUPtrVector caChainObjs;
1064 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, explicitOwner,
1065 certPassword, caChainObjs);
1067 if (retCode != CKM_API_SUCCESS && retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1068 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1071 for (auto &caCertObj : caChainObjs)
1072 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
1073 DataFormat::FORM_DER));
1076 // if anything found, return it
1077 if (privKey || cert || caChain.size() > 0)
1078 retCode = CKM_API_SUCCESS;
1083 RawBuffer CKMLogic::getPKCS12(
1084 const Credentials &cred,
1087 const ClientId &explicitOwner,
1088 const Password &keyPassword,
1089 const Password &certPassword)
1091 int retCode = CKM_API_ERROR_UNKNOWN;
1093 PKCS12Serializable output;
1097 CertificateShPtr cert;
1098 CertificateShPtrVector caChain;
1099 retCode = getPKCS12Helper(cred, name, explicitOwner, keyPassword,
1100 certPassword, privKey, cert, caChain);
1103 if (retCode == CKM_API_SUCCESS)
1104 output = PKCS12Serializable(std::move(privKey), std::move(cert),
1105 std::move(caChain));
1106 } catch (const Exc::Exception &e) {
1107 retCode = e.error();
1108 } catch (const CKM::Exception &e) {
1109 LogError("CKM::Exception: " << e.GetMessage());
1110 retCode = CKM_API_ERROR_SERVER_ERROR;
1113 auto response = MessageBuffer::Serialize(static_cast<int>
1114 (LogicCommand::GET_PKCS12),
1118 return response.Pop();
1121 int CKMLogic::getDataListHelper(const Credentials &cred,
1122 const DataType dataType,
1123 OwnerNameVector &ownerNameVector)
1125 int retCode = CKM_API_ERROR_DB_LOCKED;
1127 if (0 < m_userDataMap.count(cred.clientUid)) {
1128 auto &database = m_userDataMap[cred.clientUid].database;
1131 OwnerNameVector tmpVector;
1133 if (dataType.isKey()) {
1134 // list all key types
1135 database.listNames(cred.client,
1137 DataType::DB_KEY_FIRST,
1138 DataType::DB_KEY_LAST);
1140 // list anything else
1141 database.listNames(cred.client,
1146 ownerNameVector.insert(ownerNameVector.end(), tmpVector.begin(),
1148 retCode = CKM_API_SUCCESS;
1149 } catch (const CKM::Exception &e) {
1150 LogError("Error: " << e.GetMessage());
1151 retCode = CKM_API_ERROR_DB_ERROR;
1152 } catch (const Exc::Exception &e) {
1153 retCode = e.error();
1160 RawBuffer CKMLogic::getDataList(
1161 const Credentials &cred,
1165 OwnerNameVector systemVector;
1166 OwnerNameVector userVector;
1167 OwnerNameVector ownerNameVector;
1169 int retCode = unlockSystemDB();
1171 if (CKM_API_SUCCESS == retCode) {
1173 if (m_accessControl.isSystemService(cred)) {
1175 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1180 // user - lookup system, then client DB
1181 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1187 if (retCode == CKM_API_SUCCESS) {
1188 retCode = getDataListHelper(cred,
1195 if (retCode == CKM_API_SUCCESS) {
1196 ownerNameVector.insert(ownerNameVector.end(), systemVector.begin(),
1197 systemVector.end());
1198 ownerNameVector.insert(ownerNameVector.end(), userVector.begin(),
1202 auto response = MessageBuffer::Serialize(static_cast<int>
1203 (LogicCommand::GET_LIST),
1206 static_cast<int>(dataType),
1208 return response.Pop();
1211 int CKMLogic::importInitialData(
1213 const Crypto::Data &data,
1214 const Crypto::EncryptionParams &encParams,
1215 const Policy &policy)
1218 if (encParams.iv.empty() != encParams.tag.empty()) {
1219 LogError("Both iv and tag must be empty or set");
1220 return CKM_API_ERROR_INPUT_PARAM;
1223 // Inital values are always imported with root credentials. Client id is not important.
1224 Credentials rootCred(0, "");
1226 auto &handler = selectDatabase(rootCred, CLIENT_ID_SYSTEM);
1228 // check if save is possible
1229 DB::Crypto::Transaction transaction(&handler.database);
1230 int retCode = checkSaveConditions(rootCred, handler, name, CLIENT_ID_SYSTEM);
1232 if (retCode != CKM_API_SUCCESS)
1235 Crypto::GStore &store =
1236 m_decider.getStore(data.type, policy, !encParams.iv.empty());
1240 if (encParams.iv.empty()) {
1241 // Data are not encrypted, let's try to verify them
1242 Crypto::Data binaryData;
1244 if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1247 token = store.import(binaryData,
1248 m_accessControl.isCCMode() ? "" : policy.password,
1251 token = store.import(data,
1252 m_accessControl.isCCMode() ? "" : policy.password,
1256 DB::Row row(std::move(token), name, CLIENT_ID_SYSTEM,
1257 static_cast<int>(policy.extractable));
1258 handler.crypto.encryptRow(row);
1260 handler.database.saveRow(row);
1261 transaction.commit();
1262 } catch (const Exc::Exception &e) {
1264 } catch (const CKM::Exception &e) {
1265 LogError("CKM::Exception: " << e.GetMessage());
1266 return CKM_API_ERROR_SERVER_ERROR;
1267 } catch (const std::exception &e) {
1268 LogError("Std::exception: " << e.what());
1269 return CKM_API_ERROR_SERVER_ERROR;
1272 return CKM_API_SUCCESS;
1275 int CKMLogic::saveDataHelper(
1276 const Credentials &cred,
1278 const ClientId &explicitOwner,
1279 const Crypto::Data &data,
1280 const PolicySerializable &policy)
1282 auto &handler = selectDatabase(cred, explicitOwner);
1284 // use client id if not explicitly provided
1285 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1287 if (m_accessControl.isSystemService(cred) &&
1288 owner.compare(CLIENT_ID_SYSTEM) != 0) {
1289 LogError("System services can only use " << CLIENT_ID_SYSTEM << " as owner id") ;
1290 return CKM_API_ERROR_INPUT_PARAM;
1293 // check if save is possible
1294 DB::Crypto::Transaction transaction(&handler.database);
1295 int retCode = checkSaveConditions(cred, handler, name, owner);
1297 if (retCode != CKM_API_SUCCESS)
1301 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, owner,
1303 handler.database.saveRow(encryptedRow);
1305 transaction.commit();
1306 return CKM_API_SUCCESS;
1309 int CKMLogic::saveDataHelper(
1310 const Credentials &cred,
1312 const ClientId &explicitOwner,
1313 const PKCS12Serializable &pkcs,
1314 const PolicySerializable &keyPolicy,
1315 const PolicySerializable &certPolicy)
1317 auto &handler = selectDatabase(cred, explicitOwner);
1319 // use client id if not explicitly provided
1320 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1322 if (m_accessControl.isSystemService(cred) &&
1323 owner.compare(CLIENT_ID_SYSTEM) != 0)
1324 return CKM_API_ERROR_INPUT_PARAM;
1326 // check if save is possible
1327 DB::Crypto::Transaction transaction(&handler.database);
1328 int retCode = checkSaveConditions(cred, handler, name, owner);
1330 if (retCode != CKM_API_SUCCESS)
1333 // extract and encrypt the data
1334 DB::RowVector encryptedRows;
1335 retCode = extractPKCS12Data(handler.crypto, name, owner, pkcs, keyPolicy,
1336 certPolicy, encryptedRows);
1338 if (retCode != CKM_API_SUCCESS)
1342 handler.database.saveRows(name, owner, encryptedRows);
1343 transaction.commit();
1345 return CKM_API_SUCCESS;
1349 int CKMLogic::createKeyAESHelper(
1350 const Credentials &cred,
1353 const ClientId &explicitOwner,
1354 const PolicySerializable &policy)
1356 auto &handler = selectDatabase(cred, explicitOwner);
1358 // use client id if not explicitly provided
1359 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1361 if (m_accessControl.isSystemService(cred) &&
1362 owner.compare(CLIENT_ID_SYSTEM) != 0)
1363 return CKM_API_ERROR_INPUT_PARAM;
1365 // check if save is possible
1366 DB::Crypto::Transaction transaction(&handler.database);
1367 int retCode = checkSaveConditions(cred, handler, name, owner);
1369 if (retCode != CKM_API_SUCCESS)
1372 // create key in store
1373 CryptoAlgorithm keyGenAlgorithm;
1374 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1375 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1376 Token key = m_decider.getStore(DataType::KEY_AES,
1377 policy).generateSKey(keyGenAlgorithm, policy.password);
1380 DB::Row row(std::move(key), name, owner,
1381 static_cast<int>(policy.extractable));
1382 handler.crypto.encryptRow(row);
1384 handler.database.saveRow(row);
1386 transaction.commit();
1387 return CKM_API_SUCCESS;
1390 int CKMLogic::createKeyPairHelper(
1391 const Credentials &cred,
1392 const CryptoAlgorithmSerializable &keyGenParams,
1393 const Name &namePrivate,
1394 const ClientId &explicitOwnerPrivate,
1395 const Name &namePublic,
1396 const ClientId &explicitOwnerPublic,
1397 const PolicySerializable &policyPrivate,
1398 const PolicySerializable &policyPublic)
1400 auto &handlerPriv = selectDatabase(cred, explicitOwnerPrivate);
1401 auto &handlerPub = selectDatabase(cred, explicitOwnerPublic);
1403 AlgoType keyType = AlgoType::RSA_GEN;
1405 if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1406 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1408 const auto dtIt = ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.find(keyType);
1409 if (dtIt == ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.end())
1410 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1411 const DataTypePair& dt = dtIt->second;
1413 if (policyPrivate.backend != policyPublic.backend)
1414 ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend.");
1416 // use client id if not explicitly provided
1417 const ClientId &ownerPrv = explicitOwnerPrivate.empty() ? cred.client :
1418 explicitOwnerPrivate;
1420 if (m_accessControl.isSystemService(cred) &&
1421 ownerPrv.compare(CLIENT_ID_SYSTEM) != 0)
1422 return CKM_API_ERROR_INPUT_PARAM;
1424 const ClientId &ownerPub = explicitOwnerPublic.empty() ? cred.client :
1425 explicitOwnerPublic;
1427 if (m_accessControl.isSystemService(cred) &&
1428 ownerPub.compare(CLIENT_ID_SYSTEM) != 0)
1429 return CKM_API_ERROR_INPUT_PARAM;
1431 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1432 Policy lessRestricted(Password(), exportable, policyPrivate.backend);
1434 TokenPair keys = m_decider.getStore(policyPrivate, dt.first, dt.second).generateAKey(keyGenParams,
1435 policyPrivate.password,
1436 policyPublic.password);
1438 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1439 // in case the same database is used for private and public - the second
1440 // transaction will not be executed
1441 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1444 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerPrv);
1446 if (CKM_API_SUCCESS != retCode)
1449 retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerPub);
1451 if (CKM_API_SUCCESS != retCode)
1455 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerPrv,
1456 static_cast<int>(policyPrivate.extractable));
1457 handlerPriv.crypto.encryptRow(rowPrv);
1458 handlerPriv.database.saveRow(rowPrv);
1460 DB::Row rowPub(std::move(keys.second), namePublic, ownerPub,
1461 static_cast<int>(policyPublic.extractable));
1462 handlerPub.crypto.encryptRow(rowPub);
1463 handlerPub.database.saveRow(rowPub);
1465 transactionPub.commit();
1466 transactionPriv.commit();
1467 return CKM_API_SUCCESS;
1470 RawBuffer CKMLogic::createKeyPair(
1471 const Credentials &cred,
1473 const CryptoAlgorithmSerializable &keyGenParams,
1474 const Name &namePrivate,
1475 const ClientId &explicitOwnerPrivate,
1476 const Name &namePublic,
1477 const ClientId &explicitOwnerPublic,
1478 const PolicySerializable &policyPrivate,
1479 const PolicySerializable &policyPublic)
1481 int retCode = CKM_API_SUCCESS;
1484 retCode = createKeyPairHelper(
1488 explicitOwnerPrivate,
1490 explicitOwnerPublic,
1493 } catch (const Exc::Exception &e) {
1494 retCode = e.error();
1495 } catch (const CKM::Exception &e) {
1496 LogError("CKM::Exception: " << e.GetMessage());
1497 retCode = CKM_API_ERROR_SERVER_ERROR;
1500 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1501 commandId, retCode).Pop();
1504 RawBuffer CKMLogic::createKeyAES(
1505 const Credentials &cred,
1509 const ClientId &explicitOwner,
1510 const PolicySerializable &policy)
1512 int retCode = CKM_API_SUCCESS;
1515 retCode = createKeyAESHelper(cred, size, name, explicitOwner, policy);
1516 } catch (const Exc::Exception &e) {
1517 retCode = e.error();
1518 } catch (std::invalid_argument &e) {
1519 LogDebug("invalid argument error: " << e.what());
1520 retCode = CKM_API_ERROR_INPUT_PARAM;
1521 } catch (const CKM::Exception &e) {
1522 LogError("CKM::Exception: " << e.GetMessage());
1523 retCode = CKM_API_ERROR_SERVER_ERROR;
1526 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1527 commandId, retCode).Pop();
1530 int CKMLogic::readCertificateHelper(
1531 const Credentials &cred,
1532 const OwnerNameVector &ownerNameVector,
1533 CertificateImplVector &certVector)
1535 for (auto &i : ownerNameVector) {
1536 // certificates can't be protected with custom user password
1537 Crypto::GObjUPtr obj;
1539 ec = readDataHelper(true,
1541 DataType::CERTIFICATE,
1547 if (ec != CKM_API_SUCCESS)
1550 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1552 // try to read chain certificates (if present)
1553 Crypto::GObjUPtrVector caChainObjs;
1554 ec = readDataHelper(true,
1556 DataType::DB_CHAIN_FIRST,
1562 if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1565 for (auto &caCertObj : caChainObjs)
1566 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1569 return CKM_API_SUCCESS;
1572 int CKMLogic::getCertificateChainHelper(
1573 const CertificateImpl &cert,
1574 const RawBufferVector &untrustedCertificates,
1575 const RawBufferVector &trustedCertificates,
1576 bool useTrustedSystemCertificates,
1577 RawBufferVector &chainRawVector)
1579 CertificateImplVector untrustedCertVector;
1580 CertificateImplVector trustedCertVector;
1581 CertificateImplVector chainVector;
1584 return CKM_API_ERROR_INPUT_PARAM;
1586 for (auto &e : untrustedCertificates) {
1587 CertificateImpl c(e, DataFormat::FORM_DER);
1590 return CKM_API_ERROR_INPUT_PARAM;
1592 untrustedCertVector.push_back(std::move(c));
1595 for (auto &e : trustedCertificates) {
1596 CertificateImpl c(e, DataFormat::FORM_DER);
1599 return CKM_API_ERROR_INPUT_PARAM;
1601 trustedCertVector.push_back(std::move(c));
1604 CertificateStore store;
1605 int retCode = store.verifyCertificate(cert,
1606 untrustedCertVector,
1608 useTrustedSystemCertificates,
1609 m_accessControl.isCCMode(),
1612 if (retCode != CKM_API_SUCCESS)
1615 for (auto &e : chainVector)
1616 chainRawVector.push_back(e.getDER());
1618 return CKM_API_SUCCESS;
1621 int CKMLogic::getCertificateChainHelper(
1622 const Credentials &cred,
1623 const CertificateImpl &cert,
1624 const OwnerNameVector &untrusted,
1625 const OwnerNameVector &trusted,
1626 bool useTrustedSystemCertificates,
1627 RawBufferVector &chainRawVector)
1629 CertificateImplVector untrustedCertVector;
1630 CertificateImplVector trustedCertVector;
1631 CertificateImplVector chainVector;
1634 return CKM_API_ERROR_INPUT_PARAM;
1636 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1638 if (retCode != CKM_API_SUCCESS)
1641 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1643 if (retCode != CKM_API_SUCCESS)
1646 CertificateStore store;
1647 retCode = store.verifyCertificate(cert,
1648 untrustedCertVector,
1650 useTrustedSystemCertificates,
1651 m_accessControl.isCCMode(),
1654 if (retCode != CKM_API_SUCCESS)
1657 for (auto &i : chainVector)
1658 chainRawVector.push_back(i.getDER());
1660 return CKM_API_SUCCESS;
1663 RawBuffer CKMLogic::getCertificateChain(
1664 const Credentials & /*cred*/,
1666 const RawBuffer &certificate,
1667 const RawBufferVector &untrustedCertificates,
1668 const RawBufferVector &trustedCertificates,
1669 bool useTrustedSystemCertificates)
1671 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1672 RawBufferVector chainRawVector;
1673 int retCode = CKM_API_ERROR_UNKNOWN;
1676 retCode = getCertificateChainHelper(cert,
1677 untrustedCertificates,
1678 trustedCertificates,
1679 useTrustedSystemCertificates,
1681 } catch (const Exc::Exception &e) {
1682 retCode = e.error();
1683 } catch (const std::exception &e) {
1684 LogError("STD exception " << e.what());
1685 retCode = CKM_API_ERROR_SERVER_ERROR;
1687 LogError("Unknown error.");
1690 auto response = MessageBuffer::Serialize(static_cast<int>
1691 (LogicCommand::GET_CHAIN_CERT),
1695 return response.Pop();
1698 RawBuffer CKMLogic::getCertificateChain(
1699 const Credentials &cred,
1701 const RawBuffer &certificate,
1702 const OwnerNameVector &untrustedCertificates,
1703 const OwnerNameVector &trustedCertificates,
1704 bool useTrustedSystemCertificates)
1706 int retCode = CKM_API_ERROR_UNKNOWN;
1707 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1708 RawBufferVector chainRawVector;
1711 retCode = getCertificateChainHelper(cred,
1713 untrustedCertificates,
1714 trustedCertificates,
1715 useTrustedSystemCertificates,
1717 } catch (const Exc::Exception &e) {
1718 retCode = e.error();
1719 } catch (const std::exception &e) {
1720 LogError("STD exception " << e.what());
1721 retCode = CKM_API_ERROR_SERVER_ERROR;
1723 LogError("Unknown error.");
1726 auto response = MessageBuffer::Serialize(static_cast<int>
1727 (LogicCommand::GET_CHAIN_ALIAS),
1731 return response.Pop();
1734 RawBuffer CKMLogic::createSignature(
1735 const Credentials &cred,
1737 const Name &privateKeyName,
1738 const ClientId &explicitOwner,
1739 const Password &password, // password for private_key
1740 const RawBuffer &message,
1741 const CryptoAlgorithm &cryptoAlg)
1743 RawBuffer signature;
1745 int retCode = CKM_API_SUCCESS;
1748 Crypto::GObjUPtr obj;
1749 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
1750 explicitOwner, password, obj);
1752 if (retCode == CKM_API_SUCCESS)
1753 signature = obj->sign(cryptoAlg, message);
1754 } catch (const Exc::Exception &e) {
1755 retCode = e.error();
1756 } catch (const CKM::Exception &e) {
1757 LogError("Unknown CKM::Exception: " << e.GetMessage());
1758 retCode = CKM_API_ERROR_SERVER_ERROR;
1759 } catch (const std::exception &e) {
1760 LogError("STD exception " << e.what());
1761 retCode = CKM_API_ERROR_SERVER_ERROR;
1764 auto response = MessageBuffer::Serialize(static_cast<int>
1765 (LogicCommand::CREATE_SIGNATURE),
1769 return response.Pop();
1772 RawBuffer CKMLogic::verifySignature(
1773 const Credentials &cred,
1775 const Name &publicKeyOrCertName,
1776 const ClientId &explicitOwner,
1777 const Password &password, // password for public_key (optional)
1778 const RawBuffer &message,
1779 const RawBuffer &signature,
1780 const CryptoAlgorithm ¶ms)
1782 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1785 // try certificate first - looking for a public key.
1786 // in case of PKCS, pub key from certificate will be found first
1787 // rather than private key from the same PKCS.
1788 Crypto::GObjUPtr obj;
1789 retCode = readDataHelper(false, cred, DataType::CERTIFICATE,
1790 publicKeyOrCertName, explicitOwner, password, obj);
1792 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1793 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
1794 publicKeyOrCertName, explicitOwner, password, obj);
1796 if (retCode == CKM_API_SUCCESS)
1797 retCode = obj->verify(params, message, signature);
1798 } catch (const Exc::Exception &e) {
1799 retCode = e.error();
1800 } catch (const CKM::Exception &e) {
1801 LogError("Unknown CKM::Exception: " << e.GetMessage());
1802 retCode = CKM_API_ERROR_SERVER_ERROR;
1805 auto response = MessageBuffer::Serialize(static_cast<int>
1806 (LogicCommand::VERIFY_SIGNATURE),
1809 return response.Pop();
1812 int CKMLogic::setPermissionHelper(
1813 const Credentials &cred, // who's the client
1815 const ClientId &explicitOwner, // who's the owner
1816 const ClientId &accessor, // who will get the access
1817 const PermissionMask permissionMask)
1819 auto &handler = selectDatabase(cred, explicitOwner);
1821 // we don't know the client
1822 if (cred.client.empty() || !isClientValid(cred.client))
1823 return CKM_API_ERROR_INPUT_PARAM;
1825 // use client id if not explicitly provided
1826 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1828 // verify name and owner are correct
1829 if (!isNameValid(name) || !isClientValid(owner) ||
1830 !isClientValid(accessor))
1831 return CKM_API_ERROR_INPUT_PARAM;
1833 // currently we don't support modification of owner's permissions to his own rows
1834 if (owner == accessor)
1835 return CKM_API_ERROR_INPUT_PARAM;
1837 // system database does not support write/remove permissions
1838 if ((0 == owner.compare(CLIENT_ID_SYSTEM)) &&
1839 (permissionMask & Permission::REMOVE))
1840 return CKM_API_ERROR_INPUT_PARAM;
1842 // can the client modify permissions to owner's row?
1843 int retCode = m_accessControl.canModify(cred, owner);
1845 if (retCode != CKM_API_SUCCESS)
1848 DB::Crypto::Transaction transaction(&handler.database);
1850 if (!handler.database.isNameOwnerPresent(name, owner))
1851 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1853 // set permissions to the row owned by owner for accessor
1854 handler.database.setPermission(name, owner, accessor, permissionMask);
1855 transaction.commit();
1857 return CKM_API_SUCCESS;
1860 RawBuffer CKMLogic::setPermission(
1861 const Credentials &cred,
1865 const ClientId &explicitOwner,
1866 const ClientId &accessor,
1867 const PermissionMask permissionMask)
1872 retCode = setPermissionHelper(cred, name, explicitOwner, accessor, permissionMask);
1873 } catch (const Exc::Exception &e) {
1874 retCode = e.error();
1875 } catch (const CKM::Exception &e) {
1876 LogError("Error: " << e.GetMessage());
1877 retCode = CKM_API_ERROR_DB_ERROR;
1880 return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1883 int CKMLogic::loadAppKey(UserData &handle, const ClientId &owner)
1885 if (!handle.crypto.haveKey(owner)) {
1887 auto key_optional = handle.database.getKey(owner);
1889 if (!key_optional) {
1890 LogError("No key for given owner in database");
1891 return CKM_API_ERROR_DB_ERROR;
1894 key = *key_optional;
1895 key = handle.keyProvider.getPureDEK(key);
1896 handle.crypto.pushKey(owner, key);
1899 return CKM_API_SUCCESS;