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>
37 #include <sw-backend/crypto-service.h>
40 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
41 const char * const INIT_VALUES_DIR = "/opt/data/ckm/initial_values/";
42 const char * const INIT_VALUES_XSD = "/opt/data/ckm/initial_values/initial_values.xsd";
43 const char * const INIT_VALUES_FILE_SUFFIX = ".xml";
44 const char * const SYSTEM_DB_PASSWD = "cAtRugU7";
46 bool isLabelValid(const CKM::Label &label) {
47 // TODO: copy code from libprivilege control (for check smack label)
48 if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos)
53 bool isNameValid(const CKM::Name &name) {
54 if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
58 } // anonymous namespace
62 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
66 CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
68 m_accessControl.updateCCMode();
70 // make initial file list
71 std::vector<std::string> filesToParse;
72 DIR *dp = opendir(INIT_VALUES_DIR);
76 while ((entry = readdir(dp)))
78 std::string filename = std::string(entry->d_name);
81 std::string lowercaseFilename = filename;
82 std::transform(lowercaseFilename.begin(), lowercaseFilename.end(), lowercaseFilename.begin(), ::tolower);
83 if(lowercaseFilename.find(INIT_VALUES_FILE_SUFFIX) == std::string::npos)
86 filesToParse.push_back(std::string(INIT_VALUES_DIR) + filename);
92 for(const auto & file : filesToParse)
94 InitialValues::InitialValuesFile xmlFile(file.c_str(), *this);
95 int rc = xmlFile.Validate(INIT_VALUES_XSD);
96 if(rc == XML::Parser::PARSE_SUCCESS)
99 if(rc != XML::Parser::PARSE_SUCCESS)
100 LogError("invalid initial values file: " << file << ", parsing code: " << rc);
103 LogError("invalid initial values file: " << file << ", validation code: " << rc);
104 unlink(file.c_str());
108 CKMLogic::~CKMLogic(){}
110 void CKMLogic::loadDKEKFile(uid_t user, const Password &password) {
111 auto &handle = m_userDataMap[user];
115 auto wrappedDKEK = fs.getDKEK();
117 if (wrappedDKEK.empty()) {
118 wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
119 fs.saveDKEK(wrappedDKEK);
122 handle.keyProvider = KeyProvider(wrappedDKEK, password);
125 void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
126 auto &handle = m_userDataMap[user];
129 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
132 int CKMLogic::unlockDatabase(uid_t user, const Password & password)
134 if (0<m_userDataMap.count(user) && m_userDataMap[user].keyProvider.isInitialized())
135 return CKM_API_SUCCESS;
137 int retCode = CKM_API_SUCCESS;
140 auto &handle = m_userDataMap[user];
143 loadDKEKFile(user, password);
145 auto wrappedDatabaseDEK = fs.getDBDEK();
146 if (wrappedDatabaseDEK.empty()) {
147 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
148 fs.saveDBDEK(wrappedDatabaseDEK);
151 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
153 handle.database = DB::Crypto(fs.getDBPath(), key);
154 handle.crypto = CryptoLogic();
156 if ( !m_accessControl.isSystemService(user) )
158 // remove data of removed apps during locked state
159 AppLabelVector removedApps = fs.clearRemovedsApps();
160 for(auto& appSmackLabel : removedApps) {
161 handle.crypto.removeKey(appSmackLabel);
162 handle.database.deleteKey(appSmackLabel);
165 } catch (const KeyProvider::Exception::PassWordError &e) {
166 LogError("Incorrect Password " << e.GetMessage());
167 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
168 } catch (const KeyProvider::Exception::Base &e) {
169 LogError("Error in KeyProvider " << e.GetMessage());
170 retCode = CKM_API_ERROR_SERVER_ERROR;
171 } catch (const CryptoLogic::Exception::Base &e) {
172 LogError("CryptoLogic error: " << e.GetMessage());
173 retCode = CKM_API_ERROR_SERVER_ERROR;
174 } catch (const FileSystem::Exception::Base &e) {
175 LogError("FileSystem error: " << e.GetMessage());
176 retCode = CKM_API_ERROR_FILE_SYSTEM;
177 } catch (const CKM::Exception &e) {
178 LogError("CKM::Exception: " << e.GetMessage());
179 retCode = CKM_API_ERROR_SERVER_ERROR;
182 if (CKM_API_SUCCESS != retCode)
183 m_userDataMap.erase(user);
188 int CKMLogic::unlockSystemDB()
190 return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
193 UserData & CKMLogic::selectDatabase(const Credentials &cred, const Label &incoming_label)
195 // if user trying to access system service - check:
196 // * if user database is unlocked [mandatory]
197 // * if not - proceed with regular user database
198 // * if explicit system database label given -> switch to system DB
199 if ( !m_accessControl.isSystemService(cred) )
201 if (0 == m_userDataMap.count(cred.clientUid))
202 ThrowMsg(Exception::DatabaseLocked, "database with UID: " << cred.clientUid << " locked");
204 if (0 != incoming_label.compare(LABEL_SYSTEM_DB))
205 return m_userDataMap[cred.clientUid];
208 // system database selected, modify the label
209 if (CKM_API_SUCCESS != unlockSystemDB() )
210 ThrowMsg(Exception::DatabaseLocked, "can not unlock system database");
211 return m_userDataMap[SYSTEM_DB_UID];
214 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
216 int retCode = CKM_API_SUCCESS;
218 if( !m_accessControl.isSystemService(user) )
220 retCode = unlockDatabase(user, password);
224 // do not allow lock/unlock operations for system users
225 retCode = CKM_API_ERROR_INPUT_PARAM;
228 return MessageBuffer::Serialize(retCode).Pop();
231 RawBuffer CKMLogic::updateCCMode() {
232 m_accessControl.updateCCMode();
233 return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
236 RawBuffer CKMLogic::lockUserKey(uid_t user)
238 int retCode = CKM_API_SUCCESS;
239 if( !m_accessControl.isSystemService(user) )
241 m_userDataMap.erase(user);
245 // do not allow lock/unlock operations for system users
246 retCode = CKM_API_ERROR_INPUT_PARAM;
249 return MessageBuffer::Serialize(retCode).Pop();
253 RawBuffer CKMLogic::removeUserData(uid_t user) {
254 int retCode = CKM_API_SUCCESS;
256 if (m_accessControl.isSystemService(user))
257 user = SYSTEM_DB_UID;
259 m_userDataMap.erase(user);
264 return MessageBuffer::Serialize(retCode).Pop();
267 int CKMLogic::changeUserPasswordHelper(uid_t user,
268 const Password &oldPassword,
269 const Password &newPassword)
271 // do not allow to change system database password
272 if( m_accessControl.isSystemService(user) )
273 return CKM_API_ERROR_INPUT_PARAM;
275 loadDKEKFile(user, oldPassword);
276 saveDKEKFile(user, newPassword);
278 return CKM_API_SUCCESS;
281 RawBuffer CKMLogic::changeUserPassword(
283 const Password &oldPassword,
284 const Password &newPassword)
286 int retCode = CKM_API_SUCCESS;
289 retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
290 } catch (const KeyProvider::Exception::PassWordError &e) {
291 LogError("Incorrect Password " << e.GetMessage());
292 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
293 } catch (const KeyProvider::Exception::Base &e) {
294 LogError("Error in KeyProvider " << e.GetMessage());
295 retCode = CKM_API_ERROR_SERVER_ERROR;
296 } catch (const FileSystem::Exception::Base &e) {
297 LogError("Error in FileSystem " << e.GetMessage());
298 retCode = CKM_API_ERROR_FILE_SYSTEM;
299 } catch (const CKM::Exception &e) {
300 LogError("CKM::Exception: " << e.GetMessage());
301 retCode = CKM_API_ERROR_SERVER_ERROR;
304 return MessageBuffer::Serialize(retCode).Pop();
307 int CKMLogic::resetUserPasswordHelper(
309 const Password &newPassword)
311 // do not allow to reset system database password
312 if( m_accessControl.isSystemService(user) )
313 return CKM_API_ERROR_INPUT_PARAM;
315 int retCode = CKM_API_SUCCESS;
316 if (0 == m_userDataMap.count(user))
318 // Check if key exists. If exists we must return error
320 auto wrappedDKEKMain = fs.getDKEK();
321 if (!wrappedDKEKMain.empty())
322 retCode = CKM_API_ERROR_BAD_REQUEST;
324 saveDKEKFile(user, newPassword);
330 RawBuffer CKMLogic::resetUserPassword(
332 const Password &newPassword)
334 int retCode = CKM_API_SUCCESS;
336 retCode = resetUserPasswordHelper(user, newPassword);
337 } catch (const FileSystem::Exception::Base &e) {
338 LogError("Error in FileSystem " << e.GetMessage());
339 retCode = CKM_API_ERROR_FILE_SYSTEM;
340 } catch (const CKM::Exception &e) {
341 LogError("CKM::Exception: " << e.GetMessage());
342 retCode = CKM_API_ERROR_SERVER_ERROR;
345 return MessageBuffer::Serialize(retCode).Pop();
348 RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
349 int retCode = CKM_API_SUCCESS;
353 if (smackLabel.empty()) {
354 retCode = CKM_API_ERROR_INPUT_PARAM;
356 UidVector uids = FileSystem::getUIDsFromDBFile();
357 for (auto userId : uids) {
358 if (0 == m_userDataMap.count(userId)) {
359 FileSystem fs(userId);
360 fs.addRemovedApp(smackLabel);
362 auto &handle = m_userDataMap[userId];
363 handle.crypto.removeKey(smackLabel);
364 handle.database.deleteKey(smackLabel);
369 } catch (const DB::Crypto::Exception::InternalError &e) {
370 LogError("DB::Crypto couldn't remove data: " << e.GetMessage());
371 retCode = CKM_API_ERROR_DB_ERROR;
372 } catch (const DB::Crypto::Exception::TransactionError &e) {
373 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
374 retCode = CKM_API_ERROR_DB_ERROR;
375 } catch (const FileSystem::Exception::Base &e) {
376 LogError("Error in FileSystem " << e.GetMessage());
377 retCode = CKM_API_ERROR_FILE_SYSTEM;
378 } catch (const CKM::Exception &e) {
379 LogError("CKM::Exception: " << e.GetMessage());
380 retCode = CKM_API_ERROR_SERVER_ERROR;
383 return MessageBuffer::Serialize(retCode).Pop();
386 int CKMLogic::checkSaveConditions(
387 const Credentials &cred,
390 const Label &ownerLabel)
392 // verify name and label are correct
393 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
394 LogWarning("Invalid parameter passed to key-manager");
395 return CKM_API_ERROR_INPUT_PARAM;
398 // check if allowed to save using ownerLabel
399 int access_ec = m_accessControl.canSave(cred, ownerLabel);
400 if( access_ec != CKM_API_SUCCESS)
402 LogWarning("label " << cred.smackLabel << " can not save rows using label " << ownerLabel);
406 // check if not a duplicate
407 if( handler.database.isNameLabelPresent(name, ownerLabel))
408 return CKM_API_ERROR_DB_ALIAS_EXISTS;
410 // encryption section
411 if (!handler.crypto.haveKey(ownerLabel))
414 auto key_optional = handler.database.getKey(ownerLabel);
416 LogDebug("No Key in database found. Generating new one for label: " << ownerLabel);
417 got_key = handler.keyProvider.generateDEK(ownerLabel);
418 handler.database.saveKey(ownerLabel, got_key);
420 LogDebug("Key from DB");
421 got_key = *key_optional;
424 got_key = handler.keyProvider.getPureDEK(got_key);
425 handler.crypto.pushKey(ownerLabel, got_key);
428 return CKM_API_SUCCESS;
431 DB::Row CKMLogic::createEncryptedRow(
436 const RawBuffer &data,
437 const Policy &policy) const
439 DB::Row row(name, label, static_cast<int>(policy.extractable), dataType, data, static_cast<int>(data.size()));
440 row.backendId = m_decider.chooseCryptoBackend(dataType, policy);
442 // do not encrypt data with password during cc_mode on
443 if(m_accessControl.isCCMode()) {
444 crypto.encryptRow("", row);
446 crypto.encryptRow(policy.password, row);
451 int CKMLogic::verifyBinaryData(DataType dataType, RawBuffer &input_data) const
454 return toBinaryData(dataType, input_data, dummy);
457 int CKMLogic::toBinaryData(DataType dataType,
458 const RawBuffer &input_data,
459 RawBuffer &output_data) const
461 // verify the data integrity
462 if (dataType.isKey())
464 KeyShPtr output_key = CKM::Key::create(input_data);
465 if(output_key.get() == NULL)
467 LogError("provided binary data is not valid key data");
468 return CKM_API_ERROR_INPUT_PARAM;
470 output_data = output_key->getDER();
472 else if (dataType.isCertificate() || dataType.isChainCert())
474 CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
475 if(cert.get() == NULL)
477 LogError("provided binary data is not valid certificate data");
478 return CKM_API_ERROR_INPUT_PARAM;
480 output_data = cert->getDER();
483 output_data = input_data;
484 // TODO: add here BINARY_DATA verification, i.e: max size etc.
485 return CKM_API_SUCCESS;
488 int CKMLogic::verifyAndSaveDataHelper(
489 const Credentials &cred,
492 const RawBuffer &data,
494 const PolicySerializable &policy)
496 int retCode = CKM_API_ERROR_UNKNOWN;
499 // check if data is correct
500 RawBuffer binaryData;
501 retCode = toBinaryData(dataType, data, binaryData);
502 if(retCode == CKM_API_SUCCESS)
504 retCode = saveDataHelper(cred, name, label, dataType, binaryData, policy);
506 } catch (const KeyProvider::Exception::Base &e) {
507 LogError("KeyProvider failed with message: " << e.GetMessage());
508 retCode = CKM_API_ERROR_SERVER_ERROR;
509 } catch (const CryptoLogic::Exception::Base &e) {
510 LogError("CryptoLogic failed with message: " << e.GetMessage());
511 retCode = CKM_API_ERROR_SERVER_ERROR;
512 } catch (const DB::Crypto::Exception::InternalError &e) {
513 LogError("DB::Crypto failed with message: " << e.GetMessage());
514 retCode = CKM_API_ERROR_DB_ERROR;
515 } catch (const DB::Crypto::Exception::TransactionError &e) {
516 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
517 retCode = CKM_API_ERROR_DB_ERROR;
518 } catch (const FileSystem::Exception::Base &e) {
519 LogError("Error in FileSystem " << e.GetMessage());
520 retCode = CKM_API_ERROR_FILE_SYSTEM;
521 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
522 LogError("Error " << e.GetMessage());
523 retCode = CKM_API_ERROR_DB_LOCKED;
524 } catch (const CKM::Exception &e) {
525 LogError("CKM::Exception: " << e.GetMessage());
526 retCode = CKM_API_ERROR_SERVER_ERROR;
531 RawBuffer CKMLogic::saveData(
532 const Credentials &cred,
536 const RawBuffer &data,
538 const PolicySerializable &policy)
540 int retCode = verifyAndSaveDataHelper(cred, name, label, data, dataType, policy);
541 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
544 static_cast<int>(dataType));
545 return response.Pop();
548 int CKMLogic::extractPKCS12Data(
551 const Label &ownerLabel,
552 const PKCS12Serializable &pkcs,
553 const PolicySerializable &keyPolicy,
554 const PolicySerializable &certPolicy,
555 DB::RowVector &output) const
557 // private key is mandatory
559 return CKM_API_ERROR_INVALID_FORMAT;
560 Key* keyPtr = pkcs.getKey().get();
561 DataType keyType = DataType(keyPtr->getType());
562 RawBuffer keyData = keyPtr->getDER();
563 int retCode = verifyBinaryData(keyType, keyData);
564 if(retCode != CKM_API_SUCCESS)
566 output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyType, keyData, keyPolicy));
568 // certificate is mandatory
569 if( !pkcs.getCertificate() )
570 return CKM_API_ERROR_INVALID_FORMAT;
571 RawBuffer certData = pkcs.getCertificate().get()->getDER();
572 retCode = verifyBinaryData(DataType::CERTIFICATE, certData);
573 if(retCode != CKM_API_SUCCESS)
575 output.push_back(createEncryptedRow(crypto, name, ownerLabel, DataType::CERTIFICATE, certData, certPolicy));
578 unsigned int cert_index = 0;
579 for(const auto & ca : pkcs.getCaCertificateShPtrVector())
581 DataType chainDataType = DataType::getChainDatatype(cert_index ++);
582 RawBuffer caCertData = ca->getDER();
583 int retCode = verifyBinaryData(chainDataType, caCertData);
584 if(retCode != CKM_API_SUCCESS)
587 output.push_back(createEncryptedRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy));
590 return CKM_API_SUCCESS;
593 RawBuffer CKMLogic::savePKCS12(
594 const Credentials &cred,
598 const PKCS12Serializable &pkcs,
599 const PolicySerializable &keyPolicy,
600 const PolicySerializable &certPolicy)
602 int retCode = CKM_API_ERROR_UNKNOWN;
604 retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
605 } catch (const KeyProvider::Exception::Base &e) {
606 LogError("KeyProvider failed with message: " << e.GetMessage());
607 retCode = CKM_API_ERROR_SERVER_ERROR;
608 } catch (const CryptoLogic::Exception::Base &e) {
609 LogError("CryptoLogic failed with message: " << e.GetMessage());
610 retCode = CKM_API_ERROR_SERVER_ERROR;
611 } catch (const DB::Crypto::Exception::InternalError &e) {
612 LogError("DB::Crypto failed with message: " << e.GetMessage());
613 retCode = CKM_API_ERROR_DB_ERROR;
614 } catch (const DB::Crypto::Exception::TransactionError &e) {
615 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
616 retCode = CKM_API_ERROR_DB_ERROR;
617 } catch (const CKM::Exception &e) {
618 LogError("CKM::Exception: " << e.GetMessage());
619 retCode = CKM_API_ERROR_SERVER_ERROR;
622 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
625 return response.Pop();
629 int CKMLogic::removeDataHelper(
630 const Credentials &cred,
634 auto &handler = selectDatabase(cred, label);
636 // use client label if not explicitly provided
637 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
638 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
639 LogError("Invalid label or name format");
640 return CKM_API_ERROR_INPUT_PARAM;
643 DB::Crypto::Transaction transaction(&handler.database);
645 // read and check permissions
646 PermissionMaskOptional permissionRowOpt =
647 handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel);
648 int retCode = m_accessControl.canDelete(cred,
649 PermissionForLabel(cred.smackLabel, permissionRowOpt));
650 if(retCode != CKM_API_SUCCESS)
652 LogWarning("access control check result: " << retCode);
656 auto erased = handler.database.deleteRow(name, ownerLabel);
657 // check if the data existed or not
659 transaction.commit();
661 LogError("No row for given name and label");
662 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
665 return CKM_API_SUCCESS;
668 RawBuffer CKMLogic::removeData(
669 const Credentials &cred,
674 int retCode = CKM_API_ERROR_UNKNOWN;
678 retCode = removeDataHelper(cred, name, label);
680 catch (const CKMLogic::Exception::DatabaseLocked &e)
682 LogError("Error " << e.GetMessage());
683 retCode = CKM_API_ERROR_DB_LOCKED;
685 catch (const CKM::Exception &)
687 LogError("Error in deleting row!");
688 retCode = CKM_API_ERROR_DB_ERROR;
691 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
694 return response.Pop();
697 int CKMLogic::readSingleRow(const Name &name,
698 const Label &ownerLabel,
700 DB::Crypto & database,
703 DB::Crypto::RowOptional row_optional;
704 if (dataType.isKey())
706 // read all key types
707 row_optional = database.getRow(name,
709 DataType::DB_KEY_FIRST,
710 DataType::DB_KEY_LAST);
712 // read anything else
713 row_optional = database.getRow(name,
719 LogError("No row for given name, label and type");
720 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
725 return CKM_API_SUCCESS;
729 int CKMLogic::readMultiRow(const Name &name,
730 const Label &ownerLabel,
732 DB::Crypto & database,
733 DB::RowVector &output)
735 if (dataType.isKey())
737 // read all key types
738 database.getRows(name,
740 DataType::DB_KEY_FIRST,
741 DataType::DB_KEY_LAST,
744 else if (dataType.isChainCert())
746 // read all key types
747 database.getRows(name,
749 DataType::DB_CHAIN_FIRST,
750 DataType::DB_CHAIN_LAST,
755 // read anything else
756 database.getRows(name,
763 LogError("No row for given name, label and type");
764 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
767 return CKM_API_SUCCESS;
770 int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
772 const Label &ownerLabel,
773 const Label &accessorLabel,
776 DB::Crypto & database)
778 PermissionMaskOptional permissionRowOpt =
779 database.getPermissionRow(name, ownerLabel, accessorLabel);
782 return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt));
783 return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt));
786 int CKMLogic::readDataHelper(
788 const Credentials &cred,
792 const Password &password,
795 auto &handler = selectDatabase(cred, label);
797 // use client label if not explicitly provided
798 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
800 if (!isNameValid(name) || !isLabelValid(ownerLabel))
801 return CKM_API_ERROR_INPUT_PARAM;
804 DB::Crypto::Transaction transaction(&handler.database);
805 int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
806 if(CKM_API_SUCCESS != retCode)
809 // all read rows belong to the same owner
810 DB::Row & firstRow = rows.at(0);
812 // check access rights
813 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database);
814 if(CKM_API_SUCCESS != retCode)
818 if (!handler.crypto.haveKey(firstRow.ownerLabel)) {
820 auto key_optional = handler.database.getKey(firstRow.ownerLabel);
822 LogError("No key for given label in database");
823 return CKM_API_ERROR_DB_ERROR;
826 key = handler.keyProvider.getPureDEK(key);
827 handler.crypto.pushKey(firstRow.ownerLabel, key);
829 for(auto &row : rows)
830 handler.crypto.decryptRow(password, row);
832 return CKM_API_SUCCESS;
835 int CKMLogic::readDataHelper(
837 const Credentials &cred,
841 const Password &password,
844 auto &handler = selectDatabase(cred, label);
846 // use client label if not explicitly provided
847 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
849 if (!isNameValid(name) || !isLabelValid(ownerLabel))
850 return CKM_API_ERROR_INPUT_PARAM;
853 DB::Crypto::Transaction transaction(&handler.database);
854 int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
855 if(CKM_API_SUCCESS != retCode)
858 // check access rights
859 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
860 if(CKM_API_SUCCESS != retCode)
864 if (!handler.crypto.haveKey(row.ownerLabel)) {
866 auto key_optional = handler.database.getKey(row.ownerLabel);
868 LogError("No key for given label in database");
869 return CKM_API_ERROR_DB_ERROR;
872 key = handler.keyProvider.getPureDEK(key);
873 handler.crypto.pushKey(row.ownerLabel, key);
875 handler.crypto.decryptRow(password, row);
877 return CKM_API_SUCCESS;
880 RawBuffer CKMLogic::getData(
881 const Credentials &cred,
886 const Password &password)
888 int retCode = CKM_API_SUCCESS;
892 retCode = readDataHelper(true, cred, dataType, name, label, password, row);
893 } catch (const KeyProvider::Exception::Base &e) {
894 LogError("KeyProvider failed with error: " << e.GetMessage());
895 retCode = CKM_API_ERROR_SERVER_ERROR;
896 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
897 LogError("CryptoLogic failed with message: " << e.GetMessage());
898 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
899 } catch (const CryptoLogic::Exception::Base &e) {
900 LogError("CryptoLogic failed with message: " << e.GetMessage());
901 retCode = CKM_API_ERROR_SERVER_ERROR;
902 } catch (const DB::Crypto::Exception::Base &e) {
903 LogError("DB::Crypto failed with message: " << e.GetMessage());
904 retCode = CKM_API_ERROR_DB_ERROR;
905 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
906 LogError("Error " << e.GetMessage());
907 retCode = CKM_API_ERROR_DB_LOCKED;
908 } catch (const CKM::Exception &e) {
909 LogError("CKM::Exception: " << e.GetMessage());
910 retCode = CKM_API_ERROR_SERVER_ERROR;
913 if (CKM_API_SUCCESS != retCode) {
915 row.dataType = dataType;
918 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
921 static_cast<int>(row.dataType),
923 return response.Pop();
926 int CKMLogic::getPKCS12Helper(
927 const Credentials &cred,
930 const Password &keyPassword,
931 const Password &certPassword,
933 CertificateShPtr & cert,
934 CertificateShPtrVector & caChain)
938 // read private key (mandatory)
940 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, privKeyRow);
941 if(retCode != CKM_API_SUCCESS)
943 privKey = CKM::Key::create(privKeyRow.data);
945 // read certificate (mandatory)
947 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certRow);
948 if(retCode != CKM_API_SUCCESS)
950 cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER);
952 // read CA cert chain (optional)
953 DB::RowVector rawCaChain;
954 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, rawCaChain);
955 if(retCode != CKM_API_SUCCESS &&
956 retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
958 for(auto &rawCaCert : rawCaChain)
959 caChain.push_back(CKM::Certificate::create(rawCaCert.data, DataFormat::FORM_DER));
961 // if anything found, return it
962 if(privKey || cert || caChain.size()>0)
963 retCode = CKM_API_SUCCESS;
968 RawBuffer CKMLogic::getPKCS12(
969 const Credentials &cred,
973 const Password &keyPassword,
974 const Password &certPassword)
976 int retCode = CKM_API_ERROR_UNKNOWN;
978 PKCS12Serializable output;
981 CertificateShPtr cert;
982 CertificateShPtrVector caChain;
983 retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey, cert, caChain);
986 if(retCode == CKM_API_SUCCESS)
987 output = PKCS12Serializable(privKey, cert, caChain);
989 } catch (const KeyProvider::Exception::Base &e) {
990 LogError("KeyProvider failed with error: " << e.GetMessage());
991 retCode = CKM_API_ERROR_SERVER_ERROR;
992 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
993 LogError("CryptoLogic failed with message: " << e.GetMessage());
994 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
995 } catch (const CryptoLogic::Exception::Base &e) {
996 LogError("CryptoLogic failed with message: " << e.GetMessage());
997 retCode = CKM_API_ERROR_SERVER_ERROR;
998 } catch (const DB::Crypto::Exception::Base &e) {
999 LogError("DB::Crypto failed with message: " << e.GetMessage());
1000 retCode = CKM_API_ERROR_DB_ERROR;
1001 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1002 LogError("Error " << e.GetMessage());
1003 retCode = CKM_API_ERROR_DB_LOCKED;
1004 } catch (const CKM::Exception &e) {
1005 LogError("CKM::Exception: " << e.GetMessage());
1006 retCode = CKM_API_ERROR_SERVER_ERROR;
1009 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
1013 return response.Pop();
1016 int CKMLogic::getDataListHelper(const Credentials &cred,
1017 const DataType dataType,
1018 LabelNameVector &labelNameVector)
1020 int retCode = CKM_API_ERROR_DB_LOCKED;
1021 if (0 < m_userDataMap.count(cred.clientUid))
1023 auto &database = m_userDataMap[cred.clientUid].database;
1026 LabelNameVector tmpVector;
1027 if (dataType.isKey()) {
1028 // list all key types
1029 database.listNames(cred.smackLabel,
1031 DataType::DB_KEY_FIRST,
1032 DataType::DB_KEY_LAST);
1034 // list anything else
1035 database.listNames(cred.smackLabel,
1039 labelNameVector.insert(labelNameVector.end(), tmpVector.begin(), tmpVector.end());
1040 retCode = CKM_API_SUCCESS;
1042 Catch (CKM::Exception) {
1043 LogError("Failed to get names");
1044 retCode = CKM_API_ERROR_DB_ERROR;
1050 RawBuffer CKMLogic::getDataList(
1051 const Credentials &cred,
1055 LabelNameVector systemVector;
1056 LabelNameVector userVector;
1057 LabelNameVector labelNameVector;
1059 int retCode = unlockSystemDB();
1060 if (CKM_API_SUCCESS == retCode)
1063 if (m_accessControl.isSystemService(cred))
1066 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1073 // user - lookup system, then client DB
1074 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1080 if(retCode == CKM_API_SUCCESS)
1082 retCode = getDataListHelper(cred,
1089 if(retCode == CKM_API_SUCCESS)
1091 labelNameVector.insert(labelNameVector.end(), systemVector.begin(), systemVector.end());
1092 labelNameVector.insert(labelNameVector.end(), userVector.begin(), userVector.end());
1094 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
1097 static_cast<int>(dataType),
1099 return response.Pop();
1102 int CKMLogic::saveDataHelper(
1103 const Credentials &cred,
1107 const RawBuffer &data,
1108 const PolicySerializable &policy)
1110 auto &handler = selectDatabase(cred, label);
1112 // use client label if not explicitly provided
1113 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1114 if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
1115 return CKM_API_ERROR_INPUT_PARAM;
1117 // check if save is possible
1118 DB::Crypto::Transaction transaction(&handler.database);
1119 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1120 if(retCode != CKM_API_SUCCESS)
1124 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, dataType, data, policy);
1125 handler.database.saveRow(encryptedRow);
1127 transaction.commit();
1128 return CKM_API_SUCCESS;
1131 int CKMLogic::saveDataHelper(
1132 const Credentials &cred,
1135 const PKCS12Serializable &pkcs,
1136 const PolicySerializable &keyPolicy,
1137 const PolicySerializable &certPolicy)
1139 auto &handler = selectDatabase(cred, label);
1141 // use client label if not explicitly provided
1142 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1143 if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
1144 return CKM_API_ERROR_INPUT_PARAM;
1146 // check if save is possible
1147 DB::Crypto::Transaction transaction(&handler.database);
1148 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1149 if(retCode != CKM_API_SUCCESS)
1152 // extract and encrypt the data
1153 DB::RowVector encryptedRows;
1154 retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
1155 if(retCode != CKM_API_SUCCESS)
1159 handler.database.saveRows(name, ownerLabel, encryptedRows);
1160 transaction.commit();
1162 return CKM_API_SUCCESS;
1166 int CKMLogic::createKeyPairHelper(
1167 const Credentials &cred,
1168 const KeyType key_type,
1169 const int additional_param,
1170 const Name &namePrivate,
1171 const Label &labelPrivate,
1172 const Name &namePublic,
1173 const Label &labelPublic,
1174 const PolicySerializable &policyPrivate,
1175 const PolicySerializable &policyPublic)
1177 auto &handlerPriv = selectDatabase(cred, labelPrivate);
1178 auto &handlerPub = selectDatabase(cred, labelPublic);
1185 case KeyType::KEY_RSA_PUBLIC:
1186 case KeyType::KEY_RSA_PRIVATE:
1187 retCode = Crypto::SW::CryptoService::createKeyPairRSA(additional_param, prv, pub);
1190 case KeyType::KEY_DSA_PUBLIC:
1191 case KeyType::KEY_DSA_PRIVATE:
1192 retCode = Crypto::SW::CryptoService::createKeyPairDSA(additional_param, prv, pub);
1195 case KeyType::KEY_ECDSA_PUBLIC:
1196 case KeyType::KEY_ECDSA_PRIVATE:
1197 retCode = Crypto::SW::CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(additional_param), prv, pub);
1201 return CKM_API_ERROR_INPUT_PARAM;
1204 if (CKM_CRYPTO_CREATEKEY_SUCCESS != retCode)
1206 LogDebug("CryptoService error with code: " << retCode);
1207 return CKM_API_ERROR_SERVER_ERROR; // TODO error code
1210 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1211 // in case the same database is used for private and public - the second
1212 // transaction will not be executed
1213 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1215 retCode = saveDataHelper(cred,
1218 DataType(prv.getType()),
1221 if (CKM_API_SUCCESS != retCode)
1224 retCode = saveDataHelper(cred,
1227 DataType(pub.getType()),
1230 if (CKM_API_SUCCESS != retCode)
1233 transactionPub.commit();
1234 transactionPriv.commit();
1239 RawBuffer CKMLogic::createKeyPair(
1240 const Credentials &cred,
1241 LogicCommand protocol_cmd,
1243 const int additional_param,
1244 const Name &namePrivate,
1245 const Label &labelPrivate,
1246 const Name &namePublic,
1247 const Label &labelPublic,
1248 const PolicySerializable &policyPrivate,
1249 const PolicySerializable &policyPublic)
1251 int retCode = CKM_API_SUCCESS;
1253 KeyType key_type = KeyType::KEY_NONE;
1254 switch(protocol_cmd)
1256 case LogicCommand::CREATE_KEY_PAIR_RSA:
1257 key_type = KeyType::KEY_RSA_PUBLIC;
1259 case LogicCommand::CREATE_KEY_PAIR_DSA:
1260 key_type = KeyType::KEY_DSA_PUBLIC;
1262 case LogicCommand::CREATE_KEY_PAIR_ECDSA:
1263 key_type = KeyType::KEY_ECDSA_PUBLIC;
1270 retCode = createKeyPairHelper(
1280 } catch (DB::Crypto::Exception::TransactionError &e) {
1281 LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1282 retCode = CKM_API_ERROR_DB_ERROR;
1283 } catch (CKM::CryptoLogic::Exception::Base &e) {
1284 LogDebug("CryptoLogic error: " << e.GetMessage());
1285 retCode = CKM_API_ERROR_SERVER_ERROR;
1286 } catch (DB::Crypto::Exception::InternalError &e) {
1287 LogDebug("DB::Crypto internal error: " << e.GetMessage());
1288 retCode = CKM_API_ERROR_DB_ERROR;
1289 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1290 LogError("Error " << e.GetMessage());
1291 retCode = CKM_API_ERROR_DB_LOCKED;
1292 } catch (const CKM::Exception &e) {
1293 LogError("CKM::Exception: " << e.GetMessage());
1294 retCode = CKM_API_ERROR_SERVER_ERROR;
1297 return MessageBuffer::Serialize(static_cast<int>(protocol_cmd), commandId, retCode).Pop();
1300 int CKMLogic::readCertificateHelper(
1301 const Credentials &cred,
1302 const LabelNameVector &labelNameVector,
1303 CertificateImplVector &certVector)
1306 for (auto &i: labelNameVector) {
1307 int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), row);
1308 if (ec != CKM_API_SUCCESS)
1310 certVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
1312 // try to read chain certificates (if present)
1313 DB::RowVector rawCaChain;
1314 ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain);
1315 if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1317 for(auto &rawCaCert : rawCaChain)
1318 certVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER));
1320 return CKM_API_SUCCESS;
1323 int CKMLogic::getCertificateChainHelper(
1324 const CertificateImpl &cert,
1325 const RawBufferVector &untrustedCertificates,
1326 const RawBufferVector &trustedCertificates,
1327 bool useTrustedSystemCertificates,
1328 RawBufferVector &chainRawVector)
1330 CertificateImplVector untrustedCertVector;
1331 CertificateImplVector trustedCertVector;
1332 CertificateImplVector chainVector;
1335 return CKM_API_ERROR_INPUT_PARAM;
1337 for (auto &e: untrustedCertificates)
1338 untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1339 for (auto &e: trustedCertificates)
1340 trustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1342 CertificateStore store;
1343 int retCode = store.verifyCertificate(cert,
1344 untrustedCertVector,
1346 useTrustedSystemCertificates,
1347 m_accessControl.isCCMode(),
1349 if (retCode != CKM_API_SUCCESS)
1352 for (auto &e : chainVector)
1353 chainRawVector.push_back(e.getDER());
1354 return CKM_API_SUCCESS;
1357 int CKMLogic::getCertificateChainHelper(
1358 const Credentials &cred,
1359 const CertificateImpl &cert,
1360 const LabelNameVector &untrusted,
1361 const LabelNameVector &trusted,
1362 bool useTrustedSystemCertificates,
1363 RawBufferVector &chainRawVector)
1365 CertificateImplVector untrustedCertVector;
1366 CertificateImplVector trustedCertVector;
1367 CertificateImplVector chainVector;
1371 return CKM_API_ERROR_INPUT_PARAM;
1373 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1374 if (retCode != CKM_API_SUCCESS)
1376 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1377 if (retCode != CKM_API_SUCCESS)
1380 CertificateStore store;
1381 retCode = store.verifyCertificate(cert,
1382 untrustedCertVector,
1384 useTrustedSystemCertificates,
1385 m_accessControl.isCCMode(),
1387 if (retCode != CKM_API_SUCCESS)
1390 for (auto &i: chainVector)
1391 chainRawVector.push_back(i.getDER());
1393 return CKM_API_SUCCESS;
1396 RawBuffer CKMLogic::getCertificateChain(
1397 const Credentials & /*cred*/,
1399 const RawBuffer &certificate,
1400 const RawBufferVector &untrustedCertificates,
1401 const RawBufferVector &trustedCertificates,
1402 bool useTrustedSystemCertificates)
1404 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1405 RawBufferVector chainRawVector;
1406 int retCode = CKM_API_ERROR_UNKNOWN;
1408 retCode = getCertificateChainHelper(cert,
1409 untrustedCertificates,
1410 trustedCertificates,
1411 useTrustedSystemCertificates,
1413 } catch (const CryptoLogic::Exception::Base &e) {
1414 LogError("CryptoLogic failed with message: " << e.GetMessage());
1415 retCode = CKM_API_ERROR_SERVER_ERROR;
1416 } catch (const DB::Crypto::Exception::Base &e) {
1417 LogError("DB::Crypto failed with message: " << e.GetMessage());
1418 retCode = CKM_API_ERROR_DB_ERROR;
1419 } catch (const std::exception& e) {
1420 LogError("STD exception " << e.what());
1421 retCode = CKM_API_ERROR_SERVER_ERROR;
1423 LogError("Unknown error.");
1426 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1430 return response.Pop();
1433 RawBuffer CKMLogic::getCertificateChain(
1434 const Credentials &cred,
1436 const RawBuffer &certificate,
1437 const LabelNameVector &untrustedCertificates,
1438 const LabelNameVector &trustedCertificates,
1439 bool useTrustedSystemCertificates)
1441 int retCode = CKM_API_ERROR_UNKNOWN;
1442 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1443 RawBufferVector chainRawVector;
1445 retCode = getCertificateChainHelper(cred,
1447 untrustedCertificates,
1448 trustedCertificates,
1449 useTrustedSystemCertificates,
1451 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1452 LogError("CryptoLogic failed with message: " << e.GetMessage());
1453 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1454 } catch (const CryptoLogic::Exception::Base &e) {
1455 LogError("CryptoLogic failed with message: " << e.GetMessage());
1456 retCode = CKM_API_ERROR_SERVER_ERROR;
1457 } catch (const DB::Crypto::Exception::Base &e) {
1458 LogError("DB::Crypto failed with message: " << e.GetMessage());
1459 retCode = CKM_API_ERROR_DB_ERROR;
1460 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1461 LogError("Error " << e.GetMessage());
1462 retCode = CKM_API_ERROR_DB_LOCKED;
1463 } catch (const std::exception& e) {
1464 LogError("STD exception " << e.what());
1465 retCode = CKM_API_ERROR_SERVER_ERROR;
1467 LogError("Unknown error.");
1470 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1474 return response.Pop();
1477 RawBuffer CKMLogic::createSignature(
1478 const Credentials &cred,
1480 const Name &privateKeyName,
1481 const Label & ownerLabel,
1482 const Password &password, // password for private_key
1483 const RawBuffer &message,
1484 const HashAlgorithm hash,
1485 const RSAPaddingAlgorithm padding)
1488 RawBuffer signature;
1489 CryptoAlgorithm cryptoAlg;
1490 cryptoAlg.addParam(ParamName::SV_HASH_ALGO, hash);
1491 cryptoAlg.addParam(ParamName::SV_RSA_PADDING, padding);
1493 int retCode = CKM_API_SUCCESS;
1496 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
1497 if(retCode == CKM_API_SUCCESS) {
1498 signature = m_decider.getStore(row).getKey(row)->sign(cryptoAlg, message);
1500 } catch (const KeyProvider::Exception::Base &e) {
1501 LogError("KeyProvider failed with message: " << e.GetMessage());
1502 retCode = CKM_API_ERROR_SERVER_ERROR;
1503 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1504 LogError("CryptoLogic failed with message: " << e.GetMessage());
1505 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1506 } catch (const CryptoLogic::Exception::Base &e) {
1507 LogError("CryptoLogic failed with message: " << e.GetMessage());
1508 retCode = CKM_API_ERROR_SERVER_ERROR;
1509 } catch (const DB::Crypto::Exception::Base &e) {
1510 LogError("DB::Crypto failed with message: " << e.GetMessage());
1511 retCode = CKM_API_ERROR_DB_ERROR;
1512 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1513 LogError("Error " << e.GetMessage());
1514 retCode = CKM_API_ERROR_DB_LOCKED;
1515 } catch (const CKM::Crypto::Exception::InputParam &e) {
1516 LogError("CKM::Crypto failed with message: " << e.GetMessage());
1517 retCode = CKM_API_ERROR_INPUT_PARAM;
1518 } catch (const CKM::Crypto::Exception::Base &e) {
1519 LogError("CKM::Crypto failed with message: " << e.GetMessage());
1520 retCode = CKM_API_ERROR_SERVER_ERROR;
1521 } catch (const CKM::Exception &e) {
1522 LogError("Unknown CKM::Exception: " << e.GetMessage());
1523 retCode = CKM_API_ERROR_SERVER_ERROR;
1526 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1530 return response.Pop();
1533 RawBuffer CKMLogic::verifySignature(
1534 const Credentials &cred,
1536 const Name &publicKeyOrCertName,
1537 const Label & ownerLabel,
1538 const Password &password, // password for public_key (optional)
1539 const RawBuffer &message,
1540 const RawBuffer &signature,
1541 const HashAlgorithm hash,
1542 const RSAPaddingAlgorithm padding)
1544 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1550 CryptoAlgorithm params;
1551 params.addParam(ParamName::SV_HASH_ALGO, hash);
1552 params.addParam(ParamName::SV_RSA_PADDING, padding);
1554 // try certificate first - looking for a public key.
1555 // in case of PKCS, pub key from certificate will be found first
1556 // rather than private key from the same PKCS.
1557 retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
1558 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1559 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
1562 if (retCode == CKM_API_SUCCESS) {
1563 retCode = m_decider.getStore(row).getKey(row)->verify(params, message, signature);
1565 } catch (const Crypto::SW::CryptoService::Exception::Crypto_internal &e) {
1566 LogError("KeyProvider failed with message: " << e.GetMessage());
1567 retCode = CKM_API_ERROR_SERVER_ERROR;
1568 } catch (const Crypto::SW::CryptoService::Exception::opensslError &e) {
1569 LogError("KeyProvider failed with message: " << e.GetMessage());
1570 retCode = CKM_API_ERROR_SERVER_ERROR;
1571 } catch (const KeyProvider::Exception::Base &e) {
1572 LogError("KeyProvider failed with error: " << e.GetMessage());
1573 retCode = CKM_API_ERROR_SERVER_ERROR;
1574 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1575 LogError("CryptoLogic failed with message: " << e.GetMessage());
1576 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1577 } catch (const CryptoLogic::Exception::Base &e) {
1578 LogError("CryptoLogic failed with message: " << e.GetMessage());
1579 retCode = CKM_API_ERROR_SERVER_ERROR;
1580 } catch (const DB::Crypto::Exception::Base &e) {
1581 LogError("DB::Crypto failed with message: " << e.GetMessage());
1582 retCode = CKM_API_ERROR_DB_ERROR;
1583 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1584 LogError("Error " << e.GetMessage());
1585 retCode = CKM_API_ERROR_DB_LOCKED;
1586 } catch (const CKM::Exception &e) {
1587 LogError("Unknown CKM::Exception: " << e.GetMessage());
1588 retCode = CKM_API_ERROR_SERVER_ERROR;
1591 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1594 return response.Pop();
1597 int CKMLogic::setPermissionHelper(
1598 const Credentials &cred, // who's the client
1600 const Label &label, // who's the owner
1601 const Label &accessorLabel, // who will get the access
1602 const PermissionMask permissionMask)
1604 auto &handler = selectDatabase(cred, label);
1606 // we don't know the client
1607 if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1608 return CKM_API_ERROR_INPUT_PARAM;
1610 // use client label if not explicitly provided
1611 const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1613 // verify name and label are correct
1614 if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1615 return CKM_API_ERROR_INPUT_PARAM;
1617 // currently we don't support modification of owner's permissions to his own rows
1618 if (ownerLabel==accessorLabel)
1619 return CKM_API_ERROR_INPUT_PARAM;
1621 // system database does not support write/remove permissions
1622 if ((0 == ownerLabel.compare(LABEL_SYSTEM_DB)) &&
1623 (permissionMask & Permission::REMOVE))
1624 return CKM_API_ERROR_INPUT_PARAM;
1626 // can the client modify permissions to owner's row?
1627 int retCode = m_accessControl.canModify(cred, ownerLabel);
1628 if(retCode != CKM_API_SUCCESS)
1631 DB::Crypto::Transaction transaction(&handler.database);
1633 if( !handler.database.isNameLabelPresent(name, ownerLabel) )
1634 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1636 // removing non-existing permissions: fail
1637 if(permissionMask == Permission::NONE)
1639 if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1640 return CKM_API_ERROR_INPUT_PARAM;
1643 // set permissions to the row owned by ownerLabel for accessorLabel
1644 handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1645 transaction.commit();
1647 return CKM_API_SUCCESS;
1650 RawBuffer CKMLogic::setPermission(
1651 const Credentials &cred,
1656 const Label &accessorLabel,
1657 const PermissionMask permissionMask)
1661 retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1662 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1663 LogError("Error " << e.GetMessage());
1664 retCode = CKM_API_ERROR_DB_LOCKED;
1665 } Catch (CKM::Exception) {
1666 LogError("Error in set row!");
1667 retCode = CKM_API_ERROR_DB_ERROR;
1670 return MessageBuffer::Serialize(command, msgID, retCode).Pop();