2 * Copyright (c) 2014 - 2019 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.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 int retCode = CKM_API_SUCCESS;
242 if (m_accessControl.isSystemService(user))
243 user = SYSTEM_DB_UID;
245 m_userDataMap.erase(user);
250 return MessageBuffer::Serialize(retCode).Pop();
253 int CKMLogic::changeUserPasswordHelper(uid_t user,
254 const Password &oldPassword,
255 const Password &newPassword)
257 // do not allow to change system database password
258 if (m_accessControl.isSystemService(user))
259 return CKM_API_ERROR_INPUT_PARAM;
261 loadDKEKFile(user, oldPassword);
262 saveDKEKFile(user, newPassword);
264 return CKM_API_SUCCESS;
267 RawBuffer CKMLogic::changeUserPassword(
269 const Password &oldPassword,
270 const Password &newPassword)
272 int retCode = CKM_API_SUCCESS;
275 retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
276 } catch (const Exc::Exception &e) {
278 } catch (const CKM::Exception &e) {
279 LogError("CKM::Exception: " << e.GetMessage());
280 retCode = CKM_API_ERROR_SERVER_ERROR;
283 return MessageBuffer::Serialize(retCode).Pop();
286 int CKMLogic::resetUserPasswordHelper(
288 const Password &newPassword)
290 // do not allow to reset system database password
291 if (m_accessControl.isSystemService(user))
292 return CKM_API_ERROR_INPUT_PARAM;
294 int retCode = CKM_API_SUCCESS;
296 if (0 == m_userDataMap.count(user)) {
297 // Check if key exists. If exists we must return error
299 auto wrappedDKEKMain = fs.getDKEK();
301 if (!wrappedDKEKMain.empty())
302 retCode = CKM_API_ERROR_BAD_REQUEST;
304 saveDKEKFile(user, newPassword);
310 RawBuffer CKMLogic::resetUserPassword(
312 const Password &newPassword)
314 int retCode = CKM_API_SUCCESS;
317 retCode = resetUserPasswordHelper(user, newPassword);
318 } catch (const Exc::Exception &e) {
320 } catch (const CKM::Exception &e) {
321 LogError("CKM::Exception: " << e.GetMessage());
322 retCode = CKM_API_ERROR_SERVER_ERROR;
325 return MessageBuffer::Serialize(retCode).Pop();
328 RawBuffer CKMLogic::removeApplicationData(const ClientId &owner)
330 int retCode = CKM_API_SUCCESS;
334 retCode = CKM_API_ERROR_INPUT_PARAM;
336 UidVector uids = FileSystem::getUIDsFromDBFile();
338 for (auto userId : uids) {
339 if (0 == m_userDataMap.count(userId)) {
340 FileSystem fs(userId);
341 fs.addRemovedApp(owner);
343 auto &handle = m_userDataMap[userId];
344 handle.crypto.removeKey(owner);
345 handle.database.deleteKey(owner);
349 } catch (const Exc::Exception &e) {
351 } catch (const CKM::Exception &e) {
352 LogError("CKM::Exception: " << e.GetMessage());
353 retCode = CKM_API_ERROR_SERVER_ERROR;
356 return MessageBuffer::Serialize(retCode).Pop();
359 int CKMLogic::checkSaveConditions(
360 const Credentials &accessorCred,
363 const ClientId &owner)
365 // verify name and client are correct
366 if (!isNameValid(name) || !isClientValid(owner)) {
367 LogDebug("Invalid parameter passed to key-manager");
368 return CKM_API_ERROR_INPUT_PARAM;
371 // check if accessor is allowed to save owner's items
372 int access_ec = m_accessControl.canSave(accessorCred, owner);
374 if (access_ec != CKM_API_SUCCESS) {
375 LogDebug("accessor " << accessorCred.client << " can not save rows owned by " <<
380 // check if not a duplicate
381 if (handler.database.isNameOwnerPresent(name, owner))
382 return CKM_API_ERROR_DB_ALIAS_EXISTS;
384 // encryption section
385 if (!handler.crypto.haveKey(owner)) {
387 auto key_optional = handler.database.getKey(owner);
390 LogDebug("No Key in database found. Generating new one for client: " <<
392 got_key = handler.keyProvider.generateDEK(owner);
393 handler.database.saveKey(owner, got_key);
395 LogDebug("Key from DB");
396 got_key = *key_optional;
399 got_key = handler.keyProvider.getPureDEK(got_key);
400 handler.crypto.pushKey(owner, got_key);
403 return CKM_API_SUCCESS;
406 DB::Row CKMLogic::createEncryptedRow(
409 const ClientId &owner,
410 const Crypto::Data &data,
411 const Policy &policy) const
413 Crypto::GStore &store = m_decider.getStore(data.type, policy);
415 // do not encrypt data with password during cc_mode on
416 Token token = store.import(data,
417 m_accessControl.isCCMode() ? "" : policy.password,
418 Crypto::EncryptionParams());
419 DB::Row row(std::move(token), name, owner,
420 static_cast<int>(policy.extractable));
421 crypto.encryptRow(row);
425 int CKMLogic::verifyBinaryData(Crypto::Data &input) const
428 return toBinaryData(input, dummy);
431 int CKMLogic::toBinaryData(const Crypto::Data &input,
432 Crypto::Data &output) const
434 // verify the data integrity
435 if (input.type.isKey()) {
438 if (input.type.isSKey())
439 output_key = CKM::Key::createAES(input.data);
441 output_key = CKM::Key::create(input.data);
443 if (output_key.get() == NULL) {
444 LogDebug("provided binary data is not valid key data");
445 return CKM_API_ERROR_INPUT_PARAM;
448 output = std::move(Crypto::Data(input.type, output_key->getDER()));
449 } else if (input.type.isCertificate() || input.type.isChainCert()) {
450 CertificateShPtr cert = CKM::Certificate::create(input.data,
451 DataFormat::FORM_DER);
453 if (cert.get() == NULL) {
454 LogDebug("provided binary data is not valid certificate data");
455 return CKM_API_ERROR_INPUT_PARAM;
458 output = std::move(Crypto::Data(input.type, cert->getDER()));
463 // TODO: add here BINARY_DATA verification, i.e: max size etc.
464 return CKM_API_SUCCESS;
467 int CKMLogic::verifyAndSaveDataHelper(
468 const Credentials &cred,
470 const ClientId &explicitOwner,
471 const Crypto::Data &data,
472 const PolicySerializable &policy)
474 int retCode = CKM_API_ERROR_UNKNOWN;
477 // check if data is correct
478 Crypto::Data binaryData;
479 retCode = toBinaryData(data, binaryData);
481 if (retCode != CKM_API_SUCCESS)
484 return saveDataHelper(cred, name, explicitOwner, binaryData, policy);
485 } catch (const Exc::Exception &e) {
487 } catch (const CKM::Exception &e) {
488 LogError("CKM::Exception: " << e.GetMessage());
489 return CKM_API_ERROR_SERVER_ERROR;
493 int CKMLogic::getKeyForService(
494 const Credentials &cred,
496 const ClientId &explicitOwner,
497 const Password &pass,
498 Crypto::GObjShPtr &key)
501 // Key is for internal service use. It won't be exported to the client
502 Crypto::GObjUPtr obj;
503 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
506 if (retCode == CKM_API_SUCCESS)
507 key = std::move(obj);
510 } catch (const Exc::Exception &e) {
512 } catch (const CKM::Exception &e) {
513 LogError("CKM::Exception: " << e.GetMessage());
514 return CKM_API_ERROR_SERVER_ERROR;
518 RawBuffer CKMLogic::saveData(
519 const Credentials &cred,
522 const ClientId &explicitOwner,
523 const Crypto::Data &data,
524 const PolicySerializable &policy)
526 int retCode = verifyAndSaveDataHelper(cred, name, explicitOwner, data, policy);
527 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
530 static_cast<int>(data.type));
531 return response.Pop();
534 int CKMLogic::extractPKCS12Data(
537 const ClientId &owner,
538 const PKCS12Serializable &pkcs,
539 const PolicySerializable &keyPolicy,
540 const PolicySerializable &certPolicy,
541 DB::RowVector &output) const
543 // private key is mandatory
544 auto key = pkcs.getKey();
547 LogError("Failed to get private key from pkcs");
548 return CKM_API_ERROR_INVALID_FORMAT;
551 Crypto::Data keyData(DataType(key->getType()), key->getDER());
552 int retCode = verifyBinaryData(keyData);
554 if (retCode != CKM_API_SUCCESS)
557 output.push_back(createEncryptedRow(crypto, name, owner, keyData,
560 // certificate is mandatory
561 auto cert = pkcs.getCertificate();
564 LogError("Failed to get certificate from pkcs");
565 return CKM_API_ERROR_INVALID_FORMAT;
568 Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
569 retCode = verifyBinaryData(certData);
571 if (retCode != CKM_API_SUCCESS)
574 output.push_back(createEncryptedRow(crypto, name, owner, certData,
578 unsigned int cert_index = 0;
580 for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
581 Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++),
583 int retCode = verifyBinaryData(caCertData);
585 if (retCode != CKM_API_SUCCESS)
588 output.push_back(createEncryptedRow(crypto, name, owner, caCertData,
592 return CKM_API_SUCCESS;
595 RawBuffer CKMLogic::savePKCS12(
596 const Credentials &cred,
599 const ClientId &explicitOwner,
600 const PKCS12Serializable &pkcs,
601 const PolicySerializable &keyPolicy,
602 const PolicySerializable &certPolicy)
604 int retCode = CKM_API_ERROR_UNKNOWN;
607 retCode = saveDataHelper(cred, name, explicitOwner, pkcs, keyPolicy, certPolicy);
608 } catch (const Exc::Exception &e) {
610 } catch (const CKM::Exception &e) {
611 LogError("CKM::Exception: " << e.GetMessage());
612 retCode = CKM_API_ERROR_SERVER_ERROR;
615 auto response = MessageBuffer::Serialize(static_cast<int>
616 (LogicCommand::SAVE_PKCS12),
619 return response.Pop();
623 int CKMLogic::removeDataHelper(
624 const Credentials &cred,
626 const ClientId &explicitOwner)
628 auto &handler = selectDatabase(cred, explicitOwner);
630 // use client id if not explicitly provided
631 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
633 if (!isNameValid(name) || !isClientValid(owner)) {
634 LogDebug("Invalid owner or name format");
635 return CKM_API_ERROR_INPUT_PARAM;
638 DB::Crypto::Transaction transaction(&handler.database);
640 // read and check permissions
641 PermissionMaskOptional permissionRowOpt =
642 handler.database.getPermissionRow(name, owner, cred.client);
643 int retCode = m_accessControl.canDelete(cred,
644 toPermissionMask(permissionRowOpt));
646 if (retCode != CKM_API_SUCCESS) {
647 LogWarning("access control check result: " << retCode);
651 // get all matching rows
653 handler.database.getRows(name, owner, DataType::DB_FIRST,
654 DataType::DB_LAST, rows);
657 LogDebug("No row for given name and owner");
658 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
661 // load app key if needed
662 retCode = loadAppKey(handler, rows.front().owner);
664 if (CKM_API_SUCCESS != retCode)
667 // destroy it in store
668 for (auto &r : rows) {
670 handler.crypto.decryptRow(Password(), r);
671 m_decider.getStore(r).destroy(r);
672 } catch (const Exc::AuthenticationFailed &) {
673 LogDebug("Authentication failed when removing data. Ignored.");
678 handler.database.deleteRow(name, owner);
679 transaction.commit();
681 return CKM_API_SUCCESS;
684 RawBuffer CKMLogic::removeData(
685 const Credentials &cred,
688 const ClientId &explicitOwner)
690 int retCode = CKM_API_ERROR_UNKNOWN;
693 retCode = removeDataHelper(cred, name, explicitOwner);
694 } catch (const Exc::Exception &e) {
696 } catch (const CKM::Exception &e) {
697 LogError("Error: " << e.GetMessage());
698 retCode = CKM_API_ERROR_DB_ERROR;
701 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
704 return response.Pop();
707 int CKMLogic::readSingleRow(const Name &name,
708 const ClientId &owner,
710 DB::Crypto &database,
713 DB::Crypto::RowOptional row_optional;
715 if (dataType.isKey()) {
716 // read all key types
717 row_optional = database.getRow(name,
719 DataType::DB_KEY_FIRST,
720 DataType::DB_KEY_LAST);
722 // read anything else
723 row_optional = database.getRow(name,
729 LogDebug("No row for given name, owner and type");
730 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
735 return CKM_API_SUCCESS;
739 int CKMLogic::readMultiRow(const Name &name,
740 const ClientId &owner,
742 DB::Crypto &database,
743 DB::RowVector &output)
745 if (dataType.isKey())
746 // read all key types
747 database.getRows(name,
749 DataType::DB_KEY_FIRST,
750 DataType::DB_KEY_LAST,
752 else if (dataType.isChainCert())
753 // read all key types
754 database.getRows(name,
756 DataType::DB_CHAIN_FIRST,
757 DataType::DB_CHAIN_LAST,
760 // read anything else
761 database.getRows(name,
766 if (!output.size()) {
767 LogDebug("No row for given name, owner and type");
768 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
771 return CKM_API_SUCCESS;
774 int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred,
776 const ClientId &owner,
779 DB::Crypto &database)
781 PermissionMaskOptional permissionRowOpt =
782 database.getPermissionRow(name, owner, accessorCred.client);
785 return m_accessControl.canExport(accessorCred,
787 toPermissionMask(permissionRowOpt));
789 return m_accessControl.canRead(accessorCred,
790 toPermissionMask(permissionRowOpt));
793 Crypto::GObjUPtr CKMLogic::rowToObject(
796 const Password &password)
798 Crypto::GStore &store = m_decider.getStore(row);
800 Password pass = m_accessControl.isCCMode() ? "" : password;
803 Crypto::GObjUPtr obj;
805 if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
806 CryptoLogic::ENCRYPTION_V2) {
807 handler.crypto.decryptRow(Password(), row);
809 obj = store.getObject(row, pass);
811 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
812 handler.crypto.decryptRow(pass, row);
813 // destroy it in store
816 // import it to store with new scheme: data -> pass(data)
817 Token token = store.import(Crypto::Data(row.dataType, row.data), pass, Crypto::EncryptionParams());
819 // get it from the store (it can be different than the data we imported into store)
820 obj = store.getObject(token, pass);
822 // update row with new token
823 *static_cast<Token *>(&row) = std::move(token);
825 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
826 handler.crypto.encryptRow(row);
829 handler.database.updateRow(row);
835 int CKMLogic::readDataHelper(
837 const Credentials &cred,
840 const ClientId &explicitOwner,
841 const Password &password,
842 Crypto::GObjUPtrVector &objs)
844 auto &handler = selectDatabase(cred, explicitOwner);
846 // use client id if not explicitly provided
847 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
849 if (!isNameValid(name) || !isClientValid(owner))
850 return CKM_API_ERROR_INPUT_PARAM;
853 DB::Crypto::Transaction transaction(&handler.database);
855 int retCode = readMultiRow(name, owner, dataType, handler.database, rows);
857 if (CKM_API_SUCCESS != retCode)
860 // all read rows belong to the same owner
861 DB::Row &firstRow = rows.at(0);
863 // check access rights
864 retCode = checkDataPermissionsHelper(cred, name, owner, firstRow,
865 exportFlag, handler.database);
867 if (CKM_API_SUCCESS != retCode)
870 // load app key if needed
871 retCode = loadAppKey(handler, firstRow.owner);
873 if (CKM_API_SUCCESS != retCode)
877 for (auto &row : rows)
878 objs.push_back(rowToObject(handler, std::move(row), password));
880 // rowToObject may modify db
881 transaction.commit();
883 return CKM_API_SUCCESS;
886 int CKMLogic::readDataHelper(
888 const Credentials &cred,
891 const ClientId &explicitOwner,
892 const Password &password,
893 Crypto::GObjUPtr &obj)
895 DataType objDataType;
896 return readDataHelper(exportFlag, cred, dataType, name, explicitOwner,
897 password, obj, objDataType);
900 int CKMLogic::readDataHelper(
902 const Credentials &cred,
905 const ClientId &explicitOwner,
906 const Password &password,
907 Crypto::GObjUPtr &obj,
908 DataType &objDataType)
910 auto &handler = selectDatabase(cred, explicitOwner);
912 // use client id if not explicitly provided
913 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
915 if (!isNameValid(name) || !isClientValid(owner))
916 return CKM_API_ERROR_INPUT_PARAM;
919 DB::Crypto::Transaction transaction(&handler.database);
921 int retCode = readSingleRow(name, owner, dataType, handler.database, row);
923 if (CKM_API_SUCCESS != retCode)
926 objDataType = row.dataType;
928 // check access rights
929 retCode = checkDataPermissionsHelper(cred, name, owner, row, exportFlag,
932 if (CKM_API_SUCCESS != retCode)
935 // load app key if needed
936 retCode = loadAppKey(handler, row.owner);
938 if (CKM_API_SUCCESS != retCode)
941 obj = rowToObject(handler, std::move(row), password);
942 // rowToObject may modify db
943 transaction.commit();
945 return CKM_API_SUCCESS;
948 RawBuffer CKMLogic::getData(
949 const Credentials &cred,
953 const ClientId &explicitOwner,
954 const Password &password)
956 int retCode = CKM_API_SUCCESS;
958 DataType objDataType;
961 Crypto::GObjUPtr obj;
962 retCode = readDataHelper(true, cred, dataType, name, explicitOwner,
963 password, obj, objDataType);
965 if (retCode == CKM_API_SUCCESS)
966 rowData = obj->getBinary();
967 } catch (const Exc::Exception &e) {
969 } catch (const CKM::Exception &e) {
970 LogError("CKM::Exception: " << e.GetMessage());
971 retCode = CKM_API_ERROR_SERVER_ERROR;
974 if (CKM_API_SUCCESS != retCode)
977 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
980 static_cast<int>(objDataType),
982 return response.Pop();
985 RawBuffer CKMLogic::getDataProtectionStatus(
986 const Credentials &cred,
990 const ClientId &explicitOwner)
992 int retCode = CKM_API_SUCCESS;
994 DataType objDataType;
998 Crypto::GObjUPtr obj;
999 retCode = readDataHelper(false, cred, dataType, name, explicitOwner,
1000 password, obj, objDataType);
1002 } catch (const Exc::Exception &e) {
1003 retCode = e.error();
1004 } catch (const CKM::Exception &e) {
1005 LogError("CKM::Exception: " << e.GetMessage());
1006 retCode = CKM_API_ERROR_SERVER_ERROR;
1009 if (retCode == CKM_API_ERROR_AUTHENTICATION_FAILED) {
1011 retCode = CKM_API_SUCCESS;
1014 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PROTECTION_STATUS),
1017 static_cast<int>(objDataType),
1019 return response.Pop();
1022 int CKMLogic::getPKCS12Helper(
1023 const Credentials &cred,
1025 const ClientId &explicitOwner,
1026 const Password &keyPassword,
1027 const Password &certPassword,
1029 CertificateShPtr &cert,
1030 CertificateShPtrVector &caChain)
1034 // read private key (mandatory)
1035 Crypto::GObjUPtr keyObj;
1036 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
1037 keyPassword, keyObj);
1039 if (retCode != CKM_API_SUCCESS) {
1040 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1043 privKey = CKM::Key::create(keyObj->getBinary());
1046 // read certificate (mandatory)
1047 Crypto::GObjUPtr certObj;
1048 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, explicitOwner,
1049 certPassword, certObj);
1051 if (retCode != CKM_API_SUCCESS) {
1052 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1055 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
1058 // read CA cert chain (optional)
1059 Crypto::GObjUPtrVector caChainObjs;
1060 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, explicitOwner,
1061 certPassword, caChainObjs);
1063 if (retCode != CKM_API_SUCCESS && retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1064 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1067 for (auto &caCertObj : caChainObjs)
1068 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
1069 DataFormat::FORM_DER));
1072 // if anything found, return it
1073 if (privKey || cert || caChain.size() > 0)
1074 retCode = CKM_API_SUCCESS;
1079 RawBuffer CKMLogic::getPKCS12(
1080 const Credentials &cred,
1083 const ClientId &explicitOwner,
1084 const Password &keyPassword,
1085 const Password &certPassword)
1087 int retCode = CKM_API_ERROR_UNKNOWN;
1089 PKCS12Serializable output;
1093 CertificateShPtr cert;
1094 CertificateShPtrVector caChain;
1095 retCode = getPKCS12Helper(cred, name, explicitOwner, keyPassword,
1096 certPassword, privKey, cert, caChain);
1099 if (retCode == CKM_API_SUCCESS)
1100 output = PKCS12Serializable(std::move(privKey), std::move(cert),
1101 std::move(caChain));
1102 } catch (const Exc::Exception &e) {
1103 retCode = e.error();
1104 } catch (const CKM::Exception &e) {
1105 LogError("CKM::Exception: " << e.GetMessage());
1106 retCode = CKM_API_ERROR_SERVER_ERROR;
1109 auto response = MessageBuffer::Serialize(static_cast<int>
1110 (LogicCommand::GET_PKCS12),
1114 return response.Pop();
1117 int CKMLogic::getDataListHelper(const Credentials &cred,
1118 const DataType dataType,
1119 OwnerNameVector &ownerNameVector)
1121 int retCode = CKM_API_ERROR_DB_LOCKED;
1123 if (0 < m_userDataMap.count(cred.clientUid)) {
1124 auto &database = m_userDataMap[cred.clientUid].database;
1127 OwnerNameVector tmpVector;
1129 if (dataType.isKey()) {
1130 // list all key types
1131 database.listNames(cred.client,
1133 DataType::DB_KEY_FIRST,
1134 DataType::DB_KEY_LAST);
1136 // list anything else
1137 database.listNames(cred.client,
1142 ownerNameVector.insert(ownerNameVector.end(), tmpVector.begin(),
1144 retCode = CKM_API_SUCCESS;
1145 } catch (const CKM::Exception &e) {
1146 LogError("Error: " << e.GetMessage());
1147 retCode = CKM_API_ERROR_DB_ERROR;
1148 } catch (const Exc::Exception &e) {
1149 retCode = e.error();
1156 RawBuffer CKMLogic::getDataList(
1157 const Credentials &cred,
1161 OwnerNameVector systemVector;
1162 OwnerNameVector userVector;
1163 OwnerNameVector ownerNameVector;
1165 int retCode = unlockSystemDB();
1167 if (CKM_API_SUCCESS == retCode) {
1169 if (m_accessControl.isSystemService(cred)) {
1171 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1176 // user - lookup system, then client DB
1177 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1183 if (retCode == CKM_API_SUCCESS) {
1184 retCode = getDataListHelper(cred,
1191 if (retCode == CKM_API_SUCCESS) {
1192 ownerNameVector.insert(ownerNameVector.end(), systemVector.begin(),
1193 systemVector.end());
1194 ownerNameVector.insert(ownerNameVector.end(), userVector.begin(),
1198 auto response = MessageBuffer::Serialize(static_cast<int>
1199 (LogicCommand::GET_LIST),
1202 static_cast<int>(dataType),
1204 return response.Pop();
1207 int CKMLogic::importInitialData(
1209 const Crypto::Data &data,
1210 const Crypto::EncryptionParams &encParams,
1211 const Policy &policy)
1214 if (encParams.iv.empty() != encParams.tag.empty()) {
1215 LogError("Both iv and tag must be empty or set");
1216 return CKM_API_ERROR_INPUT_PARAM;
1219 // Inital values are always imported with root credentials. Client id is not important.
1220 Credentials rootCred(0, "");
1222 auto &handler = selectDatabase(rootCred, CLIENT_ID_SYSTEM);
1224 // check if save is possible
1225 DB::Crypto::Transaction transaction(&handler.database);
1226 int retCode = checkSaveConditions(rootCred, handler, name, CLIENT_ID_SYSTEM);
1228 if (retCode != CKM_API_SUCCESS)
1231 Crypto::GStore &store =
1232 m_decider.getStore(data.type, policy, !encParams.iv.empty());
1236 if (encParams.iv.empty()) {
1237 // Data are not encrypted, let's try to verify them
1238 Crypto::Data binaryData;
1240 if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1243 token = store.import(binaryData,
1244 m_accessControl.isCCMode() ? "" : policy.password,
1247 token = store.import(data,
1248 m_accessControl.isCCMode() ? "" : policy.password,
1252 DB::Row row(std::move(token), name, CLIENT_ID_SYSTEM,
1253 static_cast<int>(policy.extractable));
1254 handler.crypto.encryptRow(row);
1256 handler.database.saveRow(row);
1257 transaction.commit();
1258 } catch (const Exc::Exception &e) {
1260 } catch (const CKM::Exception &e) {
1261 LogError("CKM::Exception: " << e.GetMessage());
1262 return CKM_API_ERROR_SERVER_ERROR;
1263 } catch (const std::exception &e) {
1264 LogError("Std::exception: " << e.what());
1265 return CKM_API_ERROR_SERVER_ERROR;
1268 return CKM_API_SUCCESS;
1271 int CKMLogic::saveDataHelper(
1272 const Credentials &cred,
1274 const ClientId &explicitOwner,
1275 const Crypto::Data &data,
1276 const PolicySerializable &policy)
1278 auto &handler = selectDatabase(cred, explicitOwner);
1280 // use client id if not explicitly provided
1281 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1283 if (m_accessControl.isSystemService(cred) &&
1284 owner.compare(CLIENT_ID_SYSTEM) != 0) {
1285 LogError("System services can only use " << CLIENT_ID_SYSTEM << " as owner id") ;
1286 return CKM_API_ERROR_INPUT_PARAM;
1289 // check if save is possible
1290 DB::Crypto::Transaction transaction(&handler.database);
1291 int retCode = checkSaveConditions(cred, handler, name, owner);
1293 if (retCode != CKM_API_SUCCESS)
1297 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, owner,
1299 handler.database.saveRow(encryptedRow);
1301 transaction.commit();
1302 return CKM_API_SUCCESS;
1305 int CKMLogic::saveDataHelper(
1306 const Credentials &cred,
1308 const ClientId &explicitOwner,
1309 const PKCS12Serializable &pkcs,
1310 const PolicySerializable &keyPolicy,
1311 const PolicySerializable &certPolicy)
1313 auto &handler = selectDatabase(cred, explicitOwner);
1315 // use client id if not explicitly provided
1316 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1318 if (m_accessControl.isSystemService(cred) &&
1319 owner.compare(CLIENT_ID_SYSTEM) != 0)
1320 return CKM_API_ERROR_INPUT_PARAM;
1322 // check if save is possible
1323 DB::Crypto::Transaction transaction(&handler.database);
1324 int retCode = checkSaveConditions(cred, handler, name, owner);
1326 if (retCode != CKM_API_SUCCESS)
1329 // extract and encrypt the data
1330 DB::RowVector encryptedRows;
1331 retCode = extractPKCS12Data(handler.crypto, name, owner, pkcs, keyPolicy,
1332 certPolicy, encryptedRows);
1334 if (retCode != CKM_API_SUCCESS)
1338 handler.database.saveRows(name, owner, encryptedRows);
1339 transaction.commit();
1341 return CKM_API_SUCCESS;
1345 int CKMLogic::createKeyAESHelper(
1346 const Credentials &cred,
1349 const ClientId &explicitOwner,
1350 const PolicySerializable &policy)
1352 auto &handler = selectDatabase(cred, explicitOwner);
1354 // use client id if not explicitly provided
1355 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1357 if (m_accessControl.isSystemService(cred) &&
1358 owner.compare(CLIENT_ID_SYSTEM) != 0)
1359 return CKM_API_ERROR_INPUT_PARAM;
1361 // check if save is possible
1362 DB::Crypto::Transaction transaction(&handler.database);
1363 int retCode = checkSaveConditions(cred, handler, name, owner);
1365 if (retCode != CKM_API_SUCCESS)
1368 // create key in store
1369 CryptoAlgorithm keyGenAlgorithm;
1370 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1371 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1372 Token key = m_decider.getStore(DataType::KEY_AES,
1373 policy).generateSKey(keyGenAlgorithm, policy.password);
1376 DB::Row row(std::move(key), name, owner,
1377 static_cast<int>(policy.extractable));
1378 handler.crypto.encryptRow(row);
1380 handler.database.saveRow(row);
1382 transaction.commit();
1383 return CKM_API_SUCCESS;
1386 int CKMLogic::createKeyPairHelper(
1387 const Credentials &cred,
1388 const CryptoAlgorithmSerializable &keyGenParams,
1389 const Name &namePrivate,
1390 const ClientId &explicitOwnerPrivate,
1391 const Name &namePublic,
1392 const ClientId &explicitOwnerPublic,
1393 const PolicySerializable &policyPrivate,
1394 const PolicySerializable &policyPublic)
1396 auto &handlerPriv = selectDatabase(cred, explicitOwnerPrivate);
1397 auto &handlerPub = selectDatabase(cred, explicitOwnerPublic);
1399 AlgoType keyType = AlgoType::RSA_GEN;
1401 if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1402 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1404 const auto dtIt = ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.find(keyType);
1405 if (dtIt == ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.end())
1406 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1407 const DataTypePair& dt = dtIt->second;
1409 if (policyPrivate.backend != policyPublic.backend)
1410 ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend.");
1412 // use client id if not explicitly provided
1413 const ClientId &ownerPrv = explicitOwnerPrivate.empty() ? cred.client :
1414 explicitOwnerPrivate;
1416 if (m_accessControl.isSystemService(cred) &&
1417 ownerPrv.compare(CLIENT_ID_SYSTEM) != 0)
1418 return CKM_API_ERROR_INPUT_PARAM;
1420 const ClientId &ownerPub = explicitOwnerPublic.empty() ? cred.client :
1421 explicitOwnerPublic;
1423 if (m_accessControl.isSystemService(cred) &&
1424 ownerPub.compare(CLIENT_ID_SYSTEM) != 0)
1425 return CKM_API_ERROR_INPUT_PARAM;
1427 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1428 Policy lessRestricted(Password(), exportable, policyPrivate.backend);
1430 Crypto::DataParams params{
1431 Crypto::DataParam(dt.first, policyPrivate),
1432 Crypto::DataParam(dt.second, policyPublic),
1435 TokenPair keys = m_decider.getStore(params).generateAKey(keyGenParams,
1436 policyPrivate.password,
1437 policyPublic.password);
1439 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1440 // in case the same database is used for private and public - the second
1441 // transaction will not be executed
1442 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1445 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerPrv);
1447 if (CKM_API_SUCCESS != retCode)
1450 retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerPub);
1452 if (CKM_API_SUCCESS != retCode)
1456 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerPrv,
1457 static_cast<int>(policyPrivate.extractable));
1458 handlerPriv.crypto.encryptRow(rowPrv);
1459 handlerPriv.database.saveRow(rowPrv);
1461 DB::Row rowPub(std::move(keys.second), namePublic, ownerPub,
1462 static_cast<int>(policyPublic.extractable));
1463 handlerPub.crypto.encryptRow(rowPub);
1464 handlerPub.database.saveRow(rowPub);
1466 transactionPub.commit();
1467 transactionPriv.commit();
1468 return CKM_API_SUCCESS;
1471 RawBuffer CKMLogic::createKeyPair(
1472 const Credentials &cred,
1474 const CryptoAlgorithmSerializable &keyGenParams,
1475 const Name &namePrivate,
1476 const ClientId &explicitOwnerPrivate,
1477 const Name &namePublic,
1478 const ClientId &explicitOwnerPublic,
1479 const PolicySerializable &policyPrivate,
1480 const PolicySerializable &policyPublic)
1482 int retCode = CKM_API_SUCCESS;
1485 retCode = createKeyPairHelper(
1489 explicitOwnerPrivate,
1491 explicitOwnerPublic,
1494 } catch (const Exc::Exception &e) {
1495 retCode = e.error();
1496 } catch (const CKM::Exception &e) {
1497 LogError("CKM::Exception: " << e.GetMessage());
1498 retCode = CKM_API_ERROR_SERVER_ERROR;
1501 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1502 commandId, retCode).Pop();
1505 RawBuffer CKMLogic::createKeyAES(
1506 const Credentials &cred,
1510 const ClientId &explicitOwner,
1511 const PolicySerializable &policy)
1513 int retCode = CKM_API_SUCCESS;
1516 retCode = createKeyAESHelper(cred, size, name, explicitOwner, policy);
1517 } catch (const Exc::Exception &e) {
1518 retCode = e.error();
1519 } catch (std::invalid_argument &e) {
1520 LogDebug("invalid argument error: " << e.what());
1521 retCode = CKM_API_ERROR_INPUT_PARAM;
1522 } catch (const CKM::Exception &e) {
1523 LogError("CKM::Exception: " << e.GetMessage());
1524 retCode = CKM_API_ERROR_SERVER_ERROR;
1527 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1528 commandId, retCode).Pop();
1531 int CKMLogic::readCertificateHelper(
1532 const Credentials &cred,
1533 const OwnerNameVector &ownerNameVector,
1534 CertificateImplVector &certVector)
1536 for (auto &i : ownerNameVector) {
1537 // certificates can't be protected with custom user password
1538 Crypto::GObjUPtr obj;
1540 ec = readDataHelper(true,
1542 DataType::CERTIFICATE,
1548 if (ec != CKM_API_SUCCESS)
1551 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1553 // try to read chain certificates (if present)
1554 Crypto::GObjUPtrVector caChainObjs;
1555 ec = readDataHelper(true,
1557 DataType::DB_CHAIN_FIRST,
1563 if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1566 for (auto &caCertObj : caChainObjs)
1567 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1570 return CKM_API_SUCCESS;
1573 int CKMLogic::getCertificateChainHelper(
1574 const CertificateImpl &cert,
1575 const RawBufferVector &untrustedCertificates,
1576 const RawBufferVector &trustedCertificates,
1577 bool useTrustedSystemCertificates,
1578 RawBufferVector &chainRawVector)
1580 CertificateImplVector untrustedCertVector;
1581 CertificateImplVector trustedCertVector;
1582 CertificateImplVector chainVector;
1585 return CKM_API_ERROR_INPUT_PARAM;
1587 for (auto &e : untrustedCertificates) {
1588 CertificateImpl c(e, DataFormat::FORM_DER);
1591 return CKM_API_ERROR_INPUT_PARAM;
1593 untrustedCertVector.push_back(std::move(c));
1596 for (auto &e : trustedCertificates) {
1597 CertificateImpl c(e, DataFormat::FORM_DER);
1600 return CKM_API_ERROR_INPUT_PARAM;
1602 trustedCertVector.push_back(std::move(c));
1605 CertificateStore store;
1606 int retCode = store.verifyCertificate(cert,
1607 untrustedCertVector,
1609 useTrustedSystemCertificates,
1610 m_accessControl.isCCMode(),
1613 if (retCode != CKM_API_SUCCESS)
1616 for (auto &e : chainVector)
1617 chainRawVector.push_back(e.getDER());
1619 return CKM_API_SUCCESS;
1622 int CKMLogic::getCertificateChainHelper(
1623 const Credentials &cred,
1624 const CertificateImpl &cert,
1625 const OwnerNameVector &untrusted,
1626 const OwnerNameVector &trusted,
1627 bool useTrustedSystemCertificates,
1628 RawBufferVector &chainRawVector)
1630 CertificateImplVector untrustedCertVector;
1631 CertificateImplVector trustedCertVector;
1632 CertificateImplVector chainVector;
1635 return CKM_API_ERROR_INPUT_PARAM;
1637 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1639 if (retCode != CKM_API_SUCCESS)
1642 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1644 if (retCode != CKM_API_SUCCESS)
1647 CertificateStore store;
1648 retCode = store.verifyCertificate(cert,
1649 untrustedCertVector,
1651 useTrustedSystemCertificates,
1652 m_accessControl.isCCMode(),
1655 if (retCode != CKM_API_SUCCESS)
1658 for (auto &i : chainVector)
1659 chainRawVector.push_back(i.getDER());
1661 return CKM_API_SUCCESS;
1664 RawBuffer CKMLogic::getCertificateChain(
1665 const Credentials & /*cred*/,
1667 const RawBuffer &certificate,
1668 const RawBufferVector &untrustedCertificates,
1669 const RawBufferVector &trustedCertificates,
1670 bool useTrustedSystemCertificates)
1672 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1673 RawBufferVector chainRawVector;
1674 int retCode = CKM_API_ERROR_UNKNOWN;
1677 retCode = getCertificateChainHelper(cert,
1678 untrustedCertificates,
1679 trustedCertificates,
1680 useTrustedSystemCertificates,
1682 } catch (const Exc::Exception &e) {
1683 retCode = e.error();
1684 } catch (const std::exception &e) {
1685 LogError("STD exception " << e.what());
1686 retCode = CKM_API_ERROR_SERVER_ERROR;
1688 LogError("Unknown error.");
1691 auto response = MessageBuffer::Serialize(static_cast<int>
1692 (LogicCommand::GET_CHAIN_CERT),
1696 return response.Pop();
1699 RawBuffer CKMLogic::getCertificateChain(
1700 const Credentials &cred,
1702 const RawBuffer &certificate,
1703 const OwnerNameVector &untrustedCertificates,
1704 const OwnerNameVector &trustedCertificates,
1705 bool useTrustedSystemCertificates)
1707 int retCode = CKM_API_ERROR_UNKNOWN;
1708 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1709 RawBufferVector chainRawVector;
1712 retCode = getCertificateChainHelper(cred,
1714 untrustedCertificates,
1715 trustedCertificates,
1716 useTrustedSystemCertificates,
1718 } catch (const Exc::Exception &e) {
1719 retCode = e.error();
1720 } catch (const std::exception &e) {
1721 LogError("STD exception " << e.what());
1722 retCode = CKM_API_ERROR_SERVER_ERROR;
1724 LogError("Unknown error.");
1727 auto response = MessageBuffer::Serialize(static_cast<int>
1728 (LogicCommand::GET_CHAIN_ALIAS),
1732 return response.Pop();
1735 RawBuffer CKMLogic::createSignature(
1736 const Credentials &cred,
1738 const Name &privateKeyName,
1739 const ClientId &explicitOwner,
1740 const Password &password, // password for private_key
1741 const RawBuffer &message,
1742 const CryptoAlgorithm &cryptoAlg)
1744 RawBuffer signature;
1746 int retCode = CKM_API_SUCCESS;
1749 Crypto::GObjUPtr obj;
1750 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
1751 explicitOwner, password, obj);
1753 if (retCode == CKM_API_SUCCESS)
1754 signature = obj->sign(cryptoAlg, message);
1755 } catch (const Exc::Exception &e) {
1756 retCode = e.error();
1757 } catch (const CKM::Exception &e) {
1758 LogError("Unknown CKM::Exception: " << e.GetMessage());
1759 retCode = CKM_API_ERROR_SERVER_ERROR;
1760 } catch (const std::exception &e) {
1761 LogError("STD exception " << e.what());
1762 retCode = CKM_API_ERROR_SERVER_ERROR;
1765 auto response = MessageBuffer::Serialize(static_cast<int>
1766 (LogicCommand::CREATE_SIGNATURE),
1770 return response.Pop();
1773 RawBuffer CKMLogic::verifySignature(
1774 const Credentials &cred,
1776 const Name &publicKeyOrCertName,
1777 const ClientId &explicitOwner,
1778 const Password &password, // password for public_key (optional)
1779 const RawBuffer &message,
1780 const RawBuffer &signature,
1781 const CryptoAlgorithm ¶ms)
1783 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1786 // try certificate first - looking for a public key.
1787 // in case of PKCS, pub key from certificate will be found first
1788 // rather than private key from the same PKCS.
1789 Crypto::GObjUPtr obj;
1790 retCode = readDataHelper(false, cred, DataType::CERTIFICATE,
1791 publicKeyOrCertName, explicitOwner, password, obj);
1793 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1794 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
1795 publicKeyOrCertName, explicitOwner, password, obj);
1797 if (retCode == CKM_API_SUCCESS)
1798 retCode = obj->verify(params, message, signature);
1799 } catch (const Exc::Exception &e) {
1800 retCode = e.error();
1801 } catch (const CKM::Exception &e) {
1802 LogError("Unknown CKM::Exception: " << e.GetMessage());
1803 retCode = CKM_API_ERROR_SERVER_ERROR;
1806 auto response = MessageBuffer::Serialize(static_cast<int>
1807 (LogicCommand::VERIFY_SIGNATURE),
1810 return response.Pop();
1813 int CKMLogic::setPermissionHelper(
1814 const Credentials &cred, // who's the client
1816 const ClientId &explicitOwner, // who's the owner
1817 const ClientId &accessor, // who will get the access
1818 const PermissionMask permissionMask)
1820 auto &handler = selectDatabase(cred, explicitOwner);
1822 // we don't know the client
1823 if (cred.client.empty() || !isClientValid(cred.client))
1824 return CKM_API_ERROR_INPUT_PARAM;
1826 // use client id if not explicitly provided
1827 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1829 // verify name and owner are correct
1830 if (!isNameValid(name) || !isClientValid(owner) ||
1831 !isClientValid(accessor))
1832 return CKM_API_ERROR_INPUT_PARAM;
1834 // currently we don't support modification of owner's permissions to his own rows
1835 if (owner == accessor)
1836 return CKM_API_ERROR_INPUT_PARAM;
1838 // system database does not support write/remove permissions
1839 if ((0 == owner.compare(CLIENT_ID_SYSTEM)) &&
1840 (permissionMask & Permission::REMOVE))
1841 return CKM_API_ERROR_INPUT_PARAM;
1843 // can the client modify permissions to owner's row?
1844 int retCode = m_accessControl.canModify(cred, owner);
1846 if (retCode != CKM_API_SUCCESS)
1849 DB::Crypto::Transaction transaction(&handler.database);
1851 if (!handler.database.isNameOwnerPresent(name, owner))
1852 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1854 // set permissions to the row owned by owner for accessor
1855 handler.database.setPermission(name, owner, accessor, permissionMask);
1856 transaction.commit();
1858 return CKM_API_SUCCESS;
1861 RawBuffer CKMLogic::setPermission(
1862 const Credentials &cred,
1866 const ClientId &explicitOwner,
1867 const ClientId &accessor,
1868 const PermissionMask permissionMask)
1873 retCode = setPermissionHelper(cred, name, explicitOwner, accessor, permissionMask);
1874 } catch (const Exc::Exception &e) {
1875 retCode = e.error();
1876 } catch (const CKM::Exception &e) {
1877 LogError("Error: " << e.GetMessage());
1878 retCode = CKM_API_ERROR_DB_ERROR;
1881 return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1884 int CKMLogic::loadAppKey(UserData &handle, const ClientId &owner)
1886 if (!handle.crypto.haveKey(owner)) {
1888 auto key_optional = handle.database.getKey(owner);
1890 if (!key_optional) {
1891 LogError("No key for given owner in database");
1892 return CKM_API_ERROR_DB_ERROR;
1895 key = *key_optional;
1896 key = handle.keyProvider.getPureDEK(key);
1897 handle.crypto.pushKey(owner, key);
1900 return CKM_API_SUCCESS;