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 if (CKMC_ERROR_NONE == ret) {
188 picojson::value result{picojson::array{}};
189 auto& aliases = result.get<picojson::array>();
190 ckmc_alias_list_s* head = alias_list;
193 aliases.push_back(picojson::value(head->alias ? head->alias : ""));
198 ckmc_alias_list_all_free(alias_list);
201 common::tools::ReportSuccess(result, *out);
203 LoggerE("Failed to get alias list: %d", ret);
204 common::tools::ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get alias list"), out);
209 KeyManagerInstance::KeyManagerInstance() {
211 using std::placeholders::_1;
212 using std::placeholders::_2;
214 RegisterSyncHandler("KeyManager_getKeyAliasList",
215 std::bind(&KeyManagerInstance::GetKeyAliasList, this, _1, _2));
216 RegisterSyncHandler("KeyManager_getCertificatesAliasList",
217 std::bind(&KeyManagerInstance::GetCertificateAliasList, this, _1, _2));
218 RegisterSyncHandler("KeyManager_getDataAliasList",
219 std::bind(&KeyManagerInstance::GetDataAliasList, this, _1, _2));
220 RegisterSyncHandler("KeyManager_getKey",
221 std::bind(&KeyManagerInstance::GetKey, this, _1, _2));
222 RegisterSyncHandler("KeyManager_saveKey",
223 std::bind(&KeyManagerInstance::SaveKey, this, _1, _2));
224 RegisterSyncHandler("KeyManager_removeAlias",
225 std::bind(&KeyManagerInstance::RemoveAlias, this, _1, _2));
226 RegisterSyncHandler("KeyManager_generateKeyPair",
227 std::bind(&KeyManagerInstance::GenerateKeyPair, this, _1, _2));
228 RegisterSyncHandler("KeyManager_getCertificate",
229 std::bind(&KeyManagerInstance::GetCertificate, this, _1, _2));
230 RegisterSyncHandler("KeyManager_saveCertificate",
231 std::bind(&KeyManagerInstance::SaveCertificate, this, _1, _2));
232 RegisterSyncHandler("KeyManager_loadCertificateFromFile",
233 std::bind(&KeyManagerInstance::LoadCertificateFromFile, this, _1, _2));
234 RegisterSyncHandler("KeyManager_saveData",
235 std::bind(&KeyManagerInstance::SaveData, this, _1, _2));
236 RegisterSyncHandler("KeyManager_getData",
237 std::bind(&KeyManagerInstance::GetData, this, _1, _2));
238 RegisterSyncHandler("KeyManager_createSignature",
239 std::bind(&KeyManagerInstance::CreateSignature, this, _1, _2));
240 RegisterSyncHandler("KeyManager_verifySignature",
241 std::bind(&KeyManagerInstance::VerifySignature, this, _1, _2));
242 RegisterSyncHandler("KeyManager_loadFromPKCS12File",
243 std::bind(&KeyManagerInstance::LoadFromPKCS12File, this, _1, _2));
244 RegisterSyncHandler("KeyManager_allowAccessControl",
245 std::bind(&KeyManagerInstance::AllowAccessControl, this, _1, _2));
246 RegisterSyncHandler("KeyManager_denyAccessControl",
247 std::bind(&KeyManagerInstance::DenyAccessControl, this, _1, _2));
248 RegisterSyncHandler("KeyManager_isDataNameFound",
249 std::bind(&KeyManagerInstance::IsDataNameFound, this, _1, _2));
252 KeyManagerInstance::~KeyManagerInstance() {
256 void KeyManagerInstance::GetKeyAliasList(const picojson::value& args,
257 picojson::object& out) {
259 GetGenericAliasList(ckmc_get_key_alias_list, &out);
262 void KeyManagerInstance::GetCertificateAliasList(const picojson::value& args,
263 picojson::object& out) {
265 GetGenericAliasList(ckmc_get_cert_alias_list, &out);
268 void KeyManagerInstance::GetDataAliasList(const picojson::value& args,
269 picojson::object& out) {
271 GetGenericAliasList(ckmc_get_data_alias_list, &out);
274 void KeyManagerInstance::GetKey(const picojson::value& args,
275 picojson::object& out) {
277 const auto& key_alias = args.get("name").get<std::string>();
278 const auto& password_value = args.get("password");
280 std::string password;
282 if (password_value.is<std::string>()) {
283 password = password_value.get<std::string>();
286 ckmc_key_s* key = nullptr;
287 int ret = ckmc_get_key(key_alias.c_str(), password.c_str(), &key);
289 if (CKMC_ERROR_NONE == ret) {
290 picojson::object result;
292 result["name"] = picojson::value(key_alias);
293 result["password"] = picojson::value(key->password);
294 // if key was retrieved it is extractable from DB
295 result["extractable"] = picojson::value(true);
296 result["keyType"] = picojson::value(KeyTypeToString(key->key_type));
297 result["rawKey"] = picojson::value(RawBufferToBase64(ToRawBuffer(key)));
300 ReportSuccess(picojson::value{result}, out);
302 LoggerE("Failed to get key: %d", ret);
304 PlatformResult error(ErrorCode::UNKNOWN_ERR, "Failed to get key");
307 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
308 error = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to find key");
311 case CKMC_ERROR_INVALID_PARAMETER:
312 error = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Input parameter is invalid");
316 ReportError(error, &out);
320 void KeyManagerInstance::SaveKey(const picojson::value& args,
321 picojson::object& out) {
324 const picojson::value& key_obj = args.get("key");
325 const std::string& alias = key_obj.get("name").get<std::string>();
326 const std::string& type = key_obj.get("keyType").get<std::string>();
327 bool extractable = key_obj.get("extractable").get<bool>();
328 const double callback_id = args.get("callbackId").get<double>();
331 if (args.get("rawKey").is<std::string>()) {
332 base64 = args.get("rawKey").get<std::string>();
336 if (key_obj.get("password").is<std::string>()) {
337 pass = key_obj.get("password").get<std::string>();
340 RawBuffer* raw_buffer = new RawBuffer(std::move(Base64ToRawBuffer(base64)));
341 ckmc_key_type_e key_type = StringToKeyType(type);
343 auto save = [alias, pass, key_type, extractable, raw_buffer]
344 (const std::shared_ptr<picojson::value>& response) -> void {
346 ckmc_policy_s policy { const_cast<char*>(pass.c_str()), extractable };
347 ckmc_key_s key { const_cast<unsigned char*>(&(*raw_buffer)[0]),
348 raw_buffer->size(), key_type, const_cast<char*>(pass.c_str()) };
350 int ret = ckmc_save_key(alias.c_str(), key, policy);
351 if (CKMC_ERROR_NONE != ret) {
352 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
353 if (CKMC_ERROR_INVALID_PARAMETER == ret) {
354 result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
356 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save key.");
358 common::tools::ReportError(result, &response->get<picojson::object>());
360 common::tools::ReportSuccess(response->get<picojson::object>());
366 auto save_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
367 picojson::object& obj = response->get<picojson::object>();
368 obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
369 this->PostMessage(response->serialize().c_str());
372 TaskQueue::GetInstance().Queue<picojson::value>(
375 std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
378 void KeyManagerInstance::RemoveAlias(const picojson::value& args,
379 picojson::object& out) {
382 const std::string& alias = args.get("alias").get<std::string>();
383 int ret = ckmc_remove_alias(alias.c_str());
385 if (CKMC_ERROR_NONE != ret) {
386 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
388 case CKMC_ERROR_INVALID_PARAMETER:
389 result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed");
391 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
392 result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
395 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to remove alias");
397 ReportError(result, &out);
403 void KeyManagerInstance::GenerateKeyPair(const picojson::value& args,
404 picojson::object& out) {
407 const picojson::value& priv_key = args.get("privKeyName");
408 const picojson::value& pub_key = args.get("pubKeyName");
409 const std::string& priv_name = priv_key.get("name").get<std::string>();
410 const std::string& pub_name = pub_key.get("name").get<std::string>();
411 const std::string& type = args.get("type").get<std::string>();
412 const int size = std::stoi(args.get("size").get<std::string>());
413 const double callback_id = args.get("callbackId").get<double>();
415 std::string priv_pass;
416 if (priv_key.get("password").is<std::string>()) {
417 priv_pass = priv_key.get("password").get<std::string>();
419 bool extractable = priv_key.get("extractable").get<bool>();
420 ckmc_policy_s priv_policy { const_cast<char*>(priv_pass.c_str()), extractable };
422 std::string pub_pass;
423 if (pub_key.get("password").is<std::string>()) {
424 pub_pass = pub_key.get("password").get<std::string>();
426 extractable = pub_key.get("extractable").get<bool>();
427 ckmc_policy_s pub_policy { const_cast<char*>(pub_pass.c_str()), extractable };
429 std::string elliptic;
430 if (args.get("ellipticCurveType").is<std::string>()) {
431 elliptic = args.get("ellipticCurveType").get<std::string>();
434 auto generate = [size, priv_policy, pub_policy, priv_name, pub_name, type, elliptic]
435 (const std::shared_ptr<picojson::value>& response) -> void {
436 int ret = CKMC_ERROR_NONE;
437 if (kTypeRSA == type) {
438 ret = ckmc_create_key_pair_rsa(size, priv_name.c_str(),
439 pub_name.c_str(), priv_policy, pub_policy);
440 } else if (kTypeECDSA == type) {
441 ret = ckmc_create_key_pair_ecdsa(GetEllipticCurveType(elliptic), priv_name.c_str(),
442 pub_name.c_str(), priv_policy, pub_policy);
444 ret = ckmc_create_key_pair_dsa(size, priv_name.c_str(),
445 pub_name.c_str(), priv_policy, pub_policy);
448 if (CKMC_ERROR_NONE != ret) {
449 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
450 if (CKMC_ERROR_INVALID_PARAMETER == ret) {
451 result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value passed.");
453 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create key pair.");
455 common::tools::ReportError(result, &response->get<picojson::object>());
457 common::tools::ReportSuccess(response->get<picojson::object>());
461 auto generate_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
462 picojson::object& obj = response->get<picojson::object>();
463 obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
464 this->PostMessage(response->serialize().c_str());
467 TaskQueue::GetInstance().Queue<picojson::value>(
470 std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
473 void KeyManagerInstance::GetCertificate(const picojson::value& args,
474 picojson::object& out) {
477 const std::string& alias = args.get("name").get<std::string>();
480 if (args.get("password").is<std::string>()) {
481 pass = args.get("password").get<std::string>();
484 ckmc_cert_s* cert = nullptr;
485 int ret = ckmc_get_cert(alias.c_str(), pass.c_str(), &cert);
487 if (CKMC_ERROR_NONE != ret) {
488 LoggerE("Failed to get certificate: %d", ret);
489 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
491 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
492 result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Certificate alias not found");
494 case CKMC_ERROR_INVALID_PARAMETER:
495 result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed");
498 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificate");
501 ReportError(result, &out);
503 picojson::value result = picojson::value(picojson::object());
504 picojson::object& obj = result.get<picojson::object>();
506 //if cert was retrieved it is extractable from db
507 obj["extractable"] = picojson::value(true);
508 obj["name"] = picojson::value(alias);
510 obj["password"] = picojson::value(pass);
513 RawBuffer raw_cert (cert->raw_cert, cert->raw_cert + cert->cert_size);
514 obj["rawCert"] = picojson::value(RawBufferToBase64(raw_cert));
516 ReportSuccess(result, out);
520 void KeyManagerInstance::SaveCertificate(const picojson::value& args,
521 picojson::object& out) {
524 RawBuffer* raw_buffer = new RawBuffer(std::move(Base64ToRawBuffer(args.get("rawCert").get<std::string>())));
525 const auto& certificate = args.get("certificate");
526 const auto& alias = certificate.get("name").get<std::string>();
527 const auto& password_value = certificate.get("password");
528 const auto extractable = certificate.get("extractable").get<bool>();
529 double callback_id = args.get("callbackId").get<double>();
531 std::string password;
533 if (password_value.is<std::string>()) {
534 password = password_value.get<std::string>();
537 auto save_certificate = [raw_buffer, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
538 LoggerD("Enter save_certificate");
540 ckmc_cert_s certificate { const_cast<unsigned char*>(&(*raw_buffer)[0]), raw_buffer->size(), CKMC_FORM_DER };
541 ckmc_policy_s policy { const_cast<char*>(password.c_str()), extractable };
543 int ret = ckmc_save_cert(alias.c_str(), certificate, policy);
545 PlatformResult success(ErrorCode::NO_ERROR);
548 case CKMC_ERROR_NONE:
551 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
552 success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
555 case CKMC_ERROR_INVALID_PARAMETER:
556 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to save certificate");
560 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save certificate");
565 common::tools::ReportSuccess(result->get<picojson::object>());
567 LoggerE("Failed to save certificate: %d", ret);
568 common::tools::ReportError(success, &result->get<picojson::object>());
574 auto save_certificate_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
575 LoggerD("Enter save_certificate_result");
576 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
577 this->PostMessage(result->serialize().c_str());
580 TaskQueue::GetInstance().Queue<picojson::value>(
582 save_certificate_result,
583 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
588 void KeyManagerInstance::LoadCertificateFromFile(const picojson::value& args,
589 picojson::object& out) {
592 const auto& file_uri = args.get("fileURI").get<std::string>();
593 const auto& certificate = args.get("certificate");
594 const auto& alias = certificate.get("name").get<std::string>();
595 const auto& password_value = args.get("password");
596 const auto extractable = certificate.get("extractable").get<bool>();
597 double callback_id = args.get("callbackId").get<double>();
599 std::string password;
601 if (password_value.is<std::string>()) {
602 password = password_value.get<std::string>();
605 auto load_certificate = [file_uri, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
606 LoggerD("Enter load_certificate");
608 std::string file = VirtualFs::GetInstance().GetRealPath(file_uri);
609 ckmc_cert_s* certificate = nullptr;
610 int ret = ckmc_load_cert_from_file(file.c_str(), &certificate);
611 std::string certificate_data;
613 if (CKMC_ERROR_NONE == ret) {
614 ckmc_policy_s policy { const_cast<char*>(password.c_str()), extractable };
615 ret = ckmc_save_cert(alias.c_str(), *certificate, policy);
616 if (CKMC_ERROR_NONE != ret) {
617 LoggerE("Failed to save certificate: %d", ret);
619 certificate_data = RawBufferToBase64(ToRawBuffer(certificate));
620 ckmc_cert_free(certificate);
622 LoggerE("Failed to load certificate: %d", ret);
625 PlatformResult success(ErrorCode::NO_ERROR);
628 case CKMC_ERROR_NONE:
631 case CKMC_ERROR_FILE_ACCESS_DENIED:
632 success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "File not found");
635 case CKMC_ERROR_INVALID_PARAMETER:
636 case CKMC_ERROR_INVALID_FORMAT:
637 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to load certificate");
641 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to load certificate");
646 common::tools::ReportSuccess(picojson::value(certificate_data), result->get<picojson::object>());
648 common::tools::ReportError(success, &result->get<picojson::object>());
652 auto load_certificate_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
653 LoggerD("Enter load_certificate_result");
654 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
655 this->PostMessage(result->serialize().c_str());
658 TaskQueue::GetInstance().Queue<picojson::value>(
660 load_certificate_result,
661 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
666 void KeyManagerInstance::SaveData(const picojson::value& args,
667 picojson::object& out) {
670 RawBuffer* raw_buffer = new RawBuffer(std::move(Base64ToRawBuffer(args.get("rawData").get<std::string>())));
671 const auto& data = args.get("data");
672 const auto& alias = data.get("name").get<std::string>();
673 const auto& password_value = data.get("password");
674 const auto extractable = data.get("extractable").get<bool>();
675 double callback_id = args.get("callbackId").get<double>();
677 std::string password;
679 if (password_value.is<std::string>()) {
680 password = password_value.get<std::string>();
683 auto save_data = [raw_buffer, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
684 LoggerD("Enter save_data");
686 ckmc_raw_buffer_s raw_data { const_cast<unsigned char*>(&(*raw_buffer)[0]), raw_buffer->size() };
687 ckmc_policy_s policy { const_cast<char*>(password.c_str()), extractable };
689 int ret = ckmc_save_data(alias.c_str(), raw_data, policy);
691 PlatformResult success(ErrorCode::NO_ERROR);
694 case CKMC_ERROR_NONE:
697 case CKMC_ERROR_INVALID_PARAMETER:
698 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to save data");
702 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save data");
707 common::tools::ReportSuccess(result->get<picojson::object>());
709 LoggerE("Failed to save data: %d", ret);
710 common::tools::ReportError(success, &result->get<picojson::object>());
716 auto save_data_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
717 LoggerD("Enter save_data_result");
718 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
719 this->PostMessage(result->serialize().c_str());
722 TaskQueue::GetInstance().Queue<picojson::value>(
725 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
730 void KeyManagerInstance::GetData(const picojson::value& args,
731 picojson::object& out) {
734 const auto& data_alias = args.get("name").get<std::string>();
735 const auto& password_value = args.get("password");
737 std::string password;
739 if (password_value.is<std::string>()) {
740 password = password_value.get<std::string>();
743 ckmc_raw_buffer_s* data = nullptr;
744 int ret = ckmc_get_data(data_alias.c_str(), password.c_str(), &data);
746 if (CKMC_ERROR_NONE == ret) {
747 picojson::object result;
749 result["name"] = picojson::value(data_alias);
750 result["password"] = picojson::value(password);
751 // if key was retrieved it is extractable from DB
752 result["extractable"] = picojson::value(true);
753 result["rawData"] = picojson::value(RawBufferToBase64(ToRawBuffer(data)));
755 ckmc_buffer_free(data);
756 ReportSuccess(picojson::value{result}, out);
758 LoggerE("Failed to get data: %d", ret);
760 PlatformResult error(ErrorCode::UNKNOWN_ERR, "Failed to get key");
763 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
764 error = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to find key");
767 case CKMC_ERROR_INVALID_PARAMETER:
768 error = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Input parameter is invalid");
772 ReportError(error, &out);
776 void KeyManagerInstance::CreateSignature(const picojson::value& args,
777 picojson::object& out) {
780 const auto& alias = args.get("privKeyAlias").get<std::string>();
781 RawBuffer* raw_buffer = new RawBuffer(std::move(Base64ToRawBuffer(args.get("message").get<std::string>())));
782 const auto& password_value = args.get("password");
783 double callback_id = args.get("callbackId").get<double>();
784 ckmc_hash_algo_e hash = StringToHashAlgorithm(args.get("hashAlgorithmType").get<std::string>());
785 ckmc_rsa_padding_algo_e padding = StringToRsaPadding(args.get("padding").get<std::string>());
787 std::string password;
789 if (password_value.is<std::string>()) {
790 password = password_value.get<std::string>();
793 auto create_certificate = [alias, raw_buffer, password, hash, padding](const std::shared_ptr<picojson::value>& result) {
794 LoggerD("Enter create_certificate");
796 ckmc_raw_buffer_s* signature = nullptr;
797 ckmc_raw_buffer_s message = { const_cast<unsigned char*>(&(*raw_buffer)[0]), raw_buffer->size() };
798 int ret = ckmc_create_signature(alias.c_str(), password.c_str(), message, hash, padding, &signature);
800 PlatformResult success(ErrorCode::NO_ERROR);
803 case CKMC_ERROR_NONE:
806 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
807 success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
810 case CKMC_ERROR_INVALID_PARAMETER:
811 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to create signature");
815 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create signature");
820 common::tools::ReportSuccess(picojson::value(RawBufferToBase64(ToRawBuffer(signature))), result->get<picojson::object>());
821 ckmc_buffer_free(signature);
823 LoggerE("Failed to create signature: %d", ret);
824 common::tools::ReportError(success, &result->get<picojson::object>());
830 auto create_certificate_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
831 LoggerD("Enter create_certificate_result");
832 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
833 this->PostMessage(result->serialize().c_str());
836 TaskQueue::GetInstance().Queue<picojson::value>(
838 create_certificate_result,
839 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
844 void KeyManagerInstance::VerifySignature(const picojson::value& args,
845 picojson::object& out) {
848 const auto& alias = args.get("pubKeyAlias").get<std::string>();
849 RawBuffer* message = new RawBuffer(std::move(Base64ToRawBuffer(args.get("message").get<std::string>())));
850 RawBuffer* signature = new RawBuffer(std::move(Base64ToRawBuffer(args.get("signature").get<std::string>())));
851 const auto& password_value = args.get("password");
852 double callback_id = args.get("callbackId").get<double>();
853 ckmc_hash_algo_e hash = StringToHashAlgorithm(args.get("hashAlgorithmType").get<std::string>());
854 ckmc_rsa_padding_algo_e padding = StringToRsaPadding(args.get("padding").get<std::string>());
856 std::string password;
858 if (password_value.is<std::string>()) {
859 password = password_value.get<std::string>();
862 auto verify_certificate = [alias, message, signature, password, hash, padding](const std::shared_ptr<picojson::value>& result) {
863 LoggerD("Enter verify_certificate");
865 ckmc_raw_buffer_s message_buf = { const_cast<unsigned char*>(&(*message)[0]), message->size() };
866 ckmc_raw_buffer_s signature_buf = { const_cast<unsigned char*>(&(*signature)[0]), signature->size() };
868 int ret = ckmc_verify_signature(alias.c_str(), password.c_str(), message_buf, signature_buf, hash , padding);
870 PlatformResult success(ErrorCode::NO_ERROR);
873 case CKMC_ERROR_NONE:
876 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
877 success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
880 case CKMC_ERROR_INVALID_PARAMETER:
881 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to verify signature");
885 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to verify signature");
890 common::tools::ReportSuccess(result->get<picojson::object>());
892 LoggerE("Failed to verify signature: %d", ret);
893 common::tools::ReportError(success, &result->get<picojson::object>());
900 auto verify_certificate_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
901 LoggerD("Enter verify_certificate_result");
902 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
903 this->PostMessage(result->serialize().c_str());
906 TaskQueue::GetInstance().Queue<picojson::value>(
908 verify_certificate_result,
909 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
914 void KeyManagerInstance::LoadFromPKCS12File(const picojson::value& args,
915 picojson::object& out) {
918 const auto& file_uri = args.get("fileURI").get<std::string>();
919 const auto& key_alias = args.get("privKeyName").get<std::string>();
920 const auto& cert_alias = args.get("certificateName").get<std::string>();
921 const auto& password_value = args.get("password");
922 double callback_id = args.get("callbackId").get<double>();
924 std::string password;
926 if (password_value.is<std::string>()) {
927 password = password_value.get<std::string>();
930 auto load_file = [file_uri, password, cert_alias, key_alias](const std::shared_ptr<picojson::value>& result) {
931 LoggerD("Enter load_file");
932 std::string file = VirtualFs::GetInstance().GetRealPath(file_uri);
933 ckmc_pkcs12_s* pkcs12 = nullptr;
935 int ret = ckmc_pkcs12_load(file.c_str(), password.c_str(), &pkcs12);
937 if (CKMC_ERROR_NONE == ret) {
939 ckmc_pkcs12_free(pkcs12);
941 ckmc_policy_s policy { const_cast<char*>(password.c_str()), true };
943 // it's safer to use ckmc_save_pkcs12() here, however JS API specifies
944 // two different aliases for private key and certificate
946 ret = ckmc_save_cert(cert_alias.c_str(), *pkcs12->cert, policy);
947 if (CKMC_ERROR_NONE != ret) {
948 LoggerE("Failed to save certificate: %d", ret);
952 if (CKMC_ERROR_NONE == ret && pkcs12->priv_key) {
953 ret = ckmc_save_key(key_alias.c_str(), *pkcs12->priv_key, policy);
954 if (CKMC_ERROR_NONE != ret) {
955 LoggerE("Failed to save private key: %d", ret);
958 ckmc_remove_cert(cert_alias.c_str());
963 LoggerE("Failed to load PKCS12 file: %d", ret);
966 PlatformResult success(ErrorCode::NO_ERROR);
969 case CKMC_ERROR_NONE:
972 case CKMC_ERROR_FILE_ACCESS_DENIED:
973 success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Certificate file not found");
976 case CKMC_ERROR_INVALID_FORMAT:
977 case CKMC_ERROR_INVALID_PARAMETER:
978 success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Certificate file has wrong format");
981 case CKMC_ERROR_PERMISSION_DENIED:
982 success = PlatformResult(ErrorCode::IO_ERR, "Permission has been denied");
986 success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to open certificate file");
991 common::tools::ReportSuccess(result->get<picojson::object>());
993 common::tools::ReportError(success, &result->get<picojson::object>());
997 auto load_file_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
998 LoggerD("Enter load_file_result");
999 result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
1000 this->PostMessage(result->serialize().c_str());
1003 TaskQueue::GetInstance().Queue<picojson::value>(
1006 std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
1011 void KeyManagerInstance::AllowAccessControl(const picojson::value& args,
1012 picojson::object& out) {
1015 const std::string& data_name = args.get("dataName").get<std::string>();
1016 const std::string& id = args.get("id").get<std::string>();
1017 const double callback_id = args.get("callbackId").get<double>();
1018 const std::string& access = args.get("accessControlType").get<std::string>();
1019 ckmc_access_right_e granted = CKMC_AR_READ;
1020 if ("READ_REMOVE" == access) {
1021 granted = CKMC_AR_READ_REMOVE;
1024 auto allow = [data_name, id, granted](const std::shared_ptr<picojson::value>& response) -> void {
1025 //as ckmc_allow_access does not check if package id exists
1026 //it has to be done before allowing access
1027 pkgmgrinfo_pkginfo_h handle = nullptr;
1028 int ret = pkgmgrinfo_pkginfo_get_pkginfo(id.c_str(), &handle);
1029 if (PMINFO_R_OK != ret) {
1030 LoggerE("Package id not found.");
1031 common::tools::ReportError(PlatformResult(
1032 ErrorCode::NOT_FOUND_ERR, "Package id not found."), &response->get<picojson::object>());
1035 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1037 ret = ckmc_allow_access(data_name.c_str(), id.c_str(), granted);
1038 if (CKMC_ERROR_NONE != ret) {
1039 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1040 if (CKMC_ERROR_DB_ALIAS_UNKNOWN == ret) {
1041 result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found.");
1043 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to allow access.");
1045 common::tools::ReportError(result, &response->get<picojson::object>());
1047 common::tools::ReportSuccess(response->get<picojson::object>());
1051 auto allow_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1052 picojson::object& obj = response->get<picojson::object>();
1053 obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
1054 this->PostMessage(response->serialize().c_str());
1057 TaskQueue::GetInstance().Queue<picojson::value>(
1060 std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
1063 void KeyManagerInstance::DenyAccessControl(const picojson::value& args,
1064 picojson::object& out) {
1067 const std::string& data_name = args.get("dataName").get<std::string>();
1068 const std::string& id = args.get("id").get<std::string>();
1069 const double callback_id = args.get("callbackId").get<double>();
1071 auto deny = [data_name, id](const std::shared_ptr<picojson::value>& response) -> void {
1072 int ret = ckmc_deny_access(data_name.c_str(), id.c_str());
1073 if (CKMC_ERROR_NONE != ret) {
1074 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1075 if (CKMC_ERROR_DB_ALIAS_UNKNOWN == ret) {
1076 result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found.");
1078 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to deny access.");
1080 common::tools::ReportError(result, &response->get<picojson::object>());
1082 common::tools::ReportSuccess(response->get<picojson::object>());
1086 auto deny_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1087 picojson::object& obj = response->get<picojson::object>();
1088 obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
1089 this->PostMessage(response->serialize().c_str());
1092 TaskQueue::GetInstance().Queue<picojson::value>(
1095 std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
1098 void KeyManagerInstance::IsDataNameFound(const picojson::value& args,
1099 picojson::object& out){
1102 const std::string& data_name = args.get("dataName").get<std::string>();
1103 bool data_found = false;
1104 ckmc_alias_list_s* alias_list = nullptr;
1106 int ret = ckmc_get_data_alias_list(&alias_list);
1107 if (CKMC_ERROR_NONE != ret) {
1108 LoggerE("Failed to get data list [%d]", ret);
1109 PlatformResult result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get data list.");
1110 if (CKMC_ERROR_DB_ALIAS_UNKNOWN == ret) {
1111 result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Data name not found.");
1114 common::tools::ReportError(result, &out);
1118 ckmc_alias_list_s* head = alias_list;
1120 if (!strcmp(head->alias, data_name.c_str())) {
1128 ckmc_alias_list_all_free(alias_list);
1131 LoggerD("Data name found: %d", data_found);
1133 common::tools::ReportSuccess(out);
1135 common::tools::ReportError(
1136 PlatformResult(ErrorCode::NOT_FOUND_ERR, "Data name not found."), &out);
1140 } // namespace keymanager
1141 } // namespace extension