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>
35 #include <InitialValuesFile.h>
36 #include <sw-backend/store.h>
37 #include <generic-backend/exception.h>
40 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
41 const char * const INIT_VALUES_DIR = "/opt/data/ckm/initial_values/";
42 const char * const INIT_VALUES_XSD = "/usr/share/ckm/initial_values.xsd";
43 const char * const INIT_VALUES_FILE_SUFFIX = ".xml";
44 const char * const SYSTEM_DB_PASSWD = "cAtRugU7";
46 bool isLabelValid(const CKM::Label &label) {
47 // TODO: copy code from libprivilege control (for check smack label)
48 if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos)
53 bool isNameValid(const CKM::Name &name) {
54 if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
58 } // anonymous namespace
62 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
66 CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
68 m_accessControl.updateCCMode();
70 // make initial file list
71 std::vector<std::string> filesToParse;
72 DIR *dp = opendir(INIT_VALUES_DIR);
76 while ((entry = readdir(dp)))
78 std::string filename = std::string(entry->d_name);
81 std::string lowercaseFilename = filename;
82 std::transform(lowercaseFilename.begin(), lowercaseFilename.end(), lowercaseFilename.begin(), ::tolower);
83 if(lowercaseFilename.find(INIT_VALUES_FILE_SUFFIX) == std::string::npos)
86 filesToParse.push_back(std::string(INIT_VALUES_DIR) + filename);
92 for(const auto & file : filesToParse)
94 InitialValues::InitialValuesFile xmlFile(file.c_str(), *this);
95 int rc = xmlFile.Validate(INIT_VALUES_XSD);
96 if(rc == XML::Parser::PARSE_SUCCESS)
99 if(rc != XML::Parser::PARSE_SUCCESS)
100 LogError("invalid initial values file: " << file << ", parsing code: " << rc);
103 LogError("invalid initial values file: " << file << ", validation code: " << rc);
104 unlink(file.c_str());
108 CKMLogic::~CKMLogic(){}
110 void CKMLogic::loadDKEKFile(uid_t user, const Password &password) {
111 auto &handle = m_userDataMap[user];
115 auto wrappedDKEK = fs.getDKEK();
117 if (wrappedDKEK.empty()) {
118 wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
119 fs.saveDKEK(wrappedDKEK);
122 handle.keyProvider = KeyProvider(wrappedDKEK, password);
125 void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
126 auto &handle = m_userDataMap[user];
129 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
132 int CKMLogic::unlockDatabase(uid_t user, const Password & password)
134 if (0<m_userDataMap.count(user) && m_userDataMap[user].keyProvider.isInitialized())
135 return CKM_API_SUCCESS;
137 int retCode = CKM_API_SUCCESS;
140 auto &handle = m_userDataMap[user];
143 loadDKEKFile(user, password);
145 auto wrappedDatabaseDEK = fs.getDBDEK();
146 if (wrappedDatabaseDEK.empty()) {
147 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
148 fs.saveDBDEK(wrappedDatabaseDEK);
151 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
153 handle.database = DB::Crypto(fs.getDBPath(), key);
154 handle.crypto = CryptoLogic();
156 if ( !m_accessControl.isSystemService(user) )
158 // remove data of removed apps during locked state
159 AppLabelVector removedApps = fs.clearRemovedsApps();
160 for(auto& appSmackLabel : removedApps) {
161 handle.crypto.removeKey(appSmackLabel);
162 handle.database.deleteKey(appSmackLabel);
165 } catch (const Exc::Exception &e) {
167 } catch (const CKM::Exception &e) {
168 LogError("CKM::Exception: " << e.GetMessage());
169 retCode = CKM_API_ERROR_SERVER_ERROR;
172 if (CKM_API_SUCCESS != retCode)
173 m_userDataMap.erase(user);
178 int CKMLogic::unlockSystemDB()
180 return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
183 UserData & CKMLogic::selectDatabase(const Credentials &cred, const Label &incoming_label)
185 // if user trying to access system service - check:
186 // * if user database is unlocked [mandatory]
187 // * if not - proceed with regular user database
188 // * if explicit system database label given -> switch to system DB
189 if ( !m_accessControl.isSystemService(cred) )
191 if (0 == m_userDataMap.count(cred.clientUid))
192 ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
194 if (0 != incoming_label.compare(OWNER_ID_SYSTEM))
195 return m_userDataMap[cred.clientUid];
198 // system database selected, modify the label
199 if (CKM_API_SUCCESS != unlockSystemDB() )
200 ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
201 return m_userDataMap[SYSTEM_DB_UID];
204 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
206 int retCode = CKM_API_SUCCESS;
208 if( !m_accessControl.isSystemService(user) )
210 retCode = unlockDatabase(user, password);
214 // do not allow lock/unlock operations for system users
215 retCode = CKM_API_ERROR_INPUT_PARAM;
218 return MessageBuffer::Serialize(retCode).Pop();
221 RawBuffer CKMLogic::updateCCMode() {
222 m_accessControl.updateCCMode();
223 return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
226 RawBuffer CKMLogic::lockUserKey(uid_t user)
228 int retCode = CKM_API_SUCCESS;
229 if( !m_accessControl.isSystemService(user) )
231 m_userDataMap.erase(user);
235 // do not allow lock/unlock operations for system users
236 retCode = CKM_API_ERROR_INPUT_PARAM;
239 return MessageBuffer::Serialize(retCode).Pop();
243 RawBuffer CKMLogic::removeUserData(uid_t user) {
244 int retCode = CKM_API_SUCCESS;
246 if (m_accessControl.isSystemService(user))
247 user = SYSTEM_DB_UID;
249 m_userDataMap.erase(user);
254 return MessageBuffer::Serialize(retCode).Pop();
257 int CKMLogic::changeUserPasswordHelper(uid_t user,
258 const Password &oldPassword,
259 const Password &newPassword)
261 // do not allow to change system database password
262 if( m_accessControl.isSystemService(user) )
263 return CKM_API_ERROR_INPUT_PARAM;
265 loadDKEKFile(user, oldPassword);
266 saveDKEKFile(user, newPassword);
268 return CKM_API_SUCCESS;
271 RawBuffer CKMLogic::changeUserPassword(
273 const Password &oldPassword,
274 const Password &newPassword)
276 int retCode = CKM_API_SUCCESS;
279 retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
280 } catch (const Exc::Exception &e) {
282 } catch (const CKM::Exception &e) {
283 LogError("CKM::Exception: " << e.GetMessage());
284 retCode = CKM_API_ERROR_SERVER_ERROR;
287 return MessageBuffer::Serialize(retCode).Pop();
290 int CKMLogic::resetUserPasswordHelper(
292 const Password &newPassword)
294 // do not allow to reset system database password
295 if( m_accessControl.isSystemService(user) )
296 return CKM_API_ERROR_INPUT_PARAM;
298 int retCode = CKM_API_SUCCESS;
299 if (0 == m_userDataMap.count(user))
301 // Check if key exists. If exists we must return error
303 auto wrappedDKEKMain = fs.getDKEK();
304 if (!wrappedDKEKMain.empty())
305 retCode = CKM_API_ERROR_BAD_REQUEST;
307 saveDKEKFile(user, newPassword);
313 RawBuffer CKMLogic::resetUserPassword(
315 const Password &newPassword)
317 int retCode = CKM_API_SUCCESS;
319 retCode = resetUserPasswordHelper(user, newPassword);
320 } catch (const Exc::Exception &e) {
322 } catch (const CKM::Exception &e) {
323 LogError("CKM::Exception: " << e.GetMessage());
324 retCode = CKM_API_ERROR_SERVER_ERROR;
327 return MessageBuffer::Serialize(retCode).Pop();
330 RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
331 int retCode = CKM_API_SUCCESS;
335 if (smackLabel.empty()) {
336 retCode = CKM_API_ERROR_INPUT_PARAM;
338 UidVector uids = FileSystem::getUIDsFromDBFile();
339 for (auto userId : uids) {
340 if (0 == m_userDataMap.count(userId)) {
341 FileSystem fs(userId);
342 fs.addRemovedApp(smackLabel);
344 auto &handle = m_userDataMap[userId];
345 handle.crypto.removeKey(smackLabel);
346 handle.database.deleteKey(smackLabel);
351 } catch (const DB::Crypto::Exception::InternalError &e) {
352 LogError("DB::Crypto couldn't remove data: " << e.GetMessage());
353 retCode = CKM_API_ERROR_DB_ERROR;
354 } catch (const DB::Crypto::Exception::TransactionError &e) {
355 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
356 retCode = CKM_API_ERROR_DB_ERROR;
357 } catch (const Exc::Exception &e) {
359 } catch (const CKM::Exception &e) {
360 LogError("CKM::Exception: " << e.GetMessage());
361 retCode = CKM_API_ERROR_SERVER_ERROR;
364 return MessageBuffer::Serialize(retCode).Pop();
367 int CKMLogic::checkSaveConditions(
368 const Credentials &cred,
371 const Label &ownerLabel)
373 // verify name and label are correct
374 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
375 LogDebug("Invalid parameter passed to key-manager");
376 return CKM_API_ERROR_INPUT_PARAM;
379 // check if allowed to save using ownerLabel
380 int access_ec = m_accessControl.canSave(cred, ownerLabel);
381 if( access_ec != CKM_API_SUCCESS)
383 LogDebug("label " << cred.smackLabel << " can not save rows using label " << ownerLabel);
387 // check if not a duplicate
388 if( handler.database.isNameLabelPresent(name, ownerLabel))
389 return CKM_API_ERROR_DB_ALIAS_EXISTS;
391 // encryption section
392 if (!handler.crypto.haveKey(ownerLabel))
395 auto key_optional = handler.database.getKey(ownerLabel);
397 LogDebug("No Key in database found. Generating new one for label: " << ownerLabel);
398 got_key = handler.keyProvider.generateDEK(ownerLabel);
399 handler.database.saveKey(ownerLabel, got_key);
401 LogDebug("Key from DB");
402 got_key = *key_optional;
405 got_key = handler.keyProvider.getPureDEK(got_key);
406 handler.crypto.pushKey(ownerLabel, got_key);
409 return CKM_API_SUCCESS;
412 DB::Row CKMLogic::createEncryptedRow(
417 const RawBuffer &data,
418 const Policy &policy) const
420 Crypto::GStore& store = m_decider.getStore(dataType, policy.extractable);
422 // do not encrypt data with password during cc_mode on
423 Token token = store.import(dataType, data, m_accessControl.isCCMode() ? "" : policy.password);
424 DB::Row row(std::move(token), name, label, static_cast<int>(policy.extractable));
425 crypto.encryptRow(row);
429 int CKMLogic::verifyBinaryData(DataType dataType, RawBuffer &input_data) const
432 return toBinaryData(dataType, input_data, dummy);
435 int CKMLogic::toBinaryData(DataType dataType,
436 const RawBuffer &input_data,
437 RawBuffer &output_data) const
439 // verify the data integrity
440 if (dataType.isKey())
443 if(dataType.isSKey())
444 output_key = CKM::Key::createAES(input_data);
446 output_key = CKM::Key::create(input_data);
447 if(output_key.get() == NULL)
449 LogDebug("provided binary data is not valid key data");
450 return CKM_API_ERROR_INPUT_PARAM;
452 output_data = output_key->getDER();
454 else if (dataType.isCertificate() || dataType.isChainCert())
456 CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
457 if(cert.get() == NULL)
459 LogDebug("provided binary data is not valid certificate data");
460 return CKM_API_ERROR_INPUT_PARAM;
462 output_data = cert->getDER();
465 output_data = input_data;
466 // TODO: add here BINARY_DATA verification, i.e: max size etc.
467 return CKM_API_SUCCESS;
470 int CKMLogic::verifyAndSaveDataHelper(
471 const Credentials &cred,
474 const RawBuffer &data,
476 const PolicySerializable &policy)
478 int retCode = CKM_API_ERROR_UNKNOWN;
481 // check if data is correct
482 RawBuffer binaryData;
483 retCode = toBinaryData(dataType, data, binaryData);
484 if(retCode == CKM_API_SUCCESS)
486 retCode = saveDataHelper(cred, name, label, dataType, binaryData, policy);
488 } catch (const DB::Crypto::Exception::InternalError &e) {
489 LogError("DB::Crypto failed with message: " << e.GetMessage());
490 retCode = CKM_API_ERROR_DB_ERROR;
491 } catch (const DB::Crypto::Exception::TransactionError &e) {
492 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
493 retCode = CKM_API_ERROR_DB_ERROR;
494 } catch (const Exc::Exception &e) {
496 } catch (const CKM::Exception &e) {
497 LogError("CKM::Exception: " << e.GetMessage());
498 retCode = CKM_API_ERROR_SERVER_ERROR;
503 int CKMLogic::getKeyForService(
504 const Credentials &cred,
507 const Password &pass,
508 Crypto::GObjShPtr &key)
512 // Key is for internal service use. It won't be exported to the client
513 Crypto::GObjUPtr obj;
514 int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label, pass, obj);
515 if (retCode == CKM_API_SUCCESS)
516 key = std::move(obj);
518 } catch (const DB::Crypto::Exception::Base &e) {
519 LogError("DB::Crypto failed with message: " << e.GetMessage());
520 return CKM_API_ERROR_DB_ERROR;
521 } catch (const Exc::Exception &e) {
523 } catch (const CKM::Exception &e) {
524 LogError("CKM::Exception: " << e.GetMessage());
525 return CKM_API_ERROR_SERVER_ERROR;
529 RawBuffer CKMLogic::saveData(
530 const Credentials &cred,
534 const RawBuffer &data,
536 const PolicySerializable &policy)
538 int retCode = verifyAndSaveDataHelper(cred, name, label, data, dataType, policy);
539 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
542 static_cast<int>(dataType));
543 return response.Pop();
546 int CKMLogic::extractPKCS12Data(
549 const Label &ownerLabel,
550 const PKCS12Serializable &pkcs,
551 const PolicySerializable &keyPolicy,
552 const PolicySerializable &certPolicy,
553 DB::RowVector &output) const
555 // private key is mandatory
557 return CKM_API_ERROR_INVALID_FORMAT;
558 Key* keyPtr = pkcs.getKey().get();
559 DataType keyType = DataType(keyPtr->getType());
560 RawBuffer keyData = keyPtr->getDER();
561 int retCode = verifyBinaryData(keyType, keyData);
562 if(retCode != CKM_API_SUCCESS)
564 output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyType, keyData, keyPolicy));
566 // certificate is mandatory
567 if( !pkcs.getCertificate() )
568 return CKM_API_ERROR_INVALID_FORMAT;
569 RawBuffer certData = pkcs.getCertificate().get()->getDER();
570 retCode = verifyBinaryData(DataType::CERTIFICATE, certData);
571 if(retCode != CKM_API_SUCCESS)
573 output.push_back(createEncryptedRow(crypto, name, ownerLabel, DataType::CERTIFICATE, certData, certPolicy));
576 unsigned int cert_index = 0;
577 for(const auto & ca : pkcs.getCaCertificateShPtrVector())
579 DataType chainDataType = DataType::getChainDatatype(cert_index ++);
580 RawBuffer caCertData = ca->getDER();
581 int retCode = verifyBinaryData(chainDataType, caCertData);
582 if(retCode != CKM_API_SUCCESS)
585 output.push_back(createEncryptedRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy));
588 return CKM_API_SUCCESS;
591 RawBuffer CKMLogic::savePKCS12(
592 const Credentials &cred,
596 const PKCS12Serializable &pkcs,
597 const PolicySerializable &keyPolicy,
598 const PolicySerializable &certPolicy)
600 int retCode = CKM_API_ERROR_UNKNOWN;
602 retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
603 } catch (const Exc::Exception &e) {
605 } catch (const DB::Crypto::Exception::InternalError &e) {
606 LogError("DB::Crypto failed with message: " << e.GetMessage());
607 retCode = CKM_API_ERROR_DB_ERROR;
608 } catch (const DB::Crypto::Exception::TransactionError &e) {
609 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
610 retCode = CKM_API_ERROR_DB_ERROR;
611 } catch (const CKM::Exception &e) {
612 LogError("CKM::Exception: " << e.GetMessage());
613 retCode = CKM_API_ERROR_SERVER_ERROR;
616 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
619 return response.Pop();
623 int CKMLogic::removeDataHelper(
624 const Credentials &cred,
628 auto &handler = selectDatabase(cred, label);
630 // use client label if not explicitly provided
631 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
632 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
633 LogDebug("Invalid label or name format");
634 return CKM_API_ERROR_INPUT_PARAM;
637 DB::Crypto::Transaction transaction(&handler.database);
639 // read and check permissions
640 PermissionMaskOptional permissionRowOpt =
641 handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel);
642 int retCode = m_accessControl.canDelete(cred,
643 PermissionForLabel(cred.smackLabel, permissionRowOpt));
644 if(retCode != CKM_API_SUCCESS)
646 LogWarning("access control check result: " << retCode);
650 // get all matching rows
652 handler.database.getRows(name, ownerLabel, DataType::DB_FIRST, DataType::DB_LAST, rows);
654 LogDebug("No row for given name and label");
655 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
658 // load app key if needed
659 retCode = loadAppKey(handler, rows.front().ownerLabel);
660 if(CKM_API_SUCCESS != retCode)
663 // destroy it in store
664 for(auto& r : rows) {
666 handler.crypto.decryptRow(Password(), r);
667 m_decider.getStore(r).destroy(r);
668 } catch (const Exc::AuthenticationFailed&) {
669 LogDebug("Authentication failed when removing data. Ignored.");
674 handler.database.deleteRow(name, ownerLabel);
675 transaction.commit();
677 return CKM_API_SUCCESS;
680 RawBuffer CKMLogic::removeData(
681 const Credentials &cred,
686 int retCode = CKM_API_ERROR_UNKNOWN;
690 retCode = removeDataHelper(cred, name, label);
692 catch (const Exc::Exception &e)
696 catch (const CKM::Exception &)
698 LogError("Error in deleting row!");
699 retCode = CKM_API_ERROR_DB_ERROR;
702 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
705 return response.Pop();
708 int CKMLogic::readSingleRow(const Name &name,
709 const Label &ownerLabel,
711 DB::Crypto & database,
714 DB::Crypto::RowOptional row_optional;
715 if (dataType.isKey())
717 // read all key types
718 row_optional = database.getRow(name,
720 DataType::DB_KEY_FIRST,
721 DataType::DB_KEY_LAST);
723 // read anything else
724 row_optional = database.getRow(name,
730 LogDebug("No row for given name, label and type");
731 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
736 return CKM_API_SUCCESS;
740 int CKMLogic::readMultiRow(const Name &name,
741 const Label &ownerLabel,
743 DB::Crypto & database,
744 DB::RowVector &output)
746 if (dataType.isKey())
748 // read all key types
749 database.getRows(name,
751 DataType::DB_KEY_FIRST,
752 DataType::DB_KEY_LAST,
755 else if (dataType.isChainCert())
757 // read all key types
758 database.getRows(name,
760 DataType::DB_CHAIN_FIRST,
761 DataType::DB_CHAIN_LAST,
766 // read anything else
767 database.getRows(name,
774 LogDebug("No row for given name, label and type");
775 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
778 return CKM_API_SUCCESS;
781 int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
783 const Label &ownerLabel,
784 const Label &accessorLabel,
787 DB::Crypto & database)
789 PermissionMaskOptional permissionRowOpt =
790 database.getPermissionRow(name, ownerLabel, accessorLabel);
793 return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt));
794 return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt));
797 Crypto::GObjUPtr CKMLogic::rowToObject(
800 const Password& password)
802 Crypto::GStore& store = m_decider.getStore(row);
804 Password pass = m_accessControl.isCCMode() ? "" : password;
807 Crypto::GObjUPtr obj;
808 if(CryptoLogic::getSchemeVersion(row.encryptionScheme) == CryptoLogic::ENCRYPTION_V2) {
809 handler.crypto.decryptRow(Password(), row);
811 obj = store.getObject(row, pass);
813 // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
814 handler.crypto.decryptRow(pass, row);
815 // destroy it in store
818 // import it to store with new scheme: data -> pass(data)
819 Token token = store.import(row.dataType,row.data, pass);
821 // get it from the store (it can be different than the data we imported into store)
822 obj = store.getObject(token, pass);
824 // update row with new token
825 *static_cast<Token*>(&row) = std::move(token);
827 // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
828 handler.crypto.encryptRow(row);
831 handler.database.updateRow(row);
836 int CKMLogic::readDataHelper(
838 const Credentials &cred,
842 const Password &password,
843 Crypto::GObjUPtrVector &objs)
845 auto &handler = selectDatabase(cred, label);
847 // use client label if not explicitly provided
848 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
850 if (!isNameValid(name) || !isLabelValid(ownerLabel))
851 return CKM_API_ERROR_INPUT_PARAM;
854 DB::Crypto::Transaction transaction(&handler.database);
856 int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
857 if(CKM_API_SUCCESS != retCode)
860 // all read rows belong to the same owner
861 DB::Row & firstRow = rows.at(0);
863 // check access rights
864 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database);
865 if(CKM_API_SUCCESS != retCode)
868 // load app key if needed
869 retCode = loadAppKey(handler, firstRow.ownerLabel);
870 if(CKM_API_SUCCESS != retCode)
874 for(auto &row : rows)
875 objs.push_back(rowToObject(handler, std::move(row), password));
876 // rowToObject may modify db
877 transaction.commit();
879 return CKM_API_SUCCESS;
882 int CKMLogic::readDataHelper(
884 const Credentials &cred,
888 const Password &password,
889 Crypto::GObjUPtr &obj)
891 DataType objDataType;
892 return readDataHelper(exportFlag, cred, dataType, name, label, password, obj, objDataType);
895 int CKMLogic::readDataHelper(
897 const Credentials &cred,
901 const Password &password,
902 Crypto::GObjUPtr &obj,
903 DataType& objDataType)
905 auto &handler = selectDatabase(cred, label);
907 // use client label if not explicitly provided
908 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
910 if (!isNameValid(name) || !isLabelValid(ownerLabel))
911 return CKM_API_ERROR_INPUT_PARAM;
914 DB::Crypto::Transaction transaction(&handler.database);
916 int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
917 if(CKM_API_SUCCESS != retCode)
920 objDataType = row.dataType;
922 // check access rights
923 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
924 if(CKM_API_SUCCESS != retCode)
927 // load app key if needed
928 retCode = loadAppKey(handler, row.ownerLabel);
929 if(CKM_API_SUCCESS != retCode)
932 obj = rowToObject(handler, std::move(row), password);
933 // rowToObject may modify db
934 transaction.commit();
936 return CKM_API_SUCCESS;
939 RawBuffer CKMLogic::getData(
940 const Credentials &cred,
945 const Password &password)
947 int retCode = CKM_API_SUCCESS;
949 DataType objDataType;
952 Crypto::GObjUPtr obj;
953 retCode = readDataHelper(true, cred, dataType, name, label, password, obj, objDataType);
954 if(retCode == CKM_API_SUCCESS)
955 row.data = std::move(obj->getBinary());
956 } catch (const DB::Crypto::Exception::Base &e) {
957 LogError("DB::Crypto failed with message: " << e.GetMessage());
958 retCode = CKM_API_ERROR_DB_ERROR;
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, keyPassword, keyObj);
994 if(retCode != CKM_API_SUCCESS)
996 privKey = CKM::Key::create(keyObj->getBinary());
998 // read certificate (mandatory)
999 Crypto::GObjUPtr certObj;
1000 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certObj);
1001 if(retCode != CKM_API_SUCCESS)
1003 cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
1005 // read CA cert chain (optional)
1006 Crypto::GObjUPtrVector caChainObjs;
1007 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, caChainObjs);
1008 if(retCode != CKM_API_SUCCESS &&
1009 retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1011 for(auto &caCertObj : caChainObjs)
1012 caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(), DataFormat::FORM_DER));
1014 // if anything found, return it
1015 if(privKey || cert || caChain.size()>0)
1016 retCode = CKM_API_SUCCESS;
1021 RawBuffer CKMLogic::getPKCS12(
1022 const Credentials &cred,
1026 const Password &keyPassword,
1027 const Password &certPassword)
1029 int retCode = CKM_API_ERROR_UNKNOWN;
1031 PKCS12Serializable output;
1034 CertificateShPtr cert;
1035 CertificateShPtrVector caChain;
1036 retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey, cert, caChain);
1039 if(retCode == CKM_API_SUCCESS)
1040 output = PKCS12Serializable(privKey, cert, caChain);
1041 } catch (const DB::Crypto::Exception::Base &e) {
1042 LogError("DB::Crypto failed with message: " << e.GetMessage());
1043 retCode = CKM_API_ERROR_DB_ERROR;
1044 } catch (const Exc::Exception &e) {
1045 retCode = e.error();
1046 } catch (const CKM::Exception &e) {
1047 LogError("CKM::Exception: " << e.GetMessage());
1048 retCode = CKM_API_ERROR_SERVER_ERROR;
1051 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
1055 return response.Pop();
1058 int CKMLogic::getDataListHelper(const Credentials &cred,
1059 const DataType dataType,
1060 LabelNameVector &labelNameVector)
1062 int retCode = CKM_API_ERROR_DB_LOCKED;
1063 if (0 < m_userDataMap.count(cred.clientUid))
1065 auto &database = m_userDataMap[cred.clientUid].database;
1068 LabelNameVector tmpVector;
1069 if (dataType.isKey()) {
1070 // list all key types
1071 database.listNames(cred.smackLabel,
1073 DataType::DB_KEY_FIRST,
1074 DataType::DB_KEY_LAST);
1076 // list anything else
1077 database.listNames(cred.smackLabel,
1081 labelNameVector.insert(labelNameVector.end(), tmpVector.begin(), tmpVector.end());
1082 retCode = CKM_API_SUCCESS;
1084 Catch (CKM::Exception) {
1085 LogError("Failed to get names");
1086 retCode = CKM_API_ERROR_DB_ERROR;
1092 RawBuffer CKMLogic::getDataList(
1093 const Credentials &cred,
1097 LabelNameVector systemVector;
1098 LabelNameVector userVector;
1099 LabelNameVector labelNameVector;
1101 int retCode = unlockSystemDB();
1102 if (CKM_API_SUCCESS == retCode)
1105 if (m_accessControl.isSystemService(cred))
1108 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1115 // user - lookup system, then client DB
1116 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1122 if(retCode == CKM_API_SUCCESS)
1124 retCode = getDataListHelper(cred,
1131 if(retCode == CKM_API_SUCCESS)
1133 labelNameVector.insert(labelNameVector.end(), systemVector.begin(), systemVector.end());
1134 labelNameVector.insert(labelNameVector.end(), userVector.begin(), userVector.end());
1136 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
1139 static_cast<int>(dataType),
1141 return response.Pop();
1144 int CKMLogic::saveDataHelper(
1145 const Credentials &cred,
1149 const RawBuffer &data,
1150 const PolicySerializable &policy)
1152 auto &handler = selectDatabase(cred, label);
1154 // use client label if not explicitly provided
1155 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1156 if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0)
1157 return CKM_API_ERROR_INPUT_PARAM;
1159 // check if save is possible
1160 DB::Crypto::Transaction transaction(&handler.database);
1161 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1162 if(retCode != CKM_API_SUCCESS)
1166 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, dataType, data, policy);
1167 handler.database.saveRow(encryptedRow);
1169 transaction.commit();
1170 return CKM_API_SUCCESS;
1173 int CKMLogic::saveDataHelper(
1174 const Credentials &cred,
1177 const PKCS12Serializable &pkcs,
1178 const PolicySerializable &keyPolicy,
1179 const PolicySerializable &certPolicy)
1181 auto &handler = selectDatabase(cred, label);
1183 // use client label if not explicitly provided
1184 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1185 if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0)
1186 return CKM_API_ERROR_INPUT_PARAM;
1188 // check if save is possible
1189 DB::Crypto::Transaction transaction(&handler.database);
1190 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1191 if(retCode != CKM_API_SUCCESS)
1194 // extract and encrypt the data
1195 DB::RowVector encryptedRows;
1196 retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
1197 if(retCode != CKM_API_SUCCESS)
1201 handler.database.saveRows(name, ownerLabel, encryptedRows);
1202 transaction.commit();
1204 return CKM_API_SUCCESS;
1208 int CKMLogic::createKeyAESHelper(
1209 const Credentials &cred,
1213 const PolicySerializable &policy)
1215 auto &handler = selectDatabase(cred, label);
1217 // use client label if not explicitly provided
1218 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1219 if( m_accessControl.isSystemService(cred) && 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);
1225 if(retCode != CKM_API_SUCCESS)
1228 // create key in store
1229 CryptoAlgorithm keyGenAlgorithm;
1230 keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1231 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1232 Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm, policy.password);
1235 DB::Row row(std::move(key), name, ownerLabel, static_cast<int>(policy.extractable));
1236 handler.crypto.encryptRow(row);
1238 handler.database.saveRow(row);
1240 transaction.commit();
1241 return CKM_API_SUCCESS;
1245 int CKMLogic::createKeyPairHelper(
1246 const Credentials &cred,
1247 const CryptoAlgorithmSerializable & keyGenParams,
1248 const Name &namePrivate,
1249 const Label &labelPrivate,
1250 const Name &namePublic,
1251 const Label &labelPublic,
1252 const PolicySerializable &policyPrivate,
1253 const PolicySerializable &policyPublic)
1255 auto &handlerPriv = selectDatabase(cred, labelPrivate);
1256 auto &handlerPub = selectDatabase(cred, labelPublic);
1258 AlgoType keyType = AlgoType::RSA_GEN;
1259 if(!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1260 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1261 DataType dt(keyType);
1263 ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1265 // use client label if not explicitly provided
1266 const Label &ownerLabelPrv = labelPrivate.empty() ? cred.smackLabel : labelPrivate;
1267 if( m_accessControl.isSystemService(cred) && ownerLabelPrv.compare(OWNER_ID_SYSTEM)!=0)
1268 return CKM_API_ERROR_INPUT_PARAM;
1269 const Label &ownerLabelPub = labelPublic.empty() ? cred.smackLabel : labelPublic;
1270 if( m_accessControl.isSystemService(cred) && ownerLabelPub.compare(OWNER_ID_SYSTEM)!=0)
1271 return CKM_API_ERROR_INPUT_PARAM;
1273 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1274 TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams,
1275 policyPrivate.password,
1276 policyPublic.password);
1278 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1279 // in case the same database is used for private and public - the second
1280 // transaction will not be executed
1281 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1284 retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerLabelPrv);
1285 if(retCode != CKM_API_SUCCESS)
1287 retCode = checkSaveConditions(cred, handlerPub, namePrivate, ownerLabelPub);
1288 if(retCode != CKM_API_SUCCESS)
1292 DB::Row rowPrv(std::move(keys.first), namePrivate, ownerLabelPrv, static_cast<int>(policyPrivate.extractable));
1293 handlerPriv.crypto.encryptRow(rowPrv);
1294 handlerPriv.database.saveRow(rowPrv);
1296 DB::Row rowPub(std::move(keys.second), namePublic, ownerLabelPub, static_cast<int>(policyPublic.extractable));
1297 handlerPub.crypto.encryptRow(rowPub);
1298 handlerPub.database.saveRow(rowPub);
1300 transactionPub.commit();
1301 transactionPriv.commit();
1302 return CKM_API_SUCCESS;
1305 RawBuffer CKMLogic::createKeyPair(
1306 const Credentials &cred,
1308 const CryptoAlgorithmSerializable & keyGenParams,
1309 const Name &namePrivate,
1310 const Label &labelPrivate,
1311 const Name &namePublic,
1312 const Label &labelPublic,
1313 const PolicySerializable &policyPrivate,
1314 const PolicySerializable &policyPublic)
1316 int retCode = CKM_API_SUCCESS;
1319 retCode = createKeyPairHelper(
1328 } catch(const Exc::Exception &e) {
1329 retCode = e.error();
1330 } catch (DB::Crypto::Exception::TransactionError &e) {
1331 LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1332 retCode = CKM_API_ERROR_DB_ERROR;
1333 } catch (DB::Crypto::Exception::InternalError &e) {
1334 LogDebug("DB::Crypto internal error: " << e.GetMessage());
1335 retCode = CKM_API_ERROR_DB_ERROR;
1336 } catch (const CKM::Exception &e) {
1337 LogError("CKM::Exception: " << e.GetMessage());
1338 retCode = CKM_API_ERROR_SERVER_ERROR;
1341 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1342 commandId, retCode).Pop();
1345 RawBuffer CKMLogic::createKeyAES(
1346 const Credentials &cred,
1351 const PolicySerializable &policy)
1353 int retCode = CKM_API_SUCCESS;
1356 retCode = createKeyAESHelper(cred, size, name, label, policy);
1357 } catch (const Exc::Exception &e) {
1358 retCode = e.error();
1359 } catch (std::invalid_argument &e) {
1360 LogDebug("invalid argument error: " << e.what());
1361 retCode = CKM_API_ERROR_INPUT_PARAM;
1362 } catch (DB::Crypto::Exception::TransactionError &e) {
1363 LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1364 retCode = CKM_API_ERROR_DB_ERROR;
1365 } catch (DB::Crypto::Exception::InternalError &e) {
1366 LogDebug("DB::Crypto internal error: " << e.GetMessage());
1367 retCode = CKM_API_ERROR_DB_ERROR;
1368 } catch (const CKM::Exception &e) {
1369 LogError("CKM::Exception: " << e.GetMessage());
1370 retCode = CKM_API_ERROR_SERVER_ERROR;
1373 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1374 commandId, retCode).Pop();
1377 int CKMLogic::readCertificateHelper(
1378 const Credentials &cred,
1379 const LabelNameVector &labelNameVector,
1380 CertificateImplVector &certVector)
1383 for (auto &i: labelNameVector) {
1384 // certificates can't be protected with custom user password
1385 Crypto::GObjUPtr obj;
1387 ec = readDataHelper(true,
1389 DataType::CERTIFICATE,
1394 if (ec != CKM_API_SUCCESS)
1397 certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1399 // try to read chain certificates (if present)
1400 Crypto::GObjUPtrVector caChainObjs;
1401 ec = readDataHelper(true,
1403 DataType::DB_CHAIN_FIRST,
1408 if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1410 for(auto &caCertObj : caChainObjs)
1411 certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1413 return CKM_API_SUCCESS;
1416 int CKMLogic::getCertificateChainHelper(
1417 const CertificateImpl &cert,
1418 const RawBufferVector &untrustedCertificates,
1419 const RawBufferVector &trustedCertificates,
1420 bool useTrustedSystemCertificates,
1421 RawBufferVector &chainRawVector)
1423 CertificateImplVector untrustedCertVector;
1424 CertificateImplVector trustedCertVector;
1425 CertificateImplVector chainVector;
1428 return CKM_API_ERROR_INPUT_PARAM;
1430 for (auto &e: untrustedCertificates) {
1431 CertificateImpl c(e, DataFormat::FORM_DER);
1433 return CKM_API_ERROR_INPUT_PARAM;
1434 untrustedCertVector.push_back(std::move(c));
1436 for (auto &e: trustedCertificates) {
1437 CertificateImpl c(e, DataFormat::FORM_DER);
1439 return CKM_API_ERROR_INPUT_PARAM;
1440 trustedCertVector.push_back(std::move(c));
1443 CertificateStore store;
1444 int retCode = store.verifyCertificate(cert,
1445 untrustedCertVector,
1447 useTrustedSystemCertificates,
1448 m_accessControl.isCCMode(),
1450 if (retCode != CKM_API_SUCCESS)
1453 for (auto &e : chainVector)
1454 chainRawVector.push_back(e.getDER());
1455 return CKM_API_SUCCESS;
1458 int CKMLogic::getCertificateChainHelper(
1459 const Credentials &cred,
1460 const CertificateImpl &cert,
1461 const LabelNameVector &untrusted,
1462 const LabelNameVector &trusted,
1463 bool useTrustedSystemCertificates,
1464 RawBufferVector &chainRawVector)
1466 CertificateImplVector untrustedCertVector;
1467 CertificateImplVector trustedCertVector;
1468 CertificateImplVector chainVector;
1472 return CKM_API_ERROR_INPUT_PARAM;
1474 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1475 if (retCode != CKM_API_SUCCESS)
1477 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1478 if (retCode != CKM_API_SUCCESS)
1481 CertificateStore store;
1482 retCode = store.verifyCertificate(cert,
1483 untrustedCertVector,
1485 useTrustedSystemCertificates,
1486 m_accessControl.isCCMode(),
1488 if (retCode != CKM_API_SUCCESS)
1491 for (auto &i: chainVector)
1492 chainRawVector.push_back(i.getDER());
1494 return CKM_API_SUCCESS;
1497 RawBuffer CKMLogic::getCertificateChain(
1498 const Credentials & /*cred*/,
1500 const RawBuffer &certificate,
1501 const RawBufferVector &untrustedCertificates,
1502 const RawBufferVector &trustedCertificates,
1503 bool useTrustedSystemCertificates)
1505 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1506 RawBufferVector chainRawVector;
1507 int retCode = CKM_API_ERROR_UNKNOWN;
1509 retCode = getCertificateChainHelper(cert,
1510 untrustedCertificates,
1511 trustedCertificates,
1512 useTrustedSystemCertificates,
1514 } catch (const Exc::Exception &e) {
1515 retCode = e.error();
1516 } catch (const DB::Crypto::Exception::Base &e) {
1517 LogError("DB::Crypto failed with message: " << e.GetMessage());
1518 retCode = CKM_API_ERROR_DB_ERROR;
1519 } catch (const std::exception& e) {
1520 LogError("STD exception " << e.what());
1521 retCode = CKM_API_ERROR_SERVER_ERROR;
1523 LogError("Unknown error.");
1526 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1530 return response.Pop();
1533 RawBuffer CKMLogic::getCertificateChain(
1534 const Credentials &cred,
1536 const RawBuffer &certificate,
1537 const LabelNameVector &untrustedCertificates,
1538 const LabelNameVector &trustedCertificates,
1539 bool useTrustedSystemCertificates)
1541 int retCode = CKM_API_ERROR_UNKNOWN;
1542 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1543 RawBufferVector chainRawVector;
1545 retCode = getCertificateChainHelper(cred,
1547 untrustedCertificates,
1548 trustedCertificates,
1549 useTrustedSystemCertificates,
1551 } catch (const DB::Crypto::Exception::Base &e) {
1552 LogError("DB::Crypto failed with message: " << e.GetMessage());
1553 retCode = CKM_API_ERROR_DB_ERROR;
1554 } catch (const Exc::Exception &e) {
1555 retCode = e.error();
1556 } catch (const std::exception& e) {
1557 LogError("STD exception " << e.what());
1558 retCode = CKM_API_ERROR_SERVER_ERROR;
1560 LogError("Unknown error.");
1563 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1567 return response.Pop();
1570 RawBuffer CKMLogic::createSignature(
1571 const Credentials &cred,
1573 const Name &privateKeyName,
1574 const Label & ownerLabel,
1575 const Password &password, // password for private_key
1576 const RawBuffer &message,
1577 const CryptoAlgorithm &cryptoAlg)
1580 RawBuffer signature;
1582 int retCode = CKM_API_SUCCESS;
1585 Crypto::GObjUPtr obj;
1586 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, obj);
1587 if(retCode == CKM_API_SUCCESS) {
1588 signature = obj->sign(cryptoAlg, message);
1590 } catch (const DB::Crypto::Exception::Base &e) {
1591 LogError("DB::Crypto failed with message: " << e.GetMessage());
1592 retCode = CKM_API_ERROR_DB_ERROR;
1593 } catch (const Exc::Exception &e) {
1594 retCode = e.error();
1595 } catch (const CKM::Exception &e) {
1596 LogError("Unknown CKM::Exception: " << e.GetMessage());
1597 retCode = CKM_API_ERROR_SERVER_ERROR;
1600 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1604 return response.Pop();
1607 RawBuffer CKMLogic::verifySignature(
1608 const Credentials &cred,
1610 const Name &publicKeyOrCertName,
1611 const Label & ownerLabel,
1612 const Password &password, // password for public_key (optional)
1613 const RawBuffer &message,
1614 const RawBuffer &signature,
1615 const CryptoAlgorithm ¶ms)
1617 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1622 // try certificate first - looking for a public key.
1623 // in case of PKCS, pub key from certificate will be found first
1624 // rather than private key from the same PKCS.
1625 Crypto::GObjUPtr obj;
1626 retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, obj);
1627 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1628 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, obj);
1631 if (retCode == CKM_API_SUCCESS) {
1632 retCode = obj->verify(params, message, signature);
1634 } catch (const Exc::Exception &e) {
1635 retCode = e.error();
1636 } catch (const DB::Crypto::Exception::Base &e) {
1637 LogError("DB::Crypto failed with message: " << e.GetMessage());
1638 retCode = CKM_API_ERROR_DB_ERROR;
1639 } catch (const CKM::Exception &e) {
1640 LogError("Unknown CKM::Exception: " << e.GetMessage());
1641 retCode = CKM_API_ERROR_SERVER_ERROR;
1644 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1647 return response.Pop();
1650 int CKMLogic::setPermissionHelper(
1651 const Credentials &cred, // who's the client
1653 const Label &label, // who's the owner
1654 const Label &accessorLabel, // who will get the access
1655 const PermissionMask permissionMask)
1657 auto &handler = selectDatabase(cred, label);
1659 // we don't know the client
1660 if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1661 return CKM_API_ERROR_INPUT_PARAM;
1663 // use client label if not explicitly provided
1664 const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1666 // verify name and label are correct
1667 if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1668 return CKM_API_ERROR_INPUT_PARAM;
1670 // currently we don't support modification of owner's permissions to his own rows
1671 if (ownerLabel==accessorLabel)
1672 return CKM_API_ERROR_INPUT_PARAM;
1674 // system database does not support write/remove permissions
1675 if ((0 == ownerLabel.compare(OWNER_ID_SYSTEM)) &&
1676 (permissionMask & Permission::REMOVE))
1677 return CKM_API_ERROR_INPUT_PARAM;
1679 // can the client modify permissions to owner's row?
1680 int retCode = m_accessControl.canModify(cred, ownerLabel);
1681 if(retCode != CKM_API_SUCCESS)
1684 DB::Crypto::Transaction transaction(&handler.database);
1686 if( !handler.database.isNameLabelPresent(name, ownerLabel) )
1687 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1689 // removing non-existing permissions: fail
1690 if(permissionMask == Permission::NONE)
1692 if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1693 return CKM_API_ERROR_INPUT_PARAM;
1696 // set permissions to the row owned by ownerLabel for accessorLabel
1697 handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1698 transaction.commit();
1700 return CKM_API_SUCCESS;
1703 RawBuffer CKMLogic::setPermission(
1704 const Credentials &cred,
1709 const Label &accessorLabel,
1710 const PermissionMask permissionMask)
1714 retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1715 } catch (const Exc::Exception &e) {
1716 retCode = e.error();
1717 } Catch (CKM::Exception) {
1718 LogError("Error in set row!");
1719 retCode = CKM_API_ERROR_DB_ERROR;
1722 return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1725 int CKMLogic::loadAppKey(UserData& handle, const Label& appLabel)
1727 if (!handle.crypto.haveKey(appLabel)) {
1729 auto key_optional = handle.database.getKey(appLabel);
1731 LogError("No key for given label in database");
1732 return CKM_API_ERROR_DB_ERROR;
1734 key = *key_optional;
1735 key = handle.keyProvider.getPureDEK(key);
1736 handle.crypto.pushKey(appLabel, key);
1738 return CKM_API_SUCCESS;