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;
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 int CKMLogic::unlockDatabase(uid_t user, const Password &password)
100 if (0 < m_userDataMap.count(user) &&
101 m_userDataMap[user].keyProvider.isInitialized())
102 return CKM_API_SUCCESS;
104 int retCode = CKM_API_SUCCESS;
107 auto &handle = m_userDataMap[user];
110 loadDKEKFile(user, password);
112 auto wrappedDatabaseDEK = fs.getDBDEK();
114 if (wrappedDatabaseDEK.empty()) {
115 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
116 fs.saveDBDEK(wrappedDatabaseDEK);
119 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
121 handle.database = DB::Crypto(fs.getDBPath(), key);
122 handle.crypto = CryptoLogic();
124 if (!m_accessControl.isSystemService(user)) {
125 // remove data of removed apps during locked state
126 AppLabelVector removedApps = fs.clearRemovedsApps();
128 for (auto &appSmackLabel : removedApps) {
129 handle.crypto.removeKey(appSmackLabel);
130 handle.database.deleteKey(appSmackLabel);
134 if (user == SYSTEM_DB_UID && hasMigratableData()) {
135 migrateData([this](const std::string &owner,
136 const std::string &name,
137 const Crypto::Data &data) {
138 LogInfo("Saver called with owner: " << owner << " name: " << name);
140 Credentials cred(0, OWNER_ID_SYSTEM);
142 int ret = this->verifyAndSaveDataHelper(
143 Credentials(0, OWNER_ID_SYSTEM), (owner + "-" + name),
144 OWNER_ID_SYSTEM, data, PolicySerializable());
145 if (ret != CKM_API_SUCCESS)
146 LogError("Failed to migrate secure-storage data. owner: " << owner <<
147 " name: " << name << " ret: " << ret);
150 } catch (const Exc::Exception &e) {
152 } catch (const CKM::Exception &e) {
153 LogError("CKM::Exception: " << e.GetMessage());
154 retCode = CKM_API_ERROR_SERVER_ERROR;
157 if (CKM_API_SUCCESS != retCode)
158 m_userDataMap.erase(user);
163 int CKMLogic::unlockSystemDB()
165 return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
168 UserData &CKMLogic::selectDatabase(const Credentials &cred,
169 const Label &incoming_label)
171 // if user trying to access system service - check:
172 // * if user database is unlocked [mandatory]
173 // * if not - proceed with regular user database
174 // * if explicit system database label given -> switch to system DB
175 if (!m_accessControl.isSystemService(cred)) {
176 if (0 == m_userDataMap.count(cred.clientUid))
177 ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
179 if (0 != incoming_label.compare(OWNER_ID_SYSTEM))
180 return m_userDataMap[cred.clientUid];
183 // system database selected, modify the label
184 if (CKM_API_SUCCESS != unlockSystemDB())
185 ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
187 return m_userDataMap[SYSTEM_DB_UID];
190 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
192 int retCode = CKM_API_SUCCESS;
194 if (!m_accessControl.isSystemService(user))
195 retCode = unlockDatabase(user, password);
196 else // do not allow lock/unlock operations for system users
197 retCode = CKM_API_ERROR_INPUT_PARAM;
199 return MessageBuffer::Serialize(retCode).Pop();
202 RawBuffer CKMLogic::updateCCMode()
204 m_accessControl.updateCCMode();
205 return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
208 RawBuffer CKMLogic::lockUserKey(uid_t user)
210 int retCode = CKM_API_SUCCESS;
212 if (!m_accessControl.isSystemService(user))
213 m_userDataMap.erase(user);
214 else // do not allow lock/unlock operations for system users
215 retCode = CKM_API_ERROR_INPUT_PARAM;
217 return MessageBuffer::Serialize(retCode).Pop();
220 RawBuffer CKMLogic::removeUserData(uid_t user)
222 int retCode = CKM_API_SUCCESS;
224 if (m_accessControl.isSystemService(user))
225 user = SYSTEM_DB_UID;
227 m_userDataMap.erase(user);
232 return MessageBuffer::Serialize(retCode).Pop();
235 int CKMLogic::changeUserPasswordHelper(uid_t user,
236 const Password &oldPassword,
237 const Password &newPassword)
239 // do not allow to change system database password
240 if (m_accessControl.isSystemService(user))
241 return CKM_API_ERROR_INPUT_PARAM;
243 loadDKEKFile(user, oldPassword);
244 saveDKEKFile(user, newPassword);
246 return CKM_API_SUCCESS;
249 RawBuffer CKMLogic::changeUserPassword(
251 const Password &oldPassword,
252 const Password &newPassword)
254 int retCode = CKM_API_SUCCESS;
257 retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
258 } catch (const Exc::Exception &e) {
260 } catch (const CKM::Exception &e) {
261 LogError("CKM::Exception: " << e.GetMessage());
262 retCode = CKM_API_ERROR_SERVER_ERROR;
265 return MessageBuffer::Serialize(retCode).Pop();
268 int CKMLogic::resetUserPasswordHelper(
270 const Password &newPassword)
272 // do not allow to reset system database password
273 if (m_accessControl.isSystemService(user))
274 return CKM_API_ERROR_INPUT_PARAM;
276 int retCode = CKM_API_SUCCESS;
278 if (0 == m_userDataMap.count(user)) {
279 // Check if key exists. If exists we must return error
281 auto wrappedDKEKMain = fs.getDKEK();
283 if (!wrappedDKEKMain.empty())
284 retCode = CKM_API_ERROR_BAD_REQUEST;
286 saveDKEKFile(user, newPassword);
292 RawBuffer CKMLogic::resetUserPassword(
294 const Password &newPassword)
296 int retCode = CKM_API_SUCCESS;
299 retCode = resetUserPasswordHelper(user, newPassword);
300 } catch (const Exc::Exception &e) {
302 } catch (const CKM::Exception &e) {
303 LogError("CKM::Exception: " << e.GetMessage());
304 retCode = CKM_API_ERROR_SERVER_ERROR;
307 return MessageBuffer::Serialize(retCode).Pop();
310 RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel)
312 int retCode = CKM_API_SUCCESS;
315 if (smackLabel.empty()) {
316 retCode = CKM_API_ERROR_INPUT_PARAM;
318 UidVector uids = FileSystem::getUIDsFromDBFile();
320 for (auto userId : uids) {
321 if (0 == m_userDataMap.count(userId)) {
322 FileSystem fs(userId);
323 fs.addRemovedApp(smackLabel);
325 auto &handle = m_userDataMap[userId];
326 handle.crypto.removeKey(smackLabel);
327 handle.database.deleteKey(smackLabel);
331 } catch (const Exc::Exception &e) {
333 } catch (const CKM::Exception &e) {
334 LogError("CKM::Exception: " << e.GetMessage());
335 retCode = CKM_API_ERROR_SERVER_ERROR;
338 return MessageBuffer::Serialize(retCode).Pop();
341 int CKMLogic::checkSaveConditions(
342 const Credentials &cred,
345 const Label &ownerLabel)
347 // verify name and label are correct
348 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
349 LogDebug("Invalid parameter passed to key-manager");
350 return CKM_API_ERROR_INPUT_PARAM;
353 // check if allowed to save using ownerLabel
354 int access_ec = m_accessControl.canSave(cred, ownerLabel);
356 if (access_ec != CKM_API_SUCCESS) {
357 LogDebug("label " << cred.smackLabel << " can not save rows using label " <<
362 // check if not a duplicate
363 if (handler.database.isNameLabelPresent(name, ownerLabel))
364 return CKM_API_ERROR_DB_ALIAS_EXISTS;
366 // encryption section
367 if (!handler.crypto.haveKey(ownerLabel)) {
369 auto key_optional = handler.database.getKey(ownerLabel);
372 LogDebug("No Key in database found. Generating new one for label: " <<
374 got_key = handler.keyProvider.generateDEK(ownerLabel);
375 handler.database.saveKey(ownerLabel, got_key);
377 LogDebug("Key from DB");
378 got_key = *key_optional;
381 got_key = handler.keyProvider.getPureDEK(got_key);
382 handler.crypto.pushKey(ownerLabel, got_key);
385 return CKM_API_SUCCESS;
388 DB::Row CKMLogic::createEncryptedRow(
392 const Crypto::Data &data,
393 const Policy &policy) const
395 Crypto::GStore &store = m_decider.getStore(data.type, policy.extractable);
397 // do not encrypt data with password during cc_mode on
398 Token token = store.import(data,
399 m_accessControl.isCCMode() ? "" : policy.password);
400 DB::Row row(std::move(token), name, label,
401 static_cast<int>(policy.extractable));
402 crypto.encryptRow(row);
406 int CKMLogic::verifyBinaryData(Crypto::Data &input) const
409 return toBinaryData(input, dummy);
412 int CKMLogic::toBinaryData(const Crypto::Data &input,
413 Crypto::Data &output) const
415 // verify the data integrity
416 if (input.type.isKey()) {
419 if (input.type.isSKey())
420 output_key = CKM::Key::createAES(input.data);
422 output_key = CKM::Key::create(input.data);
424 if (output_key.get() == NULL) {
425 LogDebug("provided binary data is not valid key data");
426 return CKM_API_ERROR_INPUT_PARAM;
429 output = std::move(Crypto::Data(input.type, output_key->getDER()));
430 } else if (input.type.isCertificate() || input.type.isChainCert()) {
431 CertificateShPtr cert = CKM::Certificate::create(input.data,
432 DataFormat::FORM_DER);
434 if (cert.get() == NULL) {
435 LogDebug("provided binary data is not valid certificate data");
436 return CKM_API_ERROR_INPUT_PARAM;
439 output = std::move(Crypto::Data(input.type, cert->getDER()));
444 // TODO: add here BINARY_DATA verification, i.e: max size etc.
445 return CKM_API_SUCCESS;
448 int CKMLogic::verifyAndSaveDataHelper(
449 const Credentials &cred,
452 const Crypto::Data &data,
453 const PolicySerializable &policy)
455 int retCode = CKM_API_ERROR_UNKNOWN;
458 // check if data is correct
459 Crypto::Data binaryData;
460 retCode = toBinaryData(data, binaryData);
462 if (retCode != CKM_API_SUCCESS)
465 return saveDataHelper(cred, name, label, binaryData, policy);
466 } catch (const Exc::Exception &e) {
468 } catch (const CKM::Exception &e) {
469 LogError("CKM::Exception: " << e.GetMessage());
470 return CKM_API_ERROR_SERVER_ERROR;
474 int CKMLogic::getKeyForService(
475 const Credentials &cred,
478 const Password &pass,
479 Crypto::GObjShPtr &key)
484 // Key is for internal service use. It won't be exported to the client
485 Crypto::GObjUPtr obj;
486 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label,
489 if (retCode == CKM_API_SUCCESS)
490 key = std::move(obj);
493 } catch (const Exc::Exception &e) {
495 } catch (const CKM::Exception &e) {
496 LogError("CKM::Exception: " << e.GetMessage());
497 return CKM_API_ERROR_SERVER_ERROR;
501 RawBuffer CKMLogic::saveData(
502 const Credentials &cred,
506 const Crypto::Data &data,
507 const PolicySerializable &policy)
509 int retCode = verifyAndSaveDataHelper(cred, name, label, data, policy);
510 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
513 static_cast<int>(data.type));
514 return response.Pop();
517 int CKMLogic::extractPKCS12Data(
520 const Label &ownerLabel,
521 const PKCS12Serializable &pkcs,
522 const PolicySerializable &keyPolicy,
523 const PolicySerializable &certPolicy,
524 DB::RowVector &output) const
526 // private key is mandatory
527 auto key = pkcs.getKey();
530 LogError("Failed to get private key from pkcs");
531 return CKM_API_ERROR_INVALID_FORMAT;
534 Crypto::Data keyData(DataType(key->getType()), key->getDER());
535 int retCode = verifyBinaryData(keyData);
537 if (retCode != CKM_API_SUCCESS)
540 output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyData,
543 // certificate is mandatory
544 auto cert = pkcs.getCertificate();
547 LogError("Failed to get certificate from pkcs");
548 return CKM_API_ERROR_INVALID_FORMAT;
551 Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
552 retCode = verifyBinaryData(certData);
554 if (retCode != CKM_API_SUCCESS)
557 output.push_back(createEncryptedRow(crypto, name, ownerLabel, certData,
561 unsigned int cert_index = 0;
563 for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
564 Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++),
566 int retCode = verifyBinaryData(caCertData);
568 if (retCode != CKM_API_SUCCESS)
571 output.push_back(createEncryptedRow(crypto, name, ownerLabel, caCertData,
575 return CKM_API_SUCCESS;
578 RawBuffer CKMLogic::savePKCS12(
579 const Credentials &cred,
583 const PKCS12Serializable &pkcs,
584 const PolicySerializable &keyPolicy,
585 const PolicySerializable &certPolicy)
587 int retCode = CKM_API_ERROR_UNKNOWN;
590 retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
591 } catch (const Exc::Exception &e) {
593 } catch (const CKM::Exception &e) {
594 LogError("CKM::Exception: " << e.GetMessage());
595 retCode = CKM_API_ERROR_SERVER_ERROR;
598 auto response = MessageBuffer::Serialize(static_cast<int>
599 (LogicCommand::SAVE_PKCS12),
602 return response.Pop();
606 int CKMLogic::removeDataHelper(
607 const Credentials &cred,
611 auto &handler = selectDatabase(cred, label);
613 // use client label if not explicitly provided
614 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
616 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
617 LogDebug("Invalid label or name format");
618 return CKM_API_ERROR_INPUT_PARAM;
621 DB::Crypto::Transaction transaction(&handler.database);
623 // read and check permissions
624 PermissionMaskOptional permissionRowOpt =
625 handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel);
626 int retCode = m_accessControl.canDelete(cred,
627 PermissionForLabel(cred.smackLabel, permissionRowOpt));
629 if (retCode != CKM_API_SUCCESS) {
630 LogWarning("access control check result: " << retCode);
634 // get all matching rows
636 handler.database.getRows(name, ownerLabel, DataType::DB_FIRST,
637 DataType::DB_LAST, rows);
640 LogDebug("No row for given name and label");
641 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
644 // load app key if needed
645 retCode = loadAppKey(handler, rows.front().ownerLabel);
647 if (CKM_API_SUCCESS != retCode)
650 // destroy it in store
651 for (auto &r : rows) {
653 handler.crypto.decryptRow(Password(), r);
654 m_decider.getStore(r).destroy(r);
655 } catch (const Exc::AuthenticationFailed &) {
656 LogDebug("Authentication failed when removing data. Ignored.");
661 handler.database.deleteRow(name, ownerLabel);
662 transaction.commit();
664 return CKM_API_SUCCESS;
667 RawBuffer CKMLogic::removeData(
668 const Credentials &cred,
673 int retCode = CKM_API_ERROR_UNKNOWN;
676 retCode = removeDataHelper(cred, name, label);
677 } catch (const Exc::Exception &e) {
679 } catch (const CKM::Exception &e) {
680 LogError("Error: " << e.GetMessage());
681 retCode = CKM_API_ERROR_DB_ERROR;
684 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
687 return response.Pop();
690 int CKMLogic::readSingleRow(const Name &name,
691 const Label &ownerLabel,
693 DB::Crypto &database,
696 DB::Crypto::RowOptional row_optional;
698 if (dataType.isKey()) {
699 // read all key types
700 row_optional = database.getRow(name,
702 DataType::DB_KEY_FIRST,
703 DataType::DB_KEY_LAST);
705 // read anything else
706 row_optional = database.getRow(name,
712 LogDebug("No row for given name, label and type");
713 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
718 return CKM_API_SUCCESS;
722 int CKMLogic::readMultiRow(const Name &name,
723 const Label &ownerLabel,
725 DB::Crypto &database,
726 DB::RowVector &output)
728 if (dataType.isKey())
729 // read all key types
730 database.getRows(name,
732 DataType::DB_KEY_FIRST,
733 DataType::DB_KEY_LAST,
735 else if (dataType.isChainCert())
736 // read all key types
737 database.getRows(name,
739 DataType::DB_CHAIN_FIRST,
740 DataType::DB_CHAIN_LAST,
743 // read anything else
744 database.getRows(name,
749 if (!output.size()) {
750 LogDebug("No row for given name, label and type");
751 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
754 return CKM_API_SUCCESS;
757 int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
759 const Label &ownerLabel,
760 const Label &accessorLabel,
763 DB::Crypto &database)
765 PermissionMaskOptional permissionRowOpt =
766 database.getPermissionRow(name, ownerLabel, accessorLabel);
769 return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel,
772 return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel,
776 Crypto::GObjUPtr CKMLogic::rowToObject(
779 const Password &password)
781 Crypto::GStore &store = m_decider.getStore(row);
783 Password pass = m_accessControl.isCCMode() ? "" : password;
786 Crypto::GObjUPtr obj;
788 if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
789 CryptoLogic::ENCRYPTION_V2) {
790 handler.crypto.decryptRow(Password(), row);
792 obj = store.getObject(row, pass);
794 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
795 handler.crypto.decryptRow(pass, row);
796 // destroy it in store
799 // import it to store with new scheme: data -> pass(data)
800 Token token = store.import(Crypto::Data(row.dataType, row.data), pass);
802 // get it from the store (it can be different than the data we imported into store)
803 obj = store.getObject(token, pass);
805 // update row with new token
806 *static_cast<Token *>(&row) = std::move(token);
808 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
809 handler.crypto.encryptRow(row);
812 handler.database.updateRow(row);
818 int CKMLogic::readDataHelper(
820 const Credentials &cred,
824 const Password &password,
825 Crypto::GObjUPtrVector &objs)
827 auto &handler = selectDatabase(cred, label);
829 // use client label if not explicitly provided
830 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
832 if (!isNameValid(name) || !isLabelValid(ownerLabel))
833 return CKM_API_ERROR_INPUT_PARAM;
836 DB::Crypto::Transaction transaction(&handler.database);
838 int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
840 if (CKM_API_SUCCESS != retCode)
843 // all read rows belong to the same owner
844 DB::Row &firstRow = rows.at(0);
846 // check access rights
847 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel,
848 firstRow, exportFlag, handler.database);
850 if (CKM_API_SUCCESS != retCode)
853 // load app key if needed
854 retCode = loadAppKey(handler, firstRow.ownerLabel);
856 if (CKM_API_SUCCESS != retCode)
860 for (auto &row : rows)
861 objs.push_back(rowToObject(handler, std::move(row), password));
863 // rowToObject may modify db
864 transaction.commit();
866 return CKM_API_SUCCESS;
869 int CKMLogic::readDataHelper(
871 const Credentials &cred,
875 const Password &password,
876 Crypto::GObjUPtr &obj)
878 DataType objDataType;
879 return readDataHelper(exportFlag, cred, dataType, name, label, password, obj,
883 int CKMLogic::readDataHelper(
885 const Credentials &cred,
889 const Password &password,
890 Crypto::GObjUPtr &obj,
891 DataType &objDataType)
893 auto &handler = selectDatabase(cred, label);
895 // use client label if not explicitly provided
896 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
898 if (!isNameValid(name) || !isLabelValid(ownerLabel))
899 return CKM_API_ERROR_INPUT_PARAM;
902 DB::Crypto::Transaction transaction(&handler.database);
904 int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
906 if (CKM_API_SUCCESS != retCode)
909 objDataType = row.dataType;
911 // check access rights
912 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel,
913 row, exportFlag, handler.database);
915 if (CKM_API_SUCCESS != retCode)
918 // load app key if needed
919 retCode = loadAppKey(handler, row.ownerLabel);
921 if (CKM_API_SUCCESS != retCode)
924 obj = rowToObject(handler, std::move(row), password);
925 // rowToObject may modify db
926 transaction.commit();
928 return CKM_API_SUCCESS;
931 RawBuffer CKMLogic::getData(
932 const Credentials &cred,
937 const Password &password)
939 int retCode = CKM_API_SUCCESS;
941 DataType objDataType;
944 Crypto::GObjUPtr obj;
945 retCode = readDataHelper(true, cred, dataType, name, label, password, obj,
948 if (retCode == CKM_API_SUCCESS)
949 row.data = std::move(obj->getBinary());
950 } catch (const Exc::Exception &e) {
952 } catch (const CKM::Exception &e) {
953 LogError("CKM::Exception: " << e.GetMessage());
954 retCode = CKM_API_ERROR_SERVER_ERROR;
957 if (CKM_API_SUCCESS != retCode) {
959 row.dataType = dataType;
962 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
965 static_cast<int>(objDataType),
967 return response.Pop();
970 int CKMLogic::getPKCS12Helper(
971 const Credentials &cred,
974 const Password &keyPassword,
975 const Password &certPassword,
977 CertificateShPtr &cert,
978 CertificateShPtrVector &caChain)
982 // read private key (mandatory)
983 Crypto::GObjUPtr keyObj;
984 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label,
985 keyPassword, keyObj);
987 if (retCode != CKM_API_SUCCESS)
990 privKey = CKM::Key::create(keyObj->getBinary());
992 // read certificate (mandatory)
993 Crypto::GObjUPtr certObj;
994 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label,
995 certPassword, certObj);
997 if (retCode != CKM_API_SUCCESS)
1000 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
1002 // read CA cert chain (optional)
1003 Crypto::GObjUPtrVector caChainObjs;
1004 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label,
1005 certPassword, caChainObjs);
1007 if (retCode != CKM_API_SUCCESS &&
1008 retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1011 for (auto &caCertObj : caChainObjs)
1012 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
1013 DataFormat::FORM_DER));
1015 // if anything found, return it
1016 if (privKey || cert || caChain.size() > 0)
1017 retCode = CKM_API_SUCCESS;
1022 RawBuffer CKMLogic::getPKCS12(
1023 const Credentials &cred,
1027 const Password &keyPassword,
1028 const Password &certPassword)
1030 int retCode = CKM_API_ERROR_UNKNOWN;
1032 PKCS12Serializable output;
1036 CertificateShPtr cert;
1037 CertificateShPtrVector caChain;
1038 retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey,
1042 if (retCode == CKM_API_SUCCESS)
1043 output = PKCS12Serializable(std::move(privKey), std::move(cert),
1044 std::move(caChain));
1045 } catch (const Exc::Exception &e) {
1046 retCode = e.error();
1047 } catch (const CKM::Exception &e) {
1048 LogError("CKM::Exception: " << e.GetMessage());
1049 retCode = CKM_API_ERROR_SERVER_ERROR;
1052 auto response = MessageBuffer::Serialize(static_cast<int>
1053 (LogicCommand::GET_PKCS12),
1057 return response.Pop();
1060 int CKMLogic::getDataListHelper(const Credentials &cred,
1061 const DataType dataType,
1062 LabelNameVector &labelNameVector)
1064 int retCode = CKM_API_ERROR_DB_LOCKED;
1066 if (0 < m_userDataMap.count(cred.clientUid)) {
1067 auto &database = m_userDataMap[cred.clientUid].database;
1070 LabelNameVector tmpVector;
1072 if (dataType.isKey()) {
1073 // list all key types
1074 database.listNames(cred.smackLabel,
1076 DataType::DB_KEY_FIRST,
1077 DataType::DB_KEY_LAST);
1079 // list anything else
1080 database.listNames(cred.smackLabel,
1085 labelNameVector.insert(labelNameVector.end(), tmpVector.begin(),
1087 retCode = CKM_API_SUCCESS;
1088 } catch (const CKM::Exception &e) {
1089 LogError("Error: " << e.GetMessage());
1090 retCode = CKM_API_ERROR_DB_ERROR;
1091 } catch (const Exc::Exception &e) {
1092 retCode = e.error();
1099 RawBuffer CKMLogic::getDataList(
1100 const Credentials &cred,
1104 LabelNameVector systemVector;
1105 LabelNameVector userVector;
1106 LabelNameVector labelNameVector;
1108 int retCode = unlockSystemDB();
1110 if (CKM_API_SUCCESS == retCode) {
1112 if (m_accessControl.isSystemService(cred)) {
1114 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1119 // user - lookup system, then client DB
1120 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1126 if (retCode == CKM_API_SUCCESS) {
1127 retCode = getDataListHelper(cred,
1134 if (retCode == CKM_API_SUCCESS) {
1135 labelNameVector.insert(labelNameVector.end(), systemVector.begin(),
1136 systemVector.end());
1137 labelNameVector.insert(labelNameVector.end(), userVector.begin(),
1141 auto response = MessageBuffer::Serialize(static_cast<int>
1142 (LogicCommand::GET_LIST),
1145 static_cast<int>(dataType),
1147 return response.Pop();
1150 int CKMLogic::importInitialData(
1152 const Crypto::Data &data,
1153 const Crypto::DataEncryption &enc,
1154 const Policy &policy)
1157 // Inital values are always imported with root credentials. Label is not important.
1158 Credentials rootCred(0, "");
1160 auto &handler = selectDatabase(rootCred, OWNER_ID_SYSTEM);
1162 // check if save is possible
1163 DB::Crypto::Transaction transaction(&handler.database);
1164 int retCode = checkSaveConditions(rootCred, handler, name, OWNER_ID_SYSTEM);
1166 if (retCode != CKM_API_SUCCESS)
1169 Crypto::GStore &store =
1170 m_decider.getStore(data.type, policy.extractable, !enc.encryptedKey.empty());
1174 if (enc.encryptedKey.empty()) {
1175 Crypto::Data binaryData;
1177 if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1180 token = store.import(binaryData,
1181 m_accessControl.isCCMode() ? "" : policy.password);
1183 token = store.importEncrypted(data,
1184 m_accessControl.isCCMode() ? "" : policy.password, enc);
1187 DB::Row row(std::move(token), name, OWNER_ID_SYSTEM,
1188 static_cast<int>(policy.extractable));
1189 handler.crypto.encryptRow(row);
1191 handler.database.saveRow(row);
1192 transaction.commit();
1193 } catch (const Exc::Exception &e) {
1195 } catch (const CKM::Exception &e) {
1196 LogError("CKM::Exception: " << e.GetMessage());
1197 return CKM_API_ERROR_SERVER_ERROR;
1198 } catch (const std::exception &e) {
1199 LogError("Std::exception: " << e.what());
1200 return CKM_API_ERROR_SERVER_ERROR;
1203 return CKM_API_SUCCESS;
1206 int CKMLogic::saveDataHelper(
1207 const Credentials &cred,
1210 const Crypto::Data &data,
1211 const PolicySerializable &policy)
1213 auto &handler = selectDatabase(cred, label);
1215 // use client label if not explicitly provided
1216 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1218 if (m_accessControl.isSystemService(cred) &&
1219 ownerLabel.compare(OWNER_ID_SYSTEM) != 0)
1220 return CKM_API_ERROR_INPUT_PARAM;
1222 // check if save is possible
1223 DB::Crypto::Transaction transaction(&handler.database);
1224 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1226 if (retCode != CKM_API_SUCCESS)
1230 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel,
1232 handler.database.saveRow(encryptedRow);
1234 transaction.commit();
1235 return CKM_API_SUCCESS;
1238 int CKMLogic::saveDataHelper(
1239 const Credentials &cred,
1242 const PKCS12Serializable &pkcs,
1243 const PolicySerializable &keyPolicy,
1244 const PolicySerializable &certPolicy)
1246 auto &handler = selectDatabase(cred, label);
1248 // use client label if not explicitly provided
1249 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1251 if (m_accessControl.isSystemService(cred) &&
1252 ownerLabel.compare(OWNER_ID_SYSTEM) != 0)
1253 return CKM_API_ERROR_INPUT_PARAM;
1255 // check if save is possible
1256 DB::Crypto::Transaction transaction(&handler.database);
1257 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1259 if (retCode != CKM_API_SUCCESS)
1262 // extract and encrypt the data
1263 DB::RowVector encryptedRows;
1264 retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy,
1265 certPolicy, encryptedRows);
1267 if (retCode != CKM_API_SUCCESS)
1271 handler.database.saveRows(name, ownerLabel, encryptedRows);
1272 transaction.commit();
1274 return CKM_API_SUCCESS;
1278 int CKMLogic::createKeyAESHelper(
1279 const Credentials &cred,
1283 const PolicySerializable &policy)
1285 auto &handler = selectDatabase(cred, label);
1287 // use client label if not explicitly provided
1288 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1290 if (m_accessControl.isSystemService(cred) &&
1291 ownerLabel.compare(OWNER_ID_SYSTEM) != 0)
1292 return CKM_API_ERROR_INPUT_PARAM;
1294 // check if save is possible
1295 DB::Crypto::Transaction transaction(&handler.database);
1296 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1298 if (retCode != CKM_API_SUCCESS)
1301 // create key in store
1302 CryptoAlgorithm keyGenAlgorithm;
1303 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1304 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1305 Token key = m_decider.getStore(DataType::KEY_AES,
1306 policy.extractable).generateSKey(keyGenAlgorithm, policy.password);
1309 DB::Row row(std::move(key), name, ownerLabel,
1310 static_cast<int>(policy.extractable));
1311 handler.crypto.encryptRow(row);
1313 handler.database.saveRow(row);
1315 transaction.commit();
1316 return CKM_API_SUCCESS;
1319 int CKMLogic::createKeyPairHelper(
1320 const Credentials &cred,
1321 const CryptoAlgorithmSerializable &keyGenParams,
1322 const Name &namePrivate,
1323 const Label &labelPrivate,
1324 const Name &namePublic,
1325 const Label &labelPublic,
1326 const PolicySerializable &policyPrivate,
1327 const PolicySerializable &policyPublic)
1329 auto &handlerPriv = selectDatabase(cred, labelPrivate);
1330 auto &handlerPub = selectDatabase(cred, labelPublic);
1332 AlgoType keyType = AlgoType::RSA_GEN;
1334 if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1335 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1337 DataType dt(keyType);
1340 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1342 // use client label if not explicitly provided
1343 const Label &ownerLabelPrv = labelPrivate.empty() ? cred.smackLabel :
1346 if (m_accessControl.isSystemService(cred) &&
1347 ownerLabelPrv.compare(OWNER_ID_SYSTEM) != 0)
1348 return CKM_API_ERROR_INPUT_PARAM;
1350 const Label &ownerLabelPub = labelPublic.empty() ? cred.smackLabel :
1353 if (m_accessControl.isSystemService(cred) &&
1354 ownerLabelPub.compare(OWNER_ID_SYSTEM) != 0)
1355 return CKM_API_ERROR_INPUT_PARAM;
1357 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1358 TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams,
1359 policyPrivate.password,
1360 policyPublic.password);
1362 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1363 // in case the same database is used for private and public - the second
1364 // transaction will not be executed
1365 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1368 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerLabelPrv);
1370 if (CKM_API_SUCCESS != retCode)
1373 retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerLabelPub);
1375 if (CKM_API_SUCCESS != retCode)
1379 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerLabelPrv,
1380 static_cast<int>(policyPrivate.extractable));
1381 handlerPriv.crypto.encryptRow(rowPrv);
1382 handlerPriv.database.saveRow(rowPrv);
1384 DB::Row rowPub(std::move(keys.second), namePublic, ownerLabelPub,
1385 static_cast<int>(policyPublic.extractable));
1386 handlerPub.crypto.encryptRow(rowPub);
1387 handlerPub.database.saveRow(rowPub);
1389 transactionPub.commit();
1390 transactionPriv.commit();
1391 return CKM_API_SUCCESS;
1394 RawBuffer CKMLogic::createKeyPair(
1395 const Credentials &cred,
1397 const CryptoAlgorithmSerializable &keyGenParams,
1398 const Name &namePrivate,
1399 const Label &labelPrivate,
1400 const Name &namePublic,
1401 const Label &labelPublic,
1402 const PolicySerializable &policyPrivate,
1403 const PolicySerializable &policyPublic)
1405 int retCode = CKM_API_SUCCESS;
1408 retCode = createKeyPairHelper(
1417 } catch (const Exc::Exception &e) {
1418 retCode = e.error();
1419 } catch (const CKM::Exception &e) {
1420 LogError("CKM::Exception: " << e.GetMessage());
1421 retCode = CKM_API_ERROR_SERVER_ERROR;
1424 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1425 commandId, retCode).Pop();
1428 RawBuffer CKMLogic::createKeyAES(
1429 const Credentials &cred,
1434 const PolicySerializable &policy)
1436 int retCode = CKM_API_SUCCESS;
1439 retCode = createKeyAESHelper(cred, size, name, label, policy);
1440 } catch (const Exc::Exception &e) {
1441 retCode = e.error();
1442 } catch (std::invalid_argument &e) {
1443 LogDebug("invalid argument error: " << e.what());
1444 retCode = CKM_API_ERROR_INPUT_PARAM;
1445 } catch (const CKM::Exception &e) {
1446 LogError("CKM::Exception: " << e.GetMessage());
1447 retCode = CKM_API_ERROR_SERVER_ERROR;
1450 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1451 commandId, retCode).Pop();
1454 int CKMLogic::readCertificateHelper(
1455 const Credentials &cred,
1456 const LabelNameVector &labelNameVector,
1457 CertificateImplVector &certVector)
1461 for (auto &i : labelNameVector) {
1462 // certificates can't be protected with custom user password
1463 Crypto::GObjUPtr obj;
1465 ec = readDataHelper(true,
1467 DataType::CERTIFICATE,
1473 if (ec != CKM_API_SUCCESS)
1476 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1478 // try to read chain certificates (if present)
1479 Crypto::GObjUPtrVector caChainObjs;
1480 ec = readDataHelper(true,
1482 DataType::DB_CHAIN_FIRST,
1488 if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1491 for (auto &caCertObj : caChainObjs)
1492 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1495 return CKM_API_SUCCESS;
1498 int CKMLogic::getCertificateChainHelper(
1499 const CertificateImpl &cert,
1500 const RawBufferVector &untrustedCertificates,
1501 const RawBufferVector &trustedCertificates,
1502 bool useTrustedSystemCertificates,
1503 RawBufferVector &chainRawVector)
1505 CertificateImplVector untrustedCertVector;
1506 CertificateImplVector trustedCertVector;
1507 CertificateImplVector chainVector;
1510 return CKM_API_ERROR_INPUT_PARAM;
1512 for (auto &e : untrustedCertificates) {
1513 CertificateImpl c(e, DataFormat::FORM_DER);
1516 return CKM_API_ERROR_INPUT_PARAM;
1518 untrustedCertVector.push_back(std::move(c));
1521 for (auto &e : trustedCertificates) {
1522 CertificateImpl c(e, DataFormat::FORM_DER);
1525 return CKM_API_ERROR_INPUT_PARAM;
1527 trustedCertVector.push_back(std::move(c));
1530 CertificateStore store;
1531 int retCode = store.verifyCertificate(cert,
1532 untrustedCertVector,
1534 useTrustedSystemCertificates,
1535 m_accessControl.isCCMode(),
1538 if (retCode != CKM_API_SUCCESS)
1541 for (auto &e : chainVector)
1542 chainRawVector.push_back(e.getDER());
1544 return CKM_API_SUCCESS;
1547 int CKMLogic::getCertificateChainHelper(
1548 const Credentials &cred,
1549 const CertificateImpl &cert,
1550 const LabelNameVector &untrusted,
1551 const LabelNameVector &trusted,
1552 bool useTrustedSystemCertificates,
1553 RawBufferVector &chainRawVector)
1555 CertificateImplVector untrustedCertVector;
1556 CertificateImplVector trustedCertVector;
1557 CertificateImplVector chainVector;
1561 return CKM_API_ERROR_INPUT_PARAM;
1563 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1565 if (retCode != CKM_API_SUCCESS)
1568 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1570 if (retCode != CKM_API_SUCCESS)
1573 CertificateStore store;
1574 retCode = store.verifyCertificate(cert,
1575 untrustedCertVector,
1577 useTrustedSystemCertificates,
1578 m_accessControl.isCCMode(),
1581 if (retCode != CKM_API_SUCCESS)
1584 for (auto &i : chainVector)
1585 chainRawVector.push_back(i.getDER());
1587 return CKM_API_SUCCESS;
1590 RawBuffer CKMLogic::getCertificateChain(
1591 const Credentials & /*cred*/,
1593 const RawBuffer &certificate,
1594 const RawBufferVector &untrustedCertificates,
1595 const RawBufferVector &trustedCertificates,
1596 bool useTrustedSystemCertificates)
1598 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1599 RawBufferVector chainRawVector;
1600 int retCode = CKM_API_ERROR_UNKNOWN;
1603 retCode = getCertificateChainHelper(cert,
1604 untrustedCertificates,
1605 trustedCertificates,
1606 useTrustedSystemCertificates,
1608 } catch (const Exc::Exception &e) {
1609 retCode = e.error();
1610 } catch (const std::exception &e) {
1611 LogError("STD exception " << e.what());
1612 retCode = CKM_API_ERROR_SERVER_ERROR;
1614 LogError("Unknown error.");
1617 auto response = MessageBuffer::Serialize(static_cast<int>
1618 (LogicCommand::GET_CHAIN_CERT),
1622 return response.Pop();
1625 RawBuffer CKMLogic::getCertificateChain(
1626 const Credentials &cred,
1628 const RawBuffer &certificate,
1629 const LabelNameVector &untrustedCertificates,
1630 const LabelNameVector &trustedCertificates,
1631 bool useTrustedSystemCertificates)
1633 int retCode = CKM_API_ERROR_UNKNOWN;
1634 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1635 RawBufferVector chainRawVector;
1638 retCode = getCertificateChainHelper(cred,
1640 untrustedCertificates,
1641 trustedCertificates,
1642 useTrustedSystemCertificates,
1644 } catch (const Exc::Exception &e) {
1645 retCode = e.error();
1646 } catch (const std::exception &e) {
1647 LogError("STD exception " << e.what());
1648 retCode = CKM_API_ERROR_SERVER_ERROR;
1650 LogError("Unknown error.");
1653 auto response = MessageBuffer::Serialize(static_cast<int>
1654 (LogicCommand::GET_CHAIN_ALIAS),
1658 return response.Pop();
1661 RawBuffer CKMLogic::createSignature(
1662 const Credentials &cred,
1664 const Name &privateKeyName,
1665 const Label &ownerLabel,
1666 const Password &password, // password for private_key
1667 const RawBuffer &message,
1668 const CryptoAlgorithm &cryptoAlg)
1671 RawBuffer signature;
1673 int retCode = CKM_API_SUCCESS;
1676 Crypto::GObjUPtr obj;
1677 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
1678 ownerLabel, password, obj);
1680 if (retCode == CKM_API_SUCCESS)
1681 signature = obj->sign(cryptoAlg, message);
1682 } catch (const Exc::Exception &e) {
1683 retCode = e.error();
1684 } catch (const CKM::Exception &e) {
1685 LogError("Unknown CKM::Exception: " << e.GetMessage());
1686 retCode = CKM_API_ERROR_SERVER_ERROR;
1687 } catch (const std::exception &e) {
1688 LogError("STD exception " << e.what());
1689 retCode = CKM_API_ERROR_SERVER_ERROR;
1692 auto response = MessageBuffer::Serialize(static_cast<int>
1693 (LogicCommand::CREATE_SIGNATURE),
1697 return response.Pop();
1700 RawBuffer CKMLogic::verifySignature(
1701 const Credentials &cred,
1703 const Name &publicKeyOrCertName,
1704 const Label &ownerLabel,
1705 const Password &password, // password for public_key (optional)
1706 const RawBuffer &message,
1707 const RawBuffer &signature,
1708 const CryptoAlgorithm ¶ms)
1710 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1715 // try certificate first - looking for a public key.
1716 // in case of PKCS, pub key from certificate will be found first
1717 // rather than private key from the same PKCS.
1718 Crypto::GObjUPtr obj;
1719 retCode = readDataHelper(false, cred, DataType::CERTIFICATE,
1720 publicKeyOrCertName, ownerLabel, password, obj);
1722 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1723 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
1724 publicKeyOrCertName, ownerLabel, password, obj);
1726 if (retCode == CKM_API_SUCCESS)
1727 retCode = obj->verify(params, message, signature);
1728 } catch (const Exc::Exception &e) {
1729 retCode = e.error();
1730 } catch (const CKM::Exception &e) {
1731 LogError("Unknown CKM::Exception: " << e.GetMessage());
1732 retCode = CKM_API_ERROR_SERVER_ERROR;
1735 auto response = MessageBuffer::Serialize(static_cast<int>
1736 (LogicCommand::VERIFY_SIGNATURE),
1739 return response.Pop();
1742 int CKMLogic::setPermissionHelper(
1743 const Credentials &cred, // who's the client
1745 const Label &label, // who's the owner
1746 const Label &accessorLabel, // who will get the access
1747 const PermissionMask permissionMask)
1749 auto &handler = selectDatabase(cred, label);
1751 // we don't know the client
1752 if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1753 return CKM_API_ERROR_INPUT_PARAM;
1755 // use client label if not explicitly provided
1756 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1758 // verify name and label are correct
1759 if (!isNameValid(name) || !isLabelValid(ownerLabel) ||
1760 !isLabelValid(accessorLabel))
1761 return CKM_API_ERROR_INPUT_PARAM;
1763 // currently we don't support modification of owner's permissions to his own rows
1764 if (ownerLabel == accessorLabel)
1765 return CKM_API_ERROR_INPUT_PARAM;
1767 // system database does not support write/remove permissions
1768 if ((0 == ownerLabel.compare(OWNER_ID_SYSTEM)) &&
1769 (permissionMask & Permission::REMOVE))
1770 return CKM_API_ERROR_INPUT_PARAM;
1772 // can the client modify permissions to owner's row?
1773 int retCode = m_accessControl.canModify(cred, ownerLabel);
1775 if (retCode != CKM_API_SUCCESS)
1778 DB::Crypto::Transaction transaction(&handler.database);
1780 if (!handler.database.isNameLabelPresent(name, ownerLabel))
1781 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1783 // removing non-existing permissions: fail
1784 if (permissionMask == Permission::NONE) {
1785 if (!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1786 return CKM_API_ERROR_INPUT_PARAM;
1789 // set permissions to the row owned by ownerLabel for accessorLabel
1790 handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1791 transaction.commit();
1793 return CKM_API_SUCCESS;
1796 RawBuffer CKMLogic::setPermission(
1797 const Credentials &cred,
1802 const Label &accessorLabel,
1803 const PermissionMask permissionMask)
1808 retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1809 } catch (const Exc::Exception &e) {
1810 retCode = e.error();
1811 } catch (const CKM::Exception &e) {
1812 LogError("Error: " << e.GetMessage());
1813 retCode = CKM_API_ERROR_DB_ERROR;
1816 return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1819 int CKMLogic::loadAppKey(UserData &handle, const Label &appLabel)
1821 if (!handle.crypto.haveKey(appLabel)) {
1823 auto key_optional = handle.database.getKey(appLabel);
1825 if (!key_optional) {
1826 LogError("No key for given label in database");
1827 return CKM_API_ERROR_DB_ERROR;
1830 key = *key_optional;
1831 key = handle.keyProvider.getPureDEK(key);
1832 handle.crypto.pushKey(appLabel, key);
1835 return CKM_API_SUCCESS;