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(key);
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'), 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);
176 key = handler.keyProvider.getPureDEK(key);
177 handler.crypto.pushKey(cred.smackLabel, key);
178 handler.database.saveKey(cred.smackLabel, key);
180 handler.crypto.encryptRow(policy.password, row);
181 handler.database.saveDBRow(row);
182 transaction.commit();
183 return CKM_API_SUCCESS;
186 RawBuffer CKMLogic::saveData(
191 const RawBuffer &key,
192 const PolicySerializable &policy)
194 int retCode = CKM_API_SUCCESS;
196 retCode = saveDataHelper(cred, dataType, alias, key, policy);
197 LogDebug("SaveDataHelper returned: " << retCode);
198 } catch (const KeyProvider::Exception::Base &e) {
199 LogError("KeyProvider failed with message: " << e.GetMessage());
200 retCode = CKM_API_ERROR_SERVER_ERROR;
201 } catch (const DBCryptoModule::Exception::Base &e) {
202 LogError("DBCryptoModule failed with message: " << e.GetMessage());
203 retCode = CKM_API_ERROR_SERVER_ERROR;
204 } catch (const DBCrypto::Exception::InternalError &e) {
205 LogError("DBCrypto failed with message: " << e.GetMessage());
206 retCode = CKM_API_ERROR_DB_ERROR;
207 } catch (const DBCrypto::Exception::AliasExists &e) {
208 LogError("DBCrypto couldn't save duplicate alias");
209 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
210 } catch (const DBCrypto::Exception::TransactionError &e) {
211 LogError("DBCrypto transaction failed with message " << e.GetMessage());
212 retCode = CKM_API_ERROR_DB_ERROR;
215 MessageBuffer response;
216 Serialization::Serialize(response, static_cast<int>(LogicCommand::SAVE));
217 Serialization::Serialize(response, commandId);
218 Serialization::Serialize(response, retCode);
219 Serialization::Serialize(response, static_cast<int>(dataType));
221 return response.Pop();
224 RawBuffer CKMLogic::removeData(
230 int retCode = CKM_API_SUCCESS;
232 if (0 < m_userDataMap.count(cred.uid)) {
234 m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
235 } Catch (CKM::Exception) {
236 LogError("Error in deleting row!");
237 retCode = CKM_API_ERROR_DB_ERROR;
240 retCode = CKM_API_ERROR_DB_LOCKED;
243 MessageBuffer response;
244 Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
245 Serialization::Serialize(response, commandId);
246 Serialization::Serialize(response, retCode);
247 Serialization::Serialize(response, static_cast<int>(dataType));
249 return response.Pop();
252 int CKMLogic::getDataHelper(
256 const std::string &password,
260 if (0 == m_userDataMap.count(cred.uid))
261 return CKM_API_ERROR_DB_LOCKED;
263 auto &handler = m_userDataMap[cred.uid];
265 DBCrypto::DBRowOptional row_optional;
266 if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
267 row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType);
268 } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
269 && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
271 row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
273 LogError("Unknown type of requested data" << (int)dataType);
274 return CKM_API_ERROR_BAD_REQUEST;
277 LogError("No row for given alias, label and type");
278 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
283 if (!handler.crypto.haveKey(row.smackLabel)) {
285 auto key_optional = handler.database.getKey(row.smackLabel);
287 LogError("No key for given label in database");
288 return CKM_API_ERROR_DB_ERROR;
291 key = handler.keyProvider.getPureDEK(key);
292 handler.crypto.pushKey(cred.smackLabel, key);
294 handler.crypto.decryptRow(password, row);
296 return CKM_API_SUCCESS;
299 RawBuffer CKMLogic::getData(
304 const std::string &password)
306 int retCode = CKM_API_SUCCESS;
310 retCode = getDataHelper(cred, dataType, alias, password, row);
311 } catch (const KeyProvider::Exception::Base &e) {
312 LogError("KeyProvider failed with error: " << e.GetMessage());
313 retCode = CKM_API_ERROR_SERVER_ERROR;
314 } catch (const DBCryptoModule::Exception::Base &e) {
315 LogError("DBCryptoModule failed with message: " << e.GetMessage());
316 retCode = CKM_API_ERROR_SERVER_ERROR;
317 } catch (const DBCrypto::Exception::Base &e) {
318 LogError("DBCrypto failed with message: " << e.GetMessage());
319 retCode = CKM_API_ERROR_DB_ERROR;
322 if (CKM_API_SUCCESS != retCode) {
324 row.dataType = dataType;
327 MessageBuffer response;
328 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
329 Serialization::Serialize(response, commandId);
330 Serialization::Serialize(response, retCode);
331 Serialization::Serialize(response, static_cast<int>(row.dataType));
332 Serialization::Serialize(response, row.data);
333 return response.Pop();
336 RawBuffer CKMLogic::getDataList(
341 int retCode = CKM_API_SUCCESS;
342 AliasVector aliasVector;
344 if (0 < m_userDataMap.count(cred.uid)) {
345 auto &handler = m_userDataMap[cred.uid];
347 if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
348 handler.database.getAliases(dataType, cred.smackLabel, aliasVector);
350 handler.database.getKeyAliases(cred.smackLabel, aliasVector);
352 } Catch (CKM::Exception) {
353 LogError("Failed to get aliases");
354 retCode = CKM_API_ERROR_DB_ERROR;
357 retCode = CKM_API_ERROR_DB_LOCKED;
360 MessageBuffer response;
361 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
362 Serialization::Serialize(response, commandId);
363 Serialization::Serialize(response, retCode);
364 Serialization::Serialize(response, static_cast<int>(dataType));
365 Serialization::Serialize(response, aliasVector);
366 return response.Pop();
369 int CKMLogic::createKeyPairRSAHelper(
372 const Alias &aliasPrivate,
373 const Alias &aliasPublic,
374 const PolicySerializable &policyPrivate,
375 const PolicySerializable &policyPublic)
377 if (0 >= m_userDataMap.count(cred.uid))
378 return CKM_API_ERROR_DB_LOCKED;
380 auto &handler = m_userDataMap[cred.uid];
384 if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
385 (retCode = CryptoService::createKeyPairRSA(size, prv, pub)))
387 LogDebug("CryptoService error with code: " << retCode);
388 return CKM_API_ERROR_SERVER_ERROR; // TODO error code
391 DBCrypto::Transaction transaction(&handler.database);
392 retCode = saveDataHelper(cred,
393 toDBDataType(prv.getType()),
398 if (CKM_API_SUCCESS != retCode)
401 retCode = saveDataHelper(cred,
402 toDBDataType(pub.getType()),
407 if (CKM_API_SUCCESS != retCode)
410 transaction.commit();
415 RawBuffer CKMLogic::createKeyPairRSA(
419 const Alias &aliasPrivate,
420 const Alias &aliasPublic,
421 const PolicySerializable &policyPrivate,
422 const PolicySerializable &policyPublic)
424 int retCode = CKM_API_SUCCESS;
427 retCode = createKeyPairRSAHelper(
435 } catch (DBCrypto::Exception::AliasExists &e) {
436 LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
437 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
438 } catch (DBCrypto::Exception::TransactionError &e) {
439 LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
440 retCode = CKM_API_ERROR_DB_ERROR;
441 } catch (DBCrypto::Exception::InternalError &e) {
442 LogDebug("DBCrypto internal error: " << e.GetMessage());
443 retCode = CKM_API_ERROR_DB_ERROR;
446 MessageBuffer response;
447 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
448 Serialization::Serialize(response, commandId);
449 Serialization::Serialize(response, retCode);
451 return response.Pop();
454 int CKMLogic::createKeyPairECDSAHelper(
457 const Alias &aliasPrivate,
458 const Alias &aliasPublic,
459 const PolicySerializable &policyPrivate,
460 const PolicySerializable &policyPublic)
462 if (0 >= m_userDataMap.count(cred.uid))
463 return CKM_API_ERROR_DB_LOCKED;
465 auto &handler = m_userDataMap[cred.uid];
469 if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
470 (retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(type), prv, pub)))
472 LogError("CryptoService failed with code: " << retCode);
473 return CKM_API_ERROR_SERVER_ERROR; // TODO error code
476 DBCrypto::Transaction transaction(&handler.database);
478 retCode = saveDataHelper(cred,
479 toDBDataType(prv.getType()),
484 if (CKM_API_SUCCESS != retCode)
487 retCode = saveDataHelper(cred,
488 toDBDataType(pub.getType()),
493 if (CKM_API_SUCCESS != retCode)
496 transaction.commit();
501 RawBuffer CKMLogic::createKeyPairECDSA(
505 const Alias &aliasPrivate,
506 const Alias &aliasPublic,
507 const PolicySerializable &policyPrivate,
508 const PolicySerializable &policyPublic)
510 int retCode = CKM_API_SUCCESS;
513 retCode = createKeyPairECDSAHelper(
520 } catch (const DBCrypto::Exception::AliasExists &e) {
521 LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
522 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
523 } catch (const DBCrypto::Exception::TransactionError &e) {
524 LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
525 retCode = CKM_API_ERROR_DB_ERROR;
526 } catch (const DBCrypto::Exception::InternalError &e) {
527 LogDebug("DBCrypto internal error: " << e.GetMessage());
528 retCode = CKM_API_ERROR_DB_ERROR;
531 MessageBuffer response;
532 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
533 Serialization::Serialize(response, commandId);
534 Serialization::Serialize(response, retCode);
536 return response.Pop();
539 RawBuffer CKMLogic::getCertificateChain(
542 const RawBuffer &certificate,
543 const RawBufferVector &untrustedRawCertVector)
547 CertificateImpl cert(certificate, DataFormat::FORM_DER);
548 CertificateImplVector untrustedCertVector;
549 CertificateImplVector chainVector;
550 RawBufferVector chainRawVector;
552 for (auto &e: untrustedRawCertVector)
553 untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
555 LogDebug("Cert is empty: " << cert.empty());
557 int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
559 if (retCode == CKM_API_SUCCESS) {
560 for (auto &e : chainVector)
561 chainRawVector.push_back(e.getDER());
564 MessageBuffer response;
565 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_CERT));
566 Serialization::Serialize(response, commandId);
567 Serialization::Serialize(response, retCode);
568 Serialization::Serialize(response, chainRawVector);
569 return response.Pop();
572 RawBuffer CKMLogic::getCertificateChain(
575 const RawBuffer &certificate,
576 const AliasVector &aliasVector)
578 int retCode = CKM_API_SUCCESS;
579 RawBufferVector chainRawVector;
581 CertificateImpl cert(certificate, DataFormat::FORM_DER);
582 CertificateImplVector untrustedCertVector;
583 CertificateImplVector chainVector;
587 retCode = CKM_API_ERROR_SERVER_ERROR;
591 for (auto &i: aliasVector) {
592 retCode = getDataHelper(cred, DBDataType::CERTIFICATE, i, std::string(), row);
594 if (retCode != CKM_API_SUCCESS)
597 untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
600 retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
602 if (retCode != CKM_API_SUCCESS)
605 for (auto &i: chainVector)
606 chainRawVector.push_back(i.getDER());
608 } catch (const DBCryptoModule::Exception::Base &e) {
609 LogError("DBCyptorModule failed with message: " << e.GetMessage());
610 retCode = CKM_API_ERROR_SERVER_ERROR;
611 } catch (const DBCrypto::Exception::Base &e) {
612 LogError("DBCrypto failed with message: " << e.GetMessage());
613 retCode = CKM_API_ERROR_DB_ERROR;
615 LogError("Unknown error.");
619 MessageBuffer response;
620 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_ALIAS));
621 Serialization::Serialize(response, commandId);
622 Serialization::Serialize(response, retCode);
623 Serialization::Serialize(response, chainRawVector);
624 return response.Pop();
627 RawBuffer CKMLogic::createSignature(
630 const Alias &privateKeyAlias,
631 const std::string &password, // password for private_key
632 const RawBuffer &message,
633 const HashAlgorithm hash,
634 const RSAPaddingAlgorithm padding)
640 int retCode = CKM_API_SUCCESS;
644 retCode = getDataHelper(cred, DBDataType::KEY_RSA_PUBLIC, privateKeyAlias, password, row);
645 if (CKM_API_SUCCESS != retCode) {
646 LogError("getDataHelper return error");
650 GenericKey keyParsed(row.data, std::string());
651 if (keyParsed.empty())
652 retCode = CKM_API_ERROR_SERVER_ERROR;
654 cs.createSignature(keyParsed, message, hash, padding, signature);
656 } catch (const KeyProvider::Exception::Base &e) {
657 LogError("KeyProvider failed with message: " << e.GetMessage());
658 retCode = CKM_API_ERROR_SERVER_ERROR;
659 } catch (const DBCryptoModule::Exception::Base &e) {
660 LogError("DBCryptoModule failed with message: " << e.GetMessage());
661 retCode = CKM_API_ERROR_SERVER_ERROR;
662 } catch (const DBCrypto::Exception::Base &e) {
663 LogError("DBCrypto failed with message: " << e.GetMessage());
664 retCode = CKM_API_ERROR_DB_ERROR;
667 MessageBuffer response;
668 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_SIGNATURE));
669 Serialization::Serialize(response, commandId);
670 Serialization::Serialize(response, retCode);
671 Serialization::Serialize(response, signature);
672 return response.Pop();
675 RawBuffer CKMLogic::verifySignature(
678 const Alias &publicKeyOrCertAlias,
679 const std::string &password, // password for public_key (optional)
680 const RawBuffer &message,
681 const RawBuffer &signature,
682 const HashAlgorithm hash,
683 const RSAPaddingAlgorithm padding)
685 int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
693 retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertAlias, password, row);
695 if (retCode == CKM_API_SUCCESS) {
696 key = GenericKey(row.data);
697 } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
698 retCode = getDataHelper(cred, DBDataType::CERTIFICATE, publicKeyOrCertAlias, password, row);
699 if (retCode != CKM_API_SUCCESS)
701 CertificateImpl cert(row.data, DataFormat::FORM_DER);
702 key = cert.getGenericKey();
708 retCode = CKM_API_ERROR_SERVER_ERROR;
712 retCode = cs.verifySignature(key, message, signature, hash, padding);
714 } catch (const CryptoService::Exception::Crypto_internal &e) {
715 LogError("KeyProvider failed with message: " << e.GetMessage());
716 retCode = CKM_API_ERROR_SERVER_ERROR;
717 } catch (const CryptoService::Exception::opensslError &e) {
718 LogError("KeyProvider failed with message: " << e.GetMessage());
719 retCode = CKM_API_ERROR_SERVER_ERROR;
720 } catch (const KeyProvider::Exception::Base &e) {
721 LogError("KeyProvider failed with error: " << e.GetMessage());
722 retCode = CKM_API_ERROR_SERVER_ERROR;
723 } catch (const DBCryptoModule::Exception::Base &e) {
724 LogError("DBCryptoModule failed with message: " << e.GetMessage());
725 retCode = CKM_API_ERROR_SERVER_ERROR;
726 } catch (const DBCrypto::Exception::Base &e) {
727 LogError("DBCrypto failed with message: " << e.GetMessage());
728 retCode = CKM_API_ERROR_DB_ERROR;
731 MessageBuffer response;
732 Serialization::Serialize(response, static_cast<int>(LogicCommand::VERIFY_SIGNATURE));
733 Serialization::Serialize(response, commandId);
734 Serialization::Serialize(response, retCode);
736 return response.Pop();