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>
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>
31 #include <generic-key.h>
34 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
35 } // anonymous namespace
41 int retCode = FileSystem::init();
42 // TODO what can I do when init went wrong? exit(-1) ??
44 LogError("Fatal error in FileSystem::init()");
47 if (CKM_API_SUCCESS != m_certStore.setSystemCertificateDir(CERT_SYSTEM_DIR)) {
48 LogError("Fatal error in CertificateStore::setSystemCertificateDir. Chain creation will not work");
52 CKMLogic::~CKMLogic(){}
54 RawBuffer CKMLogic::unlockUserKey(uid_t user, const std::string &password) {
55 // TODO try catch for all errors that should be supported by error code
56 int retCode = CKM_API_SUCCESS;
59 if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
60 auto &handle = m_userDataMap[user];
62 auto wrappedDomainKEK = fs.getDomainKEK();
64 if (wrappedDomainKEK.empty()) {
65 wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
66 fs.saveDomainKEK(wrappedDomainKEK);
69 handle.keyProvider = KeyProvider(wrappedDomainKEK, password);
71 RawBuffer key = handle.keyProvider.getPureDomainKEK();
72 handle.database = DBCrypto(fs.getDBPath(), key);
73 handle.crypto = DBCryptoModule(key);
76 } catch (const KeyProvider::Exception::Base &e) {
77 LogError("Error in KeyProvider " << e.GetMessage());
78 retCode = CKM_API_ERROR_SERVER_ERROR;
81 MessageBuffer response;
82 Serialization::Serialize(response, retCode);
83 return response.Pop();
86 RawBuffer CKMLogic::lockUserKey(uid_t user) {
87 int retCode = CKM_API_SUCCESS;
88 // TODO try catch for all errors that should be supported by error code
89 m_userDataMap.erase(user);
91 MessageBuffer response;
92 Serialization::Serialize(response, retCode);
93 return response.Pop();
96 RawBuffer CKMLogic::removeUserData(uid_t user) {
97 int retCode = CKM_API_SUCCESS;
98 // TODO try catch for all errors that should be supported by error code
99 m_userDataMap.erase(user);
104 MessageBuffer response;
105 Serialization::Serialize(response, retCode);
106 return response.Pop();
109 RawBuffer CKMLogic::changeUserPassword(
111 const std::string &oldPassword,
112 const std::string &newPassword)
114 int retCode = CKM_API_SUCCESS;
117 auto wrappedDomainKEK = fs.getDomainKEK();
118 if (wrappedDomainKEK.empty()) {
119 retCode = CKM_API_ERROR_BAD_REQUEST;
121 wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
122 fs.saveDomainKEK(wrappedDomainKEK);
124 MessageBuffer response;
125 Serialization::Serialize(response, retCode);
126 return response.Pop();
129 RawBuffer CKMLogic::resetUserPassword(
131 const std::string &newPassword)
133 int retCode = CKM_API_SUCCESS;
135 if (0 == m_userDataMap.count(user)) {
136 retCode = CKM_API_ERROR_BAD_REQUEST;
138 auto &handler = m_userDataMap[user];
140 fs.saveDomainKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
143 MessageBuffer response;
144 Serialization::Serialize(response, retCode);
145 return response.Pop();
148 int CKMLogic::saveDataHelper(
152 const RawBuffer &key,
153 const PolicySerializable &policy)
155 if (0 == m_userDataMap.count(cred.uid))
156 return CKM_API_ERROR_DB_LOCKED;
158 DBRow row = { alias, cred.smackLabel, policy.restricted,
159 policy.extractable, dataType, DBCMAlgType::NONE,
160 0, RawBuffer(10, 'c'), key.size(), key };
162 auto &handler = m_userDataMap[cred.uid];
163 DBCrypto::Transaction transaction(&handler.database);
164 if (!handler.crypto.haveKey(cred.smackLabel)) {
166 auto key_optional = handler.database.getKey(cred.smackLabel);
168 LogDebug("No Key in database found. Generating new one for label: "
170 key = handler.keyProvider.generateDEK(cred.smackLabel);
175 key = handler.keyProvider.getPureDEK(key);
176 handler.crypto.pushKey(cred.smackLabel, key);
177 handler.database.saveKey(cred.smackLabel, key);
179 handler.crypto.encryptRow(policy.password, row);
180 handler.database.saveDBRow(row);
181 transaction.commit();
182 return CKM_API_SUCCESS;
185 RawBuffer CKMLogic::saveData(
190 const RawBuffer &key,
191 const PolicySerializable &policy)
193 int retCode = CKM_API_SUCCESS;
195 retCode = saveDataHelper(cred, dataType, alias, key, policy);
196 LogDebug("SaveDataHelper returned: " << retCode);
197 } catch (const KeyProvider::Exception::Base &e) {
198 LogError("KeyProvider failed with message: " << e.GetMessage());
199 retCode = CKM_API_ERROR_SERVER_ERROR;
200 } catch (const DBCryptoModule::Exception::Base &e) {
201 LogError("DBCryptoModule failed with message: " << e.GetMessage());
202 retCode = CKM_API_ERROR_SERVER_ERROR;
203 } catch (const DBCrypto::Exception::InternalError &e) {
204 LogError("DBCrypto failed with message: " << e.GetMessage());
205 retCode = CKM_API_ERROR_DB_ERROR;
206 } catch (const DBCrypto::Exception::AliasExists &e) {
207 LogError("DBCrypto couldn't save duplicate alias");
208 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
209 } catch (const DBCrypto::Exception::TransactionError &e) {
210 LogError("DBCrypto transaction failed with message " << e.GetMessage());
211 retCode = CKM_API_ERROR_DB_ERROR;
214 MessageBuffer response;
215 Serialization::Serialize(response, static_cast<int>(LogicCommand::SAVE));
216 Serialization::Serialize(response, commandId);
217 Serialization::Serialize(response, retCode);
218 Serialization::Serialize(response, static_cast<int>(dataType));
220 return response.Pop();
223 RawBuffer CKMLogic::removeData(
229 int retCode = CKM_API_SUCCESS;
231 if (0 < m_userDataMap.count(cred.uid)) {
233 m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
234 } Catch (CKM::Exception) {
235 LogError("Error in deleting row!");
236 retCode = CKM_API_ERROR_DB_ERROR;
239 retCode = CKM_API_ERROR_DB_LOCKED;
242 MessageBuffer response;
243 Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
244 Serialization::Serialize(response, commandId);
245 Serialization::Serialize(response, retCode);
246 Serialization::Serialize(response, static_cast<int>(dataType));
248 return response.Pop();
251 int CKMLogic::getDataHelper(
255 const std::string &password,
259 if (0 == m_userDataMap.count(cred.uid))
260 return CKM_API_ERROR_DB_LOCKED;
262 auto &handler = m_userDataMap[cred.uid];
264 DBCrypto::DBRowOptional row_optional;
265 if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
266 row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType);
267 } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
268 && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
270 row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
272 LogError("Unknown type of requested data" << (int)dataType);
273 return CKM_API_ERROR_BAD_REQUEST;
276 LogError("No row for given alias, label and type");
277 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
282 if (!handler.crypto.haveKey(row.smackLabel)) {
284 auto key_optional = handler.database.getKey(row.smackLabel);
286 LogError("No key for given label in database");
287 return CKM_API_ERROR_DB_ERROR;
290 key = handler.keyProvider.getPureDEK(key);
291 handler.crypto.pushKey(cred.smackLabel, key);
293 handler.crypto.decryptRow(password, row);
295 LogError("Datatype: " << (int) row.dataType);
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 LogError("Sending dataType: " << (int)row.dataType);
330 MessageBuffer response;
331 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
332 Serialization::Serialize(response, commandId);
333 Serialization::Serialize(response, retCode);
334 Serialization::Serialize(response, static_cast<int>(row.dataType));
335 Serialization::Serialize(response, row.data);
336 return response.Pop();
339 RawBuffer CKMLogic::getDataList(
344 int retCode = CKM_API_SUCCESS;
345 AliasVector aliasVector;
347 if (0 < m_userDataMap.count(cred.uid)) {
348 auto &handler = m_userDataMap[cred.uid];
350 if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
351 handler.database.getAliases(dataType, cred.smackLabel, aliasVector);
353 handler.database.getKeyAliases(cred.smackLabel, aliasVector);
355 } Catch (CKM::Exception) {
356 LogError("Failed to get aliases");
357 retCode = CKM_API_ERROR_DB_ERROR;
360 retCode = CKM_API_ERROR_DB_LOCKED;
363 MessageBuffer response;
364 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
365 Serialization::Serialize(response, commandId);
366 Serialization::Serialize(response, retCode);
367 Serialization::Serialize(response, static_cast<int>(dataType));
368 Serialization::Serialize(response, aliasVector);
369 return response.Pop();
372 int CKMLogic::createKeyPairRSAHelper(
375 const Alias &aliasPrivate,
376 const Alias &aliasPublic,
377 const PolicySerializable &policyPrivate,
378 const PolicySerializable &policyPublic)
380 if (0 >= m_userDataMap.count(cred.uid))
381 return CKM_API_ERROR_DB_LOCKED;
383 auto &handler = m_userDataMap[cred.uid];
387 if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
388 (retCode = CryptoService::createKeyPairRSA(size, prv, pub)))
390 LogDebug("CryptoService error with code: " << retCode);
391 return CKM_API_ERROR_SERVER_ERROR; // TODO error code
394 DBCrypto::Transaction transaction(&handler.database);
395 retCode = saveDataHelper(cred,
396 toDBDataType(prv.getType()),
401 if (CKM_API_SUCCESS != retCode)
404 retCode = saveDataHelper(cred,
405 toDBDataType(pub.getType()),
410 if (CKM_API_SUCCESS != retCode)
413 transaction.commit();
418 RawBuffer CKMLogic::createKeyPairRSA(
422 const Alias &aliasPrivate,
423 const Alias &aliasPublic,
424 const PolicySerializable &policyPrivate,
425 const PolicySerializable &policyPublic)
427 int retCode = CKM_API_SUCCESS;
430 retCode = createKeyPairRSAHelper(
438 } catch (DBCrypto::Exception::AliasExists &e) {
439 LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
440 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
441 } catch (DBCrypto::Exception::TransactionError &e) {
442 LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
443 retCode = CKM_API_ERROR_DB_ERROR;
444 } catch (DBCrypto::Exception::InternalError &e) {
445 LogDebug("DBCrypto internal error: " << e.GetMessage());
446 retCode = CKM_API_ERROR_DB_ERROR;
449 MessageBuffer response;
450 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
451 Serialization::Serialize(response, commandId);
452 Serialization::Serialize(response, retCode);
454 return response.Pop();
457 int CKMLogic::createKeyPairECDSAHelper(
460 const Alias &aliasPrivate,
461 const Alias &aliasPublic,
462 const PolicySerializable &policyPrivate,
463 const PolicySerializable &policyPublic)
465 if (0 >= m_userDataMap.count(cred.uid))
466 return CKM_API_ERROR_DB_LOCKED;
468 auto &handler = m_userDataMap[cred.uid];
472 if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
473 (retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(type), prv, pub)))
475 LogError("CryptoService failed with code: " << retCode);
476 return CKM_API_ERROR_SERVER_ERROR; // TODO error code
479 DBCrypto::Transaction transaction(&handler.database);
481 retCode = saveDataHelper(cred,
482 toDBDataType(prv.getType()),
487 if (CKM_API_SUCCESS != retCode)
490 retCode = saveDataHelper(cred,
491 toDBDataType(pub.getType()),
496 if (CKM_API_SUCCESS != retCode)
499 transaction.commit();
504 RawBuffer CKMLogic::createKeyPairECDSA(
508 const Alias &aliasPrivate,
509 const Alias &aliasPublic,
510 const PolicySerializable &policyPrivate,
511 const PolicySerializable &policyPublic)
513 int retCode = CKM_API_SUCCESS;
516 retCode = createKeyPairECDSAHelper(
523 } catch (const DBCrypto::Exception::AliasExists &e) {
524 LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
525 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
526 } catch (const DBCrypto::Exception::TransactionError &e) {
527 LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
528 retCode = CKM_API_ERROR_DB_ERROR;
529 } catch (const DBCrypto::Exception::InternalError &e) {
530 LogDebug("DBCrypto internal error: " << e.GetMessage());
531 retCode = CKM_API_ERROR_DB_ERROR;
534 MessageBuffer response;
535 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
536 Serialization::Serialize(response, commandId);
537 Serialization::Serialize(response, retCode);
539 return response.Pop();
542 RawBuffer CKMLogic::getCertificateChain(
545 const RawBuffer &certificate,
546 const RawBufferVector &untrustedRawCertVector)
550 CertificateImpl cert(certificate, DataFormat::FORM_DER);
551 CertificateImplVector untrustedCertVector;
552 CertificateImplVector chainVector;
553 RawBufferVector chainRawVector;
555 for (auto &e: untrustedRawCertVector)
556 untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
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)
584 MessageBuffer response;
585 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_ALIAS));
586 Serialization::Serialize(response, commandId);
587 Serialization::Serialize(response, static_cast<int>(CKM_API_SUCCESS));
588 Serialization::Serialize(response, RawBufferVector());
589 return response.Pop();