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 <CryptoService.h>
29 #include <ckm-logic.h>
31 #include <certificate-config.h>
32 #include <certificate-store.h>
35 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
37 bool isLabelValid(const CKM::Label &label) {
38 // TODO: copy code from libprivilege control (for check smack label)
39 if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos)
44 bool isNameValid(const CKM::Name &name) {
45 if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
50 } // anonymous namespace
56 CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
58 m_accessControl.updateCCMode();
61 CKMLogic::~CKMLogic(){}
63 void CKMLogic::loadDKEKFile(uid_t user, const Password &password, bool apiReq) {
64 auto &handle = m_userDataMap[user];
68 auto wrappedDKEKMain = fs.getDKEK();
69 auto wrappedDKEKBackup = fs.getDKEKBackup();
71 if (wrappedDKEKMain.empty()) {
72 wrappedDKEKMain = KeyProvider::generateDomainKEK(std::to_string(user), password);
73 fs.saveDKEK(wrappedDKEKMain);
76 chooseDKEKFile(handle, password, wrappedDKEKMain, wrappedDKEKBackup);
78 if (!password.empty() || apiReq) {
79 handle.isDKEKConfirmed = true;
81 if (true == handle.isMainDKEK)
82 fs.removeDKEKBackup();
88 void CKMLogic::chooseDKEKFile(
90 const Password &password,
91 const RawBuffer &first,
92 const RawBuffer &second)
95 handle.keyProvider = KeyProvider(first, password);
96 handle.isMainDKEK = true;
97 } catch (const KeyProvider::Exception::Base &e) {
98 // Second buffer is empty. Lets rethrow first error
101 handle.keyProvider = KeyProvider(second, password);
102 handle.isMainDKEK = false;
106 void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
107 auto &handle = m_userDataMap[user];
110 if (handle.isMainDKEK)
111 fs.createDKEKBackup();
113 fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
115 handle.isMainDKEK = true;
116 handle.isDKEKConfirmed = false;
119 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password, bool apiRequest) {
120 int retCode = CKM_API_SUCCESS;
123 if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
124 auto &handle = m_userDataMap[user];
127 loadDKEKFile(user, password, apiRequest);
129 auto wrappedDatabaseDEK = fs.getDBDEK();
131 if (wrappedDatabaseDEK.empty()) {
132 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
133 fs.saveDBDEK(wrappedDatabaseDEK);
136 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
137 handle.database = DB::Crypto(fs.getDBPath(), key);
138 handle.crypto = CryptoLogic();
140 // remove data of removed apps during locked state
141 AppLabelVector removedApps = fs.clearRemovedsApps();
142 for(auto& appSmackLabel : removedApps) {
143 handle.database.deleteKey(appSmackLabel);
145 } else if (apiRequest == true && m_userDataMap[user].isDKEKConfirmed == false) {
146 // now we will try to choose the DKEK key and remove old one
147 loadDKEKFile(user, password, apiRequest);
149 } catch (const KeyProvider::Exception::PassWordError &e) {
150 LogError("Incorrect Password " << e.GetMessage());
151 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
152 } catch (const KeyProvider::Exception::Base &e) {
153 LogError("Error in KeyProvider " << e.GetMessage());
154 retCode = CKM_API_ERROR_SERVER_ERROR;
155 } catch (const CryptoLogic::Exception::Base &e) {
156 LogError("CryptoLogic error: " << e.GetMessage());
157 retCode = CKM_API_ERROR_SERVER_ERROR;
158 } catch (const FileSystem::Exception::Base &e) {
159 LogError("FileSystem error: " << e.GetMessage());
160 retCode = CKM_API_ERROR_FILE_SYSTEM;
161 } catch (const CKM::Exception &e) {
162 LogError("CKM::Exception: " << e.GetMessage());
163 retCode = CKM_API_ERROR_SERVER_ERROR;
166 if(retCode != CKM_API_SUCCESS) {
167 // When not successful, UserData in m_userDataMap should be erased.
168 // Because other operations make decision based on the existence of UserData in m_userDataMap.
169 m_userDataMap.erase(user);
172 return MessageBuffer::Serialize(retCode).Pop();
175 RawBuffer CKMLogic::updateCCMode() {
176 m_accessControl.updateCCMode();
177 return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
180 RawBuffer CKMLogic::lockUserKey(uid_t user) {
181 int retCode = CKM_API_SUCCESS;
182 // TODO try catch for all errors that should be supported by error code
183 m_userDataMap.erase(user);
185 return MessageBuffer::Serialize(retCode).Pop();
189 RawBuffer CKMLogic::removeUserData(uid_t user) {
190 int retCode = CKM_API_SUCCESS;
191 // TODO try catch for all errors that should be supported by error code
192 m_userDataMap.erase(user);
197 return MessageBuffer::Serialize(retCode).Pop();
200 RawBuffer CKMLogic::changeUserPassword(
202 const Password &oldPassword,
203 const Password &newPassword)
205 int retCode = CKM_API_SUCCESS;
207 loadDKEKFile(user, oldPassword, true);
208 saveDKEKFile(user, newPassword);
209 } catch (const KeyProvider::Exception::PassWordError &e) {
210 LogError("Incorrect Password " << e.GetMessage());
211 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
212 } catch (const KeyProvider::Exception::Base &e) {
213 LogError("Error in KeyProvider " << e.GetMessage());
214 retCode = CKM_API_ERROR_SERVER_ERROR;
215 } catch (const FileSystem::Exception::Base &e) {
216 LogError("Error in FileSystem " << e.GetMessage());
217 retCode = CKM_API_ERROR_FILE_SYSTEM;
218 } catch (const CKM::Exception &e) {
219 LogError("CKM::Exception: " << e.GetMessage());
220 retCode = CKM_API_ERROR_SERVER_ERROR;
223 return MessageBuffer::Serialize(retCode).Pop();
226 RawBuffer CKMLogic::resetUserPassword(
228 const Password &newPassword)
230 int retCode = CKM_API_SUCCESS;
233 if (0 == m_userDataMap.count(user)) {
234 // Check if key exists. If exists we must return error
236 auto wrappedDKEKMain = fs.getDKEK();
237 if (!wrappedDKEKMain.empty())
238 retCode = CKM_API_ERROR_BAD_REQUEST;
240 saveDKEKFile(user, newPassword);
242 } catch (const FileSystem::Exception::Base &e) {
243 LogError("Error in FileSystem " << e.GetMessage());
244 retCode = CKM_API_ERROR_FILE_SYSTEM;
245 } catch (const CKM::Exception &e) {
246 LogError("CKM::Exception: " << e.GetMessage());
247 retCode = CKM_API_ERROR_SERVER_ERROR;
250 return MessageBuffer::Serialize(retCode).Pop();
253 RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
254 int retCode = CKM_API_SUCCESS;
258 if (smackLabel.empty()) {
259 retCode = CKM_API_ERROR_INPUT_PARAM;
261 UidVector uids = FileSystem::getUIDsFromDBFile();
262 for (auto userId : uids) {
263 if (0 == m_userDataMap.count(userId)) {
264 FileSystem fs(userId);
265 fs.addRemovedApp(smackLabel);
267 auto &handle = m_userDataMap[userId];
268 handle.database.deleteKey(smackLabel);
273 } catch (const DB::Crypto::Exception::InternalError &e) {
274 LogError("DB::Crypto couldn't remove data: " << e.GetMessage());
275 retCode = CKM_API_ERROR_DB_ERROR;
276 } catch (const DB::Crypto::Exception::TransactionError &e) {
277 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
278 retCode = CKM_API_ERROR_DB_ERROR;
279 } catch (const FileSystem::Exception::Base &e) {
280 LogError("Error in FileSystem " << e.GetMessage());
281 retCode = CKM_API_ERROR_FILE_SYSTEM;
282 } catch (const CKM::Exception &e) {
283 LogError("CKM::Exception: " << e.GetMessage());
284 retCode = CKM_API_ERROR_SERVER_ERROR;
287 return MessageBuffer::Serialize(retCode).Pop();
290 int CKMLogic::checkSaveConditions(
291 const Credentials &cred,
294 const Label &ownerLabel)
296 // verify name and label are correct
297 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
298 LogWarning("Invalid parameter passed to key-manager");
299 return CKM_API_ERROR_INPUT_PARAM;
302 // check if allowed to save using ownerLabel
303 int access_ec = m_accessControl.canSave(ownerLabel, cred.smackLabel);
304 if(access_ec != CKM_API_SUCCESS)
306 LogWarning("label " << cred.smackLabel << " can not save rows using label " << ownerLabel);
310 // check if not a duplicate
311 if( handler.database.isNameLabelPresent(name, cred.smackLabel) )
312 return CKM_API_ERROR_DB_ALIAS_EXISTS;
314 // encryption section
315 if (!handler.crypto.haveKey(cred.smackLabel)) {
317 auto key_optional = handler.database.getKey(cred.smackLabel);
319 LogDebug("No Key in database found. Generating new one for label: "
321 got_key = handler.keyProvider.generateDEK(cred.smackLabel);
322 handler.database.saveKey(cred.smackLabel, got_key);
324 LogDebug("Key from DB");
325 got_key = *key_optional;
328 got_key = handler.keyProvider.getPureDEK(got_key);
329 handler.crypto.pushKey(cred.smackLabel, got_key);
332 return CKM_API_SUCCESS;
335 DB::Row CKMLogic::createEncryptedRow(
340 const RawBuffer &data,
341 const Policy &policy) const
343 DB::Row row = { name, label, policy.extractable, dataType, DBCMAlgType::NONE,
344 0, RawBuffer(), static_cast<int>(data.size()), data, RawBuffer() };
346 // do not encrypt data with password during cc_mode on
347 if(m_accessControl.isCCMode()) {
348 crypto.encryptRow("", row);
350 crypto.encryptRow(policy.password, row);
355 int CKMLogic::verifyBinaryData(DataType dataType, const RawBuffer &input_data) const
357 // verify the data integrity
358 if (dataType.isKey())
360 KeyShPtr output_key = CKM::Key::create(input_data);
361 if(output_key.get() == NULL)
363 LogError("provided binary data is not valid key data");
364 return CKM_API_ERROR_INPUT_PARAM;
367 else if (dataType.isCertificate() || dataType.isChainCert())
369 CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
370 if(cert.get() == NULL)
372 LogError("provided binary data is not valid certificate data");
373 return CKM_API_ERROR_INPUT_PARAM;
376 // TODO: add here BINARY_DATA verification, i.e: max size etc.
377 return CKM_API_SUCCESS;
380 RawBuffer CKMLogic::saveData(
381 const Credentials &cred,
385 const RawBuffer &data,
387 const PolicySerializable &policy)
390 if (0 == m_userDataMap.count(cred.uid))
391 retCode = CKM_API_ERROR_DB_LOCKED;
395 // check if data is correct
396 retCode = verifyBinaryData(dataType, data);
397 if(retCode == CKM_API_SUCCESS)
399 retCode = saveDataHelper(cred, name, label, dataType, data, policy);
401 } catch (const KeyProvider::Exception::Base &e) {
402 LogError("KeyProvider failed with message: " << e.GetMessage());
403 retCode = CKM_API_ERROR_SERVER_ERROR;
404 } catch (const CryptoLogic::Exception::Base &e) {
405 LogError("CryptoLogic failed with message: " << e.GetMessage());
406 retCode = CKM_API_ERROR_SERVER_ERROR;
407 } catch (const DB::Crypto::Exception::InternalError &e) {
408 LogError("DB::Crypto failed with message: " << e.GetMessage());
409 retCode = CKM_API_ERROR_DB_ERROR;
410 } catch (const DB::Crypto::Exception::TransactionError &e) {
411 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
412 retCode = CKM_API_ERROR_DB_ERROR;
413 } catch (const FileSystem::Exception::Base &e) {
414 LogError("Error in FileSystem " << e.GetMessage());
415 retCode = CKM_API_ERROR_FILE_SYSTEM;
416 } catch (const CKM::Exception &e) {
417 LogError("CKM::Exception: " << e.GetMessage());
418 retCode = CKM_API_ERROR_SERVER_ERROR;
422 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
425 static_cast<int>(dataType));
426 return response.Pop();
429 int CKMLogic::extractPKCS12Data(
432 const Label &ownerLabel,
433 const PKCS12Serializable &pkcs,
434 const PolicySerializable &keyPolicy,
435 const PolicySerializable &certPolicy,
436 DB::RowVector &output) const
438 // private key is mandatory
440 return CKM_API_ERROR_INVALID_FORMAT;
441 Key* keyPtr = pkcs.getKey().get();
442 DataType keyType = DataType(keyPtr->getType());
443 RawBuffer keyData = keyPtr->getDER();
444 int retCode = verifyBinaryData(keyType, keyData);
445 if(retCode != CKM_API_SUCCESS)
447 output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyType, keyData, keyPolicy));
449 // certificate is mandatory
450 if( !pkcs.getCertificate() )
451 return CKM_API_ERROR_INVALID_FORMAT;
452 RawBuffer certData = pkcs.getCertificate().get()->getDER();
453 retCode = verifyBinaryData(DataType::CERTIFICATE, certData);
454 if(retCode != CKM_API_SUCCESS)
456 output.push_back(createEncryptedRow(crypto, name, ownerLabel, DataType::CERTIFICATE, certData, certPolicy));
459 unsigned int cert_index = 0;
460 for(const auto & ca : pkcs.getCaCertificateShPtrVector())
462 DataType chainDataType = DataType::getChainDatatype(cert_index ++);
463 RawBuffer caCertData = ca->getDER();
464 int retCode = verifyBinaryData(chainDataType, caCertData);
465 if(retCode != CKM_API_SUCCESS)
468 output.push_back(createEncryptedRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy));
471 return CKM_API_SUCCESS;
474 RawBuffer CKMLogic::savePKCS12(
475 const Credentials &cred,
479 const PKCS12Serializable &pkcs,
480 const PolicySerializable &keyPolicy,
481 const PolicySerializable &certPolicy)
484 if (0 == m_userDataMap.count(cred.uid))
485 retCode = CKM_API_ERROR_DB_LOCKED;
489 retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
490 } catch (const KeyProvider::Exception::Base &e) {
491 LogError("KeyProvider failed with message: " << e.GetMessage());
492 retCode = CKM_API_ERROR_SERVER_ERROR;
493 } catch (const CryptoLogic::Exception::Base &e) {
494 LogError("CryptoLogic failed with message: " << e.GetMessage());
495 retCode = CKM_API_ERROR_SERVER_ERROR;
496 } catch (const DB::Crypto::Exception::InternalError &e) {
497 LogError("DB::Crypto failed with message: " << e.GetMessage());
498 retCode = CKM_API_ERROR_DB_ERROR;
499 } catch (const DB::Crypto::Exception::TransactionError &e) {
500 LogError("DB::Crypto transaction failed with message " << e.GetMessage());
501 retCode = CKM_API_ERROR_DB_ERROR;
502 } catch (const CKM::Exception &e) {
503 LogError("CKM::Exception: " << e.GetMessage());
504 retCode = CKM_API_ERROR_SERVER_ERROR;
508 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
511 return response.Pop();
515 int CKMLogic::removeDataHelper(
516 const Credentials &cred,
518 const Label &ownerLabel)
520 if (0 == m_userDataMap.count(cred.uid))
521 return CKM_API_ERROR_DB_LOCKED;
523 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
524 LogError("Invalid label or name format");
525 return CKM_API_ERROR_INPUT_PARAM;
528 auto &database = m_userDataMap[cred.uid].database;
529 DB::Crypto::Transaction transaction(&database);
531 // read and check permissions
532 PermissionMaskOptional permissionRowOpt =
533 database.getPermissionRow(name, ownerLabel, cred.smackLabel);
534 int access_ec = m_accessControl.canDelete(PermissionForLabel(cred.smackLabel, permissionRowOpt));
535 if(access_ec != CKM_API_SUCCESS)
537 LogWarning("access control check result: " << access_ec);
541 auto erased = database.deleteRow(name, ownerLabel);
542 // check if the data existed or not
544 transaction.commit();
546 LogError("No row for given name and label");
547 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
550 return CKM_API_SUCCESS;
553 RawBuffer CKMLogic::removeData(
554 const Credentials &cred,
561 // use client label if not explicitly provided
562 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
564 retCode = removeDataHelper(cred, name, ownerLabel);
565 } Catch (CKM::Exception) {
566 LogError("Error in deleting row!");
567 retCode = CKM_API_ERROR_DB_ERROR;
570 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
573 return response.Pop();
576 int CKMLogic::readSingleRow(const Name &name,
577 const Label &ownerLabel,
579 DB::Crypto & database,
582 DB::Crypto::RowOptional row_optional;
583 if (dataType.isKey())
585 // read all key types
586 row_optional = database.getRow(name,
588 DataType::DB_KEY_FIRST,
589 DataType::DB_KEY_LAST);
591 // read anything else
592 row_optional = database.getRow(name,
598 LogError("No row for given name, label and type");
599 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
604 return CKM_API_SUCCESS;
608 int CKMLogic::readMultiRow(const Name &name,
609 const Label &ownerLabel,
611 DB::Crypto & database,
612 DB::RowVector &output)
614 if (dataType.isKey())
616 // read all key types
617 database.getRows(name,
619 DataType::DB_KEY_FIRST,
620 DataType::DB_KEY_LAST,
623 else if (dataType.isChainCert())
625 // read all key types
626 database.getRows(name,
628 DataType::DB_CHAIN_FIRST,
629 DataType::DB_CHAIN_LAST,
634 // read anything else
635 database.getRows(name,
642 LogError("No row for given name, label and type");
643 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
646 return CKM_API_SUCCESS;
649 int CKMLogic::checkDataPermissionsHelper(const Name &name,
650 const Label &ownerLabel,
651 const Label &accessorLabel,
654 DB::Crypto & database)
656 PermissionMaskOptional permissionRowOpt =
657 database.getPermissionRow(name, ownerLabel, accessorLabel);
660 return m_accessControl.canExport(row, PermissionForLabel(accessorLabel, permissionRowOpt));
661 return m_accessControl.canRead(PermissionForLabel(accessorLabel, permissionRowOpt));
664 int CKMLogic::readDataHelper(
666 const Credentials &cred,
670 const Password &password,
673 if (0 == m_userDataMap.count(cred.uid))
674 return CKM_API_ERROR_DB_LOCKED;
676 // use client label if not explicitly provided
677 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
679 if (!isNameValid(name) || !isLabelValid(ownerLabel))
680 return CKM_API_ERROR_INPUT_PARAM;
682 auto &handler = m_userDataMap[cred.uid];
685 DB::Crypto::Transaction transaction(&handler.database);
686 int ec = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
687 if(CKM_API_SUCCESS != ec)
690 // all read rows belong to the same owner
691 DB::Row & firstRow = rows.at(0);
693 // check access rights
694 ec = checkDataPermissionsHelper(name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database);
695 if(CKM_API_SUCCESS != ec)
699 if (!handler.crypto.haveKey(firstRow.ownerLabel)) {
701 auto key_optional = handler.database.getKey(firstRow.ownerLabel);
703 LogError("No key for given label in database");
704 return CKM_API_ERROR_DB_ERROR;
707 key = handler.keyProvider.getPureDEK(key);
708 handler.crypto.pushKey(firstRow.ownerLabel, key);
710 for(auto &row : rows)
711 handler.crypto.decryptRow(password, row);
713 return CKM_API_SUCCESS;
716 int CKMLogic::readDataHelper(
718 const Credentials &cred,
722 const Password &password,
725 if (0 == m_userDataMap.count(cred.uid))
726 return CKM_API_ERROR_DB_LOCKED;
728 // use client label if not explicitly provided
729 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
731 if (!isNameValid(name) || !isLabelValid(ownerLabel))
732 return CKM_API_ERROR_INPUT_PARAM;
734 auto &handler = m_userDataMap[cred.uid];
737 DB::Crypto::Transaction transaction(&handler.database);
738 int ec = readSingleRow(name, ownerLabel, dataType, handler.database, row);
739 if(CKM_API_SUCCESS != ec)
743 // check access rights
744 ec = checkDataPermissionsHelper(name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
745 if(CKM_API_SUCCESS != ec)
749 if (!handler.crypto.haveKey(row.ownerLabel)) {
751 auto key_optional = handler.database.getKey(row.ownerLabel);
753 LogError("No key for given label in database");
754 return CKM_API_ERROR_DB_ERROR;
757 key = handler.keyProvider.getPureDEK(key);
758 handler.crypto.pushKey(row.ownerLabel, key);
760 handler.crypto.decryptRow(password, row);
762 return CKM_API_SUCCESS;
765 RawBuffer CKMLogic::getData(
766 const Credentials &cred,
771 const Password &password)
773 int retCode = CKM_API_SUCCESS;
777 retCode = readDataHelper(true, cred, dataType, name, label, password, row);
778 } catch (const KeyProvider::Exception::Base &e) {
779 LogError("KeyProvider failed with error: " << e.GetMessage());
780 retCode = CKM_API_ERROR_SERVER_ERROR;
781 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
782 LogError("CryptoLogic failed with message: " << e.GetMessage());
783 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
784 } catch (const CryptoLogic::Exception::Base &e) {
785 LogError("CryptoLogic failed with message: " << e.GetMessage());
786 retCode = CKM_API_ERROR_SERVER_ERROR;
787 } catch (const DB::Crypto::Exception::Base &e) {
788 LogError("DB::Crypto failed with message: " << e.GetMessage());
789 retCode = CKM_API_ERROR_DB_ERROR;
790 } catch (const CKM::Exception &e) {
791 LogError("CKM::Exception: " << e.GetMessage());
792 retCode = CKM_API_ERROR_SERVER_ERROR;
795 if (CKM_API_SUCCESS != retCode) {
797 row.dataType = dataType;
800 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
803 static_cast<int>(row.dataType),
805 return response.Pop();
808 int CKMLogic::getPKCS12Helper(
809 const Credentials &cred,
812 const Password &keyPassword,
813 const Password &certPassword,
815 CertificateShPtr & cert,
816 CertificateShPtrVector & caChain)
820 // read private key (mandatory)
822 retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, privKeyRow);
823 if(retCode != CKM_API_SUCCESS)
825 privKey = CKM::Key::create(privKeyRow.data);
827 // read certificate (mandatory)
829 retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certRow);
830 if(retCode != CKM_API_SUCCESS)
832 cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER);
834 // read CA cert chain (optional)
835 DB::RowVector rawCaChain;
836 retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, rawCaChain);
837 if(retCode != CKM_API_SUCCESS &&
838 retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
840 for(auto &rawCaCert : rawCaChain)
841 caChain.push_back(CKM::Certificate::create(rawCaCert.data, DataFormat::FORM_DER));
843 // if anything found, return it
844 if(privKey || cert || caChain.size()>0)
845 retCode = CKM_API_SUCCESS;
850 RawBuffer CKMLogic::getPKCS12(
851 const Credentials &cred,
855 const Password &keyPassword,
856 const Password &certPassword)
859 PKCS12Serializable output;
863 CertificateShPtr cert;
864 CertificateShPtrVector caChain;
865 retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey, cert, caChain);
868 if(retCode == CKM_API_SUCCESS)
869 output = PKCS12Serializable(privKey, cert, caChain);
871 } catch (const KeyProvider::Exception::Base &e) {
872 LogError("KeyProvider failed with error: " << e.GetMessage());
873 retCode = CKM_API_ERROR_SERVER_ERROR;
874 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
875 LogError("CryptoLogic failed with message: " << e.GetMessage());
876 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
877 } catch (const CryptoLogic::Exception::Base &e) {
878 LogError("CryptoLogic failed with message: " << e.GetMessage());
879 retCode = CKM_API_ERROR_SERVER_ERROR;
880 } catch (const DB::Crypto::Exception::Base &e) {
881 LogError("DB::Crypto failed with message: " << e.GetMessage());
882 retCode = CKM_API_ERROR_DB_ERROR;
883 } catch (const CKM::Exception &e) {
884 LogError("CKM::Exception: " << e.GetMessage());
885 retCode = CKM_API_ERROR_SERVER_ERROR;
888 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
892 return response.Pop();
895 RawBuffer CKMLogic::getDataList(
896 const Credentials &cred,
900 int retCode = CKM_API_SUCCESS;
901 LabelNameVector labelNameVector;
903 if (0 < m_userDataMap.count(cred.uid)) {
904 auto &database = m_userDataMap[cred.uid].database;
907 if (dataType.isKey()) {
908 // list all key types
909 database.listNames(cred.smackLabel,
911 DataType::DB_KEY_FIRST,
912 DataType::DB_KEY_LAST);
914 // list anything else
915 database.listNames(cred.smackLabel,
920 Catch (CKM::Exception) {
921 LogError("Failed to get names");
922 retCode = CKM_API_ERROR_DB_ERROR;
925 retCode = CKM_API_ERROR_DB_LOCKED;
928 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
931 static_cast<int>(dataType),
933 return response.Pop();
936 int CKMLogic::saveDataHelper(
937 const Credentials &cred,
941 const RawBuffer &data,
942 const PolicySerializable &policy)
944 auto &handler = m_userDataMap[cred.uid];
946 // use client label if not explicitly provided
947 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
949 // check if save is possible
950 DB::Crypto::Transaction transaction(&handler.database);
951 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
952 if(retCode != CKM_API_SUCCESS)
956 DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, dataType, data, policy);
957 handler.database.saveRow(encryptedRow);
959 transaction.commit();
960 return CKM_API_SUCCESS;
963 int CKMLogic::saveDataHelper(
964 const Credentials &cred,
967 const PKCS12Serializable &pkcs,
968 const PolicySerializable &keyPolicy,
969 const PolicySerializable &certPolicy)
971 auto &handler = m_userDataMap[cred.uid];
973 // use client label if not explicitly provided
974 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
976 // check if save is possible
977 DB::Crypto::Transaction transaction(&handler.database);
978 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
979 if(retCode != CKM_API_SUCCESS)
982 // extract and encrypt the data
983 DB::RowVector encryptedRows;
984 retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
985 if(retCode != CKM_API_SUCCESS)
989 handler.database.saveRows(name, ownerLabel, encryptedRows);
990 transaction.commit();
992 return CKM_API_SUCCESS;
996 int CKMLogic::createKeyPairHelper(
997 const Credentials &cred,
998 const KeyType key_type,
999 const int additional_param,
1000 const Name &namePrivate,
1001 const Label &labelPrivate,
1002 const Name &namePublic,
1003 const Label &labelPublic,
1004 const PolicySerializable &policyPrivate,
1005 const PolicySerializable &policyPublic)
1007 if (0 == m_userDataMap.count(cred.uid))
1008 return CKM_API_ERROR_DB_LOCKED;
1014 case KeyType::KEY_RSA_PUBLIC:
1015 case KeyType::KEY_RSA_PRIVATE:
1016 retCode = CryptoService::createKeyPairRSA(additional_param, prv, pub);
1019 case KeyType::KEY_DSA_PUBLIC:
1020 case KeyType::KEY_DSA_PRIVATE:
1021 retCode = CryptoService::createKeyPairDSA(additional_param, prv, pub);
1024 case KeyType::KEY_ECDSA_PUBLIC:
1025 case KeyType::KEY_ECDSA_PRIVATE:
1026 retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(additional_param), prv, pub);
1030 return CKM_API_ERROR_INPUT_PARAM;
1033 if (CKM_CRYPTO_CREATEKEY_SUCCESS != retCode)
1035 LogDebug("CryptoService error with code: " << retCode);
1036 return CKM_API_ERROR_SERVER_ERROR; // TODO error code
1039 auto &database = m_userDataMap[cred.uid].database;
1040 DB::Crypto::Transaction transaction(&database);
1042 retCode = saveDataHelper(cred,
1045 DataType(prv.getType()),
1048 if (CKM_API_SUCCESS != retCode)
1051 retCode = saveDataHelper(cred,
1054 DataType(pub.getType()),
1057 if (CKM_API_SUCCESS != retCode)
1060 transaction.commit();
1065 RawBuffer CKMLogic::createKeyPair(
1066 const Credentials &cred,
1067 LogicCommand protocol_cmd,
1069 const int additional_param,
1070 const Name &namePrivate,
1071 const Label &labelPrivate,
1072 const Name &namePublic,
1073 const Label &labelPublic,
1074 const PolicySerializable &policyPrivate,
1075 const PolicySerializable &policyPublic)
1077 int retCode = CKM_API_SUCCESS;
1079 KeyType key_type = KeyType::KEY_NONE;
1080 switch(protocol_cmd)
1082 case LogicCommand::CREATE_KEY_PAIR_RSA:
1083 key_type = KeyType::KEY_RSA_PUBLIC;
1085 case LogicCommand::CREATE_KEY_PAIR_DSA:
1086 key_type = KeyType::KEY_DSA_PUBLIC;
1088 case LogicCommand::CREATE_KEY_PAIR_ECDSA:
1089 key_type = KeyType::KEY_ECDSA_PUBLIC;
1096 retCode = createKeyPairHelper(
1106 } catch (DB::Crypto::Exception::TransactionError &e) {
1107 LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1108 retCode = CKM_API_ERROR_DB_ERROR;
1109 } catch (CKM::CryptoLogic::Exception::Base &e) {
1110 LogDebug("CryptoLogic error: " << e.GetMessage());
1111 retCode = CKM_API_ERROR_SERVER_ERROR;
1112 } catch (DB::Crypto::Exception::InternalError &e) {
1113 LogDebug("DB::Crypto internal error: " << e.GetMessage());
1114 retCode = CKM_API_ERROR_DB_ERROR;
1115 } catch (const CKM::Exception &e) {
1116 LogError("CKM::Exception: " << e.GetMessage());
1117 retCode = CKM_API_ERROR_SERVER_ERROR;
1120 return MessageBuffer::Serialize(static_cast<int>(protocol_cmd), commandId, retCode).Pop();
1123 int CKMLogic::readCertificateHelper(
1124 const Credentials &cred,
1125 const LabelNameVector &labelNameVector,
1126 CertificateImplVector &certVector)
1129 for (auto &i: labelNameVector) {
1130 int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), row);
1131 if (ec != CKM_API_SUCCESS)
1133 certVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
1135 // try to read chain certificates (if present)
1136 DB::RowVector rawCaChain;
1137 ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain);
1138 if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1140 for(auto &rawCaCert : rawCaChain)
1141 certVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER));
1143 return CKM_API_SUCCESS;
1146 int CKMLogic::getCertificateChainHelper(
1147 const CertificateImpl &cert,
1148 const RawBufferVector &untrustedCertificates,
1149 const RawBufferVector &trustedCertificates,
1150 bool useTrustedSystemCertificates,
1151 RawBufferVector &chainRawVector)
1153 CertificateImplVector untrustedCertVector;
1154 CertificateImplVector trustedCertVector;
1155 CertificateImplVector chainVector;
1158 return CKM_API_ERROR_INPUT_PARAM;
1160 for (auto &e: untrustedCertificates)
1161 untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1162 for (auto &e: trustedCertificates)
1163 trustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1165 CertificateStore store;
1166 int retCode = store.verifyCertificate(cert,
1167 untrustedCertVector,
1169 useTrustedSystemCertificates,
1170 m_accessControl.isCCMode(),
1172 if (retCode != CKM_API_SUCCESS)
1175 for (auto &e : chainVector)
1176 chainRawVector.push_back(e.getDER());
1177 return CKM_API_SUCCESS;
1180 int CKMLogic::getCertificateChainHelper(
1181 const Credentials &cred,
1182 const CertificateImpl &cert,
1183 const LabelNameVector &untrusted,
1184 const LabelNameVector &trusted,
1185 bool useTrustedSystemCertificates,
1186 RawBufferVector &chainRawVector)
1188 CertificateImplVector untrustedCertVector;
1189 CertificateImplVector trustedCertVector;
1190 CertificateImplVector chainVector;
1194 return CKM_API_ERROR_INPUT_PARAM;
1196 int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1197 if (retCode != CKM_API_SUCCESS)
1199 retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1200 if (retCode != CKM_API_SUCCESS)
1203 CertificateStore store;
1204 retCode = store.verifyCertificate(cert,
1205 untrustedCertVector,
1207 useTrustedSystemCertificates,
1208 m_accessControl.isCCMode(),
1210 if (retCode != CKM_API_SUCCESS)
1213 for (auto &i: chainVector)
1214 chainRawVector.push_back(i.getDER());
1216 return CKM_API_SUCCESS;
1219 RawBuffer CKMLogic::getCertificateChain(
1220 const Credentials & /*cred*/,
1222 const RawBuffer &certificate,
1223 const RawBufferVector &untrustedCertificates,
1224 const RawBufferVector &trustedCertificates,
1225 bool useTrustedSystemCertificates)
1227 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1228 RawBufferVector chainRawVector;
1229 int retCode = CKM_API_ERROR_UNKNOWN;
1231 retCode = getCertificateChainHelper(cert,
1232 untrustedCertificates,
1233 trustedCertificates,
1234 useTrustedSystemCertificates,
1236 } catch (const CryptoLogic::Exception::Base &e) {
1237 LogError("CryptoLogic failed with message: " << e.GetMessage());
1238 retCode = CKM_API_ERROR_SERVER_ERROR;
1239 } catch (const DB::Crypto::Exception::Base &e) {
1240 LogError("DB::Crypto failed with message: " << e.GetMessage());
1241 retCode = CKM_API_ERROR_DB_ERROR;
1242 } catch (const std::exception& e) {
1243 LogError("STD exception " << e.what());
1244 retCode = CKM_API_ERROR_SERVER_ERROR;
1246 LogError("Unknown error.");
1249 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1253 return response.Pop();
1256 RawBuffer CKMLogic::getCertificateChain(
1257 const Credentials &cred,
1259 const RawBuffer &certificate,
1260 const LabelNameVector &untrustedCertificates,
1261 const LabelNameVector &trustedCertificates,
1262 bool useTrustedSystemCertificates)
1264 int retCode = CKM_API_ERROR_UNKNOWN;
1265 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1266 RawBufferVector chainRawVector;
1268 retCode = getCertificateChainHelper(cred,
1270 untrustedCertificates,
1271 trustedCertificates,
1272 useTrustedSystemCertificates,
1274 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1275 LogError("CryptoLogic failed with message: " << e.GetMessage());
1276 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1277 } catch (const CryptoLogic::Exception::Base &e) {
1278 LogError("CryptoLogic failed with message: " << e.GetMessage());
1279 retCode = CKM_API_ERROR_SERVER_ERROR;
1280 } catch (const DB::Crypto::Exception::Base &e) {
1281 LogError("DB::Crypto failed with message: " << e.GetMessage());
1282 retCode = CKM_API_ERROR_DB_ERROR;
1283 } catch (const std::exception& e) {
1284 LogError("STD exception " << e.what());
1285 retCode = CKM_API_ERROR_SERVER_ERROR;
1287 LogError("Unknown error.");
1290 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1294 return response.Pop();
1297 RawBuffer CKMLogic::createSignature(
1298 const Credentials &cred,
1300 const Name &privateKeyName,
1301 const Label & ownerLabel,
1302 const Password &password, // password for private_key
1303 const RawBuffer &message,
1304 const HashAlgorithm hash,
1305 const RSAPaddingAlgorithm padding)
1309 RawBuffer signature;
1311 int retCode = CKM_API_SUCCESS;
1314 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
1315 if(retCode == CKM_API_SUCCESS)
1317 KeyImpl keyParsed(row.data, Password());
1318 if (keyParsed.empty())
1319 retCode = CKM_API_ERROR_SERVER_ERROR;
1321 retCode = cs.createSignature(keyParsed, message, hash, padding, signature);
1323 } catch (const KeyProvider::Exception::Base &e) {
1324 LogError("KeyProvider failed with message: " << e.GetMessage());
1325 retCode = CKM_API_ERROR_SERVER_ERROR;
1326 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1327 LogError("CryptoLogic failed with message: " << e.GetMessage());
1328 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1329 } catch (const CryptoLogic::Exception::Base &e) {
1330 LogError("CryptoLogic failed with message: " << e.GetMessage());
1331 retCode = CKM_API_ERROR_SERVER_ERROR;
1332 } catch (const DB::Crypto::Exception::Base &e) {
1333 LogError("DB::Crypto failed with message: " << e.GetMessage());
1334 retCode = CKM_API_ERROR_DB_ERROR;
1335 } catch (const CKM::Exception &e) {
1336 LogError("Unknown CKM::Exception: " << e.GetMessage());
1337 retCode = CKM_API_ERROR_SERVER_ERROR;
1340 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1344 return response.Pop();
1347 RawBuffer CKMLogic::verifySignature(
1348 const Credentials &cred,
1350 const Name &publicKeyOrCertName,
1351 const Label & ownerLabel,
1352 const Password &password, // password for public_key (optional)
1353 const RawBuffer &message,
1354 const RawBuffer &signature,
1355 const HashAlgorithm hash,
1356 const RSAPaddingAlgorithm padding)
1358 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1366 // try certificate first - looking for a public key.
1367 // in case of PKCS, pub key from certificate will be found first
1368 // rather than private key from the same PKCS.
1369 retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
1370 if (retCode == CKM_API_SUCCESS) {
1371 CertificateImpl cert(row.data, DataFormat::FORM_DER);
1372 key = cert.getKeyImpl();
1373 } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1374 retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
1375 if (retCode != CKM_API_SUCCESS)
1377 key = KeyImpl(row.data);
1383 retCode = CKM_API_ERROR_SERVER_ERROR;
1387 retCode = cs.verifySignature(key, message, signature, hash, padding);
1389 } catch (const CryptoService::Exception::Crypto_internal &e) {
1390 LogError("KeyProvider failed with message: " << e.GetMessage());
1391 retCode = CKM_API_ERROR_SERVER_ERROR;
1392 } catch (const CryptoService::Exception::opensslError &e) {
1393 LogError("KeyProvider failed with message: " << e.GetMessage());
1394 retCode = CKM_API_ERROR_SERVER_ERROR;
1395 } catch (const KeyProvider::Exception::Base &e) {
1396 LogError("KeyProvider failed with error: " << e.GetMessage());
1397 retCode = CKM_API_ERROR_SERVER_ERROR;
1398 } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
1399 LogError("CryptoLogic failed with message: " << e.GetMessage());
1400 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
1401 } catch (const CryptoLogic::Exception::Base &e) {
1402 LogError("CryptoLogic failed with message: " << e.GetMessage());
1403 retCode = CKM_API_ERROR_SERVER_ERROR;
1404 } catch (const DB::Crypto::Exception::Base &e) {
1405 LogError("DB::Crypto failed with message: " << e.GetMessage());
1406 retCode = CKM_API_ERROR_DB_ERROR;
1407 } catch (const CKM::Exception &e) {
1408 LogError("Unknown CKM::Exception: " << e.GetMessage());
1409 retCode = CKM_API_ERROR_SERVER_ERROR;
1412 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1415 return response.Pop();
1418 int CKMLogic::setPermissionHelper(
1419 const Credentials &cred, // who's the client
1421 const Label &label, // who's the owner
1422 const Label &accessorLabel, // who will get the access
1423 const PermissionMask permissionMask)
1425 // we don't know the client
1426 if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1427 return CKM_API_ERROR_INPUT_PARAM;
1429 // use client label if not explicitly provided
1430 const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1432 // verify name and label are correct
1433 if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1434 return CKM_API_ERROR_INPUT_PARAM;
1436 // currently we don't support modification of owner's permissions to his own rows
1437 if (ownerLabel==accessorLabel)
1438 return CKM_API_ERROR_INPUT_PARAM;
1440 // can the client modify permissions to owner's row?
1441 int access_ec = m_accessControl.canModify(ownerLabel, cred.smackLabel);
1442 if(access_ec != CKM_API_SUCCESS)
1445 if (0 == m_userDataMap.count(cred.uid))
1446 return CKM_API_ERROR_DB_LOCKED;
1448 auto &database = m_userDataMap[cred.uid].database;
1449 DB::Crypto::Transaction transaction(&database);
1451 if( !database.isNameLabelPresent(name, ownerLabel) )
1452 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1454 // removing non-existing permissions: fail
1455 if(permissionMask == Permission::NONE)
1457 if(!database.getPermissionRow(name, ownerLabel, accessorLabel))
1458 return CKM_API_ERROR_INPUT_PARAM;
1461 // set permissions to the row owned by ownerLabel for accessorLabel
1462 database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1463 transaction.commit();
1465 return CKM_API_SUCCESS;
1468 RawBuffer CKMLogic::setPermission(
1469 const Credentials &cred,
1474 const Label &accessorLabel,
1475 const PermissionMask permissionMask)
1479 retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1480 } Catch (CKM::Exception) {
1481 LogError("Error in set row!");
1482 retCode = CKM_API_ERROR_DB_ERROR;
1485 return MessageBuffer::Serialize(command, msgID, retCode).Pop();