2 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
18 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
20 * @brief Sample service implementation.
22 #include <dpl/serialization.h>
23 #include <dpl/log/log.h>
24 #include <ckm/ckm-error.h>
25 #include <ckm/ckm-type.h>
26 #include <key-provider.h>
27 #include <file-system.h>
28 #include <ckm-logic.h>
30 #include <key-aes-impl.h>
31 #include <certificate-config.h>
32 #include <certificate-store.h>
35 #include <InitialValuesFile.h>
36 #include <sw-backend/store.h>
37 #include <generic-backend/exception.h>
40 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
41 const char * const INIT_VALUES_DIR = "/opt/data/ckm/initial_values/";
42 const char * const INIT_VALUES_XSD = "/usr/share/ckm/initial_values.xsd";
43 const char * const INIT_VALUES_FILE_SUFFIX = ".xml";
44 const char * const SYSTEM_DB_PASSWD = "cAtRugU7";
46 bool isLabelValid(const CKM::Label &label) {
47 // TODO: copy code from libprivilege control (for check smack label)
48 if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos)
53 bool isNameValid(const CKM::Name &name) {
54 if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
58 } // anonymous namespace
62 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
66 CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
68 m_accessControl.updateCCMode();
70 // make initial file list
71 std::vector<std::string> filesToParse;
72 DIR *dp = opendir(INIT_VALUES_DIR);
76 while ((entry = readdir(dp)))
78 std::string filename = std::string(entry->d_name);
81 std::string lowercaseFilename = filename;
82 std::transform(lowercaseFilename.begin(), lowercaseFilename.end(), lowercaseFilename.begin(), ::tolower);
83 if(lowercaseFilename.find(INIT_VALUES_FILE_SUFFIX) == std::string::npos)
86 filesToParse.push_back(std::string(INIT_VALUES_DIR) + filename);
92 for(const auto & file : filesToParse)
94 InitialValues::InitialValuesFile xmlFile(file.c_str(), *this);
95 int rc = xmlFile.Validate(INIT_VALUES_XSD);
96 if(rc == XML::Parser::PARSE_SUCCESS)
99 if(rc != XML::Parser::PARSE_SUCCESS)
100 LogError("invalid initial values file: " << file << ", parsing code: " << rc);
103 LogError("invalid initial values file: " << file << ", validation code: " << rc);
104 unlink(file.c_str());
108 CKMLogic::~CKMLogic(){}
110 void CKMLogic::loadDKEKFile(uid_t user, const Password &password) {
111 auto &handle = m_userDataMap[user];
115 auto wrappedDKEK = fs.getDKEK();
117 if (wrappedDKEK.empty()) {
118 wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
119 fs.saveDKEK(wrappedDKEK);
122 handle.keyProvider = KeyProvider(wrappedDKEK, password);
125 void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
126 auto &handle = m_userDataMap[user];
129 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
132 int CKMLogic::unlockDatabase(uid_t user, const Password & password)
134 if (0<m_userDataMap.count(user) && m_userDataMap[user].keyProvider.isInitialized())
135 return CKM_API_SUCCESS;
137 int retCode = CKM_API_SUCCESS;
140 auto &handle = m_userDataMap[user];
143 loadDKEKFile(user, password);
145 auto wrappedDatabaseDEK = fs.getDBDEK();
146 if (wrappedDatabaseDEK.empty()) {
147 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
148 fs.saveDBDEK(wrappedDatabaseDEK);
151 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
153 handle.database = DB::Crypto(fs.getDBPath(), key);
154 handle.crypto = CryptoLogic();
156 if ( !m_accessControl.isSystemService(user) )
158 // remove data of removed apps during locked state
159 AppLabelVector removedApps = fs.clearRemovedsApps();
160 for(auto& appSmackLabel : removedApps) {
161 handle.crypto.removeKey(appSmackLabel);
162 handle.database.deleteKey(appSmackLabel);
165 } catch (const 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.extractable);
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())
465 if(dataType.isSKey())
466 output_key = CKM::Key::createAES(input_data);
468 output_key = CKM::Key::create(input_data);
469 if(output_key.get() == NULL)
471 LogError("provided binary data is not valid key data");
472 return CKM_API_ERROR_INPUT_PARAM;
474 output_data = output_key->getDER();
476 else if (dataType.isCertificate() || dataType.isChainCert())
478 CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
479 if(cert.get() == NULL)
481 LogError("provided binary data is not valid certificate data");
482 return CKM_API_ERROR_INPUT_PARAM;
484 output_data = cert->getDER();
487 output_data = input_data;
488 // TODO: add here BINARY_DATA verification, i.e: max size etc.
489 return CKM_API_SUCCESS;
492 int CKMLogic::verifyAndSaveDataHelper(
493 const Credentials &cred,
496 const RawBuffer &data,
498 const PolicySerializable &policy)
500 int retCode = CKM_API_ERROR_UNKNOWN;
503 // check if data is correct
504 RawBuffer binaryData;
505 retCode = toBinaryData(dataType, data, binaryData);
506 if(retCode == CKM_API_SUCCESS)
508 retCode = saveDataHelper(cred, name, label, dataType, binaryData, policy);
510 } catch (const KeyProvider::Exception::Base &e) {
511 LogError("KeyProvider failed with message: " << e.GetMessage());
512 retCode = CKM_API_ERROR_SERVER_ERROR;
513 } catch (const CryptoLogic::Exception::Base &e) {
514 LogError("CryptoLogic failed with message: " << e.GetMessage());
515 retCode = CKM_API_ERROR_SERVER_ERROR;
516 } catch (const DB::Crypto::Exception::InternalError &e) {
517 LogError("DB::Crypto failed with message: " << e.GetMessage());
518 retCode = CKM_API_ERROR_DB_ERROR;
519 } catch (const DB::Crypto::Exception::TransactionError &e) {
520 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
521 retCode = CKM_API_ERROR_DB_ERROR;
522 } catch (const FileSystem::Exception::Base &e) {
523 LogError("Error in FileSystem " << e.GetMessage());
524 retCode = CKM_API_ERROR_FILE_SYSTEM;
525 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
526 LogError("Error " << e.GetMessage());
527 retCode = CKM_API_ERROR_DB_LOCKED;
528 } catch (const CKM::Exception &e) {
529 LogError("CKM::Exception: " << e.GetMessage());
530 retCode = CKM_API_ERROR_SERVER_ERROR;
535 RawBuffer CKMLogic::saveData(
536 const Credentials &cred,
540 const RawBuffer &data,
542 const PolicySerializable &policy)
544 int retCode = verifyAndSaveDataHelper(cred, name, label, data, dataType, policy);
545 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
548 static_cast<int>(dataType));
549 return response.Pop();
552 int CKMLogic::extractPKCS12Data(
555 const Label &ownerLabel,
556 const PKCS12Serializable &pkcs,
557 const PolicySerializable &keyPolicy,
558 const PolicySerializable &certPolicy,
559 DB::RowVector &output) const
561 // private key is mandatory
563 return CKM_API_ERROR_INVALID_FORMAT;
564 Key* keyPtr = pkcs.getKey().get();
565 DataType keyType = DataType(keyPtr->getType());
566 RawBuffer keyData = keyPtr->getDER();
567 int retCode = verifyBinaryData(keyType, keyData);
568 if(retCode != CKM_API_SUCCESS)
570 output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyType, keyData, keyPolicy));
572 // certificate is mandatory
573 if( !pkcs.getCertificate() )
574 return CKM_API_ERROR_INVALID_FORMAT;
575 RawBuffer certData = pkcs.getCertificate().get()->getDER();
576 retCode = verifyBinaryData(DataType::CERTIFICATE, certData);
577 if(retCode != CKM_API_SUCCESS)
579 output.push_back(createEncryptedRow(crypto, name, ownerLabel, DataType::CERTIFICATE, certData, certPolicy));
582 unsigned int cert_index = 0;
583 for(const auto & ca : pkcs.getCaCertificateShPtrVector())
585 DataType chainDataType = DataType::getChainDatatype(cert_index ++);
586 RawBuffer caCertData = ca->getDER();
587 int retCode = verifyBinaryData(chainDataType, caCertData);
588 if(retCode != CKM_API_SUCCESS)
591 output.push_back(createEncryptedRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy));
594 return CKM_API_SUCCESS;
597 RawBuffer CKMLogic::savePKCS12(
598 const Credentials &cred,
602 const PKCS12Serializable &pkcs,
603 const PolicySerializable &keyPolicy,
604 const PolicySerializable &certPolicy)
606 int retCode = CKM_API_ERROR_UNKNOWN;
608 retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
609 } catch (const KeyProvider::Exception::Base &e) {
610 LogError("KeyProvider failed with message: " << e.GetMessage());
611 retCode = CKM_API_ERROR_SERVER_ERROR;
612 } catch (const CryptoLogic::Exception::Base &e) {
613 LogError("CryptoLogic failed with message: " << e.GetMessage());
614 retCode = CKM_API_ERROR_SERVER_ERROR;
615 } catch (const DB::Crypto::Exception::InternalError &e) {
616 LogError("DB::Crypto failed with message: " << e.GetMessage());
617 retCode = CKM_API_ERROR_DB_ERROR;
618 } catch (const DB::Crypto::Exception::TransactionError &e) {
619 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
620 retCode = CKM_API_ERROR_DB_ERROR;
621 } catch (const CKM::Exception &e) {
622 LogError("CKM::Exception: " << e.GetMessage());
623 retCode = CKM_API_ERROR_SERVER_ERROR;
626 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
629 return response.Pop();
633 int CKMLogic::removeDataHelper(
634 const Credentials &cred,
638 auto &handler = selectDatabase(cred, label);
640 // use client label if not explicitly provided
641 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
642 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
643 LogError("Invalid label or name format");
644 return CKM_API_ERROR_INPUT_PARAM;
647 DB::Crypto::Transaction transaction(&handler.database);
649 // read and check permissions
650 PermissionMaskOptional permissionRowOpt =
651 handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel);
652 int retCode = m_accessControl.canDelete(cred,
653 PermissionForLabel(cred.smackLabel, permissionRowOpt));
654 if(retCode != CKM_API_SUCCESS)
656 LogWarning("access control check result: " << retCode);
660 auto erased = handler.database.deleteRow(name, ownerLabel);
661 // check if the data existed or not
663 transaction.commit();
665 LogError("No row for given name and label");
666 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
669 return CKM_API_SUCCESS;
672 RawBuffer CKMLogic::removeData(
673 const Credentials &cred,
678 int retCode = CKM_API_ERROR_UNKNOWN;
682 retCode = removeDataHelper(cred, name, label);
684 catch (const CKMLogic::Exception::DatabaseLocked &e)
686 LogError("Error " << e.GetMessage());
687 retCode = CKM_API_ERROR_DB_LOCKED;
689 catch (const CKM::Exception &)
691 LogError("Error in deleting row!");
692 retCode = CKM_API_ERROR_DB_ERROR;
695 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
698 return response.Pop();
701 int CKMLogic::readSingleRow(const Name &name,
702 const Label &ownerLabel,
704 DB::Crypto & database,
707 DB::Crypto::RowOptional row_optional;
708 if (dataType.isKey())
710 // read all key types
711 row_optional = database.getRow(name,
713 DataType::DB_KEY_FIRST,
714 DataType::DB_KEY_LAST);
716 // read anything else
717 row_optional = database.getRow(name,
723 LogError("No row for given name, label and type");
724 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
729 return CKM_API_SUCCESS;
733 int CKMLogic::readMultiRow(const Name &name,
734 const Label &ownerLabel,
736 DB::Crypto & database,
737 DB::RowVector &output)
739 if (dataType.isKey())
741 // read all key types
742 database.getRows(name,
744 DataType::DB_KEY_FIRST,
745 DataType::DB_KEY_LAST,
748 else if (dataType.isChainCert())
750 // read all key types
751 database.getRows(name,
753 DataType::DB_CHAIN_FIRST,
754 DataType::DB_CHAIN_LAST,
759 // read anything else
760 database.getRows(name,
767 LogError("No row for given name, label and type");
768 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
771 return CKM_API_SUCCESS;
774 int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
776 const Label &ownerLabel,
777 const Label &accessorLabel,
780 DB::Crypto & database)
782 PermissionMaskOptional permissionRowOpt =
783 database.getPermissionRow(name, ownerLabel, accessorLabel);
786 return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt));
787 return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt));
790 int CKMLogic::readDataHelper(
792 const Credentials &cred,
796 const Password &password,
799 auto &handler = selectDatabase(cred, label);
801 // use client label if not explicitly provided
802 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
804 if (!isNameValid(name) || !isLabelValid(ownerLabel))
805 return CKM_API_ERROR_INPUT_PARAM;
808 DB::Crypto::Transaction transaction(&handler.database);
809 int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
810 if(CKM_API_SUCCESS != retCode)
813 // all read rows belong to the same owner
814 DB::Row & firstRow = rows.at(0);
816 // check access rights
817 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database);
818 if(CKM_API_SUCCESS != retCode)
822 if (!handler.crypto.haveKey(firstRow.ownerLabel)) {
824 auto key_optional = handler.database.getKey(firstRow.ownerLabel);
826 LogError("No key for given label in database");
827 return CKM_API_ERROR_DB_ERROR;
830 key = handler.keyProvider.getPureDEK(key);
831 handler.crypto.pushKey(firstRow.ownerLabel, key);
833 for(auto &row : rows)
834 handler.crypto.decryptRow(password, row);
836 return CKM_API_SUCCESS;
839 int CKMLogic::readDataHelper(
841 const Credentials &cred,
845 const Password &password,
848 auto &handler = selectDatabase(cred, label);
850 // use client label if not explicitly provided
851 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
853 if (!isNameValid(name) || !isLabelValid(ownerLabel))
854 return CKM_API_ERROR_INPUT_PARAM;
857 DB::Crypto::Transaction transaction(&handler.database);
858 int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
859 if(CKM_API_SUCCESS != retCode)
862 // check access rights
863 retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
864 if(CKM_API_SUCCESS != retCode)
868 if (!handler.crypto.haveKey(row.ownerLabel)) {
870 auto key_optional = handler.database.getKey(row.ownerLabel);
872 LogError("No key for given label in database");
873 return CKM_API_ERROR_DB_ERROR;
876 key = handler.keyProvider.getPureDEK(key);
877 handler.crypto.pushKey(row.ownerLabel, key);
879 handler.crypto.decryptRow(password, row);
881 return CKM_API_SUCCESS;
884 RawBuffer CKMLogic::getData(
885 const Credentials &cred,
890 const Password &password)
892 int retCode = CKM_API_SUCCESS;
896 retCode = readDataHelper(true, cred, dataType, name, label, password, row);
897 } catch (const KeyProvider::Exception::Base &e) {
898 LogError("KeyProvider failed with error: " << e.GetMessage());
899 retCode = CKM_API_ERROR_SERVER_ERROR;
900 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
901 LogError("CryptoLogic failed with message: " << e.GetMessage());
902 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
903 } catch (const CryptoLogic::Exception::Base &e) {
904 LogError("CryptoLogic failed with message: " << e.GetMessage());
905 retCode = CKM_API_ERROR_SERVER_ERROR;
906 } catch (const DB::Crypto::Exception::Base &e) {
907 LogError("DB::Crypto failed with message: " << e.GetMessage());
908 retCode = CKM_API_ERROR_DB_ERROR;
909 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
910 LogError("Error " << e.GetMessage());
911 retCode = CKM_API_ERROR_DB_LOCKED;
912 } catch (const CKM::Exception &e) {
913 LogError("CKM::Exception: " << e.GetMessage());
914 retCode = CKM_API_ERROR_SERVER_ERROR;
917 if (CKM_API_SUCCESS != retCode) {
919 row.dataType = dataType;
922 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
925 static_cast<int>(row.dataType),
927 return response.Pop();
930 int CKMLogic::getPKCS12Helper(
931 const Credentials &cred,
934 const Password &keyPassword,
935 const Password &certPassword,
937 CertificateShPtr & cert,
938 CertificateShPtrVector & caChain)
942 // read private key (mandatory)
944 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, privKeyRow);
945 if(retCode != CKM_API_SUCCESS)
947 privKey = CKM::Key::create(privKeyRow.data);
949 // read certificate (mandatory)
951 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certRow);
952 if(retCode != CKM_API_SUCCESS)
954 cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER);
956 // read CA cert chain (optional)
957 DB::RowVector rawCaChain;
958 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, rawCaChain);
959 if(retCode != CKM_API_SUCCESS &&
960 retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
962 for(auto &rawCaCert : rawCaChain)
963 caChain.push_back(CKM::Certificate::create(rawCaCert.data, DataFormat::FORM_DER));
965 // if anything found, return it
966 if(privKey || cert || caChain.size()>0)
967 retCode = CKM_API_SUCCESS;
972 RawBuffer CKMLogic::getPKCS12(
973 const Credentials &cred,
977 const Password &keyPassword,
978 const Password &certPassword)
980 int retCode = CKM_API_ERROR_UNKNOWN;
982 PKCS12Serializable output;
985 CertificateShPtr cert;
986 CertificateShPtrVector caChain;
987 retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey, cert, caChain);
990 if(retCode == CKM_API_SUCCESS)
991 output = PKCS12Serializable(privKey, cert, caChain);
993 } catch (const KeyProvider::Exception::Base &e) {
994 LogError("KeyProvider failed with error: " << e.GetMessage());
995 retCode = CKM_API_ERROR_SERVER_ERROR;
996 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
997 LogError("CryptoLogic failed with message: " << e.GetMessage());
998 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
999 } catch (const CryptoLogic::Exception::Base &e) {
1000 LogError("CryptoLogic failed with message: " << e.GetMessage());
1001 retCode = CKM_API_ERROR_SERVER_ERROR;
1002 } catch (const DB::Crypto::Exception::Base &e) {
1003 LogError("DB::Crypto failed with message: " << e.GetMessage());
1004 retCode = CKM_API_ERROR_DB_ERROR;
1005 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1006 LogError("Error " << e.GetMessage());
1007 retCode = CKM_API_ERROR_DB_LOCKED;
1008 } catch (const CKM::Exception &e) {
1009 LogError("CKM::Exception: " << e.GetMessage());
1010 retCode = CKM_API_ERROR_SERVER_ERROR;
1013 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
1017 return response.Pop();
1020 int CKMLogic::getDataListHelper(const Credentials &cred,
1021 const DataType dataType,
1022 LabelNameVector &labelNameVector)
1024 int retCode = CKM_API_ERROR_DB_LOCKED;
1025 if (0 < m_userDataMap.count(cred.clientUid))
1027 auto &database = m_userDataMap[cred.clientUid].database;
1030 LabelNameVector tmpVector;
1031 if (dataType.isKey()) {
1032 // list all key types
1033 database.listNames(cred.smackLabel,
1035 DataType::DB_KEY_FIRST,
1036 DataType::DB_KEY_LAST);
1038 // list anything else
1039 database.listNames(cred.smackLabel,
1043 labelNameVector.insert(labelNameVector.end(), tmpVector.begin(), tmpVector.end());
1044 retCode = CKM_API_SUCCESS;
1046 Catch (CKM::Exception) {
1047 LogError("Failed to get names");
1048 retCode = CKM_API_ERROR_DB_ERROR;
1054 RawBuffer CKMLogic::getDataList(
1055 const Credentials &cred,
1059 LabelNameVector systemVector;
1060 LabelNameVector userVector;
1061 LabelNameVector labelNameVector;
1063 int retCode = unlockSystemDB();
1064 if (CKM_API_SUCCESS == retCode)
1067 if (m_accessControl.isSystemService(cred))
1070 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1077 // user - lookup system, then client DB
1078 retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1084 if(retCode == CKM_API_SUCCESS)
1086 retCode = getDataListHelper(cred,
1093 if(retCode == CKM_API_SUCCESS)
1095 labelNameVector.insert(labelNameVector.end(), systemVector.begin(), systemVector.end());
1096 labelNameVector.insert(labelNameVector.end(), userVector.begin(), userVector.end());
1098 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
1101 static_cast<int>(dataType),
1103 return response.Pop();
1106 int CKMLogic::saveDataHelper(
1107 const Credentials &cred,
1111 const RawBuffer &data,
1112 const PolicySerializable &policy)
1114 auto &handler = selectDatabase(cred, label);
1116 // use client label if not explicitly provided
1117 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1118 if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
1119 return CKM_API_ERROR_INPUT_PARAM;
1121 // check if save is possible
1122 DB::Crypto::Transaction transaction(&handler.database);
1123 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1124 if(retCode != CKM_API_SUCCESS)
1128 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, dataType, data, policy);
1129 handler.database.saveRow(encryptedRow);
1131 transaction.commit();
1132 return CKM_API_SUCCESS;
1135 int CKMLogic::saveDataHelper(
1136 const Credentials &cred,
1139 const PKCS12Serializable &pkcs,
1140 const PolicySerializable &keyPolicy,
1141 const PolicySerializable &certPolicy)
1143 auto &handler = selectDatabase(cred, label);
1145 // use client label if not explicitly provided
1146 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1147 if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
1148 return CKM_API_ERROR_INPUT_PARAM;
1150 // check if save is possible
1151 DB::Crypto::Transaction transaction(&handler.database);
1152 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1153 if(retCode != CKM_API_SUCCESS)
1156 // extract and encrypt the data
1157 DB::RowVector encryptedRows;
1158 retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
1159 if(retCode != CKM_API_SUCCESS)
1163 handler.database.saveRows(name, ownerLabel, encryptedRows);
1164 transaction.commit();
1166 return CKM_API_SUCCESS;
1170 int CKMLogic::createKeyAESHelper(
1171 const Credentials &cred,
1175 const PolicySerializable &policy)
1177 CryptoAlgorithm keyGenAlgorithm;
1178 keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1179 Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm);
1181 return saveDataHelper(cred,
1190 int CKMLogic::createKeyPairHelper(
1191 const Credentials &cred,
1192 const CryptoAlgorithmSerializable & keyGenParams,
1193 const Name &namePrivate,
1194 const Label &labelPrivate,
1195 const Name &namePublic,
1196 const Label &labelPublic,
1197 const PolicySerializable &policyPrivate,
1198 const PolicySerializable &policyPublic)
1200 auto &handlerPriv = selectDatabase(cred, labelPrivate);
1201 auto &handlerPub = selectDatabase(cred, labelPublic);
1203 AlgoType keyType = AlgoType::RSA_GEN;
1204 if(!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1205 ThrowMsg(Crypto::Exception::InputParam, "Error, parameter ALGO_TYPE not found.");
1206 DataType dt(keyType);
1208 ThrowMsg(Crypto::Exception::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1210 bool exportable = policyPrivate.extractable || policyPublic.extractable;
1211 TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams);
1213 DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1214 // in case the same database is used for private and public - the second
1215 // transaction will not be executed
1216 DB::Crypto::Transaction transactionPub(&handlerPub.database);
1218 int retCode = saveDataHelper(cred,
1221 keys.first.dataType,
1224 if (CKM_API_SUCCESS != retCode)
1227 retCode = saveDataHelper(cred,
1230 keys.second.dataType,
1233 if (CKM_API_SUCCESS != retCode)
1236 transactionPub.commit();
1237 transactionPriv.commit();
1238 return CKM_API_SUCCESS;
1241 RawBuffer CKMLogic::createKeyPair(
1242 const Credentials &cred,
1244 const CryptoAlgorithmSerializable & keyGenParams,
1245 const Name &namePrivate,
1246 const Label &labelPrivate,
1247 const Name &namePublic,
1248 const Label &labelPublic,
1249 const PolicySerializable &policyPrivate,
1250 const PolicySerializable &policyPublic)
1252 int retCode = CKM_API_SUCCESS;
1255 retCode = createKeyPairHelper(
1264 } catch (const Crypto::Exception::OperationNotSupported &e) {
1265 LogDebug("GStore error: operation not supported: " << e.GetMessage());
1266 retCode = CKM_API_ERROR_SERVER_ERROR;
1267 } catch (const Crypto::Exception::InternalError & e) {
1268 LogDebug("GStore key generation failed: " << e.GetMessage());
1269 retCode = CKM_API_ERROR_SERVER_ERROR;
1270 } catch( const Crypto::Exception::InputParam & e) {
1271 LogDebug("Missing or wrong input parameters: " << e.GetMessage());
1272 retCode = CKM_API_ERROR_INPUT_PARAM;
1273 } catch (DB::Crypto::Exception::TransactionError &e) {
1274 LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1275 retCode = CKM_API_ERROR_DB_ERROR;
1276 } catch (CKM::CryptoLogic::Exception::Base &e) {
1277 LogDebug("CryptoLogic error: " << e.GetMessage());
1278 retCode = CKM_API_ERROR_SERVER_ERROR;
1279 } catch (DB::Crypto::Exception::InternalError &e) {
1280 LogDebug("DB::Crypto internal error: " << e.GetMessage());
1281 retCode = CKM_API_ERROR_DB_ERROR;
1282 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1283 LogError("Error " << e.GetMessage());
1284 retCode = CKM_API_ERROR_DB_LOCKED;
1285 } catch (const CKM::Exception &e) {
1286 LogError("CKM::Exception: " << e.GetMessage());
1287 retCode = CKM_API_ERROR_SERVER_ERROR;
1290 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1291 commandId, retCode).Pop();
1294 RawBuffer CKMLogic::createKeyAES(
1295 const Credentials &cred,
1300 const PolicySerializable &policy)
1302 int retCode = CKM_API_SUCCESS;
1305 retCode = createKeyAESHelper(cred, size, name, label, policy);
1306 } catch (const Crypto::Exception::OperationNotSupported &e) {
1307 LogDebug("GStore error: operation not supported: " << e.GetMessage());
1308 retCode = CKM_API_ERROR_SERVER_ERROR;
1309 } catch (const Crypto::Exception::InternalError & e) {
1310 LogDebug("GStore key generation failed: " << e.GetMessage());
1311 retCode = CKM_API_ERROR_SERVER_ERROR;
1312 } catch( const Crypto::Exception::InputParam & e) {
1313 LogDebug("Missing or wrong input parameters: " << e.GetMessage());
1314 retCode = CKM_API_ERROR_INPUT_PARAM;
1315 } catch (std::invalid_argument &e) {
1316 LogDebug("invalid argument error: " << e.what());
1317 retCode = CKM_API_ERROR_INPUT_PARAM;
1318 } catch (DB::Crypto::Exception::TransactionError &e) {
1319 LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1320 retCode = CKM_API_ERROR_DB_ERROR;
1321 } catch (CKM::CryptoLogic::Exception::Base &e) {
1322 LogDebug("CryptoLogic error: " << e.GetMessage());
1323 retCode = CKM_API_ERROR_SERVER_ERROR;
1324 } catch (DB::Crypto::Exception::InternalError &e) {
1325 LogDebug("DB::Crypto internal error: " << e.GetMessage());
1326 retCode = CKM_API_ERROR_DB_ERROR;
1327 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1328 LogError("Error " << e.GetMessage());
1329 retCode = CKM_API_ERROR_DB_LOCKED;
1330 } catch (const CKM::Exception &e) {
1331 LogError("CKM::Exception: " << e.GetMessage());
1332 retCode = CKM_API_ERROR_SERVER_ERROR;
1335 return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1336 commandId, retCode).Pop();
1339 int CKMLogic::readCertificateHelper(
1340 const Credentials &cred,
1341 const LabelNameVector &labelNameVector,
1342 CertificateImplVector &certVector)
1345 for (auto &i: labelNameVector) {
1346 int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), row);
1347 if (ec != CKM_API_SUCCESS)
1349 certVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
1351 // try to read chain certificates (if present)
1352 DB::RowVector rawCaChain;
1353 ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain);
1354 if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1356 for(auto &rawCaCert : rawCaChain)
1357 certVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER));
1359 return CKM_API_SUCCESS;
1362 int CKMLogic::getCertificateChainHelper(
1363 const CertificateImpl &cert,
1364 const RawBufferVector &untrustedCertificates,
1365 const RawBufferVector &trustedCertificates,
1366 bool useTrustedSystemCertificates,
1367 RawBufferVector &chainRawVector)
1369 CertificateImplVector untrustedCertVector;
1370 CertificateImplVector trustedCertVector;
1371 CertificateImplVector chainVector;
1374 return CKM_API_ERROR_INPUT_PARAM;
1376 for (auto &e: untrustedCertificates)
1377 untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1378 for (auto &e: trustedCertificates)
1379 trustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1381 CertificateStore store;
1382 int retCode = store.verifyCertificate(cert,
1383 untrustedCertVector,
1385 useTrustedSystemCertificates,
1386 m_accessControl.isCCMode(),
1388 if (retCode != CKM_API_SUCCESS)
1391 for (auto &e : chainVector)
1392 chainRawVector.push_back(e.getDER());
1393 return CKM_API_SUCCESS;
1396 int CKMLogic::getCertificateChainHelper(
1397 const Credentials &cred,
1398 const CertificateImpl &cert,
1399 const LabelNameVector &untrusted,
1400 const LabelNameVector &trusted,
1401 bool useTrustedSystemCertificates,
1402 RawBufferVector &chainRawVector)
1404 CertificateImplVector untrustedCertVector;
1405 CertificateImplVector trustedCertVector;
1406 CertificateImplVector chainVector;
1410 return CKM_API_ERROR_INPUT_PARAM;
1412 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1413 if (retCode != CKM_API_SUCCESS)
1415 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1416 if (retCode != CKM_API_SUCCESS)
1419 CertificateStore store;
1420 retCode = store.verifyCertificate(cert,
1421 untrustedCertVector,
1423 useTrustedSystemCertificates,
1424 m_accessControl.isCCMode(),
1426 if (retCode != CKM_API_SUCCESS)
1429 for (auto &i: chainVector)
1430 chainRawVector.push_back(i.getDER());
1432 return CKM_API_SUCCESS;
1435 RawBuffer CKMLogic::getCertificateChain(
1436 const Credentials & /*cred*/,
1438 const RawBuffer &certificate,
1439 const RawBufferVector &untrustedCertificates,
1440 const RawBufferVector &trustedCertificates,
1441 bool useTrustedSystemCertificates)
1443 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1444 RawBufferVector chainRawVector;
1445 int retCode = CKM_API_ERROR_UNKNOWN;
1447 retCode = getCertificateChainHelper(cert,
1448 untrustedCertificates,
1449 trustedCertificates,
1450 useTrustedSystemCertificates,
1452 } catch (const CryptoLogic::Exception::Base &e) {
1453 LogError("CryptoLogic failed with message: " << e.GetMessage());
1454 retCode = CKM_API_ERROR_SERVER_ERROR;
1455 } catch (const DB::Crypto::Exception::Base &e) {
1456 LogError("DB::Crypto failed with message: " << e.GetMessage());
1457 retCode = CKM_API_ERROR_DB_ERROR;
1458 } catch (const std::exception& e) {
1459 LogError("STD exception " << e.what());
1460 retCode = CKM_API_ERROR_SERVER_ERROR;
1462 LogError("Unknown error.");
1465 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1469 return response.Pop();
1472 RawBuffer CKMLogic::getCertificateChain(
1473 const Credentials &cred,
1475 const RawBuffer &certificate,
1476 const LabelNameVector &untrustedCertificates,
1477 const LabelNameVector &trustedCertificates,
1478 bool useTrustedSystemCertificates)
1480 int retCode = CKM_API_ERROR_UNKNOWN;
1481 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1482 RawBufferVector chainRawVector;
1484 retCode = getCertificateChainHelper(cred,
1486 untrustedCertificates,
1487 trustedCertificates,
1488 useTrustedSystemCertificates,
1490 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1491 LogError("CryptoLogic failed with message: " << e.GetMessage());
1492 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1493 } catch (const CryptoLogic::Exception::Base &e) {
1494 LogError("CryptoLogic failed with message: " << e.GetMessage());
1495 retCode = CKM_API_ERROR_SERVER_ERROR;
1496 } catch (const DB::Crypto::Exception::Base &e) {
1497 LogError("DB::Crypto failed with message: " << e.GetMessage());
1498 retCode = CKM_API_ERROR_DB_ERROR;
1499 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1500 LogError("Error " << e.GetMessage());
1501 retCode = CKM_API_ERROR_DB_LOCKED;
1502 } catch (const std::exception& e) {
1503 LogError("STD exception " << e.what());
1504 retCode = CKM_API_ERROR_SERVER_ERROR;
1506 LogError("Unknown error.");
1509 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1513 return response.Pop();
1516 RawBuffer CKMLogic::createSignature(
1517 const Credentials &cred,
1519 const Name &privateKeyName,
1520 const Label & ownerLabel,
1521 const Password &password, // password for private_key
1522 const RawBuffer &message,
1523 const HashAlgorithm hash,
1524 const RSAPaddingAlgorithm padding)
1527 RawBuffer signature;
1528 CryptoAlgorithm cryptoAlg;
1529 cryptoAlg.setParam(ParamName::SV_HASH_ALGO, hash);
1530 cryptoAlg.setParam(ParamName::SV_RSA_PADDING, padding);
1532 int retCode = CKM_API_SUCCESS;
1535 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
1536 if(retCode == CKM_API_SUCCESS) {
1537 signature = m_decider.getStore(row).getKey(row)->sign(cryptoAlg, message);
1539 } catch (const KeyProvider::Exception::Base &e) {
1540 LogError("KeyProvider failed with message: " << e.GetMessage());
1541 retCode = CKM_API_ERROR_SERVER_ERROR;
1542 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1543 LogError("CryptoLogic failed with message: " << e.GetMessage());
1544 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1545 } catch (const CryptoLogic::Exception::Base &e) {
1546 LogError("CryptoLogic failed with message: " << e.GetMessage());
1547 retCode = CKM_API_ERROR_SERVER_ERROR;
1548 } catch (const DB::Crypto::Exception::Base &e) {
1549 LogError("DB::Crypto failed with message: " << e.GetMessage());
1550 retCode = CKM_API_ERROR_DB_ERROR;
1551 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1552 LogError("Error " << e.GetMessage());
1553 retCode = CKM_API_ERROR_DB_LOCKED;
1554 } catch (const CKM::Crypto::Exception::InputParam &e) {
1555 LogError("CKM::Crypto failed with message: " << e.GetMessage());
1556 retCode = CKM_API_ERROR_INPUT_PARAM;
1557 } catch (const CKM::Crypto::Exception::Base &e) {
1558 LogError("CKM::Crypto failed with message: " << e.GetMessage());
1559 retCode = CKM_API_ERROR_SERVER_ERROR;
1560 } catch (const CKM::Exception &e) {
1561 LogError("Unknown CKM::Exception: " << e.GetMessage());
1562 retCode = CKM_API_ERROR_SERVER_ERROR;
1565 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1569 return response.Pop();
1572 RawBuffer CKMLogic::verifySignature(
1573 const Credentials &cred,
1575 const Name &publicKeyOrCertName,
1576 const Label & ownerLabel,
1577 const Password &password, // password for public_key (optional)
1578 const RawBuffer &message,
1579 const RawBuffer &signature,
1580 const HashAlgorithm hash,
1581 const RSAPaddingAlgorithm padding)
1583 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1588 CryptoAlgorithm params;
1589 params.setParam(ParamName::SV_HASH_ALGO, hash);
1590 params.setParam(ParamName::SV_RSA_PADDING, padding);
1592 // try certificate first - looking for a public key.
1593 // in case of PKCS, pub key from certificate will be found first
1594 // rather than private key from the same PKCS.
1595 retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
1596 if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1597 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
1600 if (retCode == CKM_API_SUCCESS) {
1601 retCode = m_decider.getStore(row).getKey(row)->verify(params, message, signature);
1603 } catch (const Crypto::Exception::Base &e) {
1604 LogError("GStore failed with error: " << e.GetMessage());
1605 retCode = CKM_API_ERROR_SERVER_ERROR;
1606 } catch (const KeyProvider::Exception::Base &e) {
1607 LogError("KeyProvider failed with error: " << e.GetMessage());
1608 retCode = CKM_API_ERROR_SERVER_ERROR;
1609 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1610 LogError("CryptoLogic failed with message: " << e.GetMessage());
1611 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1612 } catch (const CryptoLogic::Exception::Base &e) {
1613 LogError("CryptoLogic failed with message: " << e.GetMessage());
1614 retCode = CKM_API_ERROR_SERVER_ERROR;
1615 } catch (const DB::Crypto::Exception::Base &e) {
1616 LogError("DB::Crypto failed with message: " << e.GetMessage());
1617 retCode = CKM_API_ERROR_DB_ERROR;
1618 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1619 LogError("Error " << e.GetMessage());
1620 retCode = CKM_API_ERROR_DB_LOCKED;
1621 } catch (const CKM::Exception &e) {
1622 LogError("Unknown CKM::Exception: " << e.GetMessage());
1623 retCode = CKM_API_ERROR_SERVER_ERROR;
1626 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1629 return response.Pop();
1632 int CKMLogic::setPermissionHelper(
1633 const Credentials &cred, // who's the client
1635 const Label &label, // who's the owner
1636 const Label &accessorLabel, // who will get the access
1637 const PermissionMask permissionMask)
1639 auto &handler = selectDatabase(cred, label);
1641 // we don't know the client
1642 if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1643 return CKM_API_ERROR_INPUT_PARAM;
1645 // use client label if not explicitly provided
1646 const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1648 // verify name and label are correct
1649 if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1650 return CKM_API_ERROR_INPUT_PARAM;
1652 // currently we don't support modification of owner's permissions to his own rows
1653 if (ownerLabel==accessorLabel)
1654 return CKM_API_ERROR_INPUT_PARAM;
1656 // system database does not support write/remove permissions
1657 if ((0 == ownerLabel.compare(LABEL_SYSTEM_DB)) &&
1658 (permissionMask & Permission::REMOVE))
1659 return CKM_API_ERROR_INPUT_PARAM;
1661 // can the client modify permissions to owner's row?
1662 int retCode = m_accessControl.canModify(cred, ownerLabel);
1663 if(retCode != CKM_API_SUCCESS)
1666 DB::Crypto::Transaction transaction(&handler.database);
1668 if( !handler.database.isNameLabelPresent(name, ownerLabel) )
1669 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1671 // removing non-existing permissions: fail
1672 if(permissionMask == Permission::NONE)
1674 if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1675 return CKM_API_ERROR_INPUT_PARAM;
1678 // set permissions to the row owned by ownerLabel for accessorLabel
1679 handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1680 transaction.commit();
1682 return CKM_API_SUCCESS;
1685 RawBuffer CKMLogic::setPermission(
1686 const Credentials &cred,
1691 const Label &accessorLabel,
1692 const PermissionMask permissionMask)
1696 retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1697 } catch (const CKMLogic::Exception::DatabaseLocked &e) {
1698 LogError("Error " << e.GetMessage());
1699 retCode = CKM_API_ERROR_DB_LOCKED;
1700 } Catch (CKM::Exception) {
1701 LogError("Error in set row!");
1702 retCode = CKM_API_ERROR_DB_ERROR;
1705 return MessageBuffer::Serialize(command, msgID, retCode).Pop();