2 * Copyright (c) 2000 - 2014 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 } // anonymous namespace
62 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
63 const uid_t CKMLogic::ADMIN_USER_DB_UID = 5001;
67 CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
69 m_accessControl.updateCCMode();
72 CKMLogic::~CKMLogic() {}
74 void CKMLogic::loadDKEKFile(uid_t user, const Password &password)
76 auto &handle = m_userDataMap[user];
80 auto wrappedDKEK = fs.getDKEK();
82 if (wrappedDKEK.empty()) {
83 wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
84 fs.saveDKEK(wrappedDKEK);
87 handle.keyProvider = KeyProvider(wrappedDKEK, password);
90 void CKMLogic::saveDKEKFile(uid_t user, const Password &password)
92 auto &handle = m_userDataMap[user];
95 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
98 void CKMLogic::migrateSecureStorageData(bool isAdminUser)
100 SsMigration::migrate(isAdminUser, [this](const std::string &name,
101 const Crypto::Data &data,
102 bool adminUserFlag) {
103 LogInfo("Migrate data called with name: " << name);
104 auto ownerId = adminUserFlag ? CLIENT_ID_ADMIN_USER : CLIENT_ID_SYSTEM;
105 auto uid = adminUserFlag ? ADMIN_USER_DB_UID : SYSTEM_DB_UID;
107 int ret = verifyAndSaveDataHelper(Credentials(uid, ownerId), name, ownerId, data,
108 PolicySerializable());
110 if (ret == CKM_API_ERROR_DB_ALIAS_EXISTS)
111 LogWarning("Alias already exist for migrated name: " << name);
112 else if (ret != CKM_API_SUCCESS)
113 LogError("Failed to migrate secure-storage data. name: " << name <<
118 int CKMLogic::unlockDatabase(uid_t user, const Password &password)
120 if (0 < m_userDataMap.count(user) &&
121 m_userDataMap[user].keyProvider.isInitialized())
122 return CKM_API_SUCCESS;
124 int retCode = CKM_API_SUCCESS;
127 auto &handle = m_userDataMap[user];
130 loadDKEKFile(user, password);
132 auto wrappedDatabaseDEK = fs.getDBDEK();
134 if (wrappedDatabaseDEK.empty()) {
135 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
136 fs.saveDBDEK(wrappedDatabaseDEK);
139 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
141 handle.database = DB::Crypto(fs.getDBPath(), key);
142 handle.crypto = CryptoLogic();
144 if (!m_accessControl.isSystemService(user)) {
145 // remove data of removed apps during locked state
146 ClientIdVector removedApps = fs.clearRemovedsApps();
148 for (auto &app : removedApps) {
149 handle.crypto.removeKey(app);
150 handle.database.deleteKey(app);
154 if (user == SYSTEM_DB_UID && SsMigration::hasData())
155 migrateSecureStorageData(false);
156 else if (user == ADMIN_USER_DB_UID && SsMigration::hasData())
157 migrateSecureStorageData(true);
158 } catch (const Exc::Exception &e) {
160 } catch (const CKM::Exception &e) {
161 LogError("CKM::Exception: " << e.GetMessage());
162 retCode = CKM_API_ERROR_SERVER_ERROR;
165 if (CKM_API_SUCCESS != retCode)
166 m_userDataMap.erase(user);
171 int CKMLogic::unlockSystemDB()
173 return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
176 UserData &CKMLogic::selectDatabase(const Credentials &cred,
177 const ClientId &explicitOwner)
179 // if user trying to access system service - check:
180 // * if user database is unlocked [mandatory]
181 // * if not - proceed with regular user database
182 // * if explicit system database owner given -> switch to system DB
183 if (!m_accessControl.isSystemService(cred)) {
184 if (0 == m_userDataMap.count(cred.clientUid))
185 ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
187 if (0 != explicitOwner.compare(CLIENT_ID_SYSTEM))
188 return m_userDataMap[cred.clientUid];
191 // system database selected, modify the owner id
192 if (CKM_API_SUCCESS != unlockSystemDB())
193 ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
195 return m_userDataMap[SYSTEM_DB_UID];
198 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
200 int retCode = CKM_API_SUCCESS;
202 if (!m_accessControl.isSystemService(user))
203 retCode = unlockDatabase(user, password);
204 else // do not allow lock/unlock operations for system users
205 retCode = CKM_API_ERROR_INPUT_PARAM;
207 return MessageBuffer::Serialize(retCode).Pop();
210 RawBuffer CKMLogic::updateCCMode()
212 m_accessControl.updateCCMode();
213 return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
216 RawBuffer CKMLogic::lockUserKey(uid_t user)
218 int retCode = CKM_API_SUCCESS;
220 if (!m_accessControl.isSystemService(user))
221 m_userDataMap.erase(user);
222 else // do not allow lock/unlock operations for system users
223 retCode = CKM_API_ERROR_INPUT_PARAM;
225 return MessageBuffer::Serialize(retCode).Pop();
228 RawBuffer CKMLogic::removeUserData(uid_t user)
230 int retCode = CKM_API_SUCCESS;
232 if (m_accessControl.isSystemService(user))
233 user = SYSTEM_DB_UID;
235 m_userDataMap.erase(user);
240 return MessageBuffer::Serialize(retCode).Pop();
243 int CKMLogic::changeUserPasswordHelper(uid_t user,
244 const Password &oldPassword,
245 const Password &newPassword)
247 // do not allow to change system database password
248 if (m_accessControl.isSystemService(user))
249 return CKM_API_ERROR_INPUT_PARAM;
251 loadDKEKFile(user, oldPassword);
252 saveDKEKFile(user, newPassword);
254 return CKM_API_SUCCESS;
257 RawBuffer CKMLogic::changeUserPassword(
259 const Password &oldPassword,
260 const Password &newPassword)
262 int retCode = CKM_API_SUCCESS;
265 retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
266 } catch (const Exc::Exception &e) {
268 } catch (const CKM::Exception &e) {
269 LogError("CKM::Exception: " << e.GetMessage());
270 retCode = CKM_API_ERROR_SERVER_ERROR;
273 return MessageBuffer::Serialize(retCode).Pop();
276 int CKMLogic::resetUserPasswordHelper(
278 const Password &newPassword)
280 // do not allow to reset system database password
281 if (m_accessControl.isSystemService(user))
282 return CKM_API_ERROR_INPUT_PARAM;
284 int retCode = CKM_API_SUCCESS;
286 if (0 == m_userDataMap.count(user)) {
287 // Check if key exists. If exists we must return error
289 auto wrappedDKEKMain = fs.getDKEK();
291 if (!wrappedDKEKMain.empty())
292 retCode = CKM_API_ERROR_BAD_REQUEST;
294 saveDKEKFile(user, newPassword);
300 RawBuffer CKMLogic::resetUserPassword(
302 const Password &newPassword)
304 int retCode = CKM_API_SUCCESS;
307 retCode = resetUserPasswordHelper(user, newPassword);
308 } catch (const Exc::Exception &e) {
310 } catch (const CKM::Exception &e) {
311 LogError("CKM::Exception: " << e.GetMessage());
312 retCode = CKM_API_ERROR_SERVER_ERROR;
315 return MessageBuffer::Serialize(retCode).Pop();
318 RawBuffer CKMLogic::removeApplicationData(const ClientId &owner)
320 int retCode = CKM_API_SUCCESS;
324 retCode = CKM_API_ERROR_INPUT_PARAM;
326 UidVector uids = FileSystem::getUIDsFromDBFile();
328 for (auto userId : uids) {
329 if (0 == m_userDataMap.count(userId)) {
330 FileSystem fs(userId);
331 fs.addRemovedApp(owner);
333 auto &handle = m_userDataMap[userId];
334 handle.crypto.removeKey(owner);
335 handle.database.deleteKey(owner);
339 } catch (const Exc::Exception &e) {
341 } catch (const CKM::Exception &e) {
342 LogError("CKM::Exception: " << e.GetMessage());
343 retCode = CKM_API_ERROR_SERVER_ERROR;
346 return MessageBuffer::Serialize(retCode).Pop();
349 int CKMLogic::checkSaveConditions(
350 const Credentials &accessorCred,
353 const ClientId &owner)
355 // verify name and client are correct
356 if (!isNameValid(name) || !isClientValid(owner)) {
357 LogDebug("Invalid parameter passed to key-manager");
358 return CKM_API_ERROR_INPUT_PARAM;
361 // check if accessor is allowed to save owner's items
362 int access_ec = m_accessControl.canSave(accessorCred, owner);
364 if (access_ec != CKM_API_SUCCESS) {
365 LogDebug("accessor " << accessorCred.client << " can not save rows owned by " <<
370 // check if not a duplicate
371 if (handler.database.isNameOwnerPresent(name, owner))
372 return CKM_API_ERROR_DB_ALIAS_EXISTS;
374 // encryption section
375 if (!handler.crypto.haveKey(owner)) {
377 auto key_optional = handler.database.getKey(owner);
380 LogDebug("No Key in database found. Generating new one for client: " <<
382 got_key = handler.keyProvider.generateDEK(owner);
383 handler.database.saveKey(owner, got_key);
385 LogDebug("Key from DB");
386 got_key = *key_optional;
389 got_key = handler.keyProvider.getPureDEK(got_key);
390 handler.crypto.pushKey(owner, got_key);
393 return CKM_API_SUCCESS;
396 DB::Row CKMLogic::createEncryptedRow(
399 const ClientId &owner,
400 const Crypto::Data &data,
401 const Policy &policy) const
403 Crypto::GStore &store = m_decider.getStore(data.type, policy);
405 // do not encrypt data with password during cc_mode on
406 Token token = store.import(data,
407 m_accessControl.isCCMode() ? "" : policy.password);
408 DB::Row row(std::move(token), name, owner,
409 static_cast<int>(policy.extractable));
410 crypto.encryptRow(row);
414 int CKMLogic::verifyBinaryData(Crypto::Data &input) const
417 return toBinaryData(input, dummy);
420 int CKMLogic::toBinaryData(const Crypto::Data &input,
421 Crypto::Data &output) const
423 // verify the data integrity
424 if (input.type.isKey()) {
427 if (input.type.isSKey())
428 output_key = CKM::Key::createAES(input.data);
430 output_key = CKM::Key::create(input.data);
432 if (output_key.get() == NULL) {
433 LogDebug("provided binary data is not valid key data");
434 return CKM_API_ERROR_INPUT_PARAM;
437 output = std::move(Crypto::Data(input.type, output_key->getDER()));
438 } else if (input.type.isCertificate() || input.type.isChainCert()) {
439 CertificateShPtr cert = CKM::Certificate::create(input.data,
440 DataFormat::FORM_DER);
442 if (cert.get() == NULL) {
443 LogDebug("provided binary data is not valid certificate data");
444 return CKM_API_ERROR_INPUT_PARAM;
447 output = std::move(Crypto::Data(input.type, cert->getDER()));
452 // TODO: add here BINARY_DATA verification, i.e: max size etc.
453 return CKM_API_SUCCESS;
456 int CKMLogic::verifyAndSaveDataHelper(
457 const Credentials &cred,
459 const ClientId &explicitOwner,
460 const Crypto::Data &data,
461 const PolicySerializable &policy)
463 int retCode = CKM_API_ERROR_UNKNOWN;
466 // check if data is correct
467 Crypto::Data binaryData;
468 retCode = toBinaryData(data, binaryData);
470 if (retCode != CKM_API_SUCCESS)
473 return saveDataHelper(cred, name, explicitOwner, binaryData, policy);
474 } catch (const Exc::Exception &e) {
476 } catch (const CKM::Exception &e) {
477 LogError("CKM::Exception: " << e.GetMessage());
478 return CKM_API_ERROR_SERVER_ERROR;
482 int CKMLogic::getKeyForService(
483 const Credentials &cred,
485 const ClientId &explicitOwner,
486 const Password &pass,
487 Crypto::GObjShPtr &key)
490 // Key is for internal service use. It won't be exported to the client
491 Crypto::GObjUPtr obj;
492 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
495 if (retCode == CKM_API_SUCCESS)
496 key = std::move(obj);
499 } catch (const Exc::Exception &e) {
501 } catch (const CKM::Exception &e) {
502 LogError("CKM::Exception: " << e.GetMessage());
503 return CKM_API_ERROR_SERVER_ERROR;
507 RawBuffer CKMLogic::saveData(
508 const Credentials &cred,
511 const ClientId &explicitOwner,
512 const Crypto::Data &data,
513 const PolicySerializable &policy)
515 int retCode = verifyAndSaveDataHelper(cred, name, explicitOwner, data, policy);
516 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
519 static_cast<int>(data.type));
520 return response.Pop();
523 int CKMLogic::extractPKCS12Data(
526 const ClientId &owner,
527 const PKCS12Serializable &pkcs,
528 const PolicySerializable &keyPolicy,
529 const PolicySerializable &certPolicy,
530 DB::RowVector &output) const
532 // private key is mandatory
533 auto key = pkcs.getKey();
536 LogError("Failed to get private key from pkcs");
537 return CKM_API_ERROR_INVALID_FORMAT;
540 Crypto::Data keyData(DataType(key->getType()), key->getDER());
541 int retCode = verifyBinaryData(keyData);
543 if (retCode != CKM_API_SUCCESS)
546 output.push_back(createEncryptedRow(crypto, name, owner, keyData,
549 // certificate is mandatory
550 auto cert = pkcs.getCertificate();
553 LogError("Failed to get certificate from pkcs");
554 return CKM_API_ERROR_INVALID_FORMAT;
557 Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
558 retCode = verifyBinaryData(certData);
560 if (retCode != CKM_API_SUCCESS)
563 output.push_back(createEncryptedRow(crypto, name, owner, certData,
567 unsigned int cert_index = 0;
569 for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
570 Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++),
572 int retCode = verifyBinaryData(caCertData);
574 if (retCode != CKM_API_SUCCESS)
577 output.push_back(createEncryptedRow(crypto, name, owner, caCertData,
581 return CKM_API_SUCCESS;
584 RawBuffer CKMLogic::savePKCS12(
585 const Credentials &cred,
588 const ClientId &explicitOwner,
589 const PKCS12Serializable &pkcs,
590 const PolicySerializable &keyPolicy,
591 const PolicySerializable &certPolicy)
593 int retCode = CKM_API_ERROR_UNKNOWN;
596 retCode = saveDataHelper(cred, name, explicitOwner, pkcs, keyPolicy, certPolicy);
597 } catch (const Exc::Exception &e) {
599 } catch (const CKM::Exception &e) {
600 LogError("CKM::Exception: " << e.GetMessage());
601 retCode = CKM_API_ERROR_SERVER_ERROR;
604 auto response = MessageBuffer::Serialize(static_cast<int>
605 (LogicCommand::SAVE_PKCS12),
608 return response.Pop();
612 int CKMLogic::removeDataHelper(
613 const Credentials &cred,
615 const ClientId &explicitOwner)
617 auto &handler = selectDatabase(cred, explicitOwner);
619 // use client id if not explicitly provided
620 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
622 if (!isNameValid(name) || !isClientValid(owner)) {
623 LogDebug("Invalid owner or name format");
624 return CKM_API_ERROR_INPUT_PARAM;
627 DB::Crypto::Transaction transaction(&handler.database);
629 // read and check permissions
630 PermissionMaskOptional permissionRowOpt =
631 handler.database.getPermissionRow(name, owner, cred.client);
632 int retCode = m_accessControl.canDelete(cred,
633 toPermissionMask(permissionRowOpt));
635 if (retCode != CKM_API_SUCCESS) {
636 LogWarning("access control check result: " << retCode);
640 // get all matching rows
642 handler.database.getRows(name, owner, DataType::DB_FIRST,
643 DataType::DB_LAST, rows);
646 LogDebug("No row for given name and owner");
647 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
650 // load app key if needed
651 retCode = loadAppKey(handler, rows.front().owner);
653 if (CKM_API_SUCCESS != retCode)
656 // destroy it in store
657 for (auto &r : rows) {
659 handler.crypto.decryptRow(Password(), r);
660 m_decider.getStore(r).destroy(r);
661 } catch (const Exc::AuthenticationFailed &) {
662 LogDebug("Authentication failed when removing data. Ignored.");
667 handler.database.deleteRow(name, owner);
668 transaction.commit();
670 return CKM_API_SUCCESS;
673 RawBuffer CKMLogic::removeData(
674 const Credentials &cred,
677 const ClientId &explicitOwner)
679 int retCode = CKM_API_ERROR_UNKNOWN;
682 retCode = removeDataHelper(cred, name, explicitOwner);
683 } catch (const Exc::Exception &e) {
685 } catch (const CKM::Exception &e) {
686 LogError("Error: " << e.GetMessage());
687 retCode = CKM_API_ERROR_DB_ERROR;
690 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
693 return response.Pop();
696 int CKMLogic::readSingleRow(const Name &name,
697 const ClientId &owner,
699 DB::Crypto &database,
702 DB::Crypto::RowOptional row_optional;
704 if (dataType.isKey()) {
705 // read all key types
706 row_optional = database.getRow(name,
708 DataType::DB_KEY_FIRST,
709 DataType::DB_KEY_LAST);
711 // read anything else
712 row_optional = database.getRow(name,
718 LogDebug("No row for given name, owner and type");
719 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
724 return CKM_API_SUCCESS;
728 int CKMLogic::readMultiRow(const Name &name,
729 const ClientId &owner,
731 DB::Crypto &database,
732 DB::RowVector &output)
734 if (dataType.isKey())
735 // read all key types
736 database.getRows(name,
738 DataType::DB_KEY_FIRST,
739 DataType::DB_KEY_LAST,
741 else if (dataType.isChainCert())
742 // read all key types
743 database.getRows(name,
745 DataType::DB_CHAIN_FIRST,
746 DataType::DB_CHAIN_LAST,
749 // read anything else
750 database.getRows(name,
755 if (!output.size()) {
756 LogDebug("No row for given name, owner and type");
757 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
760 return CKM_API_SUCCESS;
763 int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred,
765 const ClientId &owner,
768 DB::Crypto &database)
770 PermissionMaskOptional permissionRowOpt =
771 database.getPermissionRow(name, owner, accessorCred.client);
774 return m_accessControl.canExport(accessorCred,
776 toPermissionMask(permissionRowOpt));
778 return m_accessControl.canRead(accessorCred,
779 toPermissionMask(permissionRowOpt));
782 Crypto::GObjUPtr CKMLogic::rowToObject(
785 const Password &password)
787 Crypto::GStore &store = m_decider.getStore(row);
789 Password pass = m_accessControl.isCCMode() ? "" : password;
792 Crypto::GObjUPtr obj;
794 if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
795 CryptoLogic::ENCRYPTION_V2) {
796 handler.crypto.decryptRow(Password(), row);
798 obj = store.getObject(row, pass);
800 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
801 handler.crypto.decryptRow(pass, row);
802 // destroy it in store
805 // import it to store with new scheme: data -> pass(data)
806 Token token = store.import(Crypto::Data(row.dataType, row.data), pass);
808 // get it from the store (it can be different than the data we imported into store)
809 obj = store.getObject(token, pass);
811 // update row with new token
812 *static_cast<Token *>(&row) = std::move(token);
814 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
815 handler.crypto.encryptRow(row);
818 handler.database.updateRow(row);
824 int CKMLogic::readDataHelper(
826 const Credentials &cred,
829 const ClientId &explicitOwner,
830 const Password &password,
831 Crypto::GObjUPtrVector &objs)
833 auto &handler = selectDatabase(cred, explicitOwner);
835 // use client id if not explicitly provided
836 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
838 if (!isNameValid(name) || !isClientValid(owner))
839 return CKM_API_ERROR_INPUT_PARAM;
842 DB::Crypto::Transaction transaction(&handler.database);
844 int retCode = readMultiRow(name, owner, dataType, handler.database, rows);
846 if (CKM_API_SUCCESS != retCode)
849 // all read rows belong to the same owner
850 DB::Row &firstRow = rows.at(0);
852 // check access rights
853 retCode = checkDataPermissionsHelper(cred, name, owner, firstRow,
854 exportFlag, handler.database);
856 if (CKM_API_SUCCESS != retCode)
859 // load app key if needed
860 retCode = loadAppKey(handler, firstRow.owner);
862 if (CKM_API_SUCCESS != retCode)
866 for (auto &row : rows)
867 objs.push_back(rowToObject(handler, std::move(row), password));
869 // rowToObject may modify db
870 transaction.commit();
872 return CKM_API_SUCCESS;
875 int CKMLogic::readDataHelper(
877 const Credentials &cred,
880 const ClientId &explicitOwner,
881 const Password &password,
882 Crypto::GObjUPtr &obj)
884 DataType objDataType;
885 return readDataHelper(exportFlag, cred, dataType, name, explicitOwner,
886 password, obj, objDataType);
889 int CKMLogic::readDataHelper(
891 const Credentials &cred,
894 const ClientId &explicitOwner,
895 const Password &password,
896 Crypto::GObjUPtr &obj,
897 DataType &objDataType)
899 auto &handler = selectDatabase(cred, explicitOwner);
901 // use client id if not explicitly provided
902 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
904 if (!isNameValid(name) || !isClientValid(owner))
905 return CKM_API_ERROR_INPUT_PARAM;
908 DB::Crypto::Transaction transaction(&handler.database);
910 int retCode = readSingleRow(name, owner, dataType, handler.database, row);
912 if (CKM_API_SUCCESS != retCode)
915 objDataType = row.dataType;
917 // check access rights
918 retCode = checkDataPermissionsHelper(cred, name, owner, row, exportFlag,
921 if (CKM_API_SUCCESS != retCode)
924 // load app key if needed
925 retCode = loadAppKey(handler, row.owner);
927 if (CKM_API_SUCCESS != retCode)
930 obj = rowToObject(handler, std::move(row), password);
931 // rowToObject may modify db
932 transaction.commit();
934 return CKM_API_SUCCESS;
937 RawBuffer CKMLogic::getData(
938 const Credentials &cred,
942 const ClientId &explicitOwner,
943 const Password &password)
945 int retCode = CKM_API_SUCCESS;
947 DataType objDataType;
950 Crypto::GObjUPtr obj;
951 retCode = readDataHelper(true, cred, dataType, name, explicitOwner,
952 password, obj, objDataType);
954 if (retCode == CKM_API_SUCCESS)
955 rowData = obj->getBinary();
956 } catch (const Exc::Exception &e) {
958 } catch (const CKM::Exception &e) {
959 LogError("CKM::Exception: " << e.GetMessage());
960 retCode = CKM_API_ERROR_SERVER_ERROR;
963 if (CKM_API_SUCCESS != retCode)
966 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
969 static_cast<int>(objDataType),
971 return response.Pop();
974 int CKMLogic::getPKCS12Helper(
975 const Credentials &cred,
977 const ClientId &explicitOwner,
978 const Password &keyPassword,
979 const Password &certPassword,
981 CertificateShPtr &cert,
982 CertificateShPtrVector &caChain)
986 // read private key (mandatory)
987 Crypto::GObjUPtr keyObj;
988 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
989 keyPassword, keyObj);
991 if (retCode != CKM_API_SUCCESS) {
992 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
995 privKey = CKM::Key::create(keyObj->getBinary());
998 // read certificate (mandatory)
999 Crypto::GObjUPtr certObj;
1000 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, explicitOwner,
1001 certPassword, certObj);
1003 if (retCode != CKM_API_SUCCESS) {
1004 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1007 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
1010 // read CA cert chain (optional)
1011 Crypto::GObjUPtrVector caChainObjs;
1012 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, explicitOwner,
1013 certPassword, caChainObjs);
1015 if (retCode != CKM_API_SUCCESS && retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1016 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1019 for (auto &caCertObj : caChainObjs)
1020 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
1021 DataFormat::FORM_DER));
1024 // if anything found, return it
1025 if (privKey || cert || caChain.size() > 0)
1026 retCode = CKM_API_SUCCESS;
1031 RawBuffer CKMLogic::getPKCS12(
1032 const Credentials &cred,
1035 const ClientId &explicitOwner,
1036 const Password &keyPassword,
1037 const Password &certPassword)
1039 int retCode = CKM_API_ERROR_UNKNOWN;
1041 PKCS12Serializable output;
1045 CertificateShPtr cert;
1046 CertificateShPtrVector caChain;
1047 retCode = getPKCS12Helper(cred, name, explicitOwner, keyPassword,
1048 certPassword, privKey, cert, caChain);
1051 if (retCode == CKM_API_SUCCESS)
1052 output = PKCS12Serializable(std::move(privKey), std::move(cert),
1053 std::move(caChain));
1054 } catch (const Exc::Exception &e) {
1055 retCode = e.error();
1056 } catch (const CKM::Exception &e) {
1057 LogError("CKM::Exception: " << e.GetMessage());
1058 retCode = CKM_API_ERROR_SERVER_ERROR;
1061 auto response = MessageBuffer::Serialize(static_cast<int>
1062 (LogicCommand::GET_PKCS12),
1066 return response.Pop();
1069 int CKMLogic::getDataListHelper(const Credentials &cred,
1070 const DataType dataType,
1071 OwnerNameVector &ownerNameVector)
1073 int retCode = CKM_API_ERROR_DB_LOCKED;
1075 if (0 < m_userDataMap.count(cred.clientUid)) {
1076 auto &database = m_userDataMap[cred.clientUid].database;
1079 OwnerNameVector tmpVector;
1081 if (dataType.isKey()) {
1082 // list all key types
1083 database.listNames(cred.client,
1085 DataType::DB_KEY_FIRST,
1086 DataType::DB_KEY_LAST);
1088 // list anything else
1089 database.listNames(cred.client,
1094 ownerNameVector.insert(ownerNameVector.end(), tmpVector.begin(),
1096 retCode = CKM_API_SUCCESS;
1097 } catch (const CKM::Exception &e) {
1098 LogError("Error: " << e.GetMessage());
1099 retCode = CKM_API_ERROR_DB_ERROR;
1100 } catch (const Exc::Exception &e) {
1101 retCode = e.error();
1108 RawBuffer CKMLogic::getDataList(
1109 const Credentials &cred,
1113 OwnerNameVector systemVector;
1114 OwnerNameVector userVector;
1115 OwnerNameVector ownerNameVector;
1117 int retCode = unlockSystemDB();
1119 if (CKM_API_SUCCESS == retCode) {
1121 if (m_accessControl.isSystemService(cred)) {
1123 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1128 // user - lookup system, then client DB
1129 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1135 if (retCode == CKM_API_SUCCESS) {
1136 retCode = getDataListHelper(cred,
1143 if (retCode == CKM_API_SUCCESS) {
1144 ownerNameVector.insert(ownerNameVector.end(), systemVector.begin(),
1145 systemVector.end());
1146 ownerNameVector.insert(ownerNameVector.end(), userVector.begin(),
1150 auto response = MessageBuffer::Serialize(static_cast<int>
1151 (LogicCommand::GET_LIST),
1154 static_cast<int>(dataType),
1156 return response.Pop();
1159 int CKMLogic::importInitialData(
1161 const Crypto::Data &data,
1162 const Crypto::DataEncryption &enc,
1163 const Policy &policy)
1166 // Inital values are always imported with root credentials. Client id is not important.
1167 Credentials rootCred(0, "");
1169 auto &handler = selectDatabase(rootCred, CLIENT_ID_SYSTEM);
1171 // check if save is possible
1172 DB::Crypto::Transaction transaction(&handler.database);
1173 int retCode = checkSaveConditions(rootCred, handler, name, CLIENT_ID_SYSTEM);
1175 if (retCode != CKM_API_SUCCESS)
1178 Crypto::GStore &store = m_decider.getStore(data.type, policy, !enc.encryptedKey.empty());
1182 if (enc.encryptedKey.empty()) {
1183 Crypto::Data binaryData;
1185 if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1188 token = store.import(binaryData,
1189 m_accessControl.isCCMode() ? "" : policy.password);
1191 token = store.importEncrypted(data,
1192 m_accessControl.isCCMode() ? "" : policy.password, enc);
1195 DB::Row row(std::move(token), name, CLIENT_ID_SYSTEM,
1196 static_cast<int>(policy.extractable));
1197 handler.crypto.encryptRow(row);
1199 handler.database.saveRow(row);
1200 transaction.commit();
1201 } catch (const Exc::Exception &e) {
1203 } catch (const CKM::Exception &e) {
1204 LogError("CKM::Exception: " << e.GetMessage());
1205 return CKM_API_ERROR_SERVER_ERROR;
1206 } catch (const std::exception &e) {
1207 LogError("Std::exception: " << e.what());
1208 return CKM_API_ERROR_SERVER_ERROR;
1211 return CKM_API_SUCCESS;
1214 int CKMLogic::saveDataHelper(
1215 const Credentials &cred,
1217 const ClientId &explicitOwner,
1218 const Crypto::Data &data,
1219 const PolicySerializable &policy)
1221 auto &handler = selectDatabase(cred, explicitOwner);
1223 // use client id if not explicitly provided
1224 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1226 if (m_accessControl.isSystemService(cred) &&
1227 owner.compare(CLIENT_ID_SYSTEM) != 0) {
1228 LogError("System services can only use " << CLIENT_ID_SYSTEM << " as owner id") ;
1229 return CKM_API_ERROR_INPUT_PARAM;
1232 // check if save is possible
1233 DB::Crypto::Transaction transaction(&handler.database);
1234 int retCode = checkSaveConditions(cred, handler, name, owner);
1236 if (retCode != CKM_API_SUCCESS)
1240 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, owner,
1242 handler.database.saveRow(encryptedRow);
1244 transaction.commit();
1245 return CKM_API_SUCCESS;
1248 int CKMLogic::saveDataHelper(
1249 const Credentials &cred,
1251 const ClientId &explicitOwner,
1252 const PKCS12Serializable &pkcs,
1253 const PolicySerializable &keyPolicy,
1254 const PolicySerializable &certPolicy)
1256 auto &handler = selectDatabase(cred, explicitOwner);
1258 // use client id if not explicitly provided
1259 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1261 if (m_accessControl.isSystemService(cred) &&
1262 owner.compare(CLIENT_ID_SYSTEM) != 0)
1263 return CKM_API_ERROR_INPUT_PARAM;
1265 // check if save is possible
1266 DB::Crypto::Transaction transaction(&handler.database);
1267 int retCode = checkSaveConditions(cred, handler, name, owner);
1269 if (retCode != CKM_API_SUCCESS)
1272 // extract and encrypt the data
1273 DB::RowVector encryptedRows;
1274 retCode = extractPKCS12Data(handler.crypto, name, owner, pkcs, keyPolicy,
1275 certPolicy, encryptedRows);
1277 if (retCode != CKM_API_SUCCESS)
1281 handler.database.saveRows(name, owner, encryptedRows);
1282 transaction.commit();
1284 return CKM_API_SUCCESS;
1288 int CKMLogic::createKeyAESHelper(
1289 const Credentials &cred,
1292 const ClientId &explicitOwner,
1293 const PolicySerializable &policy)
1295 auto &handler = selectDatabase(cred, explicitOwner);
1297 // use client id if not explicitly provided
1298 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1300 if (m_accessControl.isSystemService(cred) &&
1301 owner.compare(CLIENT_ID_SYSTEM) != 0)
1302 return CKM_API_ERROR_INPUT_PARAM;
1304 // check if save is possible
1305 DB::Crypto::Transaction transaction(&handler.database);
1306 int retCode = checkSaveConditions(cred, handler, name, owner);
1308 if (retCode != CKM_API_SUCCESS)
1311 // create key in store
1312 CryptoAlgorithm keyGenAlgorithm;
1313 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1314 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1315 Token key = m_decider.getStore(DataType::KEY_AES,
1316 policy).generateSKey(keyGenAlgorithm, policy.password);
1319 DB::Row row(std::move(key), name, owner,
1320 static_cast<int>(policy.extractable));
1321 handler.crypto.encryptRow(row);
1323 handler.database.saveRow(row);
1325 transaction.commit();
1326 return CKM_API_SUCCESS;
1329 int CKMLogic::createKeyPairHelper(
1330 const Credentials &cred,
1331 const CryptoAlgorithmSerializable &keyGenParams,
1332 const Name &namePrivate,
1333 const ClientId &explicitOwnerPrivate,
1334 const Name &namePublic,
1335 const ClientId &explicitOwnerPublic,
1336 const PolicySerializable &policyPrivate,
1337 const PolicySerializable &policyPublic)
1339 auto &handlerPriv = selectDatabase(cred, explicitOwnerPrivate);
1340 auto &handlerPub = selectDatabase(cred, explicitOwnerPublic);
1342 AlgoType keyType = AlgoType::RSA_GEN;
1344 if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1345 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1347 DataType dt(keyType);
1350 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1352 if (policyPrivate.backend != policyPublic.backend)
1353 ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend.");
1355 // use client id if not explicitly provided
1356 const ClientId &ownerPrv = explicitOwnerPrivate.empty() ? cred.client :
1357 explicitOwnerPrivate;
1359 if (m_accessControl.isSystemService(cred) &&
1360 ownerPrv.compare(CLIENT_ID_SYSTEM) != 0)
1361 return CKM_API_ERROR_INPUT_PARAM;
1363 const ClientId &ownerPub = explicitOwnerPublic.empty() ? cred.client :
1364 explicitOwnerPublic;
1366 if (m_accessControl.isSystemService(cred) &&
1367 ownerPub.compare(CLIENT_ID_SYSTEM) != 0)
1368 return CKM_API_ERROR_INPUT_PARAM;
1370 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1371 Policy lessRestricted(Password(), exportable, policyPrivate.backend);
1373 TokenPair keys = m_decider.getStore(dt, lessRestricted).generateAKey(keyGenParams,
1374 policyPrivate.password,
1375 policyPublic.password);
1377 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1378 // in case the same database is used for private and public - the second
1379 // transaction will not be executed
1380 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1383 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerPrv);
1385 if (CKM_API_SUCCESS != retCode)
1388 retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerPub);
1390 if (CKM_API_SUCCESS != retCode)
1394 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerPrv,
1395 static_cast<int>(policyPrivate.extractable));
1396 handlerPriv.crypto.encryptRow(rowPrv);
1397 handlerPriv.database.saveRow(rowPrv);
1399 DB::Row rowPub(std::move(keys.second), namePublic, ownerPub,
1400 static_cast<int>(policyPublic.extractable));
1401 handlerPub.crypto.encryptRow(rowPub);
1402 handlerPub.database.saveRow(rowPub);
1404 transactionPub.commit();
1405 transactionPriv.commit();
1406 return CKM_API_SUCCESS;
1409 RawBuffer CKMLogic::createKeyPair(
1410 const Credentials &cred,
1412 const CryptoAlgorithmSerializable &keyGenParams,
1413 const Name &namePrivate,
1414 const ClientId &explicitOwnerPrivate,
1415 const Name &namePublic,
1416 const ClientId &explicitOwnerPublic,
1417 const PolicySerializable &policyPrivate,
1418 const PolicySerializable &policyPublic)
1420 int retCode = CKM_API_SUCCESS;
1423 retCode = createKeyPairHelper(
1427 explicitOwnerPrivate,
1429 explicitOwnerPublic,
1432 } catch (const Exc::Exception &e) {
1433 retCode = e.error();
1434 } catch (const CKM::Exception &e) {
1435 LogError("CKM::Exception: " << e.GetMessage());
1436 retCode = CKM_API_ERROR_SERVER_ERROR;
1439 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1440 commandId, retCode).Pop();
1443 RawBuffer CKMLogic::createKeyAES(
1444 const Credentials &cred,
1448 const ClientId &explicitOwner,
1449 const PolicySerializable &policy)
1451 int retCode = CKM_API_SUCCESS;
1454 retCode = createKeyAESHelper(cred, size, name, explicitOwner, policy);
1455 } catch (const Exc::Exception &e) {
1456 retCode = e.error();
1457 } catch (std::invalid_argument &e) {
1458 LogDebug("invalid argument error: " << e.what());
1459 retCode = CKM_API_ERROR_INPUT_PARAM;
1460 } catch (const CKM::Exception &e) {
1461 LogError("CKM::Exception: " << e.GetMessage());
1462 retCode = CKM_API_ERROR_SERVER_ERROR;
1465 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1466 commandId, retCode).Pop();
1469 int CKMLogic::readCertificateHelper(
1470 const Credentials &cred,
1471 const OwnerNameVector &ownerNameVector,
1472 CertificateImplVector &certVector)
1474 for (auto &i : ownerNameVector) {
1475 // certificates can't be protected with custom user password
1476 Crypto::GObjUPtr obj;
1478 ec = readDataHelper(true,
1480 DataType::CERTIFICATE,
1486 if (ec != CKM_API_SUCCESS)
1489 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1491 // try to read chain certificates (if present)
1492 Crypto::GObjUPtrVector caChainObjs;
1493 ec = readDataHelper(true,
1495 DataType::DB_CHAIN_FIRST,
1501 if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1504 for (auto &caCertObj : caChainObjs)
1505 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1508 return CKM_API_SUCCESS;
1511 int CKMLogic::getCertificateChainHelper(
1512 const CertificateImpl &cert,
1513 const RawBufferVector &untrustedCertificates,
1514 const RawBufferVector &trustedCertificates,
1515 bool useTrustedSystemCertificates,
1516 RawBufferVector &chainRawVector)
1518 CertificateImplVector untrustedCertVector;
1519 CertificateImplVector trustedCertVector;
1520 CertificateImplVector chainVector;
1523 return CKM_API_ERROR_INPUT_PARAM;
1525 for (auto &e : untrustedCertificates) {
1526 CertificateImpl c(e, DataFormat::FORM_DER);
1529 return CKM_API_ERROR_INPUT_PARAM;
1531 untrustedCertVector.push_back(std::move(c));
1534 for (auto &e : trustedCertificates) {
1535 CertificateImpl c(e, DataFormat::FORM_DER);
1538 return CKM_API_ERROR_INPUT_PARAM;
1540 trustedCertVector.push_back(std::move(c));
1543 CertificateStore store;
1544 int retCode = store.verifyCertificate(cert,
1545 untrustedCertVector,
1547 useTrustedSystemCertificates,
1548 m_accessControl.isCCMode(),
1551 if (retCode != CKM_API_SUCCESS)
1554 for (auto &e : chainVector)
1555 chainRawVector.push_back(e.getDER());
1557 return CKM_API_SUCCESS;
1560 int CKMLogic::getCertificateChainHelper(
1561 const Credentials &cred,
1562 const CertificateImpl &cert,
1563 const OwnerNameVector &untrusted,
1564 const OwnerNameVector &trusted,
1565 bool useTrustedSystemCertificates,
1566 RawBufferVector &chainRawVector)
1568 CertificateImplVector untrustedCertVector;
1569 CertificateImplVector trustedCertVector;
1570 CertificateImplVector chainVector;
1573 return CKM_API_ERROR_INPUT_PARAM;
1575 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1577 if (retCode != CKM_API_SUCCESS)
1580 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1582 if (retCode != CKM_API_SUCCESS)
1585 CertificateStore store;
1586 retCode = store.verifyCertificate(cert,
1587 untrustedCertVector,
1589 useTrustedSystemCertificates,
1590 m_accessControl.isCCMode(),
1593 if (retCode != CKM_API_SUCCESS)
1596 for (auto &i : chainVector)
1597 chainRawVector.push_back(i.getDER());
1599 return CKM_API_SUCCESS;
1602 RawBuffer CKMLogic::getCertificateChain(
1603 const Credentials & /*cred*/,
1605 const RawBuffer &certificate,
1606 const RawBufferVector &untrustedCertificates,
1607 const RawBufferVector &trustedCertificates,
1608 bool useTrustedSystemCertificates)
1610 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1611 RawBufferVector chainRawVector;
1612 int retCode = CKM_API_ERROR_UNKNOWN;
1615 retCode = getCertificateChainHelper(cert,
1616 untrustedCertificates,
1617 trustedCertificates,
1618 useTrustedSystemCertificates,
1620 } catch (const Exc::Exception &e) {
1621 retCode = e.error();
1622 } catch (const std::exception &e) {
1623 LogError("STD exception " << e.what());
1624 retCode = CKM_API_ERROR_SERVER_ERROR;
1626 LogError("Unknown error.");
1629 auto response = MessageBuffer::Serialize(static_cast<int>
1630 (LogicCommand::GET_CHAIN_CERT),
1634 return response.Pop();
1637 RawBuffer CKMLogic::getCertificateChain(
1638 const Credentials &cred,
1640 const RawBuffer &certificate,
1641 const OwnerNameVector &untrustedCertificates,
1642 const OwnerNameVector &trustedCertificates,
1643 bool useTrustedSystemCertificates)
1645 int retCode = CKM_API_ERROR_UNKNOWN;
1646 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1647 RawBufferVector chainRawVector;
1650 retCode = getCertificateChainHelper(cred,
1652 untrustedCertificates,
1653 trustedCertificates,
1654 useTrustedSystemCertificates,
1656 } catch (const Exc::Exception &e) {
1657 retCode = e.error();
1658 } catch (const std::exception &e) {
1659 LogError("STD exception " << e.what());
1660 retCode = CKM_API_ERROR_SERVER_ERROR;
1662 LogError("Unknown error.");
1665 auto response = MessageBuffer::Serialize(static_cast<int>
1666 (LogicCommand::GET_CHAIN_ALIAS),
1670 return response.Pop();
1673 RawBuffer CKMLogic::createSignature(
1674 const Credentials &cred,
1676 const Name &privateKeyName,
1677 const ClientId &explicitOwner,
1678 const Password &password, // password for private_key
1679 const RawBuffer &message,
1680 const CryptoAlgorithm &cryptoAlg)
1682 RawBuffer signature;
1684 int retCode = CKM_API_SUCCESS;
1687 Crypto::GObjUPtr obj;
1688 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
1689 explicitOwner, password, obj);
1691 if (retCode == CKM_API_SUCCESS)
1692 signature = obj->sign(cryptoAlg, message);
1693 } catch (const Exc::Exception &e) {
1694 retCode = e.error();
1695 } catch (const CKM::Exception &e) {
1696 LogError("Unknown CKM::Exception: " << e.GetMessage());
1697 retCode = CKM_API_ERROR_SERVER_ERROR;
1698 } catch (const std::exception &e) {
1699 LogError("STD exception " << e.what());
1700 retCode = CKM_API_ERROR_SERVER_ERROR;
1703 auto response = MessageBuffer::Serialize(static_cast<int>
1704 (LogicCommand::CREATE_SIGNATURE),
1708 return response.Pop();
1711 RawBuffer CKMLogic::verifySignature(
1712 const Credentials &cred,
1714 const Name &publicKeyOrCertName,
1715 const ClientId &explicitOwner,
1716 const Password &password, // password for public_key (optional)
1717 const RawBuffer &message,
1718 const RawBuffer &signature,
1719 const CryptoAlgorithm ¶ms)
1721 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1724 // try certificate first - looking for a public key.
1725 // in case of PKCS, pub key from certificate will be found first
1726 // rather than private key from the same PKCS.
1727 Crypto::GObjUPtr obj;
1728 retCode = readDataHelper(false, cred, DataType::CERTIFICATE,
1729 publicKeyOrCertName, explicitOwner, password, obj);
1731 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1732 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
1733 publicKeyOrCertName, explicitOwner, password, obj);
1735 if (retCode == CKM_API_SUCCESS)
1736 retCode = obj->verify(params, message, signature);
1737 } catch (const Exc::Exception &e) {
1738 retCode = e.error();
1739 } catch (const CKM::Exception &e) {
1740 LogError("Unknown CKM::Exception: " << e.GetMessage());
1741 retCode = CKM_API_ERROR_SERVER_ERROR;
1744 auto response = MessageBuffer::Serialize(static_cast<int>
1745 (LogicCommand::VERIFY_SIGNATURE),
1748 return response.Pop();
1751 int CKMLogic::setPermissionHelper(
1752 const Credentials &cred, // who's the client
1754 const ClientId &explicitOwner, // who's the owner
1755 const ClientId &accessor, // who will get the access
1756 const PermissionMask permissionMask)
1758 auto &handler = selectDatabase(cred, explicitOwner);
1760 // we don't know the client
1761 if (cred.client.empty() || !isClientValid(cred.client))
1762 return CKM_API_ERROR_INPUT_PARAM;
1764 // use client id if not explicitly provided
1765 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1767 // verify name and owner are correct
1768 if (!isNameValid(name) || !isClientValid(owner) ||
1769 !isClientValid(accessor))
1770 return CKM_API_ERROR_INPUT_PARAM;
1772 // currently we don't support modification of owner's permissions to his own rows
1773 if (owner == accessor)
1774 return CKM_API_ERROR_INPUT_PARAM;
1776 // system database does not support write/remove permissions
1777 if ((0 == owner.compare(CLIENT_ID_SYSTEM)) &&
1778 (permissionMask & Permission::REMOVE))
1779 return CKM_API_ERROR_INPUT_PARAM;
1781 // can the client modify permissions to owner's row?
1782 int retCode = m_accessControl.canModify(cred, owner);
1784 if (retCode != CKM_API_SUCCESS)
1787 DB::Crypto::Transaction transaction(&handler.database);
1789 if (!handler.database.isNameOwnerPresent(name, owner))
1790 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1792 // set permissions to the row owned by owner for accessor
1793 handler.database.setPermission(name, owner, accessor, permissionMask);
1794 transaction.commit();
1796 return CKM_API_SUCCESS;
1799 RawBuffer CKMLogic::setPermission(
1800 const Credentials &cred,
1804 const ClientId &explicitOwner,
1805 const ClientId &accessor,
1806 const PermissionMask permissionMask)
1811 retCode = setPermissionHelper(cred, name, explicitOwner, accessor, permissionMask);
1812 } catch (const Exc::Exception &e) {
1813 retCode = e.error();
1814 } catch (const CKM::Exception &e) {
1815 LogError("Error: " << e.GetMessage());
1816 retCode = CKM_API_ERROR_DB_ERROR;
1819 return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1822 int CKMLogic::loadAppKey(UserData &handle, const ClientId &owner)
1824 if (!handle.crypto.haveKey(owner)) {
1826 auto key_optional = handle.database.getKey(owner);
1828 if (!key_optional) {
1829 LogError("No key for given owner in database");
1830 return CKM_API_ERROR_DB_ERROR;
1833 key = *key_optional;
1834 key = handle.keyProvider.getPureDEK(key);
1835 handle.crypto.pushKey(owner, key);
1838 return CKM_API_SUCCESS;