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 <vconf/vconf.h>
23 #include <dpl/serialization.h>
24 #include <dpl/log/log.h>
25 #include <ckm/ckm-error.h>
26 #include <ckm/ckm-type.h>
27 #include <key-provider.h>
28 #include <file-system.h>
29 #include <CryptoService.h>
30 #include <ckm-logic.h>
34 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
36 bool isLabelValid(const CKM::Label &label) {
37 // TODO: copy code from libprivilege control (for check smack label)
38 if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos)
43 bool isNameValid(const CKM::Name &name) {
44 if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
49 } // anonymous namespace
55 if (CKM_API_SUCCESS != m_certStore.setSystemCertificateDir(CERT_SYSTEM_DIR)) {
56 LogError("Fatal error in CertificateStore::setSystemCertificateDir. Chain creation will not work");
59 m_accessControl.updateCCMode();
62 CKMLogic::~CKMLogic(){}
64 void CKMLogic::loadDKEKFile(uid_t user, const Password &password, bool apiReq) {
65 auto &handle = m_userDataMap[user];
69 auto wrappedDKEKMain = fs.getDKEK();
70 auto wrappedDKEKBackup = fs.getDKEKBackup();
72 if (wrappedDKEKMain.empty() && wrappedDKEKBackup.empty()) {
73 wrappedDKEKMain = KeyProvider::generateDomainKEK(std::to_string(user), password);
74 fs.saveDKEK(wrappedDKEKMain);
77 chooseDKEKFile(handle, password, wrappedDKEKMain, wrappedDKEKBackup);
79 if (!password.empty() || apiReq) {
80 handle.isDKEKConfirmed = true;
82 if (true == handle.isMainDKEK)
83 fs.removeDKEKBackup();
89 void CKMLogic::chooseDKEKFile(
91 const Password &password,
92 const RawBuffer &first,
93 const RawBuffer &second)
96 handle.keyProvider = KeyProvider(first, password);
97 handle.isMainDKEK = true;
98 } catch (const KeyProvider::Exception::Base &e) {
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.saveDKEKBackup(fs.getDKEK());
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 // TODO try catch for all errors that should be supported by error code
121 int retCode = CKM_API_SUCCESS;
124 if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
125 auto &handle = m_userDataMap[user];
128 loadDKEKFile(user, password, apiRequest);
130 auto wrappedDatabaseDEK = fs.getDBDEK();
132 if (wrappedDatabaseDEK.empty()) {
133 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
134 fs.saveDBDEK(wrappedDatabaseDEK);
137 RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
138 handle.database = DBCrypto(fs.getDBPath(), key);
139 handle.crypto = CryptoLogic();
141 // remove data of removed apps during locked state
142 AppLabelVector removedApps = fs.clearRemovedsApps();
143 for(auto& appSmackLabel : removedApps) {
144 handle.database.deleteKey(appSmackLabel);
146 } else if (apiRequest == true && m_userDataMap[user].isDKEKConfirmed == false) {
147 // now we will try to choose the DKEK key and remove old one
148 loadDKEKFile(user, password, apiRequest);
150 } catch (const KeyProvider::Exception::PassWordError &e) {
151 LogError("Incorrect Password " << e.GetMessage());
152 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
153 } catch (const KeyProvider::Exception::Base &e) {
154 LogError("Error in KeyProvider " << e.GetMessage());
155 retCode = CKM_API_ERROR_SERVER_ERROR;
156 } catch (const CryptoLogic::Exception::Base &e) {
157 LogError("CryptoLogic error: " << e.GetMessage());
158 retCode = CKM_API_ERROR_SERVER_ERROR;
159 } catch (const CKM::Exception &e) {
160 LogError("CKM::Exception: " << e.GetMessage());
161 retCode = CKM_API_ERROR_SERVER_ERROR;
164 if(retCode != CKM_API_SUCCESS) {
165 // When not successful, UserData in m_userDataMap should be erased.
166 // Because other operations make decision based on the existence of UserData in m_userDataMap.
167 m_userDataMap.erase(user);
170 return MessageBuffer::Serialize(retCode).Pop();
173 RawBuffer CKMLogic::updateCCMode() {
174 m_accessControl.updateCCMode();
175 return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
178 RawBuffer CKMLogic::lockUserKey(uid_t user) {
179 int retCode = CKM_API_SUCCESS;
180 // TODO try catch for all errors that should be supported by error code
181 m_userDataMap.erase(user);
183 return MessageBuffer::Serialize(retCode).Pop();
187 RawBuffer CKMLogic::removeUserData(uid_t user) {
188 int retCode = CKM_API_SUCCESS;
189 // TODO try catch for all errors that should be supported by error code
190 m_userDataMap.erase(user);
195 return MessageBuffer::Serialize(retCode).Pop();
198 RawBuffer CKMLogic::changeUserPassword(
200 const Password &oldPassword,
201 const Password &newPassword)
203 int retCode = CKM_API_SUCCESS;
205 loadDKEKFile(user, oldPassword, true);
206 saveDKEKFile(user, newPassword);
207 } catch (const KeyProvider::Exception::PassWordError &e) {
208 LogError("Incorrect Password " << e.GetMessage());
209 retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
210 } catch (const KeyProvider::Exception::Base &e) {
211 LogError("Error in KeyProvider " << e.GetMessage());
212 retCode = CKM_API_ERROR_SERVER_ERROR;
213 } catch (const CKM::Exception &e) {
214 LogError("CKM::Exception: " << e.GetMessage());
215 retCode = CKM_API_ERROR_SERVER_ERROR;
218 return MessageBuffer::Serialize(retCode).Pop();
221 RawBuffer CKMLogic::resetUserPassword(
223 const Password &newPassword)
225 int retCode = CKM_API_SUCCESS;
227 if (0 == m_userDataMap.count(user)) {
228 retCode = CKM_API_ERROR_BAD_REQUEST;
230 saveDKEKFile(user, newPassword);
233 return MessageBuffer::Serialize(retCode).Pop();
236 RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
237 int retCode = CKM_API_SUCCESS;
241 if (smackLabel.empty()) {
242 retCode = CKM_API_ERROR_INPUT_PARAM;
244 UidVector uids = FileSystem::getUIDsFromDBFile();
245 for (auto userId : uids) {
246 if (0 == m_userDataMap.count(userId)) {
247 FileSystem fs(userId);
248 fs.addRemovedApp(smackLabel);
250 auto &handle = m_userDataMap[userId];
251 handle.database.deleteKey(smackLabel);
256 } catch (const DBCrypto::Exception::InternalError &e) {
257 LogError("DBCrypto couldn't remove data: " << e.GetMessage());
258 retCode = CKM_API_ERROR_DB_ERROR;
259 } catch (const DBCrypto::Exception::TransactionError &e) {
260 LogError("DBCrypto transaction failed with message " << e.GetMessage());
261 retCode = CKM_API_ERROR_DB_ERROR;
264 return MessageBuffer::Serialize(retCode).Pop();
267 int CKMLogic::checkSaveConditions(
268 const Credentials &cred,
271 const Label &ownerLabel)
273 // verify name and label are correct
274 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
275 LogWarning("Invalid parameter passed to key-manager");
276 return CKM_API_ERROR_INPUT_PARAM;
279 // check if allowed to save using ownerLabel
280 int access_ec = m_accessControl.canSave(ownerLabel, cred.smackLabel);
281 if(access_ec != CKM_API_SUCCESS)
283 LogWarning("label " << cred.smackLabel << " can not save rows using label " << ownerLabel);
287 // check if not a duplicate
288 if( handler.database.isNameLabelPresent(name, cred.smackLabel) )
289 return CKM_API_ERROR_DB_ALIAS_EXISTS;
291 // encryption section
292 if (!handler.crypto.haveKey(cred.smackLabel)) {
294 auto key_optional = handler.database.getKey(cred.smackLabel);
296 LogDebug("No Key in database found. Generating new one for label: "
298 got_key = handler.keyProvider.generateDEK(cred.smackLabel);
299 handler.database.saveKey(cred.smackLabel, got_key);
301 LogDebug("Key from DB");
302 got_key = *key_optional;
305 got_key = handler.keyProvider.getPureDEK(got_key);
306 handler.crypto.pushKey(cred.smackLabel, got_key);
309 return CKM_API_SUCCESS;
312 DBRow CKMLogic::createEncryptedDBRow(
317 const RawBuffer &data,
318 const Policy &policy) const
320 DBRow row = { name, label, policy.extractable, dataType, DBCMAlgType::NONE,
321 0, RawBuffer(), static_cast<int>(data.size()), data, RawBuffer() };
323 // do not encrypt data with password during cc_mode on
324 if(m_accessControl.isCCMode()) {
325 crypto.encryptRow("", row);
327 crypto.encryptRow(policy.password, row);
332 int CKMLogic::verifyBinaryData(DBDataType dataType, const RawBuffer &input_data) const
334 // verify the data integrity
335 if (dataType.isKey())
337 KeyShPtr output_key = CKM::Key::create(input_data);
338 if(output_key.get() == NULL)
340 LogError("provided binary data is not valid key data");
341 return CKM_API_ERROR_INPUT_PARAM;
344 else if (dataType.isCertificate() || dataType.isChainCert())
346 CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
347 if(cert.get() == NULL)
349 LogError("provided binary data is not valid certificate data");
350 return CKM_API_ERROR_INPUT_PARAM;
353 // TODO: add here BINARY_DATA verification, i.e: max size etc.
354 return CKM_API_SUCCESS;
357 RawBuffer CKMLogic::saveData(
358 const Credentials &cred,
362 const RawBuffer &data,
364 const PolicySerializable &policy)
367 if (0 == m_userDataMap.count(cred.uid))
368 retCode = CKM_API_ERROR_DB_LOCKED;
372 // check if data is correct
373 retCode = verifyBinaryData(dataType, data);
374 if(retCode == CKM_API_SUCCESS)
376 retCode = saveDataHelper(cred, name, label, dataType, data, policy);
378 } catch (const KeyProvider::Exception::Base &e) {
379 LogError("KeyProvider failed with message: " << e.GetMessage());
380 retCode = CKM_API_ERROR_SERVER_ERROR;
381 } catch (const CryptoLogic::Exception::Base &e) {
382 LogError("CryptoLogic failed with message: " << e.GetMessage());
383 retCode = CKM_API_ERROR_SERVER_ERROR;
384 } catch (const DBCrypto::Exception::InternalError &e) {
385 LogError("DBCrypto failed with message: " << e.GetMessage());
386 retCode = CKM_API_ERROR_DB_ERROR;
387 } catch (const DBCrypto::Exception::TransactionError &e) {
388 LogError("DBCrypto transaction failed with message " << e.GetMessage());
389 retCode = CKM_API_ERROR_DB_ERROR;
393 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
396 static_cast<int>(dataType));
397 return response.Pop();
400 int CKMLogic::extractPKCS12Data(
403 const Label &ownerLabel,
404 const PKCS12Serializable &pkcs,
405 const PolicySerializable &keyPolicy,
406 const PolicySerializable &certPolicy,
407 DBRowVector &output) const
409 // private key is mandatory
411 return CKM_API_ERROR_INVALID_FORMAT;
412 Key* keyPtr = pkcs.getKey().get();
413 DBDataType keyType = DBDataType(keyPtr->getType());
414 RawBuffer keyData = keyPtr->getDER();
415 int retCode = verifyBinaryData(keyType, keyData);
416 if(retCode != CKM_API_SUCCESS)
418 output.push_back(createEncryptedDBRow(crypto, name, ownerLabel, keyType, keyData, keyPolicy));
420 // certificate is mandatory
421 if( !pkcs.getCertificate() )
422 return CKM_API_ERROR_INVALID_FORMAT;
423 RawBuffer certData = pkcs.getCertificate().get()->getDER();
424 retCode = verifyBinaryData(DBDataType::CERTIFICATE, certData);
425 if(retCode != CKM_API_SUCCESS)
427 output.push_back(createEncryptedDBRow(crypto, name, ownerLabel, DBDataType::CERTIFICATE, certData, certPolicy));
430 unsigned int cert_index = 0;
431 for(const auto & ca : pkcs.getCaCertificateShPtrVector())
433 DBDataType chainDataType = DBDataType::getChainDatatype(cert_index ++);
434 RawBuffer caCertData = ca->getDER();
435 int retCode = verifyBinaryData(chainDataType, caCertData);
436 if(retCode != CKM_API_SUCCESS)
439 output.push_back(createEncryptedDBRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy));
442 return CKM_API_SUCCESS;
445 RawBuffer CKMLogic::savePKCS12(
446 const Credentials &cred,
450 const PKCS12Serializable &pkcs,
451 const PolicySerializable &keyPolicy,
452 const PolicySerializable &certPolicy)
455 if (0 == m_userDataMap.count(cred.uid))
456 retCode = CKM_API_ERROR_DB_LOCKED;
460 retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
461 } catch (const KeyProvider::Exception::Base &e) {
462 LogError("KeyProvider failed with message: " << e.GetMessage());
463 retCode = CKM_API_ERROR_SERVER_ERROR;
464 } catch (const CryptoLogic::Exception::Base &e) {
465 LogError("CryptoLogic failed with message: " << e.GetMessage());
466 retCode = CKM_API_ERROR_SERVER_ERROR;
467 } catch (const DBCrypto::Exception::InternalError &e) {
468 LogError("DBCrypto failed with message: " << e.GetMessage());
469 retCode = CKM_API_ERROR_DB_ERROR;
470 } catch (const DBCrypto::Exception::TransactionError &e) {
471 LogError("DBCrypto transaction failed with message " << e.GetMessage());
472 retCode = CKM_API_ERROR_DB_ERROR;
476 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
479 return response.Pop();
483 int CKMLogic::removeDataHelper(
484 const Credentials &cred,
486 const Label &ownerLabel)
488 if (0 == m_userDataMap.count(cred.uid))
489 return CKM_API_ERROR_DB_LOCKED;
491 if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
492 LogError("Invalid label or name format");
493 return CKM_API_ERROR_INPUT_PARAM;
496 auto &database = m_userDataMap[cred.uid].database;
497 DBCrypto::Transaction transaction(&database);
499 // read and check permissions
500 PermissionMaskOptional permissionRowOpt =
501 database.getPermissionRow(name, ownerLabel, cred.smackLabel);
502 int access_ec = m_accessControl.canDelete(PermissionForLabel(cred.smackLabel, permissionRowOpt));
503 if(access_ec != CKM_API_SUCCESS)
505 LogWarning("access control check result: " << access_ec);
509 auto erased = database.deleteDBRow(name, ownerLabel);
510 // check if the data existed or not
512 transaction.commit();
514 LogError("No row for given name and label");
515 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
518 return CKM_API_SUCCESS;
521 RawBuffer CKMLogic::removeData(
522 const Credentials &cred,
529 // use client label if not explicitly provided
530 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
532 retCode = removeDataHelper(cred, name, ownerLabel);
533 } Catch (CKM::Exception) {
534 LogError("Error in deleting row!");
535 retCode = CKM_API_ERROR_DB_ERROR;
538 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
541 return response.Pop();
544 int CKMLogic::readSingleRow(const Name &name,
545 const Label &ownerLabel,
550 DBCrypto::DBRowOptional row_optional;
551 if (dataType.isKey())
553 // read all key types
554 row_optional = database.getDBRow(name,
556 DBDataType::DB_KEY_FIRST,
557 DBDataType::DB_KEY_LAST);
559 // read anything else
560 row_optional = database.getDBRow(name,
566 LogError("No row for given name, label and type");
567 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
572 return CKM_API_SUCCESS;
576 int CKMLogic::readMultiRow(const Name &name,
577 const Label &ownerLabel,
582 if (dataType.isKey())
584 // read all key types
585 database.getDBRows(name,
587 DBDataType::DB_KEY_FIRST,
588 DBDataType::DB_KEY_LAST,
591 else if (dataType.isChainCert())
593 // read all key types
594 database.getDBRows(name,
596 DBDataType::DB_CHAIN_FIRST,
597 DBDataType::DB_CHAIN_LAST,
602 // read anything else
603 database.getDBRows(name,
610 LogError("No row for given name, label and type");
611 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
614 return CKM_API_SUCCESS;
617 int CKMLogic::checkDataPermissionsHelper(const Name &name,
618 const Label &ownerLabel,
619 const Label &accessorLabel,
624 PermissionMaskOptional permissionRowOpt =
625 database.getPermissionRow(name, ownerLabel, accessorLabel);
628 return m_accessControl.canExport(row, PermissionForLabel(accessorLabel, permissionRowOpt));
629 return m_accessControl.canRead(PermissionForLabel(accessorLabel, permissionRowOpt));
632 int CKMLogic::readDataHelper(
634 const Credentials &cred,
638 const Password &password,
641 if (0 == m_userDataMap.count(cred.uid))
642 return CKM_API_ERROR_DB_LOCKED;
644 // use client label if not explicitly provided
645 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
647 if (!isNameValid(name) || !isLabelValid(ownerLabel))
648 return CKM_API_ERROR_INPUT_PARAM;
650 auto &handler = m_userDataMap[cred.uid];
653 DBCrypto::Transaction transaction(&handler.database);
654 int ec = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
655 if(CKM_API_SUCCESS != ec)
658 // all read rows belong to the same owner
659 DBRow & firstRow = rows.at(0);
661 // check access rights
662 ec = checkDataPermissionsHelper(name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database);
663 if(CKM_API_SUCCESS != ec)
667 if (!handler.crypto.haveKey(firstRow.ownerLabel)) {
669 auto key_optional = handler.database.getKey(firstRow.ownerLabel);
671 LogError("No key for given label in database");
672 return CKM_API_ERROR_DB_ERROR;
675 key = handler.keyProvider.getPureDEK(key);
676 handler.crypto.pushKey(firstRow.ownerLabel, key);
678 for(auto &row : rows)
679 handler.crypto.decryptRow(password, row);
681 return CKM_API_SUCCESS;
684 int CKMLogic::readDataHelper(
686 const Credentials &cred,
690 const Password &password,
693 if (0 == m_userDataMap.count(cred.uid))
694 return CKM_API_ERROR_DB_LOCKED;
696 // use client label if not explicitly provided
697 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
699 if (!isNameValid(name) || !isLabelValid(ownerLabel))
700 return CKM_API_ERROR_INPUT_PARAM;
702 auto &handler = m_userDataMap[cred.uid];
705 DBCrypto::Transaction transaction(&handler.database);
706 int ec = readSingleRow(name, ownerLabel, dataType, handler.database, row);
707 if(CKM_API_SUCCESS != ec)
711 // check access rights
712 ec = checkDataPermissionsHelper(name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
713 if(CKM_API_SUCCESS != ec)
717 if (!handler.crypto.haveKey(row.ownerLabel)) {
719 auto key_optional = handler.database.getKey(row.ownerLabel);
721 LogError("No key for given label in database");
722 return CKM_API_ERROR_DB_ERROR;
725 key = handler.keyProvider.getPureDEK(key);
726 handler.crypto.pushKey(row.ownerLabel, key);
728 handler.crypto.decryptRow(password, row);
730 return CKM_API_SUCCESS;
733 RawBuffer CKMLogic::getData(
734 const Credentials &cred,
739 const Password &password)
741 int retCode = CKM_API_SUCCESS;
745 retCode = readDataHelper(true, cred, dataType, name, label, password, row);
746 } catch (const KeyProvider::Exception::Base &e) {
747 LogError("KeyProvider failed with error: " << e.GetMessage());
748 retCode = CKM_API_ERROR_SERVER_ERROR;
749 } catch (const CryptoLogic::Exception::Base &e) {
750 LogError("CryptoLogic failed with message: " << e.GetMessage());
751 retCode = CKM_API_ERROR_SERVER_ERROR;
752 } catch (const DBCrypto::Exception::Base &e) {
753 LogError("DBCrypto failed with message: " << e.GetMessage());
754 retCode = CKM_API_ERROR_DB_ERROR;
757 if (CKM_API_SUCCESS != retCode) {
759 row.dataType = dataType;
762 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
765 static_cast<int>(row.dataType),
767 return response.Pop();
770 int CKMLogic::getPKCS12Helper(
771 const Credentials &cred,
775 CertificateShPtr & cert,
776 CertificateShPtrVector & caChain)
780 // read private key (mandatory)
782 retCode = readDataHelper(true, cred, DBDataType::DB_KEY_FIRST, name, label, CKM::Password(), privKeyRow);
783 if(retCode != CKM_API_SUCCESS)
785 privKey = CKM::Key::create(privKeyRow.data);
787 // read certificate (mandatory)
789 retCode = readDataHelper(true, cred, DBDataType::CERTIFICATE, name, label, CKM::Password(), certRow);
790 if(retCode != CKM_API_SUCCESS)
792 cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER);
794 // read CA cert chain (optional)
795 DBRowVector rawCaChain;
796 retCode = readDataHelper(true, cred, DBDataType::DB_CHAIN_FIRST, name, label, CKM::Password(), rawCaChain);
797 if(retCode != CKM_API_SUCCESS &&
798 retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
800 for(auto &rawCaCert : rawCaChain)
801 caChain.push_back(CKM::Certificate::create(rawCaCert.data, DataFormat::FORM_DER));
803 // if anything found, return it
804 if(privKey || cert || caChain.size()>0)
805 retCode = CKM_API_SUCCESS;
810 RawBuffer CKMLogic::getPKCS12(
811 const Credentials &cred,
817 PKCS12Serializable output;
821 CertificateShPtr cert;
822 CertificateShPtrVector caChain;
823 retCode = getPKCS12Helper(cred, name, label, privKey, cert, caChain);
826 if(retCode == CKM_API_SUCCESS)
827 output = PKCS12Serializable(privKey, cert, caChain);
829 } catch (const KeyProvider::Exception::Base &e) {
830 LogError("KeyProvider failed with error: " << e.GetMessage());
831 retCode = CKM_API_ERROR_SERVER_ERROR;
832 } catch (const CryptoLogic::Exception::Base &e) {
833 LogError("CryptoLogic failed with message: " << e.GetMessage());
834 retCode = CKM_API_ERROR_SERVER_ERROR;
835 } catch (const DBCrypto::Exception::Base &e) {
836 LogError("DBCrypto failed with message: " << e.GetMessage());
837 retCode = CKM_API_ERROR_DB_ERROR;
840 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
844 return response.Pop();
847 RawBuffer CKMLogic::getDataList(
848 const Credentials &cred,
852 int retCode = CKM_API_SUCCESS;
853 LabelNameVector labelNameVector;
855 if (0 < m_userDataMap.count(cred.uid)) {
856 auto &database = m_userDataMap[cred.uid].database;
859 if (dataType.isKey()) {
860 // list all key types
861 database.listNames(cred.smackLabel,
863 DBDataType::DB_KEY_FIRST,
864 DBDataType::DB_KEY_LAST);
866 // list anything else
867 database.listNames(cred.smackLabel,
872 Catch (CKM::Exception) {
873 LogError("Failed to get names");
874 retCode = CKM_API_ERROR_DB_ERROR;
877 retCode = CKM_API_ERROR_DB_LOCKED;
880 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
883 static_cast<int>(dataType),
885 return response.Pop();
888 int CKMLogic::saveDataHelper(
889 const Credentials &cred,
893 const RawBuffer &data,
894 const PolicySerializable &policy)
896 auto &handler = m_userDataMap[cred.uid];
898 // use client label if not explicitly provided
899 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
901 // check if save is possible
902 DBCrypto::Transaction transaction(&handler.database);
903 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
904 if(retCode != CKM_API_SUCCESS)
908 DBRow encryptedRow = createEncryptedDBRow(handler.crypto, name, ownerLabel, dataType, data, policy);
909 handler.database.saveDBRow(encryptedRow);
911 transaction.commit();
912 return CKM_API_SUCCESS;
915 int CKMLogic::saveDataHelper(
916 const Credentials &cred,
919 const PKCS12Serializable &pkcs,
920 const PolicySerializable &keyPolicy,
921 const PolicySerializable &certPolicy)
923 auto &handler = m_userDataMap[cred.uid];
925 // use client label if not explicitly provided
926 const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
928 // check if save is possible
929 DBCrypto::Transaction transaction(&handler.database);
930 int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
931 if(retCode != CKM_API_SUCCESS)
934 // extract and encrypt the data
935 DBRowVector encryptedRows;
936 retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
937 if(retCode != CKM_API_SUCCESS)
941 handler.database.saveDBRows(name, ownerLabel, encryptedRows);
942 transaction.commit();
944 return CKM_API_SUCCESS;
948 int CKMLogic::createKeyPairHelper(
949 const Credentials &cred,
950 const KeyType key_type,
951 const int additional_param,
952 const Name &namePrivate,
953 const Label &labelPrivate,
954 const Name &namePublic,
955 const Label &labelPublic,
956 const PolicySerializable &policyPrivate,
957 const PolicySerializable &policyPublic)
959 if (0 == m_userDataMap.count(cred.uid))
960 return CKM_API_ERROR_DB_LOCKED;
966 case KeyType::KEY_RSA_PUBLIC:
967 case KeyType::KEY_RSA_PRIVATE:
968 retCode = CryptoService::createKeyPairRSA(additional_param, prv, pub);
971 case KeyType::KEY_DSA_PUBLIC:
972 case KeyType::KEY_DSA_PRIVATE:
973 retCode = CryptoService::createKeyPairDSA(additional_param, prv, pub);
976 case KeyType::KEY_ECDSA_PUBLIC:
977 case KeyType::KEY_ECDSA_PRIVATE:
978 retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(additional_param), prv, pub);
982 return CKM_API_ERROR_INPUT_PARAM;
985 if (CKM_CRYPTO_CREATEKEY_SUCCESS != retCode)
987 LogDebug("CryptoService error with code: " << retCode);
988 return CKM_API_ERROR_SERVER_ERROR; // TODO error code
991 auto &database = m_userDataMap[cred.uid].database;
992 DBCrypto::Transaction transaction(&database);
994 retCode = saveDataHelper(cred,
997 DBDataType(prv.getType()),
1000 if (CKM_API_SUCCESS != retCode)
1003 retCode = saveDataHelper(cred,
1006 DBDataType(pub.getType()),
1009 if (CKM_API_SUCCESS != retCode)
1012 transaction.commit();
1017 RawBuffer CKMLogic::createKeyPair(
1018 const Credentials &cred,
1019 LogicCommand protocol_cmd,
1021 const int additional_param,
1022 const Name &namePrivate,
1023 const Label &labelPrivate,
1024 const Name &namePublic,
1025 const Label &labelPublic,
1026 const PolicySerializable &policyPrivate,
1027 const PolicySerializable &policyPublic)
1029 int retCode = CKM_API_SUCCESS;
1031 KeyType key_type = KeyType::KEY_NONE;
1032 switch(protocol_cmd)
1034 case LogicCommand::CREATE_KEY_PAIR_RSA:
1035 key_type = KeyType::KEY_RSA_PUBLIC;
1037 case LogicCommand::CREATE_KEY_PAIR_DSA:
1038 key_type = KeyType::KEY_DSA_PUBLIC;
1040 case LogicCommand::CREATE_KEY_PAIR_ECDSA:
1041 key_type = KeyType::KEY_ECDSA_PUBLIC;
1048 retCode = createKeyPairHelper(
1058 } catch (DBCrypto::Exception::TransactionError &e) {
1059 LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
1060 retCode = CKM_API_ERROR_DB_ERROR;
1061 } catch (CKM::CryptoLogic::Exception::Base &e) {
1062 LogDebug("CryptoLogic error: " << e.GetMessage());
1063 retCode = CKM_API_ERROR_SERVER_ERROR;
1064 } catch (DBCrypto::Exception::InternalError &e) {
1065 LogDebug("DBCrypto internal error: " << e.GetMessage());
1066 retCode = CKM_API_ERROR_DB_ERROR;
1069 return MessageBuffer::Serialize(static_cast<int>(protocol_cmd), commandId, retCode).Pop();
1072 RawBuffer CKMLogic::getCertificateChain(
1073 const Credentials &cred,
1075 const RawBuffer &certificate,
1076 const RawBufferVector &untrustedRawCertVector)
1080 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1081 CertificateImplVector untrustedCertVector;
1082 CertificateImplVector chainVector;
1083 RawBufferVector chainRawVector;
1085 for (auto &e: untrustedRawCertVector)
1086 untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1088 LogDebug("Cert is empty: " << cert.empty());
1090 int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector, m_accessControl.isCCMode());
1092 if (retCode == CKM_API_SUCCESS) {
1093 for (auto &e : chainVector)
1094 chainRawVector.push_back(e.getDER());
1097 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1101 return response.Pop();
1104 int CKMLogic::getCertificateChainHelper(
1105 const Credentials &cred,
1106 const RawBuffer &certificate,
1107 const LabelNameVector &labelNameVector,
1108 RawBufferVector & chainRawVector)
1110 CertificateImpl cert(certificate, DataFormat::FORM_DER);
1111 CertificateImplVector untrustedCertVector;
1112 CertificateImplVector chainVector;
1116 return CKM_API_ERROR_SERVER_ERROR;
1118 for (auto &i: labelNameVector) {
1119 int ec = readDataHelper(false, cred, DBDataType::CERTIFICATE, i.second, i.first, Password(), row);
1120 if (ec != CKM_API_SUCCESS)
1122 untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
1124 // try to read chain certificates (if present)
1125 DBRowVector rawCaChain;
1126 ec = readDataHelper(false, cred, DBDataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain);
1127 if(ec != CKM_API_SUCCESS &&
1128 ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1130 for(auto &rawCaCert : rawCaChain)
1131 untrustedCertVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER));
1134 int ec = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector, m_accessControl.isCCMode());
1135 if (ec != CKM_API_SUCCESS)
1138 for (auto &i: chainVector)
1139 chainRawVector.push_back(i.getDER());
1141 return CKM_API_SUCCESS;
1144 RawBuffer CKMLogic::getCertificateChain(
1145 const Credentials &cred,
1147 const RawBuffer &certificate,
1148 const LabelNameVector &labelNameVector)
1150 int retCode = CKM_API_SUCCESS;
1151 RawBufferVector chainRawVector;
1154 retCode = getCertificateChainHelper(cred, certificate, labelNameVector, chainRawVector);
1155 } catch (const CryptoLogic::Exception::Base &e) {
1156 LogError("CryptoLogic failed with message: " << e.GetMessage());
1157 retCode = CKM_API_ERROR_SERVER_ERROR;
1158 } catch (const DBCrypto::Exception::Base &e) {
1159 LogError("DBCrypto failed with message: " << e.GetMessage());
1160 retCode = CKM_API_ERROR_DB_ERROR;
1162 LogError("Unknown error.");
1165 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1169 return response.Pop();
1172 RawBuffer CKMLogic::createSignature(
1173 const Credentials &cred,
1175 const Name &privateKeyName,
1176 const Label & ownerLabel,
1177 const Password &password, // password for private_key
1178 const RawBuffer &message,
1179 const HashAlgorithm hash,
1180 const RSAPaddingAlgorithm padding)
1184 RawBuffer signature;
1186 int retCode = CKM_API_SUCCESS;
1189 retCode = readDataHelper(false, cred, DBDataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
1190 if(retCode == CKM_API_SUCCESS)
1192 KeyImpl keyParsed(row.data, Password());
1193 if (keyParsed.empty())
1194 retCode = CKM_API_ERROR_SERVER_ERROR;
1196 retCode = cs.createSignature(keyParsed, message, hash, padding, signature);
1198 } catch (const KeyProvider::Exception::Base &e) {
1199 LogError("KeyProvider failed with message: " << e.GetMessage());
1200 retCode = CKM_API_ERROR_SERVER_ERROR;
1201 } catch (const CryptoLogic::Exception::Base &e) {
1202 LogError("CryptoLogic failed with message: " << e.GetMessage());
1203 retCode = CKM_API_ERROR_SERVER_ERROR;
1204 } catch (const DBCrypto::Exception::Base &e) {
1205 LogError("DBCrypto failed with message: " << e.GetMessage());
1206 retCode = CKM_API_ERROR_DB_ERROR;
1207 } catch (const CKM::Exception &e) {
1208 LogError("Unknown CKM::Exception: " << e.GetMessage());
1209 retCode = CKM_API_ERROR_SERVER_ERROR;
1212 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1216 return response.Pop();
1219 RawBuffer CKMLogic::verifySignature(
1220 const Credentials &cred,
1222 const Name &publicKeyOrCertName,
1223 const Label & ownerLabel,
1224 const Password &password, // password for public_key (optional)
1225 const RawBuffer &message,
1226 const RawBuffer &signature,
1227 const HashAlgorithm hash,
1228 const RSAPaddingAlgorithm padding)
1230 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1238 // try certificate first - looking for a public key.
1239 // in case of PKCS, pub key from certificate will be found first
1240 // rather than private key from the same PKCS.
1241 retCode = readDataHelper(false, cred, DBDataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
1242 if (retCode == CKM_API_SUCCESS) {
1243 CertificateImpl cert(row.data, DataFormat::FORM_DER);
1244 key = cert.getKeyImpl();
1245 } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1246 retCode = readDataHelper(false, cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
1247 if (retCode != CKM_API_SUCCESS)
1249 key = KeyImpl(row.data);
1255 retCode = CKM_API_ERROR_SERVER_ERROR;
1259 retCode = cs.verifySignature(key, message, signature, hash, padding);
1261 } catch (const CryptoService::Exception::Crypto_internal &e) {
1262 LogError("KeyProvider failed with message: " << e.GetMessage());
1263 retCode = CKM_API_ERROR_SERVER_ERROR;
1264 } catch (const CryptoService::Exception::opensslError &e) {
1265 LogError("KeyProvider failed with message: " << e.GetMessage());
1266 retCode = CKM_API_ERROR_SERVER_ERROR;
1267 } catch (const KeyProvider::Exception::Base &e) {
1268 LogError("KeyProvider failed with error: " << e.GetMessage());
1269 retCode = CKM_API_ERROR_SERVER_ERROR;
1270 } catch (const CryptoLogic::Exception::Base &e) {
1271 LogError("CryptoLogic failed with message: " << e.GetMessage());
1272 retCode = CKM_API_ERROR_SERVER_ERROR;
1273 } catch (const DBCrypto::Exception::Base &e) {
1274 LogError("DBCrypto failed with message: " << e.GetMessage());
1275 retCode = CKM_API_ERROR_DB_ERROR;
1276 } catch (const CKM::Exception &e) {
1277 LogError("Unknown CKM::Exception: " << e.GetMessage());
1278 retCode = CKM_API_ERROR_SERVER_ERROR;
1281 auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1284 return response.Pop();
1287 int CKMLogic::setPermissionHelper(
1288 const Credentials &cred, // who's the client
1290 const Label &label, // who's the owner
1291 const Label &accessorLabel, // who will get the access
1292 const PermissionMask permissionMask)
1294 // we don't know the client
1295 if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1296 return CKM_API_ERROR_INPUT_PARAM;
1298 // use client label if not explicitly provided
1299 const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1301 // verify name and label are correct
1302 if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1303 return CKM_API_ERROR_INPUT_PARAM;
1305 // currently we don't support modification of owner's permissions to his own rows
1306 if (ownerLabel==accessorLabel)
1307 return CKM_API_ERROR_INPUT_PARAM;
1309 // can the client modify permissions to owner's row?
1310 int access_ec = m_accessControl.canModify(ownerLabel, cred.smackLabel);
1311 if(access_ec != CKM_API_SUCCESS)
1314 if (0 == m_userDataMap.count(cred.uid))
1315 return CKM_API_ERROR_DB_LOCKED;
1317 auto &database = m_userDataMap[cred.uid].database;
1318 DBCrypto::Transaction transaction(&database);
1320 if( !database.isNameLabelPresent(name, ownerLabel) )
1321 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1323 // removing non-existing permissions: fail
1324 if(permissionMask == Permission::NONE)
1326 if(!database.getPermissionRow(name, ownerLabel, accessorLabel))
1327 return CKM_API_ERROR_INPUT_PARAM;
1330 // set permissions to the row owned by ownerLabel for accessorLabel
1331 database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1332 transaction.commit();
1334 return CKM_API_SUCCESS;
1337 RawBuffer CKMLogic::setPermission(
1338 const Credentials &cred,
1343 const Label &accessorLabel,
1344 const PermissionMask permissionMask)
1348 retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1349 } Catch (CKM::Exception) {
1350 LogError("Error in set row!");
1351 retCode = CKM_API_ERROR_DB_ERROR;
1354 return MessageBuffer::Serialize(command, msgID, retCode).Pop();