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 KeyType key_type,
1168 const int additional_param,
1169 const Name &namePrivate,
1170 const Label &labelPrivate,
1171 const Name &namePublic,
1172 const Label &labelPublic,
1173 const PolicySerializable &policyPrivate,
1174 const PolicySerializable &policyPublic)
1176 CryptoAlgorithm keyGenAlgorithm;
1179 case KeyType::KEY_RSA_PUBLIC:
1180 case KeyType::KEY_RSA_PRIVATE:
1181 keyGenAlgorithm.addParam(ParamName::ALGO_TYPE, AlgoType::RSA_GEN);
1182 keyGenAlgorithm.addParam(ParamName::GEN_KEY_LEN, additional_param);
1185 case KeyType::KEY_DSA_PUBLIC:
1186 case KeyType::KEY_DSA_PRIVATE:
1187 keyGenAlgorithm.addParam(ParamName::ALGO_TYPE, AlgoType::DSA_GEN);
1188 keyGenAlgorithm.addParam(ParamName::GEN_KEY_LEN, additional_param);
1191 case KeyType::KEY_ECDSA_PUBLIC:
1192 case KeyType::KEY_ECDSA_PRIVATE:
1193 keyGenAlgorithm.addParam(ParamName::ALGO_TYPE, AlgoType::ECDSA_GEN);
1194 keyGenAlgorithm.addParam(ParamName::GEN_EC, additional_param);
1198 LogError("Invalid key_type for asymetric key generation: " << (int)key_type);
1199 return CKM_API_ERROR_INPUT_PARAM;
1202 auto &handlerPriv = selectDatabase(cred, labelPrivate);
1203 auto &handlerPub = selectDatabase(cred, labelPublic);
1205 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1206 TokenPair keys = m_decider.getStore(DataType(key_type), exportable).generateAKey(keyGenAlgorithm);
1208 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1209 // in case the same database is used for private and public - the second
1210 // transaction will not be executed
1211 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1213 int retCode = saveDataHelper(cred,
1216 keys.first.dataType,
1219 if (CKM_API_SUCCESS != retCode)
1222 retCode = saveDataHelper(cred,
1225 keys.second.dataType,
1228 if (CKM_API_SUCCESS != retCode)
1231 transactionPub.commit();
1232 transactionPriv.commit();
1233 return CKM_API_SUCCESS;
1236 RawBuffer CKMLogic::createKeyPair(
1237 const Credentials &cred,
1238 LogicCommand protocol_cmd,
1240 const int additional_param,
1241 const Name &namePrivate,
1242 const Label &labelPrivate,
1243 const Name &namePublic,
1244 const Label &labelPublic,
1245 const PolicySerializable &policyPrivate,
1246 const PolicySerializable &policyPublic)
1248 int retCode = CKM_API_SUCCESS;
1250 KeyType key_type = KeyType::KEY_NONE;
1251 switch(protocol_cmd)
1253 case LogicCommand::CREATE_KEY_PAIR_RSA:
1254 key_type = KeyType::KEY_RSA_PUBLIC;
1256 case LogicCommand::CREATE_KEY_PAIR_DSA:
1257 key_type = KeyType::KEY_DSA_PUBLIC;
1259 case LogicCommand::CREATE_KEY_PAIR_ECDSA:
1260 key_type = KeyType::KEY_ECDSA_PUBLIC;
1267 retCode = createKeyPairHelper(
1277 } catch (const Crypto::Exception::OperationNotSupported &e) {
1278 LogDebug("GStore error: operation not supported: " << e.GetMessage());
1279 retCode = CKM_API_ERROR_SERVER_ERROR;
1280 } catch (const Crypto::Exception::InternalError & e) {
1281 LogDebug("GStore key generation failed: " << e.GetMessage());
1282 retCode = CKM_API_ERROR_SERVER_ERROR;
1283 } catch( const Crypto::Exception::InputParam & e) {
1284 LogDebug("Missing or wrong input parameters: " << e.GetMessage());
1285 retCode = CKM_API_ERROR_INPUT_PARAM;
1286 } catch (DB::Crypto::Exception::TransactionError &e) {
1287 LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1288 retCode = CKM_API_ERROR_DB_ERROR;
1289 } catch (CKM::CryptoLogic::Exception::Base &e) {
1290 LogDebug("CryptoLogic error: " << e.GetMessage());
1291 retCode = CKM_API_ERROR_SERVER_ERROR;
1292 } catch (DB::Crypto::Exception::InternalError &e) {
1293 LogDebug("DB::Crypto internal error: " << e.GetMessage());
1294 retCode = CKM_API_ERROR_DB_ERROR;
1295 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1296 LogError("Error " << e.GetMessage());
1297 retCode = CKM_API_ERROR_DB_LOCKED;
1298 } catch (const CKM::Exception &e) {
1299 LogError("CKM::Exception: " << e.GetMessage());
1300 retCode = CKM_API_ERROR_SERVER_ERROR;
1303 return MessageBuffer::Serialize(static_cast<int>(protocol_cmd), commandId, retCode).Pop();
1306 int CKMLogic::readCertificateHelper(
1307 const Credentials &cred,
1308 const LabelNameVector &labelNameVector,
1309 CertificateImplVector &certVector)
1312 for (auto &i: labelNameVector) {
1313 int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), row);
1314 if (ec != CKM_API_SUCCESS)
1316 certVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
1318 // try to read chain certificates (if present)
1319 DB::RowVector rawCaChain;
1320 ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain);
1321 if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1323 for(auto &rawCaCert : rawCaChain)
1324 certVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER));
1326 return CKM_API_SUCCESS;
1329 int CKMLogic::getCertificateChainHelper(
1330 const CertificateImpl &cert,
1331 const RawBufferVector &untrustedCertificates,
1332 const RawBufferVector &trustedCertificates,
1333 bool useTrustedSystemCertificates,
1334 RawBufferVector &chainRawVector)
1336 CertificateImplVector untrustedCertVector;
1337 CertificateImplVector trustedCertVector;
1338 CertificateImplVector chainVector;
1341 return CKM_API_ERROR_INPUT_PARAM;
1343 for (auto &e: untrustedCertificates)
1344 untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1345 for (auto &e: trustedCertificates)
1346 trustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1348 CertificateStore store;
1349 int retCode = store.verifyCertificate(cert,
1350 untrustedCertVector,
1352 useTrustedSystemCertificates,
1353 m_accessControl.isCCMode(),
1355 if (retCode != CKM_API_SUCCESS)
1358 for (auto &e : chainVector)
1359 chainRawVector.push_back(e.getDER());
1360 return CKM_API_SUCCESS;
1363 int CKMLogic::getCertificateChainHelper(
1364 const Credentials &cred,
1365 const CertificateImpl &cert,
1366 const LabelNameVector &untrusted,
1367 const LabelNameVector &trusted,
1368 bool useTrustedSystemCertificates,
1369 RawBufferVector &chainRawVector)
1371 CertificateImplVector untrustedCertVector;
1372 CertificateImplVector trustedCertVector;
1373 CertificateImplVector chainVector;
1377 return CKM_API_ERROR_INPUT_PARAM;
1379 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1380 if (retCode != CKM_API_SUCCESS)
1382 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1383 if (retCode != CKM_API_SUCCESS)
1386 CertificateStore store;
1387 retCode = store.verifyCertificate(cert,
1388 untrustedCertVector,
1390 useTrustedSystemCertificates,
1391 m_accessControl.isCCMode(),
1393 if (retCode != CKM_API_SUCCESS)
1396 for (auto &i: chainVector)
1397 chainRawVector.push_back(i.getDER());
1399 return CKM_API_SUCCESS;
1402 RawBuffer CKMLogic::getCertificateChain(
1403 const Credentials & /*cred*/,
1405 const RawBuffer &certificate,
1406 const RawBufferVector &untrustedCertificates,
1407 const RawBufferVector &trustedCertificates,
1408 bool useTrustedSystemCertificates)
1410 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1411 RawBufferVector chainRawVector;
1412 int retCode = CKM_API_ERROR_UNKNOWN;
1414 retCode = getCertificateChainHelper(cert,
1415 untrustedCertificates,
1416 trustedCertificates,
1417 useTrustedSystemCertificates,
1419 } catch (const CryptoLogic::Exception::Base &e) {
1420 LogError("CryptoLogic failed with message: " << e.GetMessage());
1421 retCode = CKM_API_ERROR_SERVER_ERROR;
1422 } catch (const DB::Crypto::Exception::Base &e) {
1423 LogError("DB::Crypto failed with message: " << e.GetMessage());
1424 retCode = CKM_API_ERROR_DB_ERROR;
1425 } catch (const std::exception& e) {
1426 LogError("STD exception " << e.what());
1427 retCode = CKM_API_ERROR_SERVER_ERROR;
1429 LogError("Unknown error.");
1432 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1436 return response.Pop();
1439 RawBuffer CKMLogic::getCertificateChain(
1440 const Credentials &cred,
1442 const RawBuffer &certificate,
1443 const LabelNameVector &untrustedCertificates,
1444 const LabelNameVector &trustedCertificates,
1445 bool useTrustedSystemCertificates)
1447 int retCode = CKM_API_ERROR_UNKNOWN;
1448 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1449 RawBufferVector chainRawVector;
1451 retCode = getCertificateChainHelper(cred,
1453 untrustedCertificates,
1454 trustedCertificates,
1455 useTrustedSystemCertificates,
1457 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1458 LogError("CryptoLogic failed with message: " << e.GetMessage());
1459 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1460 } catch (const CryptoLogic::Exception::Base &e) {
1461 LogError("CryptoLogic failed with message: " << e.GetMessage());
1462 retCode = CKM_API_ERROR_SERVER_ERROR;
1463 } catch (const DB::Crypto::Exception::Base &e) {
1464 LogError("DB::Crypto failed with message: " << e.GetMessage());
1465 retCode = CKM_API_ERROR_DB_ERROR;
1466 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1467 LogError("Error " << e.GetMessage());
1468 retCode = CKM_API_ERROR_DB_LOCKED;
1469 } catch (const std::exception& e) {
1470 LogError("STD exception " << e.what());
1471 retCode = CKM_API_ERROR_SERVER_ERROR;
1473 LogError("Unknown error.");
1476 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1480 return response.Pop();
1483 RawBuffer CKMLogic::createSignature(
1484 const Credentials &cred,
1486 const Name &privateKeyName,
1487 const Label & ownerLabel,
1488 const Password &password, // password for private_key
1489 const RawBuffer &message,
1490 const HashAlgorithm hash,
1491 const RSAPaddingAlgorithm padding)
1494 RawBuffer signature;
1495 CryptoAlgorithm cryptoAlg;
1496 cryptoAlg.addParam(ParamName::SV_HASH_ALGO, hash);
1497 cryptoAlg.addParam(ParamName::SV_RSA_PADDING, padding);
1499 int retCode = CKM_API_SUCCESS;
1502 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
1503 if(retCode == CKM_API_SUCCESS) {
1504 signature = m_decider.getStore(row).getKey(row)->sign(cryptoAlg, message);
1506 } catch (const KeyProvider::Exception::Base &e) {
1507 LogError("KeyProvider failed with message: " << e.GetMessage());
1508 retCode = CKM_API_ERROR_SERVER_ERROR;
1509 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1510 LogError("CryptoLogic failed with message: " << e.GetMessage());
1511 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1512 } catch (const CryptoLogic::Exception::Base &e) {
1513 LogError("CryptoLogic failed with message: " << e.GetMessage());
1514 retCode = CKM_API_ERROR_SERVER_ERROR;
1515 } catch (const DB::Crypto::Exception::Base &e) {
1516 LogError("DB::Crypto failed with message: " << e.GetMessage());
1517 retCode = CKM_API_ERROR_DB_ERROR;
1518 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1519 LogError("Error " << e.GetMessage());
1520 retCode = CKM_API_ERROR_DB_LOCKED;
1521 } catch (const CKM::Crypto::Exception::InputParam &e) {
1522 LogError("CKM::Crypto failed with message: " << e.GetMessage());
1523 retCode = CKM_API_ERROR_INPUT_PARAM;
1524 } catch (const CKM::Crypto::Exception::Base &e) {
1525 LogError("CKM::Crypto failed with message: " << e.GetMessage());
1526 retCode = CKM_API_ERROR_SERVER_ERROR;
1527 } catch (const CKM::Exception &e) {
1528 LogError("Unknown CKM::Exception: " << e.GetMessage());
1529 retCode = CKM_API_ERROR_SERVER_ERROR;
1532 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1536 return response.Pop();
1539 RawBuffer CKMLogic::verifySignature(
1540 const Credentials &cred,
1542 const Name &publicKeyOrCertName,
1543 const Label & ownerLabel,
1544 const Password &password, // password for public_key (optional)
1545 const RawBuffer &message,
1546 const RawBuffer &signature,
1547 const HashAlgorithm hash,
1548 const RSAPaddingAlgorithm padding)
1550 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1555 CryptoAlgorithm params;
1556 params.addParam(ParamName::SV_HASH_ALGO, hash);
1557 params.addParam(ParamName::SV_RSA_PADDING, padding);
1559 // try certificate first - looking for a public key.
1560 // in case of PKCS, pub key from certificate will be found first
1561 // rather than private key from the same PKCS.
1562 retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
1563 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1564 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
1567 if (retCode == CKM_API_SUCCESS) {
1568 retCode = m_decider.getStore(row).getKey(row)->verify(params, message, signature);
1570 } catch (const Crypto::Exception::Base &e) {
1571 LogError("GStore failed with error: " << e.GetMessage());
1572 retCode = CKM_API_ERROR_SERVER_ERROR;
1573 } catch (const KeyProvider::Exception::Base &e) {
1574 LogError("KeyProvider failed with error: " << e.GetMessage());
1575 retCode = CKM_API_ERROR_SERVER_ERROR;
1576 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1577 LogError("CryptoLogic failed with message: " << e.GetMessage());
1578 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1579 } catch (const CryptoLogic::Exception::Base &e) {
1580 LogError("CryptoLogic failed with message: " << e.GetMessage());
1581 retCode = CKM_API_ERROR_SERVER_ERROR;
1582 } catch (const DB::Crypto::Exception::Base &e) {
1583 LogError("DB::Crypto failed with message: " << e.GetMessage());
1584 retCode = CKM_API_ERROR_DB_ERROR;
1585 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1586 LogError("Error " << e.GetMessage());
1587 retCode = CKM_API_ERROR_DB_LOCKED;
1588 } catch (const CKM::Exception &e) {
1589 LogError("Unknown CKM::Exception: " << e.GetMessage());
1590 retCode = CKM_API_ERROR_SERVER_ERROR;
1593 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1596 return response.Pop();
1599 int CKMLogic::setPermissionHelper(
1600 const Credentials &cred, // who's the client
1602 const Label &label, // who's the owner
1603 const Label &accessorLabel, // who will get the access
1604 const PermissionMask permissionMask)
1606 auto &handler = selectDatabase(cred, label);
1608 // we don't know the client
1609 if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1610 return CKM_API_ERROR_INPUT_PARAM;
1612 // use client label if not explicitly provided
1613 const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1615 // verify name and label are correct
1616 if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1617 return CKM_API_ERROR_INPUT_PARAM;
1619 // currently we don't support modification of owner's permissions to his own rows
1620 if (ownerLabel==accessorLabel)
1621 return CKM_API_ERROR_INPUT_PARAM;
1623 // system database does not support write/remove permissions
1624 if ((0 == ownerLabel.compare(LABEL_SYSTEM_DB)) &&
1625 (permissionMask & Permission::REMOVE))
1626 return CKM_API_ERROR_INPUT_PARAM;
1628 // can the client modify permissions to owner's row?
1629 int retCode = m_accessControl.canModify(cred, ownerLabel);
1630 if(retCode != CKM_API_SUCCESS)
1633 DB::Crypto::Transaction transaction(&handler.database);
1635 if( !handler.database.isNameLabelPresent(name, ownerLabel) )
1636 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1638 // removing non-existing permissions: fail
1639 if(permissionMask == Permission::NONE)
1641 if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1642 return CKM_API_ERROR_INPUT_PARAM;
1645 // set permissions to the row owned by ownerLabel for accessorLabel
1646 handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1647 transaction.commit();
1649 return CKM_API_SUCCESS;
1652 RawBuffer CKMLogic::setPermission(
1653 const Credentials &cred,
1658 const Label &accessorLabel,
1659 const PermissionMask permissionMask)
1663 retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1664 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1665 LogError("Error " << e.GetMessage());
1666 retCode = CKM_API_ERROR_DB_LOCKED;
1667 } Catch (CKM::Exception) {
1668 LogError("Error in set row!");
1669 retCode = CKM_API_ERROR_DB_ERROR;
1672 return MessageBuffer::Serialize(command, msgID, retCode).Pop();