2 * Copyright (c) 2015 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.
17 #include "keymanager/keymanager_instance.h"
19 #include <ckmc/ckmc-manager.h>
21 #include <pkgmgr-info.h>
23 #include "common/logger.h"
24 #include "common/optional.h"
25 #include "common/platform_result.h"
26 #include "common/scope_exit.h"
27 #include "common/task-queue.h"
28 #include "common/tools.h"
29 #include "common/virtual_fs.h"
32 namespace keymanager {
34 using common::ErrorCode;
35 using common::optional;
36 using common::PlatformResult;
37 using common::TaskQueue;
38 using common::VirtualFs;
42 typedef std::vector<unsigned char> RawBuffer;
44 const char* kTypeRSA = "RSA";
45 const char* kTypeECDSA = "ECDSA";
47 RawBuffer Base64ToRawBuffer(const std::string& base64) {
51 guchar* raw_data = g_base64_decode(base64.c_str(), &len);
55 raw_buffer.assign(raw_data, raw_data + len);
62 std::string RawBufferToBase64(const RawBuffer& buf) {
68 gchar* base64 = g_base64_encode(&buf[0], buf.size());
76 ckmc_ec_type_e GetEllipticCurveType(const std::string& type) {
79 if ("EC_PRIME256V1" == type) {
80 return CKMC_EC_PRIME256V1;
81 } else if ("EC_SECP384R1" == type) {
82 return CKMC_EC_SECP384R1;
84 return CKMC_EC_PRIME192V1;
88 ckmc_key_type_e StringToKeyType(const std::string& type) {
91 if ("KEY_RSA_PUBLIC" == type) {
92 return CKMC_KEY_RSA_PUBLIC;
93 } else if ("KEY_RSA_PRIVATE" == type) {
94 return CKMC_KEY_RSA_PRIVATE;
95 } else if ("KEY_ECDSA_PUBLIC" == type) {
96 return CKMC_KEY_ECDSA_PUBLIC;
97 } else if ("KEY_ECDSA_PRIVATE" == type) {
98 return CKMC_KEY_ECDSA_PRIVATE;
99 } else if ("KEY_DSA_PUBLIC" == type) {
100 return CKMC_KEY_DSA_PUBLIC;
101 } else if ("KEY_DSA_PRIVATE" == type) {
102 return CKMC_KEY_DSA_PRIVATE;
103 } else if ("KEY_AES" == type) {
106 return CKMC_KEY_NONE;
110 std::string KeyTypeToString(ckmc_key_type_e type) {
117 case CKMC_KEY_RSA_PUBLIC:
118 return "KEY_RSA_PUBLIC";
120 case CKMC_KEY_RSA_PRIVATE:
121 return "KEY_RSA_PRIVATE";
123 case CKMC_KEY_ECDSA_PUBLIC:
124 return "KEY_ECDSA_PUBLIC";
126 case CKMC_KEY_ECDSA_PRIVATE:
127 return "KEY_ECDSA_PRIVATE";
129 case CKMC_KEY_DSA_PUBLIC:
130 return "KEY_DSA_PUBLIC";
132 case CKMC_KEY_DSA_PRIVATE:
133 return "KEY_DSA_PRIVATE";
139 LoggerE("Unknown key type");
140 return "KEY_UNKNOWN";
143 ckmc_hash_algo_e StringToHashAlgorithm(const std::string& str) {
144 if ("HASH_SHA1" == str) {
145 return CKMC_HASH_SHA1;
146 } else if ("HASH_SHA256" == str) {
147 return CKMC_HASH_SHA256;
148 } else if ("HASH_SHA384" == str) {
149 return CKMC_HASH_SHA384;
150 } else if ("HASH_SHA512" == str) {
151 return CKMC_HASH_SHA512;
154 return CKMC_HASH_NONE;
157 ckmc_rsa_padding_algo_e StringToRsaPadding(const std::string& str) {
158 if ("PADDING_PKCS1" == str) {
159 return CKMC_PKCS1_PADDING;
160 } else if ("PADDING_X931" == str) {
161 return CKMC_X931_PADDING;
164 return CKMC_NONE_PADDING;
167 RawBuffer ToRawBuffer(const ckmc_key_s* key) {
168 return RawBuffer(key->raw_key, key->raw_key + key->key_size);
171 RawBuffer ToRawBuffer(const ckmc_raw_buffer_s* buffer) {
172 return RawBuffer(buffer->data, buffer->data + buffer->size);
175 RawBuffer ToRawBuffer(const ckmc_cert_s* cert) {
176 return RawBuffer(cert->raw_cert, cert->raw_cert + cert->cert_size);
179 typedef int (*AliasListFunction)(ckmc_alias_list_s**);
181 void GetGenericAliasList(AliasListFunction func, picojson::object* out) {
184 ckmc_alias_list_s* alias_list = nullptr;
185 int ret = func(&alias_list);
187 picojson::value result{picojson::array{}};
189 if (CKMC_ERROR_NONE == ret) {
190 auto& aliases = result.get<picojson::array>();
191 ckmc_alias_list_s* head = alias_list;
194 aliases.push_back(picojson::value(head->alias ? head->alias : ""));
199 ckmc_alias_list_all_free(alias_list);
203 common::tools::ReportSuccess(result, *out);
207 KeyManagerInstance::KeyManagerInstance() {
209 using std::placeholders::_1;
210 using std::placeholders::_2;
212 RegisterSyncHandler("KeyManager_getKeyAliasList",
213 std::bind(&KeyManagerInstance::GetKeyAliasList, this, _1, _2));
214 RegisterSyncHandler("KeyManager_getCertificatesAliasList",
215 std::bind(&KeyManagerInstance::GetCertificateAliasList, this, _1, _2));
216 RegisterSyncHandler("KeyManager_getDataAliasList",
217 std::bind(&KeyManagerInstance::GetDataAliasList, this, _1, _2));
218 RegisterSyncHandler("KeyManager_getKey",
219 std::bind(&KeyManagerInstance::GetKey, this, _1, _2));
220 RegisterSyncHandler("KeyManager_saveKey",
221 std::bind(&KeyManagerInstance::SaveKey, this, _1, _2));
222 RegisterSyncHandler("KeyManager_removeAlias",
223 std::bind(&KeyManagerInstance::RemoveAlias, this, _1, _2));
224 RegisterSyncHandler("KeyManager_generateKeyPair",
225 std::bind(&KeyManagerInstance::GenerateKeyPair, this, _1, _2));
226 RegisterSyncHandler("KeyManager_getCertificate",
227 std::bind(&KeyManagerInstance::GetCertificate, this, _1, _2));
228 RegisterSyncHandler("KeyManager_saveCertificate",
229 std::bind(&KeyManagerInstance::SaveCertificate, this, _1, _2));
230 RegisterSyncHandler("KeyManager_loadCertificateFromFile",
231 std::bind(&KeyManagerInstance::LoadCertificateFromFile, this, _1, _2));
232 RegisterSyncHandler("KeyManager_saveData",
233 std::bind(&KeyManagerInstance::SaveData, this, _1, _2));
234 RegisterSyncHandler("KeyManager_getData",
235 std::bind(&KeyManagerInstance::GetData, this, _1, _2));
236 RegisterSyncHandler("KeyManager_createSignature",
237 std::bind(&KeyManagerInstance::CreateSignature, this, _1, _2));
238 RegisterSyncHandler("KeyManager_verifySignature",
239 std::bind(&KeyManagerInstance::VerifySignature, this, _1, _2));
240 RegisterSyncHandler("KeyManager_loadFromPKCS12File",
241 std::bind(&KeyManagerInstance::LoadFromPKCS12File, this, _1, _2));
242 RegisterSyncHandler("KeyManager_allowAccessControl",
243 std::bind(&KeyManagerInstance::AllowAccessControl, this, _1, _2));
244 RegisterSyncHandler("KeyManager_denyAccessControl",
245 std::bind(&KeyManagerInstance::DenyAccessControl, this, _1, _2));
246 RegisterSyncHandler("KeyManager_isDataNameFound",
247 std::bind(&KeyManagerInstance::IsDataNameFound, this, _1, _2));
250 KeyManagerInstance::~KeyManagerInstance() {
254 void KeyManagerInstance::GetKeyAliasList(const picojson::value& args,
255 picojson::object& out) {
257 GetGenericAliasList(ckmc_get_key_alias_list, &out);
260 void KeyManagerInstance::GetCertificateAliasList(const picojson::value& args,
261 picojson::object& out) {
263 GetGenericAliasList(ckmc_get_cert_alias_list, &out);
266 void KeyManagerInstance::GetDataAliasList(const picojson::value& args,
267 picojson::object& out) {
269 GetGenericAliasList(ckmc_get_data_alias_list, &out);
272 void KeyManagerInstance::GetKey(const picojson::value& args,
273 picojson::object& out) {
275 const auto& key_alias = args.get("name").get<std::string>();
276 const auto& password_value = args.get("password");
278 std::string password;
280 if (password_value.is<std::string>()) {
281 password = password_value.get<std::string>();
284 ckmc_key_s* key = nullptr;
285 int ret = ckmc_get_key(key_alias.c_str(), password.c_str(), &key);
287 if (CKMC_ERROR_NONE == ret) {
288 picojson::object result;
290 result["name"] = picojson::value(key_alias);
292 result["password"] = picojson::value(key->password);
295 // if key was retrieved it is extractable from DB
296 result["extractable"] = picojson::value(true);
297 result["keyType"] = picojson::value(KeyTypeToString(key->key_type));
298 result["rawKey"] = picojson::value(RawBufferToBase64(ToRawBuffer(key)));
301 ReportSuccess(picojson::value{result}, out);
303 LoggerE("Failed to get key: %d", ret);
305 PlatformResult error(ErrorCode::UNKNOWN_ERR, "Failed to get key");
308 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
309 error = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to find key");
312 case CKMC_ERROR_INVALID_PARAMETER:
313 error = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Input parameter is invalid");
317 ReportError(error, &out);
321 void KeyManagerInstance::SaveKey(const picojson::value& args,
322 picojson::object& out) {
325 const picojson::value& key_obj = args.get("key");
326 const std::string& alias = key_obj.get("name").get<std::string>();
327 const std::string& type = key_obj.get("keyType").get<std::string>();
328 bool extractable = key_obj.get("extractable").get<bool>();
329 const double callback_id = args.get("callbackId").get<double>();
332 if (args.get("rawKey").is<std::string>()) {
333 base64 = args.get("rawKey").get<std::string>();
337 if (key_obj.get("password").is<std::string>()) {
338 pass = key_obj.get("password").get<std::string>();
341 RawBuffer* raw_buffer = new RawBuffer(std::move(Base64ToRawBuffer(base64)));
342 ckmc_key_type_e key_type = StringToKeyType(type);
344 auto save = [alias, pass, key_type, extractable, raw_buffer]
345 (const std::shared_ptr<picojson::value>& response) -> void {
347 LoggerD("Enter save_key");
348 ckmc_policy_s policy { const_cast<char*>(pass.c_str()), extractable };
349 ckmc_key_s key { const_cast<unsigned char*>(&(*raw_buffer)[0]),
350 raw_buffer->size(), key_type, const_cast<char*>(pass.c_str()) };
352 int ret = ckmc_save_key(alias.c_str(), key, policy);
353 if (CKMC_ERROR_NONE != ret) {
354 LoggerE("Failed to save key alias [%d]", ret);
355 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
356 if (CKMC_ERROR_INVALID_PARAMETER == ret) {
357 result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
359 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save key.");
361 common::tools::ReportError(result, &response->get<picojson::object>());
363 //as key_type is determined inside key manager during storing keys
364 //we have to get saved key and check key_type again.
365 ckmc_key_s * saved_key = nullptr;
366 ret = ckmc_get_key(alias.c_str(), pass.c_str(), &saved_key);
367 if (CKMC_ERROR_NONE == ret) {
368 picojson::object& obj = response->get<picojson::object>();
369 obj["keyType"] = picojson::value(KeyTypeToString(saved_key->key_type));
370 ckmc_key_free(saved_key);
373 common::tools::ReportSuccess(response->get<picojson::object>());
379 auto save_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
380 LoggerD("Enter save_key_result");
381 picojson::object& obj = response->get<picojson::object>();
382 obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
383 this->PostMessage(response->serialize().c_str());
386 TaskQueue::GetInstance().Queue<picojson::value>(
389 std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
392 void KeyManagerInstance::RemoveAlias(const picojson::value& args,
393 picojson::object& out) {
396 const std::string& alias = args.get("alias").get<std::string>();
397 int ret = ckmc_remove_alias(alias.c_str());
399 if (CKMC_ERROR_NONE != ret) {
400 LoggerE("Failed to remove alias [%d]", ret);
401 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
403 case CKMC_ERROR_INVALID_PARAMETER:
404 result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed");
406 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
407 result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
410 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to remove alias");
412 ReportError(result, &out);
418 void KeyManagerInstance::GenerateKeyPair(const picojson::value& args,
419 picojson::object& out) {
422 const picojson::value& priv_key = args.get("privKeyName");
423 const picojson::value& pub_key = args.get("pubKeyName");
424 const std::string& priv_name = priv_key.get("name").get<std::string>();
425 const std::string& pub_name = pub_key.get("name").get<std::string>();
426 const std::string& type = args.get("type").get<std::string>();
427 const int size = std::stoi(args.get("size").get<std::string>());
428 const double callback_id = args.get("callbackId").get<double>();
430 std::string priv_pass;
431 if (priv_key.get("password").is<std::string>()) {
432 priv_pass = priv_key.get("password").get<std::string>();
434 bool priv_extractable = priv_key.get("extractable").get<bool>();
436 std::string pub_pass;
437 if (pub_key.get("password").is<std::string>()) {
438 pub_pass = pub_key.get("password").get<std::string>();
440 bool pub_extractable = pub_key.get("extractable").get<bool>();
442 std::string elliptic;
443 if (args.get("ellipticCurveType").is<std::string>()) {
444 elliptic = args.get("ellipticCurveType").get<std::string>();
448 [size, priv_pass, pub_pass, priv_extractable, pub_extractable, priv_name, pub_name, type, elliptic]
449 (const std::shared_ptr<picojson::value>& response) -> void {
450 LoggerD("Enter generate");
451 int ret = CKMC_ERROR_NONE;
453 ckmc_policy_s priv_policy { const_cast<char*>(priv_pass.c_str()), priv_extractable };
454 ckmc_policy_s pub_policy { const_cast<char*>(pub_pass.c_str()), pub_extractable };
456 if (kTypeRSA == type) {
457 LoggerD("Generating RSA, size: %d", size);
458 ret = ckmc_create_key_pair_rsa(size, priv_name.c_str(),
459 pub_name.c_str(), priv_policy, pub_policy);
460 LoggerD("Generating RSA - done");
461 } else if (kTypeECDSA == type) {
462 LoggerD("Generating ECDSA, curve: %s", elliptic.c_str());
463 ret = ckmc_create_key_pair_ecdsa(GetEllipticCurveType(elliptic), priv_name.c_str(),
464 pub_name.c_str(), priv_policy, pub_policy);
465 LoggerD("Generating ECDSA - done");
467 LoggerD("Generating DSA, size: %d", size);
468 ret = ckmc_create_key_pair_dsa(size, priv_name.c_str(),
469 pub_name.c_str(), priv_policy, pub_policy);
470 LoggerD("Generating DSA - done");
473 if (CKMC_ERROR_NONE != ret) {
474 LoggerD("Failed to generate key pair: %d", ret);
475 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
476 if (CKMC_ERROR_INVALID_PARAMETER == ret) {
477 result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value passed.");
479 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create key pair.");
481 common::tools::ReportError(result, &response->get<picojson::object>());
483 common::tools::ReportSuccess(response->get<picojson::object>());
487 auto generate_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
488 LoggerD("Enter generate_response");
489 picojson::object& obj = response->get<picojson::object>();
490 obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
491 this->PostMessage(response->serialize().c_str());
494 TaskQueue::GetInstance().Queue<picojson::value>(
497 std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
502 void KeyManagerInstance::GetCertificate(const picojson::value& args,
503 picojson::object& out) {
506 const std::string& alias = args.get("name").get<std::string>();
509 if (args.get("password").is<std::string>()) {
510 pass = args.get("password").get<std::string>();
513 ckmc_cert_s* cert = nullptr;
514 int ret = ckmc_get_cert(alias.c_str(), pass.c_str(), &cert);
516 if (CKMC_ERROR_NONE != ret) {
517 LoggerE("Failed to get certificate: %d", ret);
518 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
520 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
521 result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Certificate alias not found");
523 case CKMC_ERROR_INVALID_PARAMETER:
524 result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed");
527 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificate");
530 ReportError(result, &out);
532 picojson::value result = picojson::value(picojson::object());
533 picojson::object& obj = result.get<picojson::object>();
535 //if cert was retrieved it is extractable from db
536 obj["extractable"] = picojson::value(true);
537 obj["name"] = picojson::value(alias);
539 obj["password"] = picojson::value(pass);
542 RawBuffer raw_cert (cert->raw_cert, cert->raw_cert + cert->cert_size);
543 obj["rawCert"] = picojson::value(RawBufferToBase64(raw_cert));
545 ReportSuccess(result, out);
549 void KeyManagerInstance::SaveCertificate(const picojson::value& args,
550 picojson::object& out) {
553 RawBuffer* raw_buffer = new RawBuffer(std::move(Base64ToRawBuffer(args.get("rawCert").get<std::string>())));
554 const auto& certificate = args.get("certificate");
555 const auto& alias = certificate.get("name").get<std::string>();
556 const auto& password_value = certificate.get("password");
557 const auto extractable = certificate.get("extractable").get<bool>();
558 double callback_id = args.get("callbackId").get<double>();
560 std::string password;
562 if (password_value.is<std::string>()) {
563 password = password_value.get<std::string>();
566 auto save_certificate = [raw_buffer, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
567 LoggerD("Enter save_certificate");
569 ckmc_cert_s certificate { const_cast<unsigned char*>(&(*raw_buffer)[0]), raw_buffer->size(), CKMC_FORM_DER };
570 ckmc_policy_s policy { const_cast<char*>(password.c_str()), extractable };
572 int ret = ckmc_save_cert(alias.c_str(), certificate, policy);
574 PlatformResult success(ErrorCode::NO_ERROR);
577 case CKMC_ERROR_NONE:
580 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
581 success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
584 case CKMC_ERROR_INVALID_PARAMETER:
585 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to save certificate");
589 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save certificate");
594 common::tools::ReportSuccess(result->get<picojson::object>());
596 LoggerE("Failed to save certificate: %d", ret);
597 common::tools::ReportError(success, &result->get<picojson::object>());
603 auto save_certificate_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
604 LoggerD("Enter save_certificate_result");
605 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
606 this->PostMessage(result->serialize().c_str());
609 TaskQueue::GetInstance().Queue<picojson::value>(
611 save_certificate_result,
612 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
617 void KeyManagerInstance::LoadCertificateFromFile(const picojson::value& args,
618 picojson::object& out) {
621 const auto& file_uri = args.get("fileURI").get<std::string>();
622 const auto& certificate = args.get("certificate");
623 const auto& alias = certificate.get("name").get<std::string>();
624 const auto& password_value = args.get("password");
625 const auto extractable = certificate.get("extractable").get<bool>();
626 double callback_id = args.get("callbackId").get<double>();
628 std::string password;
630 if (password_value.is<std::string>()) {
631 password = password_value.get<std::string>();
634 auto load_certificate = [file_uri, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
635 LoggerD("Enter load_certificate");
637 std::string file = VirtualFs::GetInstance().GetRealPath(file_uri);
638 ckmc_cert_s* certificate = nullptr;
639 int ret = ckmc_load_cert_from_file(file.c_str(), &certificate);
640 std::string certificate_data;
642 if (CKMC_ERROR_NONE == ret) {
643 ckmc_policy_s policy { const_cast<char*>(password.c_str()), extractable };
644 ret = ckmc_save_cert(alias.c_str(), *certificate, policy);
645 if (CKMC_ERROR_NONE != ret) {
646 LoggerE("Failed to save certificate: %d", ret);
648 certificate_data = RawBufferToBase64(ToRawBuffer(certificate));
649 ckmc_cert_free(certificate);
651 LoggerE("Failed to load certificate: %d", ret);
654 PlatformResult success(ErrorCode::NO_ERROR);
657 case CKMC_ERROR_NONE:
660 case CKMC_ERROR_FILE_ACCESS_DENIED:
661 success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "File not found");
664 case CKMC_ERROR_INVALID_PARAMETER:
665 case CKMC_ERROR_INVALID_FORMAT:
666 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to load certificate");
670 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to load certificate");
675 common::tools::ReportSuccess(picojson::value(certificate_data), result->get<picojson::object>());
677 common::tools::ReportError(success, &result->get<picojson::object>());
681 auto load_certificate_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
682 LoggerD("Enter load_certificate_result");
683 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
684 this->PostMessage(result->serialize().c_str());
687 TaskQueue::GetInstance().Queue<picojson::value>(
689 load_certificate_result,
690 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
695 void KeyManagerInstance::SaveData(const picojson::value& args,
696 picojson::object& out) {
699 std::string data_raw = args.get("rawData").get<std::string>();
700 const auto& data = args.get("data");
701 const auto& alias = data.get("name").get<std::string>();
702 const auto& password_value = data.get("password");
703 const auto extractable = data.get("extractable").get<bool>();
704 double callback_id = args.get("callbackId").get<double>();
706 std::string password;
708 if (password_value.is<std::string>()) {
709 password = password_value.get<std::string>();
712 auto save_data = [data_raw, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
713 LoggerD("Enter save_data");
715 unsigned char* data = new unsigned char[data_raw.size()];
716 std::copy(data_raw.begin(), data_raw.end(), data);
718 ckmc_raw_buffer_s raw_data { data, data_raw.size() };
719 ckmc_policy_s policy { const_cast<char*>(password.c_str()), extractable };
721 int ret = ckmc_save_data(alias.c_str(), raw_data, policy);
723 PlatformResult success(ErrorCode::NO_ERROR);
726 case CKMC_ERROR_NONE:
729 case CKMC_ERROR_INVALID_PARAMETER:
730 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to save data");
734 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save data");
739 common::tools::ReportSuccess(result->get<picojson::object>());
741 LoggerE("Failed to save data: %d", ret);
742 common::tools::ReportError(success, &result->get<picojson::object>());
748 auto save_data_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
749 LoggerD("Enter save_data_result");
750 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
751 this->PostMessage(result->serialize().c_str());
754 TaskQueue::GetInstance().Queue<picojson::value>(
757 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
762 void KeyManagerInstance::GetData(const picojson::value& args,
763 picojson::object& out) {
766 const auto& data_alias = args.get("name").get<std::string>();
767 const auto& password_value = args.get("password");
769 std::string password;
771 if (password_value.is<std::string>()) {
772 password = password_value.get<std::string>();
775 ckmc_raw_buffer_s* data = nullptr;
776 int ret = ckmc_get_data(data_alias.c_str(), password.c_str(), &data);
778 if (CKMC_ERROR_NONE == ret) {
779 picojson::object result;
781 result["name"] = picojson::value(data_alias);
782 result["password"] = picojson::value(password);
783 // if key was retrieved it is extractable from DB
784 result["extractable"] = picojson::value(true);
785 result["rawData"] = picojson::value(std::string (data->data, data->data + data->size));
787 ckmc_buffer_free(data);
788 ReportSuccess(picojson::value{result}, out);
790 LoggerE("Failed to get data: %d", ret);
792 PlatformResult error(ErrorCode::UNKNOWN_ERR, "Failed to get key");
795 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
796 error = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to find key");
799 case CKMC_ERROR_INVALID_PARAMETER:
800 error = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Input parameter is invalid");
804 ReportError(error, &out);
808 void KeyManagerInstance::CreateSignature(const picojson::value& args,
809 picojson::object& out) {
812 const auto& alias = args.get("privKeyAlias").get<std::string>();
813 RawBuffer* raw_buffer = new RawBuffer(std::move(Base64ToRawBuffer(args.get("message").get<std::string>())));
814 const auto& password_value = args.get("password");
815 double callback_id = args.get("callbackId").get<double>();
816 ckmc_hash_algo_e hash = StringToHashAlgorithm(args.get("hashAlgorithmType").get<std::string>());
817 ckmc_rsa_padding_algo_e padding = StringToRsaPadding(args.get("padding").get<std::string>());
819 std::string password;
821 if (password_value.is<std::string>()) {
822 password = password_value.get<std::string>();
825 auto create_certificate = [alias, raw_buffer, password, hash, padding](const std::shared_ptr<picojson::value>& result) {
826 LoggerD("Enter create_certificate");
828 ckmc_raw_buffer_s* signature = nullptr;
829 ckmc_raw_buffer_s message = { const_cast<unsigned char*>(&(*raw_buffer)[0]), raw_buffer->size() };
830 int ret = ckmc_create_signature(alias.c_str(), password.c_str(), message, hash, padding, &signature);
832 PlatformResult success(ErrorCode::NO_ERROR);
835 case CKMC_ERROR_NONE:
838 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
839 success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
842 case CKMC_ERROR_INVALID_PARAMETER:
843 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to create signature");
847 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create signature");
852 common::tools::ReportSuccess(picojson::value(RawBufferToBase64(ToRawBuffer(signature))), result->get<picojson::object>());
853 ckmc_buffer_free(signature);
855 LoggerE("Failed to create signature: %d", ret);
856 common::tools::ReportError(success, &result->get<picojson::object>());
862 auto create_certificate_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
863 LoggerD("Enter create_certificate_result");
864 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
865 this->PostMessage(result->serialize().c_str());
868 TaskQueue::GetInstance().Queue<picojson::value>(
870 create_certificate_result,
871 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
876 void KeyManagerInstance::VerifySignature(const picojson::value& args,
877 picojson::object& out) {
880 const auto& alias = args.get("pubKeyAlias").get<std::string>();
881 RawBuffer* message = new RawBuffer(std::move(Base64ToRawBuffer(args.get("message").get<std::string>())));
882 RawBuffer* signature = new RawBuffer(std::move(Base64ToRawBuffer(args.get("signature").get<std::string>())));
883 const auto& password_value = args.get("password");
884 double callback_id = args.get("callbackId").get<double>();
885 ckmc_hash_algo_e hash = StringToHashAlgorithm(args.get("hashAlgorithmType").get<std::string>());
886 ckmc_rsa_padding_algo_e padding = StringToRsaPadding(args.get("padding").get<std::string>());
888 std::string password;
890 if (password_value.is<std::string>()) {
891 password = password_value.get<std::string>();
894 auto verify_certificate = [alias, message, signature, password, hash, padding](const std::shared_ptr<picojson::value>& result) {
895 LoggerD("Enter verify_certificate");
897 ckmc_raw_buffer_s message_buf = { const_cast<unsigned char*>(&(*message)[0]), message->size() };
898 ckmc_raw_buffer_s signature_buf = { const_cast<unsigned char*>(&(*signature)[0]), signature->size() };
900 int ret = ckmc_verify_signature(alias.c_str(), password.c_str(), message_buf, signature_buf, hash , padding);
902 PlatformResult success(ErrorCode::NO_ERROR);
905 case CKMC_ERROR_NONE:
908 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
909 success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
912 case CKMC_ERROR_INVALID_PARAMETER:
913 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to verify signature");
917 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to verify signature");
922 common::tools::ReportSuccess(result->get<picojson::object>());
924 LoggerE("Failed to verify signature: %d", ret);
925 common::tools::ReportError(success, &result->get<picojson::object>());
932 auto verify_certificate_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
933 LoggerD("Enter verify_certificate_result");
934 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
935 this->PostMessage(result->serialize().c_str());
938 TaskQueue::GetInstance().Queue<picojson::value>(
940 verify_certificate_result,
941 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
946 void KeyManagerInstance::LoadFromPKCS12File(const picojson::value& args,
947 picojson::object& out) {
950 const auto& file_uri = args.get("fileURI").get<std::string>();
951 const auto& key_alias = args.get("privKeyName").get<std::string>();
952 const auto& cert_alias = args.get("certificateName").get<std::string>();
953 const auto& password_value = args.get("password");
954 double callback_id = args.get("callbackId").get<double>();
956 std::string password;
958 if (password_value.is<std::string>()) {
959 password = password_value.get<std::string>();
962 auto load_file = [file_uri, password, cert_alias, key_alias](const std::shared_ptr<picojson::value>& result) {
963 LoggerD("Enter load_file");
964 std::string file = VirtualFs::GetInstance().GetRealPath(file_uri);
965 ckmc_pkcs12_s* pkcs12 = nullptr;
967 int ret = ckmc_pkcs12_load(file.c_str(), password.c_str(), &pkcs12);
969 if (CKMC_ERROR_NONE == ret) {
971 ckmc_pkcs12_free(pkcs12);
973 ckmc_policy_s policy { const_cast<char*>(password.c_str()), true };
975 // it's safer to use ckmc_save_pkcs12() here, however JS API specifies
976 // two different aliases for private key and certificate
978 ret = ckmc_save_cert(cert_alias.c_str(), *pkcs12->cert, policy);
979 if (CKMC_ERROR_NONE != ret) {
980 LoggerE("Failed to save certificate: %d", ret);
984 if (CKMC_ERROR_NONE == ret && pkcs12->priv_key) {
985 ret = ckmc_save_key(key_alias.c_str(), *pkcs12->priv_key, policy);
986 if (CKMC_ERROR_NONE != ret) {
987 LoggerE("Failed to save private key: %d", ret);
990 ckmc_remove_cert(cert_alias.c_str());
995 LoggerE("Failed to load PKCS12 file: %d", ret);
998 PlatformResult success(ErrorCode::NO_ERROR);
1001 case CKMC_ERROR_NONE:
1004 case CKMC_ERROR_FILE_ACCESS_DENIED:
1005 success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Certificate file not found");
1008 case CKMC_ERROR_INVALID_FORMAT:
1009 case CKMC_ERROR_INVALID_PARAMETER:
1010 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Certificate file has wrong format");
1013 case CKMC_ERROR_PERMISSION_DENIED:
1014 success = PlatformResult(ErrorCode::IO_ERR, "Permission has been denied");
1018 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to open certificate file");
1023 common::tools::ReportSuccess(result->get<picojson::object>());
1025 common::tools::ReportError(success, &result->get<picojson::object>());
1029 auto load_file_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
1030 LoggerD("Enter load_file_result");
1031 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
1032 this->PostMessage(result->serialize().c_str());
1035 TaskQueue::GetInstance().Queue<picojson::value>(
1038 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
1043 void KeyManagerInstance::AllowAccessControl(const picojson::value& args,
1044 picojson::object& out) {
1047 const std::string& data_name = args.get("dataName").get<std::string>();
1048 const std::string& id = args.get("id").get<std::string>();
1049 const double callback_id = args.get("callbackId").get<double>();
1050 const std::string& access = args.get("accessControlType").get<std::string>();
1051 ckmc_access_right_e granted = CKMC_AR_READ;
1052 if ("READ_REMOVE" == access) {
1053 granted = CKMC_AR_READ_REMOVE;
1056 auto allow = [data_name, id, granted](const std::shared_ptr<picojson::value>& response) -> void {
1057 //as ckmc_allow_access does not check if package id exists
1058 //it has to be done before allowing access
1059 pkgmgrinfo_pkginfo_h handle = nullptr;
1060 int ret = pkgmgrinfo_pkginfo_get_pkginfo(id.c_str(), &handle);
1061 if (PMINFO_R_OK != ret) {
1062 LoggerE("Package id not found.");
1063 common::tools::ReportError(PlatformResult(
1064 ErrorCode::NOT_FOUND_ERR, "Package id not found."), &response->get<picojson::object>());
1067 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1069 ret = ckmc_allow_access(data_name.c_str(), id.c_str(), granted);
1070 if (CKMC_ERROR_NONE != ret) {
1071 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1072 if (CKMC_ERROR_DB_ALIAS_UNKNOWN == ret) {
1073 result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found.");
1075 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to allow access.");
1077 common::tools::ReportError(result, &response->get<picojson::object>());
1079 common::tools::ReportSuccess(response->get<picojson::object>());
1083 auto allow_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1084 picojson::object& obj = response->get<picojson::object>();
1085 obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
1086 this->PostMessage(response->serialize().c_str());
1089 TaskQueue::GetInstance().Queue<picojson::value>(
1092 std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
1095 void KeyManagerInstance::DenyAccessControl(const picojson::value& args,
1096 picojson::object& out) {
1099 const std::string& data_name = args.get("dataName").get<std::string>();
1100 const std::string& id = args.get("id").get<std::string>();
1101 const double callback_id = args.get("callbackId").get<double>();
1103 auto deny = [data_name, id](const std::shared_ptr<picojson::value>& response) -> void {
1104 int ret = ckmc_deny_access(data_name.c_str(), id.c_str());
1105 if (CKMC_ERROR_NONE != ret) {
1106 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1107 if (CKMC_ERROR_DB_ALIAS_UNKNOWN == ret) {
1108 result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found.");
1110 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to deny access.");
1112 common::tools::ReportError(result, &response->get<picojson::object>());
1114 common::tools::ReportSuccess(response->get<picojson::object>());
1118 auto deny_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1119 picojson::object& obj = response->get<picojson::object>();
1120 obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
1121 this->PostMessage(response->serialize().c_str());
1124 TaskQueue::GetInstance().Queue<picojson::value>(
1127 std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
1130 void KeyManagerInstance::IsDataNameFound(const picojson::value& args,
1131 picojson::object& out){
1134 const std::string& data_name = args.get("dataName").get<std::string>();
1135 bool data_found = false;
1136 ckmc_alias_list_s* alias_list = nullptr;
1138 int ret = ckmc_get_data_alias_list(&alias_list);
1139 if (CKMC_ERROR_NONE != ret) {
1140 LoggerE("Failed to get data list [%d]", ret);
1141 PlatformResult result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get data list.");
1142 if (CKMC_ERROR_DB_ALIAS_UNKNOWN == ret) {
1143 result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Data name not found.");
1146 common::tools::ReportError(result, &out);
1150 ckmc_alias_list_s* head = alias_list;
1152 if (!strcmp(head->alias, data_name.c_str())) {
1160 ckmc_alias_list_all_free(alias_list);
1163 LoggerD("Data name found: %d", data_found);
1165 common::tools::ReportSuccess(out);
1167 common::tools::ReportError(
1168 PlatformResult(ErrorCode::NOT_FOUND_ERR, "Data name not found."), &out);
1172 } // namespace keymanager
1173 } // namespace extension