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>
38 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
39 const char * const SYSTEM_DB_PASSWD = "cAtRugU7";
41 bool isLabelValid(const CKM::Label &label) {
42 // TODO: copy code from libprivilege control (for check smack label)
43 if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos)
48 bool isNameValid(const CKM::Name &name) {
49 if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
53 } // anonymous namespace
57 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
61 CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
63 m_accessControl.updateCCMode();
66 CKMLogic::~CKMLogic(){}
68 void CKMLogic::loadDKEKFile(uid_t user, const Password &password) {
69 auto &handle = m_userDataMap[user];
73 auto wrappedDKEK = fs.getDKEK();
75 if (wrappedDKEK.empty()) {
76 wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
77 fs.saveDKEK(wrappedDKEK);
80 handle.keyProvider = KeyProvider(wrappedDKEK, password);
83 void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
84 auto &handle = m_userDataMap[user];
87 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
90 int CKMLogic::unlockDatabase(uid_t user, const Password & password)
92 if (0<m_userDataMap.count(user) && m_userDataMap[user].keyProvider.isInitialized())
93 return CKM_API_SUCCESS;
95 int retCode = CKM_API_SUCCESS;
98 auto &handle = m_userDataMap[user];
101 loadDKEKFile(user, password);
103 auto wrappedDatabaseDEK = fs.getDBDEK();
104 if (wrappedDatabaseDEK.empty()) {
105 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
106 fs.saveDBDEK(wrappedDatabaseDEK);
109 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
111 handle.database = DB::Crypto(fs.getDBPath(), key);
112 handle.crypto = CryptoLogic();
114 if ( !m_accessControl.isSystemService(user) )
116 // remove data of removed apps during locked state
117 AppLabelVector removedApps = fs.clearRemovedsApps();
118 for(auto& appSmackLabel : removedApps) {
119 handle.crypto.removeKey(appSmackLabel);
120 handle.database.deleteKey(appSmackLabel);
123 } catch (const Exc::Exception &e) {
125 } catch (const CKM::Exception &e) {
126 LogError("CKM::Exception: " << e.GetMessage());
127 retCode = CKM_API_ERROR_SERVER_ERROR;
130 if (CKM_API_SUCCESS != retCode)
131 m_userDataMap.erase(user);
136 int CKMLogic::unlockSystemDB()
138 return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
141 UserData & CKMLogic::selectDatabase(const Credentials &cred, const Label &incoming_label)
143 // if user trying to access system service - check:
144 // * if user database is unlocked [mandatory]
145 // * if not - proceed with regular user database
146 // * if explicit system database label given -> switch to system DB
147 if ( !m_accessControl.isSystemService(cred) )
149 if (0 == m_userDataMap.count(cred.clientUid))
150 ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
152 if (0 != incoming_label.compare(OWNER_ID_SYSTEM))
153 return m_userDataMap[cred.clientUid];
156 // system database selected, modify the label
157 if (CKM_API_SUCCESS != unlockSystemDB() )
158 ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
159 return m_userDataMap[SYSTEM_DB_UID];
162 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
164 int retCode = CKM_API_SUCCESS;
166 if( !m_accessControl.isSystemService(user) )
168 retCode = unlockDatabase(user, password);
172 // do not allow lock/unlock operations for system users
173 retCode = CKM_API_ERROR_INPUT_PARAM;
176 return MessageBuffer::Serialize(retCode).Pop();
179 RawBuffer CKMLogic::updateCCMode() {
180 m_accessControl.updateCCMode();
181 return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
184 RawBuffer CKMLogic::lockUserKey(uid_t user)
186 int retCode = CKM_API_SUCCESS;
187 if( !m_accessControl.isSystemService(user) )
189 m_userDataMap.erase(user);
193 // do not allow lock/unlock operations for system users
194 retCode = CKM_API_ERROR_INPUT_PARAM;
197 return MessageBuffer::Serialize(retCode).Pop();
201 RawBuffer CKMLogic::removeUserData(uid_t user) {
202 int retCode = CKM_API_SUCCESS;
204 if (m_accessControl.isSystemService(user))
205 user = SYSTEM_DB_UID;
207 m_userDataMap.erase(user);
212 return MessageBuffer::Serialize(retCode).Pop();
215 int CKMLogic::changeUserPasswordHelper(uid_t user,
216 const Password &oldPassword,
217 const Password &newPassword)
219 // do not allow to change system database password
220 if( m_accessControl.isSystemService(user) )
221 return CKM_API_ERROR_INPUT_PARAM;
223 loadDKEKFile(user, oldPassword);
224 saveDKEKFile(user, newPassword);
226 return CKM_API_SUCCESS;
229 RawBuffer CKMLogic::changeUserPassword(
231 const Password &oldPassword,
232 const Password &newPassword)
234 int retCode = CKM_API_SUCCESS;
237 retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
238 } catch (const Exc::Exception &e) {
240 } catch (const CKM::Exception &e) {
241 LogError("CKM::Exception: " << e.GetMessage());
242 retCode = CKM_API_ERROR_SERVER_ERROR;
245 return MessageBuffer::Serialize(retCode).Pop();
248 int CKMLogic::resetUserPasswordHelper(
250 const Password &newPassword)
252 // do not allow to reset system database password
253 if( m_accessControl.isSystemService(user) )
254 return CKM_API_ERROR_INPUT_PARAM;
256 int retCode = CKM_API_SUCCESS;
257 if (0 == m_userDataMap.count(user))
259 // Check if key exists. If exists we must return error
261 auto wrappedDKEKMain = fs.getDKEK();
262 if (!wrappedDKEKMain.empty())
263 retCode = CKM_API_ERROR_BAD_REQUEST;
265 saveDKEKFile(user, newPassword);
271 RawBuffer CKMLogic::resetUserPassword(
273 const Password &newPassword)
275 int retCode = CKM_API_SUCCESS;
277 retCode = resetUserPasswordHelper(user, newPassword);
278 } catch (const Exc::Exception &e) {
280 } catch (const CKM::Exception &e) {
281 LogError("CKM::Exception: " << e.GetMessage());
282 retCode = CKM_API_ERROR_SERVER_ERROR;
285 return MessageBuffer::Serialize(retCode).Pop();
288 RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
289 int retCode = CKM_API_SUCCESS;
293 if (smackLabel.empty()) {
294 retCode = CKM_API_ERROR_INPUT_PARAM;
296 UidVector uids = FileSystem::getUIDsFromDBFile();
297 for (auto userId : uids) {
298 if (0 == m_userDataMap.count(userId)) {
299 FileSystem fs(userId);
300 fs.addRemovedApp(smackLabel);
302 auto &handle = m_userDataMap[userId];
303 handle.crypto.removeKey(smackLabel);
304 handle.database.deleteKey(smackLabel);
309 } catch (const DB::Crypto::Exception::InternalError &e) {
310 LogError("DB::Crypto couldn't remove data: " << e.GetMessage());
311 retCode = CKM_API_ERROR_DB_ERROR;
312 } catch (const DB::Crypto::Exception::TransactionError &e) {
313 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
314 retCode = CKM_API_ERROR_DB_ERROR;
315 } catch (const Exc::Exception &e) {
317 } catch (const CKM::Exception &e) {
318 LogError("CKM::Exception: " << e.GetMessage());
319 retCode = CKM_API_ERROR_SERVER_ERROR;
322 return MessageBuffer::Serialize(retCode).Pop();
325 int CKMLogic::checkSaveConditions(
326 const Credentials &cred,
329 const Label &ownerLabel)
331 // verify name and label are correct
332 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
333 LogDebug("Invalid parameter passed to key-manager");
334 return CKM_API_ERROR_INPUT_PARAM;
337 // check if allowed to save using ownerLabel
338 int access_ec = m_accessControl.canSave(cred, ownerLabel);
339 if( access_ec != CKM_API_SUCCESS)
341 LogDebug("label " << cred.smackLabel << " can not save rows using label " << ownerLabel);
345 // check if not a duplicate
346 if( handler.database.isNameLabelPresent(name, ownerLabel))
347 return CKM_API_ERROR_DB_ALIAS_EXISTS;
349 // encryption section
350 if (!handler.crypto.haveKey(ownerLabel))
353 auto key_optional = handler.database.getKey(ownerLabel);
355 LogDebug("No Key in database found. Generating new one for label: " << ownerLabel);
356 got_key = handler.keyProvider.generateDEK(ownerLabel);
357 handler.database.saveKey(ownerLabel, got_key);
359 LogDebug("Key from DB");
360 got_key = *key_optional;
363 got_key = handler.keyProvider.getPureDEK(got_key);
364 handler.crypto.pushKey(ownerLabel, got_key);
367 return CKM_API_SUCCESS;
370 DB::Row CKMLogic::createEncryptedRow(
374 const Crypto::Data &data,
375 const Policy &policy) const
377 Crypto::GStore& store = m_decider.getStore(data.type, policy.extractable);
379 // do not encrypt data with password during cc_mode on
380 Token token = store.import(data, m_accessControl.isCCMode() ? "" : policy.password);
381 DB::Row row(std::move(token), name, label, static_cast<int>(policy.extractable));
382 crypto.encryptRow(row);
386 int CKMLogic::verifyBinaryData(Crypto::Data &input) const
389 return toBinaryData(input, dummy);
392 int CKMLogic::toBinaryData(const Crypto::Data &input, Crypto::Data &output) const
394 // verify the data integrity
395 if (input.type.isKey())
398 if(input.type.isSKey())
399 output_key = CKM::Key::createAES(input.data);
401 output_key = CKM::Key::create(input.data);
402 if(output_key.get() == NULL)
404 LogDebug("provided binary data is not valid key data");
405 return CKM_API_ERROR_INPUT_PARAM;
407 output = std::move(Crypto::Data(input.type, output_key->getDER()));
409 else if (input.type.isCertificate() || input.type.isChainCert())
411 CertificateShPtr cert = CKM::Certificate::create(input.data, DataFormat::FORM_DER);
412 if(cert.get() == NULL)
414 LogDebug("provided binary data is not valid certificate data");
415 return CKM_API_ERROR_INPUT_PARAM;
417 output = std::move(Crypto::Data(input.type, cert->getDER()));
421 // TODO: add here BINARY_DATA verification, i.e: max size etc.
422 return CKM_API_SUCCESS;
425 int CKMLogic::verifyAndSaveDataHelper(
426 const Credentials &cred,
429 const Crypto::Data &data,
430 const PolicySerializable &policy)
432 int retCode = CKM_API_ERROR_UNKNOWN;
435 // check if data is correct
436 Crypto::Data binaryData;
437 retCode = toBinaryData(data, binaryData);
438 if(retCode == CKM_API_SUCCESS)
440 retCode = saveDataHelper(cred, name, label, binaryData, policy);
442 } catch (const DB::Crypto::Exception::InternalError &e) {
443 LogError("DB::Crypto failed with message: " << e.GetMessage());
444 retCode = CKM_API_ERROR_DB_ERROR;
445 } catch (const DB::Crypto::Exception::TransactionError &e) {
446 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
447 retCode = CKM_API_ERROR_DB_ERROR;
448 } catch (const Exc::Exception &e) {
450 } catch (const CKM::Exception &e) {
451 LogError("CKM::Exception: " << e.GetMessage());
452 retCode = CKM_API_ERROR_SERVER_ERROR;
457 int CKMLogic::getKeyForService(
458 const Credentials &cred,
461 const Password &pass,
462 Crypto::GObjShPtr &key)
466 // Key is for internal service use. It won't be exported to the client
467 Crypto::GObjUPtr obj;
468 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label, pass, obj);
469 if (retCode == CKM_API_SUCCESS)
470 key = std::move(obj);
472 } catch (const DB::Crypto::Exception::Base &e) {
473 LogError("DB::Crypto failed with message: " << e.GetMessage());
474 return CKM_API_ERROR_DB_ERROR;
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 RawBuffer CKMLogic::saveData(
484 const Credentials &cred,
488 const Crypto::Data &data,
489 const PolicySerializable &policy)
491 int retCode = verifyAndSaveDataHelper(cred, name, label, data, policy);
492 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
495 static_cast<int>(data.type));
496 return response.Pop();
499 int CKMLogic::extractPKCS12Data(
502 const Label &ownerLabel,
503 const PKCS12Serializable &pkcs,
504 const PolicySerializable &keyPolicy,
505 const PolicySerializable &certPolicy,
506 DB::RowVector &output) const
508 // private key is mandatory
510 return CKM_API_ERROR_INVALID_FORMAT;
511 Key* keyPtr = pkcs.getKey().get();
512 Crypto::Data keyData(DataType(keyPtr->getType()), keyPtr->getDER());
513 int retCode = verifyBinaryData(keyData);
514 if(retCode != CKM_API_SUCCESS)
516 output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyData, keyPolicy));
518 // certificate is mandatory
519 if( !pkcs.getCertificate() )
520 return CKM_API_ERROR_INVALID_FORMAT;
521 Crypto::Data certData(DataType::CERTIFICATE, pkcs.getCertificate().get()->getDER());
522 retCode = verifyBinaryData(certData);
523 if(retCode != CKM_API_SUCCESS)
525 output.push_back(createEncryptedRow(crypto, name, ownerLabel, certData, certPolicy));
528 unsigned int cert_index = 0;
529 for(const auto & ca : pkcs.getCaCertificateShPtrVector())
531 Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++), ca->getDER());
532 int retCode = verifyBinaryData(caCertData);
533 if(retCode != CKM_API_SUCCESS)
536 output.push_back(createEncryptedRow(crypto, name, ownerLabel, caCertData, certPolicy));
539 return CKM_API_SUCCESS;
542 RawBuffer CKMLogic::savePKCS12(
543 const Credentials &cred,
547 const PKCS12Serializable &pkcs,
548 const PolicySerializable &keyPolicy,
549 const PolicySerializable &certPolicy)
551 int retCode = CKM_API_ERROR_UNKNOWN;
553 retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
554 } catch (const Exc::Exception &e) {
556 } catch (const DB::Crypto::Exception::InternalError &e) {
557 LogError("DB::Crypto failed with message: " << e.GetMessage());
558 retCode = CKM_API_ERROR_DB_ERROR;
559 } catch (const DB::Crypto::Exception::TransactionError &e) {
560 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
561 retCode = CKM_API_ERROR_DB_ERROR;
562 } catch (const CKM::Exception &e) {
563 LogError("CKM::Exception: " << e.GetMessage());
564 retCode = CKM_API_ERROR_SERVER_ERROR;
567 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
570 return response.Pop();
574 int CKMLogic::removeDataHelper(
575 const Credentials &cred,
579 auto &handler = selectDatabase(cred, label);
581 // use client label if not explicitly provided
582 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
583 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
584 LogDebug("Invalid label or name format");
585 return CKM_API_ERROR_INPUT_PARAM;
588 DB::Crypto::Transaction transaction(&handler.database);
590 // read and check permissions
591 PermissionMaskOptional permissionRowOpt =
592 handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel);
593 int retCode = m_accessControl.canDelete(cred,
594 PermissionForLabel(cred.smackLabel, permissionRowOpt));
595 if(retCode != CKM_API_SUCCESS)
597 LogWarning("access control check result: " << retCode);
601 // get all matching rows
603 handler.database.getRows(name, ownerLabel, DataType::DB_FIRST, DataType::DB_LAST, rows);
605 LogDebug("No row for given name and label");
606 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
609 // load app key if needed
610 retCode = loadAppKey(handler, rows.front().ownerLabel);
611 if(CKM_API_SUCCESS != retCode)
614 // destroy it in store
615 for(auto& r : rows) {
617 handler.crypto.decryptRow(Password(), r);
618 m_decider.getStore(r).destroy(r);
619 } catch (const Exc::AuthenticationFailed&) {
620 LogDebug("Authentication failed when removing data. Ignored.");
625 handler.database.deleteRow(name, ownerLabel);
626 transaction.commit();
628 return CKM_API_SUCCESS;
631 RawBuffer CKMLogic::removeData(
632 const Credentials &cred,
637 int retCode = CKM_API_ERROR_UNKNOWN;
641 retCode = removeDataHelper(cred, name, label);
643 catch (const Exc::Exception &e)
647 catch (const CKM::Exception &)
649 LogError("Error in deleting row!");
650 retCode = CKM_API_ERROR_DB_ERROR;
653 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
656 return response.Pop();
659 int CKMLogic::readSingleRow(const Name &name,
660 const Label &ownerLabel,
662 DB::Crypto & database,
665 DB::Crypto::RowOptional row_optional;
666 if (dataType.isKey())
668 // read all key types
669 row_optional = database.getRow(name,
671 DataType::DB_KEY_FIRST,
672 DataType::DB_KEY_LAST);
674 // read anything else
675 row_optional = database.getRow(name,
681 LogDebug("No row for given name, label and type");
682 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
687 return CKM_API_SUCCESS;
691 int CKMLogic::readMultiRow(const Name &name,
692 const Label &ownerLabel,
694 DB::Crypto & database,
695 DB::RowVector &output)
697 if (dataType.isKey())
699 // read all key types
700 database.getRows(name,
702 DataType::DB_KEY_FIRST,
703 DataType::DB_KEY_LAST,
706 else if (dataType.isChainCert())
708 // read all key types
709 database.getRows(name,
711 DataType::DB_CHAIN_FIRST,
712 DataType::DB_CHAIN_LAST,
717 // read anything else
718 database.getRows(name,
725 LogDebug("No row for given name, label and type");
726 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
729 return CKM_API_SUCCESS;
732 int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
734 const Label &ownerLabel,
735 const Label &accessorLabel,
738 DB::Crypto & database)
740 PermissionMaskOptional permissionRowOpt =
741 database.getPermissionRow(name, ownerLabel, accessorLabel);
744 return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt));
745 return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt));
748 Crypto::GObjUPtr CKMLogic::rowToObject(
751 const Password& password)
753 Crypto::GStore& store = m_decider.getStore(row);
755 Password pass = m_accessControl.isCCMode() ? "" : password;
758 Crypto::GObjUPtr obj;
759 if(CryptoLogic::getSchemeVersion(row.encryptionScheme) == CryptoLogic::ENCRYPTION_V2) {
760 handler.crypto.decryptRow(Password(), row);
762 obj = store.getObject(row, pass);
764 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
765 handler.crypto.decryptRow(pass, row);
766 // destroy it in store
769 // import it to store with new scheme: data -> pass(data)
770 Token token = store.import(Crypto::Data(row.dataType, row.data), pass);
772 // get it from the store (it can be different than the data we imported into store)
773 obj = store.getObject(token, pass);
775 // update row with new token
776 *static_cast<Token*>(&row) = std::move(token);
778 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
779 handler.crypto.encryptRow(row);
782 handler.database.updateRow(row);
787 int CKMLogic::readDataHelper(
789 const Credentials &cred,
793 const Password &password,
794 Crypto::GObjUPtrVector &objs)
796 auto &handler = selectDatabase(cred, label);
798 // use client label if not explicitly provided
799 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
801 if (!isNameValid(name) || !isLabelValid(ownerLabel))
802 return CKM_API_ERROR_INPUT_PARAM;
805 DB::Crypto::Transaction transaction(&handler.database);
807 int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
808 if(CKM_API_SUCCESS != retCode)
811 // all read rows belong to the same owner
812 DB::Row & firstRow = rows.at(0);
814 // check access rights
815 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database);
816 if(CKM_API_SUCCESS != retCode)
819 // load app key if needed
820 retCode = loadAppKey(handler, firstRow.ownerLabel);
821 if(CKM_API_SUCCESS != retCode)
825 for(auto &row : rows)
826 objs.push_back(rowToObject(handler, std::move(row), password));
827 // rowToObject may modify db
828 transaction.commit();
830 return CKM_API_SUCCESS;
833 int CKMLogic::readDataHelper(
835 const Credentials &cred,
839 const Password &password,
840 Crypto::GObjUPtr &obj)
842 DataType objDataType;
843 return readDataHelper(exportFlag, cred, dataType, name, label, password, obj, objDataType);
846 int CKMLogic::readDataHelper(
848 const Credentials &cred,
852 const Password &password,
853 Crypto::GObjUPtr &obj,
854 DataType& objDataType)
856 auto &handler = selectDatabase(cred, label);
858 // use client label if not explicitly provided
859 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
861 if (!isNameValid(name) || !isLabelValid(ownerLabel))
862 return CKM_API_ERROR_INPUT_PARAM;
865 DB::Crypto::Transaction transaction(&handler.database);
867 int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
868 if(CKM_API_SUCCESS != retCode)
871 objDataType = row.dataType;
873 // check access rights
874 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
875 if(CKM_API_SUCCESS != retCode)
878 // load app key if needed
879 retCode = loadAppKey(handler, row.ownerLabel);
880 if(CKM_API_SUCCESS != retCode)
883 obj = rowToObject(handler, std::move(row), password);
884 // rowToObject may modify db
885 transaction.commit();
887 return CKM_API_SUCCESS;
890 RawBuffer CKMLogic::getData(
891 const Credentials &cred,
896 const Password &password)
898 int retCode = CKM_API_SUCCESS;
900 DataType objDataType;
903 Crypto::GObjUPtr obj;
904 retCode = readDataHelper(true, cred, dataType, name, label, password, obj, objDataType);
905 if(retCode == CKM_API_SUCCESS)
906 row.data = std::move(obj->getBinary());
907 } catch (const DB::Crypto::Exception::Base &e) {
908 LogError("DB::Crypto failed with message: " << e.GetMessage());
909 retCode = CKM_API_ERROR_DB_ERROR;
910 } catch (const Exc::Exception &e) {
912 } catch (const CKM::Exception &e) {
913 LogError("CKM::Exception: " << e.GetMessage());
914 retCode = CKM_API_ERROR_SERVER_ERROR;
917 if (CKM_API_SUCCESS != retCode) {
919 row.dataType = dataType;
922 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
925 static_cast<int>(objDataType),
927 return response.Pop();
930 int CKMLogic::getPKCS12Helper(
931 const Credentials &cred,
934 const Password &keyPassword,
935 const Password &certPassword,
937 CertificateShPtr & cert,
938 CertificateShPtrVector & caChain)
942 // read private key (mandatory)
943 Crypto::GObjUPtr keyObj;
944 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, keyObj);
945 if(retCode != CKM_API_SUCCESS)
947 privKey = CKM::Key::create(keyObj->getBinary());
949 // read certificate (mandatory)
950 Crypto::GObjUPtr certObj;
951 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certObj);
952 if(retCode != CKM_API_SUCCESS)
954 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
956 // read CA cert chain (optional)
957 Crypto::GObjUPtrVector caChainObjs;
958 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, caChainObjs);
959 if(retCode != CKM_API_SUCCESS &&
960 retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
962 for(auto &caCertObj : caChainObjs)
963 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(), DataFormat::FORM_DER));
965 // if anything found, return it
966 if(privKey || cert || caChain.size()>0)
967 retCode = CKM_API_SUCCESS;
972 RawBuffer CKMLogic::getPKCS12(
973 const Credentials &cred,
977 const Password &keyPassword,
978 const Password &certPassword)
980 int retCode = CKM_API_ERROR_UNKNOWN;
982 PKCS12Serializable output;
985 CertificateShPtr cert;
986 CertificateShPtrVector caChain;
987 retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey, cert, caChain);
990 if(retCode == CKM_API_SUCCESS)
991 output = PKCS12Serializable(privKey, cert, caChain);
992 } catch (const DB::Crypto::Exception::Base &e) {
993 LogError("DB::Crypto failed with message: " << e.GetMessage());
994 retCode = CKM_API_ERROR_DB_ERROR;
995 } catch (const Exc::Exception &e) {
997 } catch (const CKM::Exception &e) {
998 LogError("CKM::Exception: " << e.GetMessage());
999 retCode = CKM_API_ERROR_SERVER_ERROR;
1002 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
1006 return response.Pop();
1009 int CKMLogic::getDataListHelper(const Credentials &cred,
1010 const DataType dataType,
1011 LabelNameVector &labelNameVector)
1013 int retCode = CKM_API_ERROR_DB_LOCKED;
1014 if (0 < m_userDataMap.count(cred.clientUid))
1016 auto &database = m_userDataMap[cred.clientUid].database;
1019 LabelNameVector tmpVector;
1020 if (dataType.isKey()) {
1021 // list all key types
1022 database.listNames(cred.smackLabel,
1024 DataType::DB_KEY_FIRST,
1025 DataType::DB_KEY_LAST);
1027 // list anything else
1028 database.listNames(cred.smackLabel,
1032 labelNameVector.insert(labelNameVector.end(), tmpVector.begin(), tmpVector.end());
1033 retCode = CKM_API_SUCCESS;
1035 Catch (CKM::Exception) {
1036 LogError("Failed to get names");
1037 retCode = CKM_API_ERROR_DB_ERROR;
1043 RawBuffer CKMLogic::getDataList(
1044 const Credentials &cred,
1048 LabelNameVector systemVector;
1049 LabelNameVector userVector;
1050 LabelNameVector labelNameVector;
1052 int retCode = unlockSystemDB();
1053 if (CKM_API_SUCCESS == retCode)
1056 if (m_accessControl.isSystemService(cred))
1059 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1066 // user - lookup system, then client DB
1067 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1073 if(retCode == CKM_API_SUCCESS)
1075 retCode = getDataListHelper(cred,
1082 if(retCode == CKM_API_SUCCESS)
1084 labelNameVector.insert(labelNameVector.end(), systemVector.begin(), systemVector.end());
1085 labelNameVector.insert(labelNameVector.end(), userVector.begin(), userVector.end());
1087 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
1090 static_cast<int>(dataType),
1092 return response.Pop();
1095 int CKMLogic::importInitialData(
1097 const Crypto::Data &data,
1098 const Crypto::DataEncryption &enc,
1099 const Policy &policy)
1101 // Inital values are always imported with root credentials. Label is not important.
1102 Credentials rootCred(0,"");
1104 auto &handler = selectDatabase(rootCred, OWNER_ID_SYSTEM);
1106 // check if save is possible
1107 DB::Crypto::Transaction transaction(&handler.database);
1108 int retCode = checkSaveConditions(rootCred, handler, name, OWNER_ID_SYSTEM);
1109 if(retCode != CKM_API_SUCCESS)
1112 Crypto::GStore& store =
1113 m_decider.getStore(data.type, policy.extractable, !enc.encryptedKey.empty());
1116 if (enc.encryptedKey.empty())
1117 token = store.import(data, m_accessControl.isCCMode() ? "" : policy.password);
1119 token = store.importEncrypted(data, m_accessControl.isCCMode() ? "" : policy.password, enc);
1121 DB::Row row(std::move(token), name, OWNER_ID_SYSTEM, static_cast<int>(policy.extractable));
1122 handler.crypto.encryptRow(row);
1124 handler.database.saveRow(row);
1125 transaction.commit();
1127 return CKM_API_SUCCESS;
1130 int CKMLogic::saveDataHelper(
1131 const Credentials &cred,
1134 const Crypto::Data &data,
1135 const PolicySerializable &policy)
1137 auto &handler = selectDatabase(cred, label);
1139 // use client label if not explicitly provided
1140 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1141 if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0)
1142 return CKM_API_ERROR_INPUT_PARAM;
1144 // check if save is possible
1145 DB::Crypto::Transaction transaction(&handler.database);
1146 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1147 if(retCode != CKM_API_SUCCESS)
1151 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, data, policy);
1152 handler.database.saveRow(encryptedRow);
1154 transaction.commit();
1155 return CKM_API_SUCCESS;
1158 int CKMLogic::saveDataHelper(
1159 const Credentials &cred,
1162 const PKCS12Serializable &pkcs,
1163 const PolicySerializable &keyPolicy,
1164 const PolicySerializable &certPolicy)
1166 auto &handler = selectDatabase(cred, label);
1168 // use client label if not explicitly provided
1169 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1170 if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0)
1171 return CKM_API_ERROR_INPUT_PARAM;
1173 // check if save is possible
1174 DB::Crypto::Transaction transaction(&handler.database);
1175 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1176 if(retCode != CKM_API_SUCCESS)
1179 // extract and encrypt the data
1180 DB::RowVector encryptedRows;
1181 retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
1182 if(retCode != CKM_API_SUCCESS)
1186 handler.database.saveRows(name, ownerLabel, encryptedRows);
1187 transaction.commit();
1189 return CKM_API_SUCCESS;
1193 int CKMLogic::createKeyAESHelper(
1194 const Credentials &cred,
1198 const PolicySerializable &policy)
1200 auto &handler = selectDatabase(cred, label);
1202 // use client label if not explicitly provided
1203 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1204 if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0)
1205 return CKM_API_ERROR_INPUT_PARAM;
1207 // check if save is possible
1208 DB::Crypto::Transaction transaction(&handler.database);
1209 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1210 if(retCode != CKM_API_SUCCESS)
1213 // create key in store
1214 CryptoAlgorithm keyGenAlgorithm;
1215 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1216 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1217 Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm, policy.password);
1220 DB::Row row(std::move(key), name, ownerLabel, static_cast<int>(policy.extractable));
1221 handler.crypto.encryptRow(row);
1223 handler.database.saveRow(row);
1225 transaction.commit();
1226 return CKM_API_SUCCESS;
1229 int CKMLogic::createKeyPairHelper(
1230 const Credentials &cred,
1231 const CryptoAlgorithmSerializable & keyGenParams,
1232 const Name &namePrivate,
1233 const Label &labelPrivate,
1234 const Name &namePublic,
1235 const Label &labelPublic,
1236 const PolicySerializable &policyPrivate,
1237 const PolicySerializable &policyPublic)
1239 auto &handlerPriv = selectDatabase(cred, labelPrivate);
1240 auto &handlerPub = selectDatabase(cred, labelPublic);
1242 AlgoType keyType = AlgoType::RSA_GEN;
1243 if(!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1244 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1245 DataType dt(keyType);
1247 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1249 // use client label if not explicitly provided
1250 const Label &ownerLabelPrv = labelPrivate.empty() ? cred.smackLabel : labelPrivate;
1251 if( m_accessControl.isSystemService(cred) && ownerLabelPrv.compare(OWNER_ID_SYSTEM)!=0)
1252 return CKM_API_ERROR_INPUT_PARAM;
1253 const Label &ownerLabelPub = labelPublic.empty() ? cred.smackLabel : labelPublic;
1254 if( m_accessControl.isSystemService(cred) && ownerLabelPub.compare(OWNER_ID_SYSTEM)!=0)
1255 return CKM_API_ERROR_INPUT_PARAM;
1257 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1258 TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams,
1259 policyPrivate.password,
1260 policyPublic.password);
1262 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1263 // in case the same database is used for private and public - the second
1264 // transaction will not be executed
1265 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1268 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerLabelPrv);
1269 if (CKM_API_SUCCESS != retCode)
1272 retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerLabelPub);
1273 if (CKM_API_SUCCESS != retCode)
1277 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerLabelPrv, static_cast<int>(policyPrivate.extractable));
1278 handlerPriv.crypto.encryptRow(rowPrv);
1279 handlerPriv.database.saveRow(rowPrv);
1281 DB::Row rowPub(std::move(keys.second), namePublic, ownerLabelPub, static_cast<int>(policyPublic.extractable));
1282 handlerPub.crypto.encryptRow(rowPub);
1283 handlerPub.database.saveRow(rowPub);
1285 transactionPub.commit();
1286 transactionPriv.commit();
1287 return CKM_API_SUCCESS;
1290 RawBuffer CKMLogic::createKeyPair(
1291 const Credentials &cred,
1293 const CryptoAlgorithmSerializable & keyGenParams,
1294 const Name &namePrivate,
1295 const Label &labelPrivate,
1296 const Name &namePublic,
1297 const Label &labelPublic,
1298 const PolicySerializable &policyPrivate,
1299 const PolicySerializable &policyPublic)
1301 int retCode = CKM_API_SUCCESS;
1304 retCode = createKeyPairHelper(
1313 } catch(const Exc::Exception &e) {
1314 retCode = e.error();
1315 } catch (DB::Crypto::Exception::TransactionError &e) {
1316 LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1317 retCode = CKM_API_ERROR_DB_ERROR;
1318 } catch (DB::Crypto::Exception::InternalError &e) {
1319 LogDebug("DB::Crypto internal error: " << e.GetMessage());
1320 retCode = CKM_API_ERROR_DB_ERROR;
1321 } catch (const CKM::Exception &e) {
1322 LogError("CKM::Exception: " << e.GetMessage());
1323 retCode = CKM_API_ERROR_SERVER_ERROR;
1326 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1327 commandId, retCode).Pop();
1330 RawBuffer CKMLogic::createKeyAES(
1331 const Credentials &cred,
1336 const PolicySerializable &policy)
1338 int retCode = CKM_API_SUCCESS;
1341 retCode = createKeyAESHelper(cred, size, name, label, policy);
1342 } catch (const Exc::Exception &e) {
1343 retCode = e.error();
1344 } catch (std::invalid_argument &e) {
1345 LogDebug("invalid argument error: " << e.what());
1346 retCode = CKM_API_ERROR_INPUT_PARAM;
1347 } catch (DB::Crypto::Exception::TransactionError &e) {
1348 LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1349 retCode = CKM_API_ERROR_DB_ERROR;
1350 } catch (DB::Crypto::Exception::InternalError &e) {
1351 LogDebug("DB::Crypto internal error: " << e.GetMessage());
1352 retCode = CKM_API_ERROR_DB_ERROR;
1353 } catch (const CKM::Exception &e) {
1354 LogError("CKM::Exception: " << e.GetMessage());
1355 retCode = CKM_API_ERROR_SERVER_ERROR;
1358 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1359 commandId, retCode).Pop();
1362 int CKMLogic::readCertificateHelper(
1363 const Credentials &cred,
1364 const LabelNameVector &labelNameVector,
1365 CertificateImplVector &certVector)
1368 for (auto &i: labelNameVector) {
1369 // certificates can't be protected with custom user password
1370 Crypto::GObjUPtr obj;
1372 ec = readDataHelper(true,
1374 DataType::CERTIFICATE,
1379 if (ec != CKM_API_SUCCESS)
1382 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1384 // try to read chain certificates (if present)
1385 Crypto::GObjUPtrVector caChainObjs;
1386 ec = readDataHelper(true,
1388 DataType::DB_CHAIN_FIRST,
1393 if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1395 for(auto &caCertObj : caChainObjs)
1396 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1398 return CKM_API_SUCCESS;
1401 int CKMLogic::getCertificateChainHelper(
1402 const CertificateImpl &cert,
1403 const RawBufferVector &untrustedCertificates,
1404 const RawBufferVector &trustedCertificates,
1405 bool useTrustedSystemCertificates,
1406 RawBufferVector &chainRawVector)
1408 CertificateImplVector untrustedCertVector;
1409 CertificateImplVector trustedCertVector;
1410 CertificateImplVector chainVector;
1413 return CKM_API_ERROR_INPUT_PARAM;
1415 for (auto &e: untrustedCertificates) {
1416 CertificateImpl c(e, DataFormat::FORM_DER);
1418 return CKM_API_ERROR_INPUT_PARAM;
1419 untrustedCertVector.push_back(std::move(c));
1421 for (auto &e: trustedCertificates) {
1422 CertificateImpl c(e, DataFormat::FORM_DER);
1424 return CKM_API_ERROR_INPUT_PARAM;
1425 trustedCertVector.push_back(std::move(c));
1428 CertificateStore store;
1429 int retCode = store.verifyCertificate(cert,
1430 untrustedCertVector,
1432 useTrustedSystemCertificates,
1433 m_accessControl.isCCMode(),
1435 if (retCode != CKM_API_SUCCESS)
1438 for (auto &e : chainVector)
1439 chainRawVector.push_back(e.getDER());
1440 return CKM_API_SUCCESS;
1443 int CKMLogic::getCertificateChainHelper(
1444 const Credentials &cred,
1445 const CertificateImpl &cert,
1446 const LabelNameVector &untrusted,
1447 const LabelNameVector &trusted,
1448 bool useTrustedSystemCertificates,
1449 RawBufferVector &chainRawVector)
1451 CertificateImplVector untrustedCertVector;
1452 CertificateImplVector trustedCertVector;
1453 CertificateImplVector chainVector;
1457 return CKM_API_ERROR_INPUT_PARAM;
1459 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1460 if (retCode != CKM_API_SUCCESS)
1462 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1463 if (retCode != CKM_API_SUCCESS)
1466 CertificateStore store;
1467 retCode = store.verifyCertificate(cert,
1468 untrustedCertVector,
1470 useTrustedSystemCertificates,
1471 m_accessControl.isCCMode(),
1473 if (retCode != CKM_API_SUCCESS)
1476 for (auto &i: chainVector)
1477 chainRawVector.push_back(i.getDER());
1479 return CKM_API_SUCCESS;
1482 RawBuffer CKMLogic::getCertificateChain(
1483 const Credentials & /*cred*/,
1485 const RawBuffer &certificate,
1486 const RawBufferVector &untrustedCertificates,
1487 const RawBufferVector &trustedCertificates,
1488 bool useTrustedSystemCertificates)
1490 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1491 RawBufferVector chainRawVector;
1492 int retCode = CKM_API_ERROR_UNKNOWN;
1494 retCode = getCertificateChainHelper(cert,
1495 untrustedCertificates,
1496 trustedCertificates,
1497 useTrustedSystemCertificates,
1499 } catch (const Exc::Exception &e) {
1500 retCode = e.error();
1501 } catch (const DB::Crypto::Exception::Base &e) {
1502 LogError("DB::Crypto failed with message: " << e.GetMessage());
1503 retCode = CKM_API_ERROR_DB_ERROR;
1504 } catch (const std::exception& e) {
1505 LogError("STD exception " << e.what());
1506 retCode = CKM_API_ERROR_SERVER_ERROR;
1508 LogError("Unknown error.");
1511 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1515 return response.Pop();
1518 RawBuffer CKMLogic::getCertificateChain(
1519 const Credentials &cred,
1521 const RawBuffer &certificate,
1522 const LabelNameVector &untrustedCertificates,
1523 const LabelNameVector &trustedCertificates,
1524 bool useTrustedSystemCertificates)
1526 int retCode = CKM_API_ERROR_UNKNOWN;
1527 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1528 RawBufferVector chainRawVector;
1530 retCode = getCertificateChainHelper(cred,
1532 untrustedCertificates,
1533 trustedCertificates,
1534 useTrustedSystemCertificates,
1536 } catch (const DB::Crypto::Exception::Base &e) {
1537 LogError("DB::Crypto failed with message: " << e.GetMessage());
1538 retCode = CKM_API_ERROR_DB_ERROR;
1539 } catch (const Exc::Exception &e) {
1540 retCode = e.error();
1541 } catch (const std::exception& e) {
1542 LogError("STD exception " << e.what());
1543 retCode = CKM_API_ERROR_SERVER_ERROR;
1545 LogError("Unknown error.");
1548 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1552 return response.Pop();
1555 RawBuffer CKMLogic::createSignature(
1556 const Credentials &cred,
1558 const Name &privateKeyName,
1559 const Label & ownerLabel,
1560 const Password &password, // password for private_key
1561 const RawBuffer &message,
1562 const CryptoAlgorithm &cryptoAlg)
1565 RawBuffer signature;
1567 int retCode = CKM_API_SUCCESS;
1570 Crypto::GObjUPtr obj;
1571 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, obj);
1572 if(retCode == CKM_API_SUCCESS) {
1573 signature = obj->sign(cryptoAlg, message);
1575 } catch (const DB::Crypto::Exception::Base &e) {
1576 LogError("DB::Crypto failed with message: " << e.GetMessage());
1577 retCode = CKM_API_ERROR_DB_ERROR;
1578 } catch (const Exc::Exception &e) {
1579 retCode = e.error();
1580 } catch (const CKM::Exception &e) {
1581 LogError("Unknown CKM::Exception: " << e.GetMessage());
1582 retCode = CKM_API_ERROR_SERVER_ERROR;
1585 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1589 return response.Pop();
1592 RawBuffer CKMLogic::verifySignature(
1593 const Credentials &cred,
1595 const Name &publicKeyOrCertName,
1596 const Label & ownerLabel,
1597 const Password &password, // password for public_key (optional)
1598 const RawBuffer &message,
1599 const RawBuffer &signature,
1600 const CryptoAlgorithm ¶ms)
1602 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1607 // try certificate first - looking for a public key.
1608 // in case of PKCS, pub key from certificate will be found first
1609 // rather than private key from the same PKCS.
1610 Crypto::GObjUPtr obj;
1611 retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, obj);
1612 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1613 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, obj);
1616 if (retCode == CKM_API_SUCCESS) {
1617 retCode = obj->verify(params, message, signature);
1619 } catch (const Exc::Exception &e) {
1620 retCode = e.error();
1621 } catch (const DB::Crypto::Exception::Base &e) {
1622 LogError("DB::Crypto failed with message: " << e.GetMessage());
1623 retCode = CKM_API_ERROR_DB_ERROR;
1624 } catch (const CKM::Exception &e) {
1625 LogError("Unknown CKM::Exception: " << e.GetMessage());
1626 retCode = CKM_API_ERROR_SERVER_ERROR;
1629 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1632 return response.Pop();
1635 int CKMLogic::setPermissionHelper(
1636 const Credentials &cred, // who's the client
1638 const Label &label, // who's the owner
1639 const Label &accessorLabel, // who will get the access
1640 const PermissionMask permissionMask)
1642 auto &handler = selectDatabase(cred, label);
1644 // we don't know the client
1645 if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1646 return CKM_API_ERROR_INPUT_PARAM;
1648 // use client label if not explicitly provided
1649 const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1651 // verify name and label are correct
1652 if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1653 return CKM_API_ERROR_INPUT_PARAM;
1655 // currently we don't support modification of owner's permissions to his own rows
1656 if (ownerLabel==accessorLabel)
1657 return CKM_API_ERROR_INPUT_PARAM;
1659 // system database does not support write/remove permissions
1660 if ((0 == ownerLabel.compare(OWNER_ID_SYSTEM)) &&
1661 (permissionMask & Permission::REMOVE))
1662 return CKM_API_ERROR_INPUT_PARAM;
1664 // can the client modify permissions to owner's row?
1665 int retCode = m_accessControl.canModify(cred, ownerLabel);
1666 if(retCode != CKM_API_SUCCESS)
1669 DB::Crypto::Transaction transaction(&handler.database);
1671 if( !handler.database.isNameLabelPresent(name, ownerLabel) )
1672 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1674 // removing non-existing permissions: fail
1675 if(permissionMask == Permission::NONE)
1677 if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1678 return CKM_API_ERROR_INPUT_PARAM;
1681 // set permissions to the row owned by ownerLabel for accessorLabel
1682 handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1683 transaction.commit();
1685 return CKM_API_SUCCESS;
1688 RawBuffer CKMLogic::setPermission(
1689 const Credentials &cred,
1694 const Label &accessorLabel,
1695 const PermissionMask permissionMask)
1699 retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1700 } catch (const Exc::Exception &e) {
1701 retCode = e.error();
1702 } Catch (CKM::Exception) {
1703 LogError("Error in set row!");
1704 retCode = CKM_API_ERROR_DB_ERROR;
1707 return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1710 int CKMLogic::loadAppKey(UserData& handle, const Label& appLabel)
1712 if (!handle.crypto.haveKey(appLabel)) {
1714 auto key_optional = handle.database.getKey(appLabel);
1716 LogError("No key for given label in database");
1717 return CKM_API_ERROR_DB_ERROR;
1719 key = *key_optional;
1720 key = handle.keyProvider.getPureDEK(key);
1721 handle.crypto.pushKey(appLabel, key);
1723 return CKM_API_SUCCESS;