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 <certificate-config.h>
31 #include <certificate-store.h>
34 #include <InitialValuesFile.h>
36 #include <generic-backend/exception.h>
39 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
40 const char * const INIT_VALUES_DIR = "/opt/data/ckm/initial_values/";
41 const char * const INIT_VALUES_XSD = "/usr/share/ckm/initial_values.xsd";
42 const char * const INIT_VALUES_FILE_SUFFIX = ".xml";
43 const char * const SYSTEM_DB_PASSWD = "cAtRugU7";
45 bool isLabelValid(const CKM::Label &label) {
46 // TODO: copy code from libprivilege control (for check smack label)
47 if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos)
52 bool isNameValid(const CKM::Name &name) {
53 if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
57 } // anonymous namespace
61 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
65 CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
67 m_accessControl.updateCCMode();
69 // make initial file list
70 std::vector<std::string> filesToParse;
71 DIR *dp = opendir(INIT_VALUES_DIR);
75 while ((entry = readdir(dp)))
77 std::string filename = std::string(entry->d_name);
80 std::string lowercaseFilename = filename;
81 std::transform(lowercaseFilename.begin(), lowercaseFilename.end(), lowercaseFilename.begin(), ::tolower);
82 if(lowercaseFilename.find(INIT_VALUES_FILE_SUFFIX) == std::string::npos)
85 filesToParse.push_back(std::string(INIT_VALUES_DIR) + filename);
91 for(const auto & file : filesToParse)
93 InitialValues::InitialValuesFile xmlFile(file.c_str(), *this);
94 int rc = xmlFile.Validate(INIT_VALUES_XSD);
95 if(rc == XML::Parser::PARSE_SUCCESS)
98 if(rc != XML::Parser::PARSE_SUCCESS)
99 LogError("invalid initial values file: " << file << ", parsing code: " << rc);
102 LogError("invalid initial values file: " << file << ", validation code: " << rc);
103 unlink(file.c_str());
107 CKMLogic::~CKMLogic(){}
109 void CKMLogic::loadDKEKFile(uid_t user, const Password &password) {
110 auto &handle = m_userDataMap[user];
114 auto wrappedDKEK = fs.getDKEK();
116 if (wrappedDKEK.empty()) {
117 wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
118 fs.saveDKEK(wrappedDKEK);
121 handle.keyProvider = KeyProvider(wrappedDKEK, password);
124 void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
125 auto &handle = m_userDataMap[user];
128 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
131 int CKMLogic::unlockDatabase(uid_t user, const Password & password)
133 if (0<m_userDataMap.count(user) && m_userDataMap[user].keyProvider.isInitialized())
134 return CKM_API_SUCCESS;
136 int retCode = CKM_API_SUCCESS;
139 auto &handle = m_userDataMap[user];
142 loadDKEKFile(user, password);
144 auto wrappedDatabaseDEK = fs.getDBDEK();
145 if (wrappedDatabaseDEK.empty()) {
146 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
147 fs.saveDBDEK(wrappedDatabaseDEK);
150 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
152 handle.database = DB::Crypto(fs.getDBPath(), key);
153 handle.crypto = CryptoLogic();
155 if ( !m_accessControl.isSystemService(user) )
157 // remove data of removed apps during locked state
158 AppLabelVector removedApps = fs.clearRemovedsApps();
159 for(auto& appSmackLabel : removedApps) {
160 handle.crypto.removeKey(appSmackLabel);
161 handle.database.deleteKey(appSmackLabel);
164 } catch (const KeyProvider::Exception::PassWordError &e) {
165 LogError("Incorrect Password " << e.GetMessage());
166 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
167 } catch (const KeyProvider::Exception::Base &e) {
168 LogError("Error in KeyProvider " << e.GetMessage());
169 retCode = CKM_API_ERROR_SERVER_ERROR;
170 } catch (const CryptoLogic::Exception::Base &e) {
171 LogError("CryptoLogic error: " << e.GetMessage());
172 retCode = CKM_API_ERROR_SERVER_ERROR;
173 } catch (const FileSystem::Exception::Base &e) {
174 LogError("FileSystem error: " << e.GetMessage());
175 retCode = CKM_API_ERROR_FILE_SYSTEM;
176 } catch (const CKM::Exception &e) {
177 LogError("CKM::Exception: " << e.GetMessage());
178 retCode = CKM_API_ERROR_SERVER_ERROR;
181 if (CKM_API_SUCCESS != retCode)
182 m_userDataMap.erase(user);
187 int CKMLogic::unlockSystemDB()
189 return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
192 UserData & CKMLogic::selectDatabase(const Credentials &cred, const Label &incoming_label)
194 // if user trying to access system service - check:
195 // * if user database is unlocked [mandatory]
196 // * if not - proceed with regular user database
197 // * if explicit system database label given -> switch to system DB
198 if ( !m_accessControl.isSystemService(cred) )
200 if (0 == m_userDataMap.count(cred.clientUid))
201 ThrowMsg(Exception::DatabaseLocked, "database with UID: " << cred.clientUid << " locked");
203 if (0 != incoming_label.compare(LABEL_SYSTEM_DB))
204 return m_userDataMap[cred.clientUid];
207 // system database selected, modify the label
208 if (CKM_API_SUCCESS != unlockSystemDB() )
209 ThrowMsg(Exception::DatabaseLocked, "can not unlock system database");
210 return m_userDataMap[SYSTEM_DB_UID];
213 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
215 int retCode = CKM_API_SUCCESS;
217 if( !m_accessControl.isSystemService(user) )
219 retCode = unlockDatabase(user, password);
223 // do not allow lock/unlock operations for system users
224 retCode = CKM_API_ERROR_INPUT_PARAM;
227 return MessageBuffer::Serialize(retCode).Pop();
230 RawBuffer CKMLogic::updateCCMode() {
231 m_accessControl.updateCCMode();
232 return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
235 RawBuffer CKMLogic::lockUserKey(uid_t user)
237 int retCode = CKM_API_SUCCESS;
238 if( !m_accessControl.isSystemService(user) )
240 m_userDataMap.erase(user);
244 // do not allow lock/unlock operations for system users
245 retCode = CKM_API_ERROR_INPUT_PARAM;
248 return MessageBuffer::Serialize(retCode).Pop();
252 RawBuffer CKMLogic::removeUserData(uid_t user) {
253 int retCode = CKM_API_SUCCESS;
255 if (m_accessControl.isSystemService(user))
256 user = SYSTEM_DB_UID;
258 m_userDataMap.erase(user);
263 return MessageBuffer::Serialize(retCode).Pop();
266 int CKMLogic::changeUserPasswordHelper(uid_t user,
267 const Password &oldPassword,
268 const Password &newPassword)
270 // do not allow to change system database password
271 if( m_accessControl.isSystemService(user) )
272 return CKM_API_ERROR_INPUT_PARAM;
274 loadDKEKFile(user, oldPassword);
275 saveDKEKFile(user, newPassword);
277 return CKM_API_SUCCESS;
280 RawBuffer CKMLogic::changeUserPassword(
282 const Password &oldPassword,
283 const Password &newPassword)
285 int retCode = CKM_API_SUCCESS;
288 retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
289 } catch (const KeyProvider::Exception::PassWordError &e) {
290 LogError("Incorrect Password " << e.GetMessage());
291 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
292 } catch (const KeyProvider::Exception::Base &e) {
293 LogError("Error in KeyProvider " << e.GetMessage());
294 retCode = CKM_API_ERROR_SERVER_ERROR;
295 } catch (const FileSystem::Exception::Base &e) {
296 LogError("Error in FileSystem " << e.GetMessage());
297 retCode = CKM_API_ERROR_FILE_SYSTEM;
298 } catch (const CKM::Exception &e) {
299 LogError("CKM::Exception: " << e.GetMessage());
300 retCode = CKM_API_ERROR_SERVER_ERROR;
303 return MessageBuffer::Serialize(retCode).Pop();
306 int CKMLogic::resetUserPasswordHelper(
308 const Password &newPassword)
310 // do not allow to reset system database password
311 if( m_accessControl.isSystemService(user) )
312 return CKM_API_ERROR_INPUT_PARAM;
314 int retCode = CKM_API_SUCCESS;
315 if (0 == m_userDataMap.count(user))
317 // Check if key exists. If exists we must return error
319 auto wrappedDKEKMain = fs.getDKEK();
320 if (!wrappedDKEKMain.empty())
321 retCode = CKM_API_ERROR_BAD_REQUEST;
323 saveDKEKFile(user, newPassword);
329 RawBuffer CKMLogic::resetUserPassword(
331 const Password &newPassword)
333 int retCode = CKM_API_SUCCESS;
335 retCode = resetUserPasswordHelper(user, newPassword);
336 } catch (const FileSystem::Exception::Base &e) {
337 LogError("Error in FileSystem " << e.GetMessage());
338 retCode = CKM_API_ERROR_FILE_SYSTEM;
339 } catch (const CKM::Exception &e) {
340 LogError("CKM::Exception: " << e.GetMessage());
341 retCode = CKM_API_ERROR_SERVER_ERROR;
344 return MessageBuffer::Serialize(retCode).Pop();
347 RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
348 int retCode = CKM_API_SUCCESS;
352 if (smackLabel.empty()) {
353 retCode = CKM_API_ERROR_INPUT_PARAM;
355 UidVector uids = FileSystem::getUIDsFromDBFile();
356 for (auto userId : uids) {
357 if (0 == m_userDataMap.count(userId)) {
358 FileSystem fs(userId);
359 fs.addRemovedApp(smackLabel);
361 auto &handle = m_userDataMap[userId];
362 handle.crypto.removeKey(smackLabel);
363 handle.database.deleteKey(smackLabel);
368 } catch (const DB::Crypto::Exception::InternalError &e) {
369 LogError("DB::Crypto couldn't remove data: " << e.GetMessage());
370 retCode = CKM_API_ERROR_DB_ERROR;
371 } catch (const DB::Crypto::Exception::TransactionError &e) {
372 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
373 retCode = CKM_API_ERROR_DB_ERROR;
374 } catch (const FileSystem::Exception::Base &e) {
375 LogError("Error in FileSystem " << e.GetMessage());
376 retCode = CKM_API_ERROR_FILE_SYSTEM;
377 } catch (const CKM::Exception &e) {
378 LogError("CKM::Exception: " << e.GetMessage());
379 retCode = CKM_API_ERROR_SERVER_ERROR;
382 return MessageBuffer::Serialize(retCode).Pop();
385 int CKMLogic::checkSaveConditions(
386 const Credentials &cred,
389 const Label &ownerLabel)
391 // verify name and label are correct
392 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
393 LogWarning("Invalid parameter passed to key-manager");
394 return CKM_API_ERROR_INPUT_PARAM;
397 // check if allowed to save using ownerLabel
398 int access_ec = m_accessControl.canSave(cred, ownerLabel);
399 if( access_ec != CKM_API_SUCCESS)
401 LogWarning("label " << cred.smackLabel << " can not save rows using label " << ownerLabel);
405 // check if not a duplicate
406 if( handler.database.isNameLabelPresent(name, ownerLabel))
407 return CKM_API_ERROR_DB_ALIAS_EXISTS;
409 // encryption section
410 if (!handler.crypto.haveKey(ownerLabel))
413 auto key_optional = handler.database.getKey(ownerLabel);
415 LogDebug("No Key in database found. Generating new one for label: " << ownerLabel);
416 got_key = handler.keyProvider.generateDEK(ownerLabel);
417 handler.database.saveKey(ownerLabel, got_key);
419 LogDebug("Key from DB");
420 got_key = *key_optional;
423 got_key = handler.keyProvider.getPureDEK(got_key);
424 handler.crypto.pushKey(ownerLabel, got_key);
427 return CKM_API_SUCCESS;
430 DB::Row CKMLogic::createEncryptedRow(
435 const RawBuffer &data,
436 const Policy &policy) const
438 DB::Row row(name, label, static_cast<int>(policy.extractable), dataType, data, static_cast<int>(data.size()));
439 row.backendId = m_decider.chooseCryptoBackend(dataType, policy.extractable);
441 // do not encrypt data with password during cc_mode on
442 if(m_accessControl.isCCMode()) {
443 crypto.encryptRow("", row);
445 crypto.encryptRow(policy.password, row);
450 int CKMLogic::verifyBinaryData(DataType dataType, RawBuffer &input_data) const
453 return toBinaryData(dataType, input_data, dummy);
456 int CKMLogic::toBinaryData(DataType dataType,
457 const RawBuffer &input_data,
458 RawBuffer &output_data) const
460 // verify the data integrity
461 if (dataType.isKey())
463 KeyShPtr output_key = CKM::Key::create(input_data);
464 if(output_key.get() == NULL)
466 LogError("provided binary data is not valid key data");
467 return CKM_API_ERROR_INPUT_PARAM;
469 output_data = output_key->getDER();
471 else if (dataType.isCertificate() || dataType.isChainCert())
473 CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
474 if(cert.get() == NULL)
476 LogError("provided binary data is not valid certificate data");
477 return CKM_API_ERROR_INPUT_PARAM;
479 output_data = cert->getDER();
482 output_data = input_data;
483 // TODO: add here BINARY_DATA verification, i.e: max size etc.
484 return CKM_API_SUCCESS;
487 int CKMLogic::verifyAndSaveDataHelper(
488 const Credentials &cred,
491 const RawBuffer &data,
493 const PolicySerializable &policy)
495 int retCode = CKM_API_ERROR_UNKNOWN;
498 // check if data is correct
499 RawBuffer binaryData;
500 retCode = toBinaryData(dataType, data, binaryData);
501 if(retCode == CKM_API_SUCCESS)
503 retCode = saveDataHelper(cred, name, label, dataType, binaryData, policy);
505 } catch (const KeyProvider::Exception::Base &e) {
506 LogError("KeyProvider failed with message: " << e.GetMessage());
507 retCode = CKM_API_ERROR_SERVER_ERROR;
508 } catch (const CryptoLogic::Exception::Base &e) {
509 LogError("CryptoLogic failed with message: " << e.GetMessage());
510 retCode = CKM_API_ERROR_SERVER_ERROR;
511 } catch (const DB::Crypto::Exception::InternalError &e) {
512 LogError("DB::Crypto failed with message: " << e.GetMessage());
513 retCode = CKM_API_ERROR_DB_ERROR;
514 } catch (const DB::Crypto::Exception::TransactionError &e) {
515 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
516 retCode = CKM_API_ERROR_DB_ERROR;
517 } catch (const FileSystem::Exception::Base &e) {
518 LogError("Error in FileSystem " << e.GetMessage());
519 retCode = CKM_API_ERROR_FILE_SYSTEM;
520 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
521 LogError("Error " << e.GetMessage());
522 retCode = CKM_API_ERROR_DB_LOCKED;
523 } catch (const CKM::Exception &e) {
524 LogError("CKM::Exception: " << e.GetMessage());
525 retCode = CKM_API_ERROR_SERVER_ERROR;
530 RawBuffer CKMLogic::saveData(
531 const Credentials &cred,
535 const RawBuffer &data,
537 const PolicySerializable &policy)
539 int retCode = verifyAndSaveDataHelper(cred, name, label, data, dataType, policy);
540 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
543 static_cast<int>(dataType));
544 return response.Pop();
547 int CKMLogic::extractPKCS12Data(
550 const Label &ownerLabel,
551 const PKCS12Serializable &pkcs,
552 const PolicySerializable &keyPolicy,
553 const PolicySerializable &certPolicy,
554 DB::RowVector &output) const
556 // private key is mandatory
558 return CKM_API_ERROR_INVALID_FORMAT;
559 Key* keyPtr = pkcs.getKey().get();
560 DataType keyType = DataType(keyPtr->getType());
561 RawBuffer keyData = keyPtr->getDER();
562 int retCode = verifyBinaryData(keyType, keyData);
563 if(retCode != CKM_API_SUCCESS)
565 output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyType, keyData, keyPolicy));
567 // certificate is mandatory
568 if( !pkcs.getCertificate() )
569 return CKM_API_ERROR_INVALID_FORMAT;
570 RawBuffer certData = pkcs.getCertificate().get()->getDER();
571 retCode = verifyBinaryData(DataType::CERTIFICATE, certData);
572 if(retCode != CKM_API_SUCCESS)
574 output.push_back(createEncryptedRow(crypto, name, ownerLabel, DataType::CERTIFICATE, certData, certPolicy));
577 unsigned int cert_index = 0;
578 for(const auto & ca : pkcs.getCaCertificateShPtrVector())
580 DataType chainDataType = DataType::getChainDatatype(cert_index ++);
581 RawBuffer caCertData = ca->getDER();
582 int retCode = verifyBinaryData(chainDataType, caCertData);
583 if(retCode != CKM_API_SUCCESS)
586 output.push_back(createEncryptedRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy));
589 return CKM_API_SUCCESS;
592 RawBuffer CKMLogic::savePKCS12(
593 const Credentials &cred,
597 const PKCS12Serializable &pkcs,
598 const PolicySerializable &keyPolicy,
599 const PolicySerializable &certPolicy)
601 int retCode = CKM_API_ERROR_UNKNOWN;
603 retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
604 } catch (const KeyProvider::Exception::Base &e) {
605 LogError("KeyProvider failed with message: " << e.GetMessage());
606 retCode = CKM_API_ERROR_SERVER_ERROR;
607 } catch (const CryptoLogic::Exception::Base &e) {
608 LogError("CryptoLogic failed with message: " << e.GetMessage());
609 retCode = CKM_API_ERROR_SERVER_ERROR;
610 } catch (const DB::Crypto::Exception::InternalError &e) {
611 LogError("DB::Crypto failed with message: " << e.GetMessage());
612 retCode = CKM_API_ERROR_DB_ERROR;
613 } catch (const DB::Crypto::Exception::TransactionError &e) {
614 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
615 retCode = CKM_API_ERROR_DB_ERROR;
616 } catch (const CKM::Exception &e) {
617 LogError("CKM::Exception: " << e.GetMessage());
618 retCode = CKM_API_ERROR_SERVER_ERROR;
621 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
624 return response.Pop();
628 int CKMLogic::removeDataHelper(
629 const Credentials &cred,
633 auto &handler = selectDatabase(cred, label);
635 // use client label if not explicitly provided
636 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
637 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
638 LogError("Invalid label or name format");
639 return CKM_API_ERROR_INPUT_PARAM;
642 DB::Crypto::Transaction transaction(&handler.database);
644 // read and check permissions
645 PermissionMaskOptional permissionRowOpt =
646 handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel);
647 int retCode = m_accessControl.canDelete(cred,
648 PermissionForLabel(cred.smackLabel, permissionRowOpt));
649 if(retCode != CKM_API_SUCCESS)
651 LogWarning("access control check result: " << retCode);
655 auto erased = handler.database.deleteRow(name, ownerLabel);
656 // check if the data existed or not
658 transaction.commit();
660 LogError("No row for given name and label");
661 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
664 return CKM_API_SUCCESS;
667 RawBuffer CKMLogic::removeData(
668 const Credentials &cred,
673 int retCode = CKM_API_ERROR_UNKNOWN;
677 retCode = removeDataHelper(cred, name, label);
679 catch (const CKMLogic::Exception::DatabaseLocked &e)
681 LogError("Error " << e.GetMessage());
682 retCode = CKM_API_ERROR_DB_LOCKED;
684 catch (const CKM::Exception &)
686 LogError("Error in deleting row!");
687 retCode = CKM_API_ERROR_DB_ERROR;
690 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
693 return response.Pop();
696 int CKMLogic::readSingleRow(const Name &name,
697 const Label &ownerLabel,
699 DB::Crypto & database,
702 DB::Crypto::RowOptional row_optional;
703 if (dataType.isKey())
705 // read all key types
706 row_optional = database.getRow(name,
708 DataType::DB_KEY_FIRST,
709 DataType::DB_KEY_LAST);
711 // read anything else
712 row_optional = database.getRow(name,
718 LogError("No row for given name, label and type");
719 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
724 return CKM_API_SUCCESS;
728 int CKMLogic::readMultiRow(const Name &name,
729 const Label &ownerLabel,
731 DB::Crypto & database,
732 DB::RowVector &output)
734 if (dataType.isKey())
736 // read all key types
737 database.getRows(name,
739 DataType::DB_KEY_FIRST,
740 DataType::DB_KEY_LAST,
743 else if (dataType.isChainCert())
745 // read all key types
746 database.getRows(name,
748 DataType::DB_CHAIN_FIRST,
749 DataType::DB_CHAIN_LAST,
754 // read anything else
755 database.getRows(name,
762 LogError("No row for given name, label and type");
763 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
766 return CKM_API_SUCCESS;
769 int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
771 const Label &ownerLabel,
772 const Label &accessorLabel,
775 DB::Crypto & database)
777 PermissionMaskOptional permissionRowOpt =
778 database.getPermissionRow(name, ownerLabel, accessorLabel);
781 return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt));
782 return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt));
785 int CKMLogic::readDataHelper(
787 const Credentials &cred,
791 const Password &password,
794 auto &handler = selectDatabase(cred, label);
796 // use client label if not explicitly provided
797 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
799 if (!isNameValid(name) || !isLabelValid(ownerLabel))
800 return CKM_API_ERROR_INPUT_PARAM;
803 DB::Crypto::Transaction transaction(&handler.database);
804 int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
805 if(CKM_API_SUCCESS != retCode)
808 // all read rows belong to the same owner
809 DB::Row & firstRow = rows.at(0);
811 // check access rights
812 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database);
813 if(CKM_API_SUCCESS != retCode)
817 if (!handler.crypto.haveKey(firstRow.ownerLabel)) {
819 auto key_optional = handler.database.getKey(firstRow.ownerLabel);
821 LogError("No key for given label in database");
822 return CKM_API_ERROR_DB_ERROR;
825 key = handler.keyProvider.getPureDEK(key);
826 handler.crypto.pushKey(firstRow.ownerLabel, key);
828 for(auto &row : rows)
829 handler.crypto.decryptRow(password, row);
831 return CKM_API_SUCCESS;
834 int CKMLogic::readDataHelper(
836 const Credentials &cred,
840 const Password &password,
843 auto &handler = selectDatabase(cred, label);
845 // use client label if not explicitly provided
846 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
848 if (!isNameValid(name) || !isLabelValid(ownerLabel))
849 return CKM_API_ERROR_INPUT_PARAM;
852 DB::Crypto::Transaction transaction(&handler.database);
853 int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
854 if(CKM_API_SUCCESS != retCode)
857 // check access rights
858 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
859 if(CKM_API_SUCCESS != retCode)
863 if (!handler.crypto.haveKey(row.ownerLabel)) {
865 auto key_optional = handler.database.getKey(row.ownerLabel);
867 LogError("No key for given label in database");
868 return CKM_API_ERROR_DB_ERROR;
871 key = handler.keyProvider.getPureDEK(key);
872 handler.crypto.pushKey(row.ownerLabel, key);
874 handler.crypto.decryptRow(password, row);
876 return CKM_API_SUCCESS;
879 RawBuffer CKMLogic::getData(
880 const Credentials &cred,
885 const Password &password)
887 int retCode = CKM_API_SUCCESS;
891 retCode = readDataHelper(true, cred, dataType, name, label, password, row);
892 } catch (const KeyProvider::Exception::Base &e) {
893 LogError("KeyProvider failed with error: " << e.GetMessage());
894 retCode = CKM_API_ERROR_SERVER_ERROR;
895 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
896 LogError("CryptoLogic failed with message: " << e.GetMessage());
897 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
898 } catch (const CryptoLogic::Exception::Base &e) {
899 LogError("CryptoLogic failed with message: " << e.GetMessage());
900 retCode = CKM_API_ERROR_SERVER_ERROR;
901 } catch (const DB::Crypto::Exception::Base &e) {
902 LogError("DB::Crypto failed with message: " << e.GetMessage());
903 retCode = CKM_API_ERROR_DB_ERROR;
904 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
905 LogError("Error " << e.GetMessage());
906 retCode = CKM_API_ERROR_DB_LOCKED;
907 } catch (const CKM::Exception &e) {
908 LogError("CKM::Exception: " << e.GetMessage());
909 retCode = CKM_API_ERROR_SERVER_ERROR;
912 if (CKM_API_SUCCESS != retCode) {
914 row.dataType = dataType;
917 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
920 static_cast<int>(row.dataType),
922 return response.Pop();
925 int CKMLogic::getPKCS12Helper(
926 const Credentials &cred,
929 const Password &keyPassword,
930 const Password &certPassword,
932 CertificateShPtr & cert,
933 CertificateShPtrVector & caChain)
937 // read private key (mandatory)
939 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, privKeyRow);
940 if(retCode != CKM_API_SUCCESS)
942 privKey = CKM::Key::create(privKeyRow.data);
944 // read certificate (mandatory)
946 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certRow);
947 if(retCode != CKM_API_SUCCESS)
949 cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER);
951 // read CA cert chain (optional)
952 DB::RowVector rawCaChain;
953 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, rawCaChain);
954 if(retCode != CKM_API_SUCCESS &&
955 retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
957 for(auto &rawCaCert : rawCaChain)
958 caChain.push_back(CKM::Certificate::create(rawCaCert.data, DataFormat::FORM_DER));
960 // if anything found, return it
961 if(privKey || cert || caChain.size()>0)
962 retCode = CKM_API_SUCCESS;
967 RawBuffer CKMLogic::getPKCS12(
968 const Credentials &cred,
972 const Password &keyPassword,
973 const Password &certPassword)
975 int retCode = CKM_API_ERROR_UNKNOWN;
977 PKCS12Serializable output;
980 CertificateShPtr cert;
981 CertificateShPtrVector caChain;
982 retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey, cert, caChain);
985 if(retCode == CKM_API_SUCCESS)
986 output = PKCS12Serializable(privKey, cert, caChain);
988 } catch (const KeyProvider::Exception::Base &e) {
989 LogError("KeyProvider failed with error: " << e.GetMessage());
990 retCode = CKM_API_ERROR_SERVER_ERROR;
991 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
992 LogError("CryptoLogic failed with message: " << e.GetMessage());
993 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
994 } catch (const CryptoLogic::Exception::Base &e) {
995 LogError("CryptoLogic failed with message: " << e.GetMessage());
996 retCode = CKM_API_ERROR_SERVER_ERROR;
997 } catch (const DB::Crypto::Exception::Base &e) {
998 LogError("DB::Crypto failed with message: " << e.GetMessage());
999 retCode = CKM_API_ERROR_DB_ERROR;
1000 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1001 LogError("Error " << e.GetMessage());
1002 retCode = CKM_API_ERROR_DB_LOCKED;
1003 } catch (const CKM::Exception &e) {
1004 LogError("CKM::Exception: " << e.GetMessage());
1005 retCode = CKM_API_ERROR_SERVER_ERROR;
1008 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
1012 return response.Pop();
1015 int CKMLogic::getDataListHelper(const Credentials &cred,
1016 const DataType dataType,
1017 LabelNameVector &labelNameVector)
1019 int retCode = CKM_API_ERROR_DB_LOCKED;
1020 if (0 < m_userDataMap.count(cred.clientUid))
1022 auto &database = m_userDataMap[cred.clientUid].database;
1025 LabelNameVector tmpVector;
1026 if (dataType.isKey()) {
1027 // list all key types
1028 database.listNames(cred.smackLabel,
1030 DataType::DB_KEY_FIRST,
1031 DataType::DB_KEY_LAST);
1033 // list anything else
1034 database.listNames(cred.smackLabel,
1038 labelNameVector.insert(labelNameVector.end(), tmpVector.begin(), tmpVector.end());
1039 retCode = CKM_API_SUCCESS;
1041 Catch (CKM::Exception) {
1042 LogError("Failed to get names");
1043 retCode = CKM_API_ERROR_DB_ERROR;
1049 RawBuffer CKMLogic::getDataList(
1050 const Credentials &cred,
1054 LabelNameVector systemVector;
1055 LabelNameVector userVector;
1056 LabelNameVector labelNameVector;
1058 int retCode = unlockSystemDB();
1059 if (CKM_API_SUCCESS == retCode)
1062 if (m_accessControl.isSystemService(cred))
1065 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1072 // user - lookup system, then client DB
1073 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1079 if(retCode == CKM_API_SUCCESS)
1081 retCode = getDataListHelper(cred,
1088 if(retCode == CKM_API_SUCCESS)
1090 labelNameVector.insert(labelNameVector.end(), systemVector.begin(), systemVector.end());
1091 labelNameVector.insert(labelNameVector.end(), userVector.begin(), userVector.end());
1093 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
1096 static_cast<int>(dataType),
1098 return response.Pop();
1101 int CKMLogic::saveDataHelper(
1102 const Credentials &cred,
1106 const RawBuffer &data,
1107 const PolicySerializable &policy)
1109 auto &handler = selectDatabase(cred, label);
1111 // use client label if not explicitly provided
1112 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1113 if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
1114 return CKM_API_ERROR_INPUT_PARAM;
1116 // check if save is possible
1117 DB::Crypto::Transaction transaction(&handler.database);
1118 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1119 if(retCode != CKM_API_SUCCESS)
1123 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, dataType, data, policy);
1124 handler.database.saveRow(encryptedRow);
1126 transaction.commit();
1127 return CKM_API_SUCCESS;
1130 int CKMLogic::saveDataHelper(
1131 const Credentials &cred,
1134 const PKCS12Serializable &pkcs,
1135 const PolicySerializable &keyPolicy,
1136 const PolicySerializable &certPolicy)
1138 auto &handler = selectDatabase(cred, label);
1140 // use client label if not explicitly provided
1141 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1142 if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
1143 return CKM_API_ERROR_INPUT_PARAM;
1145 // check if save is possible
1146 DB::Crypto::Transaction transaction(&handler.database);
1147 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1148 if(retCode != CKM_API_SUCCESS)
1151 // extract and encrypt the data
1152 DB::RowVector encryptedRows;
1153 retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
1154 if(retCode != CKM_API_SUCCESS)
1158 handler.database.saveRows(name, ownerLabel, encryptedRows);
1159 transaction.commit();
1161 return CKM_API_SUCCESS;
1165 int CKMLogic::createKeyPairHelper(
1166 const Credentials &cred,
1167 const CryptoAlgorithmSerializable & keyGenParams,
1168 const Name &namePrivate,
1169 const Label &labelPrivate,
1170 const Name &namePublic,
1171 const Label &labelPublic,
1172 const PolicySerializable &policyPrivate,
1173 const PolicySerializable &policyPublic)
1175 auto &handlerPriv = selectDatabase(cred, labelPrivate);
1176 auto &handlerPub = selectDatabase(cred, labelPublic);
1178 AlgoType keyType = AlgoType::RSA_GEN;
1179 if(!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1180 ThrowMsg(Crypto::Exception::InputParam, "Error, parameter ALGO_TYPE not found.");
1181 DataType dt(keyType);
1183 ThrowMsg(Crypto::Exception::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1185 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1186 TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams);
1188 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1189 // in case the same database is used for private and public - the second
1190 // transaction will not be executed
1191 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1193 int retCode = saveDataHelper(cred,
1196 keys.first.dataType,
1199 if (CKM_API_SUCCESS != retCode)
1202 retCode = saveDataHelper(cred,
1205 keys.second.dataType,
1208 if (CKM_API_SUCCESS != retCode)
1211 transactionPub.commit();
1212 transactionPriv.commit();
1213 return CKM_API_SUCCESS;
1216 RawBuffer CKMLogic::createKeyPair(
1217 const Credentials &cred,
1219 const CryptoAlgorithmSerializable & keyGenParams,
1220 const Name &namePrivate,
1221 const Label &labelPrivate,
1222 const Name &namePublic,
1223 const Label &labelPublic,
1224 const PolicySerializable &policyPrivate,
1225 const PolicySerializable &policyPublic)
1227 int retCode = CKM_API_SUCCESS;
1230 retCode = createKeyPairHelper(
1239 } catch (const Crypto::Exception::OperationNotSupported &e) {
1240 LogDebug("GStore error: operation not supported: " << e.GetMessage());
1241 retCode = CKM_API_ERROR_SERVER_ERROR;
1242 } catch (const Crypto::Exception::InternalError & e) {
1243 LogDebug("GStore key generation failed: " << e.GetMessage());
1244 retCode = CKM_API_ERROR_SERVER_ERROR;
1245 } catch( const Crypto::Exception::InputParam & e) {
1246 LogDebug("Missing or wrong input parameters: " << e.GetMessage());
1247 retCode = CKM_API_ERROR_INPUT_PARAM;
1248 } catch (DB::Crypto::Exception::TransactionError &e) {
1249 LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1250 retCode = CKM_API_ERROR_DB_ERROR;
1251 } catch (CKM::CryptoLogic::Exception::Base &e) {
1252 LogDebug("CryptoLogic error: " << e.GetMessage());
1253 retCode = CKM_API_ERROR_SERVER_ERROR;
1254 } catch (DB::Crypto::Exception::InternalError &e) {
1255 LogDebug("DB::Crypto internal error: " << e.GetMessage());
1256 retCode = CKM_API_ERROR_DB_ERROR;
1257 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1258 LogError("Error " << e.GetMessage());
1259 retCode = CKM_API_ERROR_DB_LOCKED;
1260 } catch (const CKM::Exception &e) {
1261 LogError("CKM::Exception: " << e.GetMessage());
1262 retCode = CKM_API_ERROR_SERVER_ERROR;
1265 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1266 commandId, retCode).Pop();
1269 int CKMLogic::readCertificateHelper(
1270 const Credentials &cred,
1271 const LabelNameVector &labelNameVector,
1272 CertificateImplVector &certVector)
1275 for (auto &i: labelNameVector) {
1276 int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), row);
1277 if (ec != CKM_API_SUCCESS)
1279 certVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
1281 // try to read chain certificates (if present)
1282 DB::RowVector rawCaChain;
1283 ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain);
1284 if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1286 for(auto &rawCaCert : rawCaChain)
1287 certVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER));
1289 return CKM_API_SUCCESS;
1292 int CKMLogic::getCertificateChainHelper(
1293 const CertificateImpl &cert,
1294 const RawBufferVector &untrustedCertificates,
1295 const RawBufferVector &trustedCertificates,
1296 bool useTrustedSystemCertificates,
1297 RawBufferVector &chainRawVector)
1299 CertificateImplVector untrustedCertVector;
1300 CertificateImplVector trustedCertVector;
1301 CertificateImplVector chainVector;
1304 return CKM_API_ERROR_INPUT_PARAM;
1306 for (auto &e: untrustedCertificates)
1307 untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1308 for (auto &e: trustedCertificates)
1309 trustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1311 CertificateStore store;
1312 int retCode = store.verifyCertificate(cert,
1313 untrustedCertVector,
1315 useTrustedSystemCertificates,
1316 m_accessControl.isCCMode(),
1318 if (retCode != CKM_API_SUCCESS)
1321 for (auto &e : chainVector)
1322 chainRawVector.push_back(e.getDER());
1323 return CKM_API_SUCCESS;
1326 int CKMLogic::getCertificateChainHelper(
1327 const Credentials &cred,
1328 const CertificateImpl &cert,
1329 const LabelNameVector &untrusted,
1330 const LabelNameVector &trusted,
1331 bool useTrustedSystemCertificates,
1332 RawBufferVector &chainRawVector)
1334 CertificateImplVector untrustedCertVector;
1335 CertificateImplVector trustedCertVector;
1336 CertificateImplVector chainVector;
1340 return CKM_API_ERROR_INPUT_PARAM;
1342 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1343 if (retCode != CKM_API_SUCCESS)
1345 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1346 if (retCode != CKM_API_SUCCESS)
1349 CertificateStore store;
1350 retCode = store.verifyCertificate(cert,
1351 untrustedCertVector,
1353 useTrustedSystemCertificates,
1354 m_accessControl.isCCMode(),
1356 if (retCode != CKM_API_SUCCESS)
1359 for (auto &i: chainVector)
1360 chainRawVector.push_back(i.getDER());
1362 return CKM_API_SUCCESS;
1365 RawBuffer CKMLogic::getCertificateChain(
1366 const Credentials & /*cred*/,
1368 const RawBuffer &certificate,
1369 const RawBufferVector &untrustedCertificates,
1370 const RawBufferVector &trustedCertificates,
1371 bool useTrustedSystemCertificates)
1373 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1374 RawBufferVector chainRawVector;
1375 int retCode = CKM_API_ERROR_UNKNOWN;
1377 retCode = getCertificateChainHelper(cert,
1378 untrustedCertificates,
1379 trustedCertificates,
1380 useTrustedSystemCertificates,
1382 } catch (const CryptoLogic::Exception::Base &e) {
1383 LogError("CryptoLogic failed with message: " << e.GetMessage());
1384 retCode = CKM_API_ERROR_SERVER_ERROR;
1385 } catch (const DB::Crypto::Exception::Base &e) {
1386 LogError("DB::Crypto failed with message: " << e.GetMessage());
1387 retCode = CKM_API_ERROR_DB_ERROR;
1388 } catch (const std::exception& e) {
1389 LogError("STD exception " << e.what());
1390 retCode = CKM_API_ERROR_SERVER_ERROR;
1392 LogError("Unknown error.");
1395 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1399 return response.Pop();
1402 RawBuffer CKMLogic::getCertificateChain(
1403 const Credentials &cred,
1405 const RawBuffer &certificate,
1406 const LabelNameVector &untrustedCertificates,
1407 const LabelNameVector &trustedCertificates,
1408 bool useTrustedSystemCertificates)
1410 int retCode = CKM_API_ERROR_UNKNOWN;
1411 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1412 RawBufferVector chainRawVector;
1414 retCode = getCertificateChainHelper(cred,
1416 untrustedCertificates,
1417 trustedCertificates,
1418 useTrustedSystemCertificates,
1420 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1421 LogError("CryptoLogic failed with message: " << e.GetMessage());
1422 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1423 } catch (const CryptoLogic::Exception::Base &e) {
1424 LogError("CryptoLogic failed with message: " << e.GetMessage());
1425 retCode = CKM_API_ERROR_SERVER_ERROR;
1426 } catch (const DB::Crypto::Exception::Base &e) {
1427 LogError("DB::Crypto failed with message: " << e.GetMessage());
1428 retCode = CKM_API_ERROR_DB_ERROR;
1429 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1430 LogError("Error " << e.GetMessage());
1431 retCode = CKM_API_ERROR_DB_LOCKED;
1432 } catch (const std::exception& e) {
1433 LogError("STD exception " << e.what());
1434 retCode = CKM_API_ERROR_SERVER_ERROR;
1436 LogError("Unknown error.");
1439 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1443 return response.Pop();
1446 RawBuffer CKMLogic::createSignature(
1447 const Credentials &cred,
1449 const Name &privateKeyName,
1450 const Label & ownerLabel,
1451 const Password &password, // password for private_key
1452 const RawBuffer &message,
1453 const HashAlgorithm hash,
1454 const RSAPaddingAlgorithm padding)
1457 RawBuffer signature;
1458 CryptoAlgorithm cryptoAlg;
1459 cryptoAlg.addParam(ParamName::SV_HASH_ALGO, hash);
1460 cryptoAlg.addParam(ParamName::SV_RSA_PADDING, padding);
1462 int retCode = CKM_API_SUCCESS;
1465 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
1466 if(retCode == CKM_API_SUCCESS) {
1467 signature = m_decider.getStore(row).getKey(row)->sign(cryptoAlg, message);
1469 } catch (const KeyProvider::Exception::Base &e) {
1470 LogError("KeyProvider failed with message: " << e.GetMessage());
1471 retCode = CKM_API_ERROR_SERVER_ERROR;
1472 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1473 LogError("CryptoLogic failed with message: " << e.GetMessage());
1474 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1475 } catch (const CryptoLogic::Exception::Base &e) {
1476 LogError("CryptoLogic failed with message: " << e.GetMessage());
1477 retCode = CKM_API_ERROR_SERVER_ERROR;
1478 } catch (const DB::Crypto::Exception::Base &e) {
1479 LogError("DB::Crypto failed with message: " << e.GetMessage());
1480 retCode = CKM_API_ERROR_DB_ERROR;
1481 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1482 LogError("Error " << e.GetMessage());
1483 retCode = CKM_API_ERROR_DB_LOCKED;
1484 } catch (const CKM::Crypto::Exception::InputParam &e) {
1485 LogError("CKM::Crypto failed with message: " << e.GetMessage());
1486 retCode = CKM_API_ERROR_INPUT_PARAM;
1487 } catch (const CKM::Crypto::Exception::Base &e) {
1488 LogError("CKM::Crypto failed with message: " << e.GetMessage());
1489 retCode = CKM_API_ERROR_SERVER_ERROR;
1490 } catch (const CKM::Exception &e) {
1491 LogError("Unknown CKM::Exception: " << e.GetMessage());
1492 retCode = CKM_API_ERROR_SERVER_ERROR;
1495 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1499 return response.Pop();
1502 RawBuffer CKMLogic::verifySignature(
1503 const Credentials &cred,
1505 const Name &publicKeyOrCertName,
1506 const Label & ownerLabel,
1507 const Password &password, // password for public_key (optional)
1508 const RawBuffer &message,
1509 const RawBuffer &signature,
1510 const HashAlgorithm hash,
1511 const RSAPaddingAlgorithm padding)
1513 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1518 CryptoAlgorithm params;
1519 params.addParam(ParamName::SV_HASH_ALGO, hash);
1520 params.addParam(ParamName::SV_RSA_PADDING, padding);
1522 // try certificate first - looking for a public key.
1523 // in case of PKCS, pub key from certificate will be found first
1524 // rather than private key from the same PKCS.
1525 retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
1526 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1527 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
1530 if (retCode == CKM_API_SUCCESS) {
1531 retCode = m_decider.getStore(row).getKey(row)->verify(params, message, signature);
1533 } catch (const Crypto::Exception::Base &e) {
1534 LogError("GStore failed with error: " << e.GetMessage());
1535 retCode = CKM_API_ERROR_SERVER_ERROR;
1536 } catch (const KeyProvider::Exception::Base &e) {
1537 LogError("KeyProvider failed with error: " << e.GetMessage());
1538 retCode = CKM_API_ERROR_SERVER_ERROR;
1539 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1540 LogError("CryptoLogic failed with message: " << e.GetMessage());
1541 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1542 } catch (const CryptoLogic::Exception::Base &e) {
1543 LogError("CryptoLogic failed with message: " << e.GetMessage());
1544 retCode = CKM_API_ERROR_SERVER_ERROR;
1545 } catch (const DB::Crypto::Exception::Base &e) {
1546 LogError("DB::Crypto failed with message: " << e.GetMessage());
1547 retCode = CKM_API_ERROR_DB_ERROR;
1548 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1549 LogError("Error " << e.GetMessage());
1550 retCode = CKM_API_ERROR_DB_LOCKED;
1551 } catch (const CKM::Exception &e) {
1552 LogError("Unknown CKM::Exception: " << e.GetMessage());
1553 retCode = CKM_API_ERROR_SERVER_ERROR;
1556 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1559 return response.Pop();
1562 int CKMLogic::setPermissionHelper(
1563 const Credentials &cred, // who's the client
1565 const Label &label, // who's the owner
1566 const Label &accessorLabel, // who will get the access
1567 const PermissionMask permissionMask)
1569 auto &handler = selectDatabase(cred, label);
1571 // we don't know the client
1572 if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1573 return CKM_API_ERROR_INPUT_PARAM;
1575 // use client label if not explicitly provided
1576 const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1578 // verify name and label are correct
1579 if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1580 return CKM_API_ERROR_INPUT_PARAM;
1582 // currently we don't support modification of owner's permissions to his own rows
1583 if (ownerLabel==accessorLabel)
1584 return CKM_API_ERROR_INPUT_PARAM;
1586 // system database does not support write/remove permissions
1587 if ((0 == ownerLabel.compare(LABEL_SYSTEM_DB)) &&
1588 (permissionMask & Permission::REMOVE))
1589 return CKM_API_ERROR_INPUT_PARAM;
1591 // can the client modify permissions to owner's row?
1592 int retCode = m_accessControl.canModify(cred, ownerLabel);
1593 if(retCode != CKM_API_SUCCESS)
1596 DB::Crypto::Transaction transaction(&handler.database);
1598 if( !handler.database.isNameLabelPresent(name, ownerLabel) )
1599 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1601 // removing non-existing permissions: fail
1602 if(permissionMask == Permission::NONE)
1604 if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1605 return CKM_API_ERROR_INPUT_PARAM;
1608 // set permissions to the row owned by ownerLabel for accessorLabel
1609 handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1610 transaction.commit();
1612 return CKM_API_SUCCESS;
1615 RawBuffer CKMLogic::setPermission(
1616 const Credentials &cred,
1621 const Label &accessorLabel,
1622 const PermissionMask permissionMask)
1626 retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1627 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1628 LogError("Error " << e.GetMessage());
1629 retCode = CKM_API_ERROR_DB_LOCKED;
1630 } Catch (CKM::Exception) {
1631 LogError("Error in set row!");
1632 retCode = CKM_API_ERROR_DB_ERROR;
1635 return MessageBuffer::Serialize(command, msgID, retCode).Pop();