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 isLabelValid(const CKM::Label &label)
44 // TODO: copy code from libprivilege control (for check smack label)
45 if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos)
51 bool isNameValid(const CKM::Name &name)
53 if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
59 } // anonymous namespace
63 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
64 const uid_t CKMLogic::ADMIN_USER_DB_UID = 5001;
68 CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
70 m_accessControl.updateCCMode();
73 CKMLogic::~CKMLogic() {}
75 void CKMLogic::loadDKEKFile(uid_t user, const Password &password)
77 auto &handle = m_userDataMap[user];
81 auto wrappedDKEK = fs.getDKEK();
83 if (wrappedDKEK.empty()) {
84 wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
85 fs.saveDKEK(wrappedDKEK);
88 handle.keyProvider = KeyProvider(wrappedDKEK, password);
91 void CKMLogic::saveDKEKFile(uid_t user, const Password &password)
93 auto &handle = m_userDataMap[user];
96 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
99 void CKMLogic::migrateSecureStorageData(bool isAdminUser)
101 SsMigration::migrate(isAdminUser, [this](const std::string &name,
102 const Crypto::Data &data,
103 bool adminUserFlag) {
104 LogInfo("Migrate data called with name: " << name);
105 auto ownerId = adminUserFlag ? OWNER_ID_ADMIN_USER : OWNER_ID_SYSTEM;
106 auto uid = adminUserFlag ? ADMIN_USER_DB_UID : SYSTEM_DB_UID;
108 int ret = verifyAndSaveDataHelper(Credentials(uid, ownerId), name, ownerId, data,
109 PolicySerializable());
111 if (ret == CKM_API_ERROR_DB_ALIAS_EXISTS)
112 LogWarning("Alias already exist for migrated name: " << name);
113 else if (ret != CKM_API_SUCCESS)
114 LogError("Failed to migrate secure-storage data. name: " << name <<
119 int CKMLogic::unlockDatabase(uid_t user, const Password &password)
121 if (0 < m_userDataMap.count(user) &&
122 m_userDataMap[user].keyProvider.isInitialized())
123 return CKM_API_SUCCESS;
125 int retCode = CKM_API_SUCCESS;
128 auto &handle = m_userDataMap[user];
131 loadDKEKFile(user, password);
133 auto wrappedDatabaseDEK = fs.getDBDEK();
135 if (wrappedDatabaseDEK.empty()) {
136 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
137 fs.saveDBDEK(wrappedDatabaseDEK);
140 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
142 handle.database = DB::Crypto(fs.getDBPath(), key);
143 handle.crypto = CryptoLogic();
145 if (!m_accessControl.isSystemService(user)) {
146 // remove data of removed apps during locked state
147 AppLabelVector removedApps = fs.clearRemovedsApps();
149 for (auto &appSmackLabel : removedApps) {
150 handle.crypto.removeKey(appSmackLabel);
151 handle.database.deleteKey(appSmackLabel);
155 if (user == SYSTEM_DB_UID && SsMigration::hasData())
156 migrateSecureStorageData(false);
157 else if (user == ADMIN_USER_DB_UID && SsMigration::hasData())
158 migrateSecureStorageData(true);
159 } catch (const Exc::Exception &e) {
161 } catch (const CKM::Exception &e) {
162 LogError("CKM::Exception: " << e.GetMessage());
163 retCode = CKM_API_ERROR_SERVER_ERROR;
166 if (CKM_API_SUCCESS != retCode)
167 m_userDataMap.erase(user);
172 int CKMLogic::unlockSystemDB()
174 return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
177 UserData &CKMLogic::selectDatabase(const Credentials &cred,
178 const Label &incoming_label)
180 // if user trying to access system service - check:
181 // * if user database is unlocked [mandatory]
182 // * if not - proceed with regular user database
183 // * if explicit system database label given -> switch to system DB
184 if (!m_accessControl.isSystemService(cred)) {
185 if (0 == m_userDataMap.count(cred.clientUid))
186 ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
188 if (0 != incoming_label.compare(OWNER_ID_SYSTEM))
189 return m_userDataMap[cred.clientUid];
192 // system database selected, modify the label
193 if (CKM_API_SUCCESS != unlockSystemDB())
194 ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
196 return m_userDataMap[SYSTEM_DB_UID];
199 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
201 int retCode = CKM_API_SUCCESS;
203 if (!m_accessControl.isSystemService(user))
204 retCode = unlockDatabase(user, password);
205 else // do not allow lock/unlock operations for system users
206 retCode = CKM_API_ERROR_INPUT_PARAM;
208 return MessageBuffer::Serialize(retCode).Pop();
211 RawBuffer CKMLogic::updateCCMode()
213 m_accessControl.updateCCMode();
214 return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
217 RawBuffer CKMLogic::lockUserKey(uid_t user)
219 int retCode = CKM_API_SUCCESS;
221 if (!m_accessControl.isSystemService(user))
222 m_userDataMap.erase(user);
223 else // do not allow lock/unlock operations for system users
224 retCode = CKM_API_ERROR_INPUT_PARAM;
226 return MessageBuffer::Serialize(retCode).Pop();
229 RawBuffer CKMLogic::removeUserData(uid_t user)
231 int retCode = CKM_API_SUCCESS;
233 if (m_accessControl.isSystemService(user))
234 user = SYSTEM_DB_UID;
236 m_userDataMap.erase(user);
241 return MessageBuffer::Serialize(retCode).Pop();
244 int CKMLogic::changeUserPasswordHelper(uid_t user,
245 const Password &oldPassword,
246 const Password &newPassword)
248 // do not allow to change system database password
249 if (m_accessControl.isSystemService(user))
250 return CKM_API_ERROR_INPUT_PARAM;
252 loadDKEKFile(user, oldPassword);
253 saveDKEKFile(user, newPassword);
255 return CKM_API_SUCCESS;
258 RawBuffer CKMLogic::changeUserPassword(
260 const Password &oldPassword,
261 const Password &newPassword)
263 int retCode = CKM_API_SUCCESS;
266 retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
267 } catch (const Exc::Exception &e) {
269 } catch (const CKM::Exception &e) {
270 LogError("CKM::Exception: " << e.GetMessage());
271 retCode = CKM_API_ERROR_SERVER_ERROR;
274 return MessageBuffer::Serialize(retCode).Pop();
277 int CKMLogic::resetUserPasswordHelper(
279 const Password &newPassword)
281 // do not allow to reset system database password
282 if (m_accessControl.isSystemService(user))
283 return CKM_API_ERROR_INPUT_PARAM;
285 int retCode = CKM_API_SUCCESS;
287 if (0 == m_userDataMap.count(user)) {
288 // Check if key exists. If exists we must return error
290 auto wrappedDKEKMain = fs.getDKEK();
292 if (!wrappedDKEKMain.empty())
293 retCode = CKM_API_ERROR_BAD_REQUEST;
295 saveDKEKFile(user, newPassword);
301 RawBuffer CKMLogic::resetUserPassword(
303 const Password &newPassword)
305 int retCode = CKM_API_SUCCESS;
308 retCode = resetUserPasswordHelper(user, newPassword);
309 } catch (const Exc::Exception &e) {
311 } catch (const CKM::Exception &e) {
312 LogError("CKM::Exception: " << e.GetMessage());
313 retCode = CKM_API_ERROR_SERVER_ERROR;
316 return MessageBuffer::Serialize(retCode).Pop();
319 RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel)
321 int retCode = CKM_API_SUCCESS;
324 if (smackLabel.empty()) {
325 retCode = CKM_API_ERROR_INPUT_PARAM;
327 UidVector uids = FileSystem::getUIDsFromDBFile();
329 for (auto userId : uids) {
330 if (0 == m_userDataMap.count(userId)) {
331 FileSystem fs(userId);
332 fs.addRemovedApp(smackLabel);
334 auto &handle = m_userDataMap[userId];
335 handle.crypto.removeKey(smackLabel);
336 handle.database.deleteKey(smackLabel);
340 } catch (const Exc::Exception &e) {
342 } catch (const CKM::Exception &e) {
343 LogError("CKM::Exception: " << e.GetMessage());
344 retCode = CKM_API_ERROR_SERVER_ERROR;
347 return MessageBuffer::Serialize(retCode).Pop();
350 int CKMLogic::checkSaveConditions(
351 const Credentials &cred,
354 const Label &ownerLabel)
356 // verify name and label are correct
357 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
358 LogDebug("Invalid parameter passed to key-manager");
359 return CKM_API_ERROR_INPUT_PARAM;
362 // check if allowed to save using ownerLabel
363 int access_ec = m_accessControl.canSave(cred, ownerLabel);
365 if (access_ec != CKM_API_SUCCESS) {
366 LogDebug("label " << cred.smackLabel << " can not save rows using label " <<
371 // check if not a duplicate
372 if (handler.database.isNameLabelPresent(name, ownerLabel))
373 return CKM_API_ERROR_DB_ALIAS_EXISTS;
375 // encryption section
376 if (!handler.crypto.haveKey(ownerLabel)) {
378 auto key_optional = handler.database.getKey(ownerLabel);
381 LogDebug("No Key in database found. Generating new one for label: " <<
383 got_key = handler.keyProvider.generateDEK(ownerLabel);
384 handler.database.saveKey(ownerLabel, got_key);
386 LogDebug("Key from DB");
387 got_key = *key_optional;
390 got_key = handler.keyProvider.getPureDEK(got_key);
391 handler.crypto.pushKey(ownerLabel, got_key);
394 return CKM_API_SUCCESS;
397 DB::Row CKMLogic::createEncryptedRow(
401 const Crypto::Data &data,
402 const Policy &policy) const
404 Crypto::GStore &store = m_decider.getStore(data.type, policy.extractable);
406 // do not encrypt data with password during cc_mode on
407 Token token = store.import(data,
408 m_accessControl.isCCMode() ? "" : policy.password);
409 DB::Row row(std::move(token), name, label,
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,
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, label, 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,
487 const Password &pass,
488 Crypto::GObjShPtr &key)
493 // Key is for internal service use. It won't be exported to the client
494 Crypto::GObjUPtr obj;
495 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label,
498 if (retCode == CKM_API_SUCCESS)
499 key = std::move(obj);
502 } catch (const Exc::Exception &e) {
504 } catch (const CKM::Exception &e) {
505 LogError("CKM::Exception: " << e.GetMessage());
506 return CKM_API_ERROR_SERVER_ERROR;
510 RawBuffer CKMLogic::saveData(
511 const Credentials &cred,
515 const Crypto::Data &data,
516 const PolicySerializable &policy)
518 int retCode = verifyAndSaveDataHelper(cred, name, label, data, policy);
519 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
522 static_cast<int>(data.type));
523 return response.Pop();
526 int CKMLogic::extractPKCS12Data(
529 const Label &ownerLabel,
530 const PKCS12Serializable &pkcs,
531 const PolicySerializable &keyPolicy,
532 const PolicySerializable &certPolicy,
533 DB::RowVector &output) const
535 // private key is mandatory
536 auto key = pkcs.getKey();
539 LogError("Failed to get private key from pkcs");
540 return CKM_API_ERROR_INVALID_FORMAT;
543 Crypto::Data keyData(DataType(key->getType()), key->getDER());
544 int retCode = verifyBinaryData(keyData);
546 if (retCode != CKM_API_SUCCESS)
549 output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyData,
552 // certificate is mandatory
553 auto cert = pkcs.getCertificate();
556 LogError("Failed to get certificate from pkcs");
557 return CKM_API_ERROR_INVALID_FORMAT;
560 Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
561 retCode = verifyBinaryData(certData);
563 if (retCode != CKM_API_SUCCESS)
566 output.push_back(createEncryptedRow(crypto, name, ownerLabel, certData,
570 unsigned int cert_index = 0;
572 for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
573 Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++),
575 int retCode = verifyBinaryData(caCertData);
577 if (retCode != CKM_API_SUCCESS)
580 output.push_back(createEncryptedRow(crypto, name, ownerLabel, caCertData,
584 return CKM_API_SUCCESS;
587 RawBuffer CKMLogic::savePKCS12(
588 const Credentials &cred,
592 const PKCS12Serializable &pkcs,
593 const PolicySerializable &keyPolicy,
594 const PolicySerializable &certPolicy)
596 int retCode = CKM_API_ERROR_UNKNOWN;
599 retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
600 } catch (const Exc::Exception &e) {
602 } catch (const CKM::Exception &e) {
603 LogError("CKM::Exception: " << e.GetMessage());
604 retCode = CKM_API_ERROR_SERVER_ERROR;
607 auto response = MessageBuffer::Serialize(static_cast<int>
608 (LogicCommand::SAVE_PKCS12),
611 return response.Pop();
615 int CKMLogic::removeDataHelper(
616 const Credentials &cred,
620 auto &handler = selectDatabase(cred, label);
622 // use client label if not explicitly provided
623 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
625 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
626 LogDebug("Invalid label or name format");
627 return CKM_API_ERROR_INPUT_PARAM;
630 DB::Crypto::Transaction transaction(&handler.database);
632 // read and check permissions
633 PermissionMaskOptional permissionRowOpt =
634 handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel);
635 int retCode = m_accessControl.canDelete(cred,
636 PermissionForLabel(cred.smackLabel, permissionRowOpt));
638 if (retCode != CKM_API_SUCCESS) {
639 LogWarning("access control check result: " << retCode);
643 // get all matching rows
645 handler.database.getRows(name, ownerLabel, DataType::DB_FIRST,
646 DataType::DB_LAST, rows);
649 LogDebug("No row for given name and label");
650 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
653 // load app key if needed
654 retCode = loadAppKey(handler, rows.front().ownerLabel);
656 if (CKM_API_SUCCESS != retCode)
659 // destroy it in store
660 for (auto &r : rows) {
662 handler.crypto.decryptRow(Password(), r);
663 m_decider.getStore(r).destroy(r);
664 } catch (const Exc::AuthenticationFailed &) {
665 LogDebug("Authentication failed when removing data. Ignored.");
670 handler.database.deleteRow(name, ownerLabel);
671 transaction.commit();
673 return CKM_API_SUCCESS;
676 RawBuffer CKMLogic::removeData(
677 const Credentials &cred,
682 int retCode = CKM_API_ERROR_UNKNOWN;
685 retCode = removeDataHelper(cred, name, label);
686 } catch (const Exc::Exception &e) {
688 } catch (const CKM::Exception &e) {
689 LogError("Error: " << e.GetMessage());
690 retCode = CKM_API_ERROR_DB_ERROR;
693 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
696 return response.Pop();
699 int CKMLogic::readSingleRow(const Name &name,
700 const Label &ownerLabel,
702 DB::Crypto &database,
705 DB::Crypto::RowOptional row_optional;
707 if (dataType.isKey()) {
708 // read all key types
709 row_optional = database.getRow(name,
711 DataType::DB_KEY_FIRST,
712 DataType::DB_KEY_LAST);
714 // read anything else
715 row_optional = database.getRow(name,
721 LogDebug("No row for given name, label and type");
722 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
727 return CKM_API_SUCCESS;
731 int CKMLogic::readMultiRow(const Name &name,
732 const Label &ownerLabel,
734 DB::Crypto &database,
735 DB::RowVector &output)
737 if (dataType.isKey())
738 // read all key types
739 database.getRows(name,
741 DataType::DB_KEY_FIRST,
742 DataType::DB_KEY_LAST,
744 else if (dataType.isChainCert())
745 // read all key types
746 database.getRows(name,
748 DataType::DB_CHAIN_FIRST,
749 DataType::DB_CHAIN_LAST,
752 // read anything else
753 database.getRows(name,
758 if (!output.size()) {
759 LogDebug("No row for given name, label and type");
760 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
763 return CKM_API_SUCCESS;
766 int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
768 const Label &ownerLabel,
769 const Label &accessorLabel,
772 DB::Crypto &database)
774 PermissionMaskOptional permissionRowOpt =
775 database.getPermissionRow(name, ownerLabel, accessorLabel);
778 return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel,
781 return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel,
785 Crypto::GObjUPtr CKMLogic::rowToObject(
788 const Password &password)
790 Crypto::GStore &store = m_decider.getStore(row);
792 Password pass = m_accessControl.isCCMode() ? "" : password;
795 Crypto::GObjUPtr obj;
797 if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
798 CryptoLogic::ENCRYPTION_V2) {
799 handler.crypto.decryptRow(Password(), row);
801 obj = store.getObject(row, pass);
803 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
804 handler.crypto.decryptRow(pass, row);
805 // destroy it in store
808 // import it to store with new scheme: data -> pass(data)
809 Token token = store.import(Crypto::Data(row.dataType, row.data), pass);
811 // get it from the store (it can be different than the data we imported into store)
812 obj = store.getObject(token, pass);
814 // update row with new token
815 *static_cast<Token *>(&row) = std::move(token);
817 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
818 handler.crypto.encryptRow(row);
821 handler.database.updateRow(row);
827 int CKMLogic::readDataHelper(
829 const Credentials &cred,
833 const Password &password,
834 Crypto::GObjUPtrVector &objs)
836 auto &handler = selectDatabase(cred, label);
838 // use client label if not explicitly provided
839 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
841 if (!isNameValid(name) || !isLabelValid(ownerLabel))
842 return CKM_API_ERROR_INPUT_PARAM;
845 DB::Crypto::Transaction transaction(&handler.database);
847 int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
849 if (CKM_API_SUCCESS != retCode)
852 // all read rows belong to the same owner
853 DB::Row &firstRow = rows.at(0);
855 // check access rights
856 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel,
857 firstRow, exportFlag, handler.database);
859 if (CKM_API_SUCCESS != retCode)
862 // load app key if needed
863 retCode = loadAppKey(handler, firstRow.ownerLabel);
865 if (CKM_API_SUCCESS != retCode)
869 for (auto &row : rows)
870 objs.push_back(rowToObject(handler, std::move(row), password));
872 // rowToObject may modify db
873 transaction.commit();
875 return CKM_API_SUCCESS;
878 int CKMLogic::readDataHelper(
880 const Credentials &cred,
884 const Password &password,
885 Crypto::GObjUPtr &obj)
887 DataType objDataType;
888 return readDataHelper(exportFlag, cred, dataType, name, label, password, obj,
892 int CKMLogic::readDataHelper(
894 const Credentials &cred,
898 const Password &password,
899 Crypto::GObjUPtr &obj,
900 DataType &objDataType)
902 auto &handler = selectDatabase(cred, label);
904 // use client label if not explicitly provided
905 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
907 if (!isNameValid(name) || !isLabelValid(ownerLabel))
908 return CKM_API_ERROR_INPUT_PARAM;
911 DB::Crypto::Transaction transaction(&handler.database);
913 int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
915 if (CKM_API_SUCCESS != retCode)
918 objDataType = row.dataType;
920 // check access rights
921 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel,
922 row, exportFlag, handler.database);
924 if (CKM_API_SUCCESS != retCode)
927 // load app key if needed
928 retCode = loadAppKey(handler, row.ownerLabel);
930 if (CKM_API_SUCCESS != retCode)
933 obj = rowToObject(handler, std::move(row), password);
934 // rowToObject may modify db
935 transaction.commit();
937 return CKM_API_SUCCESS;
940 RawBuffer CKMLogic::getData(
941 const Credentials &cred,
946 const Password &password)
948 int retCode = CKM_API_SUCCESS;
950 DataType objDataType;
953 Crypto::GObjUPtr obj;
954 retCode = readDataHelper(true, cred, dataType, name, label, password, obj,
957 if (retCode == CKM_API_SUCCESS)
958 row.data = std::move(obj->getBinary());
959 } catch (const Exc::Exception &e) {
961 } catch (const CKM::Exception &e) {
962 LogError("CKM::Exception: " << e.GetMessage());
963 retCode = CKM_API_ERROR_SERVER_ERROR;
966 if (CKM_API_SUCCESS != retCode) {
968 row.dataType = dataType;
971 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
974 static_cast<int>(objDataType),
976 return response.Pop();
979 int CKMLogic::getPKCS12Helper(
980 const Credentials &cred,
983 const Password &keyPassword,
984 const Password &certPassword,
986 CertificateShPtr &cert,
987 CertificateShPtrVector &caChain)
991 // read private key (mandatory)
992 Crypto::GObjUPtr keyObj;
993 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label,
994 keyPassword, keyObj);
996 if (retCode != CKM_API_SUCCESS)
999 privKey = CKM::Key::create(keyObj->getBinary());
1001 // read certificate (mandatory)
1002 Crypto::GObjUPtr certObj;
1003 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label,
1004 certPassword, certObj);
1006 if (retCode != CKM_API_SUCCESS)
1009 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
1011 // read CA cert chain (optional)
1012 Crypto::GObjUPtrVector caChainObjs;
1013 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label,
1014 certPassword, caChainObjs);
1016 if (retCode != CKM_API_SUCCESS &&
1017 retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1020 for (auto &caCertObj : caChainObjs)
1021 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
1022 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,
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, label, keyPassword, certPassword, privKey,
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 LabelNameVector &labelNameVector)
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 LabelNameVector tmpVector;
1081 if (dataType.isKey()) {
1082 // list all key types
1083 database.listNames(cred.smackLabel,
1085 DataType::DB_KEY_FIRST,
1086 DataType::DB_KEY_LAST);
1088 // list anything else
1089 database.listNames(cred.smackLabel,
1094 labelNameVector.insert(labelNameVector.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 LabelNameVector systemVector;
1114 LabelNameVector userVector;
1115 LabelNameVector labelNameVector;
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 labelNameVector.insert(labelNameVector.end(), systemVector.begin(),
1145 systemVector.end());
1146 labelNameVector.insert(labelNameVector.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. Label is not important.
1167 Credentials rootCred(0, "");
1169 auto &handler = selectDatabase(rootCred, OWNER_ID_SYSTEM);
1171 // check if save is possible
1172 DB::Crypto::Transaction transaction(&handler.database);
1173 int retCode = checkSaveConditions(rootCred, handler, name, OWNER_ID_SYSTEM);
1175 if (retCode != CKM_API_SUCCESS)
1178 Crypto::GStore &store =
1179 m_decider.getStore(data.type, policy.extractable, !enc.encryptedKey.empty());
1183 if (enc.encryptedKey.empty()) {
1184 Crypto::Data binaryData;
1186 if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1189 token = store.import(binaryData,
1190 m_accessControl.isCCMode() ? "" : policy.password);
1192 token = store.importEncrypted(data,
1193 m_accessControl.isCCMode() ? "" : policy.password, enc);
1196 DB::Row row(std::move(token), name, OWNER_ID_SYSTEM,
1197 static_cast<int>(policy.extractable));
1198 handler.crypto.encryptRow(row);
1200 handler.database.saveRow(row);
1201 transaction.commit();
1202 } catch (const Exc::Exception &e) {
1204 } catch (const CKM::Exception &e) {
1205 LogError("CKM::Exception: " << e.GetMessage());
1206 return CKM_API_ERROR_SERVER_ERROR;
1207 } catch (const std::exception &e) {
1208 LogError("Std::exception: " << e.what());
1209 return CKM_API_ERROR_SERVER_ERROR;
1212 return CKM_API_SUCCESS;
1215 int CKMLogic::saveDataHelper(
1216 const Credentials &cred,
1219 const Crypto::Data &data,
1220 const PolicySerializable &policy)
1222 auto &handler = selectDatabase(cred, label);
1224 // use client label if not explicitly provided
1225 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1227 if (m_accessControl.isSystemService(cred) &&
1228 ownerLabel.compare(OWNER_ID_SYSTEM) != 0)
1229 return CKM_API_ERROR_INPUT_PARAM;
1231 // check if save is possible
1232 DB::Crypto::Transaction transaction(&handler.database);
1233 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1235 if (retCode != CKM_API_SUCCESS)
1239 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel,
1241 handler.database.saveRow(encryptedRow);
1243 transaction.commit();
1244 return CKM_API_SUCCESS;
1247 int CKMLogic::saveDataHelper(
1248 const Credentials &cred,
1251 const PKCS12Serializable &pkcs,
1252 const PolicySerializable &keyPolicy,
1253 const PolicySerializable &certPolicy)
1255 auto &handler = selectDatabase(cred, label);
1257 // use client label if not explicitly provided
1258 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1260 if (m_accessControl.isSystemService(cred) &&
1261 ownerLabel.compare(OWNER_ID_SYSTEM) != 0)
1262 return CKM_API_ERROR_INPUT_PARAM;
1264 // check if save is possible
1265 DB::Crypto::Transaction transaction(&handler.database);
1266 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1268 if (retCode != CKM_API_SUCCESS)
1271 // extract and encrypt the data
1272 DB::RowVector encryptedRows;
1273 retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy,
1274 certPolicy, encryptedRows);
1276 if (retCode != CKM_API_SUCCESS)
1280 handler.database.saveRows(name, ownerLabel, encryptedRows);
1281 transaction.commit();
1283 return CKM_API_SUCCESS;
1287 int CKMLogic::createKeyAESHelper(
1288 const Credentials &cred,
1292 const PolicySerializable &policy)
1294 auto &handler = selectDatabase(cred, label);
1296 // use client label if not explicitly provided
1297 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1299 if (m_accessControl.isSystemService(cred) &&
1300 ownerLabel.compare(OWNER_ID_SYSTEM) != 0)
1301 return CKM_API_ERROR_INPUT_PARAM;
1303 // check if save is possible
1304 DB::Crypto::Transaction transaction(&handler.database);
1305 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1307 if (retCode != CKM_API_SUCCESS)
1310 // create key in store
1311 CryptoAlgorithm keyGenAlgorithm;
1312 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1313 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1314 Token key = m_decider.getStore(DataType::KEY_AES,
1315 policy.extractable).generateSKey(keyGenAlgorithm, policy.password);
1318 DB::Row row(std::move(key), name, ownerLabel,
1319 static_cast<int>(policy.extractable));
1320 handler.crypto.encryptRow(row);
1322 handler.database.saveRow(row);
1324 transaction.commit();
1325 return CKM_API_SUCCESS;
1328 int CKMLogic::createKeyPairHelper(
1329 const Credentials &cred,
1330 const CryptoAlgorithmSerializable &keyGenParams,
1331 const Name &namePrivate,
1332 const Label &labelPrivate,
1333 const Name &namePublic,
1334 const Label &labelPublic,
1335 const PolicySerializable &policyPrivate,
1336 const PolicySerializable &policyPublic)
1338 auto &handlerPriv = selectDatabase(cred, labelPrivate);
1339 auto &handlerPub = selectDatabase(cred, labelPublic);
1341 AlgoType keyType = AlgoType::RSA_GEN;
1343 if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1344 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1346 DataType dt(keyType);
1349 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1351 // use client label if not explicitly provided
1352 const Label &ownerLabelPrv = labelPrivate.empty() ? cred.smackLabel :
1355 if (m_accessControl.isSystemService(cred) &&
1356 ownerLabelPrv.compare(OWNER_ID_SYSTEM) != 0)
1357 return CKM_API_ERROR_INPUT_PARAM;
1359 const Label &ownerLabelPub = labelPublic.empty() ? cred.smackLabel :
1362 if (m_accessControl.isSystemService(cred) &&
1363 ownerLabelPub.compare(OWNER_ID_SYSTEM) != 0)
1364 return CKM_API_ERROR_INPUT_PARAM;
1366 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1367 TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams,
1368 policyPrivate.password,
1369 policyPublic.password);
1371 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1372 // in case the same database is used for private and public - the second
1373 // transaction will not be executed
1374 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1377 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerLabelPrv);
1379 if (CKM_API_SUCCESS != retCode)
1382 retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerLabelPub);
1384 if (CKM_API_SUCCESS != retCode)
1388 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerLabelPrv,
1389 static_cast<int>(policyPrivate.extractable));
1390 handlerPriv.crypto.encryptRow(rowPrv);
1391 handlerPriv.database.saveRow(rowPrv);
1393 DB::Row rowPub(std::move(keys.second), namePublic, ownerLabelPub,
1394 static_cast<int>(policyPublic.extractable));
1395 handlerPub.crypto.encryptRow(rowPub);
1396 handlerPub.database.saveRow(rowPub);
1398 transactionPub.commit();
1399 transactionPriv.commit();
1400 return CKM_API_SUCCESS;
1403 RawBuffer CKMLogic::createKeyPair(
1404 const Credentials &cred,
1406 const CryptoAlgorithmSerializable &keyGenParams,
1407 const Name &namePrivate,
1408 const Label &labelPrivate,
1409 const Name &namePublic,
1410 const Label &labelPublic,
1411 const PolicySerializable &policyPrivate,
1412 const PolicySerializable &policyPublic)
1414 int retCode = CKM_API_SUCCESS;
1417 retCode = createKeyPairHelper(
1426 } catch (const Exc::Exception &e) {
1427 retCode = e.error();
1428 } catch (const CKM::Exception &e) {
1429 LogError("CKM::Exception: " << e.GetMessage());
1430 retCode = CKM_API_ERROR_SERVER_ERROR;
1433 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1434 commandId, retCode).Pop();
1437 RawBuffer CKMLogic::createKeyAES(
1438 const Credentials &cred,
1443 const PolicySerializable &policy)
1445 int retCode = CKM_API_SUCCESS;
1448 retCode = createKeyAESHelper(cred, size, name, label, policy);
1449 } catch (const Exc::Exception &e) {
1450 retCode = e.error();
1451 } catch (std::invalid_argument &e) {
1452 LogDebug("invalid argument error: " << e.what());
1453 retCode = CKM_API_ERROR_INPUT_PARAM;
1454 } catch (const CKM::Exception &e) {
1455 LogError("CKM::Exception: " << e.GetMessage());
1456 retCode = CKM_API_ERROR_SERVER_ERROR;
1459 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1460 commandId, retCode).Pop();
1463 int CKMLogic::readCertificateHelper(
1464 const Credentials &cred,
1465 const LabelNameVector &labelNameVector,
1466 CertificateImplVector &certVector)
1470 for (auto &i : labelNameVector) {
1471 // certificates can't be protected with custom user password
1472 Crypto::GObjUPtr obj;
1474 ec = readDataHelper(true,
1476 DataType::CERTIFICATE,
1482 if (ec != CKM_API_SUCCESS)
1485 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1487 // try to read chain certificates (if present)
1488 Crypto::GObjUPtrVector caChainObjs;
1489 ec = readDataHelper(true,
1491 DataType::DB_CHAIN_FIRST,
1497 if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1500 for (auto &caCertObj : caChainObjs)
1501 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1504 return CKM_API_SUCCESS;
1507 int CKMLogic::getCertificateChainHelper(
1508 const CertificateImpl &cert,
1509 const RawBufferVector &untrustedCertificates,
1510 const RawBufferVector &trustedCertificates,
1511 bool useTrustedSystemCertificates,
1512 RawBufferVector &chainRawVector)
1514 CertificateImplVector untrustedCertVector;
1515 CertificateImplVector trustedCertVector;
1516 CertificateImplVector chainVector;
1519 return CKM_API_ERROR_INPUT_PARAM;
1521 for (auto &e : untrustedCertificates) {
1522 CertificateImpl c(e, DataFormat::FORM_DER);
1525 return CKM_API_ERROR_INPUT_PARAM;
1527 untrustedCertVector.push_back(std::move(c));
1530 for (auto &e : trustedCertificates) {
1531 CertificateImpl c(e, DataFormat::FORM_DER);
1534 return CKM_API_ERROR_INPUT_PARAM;
1536 trustedCertVector.push_back(std::move(c));
1539 CertificateStore store;
1540 int retCode = store.verifyCertificate(cert,
1541 untrustedCertVector,
1543 useTrustedSystemCertificates,
1544 m_accessControl.isCCMode(),
1547 if (retCode != CKM_API_SUCCESS)
1550 for (auto &e : chainVector)
1551 chainRawVector.push_back(e.getDER());
1553 return CKM_API_SUCCESS;
1556 int CKMLogic::getCertificateChainHelper(
1557 const Credentials &cred,
1558 const CertificateImpl &cert,
1559 const LabelNameVector &untrusted,
1560 const LabelNameVector &trusted,
1561 bool useTrustedSystemCertificates,
1562 RawBufferVector &chainRawVector)
1564 CertificateImplVector untrustedCertVector;
1565 CertificateImplVector trustedCertVector;
1566 CertificateImplVector chainVector;
1570 return CKM_API_ERROR_INPUT_PARAM;
1572 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1574 if (retCode != CKM_API_SUCCESS)
1577 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1579 if (retCode != CKM_API_SUCCESS)
1582 CertificateStore store;
1583 retCode = store.verifyCertificate(cert,
1584 untrustedCertVector,
1586 useTrustedSystemCertificates,
1587 m_accessControl.isCCMode(),
1590 if (retCode != CKM_API_SUCCESS)
1593 for (auto &i : chainVector)
1594 chainRawVector.push_back(i.getDER());
1596 return CKM_API_SUCCESS;
1599 RawBuffer CKMLogic::getCertificateChain(
1600 const Credentials & /*cred*/,
1602 const RawBuffer &certificate,
1603 const RawBufferVector &untrustedCertificates,
1604 const RawBufferVector &trustedCertificates,
1605 bool useTrustedSystemCertificates)
1607 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1608 RawBufferVector chainRawVector;
1609 int retCode = CKM_API_ERROR_UNKNOWN;
1612 retCode = getCertificateChainHelper(cert,
1613 untrustedCertificates,
1614 trustedCertificates,
1615 useTrustedSystemCertificates,
1617 } catch (const Exc::Exception &e) {
1618 retCode = e.error();
1619 } catch (const std::exception &e) {
1620 LogError("STD exception " << e.what());
1621 retCode = CKM_API_ERROR_SERVER_ERROR;
1623 LogError("Unknown error.");
1626 auto response = MessageBuffer::Serialize(static_cast<int>
1627 (LogicCommand::GET_CHAIN_CERT),
1631 return response.Pop();
1634 RawBuffer CKMLogic::getCertificateChain(
1635 const Credentials &cred,
1637 const RawBuffer &certificate,
1638 const LabelNameVector &untrustedCertificates,
1639 const LabelNameVector &trustedCertificates,
1640 bool useTrustedSystemCertificates)
1642 int retCode = CKM_API_ERROR_UNKNOWN;
1643 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1644 RawBufferVector chainRawVector;
1647 retCode = getCertificateChainHelper(cred,
1649 untrustedCertificates,
1650 trustedCertificates,
1651 useTrustedSystemCertificates,
1653 } catch (const Exc::Exception &e) {
1654 retCode = e.error();
1655 } catch (const std::exception &e) {
1656 LogError("STD exception " << e.what());
1657 retCode = CKM_API_ERROR_SERVER_ERROR;
1659 LogError("Unknown error.");
1662 auto response = MessageBuffer::Serialize(static_cast<int>
1663 (LogicCommand::GET_CHAIN_ALIAS),
1667 return response.Pop();
1670 RawBuffer CKMLogic::createSignature(
1671 const Credentials &cred,
1673 const Name &privateKeyName,
1674 const Label &ownerLabel,
1675 const Password &password, // password for private_key
1676 const RawBuffer &message,
1677 const CryptoAlgorithm &cryptoAlg)
1680 RawBuffer signature;
1682 int retCode = CKM_API_SUCCESS;
1685 Crypto::GObjUPtr obj;
1686 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
1687 ownerLabel, password, obj);
1689 if (retCode == CKM_API_SUCCESS)
1690 signature = obj->sign(cryptoAlg, message);
1691 } catch (const Exc::Exception &e) {
1692 retCode = e.error();
1693 } catch (const CKM::Exception &e) {
1694 LogError("Unknown CKM::Exception: " << e.GetMessage());
1695 retCode = CKM_API_ERROR_SERVER_ERROR;
1696 } catch (const std::exception &e) {
1697 LogError("STD exception " << e.what());
1698 retCode = CKM_API_ERROR_SERVER_ERROR;
1701 auto response = MessageBuffer::Serialize(static_cast<int>
1702 (LogicCommand::CREATE_SIGNATURE),
1706 return response.Pop();
1709 RawBuffer CKMLogic::verifySignature(
1710 const Credentials &cred,
1712 const Name &publicKeyOrCertName,
1713 const Label &ownerLabel,
1714 const Password &password, // password for public_key (optional)
1715 const RawBuffer &message,
1716 const RawBuffer &signature,
1717 const CryptoAlgorithm ¶ms)
1719 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, ownerLabel, password, obj);
1731 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1732 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
1733 publicKeyOrCertName, ownerLabel, 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 Label &label, // who's the owner
1755 const Label &accessorLabel, // who will get the access
1756 const PermissionMask permissionMask)
1758 auto &handler = selectDatabase(cred, label);
1760 // we don't know the client
1761 if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1762 return CKM_API_ERROR_INPUT_PARAM;
1764 // use client label if not explicitly provided
1765 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1767 // verify name and label are correct
1768 if (!isNameValid(name) || !isLabelValid(ownerLabel) ||
1769 !isLabelValid(accessorLabel))
1770 return CKM_API_ERROR_INPUT_PARAM;
1772 // currently we don't support modification of owner's permissions to his own rows
1773 if (ownerLabel == accessorLabel)
1774 return CKM_API_ERROR_INPUT_PARAM;
1776 // system database does not support write/remove permissions
1777 if ((0 == ownerLabel.compare(OWNER_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, ownerLabel);
1784 if (retCode != CKM_API_SUCCESS)
1787 DB::Crypto::Transaction transaction(&handler.database);
1789 if (!handler.database.isNameLabelPresent(name, ownerLabel))
1790 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1792 // removing non-existing permissions: fail
1793 if (permissionMask == Permission::NONE) {
1794 if (!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1795 return CKM_API_ERROR_INPUT_PARAM;
1798 // set permissions to the row owned by ownerLabel for accessorLabel
1799 handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1800 transaction.commit();
1802 return CKM_API_SUCCESS;
1805 RawBuffer CKMLogic::setPermission(
1806 const Credentials &cred,
1811 const Label &accessorLabel,
1812 const PermissionMask permissionMask)
1817 retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1818 } catch (const Exc::Exception &e) {
1819 retCode = e.error();
1820 } catch (const CKM::Exception &e) {
1821 LogError("Error: " << e.GetMessage());
1822 retCode = CKM_API_ERROR_DB_ERROR;
1825 return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1828 int CKMLogic::loadAppKey(UserData &handle, const Label &appLabel)
1830 if (!handle.crypto.haveKey(appLabel)) {
1832 auto key_optional = handle.database.getKey(appLabel);
1834 if (!key_optional) {
1835 LogError("No key for given label in database");
1836 return CKM_API_ERROR_DB_ERROR;
1839 key = *key_optional;
1840 key = handle.keyProvider.getPureDEK(key);
1841 handle.crypto.pushKey(appLabel, key);
1844 return CKM_API_SUCCESS;