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 = DBCryptoModule();
77 } catch (const KeyProvider::Exception::Base &e) {
78 LogError("Error in KeyProvider " << e.GetMessage());
79 retCode = CKM_API_ERROR_SERVER_ERROR;
82 MessageBuffer response;
83 Serialization::Serialize(response, retCode);
84 return response.Pop();
87 RawBuffer CKMLogic::lockUserKey(uid_t user) {
88 int retCode = CKM_API_SUCCESS;
89 // TODO try catch for all errors that should be supported by error code
90 m_userDataMap.erase(user);
92 MessageBuffer response;
93 Serialization::Serialize(response, retCode);
94 return response.Pop();
97 RawBuffer CKMLogic::removeUserData(uid_t user) {
98 int retCode = CKM_API_SUCCESS;
99 // TODO try catch for all errors that should be supported by error code
100 m_userDataMap.erase(user);
105 MessageBuffer response;
106 Serialization::Serialize(response, retCode);
107 return response.Pop();
110 RawBuffer CKMLogic::changeUserPassword(
112 const std::string &oldPassword,
113 const std::string &newPassword)
115 int retCode = CKM_API_SUCCESS;
118 auto wrappedDomainKEK = fs.getDomainKEK();
119 if (wrappedDomainKEK.empty()) {
120 retCode = CKM_API_ERROR_BAD_REQUEST;
122 wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
123 fs.saveDomainKEK(wrappedDomainKEK);
125 MessageBuffer response;
126 Serialization::Serialize(response, retCode);
127 return response.Pop();
130 RawBuffer CKMLogic::resetUserPassword(
132 const std::string &newPassword)
134 int retCode = CKM_API_SUCCESS;
136 if (0 == m_userDataMap.count(user)) {
137 retCode = CKM_API_ERROR_BAD_REQUEST;
139 auto &handler = m_userDataMap[user];
141 fs.saveDomainKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
144 MessageBuffer response;
145 Serialization::Serialize(response, retCode);
146 return response.Pop();
149 int CKMLogic::saveDataHelper(
153 const RawBuffer &key,
154 const PolicySerializable &policy)
156 if (0 == m_userDataMap.count(cred.uid))
157 return CKM_API_ERROR_DB_LOCKED;
159 DBRow row = { alias, cred.smackLabel, policy.restricted,
160 policy.extractable, dataType, DBCMAlgType::NONE,
161 0, RawBuffer(10, 'c'), static_cast<int>(key.size()), key };
163 auto &handler = m_userDataMap[cred.uid];
164 DBCrypto::Transaction transaction(&handler.database);
165 if (!handler.crypto.haveKey(cred.smackLabel)) {
167 auto key_optional = handler.database.getKey(cred.smackLabel);
169 LogDebug("No Key in database found. Generating new one for label: "
171 key = handler.keyProvider.generateDEK(cred.smackLabel);
172 handler.database.saveKey(cred.smackLabel, key);
174 LogDebug("Key from DB");
178 key = handler.keyProvider.getPureDEK(key);
179 handler.crypto.pushKey(cred.smackLabel, key);
181 handler.crypto.encryptRow(policy.password, row);
182 handler.database.saveDBRow(row);
183 transaction.commit();
184 return CKM_API_SUCCESS;
187 RawBuffer CKMLogic::saveData(
192 const RawBuffer &key,
193 const PolicySerializable &policy)
195 int retCode = CKM_API_SUCCESS;
197 retCode = saveDataHelper(cred, dataType, alias, key, policy);
198 LogDebug("SaveDataHelper returned: " << retCode);
199 } catch (const KeyProvider::Exception::Base &e) {
200 LogError("KeyProvider failed with message: " << e.GetMessage());
201 retCode = CKM_API_ERROR_SERVER_ERROR;
202 } catch (const DBCryptoModule::Exception::Base &e) {
203 LogError("DBCryptoModule failed with message: " << e.GetMessage());
204 retCode = CKM_API_ERROR_SERVER_ERROR;
205 } catch (const DBCrypto::Exception::InternalError &e) {
206 LogError("DBCrypto failed with message: " << e.GetMessage());
207 retCode = CKM_API_ERROR_DB_ERROR;
208 } catch (const DBCrypto::Exception::AliasExists &e) {
209 LogError("DBCrypto couldn't save duplicate alias");
210 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
211 } catch (const DBCrypto::Exception::TransactionError &e) {
212 LogError("DBCrypto transaction failed with message " << e.GetMessage());
213 retCode = CKM_API_ERROR_DB_ERROR;
216 MessageBuffer response;
217 Serialization::Serialize(response, static_cast<int>(LogicCommand::SAVE));
218 Serialization::Serialize(response, commandId);
219 Serialization::Serialize(response, retCode);
220 Serialization::Serialize(response, static_cast<int>(dataType));
222 return response.Pop();
225 RawBuffer CKMLogic::removeData(
231 int retCode = CKM_API_SUCCESS;
233 if (0 < m_userDataMap.count(cred.uid)) {
235 m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
236 } Catch (CKM::Exception) {
237 LogError("Error in deleting row!");
238 retCode = CKM_API_ERROR_DB_ERROR;
241 retCode = CKM_API_ERROR_DB_LOCKED;
244 MessageBuffer response;
245 Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
246 Serialization::Serialize(response, commandId);
247 Serialization::Serialize(response, retCode);
248 Serialization::Serialize(response, static_cast<int>(dataType));
250 return response.Pop();
253 int CKMLogic::getDataHelper(
257 const std::string &password,
261 if (0 == m_userDataMap.count(cred.uid))
262 return CKM_API_ERROR_DB_LOCKED;
264 auto &handler = m_userDataMap[cred.uid];
266 DBCrypto::DBRowOptional row_optional;
267 if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
268 row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType);
269 } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
270 && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
272 row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
274 LogError("Unknown type of requested data" << (int)dataType);
275 return CKM_API_ERROR_BAD_REQUEST;
278 LogError("No row for given alias, label and type");
279 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
284 if (!handler.crypto.haveKey(row.smackLabel)) {
286 auto key_optional = handler.database.getKey(row.smackLabel);
288 LogError("No key for given label in database");
289 return CKM_API_ERROR_DB_ERROR;
292 key = handler.keyProvider.getPureDEK(key);
293 handler.crypto.pushKey(cred.smackLabel, key);
295 handler.crypto.decryptRow(password, row);
297 return CKM_API_SUCCESS;
300 RawBuffer CKMLogic::getData(
305 const std::string &password)
307 int retCode = CKM_API_SUCCESS;
311 retCode = getDataHelper(cred, dataType, alias, password, row);
312 } catch (const KeyProvider::Exception::Base &e) {
313 LogError("KeyProvider failed with error: " << e.GetMessage());
314 retCode = CKM_API_ERROR_SERVER_ERROR;
315 } catch (const DBCryptoModule::Exception::Base &e) {
316 LogError("DBCryptoModule failed with message: " << e.GetMessage());
317 retCode = CKM_API_ERROR_SERVER_ERROR;
318 } catch (const DBCrypto::Exception::Base &e) {
319 LogError("DBCrypto failed with message: " << e.GetMessage());
320 retCode = CKM_API_ERROR_DB_ERROR;
323 if (CKM_API_SUCCESS != retCode) {
325 row.dataType = dataType;
328 MessageBuffer response;
329 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
330 Serialization::Serialize(response, commandId);
331 Serialization::Serialize(response, retCode);
332 Serialization::Serialize(response, static_cast<int>(row.dataType));
333 Serialization::Serialize(response, row.data);
334 return response.Pop();
337 RawBuffer CKMLogic::getDataList(
342 int retCode = CKM_API_SUCCESS;
343 AliasVector aliasVector;
345 if (0 < m_userDataMap.count(cred.uid)) {
346 auto &handler = m_userDataMap[cred.uid];
348 if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
349 handler.database.getAliases(dataType, cred.smackLabel, aliasVector);
351 handler.database.getKeyAliases(cred.smackLabel, aliasVector);
353 } Catch (CKM::Exception) {
354 LogError("Failed to get aliases");
355 retCode = CKM_API_ERROR_DB_ERROR;
358 retCode = CKM_API_ERROR_DB_LOCKED;
361 MessageBuffer response;
362 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
363 Serialization::Serialize(response, commandId);
364 Serialization::Serialize(response, retCode);
365 Serialization::Serialize(response, static_cast<int>(dataType));
366 Serialization::Serialize(response, aliasVector);
367 return response.Pop();
370 int CKMLogic::createKeyPairRSAHelper(
373 const Alias &aliasPrivate,
374 const Alias &aliasPublic,
375 const PolicySerializable &policyPrivate,
376 const PolicySerializable &policyPublic)
378 if (0 >= m_userDataMap.count(cred.uid))
379 return CKM_API_ERROR_DB_LOCKED;
381 auto &handler = m_userDataMap[cred.uid];
385 if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
386 (retCode = CryptoService::createKeyPairRSA(size, prv, pub)))
388 LogDebug("CryptoService error with code: " << retCode);
389 return CKM_API_ERROR_SERVER_ERROR; // TODO error code
392 DBCrypto::Transaction transaction(&handler.database);
393 retCode = saveDataHelper(cred,
394 toDBDataType(prv.getType()),
399 if (CKM_API_SUCCESS != retCode)
402 retCode = saveDataHelper(cred,
403 toDBDataType(pub.getType()),
408 if (CKM_API_SUCCESS != retCode)
411 transaction.commit();
416 RawBuffer CKMLogic::createKeyPairRSA(
420 const Alias &aliasPrivate,
421 const Alias &aliasPublic,
422 const PolicySerializable &policyPrivate,
423 const PolicySerializable &policyPublic)
425 int retCode = CKM_API_SUCCESS;
428 retCode = createKeyPairRSAHelper(
436 } catch (DBCrypto::Exception::AliasExists &e) {
437 LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
438 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
439 } catch (DBCrypto::Exception::TransactionError &e) {
440 LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
441 retCode = CKM_API_ERROR_DB_ERROR;
442 } catch (DBCrypto::Exception::InternalError &e) {
443 LogDebug("DBCrypto internal error: " << e.GetMessage());
444 retCode = CKM_API_ERROR_DB_ERROR;
447 MessageBuffer response;
448 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
449 Serialization::Serialize(response, commandId);
450 Serialization::Serialize(response, retCode);
452 return response.Pop();
455 int CKMLogic::createKeyPairECDSAHelper(
458 const Alias &aliasPrivate,
459 const Alias &aliasPublic,
460 const PolicySerializable &policyPrivate,
461 const PolicySerializable &policyPublic)
463 if (0 >= m_userDataMap.count(cred.uid))
464 return CKM_API_ERROR_DB_LOCKED;
466 auto &handler = m_userDataMap[cred.uid];
470 if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
471 (retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(type), prv, pub)))
473 LogError("CryptoService failed with code: " << retCode);
474 return CKM_API_ERROR_SERVER_ERROR; // TODO error code
477 DBCrypto::Transaction transaction(&handler.database);
479 retCode = saveDataHelper(cred,
480 toDBDataType(prv.getType()),
485 if (CKM_API_SUCCESS != retCode)
488 retCode = saveDataHelper(cred,
489 toDBDataType(pub.getType()),
494 if (CKM_API_SUCCESS != retCode)
497 transaction.commit();
502 RawBuffer CKMLogic::createKeyPairECDSA(
506 const Alias &aliasPrivate,
507 const Alias &aliasPublic,
508 const PolicySerializable &policyPrivate,
509 const PolicySerializable &policyPublic)
511 int retCode = CKM_API_SUCCESS;
514 retCode = createKeyPairECDSAHelper(
521 } catch (const DBCrypto::Exception::AliasExists &e) {
522 LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
523 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
524 } catch (const DBCrypto::Exception::TransactionError &e) {
525 LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
526 retCode = CKM_API_ERROR_DB_ERROR;
527 } catch (const DBCrypto::Exception::InternalError &e) {
528 LogDebug("DBCrypto internal error: " << e.GetMessage());
529 retCode = CKM_API_ERROR_DB_ERROR;
532 MessageBuffer response;
533 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
534 Serialization::Serialize(response, commandId);
535 Serialization::Serialize(response, retCode);
537 return response.Pop();
540 RawBuffer CKMLogic::getCertificateChain(
543 const RawBuffer &certificate,
544 const RawBufferVector &untrustedRawCertVector)
548 CertificateImpl cert(certificate, DataFormat::FORM_DER);
549 CertificateImplVector untrustedCertVector;
550 CertificateImplVector chainVector;
551 RawBufferVector chainRawVector;
553 for (auto &e: untrustedRawCertVector)
554 untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
556 LogDebug("Cert is empty: " << cert.empty());
558 int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
560 if (retCode == CKM_API_SUCCESS) {
561 for (auto &e : chainVector)
562 chainRawVector.push_back(e.getDER());
565 MessageBuffer response;
566 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_CERT));
567 Serialization::Serialize(response, commandId);
568 Serialization::Serialize(response, retCode);
569 Serialization::Serialize(response, chainRawVector);
570 return response.Pop();
573 RawBuffer CKMLogic::getCertificateChain(
576 const RawBuffer &certificate,
577 const AliasVector &aliasVector)
579 int retCode = CKM_API_SUCCESS;
580 RawBufferVector chainRawVector;
582 CertificateImpl cert(certificate, DataFormat::FORM_DER);
583 CertificateImplVector untrustedCertVector;
584 CertificateImplVector chainVector;
588 retCode = CKM_API_ERROR_SERVER_ERROR;
592 for (auto &i: aliasVector) {
593 retCode = getDataHelper(cred, DBDataType::CERTIFICATE, i, std::string(), row);
595 if (retCode != CKM_API_SUCCESS)
598 untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
601 retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
603 if (retCode != CKM_API_SUCCESS)
606 for (auto &i: chainVector)
607 chainRawVector.push_back(i.getDER());
609 } catch (const DBCryptoModule::Exception::Base &e) {
610 LogError("DBCyptorModule failed with message: " << e.GetMessage());
611 retCode = CKM_API_ERROR_SERVER_ERROR;
612 } catch (const DBCrypto::Exception::Base &e) {
613 LogError("DBCrypto failed with message: " << e.GetMessage());
614 retCode = CKM_API_ERROR_DB_ERROR;
616 LogError("Unknown error.");
620 MessageBuffer response;
621 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_ALIAS));
622 Serialization::Serialize(response, commandId);
623 Serialization::Serialize(response, retCode);
624 Serialization::Serialize(response, chainRawVector);
625 return response.Pop();
628 RawBuffer CKMLogic::createSignature(
631 const Alias &privateKeyAlias,
632 const std::string &password, // password for private_key
633 const RawBuffer &message,
634 const HashAlgorithm hash,
635 const RSAPaddingAlgorithm padding)
641 int retCode = CKM_API_SUCCESS;
645 retCode = getDataHelper(cred, DBDataType::KEY_RSA_PUBLIC, privateKeyAlias, password, row);
646 if (CKM_API_SUCCESS != retCode) {
647 LogError("getDataHelper return error");
651 GenericKey keyParsed(row.data, std::string());
652 if (keyParsed.empty())
653 retCode = CKM_API_ERROR_SERVER_ERROR;
655 cs.createSignature(keyParsed, message, hash, padding, signature);
657 } catch (const KeyProvider::Exception::Base &e) {
658 LogError("KeyProvider failed with message: " << e.GetMessage());
659 retCode = CKM_API_ERROR_SERVER_ERROR;
660 } catch (const DBCryptoModule::Exception::Base &e) {
661 LogError("DBCryptoModule failed with message: " << e.GetMessage());
662 retCode = CKM_API_ERROR_SERVER_ERROR;
663 } catch (const DBCrypto::Exception::Base &e) {
664 LogError("DBCrypto failed with message: " << e.GetMessage());
665 retCode = CKM_API_ERROR_DB_ERROR;
668 MessageBuffer response;
669 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_SIGNATURE));
670 Serialization::Serialize(response, commandId);
671 Serialization::Serialize(response, retCode);
672 Serialization::Serialize(response, signature);
673 return response.Pop();
676 RawBuffer CKMLogic::verifySignature(
679 const Alias &publicKeyOrCertAlias,
680 const std::string &password, // password for public_key (optional)
681 const RawBuffer &message,
682 const RawBuffer &signature,
683 const HashAlgorithm hash,
684 const RSAPaddingAlgorithm padding)
686 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
694 retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertAlias, password, row);
696 if (retCode == CKM_API_SUCCESS) {
697 key = GenericKey(row.data);
698 } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
699 retCode = getDataHelper(cred, DBDataType::CERTIFICATE, publicKeyOrCertAlias, password, row);
700 if (retCode != CKM_API_SUCCESS)
702 CertificateImpl cert(row.data, DataFormat::FORM_DER);
703 key = cert.getGenericKey();
709 retCode = CKM_API_ERROR_SERVER_ERROR;
713 retCode = cs.verifySignature(key, message, signature, hash, padding);
715 } catch (const CryptoService::Exception::Crypto_internal &e) {
716 LogError("KeyProvider failed with message: " << e.GetMessage());
717 retCode = CKM_API_ERROR_SERVER_ERROR;
718 } catch (const CryptoService::Exception::opensslError &e) {
719 LogError("KeyProvider failed with message: " << e.GetMessage());
720 retCode = CKM_API_ERROR_SERVER_ERROR;
721 } catch (const KeyProvider::Exception::Base &e) {
722 LogError("KeyProvider failed with error: " << e.GetMessage());
723 retCode = CKM_API_ERROR_SERVER_ERROR;
724 } catch (const DBCryptoModule::Exception::Base &e) {
725 LogError("DBCryptoModule failed with message: " << e.GetMessage());
726 retCode = CKM_API_ERROR_SERVER_ERROR;
727 } catch (const DBCrypto::Exception::Base &e) {
728 LogError("DBCrypto failed with message: " << e.GetMessage());
729 retCode = CKM_API_ERROR_DB_ERROR;
732 MessageBuffer response;
733 Serialization::Serialize(response, static_cast<int>(LogicCommand::VERIFY_SIGNATURE));
734 Serialization::Serialize(response, commandId);
735 Serialization::Serialize(response, retCode);
737 return response.Pop();