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-manager.h>
25 #include <ckm/ckm-control.h>
26 #include <ckm/ckm-error.h>
27 #include <ckm/ckm-type.h>
28 #include <key-provider.h>
29 #include <file-system.h>
30 #include <CryptoService.h>
31 #include <ckm-logic.h>
32 #include <generic-key.h>
35 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
36 } // anonymous namespace
42 int retCode = FileSystem::init();
43 // TODO what can I do when init went wrong? exit(-1) ??
45 LogError("Fatal error in FileSystem::init()");
48 if (CKM_API_SUCCESS != m_certStore.setSystemCertificateDir(CERT_SYSTEM_DIR)) {
49 LogError("Fatal error in CertificateStore::setSystemCertificateDir. Chain creation will not work");
53 CKMLogic::~CKMLogic(){}
55 RawBuffer CKMLogic::unlockUserKey(uid_t user, const std::string &password) {
56 // TODO try catch for all errors that should be supported by error code
57 int retCode = CKM_API_SUCCESS;
60 if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
61 auto &handle = m_userDataMap[user];
63 auto wrappedDomainKEK = fs.getDomainKEK();
65 if (wrappedDomainKEK.empty()) {
66 wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
67 fs.saveDomainKEK(wrappedDomainKEK);
70 handle.keyProvider = KeyProvider(wrappedDomainKEK, password);
72 RawBuffer key = handle.keyProvider.getPureDomainKEK();
73 handle.database = DBCrypto(fs.getDBPath(), key);
74 handle.crypto = CryptoLogic();
77 } catch (const KeyProvider::Exception::Base &e) {
78 LogError("Error in KeyProvider " << e.GetMessage());
79 retCode = CKM_API_ERROR_SERVER_ERROR;
80 } catch (const CryptoLogic::Exception::Base &e) {
81 LogError("CryptoLogic error: " << e.GetMessage());
82 retCode = CKM_API_ERROR_SERVER_ERROR;
83 } catch (const CKM::Exception &e) {
84 LogError("CKM::Exception: " << e.GetMessage());
85 retCode = CKM_API_ERROR_SERVER_ERROR;
88 MessageBuffer response;
89 Serialization::Serialize(response, retCode);
90 return response.Pop();
93 RawBuffer CKMLogic::lockUserKey(uid_t user) {
94 int retCode = CKM_API_SUCCESS;
95 // TODO try catch for all errors that should be supported by error code
96 m_userDataMap.erase(user);
98 MessageBuffer response;
99 Serialization::Serialize(response, retCode);
100 return response.Pop();
103 RawBuffer CKMLogic::removeUserData(uid_t user) {
104 int retCode = CKM_API_SUCCESS;
105 // TODO try catch for all errors that should be supported by error code
106 m_userDataMap.erase(user);
111 MessageBuffer response;
112 Serialization::Serialize(response, retCode);
113 return response.Pop();
116 RawBuffer CKMLogic::changeUserPassword(
118 const std::string &oldPassword,
119 const std::string &newPassword)
121 int retCode = CKM_API_SUCCESS;
124 auto wrappedDomainKEK = fs.getDomainKEK();
125 if (wrappedDomainKEK.empty()) {
126 retCode = CKM_API_ERROR_BAD_REQUEST;
128 wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
129 fs.saveDomainKEK(wrappedDomainKEK);
131 MessageBuffer response;
132 Serialization::Serialize(response, retCode);
133 return response.Pop();
136 RawBuffer CKMLogic::resetUserPassword(
138 const std::string &newPassword)
140 int retCode = CKM_API_SUCCESS;
142 if (0 == m_userDataMap.count(user)) {
143 retCode = CKM_API_ERROR_BAD_REQUEST;
145 auto &handler = m_userDataMap[user];
147 fs.saveDomainKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
150 MessageBuffer response;
151 Serialization::Serialize(response, retCode);
152 return response.Pop();
155 int CKMLogic::saveDataHelper(
159 const RawBuffer &key,
160 const PolicySerializable &policy)
162 if (0 == m_userDataMap.count(cred.uid))
163 return CKM_API_ERROR_DB_LOCKED;
165 DBRow row = { alias, cred.smackLabel, policy.restricted,
166 policy.extractable, dataType, DBCMAlgType::NONE,
167 0, RawBuffer(), static_cast<int>(key.size()), key };
169 auto &handler = m_userDataMap[cred.uid];
170 DBCrypto::Transaction transaction(&handler.database);
171 if (!handler.crypto.haveKey(cred.smackLabel)) {
173 auto key_optional = handler.database.getKey(cred.smackLabel);
175 LogDebug("No Key in database found. Generating new one for label: "
177 key = handler.keyProvider.generateDEK(cred.smackLabel);
178 handler.database.saveKey(cred.smackLabel, key);
180 LogDebug("Key from DB");
184 key = handler.keyProvider.getPureDEK(key);
185 handler.crypto.pushKey(cred.smackLabel, key);
187 handler.crypto.encryptRow(policy.password, row);
188 handler.database.saveDBRow(row);
189 transaction.commit();
190 return CKM_API_SUCCESS;
193 RawBuffer CKMLogic::saveData(
198 const RawBuffer &key,
199 const PolicySerializable &policy)
201 int retCode = CKM_API_SUCCESS;
203 retCode = saveDataHelper(cred, dataType, alias, key, policy);
204 LogDebug("SaveDataHelper returned: " << retCode);
205 } catch (const KeyProvider::Exception::Base &e) {
206 LogError("KeyProvider failed with message: " << e.GetMessage());
207 retCode = CKM_API_ERROR_SERVER_ERROR;
208 } catch (const CryptoLogic::Exception::Base &e) {
209 LogError("CryptoLogic failed with message: " << e.GetMessage());
210 retCode = CKM_API_ERROR_SERVER_ERROR;
211 } catch (const DBCrypto::Exception::InternalError &e) {
212 LogError("DBCrypto failed with message: " << e.GetMessage());
213 retCode = CKM_API_ERROR_DB_ERROR;
214 } catch (const DBCrypto::Exception::AliasExists &e) {
215 LogError("DBCrypto couldn't save duplicate alias");
216 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
217 } catch (const DBCrypto::Exception::TransactionError &e) {
218 LogError("DBCrypto transaction failed with message " << e.GetMessage());
219 retCode = CKM_API_ERROR_DB_ERROR;
222 MessageBuffer response;
223 Serialization::Serialize(response, static_cast<int>(LogicCommand::SAVE));
224 Serialization::Serialize(response, commandId);
225 Serialization::Serialize(response, retCode);
226 Serialization::Serialize(response, static_cast<int>(dataType));
228 return response.Pop();
231 RawBuffer CKMLogic::removeData(
237 int retCode = CKM_API_SUCCESS;
239 if (0 < m_userDataMap.count(cred.uid)) {
241 m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
242 } Catch (CKM::Exception) {
243 LogError("Error in deleting row!");
244 retCode = CKM_API_ERROR_DB_ERROR;
247 retCode = CKM_API_ERROR_DB_LOCKED;
250 MessageBuffer response;
251 Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
252 Serialization::Serialize(response, commandId);
253 Serialization::Serialize(response, retCode);
254 Serialization::Serialize(response, static_cast<int>(dataType));
256 return response.Pop();
259 int CKMLogic::getDataHelper(
263 const std::string &password,
267 if (0 == m_userDataMap.count(cred.uid))
268 return CKM_API_ERROR_DB_LOCKED;
270 auto &handler = m_userDataMap[cred.uid];
272 DBCrypto::DBRowOptional row_optional;
273 if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
274 row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType);
275 } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
276 && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
278 row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
280 LogError("Unknown type of requested data" << (int)dataType);
281 return CKM_API_ERROR_BAD_REQUEST;
284 LogError("No row for given alias, label and type");
285 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
290 if (!handler.crypto.haveKey(row.smackLabel)) {
292 auto key_optional = handler.database.getKey(row.smackLabel);
294 LogError("No key for given label in database");
295 return CKM_API_ERROR_DB_ERROR;
298 key = handler.keyProvider.getPureDEK(key);
299 handler.crypto.pushKey(cred.smackLabel, key);
301 handler.crypto.decryptRow(password, row);
303 return CKM_API_SUCCESS;
306 RawBuffer CKMLogic::getData(
311 const std::string &password)
313 int retCode = CKM_API_SUCCESS;
317 retCode = getDataHelper(cred, dataType, alias, password, row);
318 } catch (const KeyProvider::Exception::Base &e) {
319 LogError("KeyProvider failed with error: " << e.GetMessage());
320 retCode = CKM_API_ERROR_SERVER_ERROR;
321 } catch (const CryptoLogic::Exception::Base &e) {
322 LogError("CryptoLogic failed with message: " << e.GetMessage());
323 retCode = CKM_API_ERROR_SERVER_ERROR;
324 } catch (const DBCrypto::Exception::Base &e) {
325 LogError("DBCrypto failed with message: " << e.GetMessage());
326 retCode = CKM_API_ERROR_DB_ERROR;
329 if (CKM_API_SUCCESS != retCode) {
331 row.dataType = dataType;
334 MessageBuffer response;
335 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
336 Serialization::Serialize(response, commandId);
337 Serialization::Serialize(response, retCode);
338 Serialization::Serialize(response, static_cast<int>(row.dataType));
339 Serialization::Serialize(response, row.data);
340 return response.Pop();
343 RawBuffer CKMLogic::getDataList(
348 int retCode = CKM_API_SUCCESS;
349 AliasVector aliasVector;
351 if (0 < m_userDataMap.count(cred.uid)) {
352 auto &handler = m_userDataMap[cred.uid];
354 if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
355 handler.database.getAliases(dataType, cred.smackLabel, aliasVector);
357 handler.database.getKeyAliases(cred.smackLabel, aliasVector);
359 } Catch (CKM::Exception) {
360 LogError("Failed to get aliases");
361 retCode = CKM_API_ERROR_DB_ERROR;
364 retCode = CKM_API_ERROR_DB_LOCKED;
367 MessageBuffer response;
368 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
369 Serialization::Serialize(response, commandId);
370 Serialization::Serialize(response, retCode);
371 Serialization::Serialize(response, static_cast<int>(dataType));
372 Serialization::Serialize(response, aliasVector);
373 return response.Pop();
376 int CKMLogic::createKeyPairRSAHelper(
379 const Alias &aliasPrivate,
380 const Alias &aliasPublic,
381 const PolicySerializable &policyPrivate,
382 const PolicySerializable &policyPublic)
384 if (0 >= m_userDataMap.count(cred.uid))
385 return CKM_API_ERROR_DB_LOCKED;
387 auto &handler = m_userDataMap[cred.uid];
391 if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
392 (retCode = CryptoService::createKeyPairRSA(size, prv, pub)))
394 LogDebug("CryptoService error with code: " << retCode);
395 return CKM_API_ERROR_SERVER_ERROR; // TODO error code
398 DBCrypto::Transaction transaction(&handler.database);
399 retCode = saveDataHelper(cred,
400 toDBDataType(prv.getType()),
405 if (CKM_API_SUCCESS != retCode)
408 retCode = saveDataHelper(cred,
409 toDBDataType(pub.getType()),
414 if (CKM_API_SUCCESS != retCode)
417 transaction.commit();
422 RawBuffer CKMLogic::createKeyPairRSA(
426 const Alias &aliasPrivate,
427 const Alias &aliasPublic,
428 const PolicySerializable &policyPrivate,
429 const PolicySerializable &policyPublic)
431 int retCode = CKM_API_SUCCESS;
434 retCode = createKeyPairRSAHelper(
442 } catch (DBCrypto::Exception::AliasExists &e) {
443 LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
444 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
445 } catch (DBCrypto::Exception::TransactionError &e) {
446 LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
447 retCode = CKM_API_ERROR_DB_ERROR;
448 } catch (CKM::CryptoLogic::Exception::Base &e) {
449 LogDebug("CryptoLogic error: " << e.GetMessage());
450 retCode = CKM_API_ERROR_SERVER_ERROR;
451 } catch (DBCrypto::Exception::InternalError &e) {
452 LogDebug("DBCrypto internal error: " << e.GetMessage());
453 retCode = CKM_API_ERROR_DB_ERROR;
456 MessageBuffer response;
457 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
458 Serialization::Serialize(response, commandId);
459 Serialization::Serialize(response, retCode);
461 return response.Pop();
464 int CKMLogic::createKeyPairECDSAHelper(
467 const Alias &aliasPrivate,
468 const Alias &aliasPublic,
469 const PolicySerializable &policyPrivate,
470 const PolicySerializable &policyPublic)
472 if (0 >= m_userDataMap.count(cred.uid))
473 return CKM_API_ERROR_DB_LOCKED;
475 auto &handler = m_userDataMap[cred.uid];
479 if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
480 (retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(type), prv, pub)))
482 LogError("CryptoService failed with code: " << retCode);
483 return CKM_API_ERROR_SERVER_ERROR; // TODO error code
486 DBCrypto::Transaction transaction(&handler.database);
488 retCode = saveDataHelper(cred,
489 toDBDataType(prv.getType()),
494 if (CKM_API_SUCCESS != retCode)
497 retCode = saveDataHelper(cred,
498 toDBDataType(pub.getType()),
503 if (CKM_API_SUCCESS != retCode)
506 transaction.commit();
511 RawBuffer CKMLogic::createKeyPairECDSA(
515 const Alias &aliasPrivate,
516 const Alias &aliasPublic,
517 const PolicySerializable &policyPrivate,
518 const PolicySerializable &policyPublic)
520 int retCode = CKM_API_SUCCESS;
523 retCode = createKeyPairECDSAHelper(
530 } catch (const DBCrypto::Exception::AliasExists &e) {
531 LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
532 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
533 } catch (const DBCrypto::Exception::TransactionError &e) {
534 LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
535 retCode = CKM_API_ERROR_DB_ERROR;
536 } catch (const CKM::CryptoLogic::Exception::Base &e) {
537 LogDebug("CryptoLogic error: " << e.GetMessage());
538 retCode = CKM_API_ERROR_SERVER_ERROR;
539 } catch (const DBCrypto::Exception::InternalError &e) {
540 LogDebug("DBCrypto internal error: " << e.GetMessage());
541 retCode = CKM_API_ERROR_DB_ERROR;
544 MessageBuffer response;
545 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
546 Serialization::Serialize(response, commandId);
547 Serialization::Serialize(response, retCode);
549 return response.Pop();
552 RawBuffer CKMLogic::getCertificateChain(
555 const RawBuffer &certificate,
556 const RawBufferVector &untrustedRawCertVector)
560 CertificateImpl cert(certificate, DataFormat::FORM_DER);
561 CertificateImplVector untrustedCertVector;
562 CertificateImplVector chainVector;
563 RawBufferVector chainRawVector;
565 for (auto &e: untrustedRawCertVector)
566 untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
568 LogDebug("Cert is empty: " << cert.empty());
570 int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
572 if (retCode == CKM_API_SUCCESS) {
573 for (auto &e : chainVector)
574 chainRawVector.push_back(e.getDER());
577 MessageBuffer response;
578 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_CERT));
579 Serialization::Serialize(response, commandId);
580 Serialization::Serialize(response, retCode);
581 Serialization::Serialize(response, chainRawVector);
582 return response.Pop();
585 RawBuffer CKMLogic::getCertificateChain(
588 const RawBuffer &certificate,
589 const AliasVector &aliasVector)
591 int retCode = CKM_API_SUCCESS;
592 RawBufferVector chainRawVector;
594 CertificateImpl cert(certificate, DataFormat::FORM_DER);
595 CertificateImplVector untrustedCertVector;
596 CertificateImplVector chainVector;
600 retCode = CKM_API_ERROR_SERVER_ERROR;
604 for (auto &i: aliasVector) {
605 retCode = getDataHelper(cred, DBDataType::CERTIFICATE, i, std::string(), row);
607 if (retCode != CKM_API_SUCCESS)
610 untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
613 retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
615 if (retCode != CKM_API_SUCCESS)
618 for (auto &i: chainVector)
619 chainRawVector.push_back(i.getDER());
621 } catch (const CryptoLogic::Exception::Base &e) {
622 LogError("DBCyptorModule failed with message: " << e.GetMessage());
623 retCode = CKM_API_ERROR_SERVER_ERROR;
624 } catch (const DBCrypto::Exception::Base &e) {
625 LogError("DBCrypto failed with message: " << e.GetMessage());
626 retCode = CKM_API_ERROR_DB_ERROR;
628 LogError("Unknown error.");
632 MessageBuffer response;
633 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_ALIAS));
634 Serialization::Serialize(response, commandId);
635 Serialization::Serialize(response, retCode);
636 Serialization::Serialize(response, chainRawVector);
637 return response.Pop();
640 RawBuffer CKMLogic::createSignature(
643 const Alias &privateKeyAlias,
644 const std::string &password, // password for private_key
645 const RawBuffer &message,
646 const HashAlgorithm hash,
647 const RSAPaddingAlgorithm padding)
653 int retCode = CKM_API_SUCCESS;
657 retCode = getDataHelper(cred, DBDataType::KEY_RSA_PUBLIC, privateKeyAlias, password, row);
658 if (CKM_API_SUCCESS != retCode) {
659 LogError("getDataHelper return error");
663 GenericKey keyParsed(row.data, std::string());
664 if (keyParsed.empty())
665 retCode = CKM_API_ERROR_SERVER_ERROR;
667 cs.createSignature(keyParsed, message, hash, padding, signature);
669 } catch (const KeyProvider::Exception::Base &e) {
670 LogError("KeyProvider failed with message: " << e.GetMessage());
671 retCode = CKM_API_ERROR_SERVER_ERROR;
672 } catch (const CryptoLogic::Exception::Base &e) {
673 LogError("CryptoLogic failed with message: " << e.GetMessage());
674 retCode = CKM_API_ERROR_SERVER_ERROR;
675 } catch (const DBCrypto::Exception::Base &e) {
676 LogError("DBCrypto failed with message: " << e.GetMessage());
677 retCode = CKM_API_ERROR_DB_ERROR;
678 } catch (const CKM::Exception &e) {
679 LogError("Unknown CKM::Exception: " << e.GetMessage());
680 retCode = CKM_API_ERROR_SERVER_ERROR;
683 MessageBuffer response;
684 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_SIGNATURE));
685 Serialization::Serialize(response, commandId);
686 Serialization::Serialize(response, retCode);
687 Serialization::Serialize(response, signature);
688 return response.Pop();
691 RawBuffer CKMLogic::verifySignature(
694 const Alias &publicKeyOrCertAlias,
695 const std::string &password, // password for public_key (optional)
696 const RawBuffer &message,
697 const RawBuffer &signature,
698 const HashAlgorithm hash,
699 const RSAPaddingAlgorithm padding)
701 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
709 retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertAlias, password, row);
711 if (retCode == CKM_API_SUCCESS) {
712 key = GenericKey(row.data);
713 } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
714 retCode = getDataHelper(cred, DBDataType::CERTIFICATE, publicKeyOrCertAlias, password, row);
715 if (retCode != CKM_API_SUCCESS)
717 CertificateImpl cert(row.data, DataFormat::FORM_DER);
718 key = cert.getGenericKey();
724 retCode = CKM_API_ERROR_SERVER_ERROR;
728 retCode = cs.verifySignature(key, message, signature, hash, padding);
730 } catch (const CryptoService::Exception::Crypto_internal &e) {
731 LogError("KeyProvider failed with message: " << e.GetMessage());
732 retCode = CKM_API_ERROR_SERVER_ERROR;
733 } catch (const CryptoService::Exception::opensslError &e) {
734 LogError("KeyProvider failed with message: " << e.GetMessage());
735 retCode = CKM_API_ERROR_SERVER_ERROR;
736 } catch (const KeyProvider::Exception::Base &e) {
737 LogError("KeyProvider failed with error: " << e.GetMessage());
738 retCode = CKM_API_ERROR_SERVER_ERROR;
739 } catch (const CryptoLogic::Exception::Base &e) {
740 LogError("CryptoLogic failed with message: " << e.GetMessage());
741 retCode = CKM_API_ERROR_SERVER_ERROR;
742 } catch (const DBCrypto::Exception::Base &e) {
743 LogError("DBCrypto failed with message: " << e.GetMessage());
744 retCode = CKM_API_ERROR_DB_ERROR;
745 } catch (const CKM::Exception &e) {
746 LogError("Unknown CKM::Exception: " << e.GetMessage());
747 retCode = CKM_API_ERROR_SERVER_ERROR;
750 MessageBuffer response;
751 Serialization::Serialize(response, static_cast<int>(LogicCommand::VERIFY_SIGNATURE));
752 Serialization::Serialize(response, commandId);
753 Serialization::Serialize(response, retCode);
755 return response.Pop();