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>
36 int retCode = FileSystem::init();
37 // TODO what can I do when init went wrong? exit(-1) ??
39 LogError("Fatal error in FileSystem::init()");
43 CKMLogic::~CKMLogic(){}
45 RawBuffer CKMLogic::unlockUserKey(uid_t user, const std::string &password) {
46 // TODO try catch for all errors that should be supported by error code
47 int retCode = KEY_MANAGER_API_SUCCESS;
50 if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
51 auto &handle = m_userDataMap[user];
53 auto wrappedDomainKEK = fs.getDomainKEK();
55 if (wrappedDomainKEK.empty()) {
56 wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
57 fs.saveDomainKEK(wrappedDomainKEK);
60 handle.keyProvider = KeyProvider(wrappedDomainKEK, password);
62 RawBuffer key = handle.keyProvider.getPureDomainKEK();
63 handle.database = DBCrypto(fs.getDBPath(), key);
64 handle.crypto = DBCryptoModule(key);
67 } catch (const KeyProvider::Exception::Base &e) {
68 LogError("Error in KeyProvider " << e.GetMessage());
69 retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
72 MessageBuffer response;
73 Serialization::Serialize(response, retCode);
74 return response.Pop();
77 RawBuffer CKMLogic::lockUserKey(uid_t user) {
78 int retCode = KEY_MANAGER_API_SUCCESS;
79 // TODO try catch for all errors that should be supported by error code
80 m_userDataMap.erase(user);
82 MessageBuffer response;
83 Serialization::Serialize(response, retCode);
84 return response.Pop();
87 RawBuffer CKMLogic::removeUserData(uid_t user) {
88 int retCode = KEY_MANAGER_API_SUCCESS;
89 // TODO try catch for all errors that should be supported by error code
90 m_userDataMap.erase(user);
95 MessageBuffer response;
96 Serialization::Serialize(response, retCode);
97 return response.Pop();
100 RawBuffer CKMLogic::changeUserPassword(
102 const std::string &oldPassword,
103 const std::string &newPassword)
105 int retCode = KEY_MANAGER_API_SUCCESS;
108 auto wrappedDomainKEK = fs.getDomainKEK();
109 if (wrappedDomainKEK.empty()) {
110 retCode = KEY_MANAGER_API_ERROR_BAD_REQUEST;
112 wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
113 fs.saveDomainKEK(wrappedDomainKEK);
115 MessageBuffer response;
116 Serialization::Serialize(response, retCode);
117 return response.Pop();
120 RawBuffer CKMLogic::resetUserPassword(
122 const std::string &newPassword)
124 int retCode = KEY_MANAGER_API_SUCCESS;
126 if (0 == m_userDataMap.count(user)) {
127 retCode = KEY_MANAGER_API_ERROR_BAD_REQUEST;
129 auto &handler = m_userDataMap[user];
131 fs.saveDomainKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
134 MessageBuffer response;
135 Serialization::Serialize(response, retCode);
136 return response.Pop();
139 int CKMLogic::saveDataHelper(
143 const RawBuffer &key,
144 const PolicySerializable &policy)
146 if (0 == m_userDataMap.count(cred.uid))
147 return KEY_MANAGER_API_ERROR_DB_LOCKED;
149 DBRow row = { alias, cred.smackLabel, policy.restricted,
150 policy.extractable, dataType, DBCMAlgType::NONE,
151 0, RawBuffer(10, 'c'), key.size(), key };
153 auto &handler = m_userDataMap[cred.uid];
154 DBCrypto::Transaction transaction(&handler.database);
155 if (!handler.crypto.haveKey(cred.smackLabel)) {
157 auto key_optional = handler.database.getKey(cred.smackLabel);
159 LogDebug("No Key in database found. Generating new one for label: "
161 key = handler.keyProvider.generateDEK(cred.smackLabel);
166 key = handler.keyProvider.getPureDEK(key);
167 handler.crypto.pushKey(cred.smackLabel, key);
168 handler.database.saveKey(cred.smackLabel, key);
170 handler.crypto.encryptRow(policy.password, row);
171 handler.database.saveDBRow(row);
172 transaction.commit();
173 return KEY_MANAGER_API_SUCCESS;
176 RawBuffer CKMLogic::saveData(
181 const RawBuffer &key,
182 const PolicySerializable &policy)
184 int retCode = KEY_MANAGER_API_SUCCESS;
186 retCode = saveDataHelper(cred, dataType, alias, key, policy);
187 LogDebug("SaveDataHelper returned: " << retCode);
188 } catch (const KeyProvider::Exception::Base &e) {
189 LogError("KeyProvider failed with message: " << e.GetMessage());
190 retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
191 } catch (const DBCryptoModule::Exception::Base &e) {
192 LogError("DBCryptoModule failed with message: " << e.GetMessage());
193 retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
194 } catch (const DBCrypto::Exception::InternalError &e) {
195 LogError("DBCrypto failed with message: " << e.GetMessage());
196 retCode = KEY_MANAGER_API_ERROR_DB_ERROR;
197 } catch (const DBCrypto::Exception::AliasExists &e) {
198 LogError("DBCrypto couldn't save duplicate alias");
199 retCode = KEY_MANAGER_API_ERROR_DB_ALIAS_EXISTS;
200 } catch (const DBCrypto::Exception::TransactionError &e) {
201 LogError("DBCrypto transaction failed with message " << e.GetMessage());
202 retCode = KEY_MANAGER_API_ERROR_DB_ERROR;
205 MessageBuffer response;
206 Serialization::Serialize(response, static_cast<int>(LogicCommand::SAVE));
207 Serialization::Serialize(response, commandId);
208 Serialization::Serialize(response, retCode);
209 Serialization::Serialize(response, static_cast<int>(dataType));
211 return response.Pop();
214 RawBuffer CKMLogic::removeData(
220 int retCode = KEY_MANAGER_API_SUCCESS;
222 if (0 < m_userDataMap.count(cred.uid)) {
224 m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
225 } Catch (CKM::Exception) {
226 LogError("Error in deleting row!");
227 retCode = KEY_MANAGER_API_ERROR_DB_ERROR;
230 retCode = KEY_MANAGER_API_ERROR_DB_LOCKED;
233 MessageBuffer response;
234 Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
235 Serialization::Serialize(response, commandId);
236 Serialization::Serialize(response, retCode);
237 Serialization::Serialize(response, static_cast<int>(dataType));
239 return response.Pop();
242 int CKMLogic::getDataHelper(
246 const std::string &password,
250 if (0 == m_userDataMap.count(cred.uid))
251 return KEY_MANAGER_API_ERROR_DB_LOCKED;
253 auto &handler = m_userDataMap[cred.uid];
255 DBCrypto::DBRowOptional row_optional;
256 if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
257 row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType);
258 } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
259 && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
261 row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
263 LogError("Unknown type of requested data" << (int)dataType);
264 return KEY_MANAGER_API_ERROR_BAD_REQUEST;
267 LogError("No row for given alias, label and type");
268 return KEY_MANAGER_API_ERROR_DB_ALIAS_UNKNOWN;
273 if (!handler.crypto.haveKey(row.smackLabel)) {
275 auto key_optional = handler.database.getKey(row.smackLabel);
277 LogError("No key for given label in database");
278 return KEY_MANAGER_API_ERROR_DB_ERROR;
281 key = handler.keyProvider.getPureDEK(key);
282 handler.crypto.pushKey(cred.smackLabel, key);
284 handler.crypto.decryptRow(password, row);
286 LogError("Datatype: " << (int) row.dataType);
288 return KEY_MANAGER_API_SUCCESS;
291 RawBuffer CKMLogic::getData(
296 const std::string &password)
298 int retCode = KEY_MANAGER_API_SUCCESS;
302 retCode = getDataHelper(cred, dataType, alias, password, row);
303 } catch (const KeyProvider::Exception::Base &e) {
304 LogError("KeyProvider failed with error: " << e.GetMessage());
305 retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
306 } catch (const DBCryptoModule::Exception::Base &e) {
307 LogError("DBCryptoModule failed with message: " << e.GetMessage());
308 retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
309 } catch (const DBCrypto::Exception::Base &e) {
310 LogError("DBCrypto failed with message: " << e.GetMessage());
311 retCode = KEY_MANAGER_API_ERROR_DB_ERROR;
314 if (KEY_MANAGER_API_SUCCESS != retCode) {
316 row.dataType = dataType;
319 LogError("Sending dataType: " << (int)row.dataType);
321 MessageBuffer response;
322 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
323 Serialization::Serialize(response, commandId);
324 Serialization::Serialize(response, retCode);
325 Serialization::Serialize(response, static_cast<int>(row.dataType));
326 Serialization::Serialize(response, row.data);
327 return response.Pop();
330 RawBuffer CKMLogic::getDataList(
335 int retCode = KEY_MANAGER_API_SUCCESS;
336 AliasVector aliasVector;
338 if (0 < m_userDataMap.count(cred.uid)) {
339 auto &handler = m_userDataMap[cred.uid];
341 if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
342 handler.database.getAliases(dataType, cred.smackLabel, aliasVector);
344 handler.database.getKeyAliases(cred.smackLabel, aliasVector);
346 } Catch (CKM::Exception) {
347 LogError("Failed to get aliases");
348 retCode = KEY_MANAGER_API_ERROR_DB_ERROR;
351 retCode = KEY_MANAGER_API_ERROR_DB_LOCKED;
354 MessageBuffer response;
355 Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
356 Serialization::Serialize(response, commandId);
357 Serialization::Serialize(response, retCode);
358 Serialization::Serialize(response, static_cast<int>(dataType));
359 Serialization::Serialize(response, aliasVector);
360 return response.Pop();
363 int CKMLogic::createKeyPairRSAHelper(
366 const Alias &aliasPrivate,
367 const Alias &aliasPublic,
368 const PolicySerializable &policyPrivate,
369 const PolicySerializable &policyPublic)
371 if (0 >= m_userDataMap.count(cred.uid))
372 return KEY_MANAGER_API_ERROR_DB_LOCKED;
374 auto &handler = m_userDataMap[cred.uid];
378 if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
379 (retCode = CryptoService::createKeyPairRSA(size, prv, pub)))
381 LogDebug("CryptoService error with code: " << retCode);
382 return KEY_MANAGER_API_ERROR_SERVER_ERROR; // TODO error code
385 DBCrypto::Transaction transaction(&handler.database);
386 retCode = saveDataHelper(cred,
387 toDBDataType(prv.getType()),
392 if (KEY_MANAGER_API_SUCCESS != retCode)
395 retCode = saveDataHelper(cred,
396 toDBDataType(pub.getType()),
401 if (KEY_MANAGER_API_SUCCESS != retCode)
404 transaction.commit();
409 RawBuffer CKMLogic::createKeyPairRSA(
413 const Alias &aliasPrivate,
414 const Alias &aliasPublic,
415 const PolicySerializable &policyPrivate,
416 const PolicySerializable &policyPublic)
418 int retCode = KEY_MANAGER_API_SUCCESS;
421 retCode = createKeyPairRSAHelper(
429 } catch (DBCrypto::Exception::AliasExists &e) {
430 LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
431 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
432 } catch (DBCrypto::Exception::TransactionError &e) {
433 LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
434 retCode = CKM_API_ERROR_DB_ERROR;
435 } catch (DBCrypto::Exception::InternalError &e) {
436 LogDebug("DBCrypto internal error: " << e.GetMessage());
437 retCode = KEY_MANAGER_API_ERROR_DB_ERROR;
440 MessageBuffer response;
441 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
442 Serialization::Serialize(response, commandId);
443 Serialization::Serialize(response, retCode);
445 return response.Pop();
448 int CKMLogic::createKeyPairECDSAHelper(
451 const Alias &aliasPrivate,
452 const Alias &aliasPublic,
453 const PolicySerializable &policyPrivate,
454 const PolicySerializable &policyPublic)
456 if (0 >= m_userDataMap.count(cred.uid))
457 return KEY_MANAGER_API_ERROR_DB_LOCKED;
459 auto &handler = m_userDataMap[cred.uid];
463 if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
464 (retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(type), prv, pub)))
466 LogError("CryptoService failed with code: " << retCode);
467 return KEY_MANAGER_API_ERROR_SERVER_ERROR; // TODO error code
470 DBCrypto::Transaction transaction(&handler.database);
472 retCode = saveDataHelper(cred,
473 toDBDataType(prv.getType()),
478 if (KEY_MANAGER_API_SUCCESS != retCode)
481 retCode = saveDataHelper(cred,
482 toDBDataType(pub.getType()),
487 if (KEY_MANAGER_API_SUCCESS != retCode)
490 transaction.commit();
495 RawBuffer CKMLogic::createKeyPairECDSA(
499 const Alias &aliasPrivate,
500 const Alias &aliasPublic,
501 const PolicySerializable &policyPrivate,
502 const PolicySerializable &policyPublic)
504 int retCode = KEY_MANAGER_API_SUCCESS;
507 retCode = createKeyPairECDSAHelper(
514 } catch (const DBCrypto::Exception::AliasExists &e) {
515 LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
516 retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
517 } catch (const DBCrypto::Exception::TransactionError &e) {
518 LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
519 retCode = CKM_API_ERROR_DB_ERROR;
520 } catch (const DBCrypto::Exception::InternalError &e) {
521 LogDebug("DBCrypto internal error: " << e.GetMessage());
522 retCode = KEY_MANAGER_API_ERROR_DB_ERROR;
525 MessageBuffer response;
526 Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
527 Serialization::Serialize(response, commandId);
528 Serialization::Serialize(response, retCode);
530 return response.Pop();