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 } // 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 Crypto::EncryptionParams());
409 DB::Row row(std::move(token), name, owner,
410 static_cast<int>(policy.extractable));
411 crypto.encryptRow(row);
415 int CKMLogic::verifyBinaryData(Crypto::Data &input) const
418 return toBinaryData(input, dummy);
421 int CKMLogic::toBinaryData(const Crypto::Data &input,
422 Crypto::Data &output) const
424 // verify the data integrity
425 if (input.type.isKey()) {
428 if (input.type.isSKey())
429 output_key = CKM::Key::createAES(input.data);
431 output_key = CKM::Key::create(input.data);
433 if (output_key.get() == NULL) {
434 LogDebug("provided binary data is not valid key data");
435 return CKM_API_ERROR_INPUT_PARAM;
438 output = std::move(Crypto::Data(input.type, output_key->getDER()));
439 } else if (input.type.isCertificate() || input.type.isChainCert()) {
440 CertificateShPtr cert = CKM::Certificate::create(input.data,
441 DataFormat::FORM_DER);
443 if (cert.get() == NULL) {
444 LogDebug("provided binary data is not valid certificate data");
445 return CKM_API_ERROR_INPUT_PARAM;
448 output = std::move(Crypto::Data(input.type, cert->getDER()));
453 // TODO: add here BINARY_DATA verification, i.e: max size etc.
454 return CKM_API_SUCCESS;
457 int CKMLogic::verifyAndSaveDataHelper(
458 const Credentials &cred,
460 const ClientId &explicitOwner,
461 const Crypto::Data &data,
462 const PolicySerializable &policy)
464 int retCode = CKM_API_ERROR_UNKNOWN;
467 // check if data is correct
468 Crypto::Data binaryData;
469 retCode = toBinaryData(data, binaryData);
471 if (retCode != CKM_API_SUCCESS)
474 return saveDataHelper(cred, name, explicitOwner, binaryData, policy);
475 } catch (const Exc::Exception &e) {
477 } catch (const CKM::Exception &e) {
478 LogError("CKM::Exception: " << e.GetMessage());
479 return CKM_API_ERROR_SERVER_ERROR;
483 int CKMLogic::getKeyForService(
484 const Credentials &cred,
486 const ClientId &explicitOwner,
487 const Password &pass,
488 Crypto::GObjShPtr &key)
491 // Key is for internal service use. It won't be exported to the client
492 Crypto::GObjUPtr obj;
493 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
496 if (retCode == CKM_API_SUCCESS)
497 key = std::move(obj);
500 } catch (const Exc::Exception &e) {
502 } catch (const CKM::Exception &e) {
503 LogError("CKM::Exception: " << e.GetMessage());
504 return CKM_API_ERROR_SERVER_ERROR;
508 RawBuffer CKMLogic::saveData(
509 const Credentials &cred,
512 const ClientId &explicitOwner,
513 const Crypto::Data &data,
514 const PolicySerializable &policy)
516 int retCode = verifyAndSaveDataHelper(cred, name, explicitOwner, data, policy);
517 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
520 static_cast<int>(data.type));
521 return response.Pop();
524 int CKMLogic::extractPKCS12Data(
527 const ClientId &owner,
528 const PKCS12Serializable &pkcs,
529 const PolicySerializable &keyPolicy,
530 const PolicySerializable &certPolicy,
531 DB::RowVector &output) const
533 // private key is mandatory
534 auto key = pkcs.getKey();
537 LogError("Failed to get private key from pkcs");
538 return CKM_API_ERROR_INVALID_FORMAT;
541 Crypto::Data keyData(DataType(key->getType()), key->getDER());
542 int retCode = verifyBinaryData(keyData);
544 if (retCode != CKM_API_SUCCESS)
547 output.push_back(createEncryptedRow(crypto, name, owner, keyData,
550 // certificate is mandatory
551 auto cert = pkcs.getCertificate();
554 LogError("Failed to get certificate from pkcs");
555 return CKM_API_ERROR_INVALID_FORMAT;
558 Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
559 retCode = verifyBinaryData(certData);
561 if (retCode != CKM_API_SUCCESS)
564 output.push_back(createEncryptedRow(crypto, name, owner, certData,
568 unsigned int cert_index = 0;
570 for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
571 Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++),
573 int retCode = verifyBinaryData(caCertData);
575 if (retCode != CKM_API_SUCCESS)
578 output.push_back(createEncryptedRow(crypto, name, owner, caCertData,
582 return CKM_API_SUCCESS;
585 RawBuffer CKMLogic::savePKCS12(
586 const Credentials &cred,
589 const ClientId &explicitOwner,
590 const PKCS12Serializable &pkcs,
591 const PolicySerializable &keyPolicy,
592 const PolicySerializable &certPolicy)
594 int retCode = CKM_API_ERROR_UNKNOWN;
597 retCode = saveDataHelper(cred, name, explicitOwner, pkcs, keyPolicy, certPolicy);
598 } catch (const Exc::Exception &e) {
600 } catch (const CKM::Exception &e) {
601 LogError("CKM::Exception: " << e.GetMessage());
602 retCode = CKM_API_ERROR_SERVER_ERROR;
605 auto response = MessageBuffer::Serialize(static_cast<int>
606 (LogicCommand::SAVE_PKCS12),
609 return response.Pop();
613 int CKMLogic::removeDataHelper(
614 const Credentials &cred,
616 const ClientId &explicitOwner)
618 auto &handler = selectDatabase(cred, explicitOwner);
620 // use client id if not explicitly provided
621 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
623 if (!isNameValid(name) || !isClientValid(owner)) {
624 LogDebug("Invalid owner or name format");
625 return CKM_API_ERROR_INPUT_PARAM;
628 DB::Crypto::Transaction transaction(&handler.database);
630 // read and check permissions
631 PermissionMaskOptional permissionRowOpt =
632 handler.database.getPermissionRow(name, owner, cred.client);
633 int retCode = m_accessControl.canDelete(cred,
634 toPermissionMask(permissionRowOpt));
636 if (retCode != CKM_API_SUCCESS) {
637 LogWarning("access control check result: " << retCode);
641 // get all matching rows
643 handler.database.getRows(name, owner, DataType::DB_FIRST,
644 DataType::DB_LAST, rows);
647 LogDebug("No row for given name and owner");
648 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
651 // load app key if needed
652 retCode = loadAppKey(handler, rows.front().owner);
654 if (CKM_API_SUCCESS != retCode)
657 // destroy it in store
658 for (auto &r : rows) {
660 handler.crypto.decryptRow(Password(), r);
661 m_decider.getStore(r).destroy(r);
662 } catch (const Exc::AuthenticationFailed &) {
663 LogDebug("Authentication failed when removing data. Ignored.");
668 handler.database.deleteRow(name, owner);
669 transaction.commit();
671 return CKM_API_SUCCESS;
674 RawBuffer CKMLogic::removeData(
675 const Credentials &cred,
678 const ClientId &explicitOwner)
680 int retCode = CKM_API_ERROR_UNKNOWN;
683 retCode = removeDataHelper(cred, name, explicitOwner);
684 } catch (const Exc::Exception &e) {
686 } catch (const CKM::Exception &e) {
687 LogError("Error: " << e.GetMessage());
688 retCode = CKM_API_ERROR_DB_ERROR;
691 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
694 return response.Pop();
697 int CKMLogic::readSingleRow(const Name &name,
698 const ClientId &owner,
700 DB::Crypto &database,
703 DB::Crypto::RowOptional row_optional;
705 if (dataType.isKey()) {
706 // read all key types
707 row_optional = database.getRow(name,
709 DataType::DB_KEY_FIRST,
710 DataType::DB_KEY_LAST);
712 // read anything else
713 row_optional = database.getRow(name,
719 LogDebug("No row for given name, owner and type");
720 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
725 return CKM_API_SUCCESS;
729 int CKMLogic::readMultiRow(const Name &name,
730 const ClientId &owner,
732 DB::Crypto &database,
733 DB::RowVector &output)
735 if (dataType.isKey())
736 // read all key types
737 database.getRows(name,
739 DataType::DB_KEY_FIRST,
740 DataType::DB_KEY_LAST,
742 else if (dataType.isChainCert())
743 // read all key types
744 database.getRows(name,
746 DataType::DB_CHAIN_FIRST,
747 DataType::DB_CHAIN_LAST,
750 // read anything else
751 database.getRows(name,
756 if (!output.size()) {
757 LogDebug("No row for given name, owner and type");
758 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
761 return CKM_API_SUCCESS;
764 int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred,
766 const ClientId &owner,
769 DB::Crypto &database)
771 PermissionMaskOptional permissionRowOpt =
772 database.getPermissionRow(name, owner, accessorCred.client);
775 return m_accessControl.canExport(accessorCred,
777 toPermissionMask(permissionRowOpt));
779 return m_accessControl.canRead(accessorCred,
780 toPermissionMask(permissionRowOpt));
783 Crypto::GObjUPtr CKMLogic::rowToObject(
786 const Password &password)
788 Crypto::GStore &store = m_decider.getStore(row);
790 Password pass = m_accessControl.isCCMode() ? "" : password;
793 Crypto::GObjUPtr obj;
795 if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
796 CryptoLogic::ENCRYPTION_V2) {
797 handler.crypto.decryptRow(Password(), row);
799 obj = store.getObject(row, pass);
801 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
802 handler.crypto.decryptRow(pass, row);
803 // destroy it in store
806 // import it to store with new scheme: data -> pass(data)
807 Token token = store.import(Crypto::Data(row.dataType, row.data), pass, Crypto::EncryptionParams());
809 // get it from the store (it can be different than the data we imported into store)
810 obj = store.getObject(token, pass);
812 // update row with new token
813 *static_cast<Token *>(&row) = std::move(token);
815 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
816 handler.crypto.encryptRow(row);
819 handler.database.updateRow(row);
825 int CKMLogic::readDataHelper(
827 const Credentials &cred,
830 const ClientId &explicitOwner,
831 const Password &password,
832 Crypto::GObjUPtrVector &objs)
834 auto &handler = selectDatabase(cred, explicitOwner);
836 // use client id if not explicitly provided
837 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
839 if (!isNameValid(name) || !isClientValid(owner))
840 return CKM_API_ERROR_INPUT_PARAM;
843 DB::Crypto::Transaction transaction(&handler.database);
845 int retCode = readMultiRow(name, owner, dataType, handler.database, rows);
847 if (CKM_API_SUCCESS != retCode)
850 // all read rows belong to the same owner
851 DB::Row &firstRow = rows.at(0);
853 // check access rights
854 retCode = checkDataPermissionsHelper(cred, name, owner, firstRow,
855 exportFlag, handler.database);
857 if (CKM_API_SUCCESS != retCode)
860 // load app key if needed
861 retCode = loadAppKey(handler, firstRow.owner);
863 if (CKM_API_SUCCESS != retCode)
867 for (auto &row : rows)
868 objs.push_back(rowToObject(handler, std::move(row), password));
870 // rowToObject may modify db
871 transaction.commit();
873 return CKM_API_SUCCESS;
876 int CKMLogic::readDataHelper(
878 const Credentials &cred,
881 const ClientId &explicitOwner,
882 const Password &password,
883 Crypto::GObjUPtr &obj)
885 DataType objDataType;
886 return readDataHelper(exportFlag, cred, dataType, name, explicitOwner,
887 password, obj, objDataType);
890 int CKMLogic::readDataHelper(
892 const Credentials &cred,
895 const ClientId &explicitOwner,
896 const Password &password,
897 Crypto::GObjUPtr &obj,
898 DataType &objDataType)
900 auto &handler = selectDatabase(cred, explicitOwner);
902 // use client id if not explicitly provided
903 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
905 if (!isNameValid(name) || !isClientValid(owner))
906 return CKM_API_ERROR_INPUT_PARAM;
909 DB::Crypto::Transaction transaction(&handler.database);
911 int retCode = readSingleRow(name, owner, dataType, handler.database, row);
913 if (CKM_API_SUCCESS != retCode)
916 objDataType = row.dataType;
918 // check access rights
919 retCode = checkDataPermissionsHelper(cred, name, owner, row, exportFlag,
922 if (CKM_API_SUCCESS != retCode)
925 // load app key if needed
926 retCode = loadAppKey(handler, row.owner);
928 if (CKM_API_SUCCESS != retCode)
931 obj = rowToObject(handler, std::move(row), password);
932 // rowToObject may modify db
933 transaction.commit();
935 return CKM_API_SUCCESS;
938 RawBuffer CKMLogic::getData(
939 const Credentials &cred,
943 const ClientId &explicitOwner,
944 const Password &password)
946 int retCode = CKM_API_SUCCESS;
948 DataType objDataType;
951 Crypto::GObjUPtr obj;
952 retCode = readDataHelper(true, cred, dataType, name, explicitOwner,
953 password, obj, objDataType);
955 if (retCode == CKM_API_SUCCESS)
956 rowData = obj->getBinary();
957 } catch (const Exc::Exception &e) {
959 } catch (const CKM::Exception &e) {
960 LogError("CKM::Exception: " << e.GetMessage());
961 retCode = CKM_API_ERROR_SERVER_ERROR;
964 if (CKM_API_SUCCESS != retCode)
967 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
970 static_cast<int>(objDataType),
972 return response.Pop();
975 RawBuffer CKMLogic::getDataProtectionStatus(
976 const Credentials &cred,
980 const ClientId &explicitOwner)
982 int retCode = CKM_API_SUCCESS;
984 DataType objDataType;
988 Crypto::GObjUPtr obj;
989 retCode = readDataHelper(false, cred, dataType, name, explicitOwner,
990 password, obj, objDataType);
992 } catch (const Exc::Exception &e) {
994 } catch (const CKM::Exception &e) {
995 LogError("CKM::Exception: " << e.GetMessage());
996 retCode = CKM_API_ERROR_SERVER_ERROR;
999 if (retCode == CKM_API_ERROR_AUTHENTICATION_FAILED) {
1001 retCode = CKM_API_SUCCESS;
1004 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PROTECTION_STATUS),
1007 static_cast<int>(objDataType),
1009 return response.Pop();
1012 int CKMLogic::getPKCS12Helper(
1013 const Credentials &cred,
1015 const ClientId &explicitOwner,
1016 const Password &keyPassword,
1017 const Password &certPassword,
1019 CertificateShPtr &cert,
1020 CertificateShPtrVector &caChain)
1024 // read private key (mandatory)
1025 Crypto::GObjUPtr keyObj;
1026 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, explicitOwner,
1027 keyPassword, keyObj);
1029 if (retCode != CKM_API_SUCCESS) {
1030 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1033 privKey = CKM::Key::create(keyObj->getBinary());
1036 // read certificate (mandatory)
1037 Crypto::GObjUPtr certObj;
1038 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, explicitOwner,
1039 certPassword, certObj);
1041 if (retCode != CKM_API_SUCCESS) {
1042 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1045 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
1048 // read CA cert chain (optional)
1049 Crypto::GObjUPtrVector caChainObjs;
1050 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, explicitOwner,
1051 certPassword, caChainObjs);
1053 if (retCode != CKM_API_SUCCESS && retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1054 if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
1057 for (auto &caCertObj : caChainObjs)
1058 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
1059 DataFormat::FORM_DER));
1062 // if anything found, return it
1063 if (privKey || cert || caChain.size() > 0)
1064 retCode = CKM_API_SUCCESS;
1069 RawBuffer CKMLogic::getPKCS12(
1070 const Credentials &cred,
1073 const ClientId &explicitOwner,
1074 const Password &keyPassword,
1075 const Password &certPassword)
1077 int retCode = CKM_API_ERROR_UNKNOWN;
1079 PKCS12Serializable output;
1083 CertificateShPtr cert;
1084 CertificateShPtrVector caChain;
1085 retCode = getPKCS12Helper(cred, name, explicitOwner, keyPassword,
1086 certPassword, privKey, cert, caChain);
1089 if (retCode == CKM_API_SUCCESS)
1090 output = PKCS12Serializable(std::move(privKey), std::move(cert),
1091 std::move(caChain));
1092 } catch (const Exc::Exception &e) {
1093 retCode = e.error();
1094 } catch (const CKM::Exception &e) {
1095 LogError("CKM::Exception: " << e.GetMessage());
1096 retCode = CKM_API_ERROR_SERVER_ERROR;
1099 auto response = MessageBuffer::Serialize(static_cast<int>
1100 (LogicCommand::GET_PKCS12),
1104 return response.Pop();
1107 int CKMLogic::getDataListHelper(const Credentials &cred,
1108 const DataType dataType,
1109 OwnerNameVector &ownerNameVector)
1111 int retCode = CKM_API_ERROR_DB_LOCKED;
1113 if (0 < m_userDataMap.count(cred.clientUid)) {
1114 auto &database = m_userDataMap[cred.clientUid].database;
1117 OwnerNameVector tmpVector;
1119 if (dataType.isKey()) {
1120 // list all key types
1121 database.listNames(cred.client,
1123 DataType::DB_KEY_FIRST,
1124 DataType::DB_KEY_LAST);
1126 // list anything else
1127 database.listNames(cred.client,
1132 ownerNameVector.insert(ownerNameVector.end(), tmpVector.begin(),
1134 retCode = CKM_API_SUCCESS;
1135 } catch (const CKM::Exception &e) {
1136 LogError("Error: " << e.GetMessage());
1137 retCode = CKM_API_ERROR_DB_ERROR;
1138 } catch (const Exc::Exception &e) {
1139 retCode = e.error();
1146 RawBuffer CKMLogic::getDataList(
1147 const Credentials &cred,
1151 OwnerNameVector systemVector;
1152 OwnerNameVector userVector;
1153 OwnerNameVector ownerNameVector;
1155 int retCode = unlockSystemDB();
1157 if (CKM_API_SUCCESS == retCode) {
1159 if (m_accessControl.isSystemService(cred)) {
1161 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1166 // user - lookup system, then client DB
1167 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1173 if (retCode == CKM_API_SUCCESS) {
1174 retCode = getDataListHelper(cred,
1181 if (retCode == CKM_API_SUCCESS) {
1182 ownerNameVector.insert(ownerNameVector.end(), systemVector.begin(),
1183 systemVector.end());
1184 ownerNameVector.insert(ownerNameVector.end(), userVector.begin(),
1188 auto response = MessageBuffer::Serialize(static_cast<int>
1189 (LogicCommand::GET_LIST),
1192 static_cast<int>(dataType),
1194 return response.Pop();
1197 int CKMLogic::importInitialData(
1199 const Crypto::Data &data,
1200 const Crypto::EncryptionParams &encParams,
1201 const Policy &policy)
1204 if (encParams.iv.empty() != encParams.tag.empty()) {
1205 LogError("Both iv and tag must be empty or set");
1206 return CKM_API_ERROR_INPUT_PARAM;
1209 // Inital values are always imported with root credentials. Client id is not important.
1210 Credentials rootCred(0, "");
1212 auto &handler = selectDatabase(rootCred, CLIENT_ID_SYSTEM);
1214 // check if save is possible
1215 DB::Crypto::Transaction transaction(&handler.database);
1216 int retCode = checkSaveConditions(rootCred, handler, name, CLIENT_ID_SYSTEM);
1218 if (retCode != CKM_API_SUCCESS)
1221 Crypto::GStore &store =
1222 m_decider.getStore(data.type, policy, !encParams.iv.empty());
1226 if (encParams.iv.empty()) {
1227 // Data are not encrypted, let's try to verify them
1228 Crypto::Data binaryData;
1230 if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1233 token = store.import(binaryData,
1234 m_accessControl.isCCMode() ? "" : policy.password,
1237 token = store.import(data,
1238 m_accessControl.isCCMode() ? "" : policy.password,
1242 DB::Row row(std::move(token), name, CLIENT_ID_SYSTEM,
1243 static_cast<int>(policy.extractable));
1244 handler.crypto.encryptRow(row);
1246 handler.database.saveRow(row);
1247 transaction.commit();
1248 } catch (const Exc::Exception &e) {
1250 } catch (const CKM::Exception &e) {
1251 LogError("CKM::Exception: " << e.GetMessage());
1252 return CKM_API_ERROR_SERVER_ERROR;
1253 } catch (const std::exception &e) {
1254 LogError("Std::exception: " << e.what());
1255 return CKM_API_ERROR_SERVER_ERROR;
1258 return CKM_API_SUCCESS;
1261 int CKMLogic::saveDataHelper(
1262 const Credentials &cred,
1264 const ClientId &explicitOwner,
1265 const Crypto::Data &data,
1266 const PolicySerializable &policy)
1268 auto &handler = selectDatabase(cred, explicitOwner);
1270 // use client id if not explicitly provided
1271 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1273 if (m_accessControl.isSystemService(cred) &&
1274 owner.compare(CLIENT_ID_SYSTEM) != 0) {
1275 LogError("System services can only use " << CLIENT_ID_SYSTEM << " as owner id") ;
1276 return CKM_API_ERROR_INPUT_PARAM;
1279 // check if save is possible
1280 DB::Crypto::Transaction transaction(&handler.database);
1281 int retCode = checkSaveConditions(cred, handler, name, owner);
1283 if (retCode != CKM_API_SUCCESS)
1287 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, owner,
1289 handler.database.saveRow(encryptedRow);
1291 transaction.commit();
1292 return CKM_API_SUCCESS;
1295 int CKMLogic::saveDataHelper(
1296 const Credentials &cred,
1298 const ClientId &explicitOwner,
1299 const PKCS12Serializable &pkcs,
1300 const PolicySerializable &keyPolicy,
1301 const PolicySerializable &certPolicy)
1303 auto &handler = selectDatabase(cred, explicitOwner);
1305 // use client id if not explicitly provided
1306 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1308 if (m_accessControl.isSystemService(cred) &&
1309 owner.compare(CLIENT_ID_SYSTEM) != 0)
1310 return CKM_API_ERROR_INPUT_PARAM;
1312 // check if save is possible
1313 DB::Crypto::Transaction transaction(&handler.database);
1314 int retCode = checkSaveConditions(cred, handler, name, owner);
1316 if (retCode != CKM_API_SUCCESS)
1319 // extract and encrypt the data
1320 DB::RowVector encryptedRows;
1321 retCode = extractPKCS12Data(handler.crypto, name, owner, pkcs, keyPolicy,
1322 certPolicy, encryptedRows);
1324 if (retCode != CKM_API_SUCCESS)
1328 handler.database.saveRows(name, owner, encryptedRows);
1329 transaction.commit();
1331 return CKM_API_SUCCESS;
1335 int CKMLogic::createKeyAESHelper(
1336 const Credentials &cred,
1339 const ClientId &explicitOwner,
1340 const PolicySerializable &policy)
1342 auto &handler = selectDatabase(cred, explicitOwner);
1344 // use client id if not explicitly provided
1345 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1347 if (m_accessControl.isSystemService(cred) &&
1348 owner.compare(CLIENT_ID_SYSTEM) != 0)
1349 return CKM_API_ERROR_INPUT_PARAM;
1351 // check if save is possible
1352 DB::Crypto::Transaction transaction(&handler.database);
1353 int retCode = checkSaveConditions(cred, handler, name, owner);
1355 if (retCode != CKM_API_SUCCESS)
1358 // create key in store
1359 CryptoAlgorithm keyGenAlgorithm;
1360 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1361 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1362 Token key = m_decider.getStore(DataType::KEY_AES,
1363 policy).generateSKey(keyGenAlgorithm, policy.password);
1366 DB::Row row(std::move(key), name, owner,
1367 static_cast<int>(policy.extractable));
1368 handler.crypto.encryptRow(row);
1370 handler.database.saveRow(row);
1372 transaction.commit();
1373 return CKM_API_SUCCESS;
1376 int CKMLogic::createKeyPairHelper(
1377 const Credentials &cred,
1378 const CryptoAlgorithmSerializable &keyGenParams,
1379 const Name &namePrivate,
1380 const ClientId &explicitOwnerPrivate,
1381 const Name &namePublic,
1382 const ClientId &explicitOwnerPublic,
1383 const PolicySerializable &policyPrivate,
1384 const PolicySerializable &policyPublic)
1386 auto &handlerPriv = selectDatabase(cred, explicitOwnerPrivate);
1387 auto &handlerPub = selectDatabase(cred, explicitOwnerPublic);
1389 AlgoType keyType = AlgoType::RSA_GEN;
1391 if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1392 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1394 DataType dt(keyType);
1397 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1399 if (policyPrivate.backend != policyPublic.backend)
1400 ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend.");
1402 // use client id if not explicitly provided
1403 const ClientId &ownerPrv = explicitOwnerPrivate.empty() ? cred.client :
1404 explicitOwnerPrivate;
1406 if (m_accessControl.isSystemService(cred) &&
1407 ownerPrv.compare(CLIENT_ID_SYSTEM) != 0)
1408 return CKM_API_ERROR_INPUT_PARAM;
1410 const ClientId &ownerPub = explicitOwnerPublic.empty() ? cred.client :
1411 explicitOwnerPublic;
1413 if (m_accessControl.isSystemService(cred) &&
1414 ownerPub.compare(CLIENT_ID_SYSTEM) != 0)
1415 return CKM_API_ERROR_INPUT_PARAM;
1417 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1418 Policy lessRestricted(Password(), exportable, policyPrivate.backend);
1420 TokenPair keys = m_decider.getStore(dt, lessRestricted).generateAKey(keyGenParams,
1421 policyPrivate.password,
1422 policyPublic.password);
1424 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1425 // in case the same database is used for private and public - the second
1426 // transaction will not be executed
1427 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1430 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerPrv);
1432 if (CKM_API_SUCCESS != retCode)
1435 retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerPub);
1437 if (CKM_API_SUCCESS != retCode)
1441 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerPrv,
1442 static_cast<int>(policyPrivate.extractable));
1443 handlerPriv.crypto.encryptRow(rowPrv);
1444 handlerPriv.database.saveRow(rowPrv);
1446 DB::Row rowPub(std::move(keys.second), namePublic, ownerPub,
1447 static_cast<int>(policyPublic.extractable));
1448 handlerPub.crypto.encryptRow(rowPub);
1449 handlerPub.database.saveRow(rowPub);
1451 transactionPub.commit();
1452 transactionPriv.commit();
1453 return CKM_API_SUCCESS;
1456 RawBuffer CKMLogic::createKeyPair(
1457 const Credentials &cred,
1459 const CryptoAlgorithmSerializable &keyGenParams,
1460 const Name &namePrivate,
1461 const ClientId &explicitOwnerPrivate,
1462 const Name &namePublic,
1463 const ClientId &explicitOwnerPublic,
1464 const PolicySerializable &policyPrivate,
1465 const PolicySerializable &policyPublic)
1467 int retCode = CKM_API_SUCCESS;
1470 retCode = createKeyPairHelper(
1474 explicitOwnerPrivate,
1476 explicitOwnerPublic,
1479 } catch (const Exc::Exception &e) {
1480 retCode = e.error();
1481 } catch (const CKM::Exception &e) {
1482 LogError("CKM::Exception: " << e.GetMessage());
1483 retCode = CKM_API_ERROR_SERVER_ERROR;
1486 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1487 commandId, retCode).Pop();
1490 RawBuffer CKMLogic::createKeyAES(
1491 const Credentials &cred,
1495 const ClientId &explicitOwner,
1496 const PolicySerializable &policy)
1498 int retCode = CKM_API_SUCCESS;
1501 retCode = createKeyAESHelper(cred, size, name, explicitOwner, policy);
1502 } catch (const Exc::Exception &e) {
1503 retCode = e.error();
1504 } catch (std::invalid_argument &e) {
1505 LogDebug("invalid argument error: " << e.what());
1506 retCode = CKM_API_ERROR_INPUT_PARAM;
1507 } catch (const CKM::Exception &e) {
1508 LogError("CKM::Exception: " << e.GetMessage());
1509 retCode = CKM_API_ERROR_SERVER_ERROR;
1512 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1513 commandId, retCode).Pop();
1516 int CKMLogic::readCertificateHelper(
1517 const Credentials &cred,
1518 const OwnerNameVector &ownerNameVector,
1519 CertificateImplVector &certVector)
1521 for (auto &i : ownerNameVector) {
1522 // certificates can't be protected with custom user password
1523 Crypto::GObjUPtr obj;
1525 ec = readDataHelper(true,
1527 DataType::CERTIFICATE,
1533 if (ec != CKM_API_SUCCESS)
1536 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1538 // try to read chain certificates (if present)
1539 Crypto::GObjUPtrVector caChainObjs;
1540 ec = readDataHelper(true,
1542 DataType::DB_CHAIN_FIRST,
1548 if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1551 for (auto &caCertObj : caChainObjs)
1552 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1555 return CKM_API_SUCCESS;
1558 int CKMLogic::getCertificateChainHelper(
1559 const CertificateImpl &cert,
1560 const RawBufferVector &untrustedCertificates,
1561 const RawBufferVector &trustedCertificates,
1562 bool useTrustedSystemCertificates,
1563 RawBufferVector &chainRawVector)
1565 CertificateImplVector untrustedCertVector;
1566 CertificateImplVector trustedCertVector;
1567 CertificateImplVector chainVector;
1570 return CKM_API_ERROR_INPUT_PARAM;
1572 for (auto &e : untrustedCertificates) {
1573 CertificateImpl c(e, DataFormat::FORM_DER);
1576 return CKM_API_ERROR_INPUT_PARAM;
1578 untrustedCertVector.push_back(std::move(c));
1581 for (auto &e : trustedCertificates) {
1582 CertificateImpl c(e, DataFormat::FORM_DER);
1585 return CKM_API_ERROR_INPUT_PARAM;
1587 trustedCertVector.push_back(std::move(c));
1590 CertificateStore store;
1591 int retCode = store.verifyCertificate(cert,
1592 untrustedCertVector,
1594 useTrustedSystemCertificates,
1595 m_accessControl.isCCMode(),
1598 if (retCode != CKM_API_SUCCESS)
1601 for (auto &e : chainVector)
1602 chainRawVector.push_back(e.getDER());
1604 return CKM_API_SUCCESS;
1607 int CKMLogic::getCertificateChainHelper(
1608 const Credentials &cred,
1609 const CertificateImpl &cert,
1610 const OwnerNameVector &untrusted,
1611 const OwnerNameVector &trusted,
1612 bool useTrustedSystemCertificates,
1613 RawBufferVector &chainRawVector)
1615 CertificateImplVector untrustedCertVector;
1616 CertificateImplVector trustedCertVector;
1617 CertificateImplVector chainVector;
1620 return CKM_API_ERROR_INPUT_PARAM;
1622 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1624 if (retCode != CKM_API_SUCCESS)
1627 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1629 if (retCode != CKM_API_SUCCESS)
1632 CertificateStore store;
1633 retCode = store.verifyCertificate(cert,
1634 untrustedCertVector,
1636 useTrustedSystemCertificates,
1637 m_accessControl.isCCMode(),
1640 if (retCode != CKM_API_SUCCESS)
1643 for (auto &i : chainVector)
1644 chainRawVector.push_back(i.getDER());
1646 return CKM_API_SUCCESS;
1649 RawBuffer CKMLogic::getCertificateChain(
1650 const Credentials & /*cred*/,
1652 const RawBuffer &certificate,
1653 const RawBufferVector &untrustedCertificates,
1654 const RawBufferVector &trustedCertificates,
1655 bool useTrustedSystemCertificates)
1657 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1658 RawBufferVector chainRawVector;
1659 int retCode = CKM_API_ERROR_UNKNOWN;
1662 retCode = getCertificateChainHelper(cert,
1663 untrustedCertificates,
1664 trustedCertificates,
1665 useTrustedSystemCertificates,
1667 } catch (const Exc::Exception &e) {
1668 retCode = e.error();
1669 } catch (const std::exception &e) {
1670 LogError("STD exception " << e.what());
1671 retCode = CKM_API_ERROR_SERVER_ERROR;
1673 LogError("Unknown error.");
1676 auto response = MessageBuffer::Serialize(static_cast<int>
1677 (LogicCommand::GET_CHAIN_CERT),
1681 return response.Pop();
1684 RawBuffer CKMLogic::getCertificateChain(
1685 const Credentials &cred,
1687 const RawBuffer &certificate,
1688 const OwnerNameVector &untrustedCertificates,
1689 const OwnerNameVector &trustedCertificates,
1690 bool useTrustedSystemCertificates)
1692 int retCode = CKM_API_ERROR_UNKNOWN;
1693 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1694 RawBufferVector chainRawVector;
1697 retCode = getCertificateChainHelper(cred,
1699 untrustedCertificates,
1700 trustedCertificates,
1701 useTrustedSystemCertificates,
1703 } catch (const Exc::Exception &e) {
1704 retCode = e.error();
1705 } catch (const std::exception &e) {
1706 LogError("STD exception " << e.what());
1707 retCode = CKM_API_ERROR_SERVER_ERROR;
1709 LogError("Unknown error.");
1712 auto response = MessageBuffer::Serialize(static_cast<int>
1713 (LogicCommand::GET_CHAIN_ALIAS),
1717 return response.Pop();
1720 RawBuffer CKMLogic::createSignature(
1721 const Credentials &cred,
1723 const Name &privateKeyName,
1724 const ClientId &explicitOwner,
1725 const Password &password, // password for private_key
1726 const RawBuffer &message,
1727 const CryptoAlgorithm &cryptoAlg)
1729 RawBuffer signature;
1731 int retCode = CKM_API_SUCCESS;
1734 Crypto::GObjUPtr obj;
1735 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
1736 explicitOwner, password, obj);
1738 if (retCode == CKM_API_SUCCESS)
1739 signature = obj->sign(cryptoAlg, message);
1740 } catch (const Exc::Exception &e) {
1741 retCode = e.error();
1742 } catch (const CKM::Exception &e) {
1743 LogError("Unknown CKM::Exception: " << e.GetMessage());
1744 retCode = CKM_API_ERROR_SERVER_ERROR;
1745 } catch (const std::exception &e) {
1746 LogError("STD exception " << e.what());
1747 retCode = CKM_API_ERROR_SERVER_ERROR;
1750 auto response = MessageBuffer::Serialize(static_cast<int>
1751 (LogicCommand::CREATE_SIGNATURE),
1755 return response.Pop();
1758 RawBuffer CKMLogic::verifySignature(
1759 const Credentials &cred,
1761 const Name &publicKeyOrCertName,
1762 const ClientId &explicitOwner,
1763 const Password &password, // password for public_key (optional)
1764 const RawBuffer &message,
1765 const RawBuffer &signature,
1766 const CryptoAlgorithm ¶ms)
1768 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1771 // try certificate first - looking for a public key.
1772 // in case of PKCS, pub key from certificate will be found first
1773 // rather than private key from the same PKCS.
1774 Crypto::GObjUPtr obj;
1775 retCode = readDataHelper(false, cred, DataType::CERTIFICATE,
1776 publicKeyOrCertName, explicitOwner, password, obj);
1778 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1779 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
1780 publicKeyOrCertName, explicitOwner, password, obj);
1782 if (retCode == CKM_API_SUCCESS)
1783 retCode = obj->verify(params, message, signature);
1784 } catch (const Exc::Exception &e) {
1785 retCode = e.error();
1786 } catch (const CKM::Exception &e) {
1787 LogError("Unknown CKM::Exception: " << e.GetMessage());
1788 retCode = CKM_API_ERROR_SERVER_ERROR;
1791 auto response = MessageBuffer::Serialize(static_cast<int>
1792 (LogicCommand::VERIFY_SIGNATURE),
1795 return response.Pop();
1798 int CKMLogic::setPermissionHelper(
1799 const Credentials &cred, // who's the client
1801 const ClientId &explicitOwner, // who's the owner
1802 const ClientId &accessor, // who will get the access
1803 const PermissionMask permissionMask)
1805 auto &handler = selectDatabase(cred, explicitOwner);
1807 // we don't know the client
1808 if (cred.client.empty() || !isClientValid(cred.client))
1809 return CKM_API_ERROR_INPUT_PARAM;
1811 // use client id if not explicitly provided
1812 const ClientId &owner = explicitOwner.empty() ? cred.client : explicitOwner;
1814 // verify name and owner are correct
1815 if (!isNameValid(name) || !isClientValid(owner) ||
1816 !isClientValid(accessor))
1817 return CKM_API_ERROR_INPUT_PARAM;
1819 // currently we don't support modification of owner's permissions to his own rows
1820 if (owner == accessor)
1821 return CKM_API_ERROR_INPUT_PARAM;
1823 // system database does not support write/remove permissions
1824 if ((0 == owner.compare(CLIENT_ID_SYSTEM)) &&
1825 (permissionMask & Permission::REMOVE))
1826 return CKM_API_ERROR_INPUT_PARAM;
1828 // can the client modify permissions to owner's row?
1829 int retCode = m_accessControl.canModify(cred, owner);
1831 if (retCode != CKM_API_SUCCESS)
1834 DB::Crypto::Transaction transaction(&handler.database);
1836 if (!handler.database.isNameOwnerPresent(name, owner))
1837 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1839 // set permissions to the row owned by owner for accessor
1840 handler.database.setPermission(name, owner, accessor, permissionMask);
1841 transaction.commit();
1843 return CKM_API_SUCCESS;
1846 RawBuffer CKMLogic::setPermission(
1847 const Credentials &cred,
1851 const ClientId &explicitOwner,
1852 const ClientId &accessor,
1853 const PermissionMask permissionMask)
1858 retCode = setPermissionHelper(cred, name, explicitOwner, accessor, permissionMask);
1859 } catch (const Exc::Exception &e) {
1860 retCode = e.error();
1861 } catch (const CKM::Exception &e) {
1862 LogError("Error: " << e.GetMessage());
1863 retCode = CKM_API_ERROR_DB_ERROR;
1866 return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1869 int CKMLogic::loadAppKey(UserData &handle, const ClientId &owner)
1871 if (!handle.crypto.haveKey(owner)) {
1873 auto key_optional = handle.database.getKey(owner);
1875 if (!key_optional) {
1876 LogError("No key for given owner in database");
1877 return CKM_API_ERROR_DB_ERROR;
1880 key = *key_optional;
1881 key = handle.keyProvider.getPureDEK(key);
1882 handle.crypto.pushKey(owner, key);
1885 return CKM_API_SUCCESS;