[KeyManger] Update certificate after calls to save() and loadFromFile().
[platform/core/api/webapi-plugins.git] / src / keymanager / keymanager_instance.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "keymanager/keymanager_instance.h"
18
19 #include <ckmc/ckmc-manager.h>
20 #include <glib.h>
21 #include <pkgmgr-info.h>
22
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"
30
31 namespace extension {
32 namespace keymanager {
33
34 using common::ErrorCode;
35 using common::optional;
36 using common::PlatformResult;
37 using common::TaskQueue;
38 using common::VirtualFs;
39
40 namespace {
41
42 typedef std::vector<unsigned char> RawBuffer;
43
44 const char* kTypeRSA = "RSA";
45 const char* kTypeECDSA = "ECDSA";
46
47 RawBuffer Base64ToRawBuffer(const std::string& base64) {
48   LoggerD("Enter");
49
50   gsize len = 0;
51   guchar* raw_data = g_base64_decode(base64.c_str(), &len);
52   RawBuffer raw_buffer;
53
54   if (raw_data) {
55     raw_buffer.assign(raw_data, raw_data + len);
56     g_free(raw_data);
57   }
58
59   return raw_buffer;
60 }
61
62 std::string RawBufferToBase64(const RawBuffer& buf) {
63   LoggerD("Enter");
64
65   std::string result;
66
67   if (!buf.empty()) {
68     gchar* base64 = g_base64_encode(&buf[0], buf.size());
69     result = base64;
70     g_free(base64);
71   }
72
73   return result;
74 }
75
76 ckmc_ec_type_e GetEllipticCurveType(const std::string& type) {
77   LoggerD("Enter");
78
79   if ("EC_PRIME256V1" == type) {
80     return CKMC_EC_PRIME256V1;
81   } else if ("EC_SECP384R1" == type) {
82     return CKMC_EC_SECP384R1;
83   } else {
84     return CKMC_EC_PRIME192V1;
85   }
86 }
87
88 ckmc_key_type_e StringToKeyType(const std::string& type) {
89   LoggerD("Enter");
90
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) {
104     return CKMC_KEY_AES;
105   } else {
106     return CKMC_KEY_NONE;
107   }
108 }
109
110 std::string KeyTypeToString(ckmc_key_type_e type) {
111   LoggerD("Enter");
112
113   switch (type) {
114     case CKMC_KEY_NONE:
115       return "KEY_NONE";
116
117     case CKMC_KEY_RSA_PUBLIC:
118       return "KEY_RSA_PUBLIC";
119
120     case CKMC_KEY_RSA_PRIVATE:
121       return "KEY_RSA_PRIVATE";
122
123     case CKMC_KEY_ECDSA_PUBLIC:
124       return "KEY_ECDSA_PUBLIC";
125
126     case CKMC_KEY_ECDSA_PRIVATE:
127       return "KEY_ECDSA_PRIVATE";
128
129     case CKMC_KEY_DSA_PUBLIC:
130       return "KEY_DSA_PUBLIC";
131
132     case CKMC_KEY_DSA_PRIVATE:
133       return "KEY_DSA_PRIVATE";
134
135     case CKMC_KEY_AES:
136       return "KEY_AES";
137   }
138
139   LoggerE("Unknown key type");
140   return "KEY_UNKNOWN";
141 }
142
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;
152   }
153
154   return CKMC_HASH_NONE;
155 }
156
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;
162   }
163
164   return CKMC_NONE_PADDING;
165 }
166
167 RawBuffer ToRawBuffer(const ckmc_key_s* key) {
168   return RawBuffer(key->raw_key, key->raw_key + key->key_size);
169 }//
170
171 RawBuffer ToRawBuffer(const ckmc_raw_buffer_s* buffer) {
172   return RawBuffer(buffer->data, buffer->data + buffer->size);
173 }
174
175 RawBuffer ToRawBuffer(const ckmc_cert_s* cert) {
176   return RawBuffer(cert->raw_cert, cert->raw_cert + cert->cert_size);
177 }
178
179 typedef int (*AliasListFunction)(ckmc_alias_list_s**);
180
181 void GetGenericAliasList(AliasListFunction func, picojson::object* out) {
182   LoggerD("Enter");
183
184   ckmc_alias_list_s* alias_list = nullptr;
185   int ret = func(&alias_list);
186
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;
191
192     while (head) {
193       aliases.push_back(picojson::value(head->alias ? head->alias : ""));
194       head = head->next;
195     }
196
197     if (alias_list) {
198       ckmc_alias_list_all_free(alias_list);
199     }
200
201     common::tools::ReportSuccess(result, *out);
202   } else {
203     LoggerE("Failed to get alias list: %d", ret);
204     common::tools::ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get alias list"), out);
205   }
206 }
207 }  // namespace
208
209 KeyManagerInstance::KeyManagerInstance() {
210   LoggerD("Enter");
211   using std::placeholders::_1;
212   using std::placeholders::_2;
213
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));
250 }
251
252 KeyManagerInstance::~KeyManagerInstance() {
253   LoggerD("Enter");
254 }
255
256 void KeyManagerInstance::GetKeyAliasList(const picojson::value& args,
257                                          picojson::object& out) {
258   LoggerD("Enter");
259   GetGenericAliasList(ckmc_get_key_alias_list, &out);
260 }
261
262 void KeyManagerInstance::GetCertificateAliasList(const picojson::value& args,
263                                                  picojson::object& out) {
264   LoggerD("Enter");
265   GetGenericAliasList(ckmc_get_cert_alias_list, &out);
266 }
267
268 void KeyManagerInstance::GetDataAliasList(const picojson::value& args,
269                                           picojson::object& out) {
270   LoggerD("Enter");
271   GetGenericAliasList(ckmc_get_data_alias_list, &out);
272 }
273
274 void KeyManagerInstance::GetKey(const picojson::value& args,
275                                 picojson::object& out) {
276   LoggerD("Enter");
277   const auto& key_alias = args.get("name").get<std::string>();
278   const auto& password_value = args.get("password");
279
280   std::string password;
281
282   if (password_value.is<std::string>()) {
283     password = password_value.get<std::string>();
284   }
285
286   ckmc_key_s* key = nullptr;
287   int ret = ckmc_get_key(key_alias.c_str(), password.c_str(), &key);
288
289   if (CKMC_ERROR_NONE == ret) {
290     picojson::object result;
291
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)));
298
299     ckmc_key_free(key);
300     ReportSuccess(picojson::value{result}, out);
301   } else {
302     LoggerE("Failed to get key: %d", ret);
303
304     PlatformResult error(ErrorCode::UNKNOWN_ERR, "Failed to get key");
305
306     switch (ret) {
307       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
308         error = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to find key");
309         break;
310
311       case CKMC_ERROR_INVALID_PARAMETER:
312         error = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Input parameter is invalid");
313         break;
314     }
315
316     ReportError(error, &out);
317   }
318 }
319
320 void KeyManagerInstance::SaveKey(const picojson::value& args,
321                                  picojson::object& out) {
322   LoggerD("Enter");
323
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>();
329
330   std::string base64;
331   if (args.get("rawKey").is<std::string>()) {
332     base64 = args.get("rawKey").get<std::string>();
333   }
334
335   std::string pass;
336   if (key_obj.get("password").is<std::string>()) {
337     pass = key_obj.get("password").get<std::string>();
338   }
339
340   RawBuffer* raw_buffer = new RawBuffer(std::move(Base64ToRawBuffer(base64)));
341   ckmc_key_type_e key_type = StringToKeyType(type);
342
343   auto save = [alias, pass, key_type, extractable, raw_buffer]
344                (const std::shared_ptr<picojson::value>& response) -> void {
345
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()) };
349
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.");
355       } else {
356         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save key.");
357       }
358       common::tools::ReportError(result, &response->get<picojson::object>());
359     } else {
360       common::tools::ReportSuccess(response->get<picojson::object>());
361     }
362
363     delete raw_buffer;
364   };
365
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());
370   };
371
372   TaskQueue::GetInstance().Queue<picojson::value>(
373       save,
374       save_response,
375       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
376 }
377
378 void KeyManagerInstance::RemoveAlias(const picojson::value& args,
379                                    picojson::object& out) {
380   LoggerD("Enter");
381
382   const std::string& alias = args.get("alias").get<std::string>();
383   int ret = ckmc_remove_alias(alias.c_str());
384
385   if (CKMC_ERROR_NONE != ret) {
386     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
387     switch(ret) {
388       case CKMC_ERROR_INVALID_PARAMETER:
389         result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed");
390         break;
391       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
392         result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
393         break;
394       default:
395         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to remove alias");
396     }
397     ReportError(result, &out);
398   } else {
399     ReportSuccess(out);
400   }
401 }
402
403 void KeyManagerInstance::GenerateKeyPair(const picojson::value& args,
404                                          picojson::object& out) {
405   LoggerD("Enter");
406
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>();
414
415   std::string priv_pass;
416   if (priv_key.get("password").is<std::string>()) {
417     priv_pass = priv_key.get("password").get<std::string>();
418   }
419   bool extractable = priv_key.get("extractable").get<bool>();
420   ckmc_policy_s priv_policy { const_cast<char*>(priv_pass.c_str()), extractable };
421
422   std::string pub_pass;
423   if (pub_key.get("password").is<std::string>()) {
424     pub_pass = pub_key.get("password").get<std::string>();
425   }
426   extractable = pub_key.get("extractable").get<bool>();
427   ckmc_policy_s pub_policy { const_cast<char*>(pub_pass.c_str()), extractable };
428
429   std::string elliptic;
430   if (args.get("ellipticCurveType").is<std::string>()) {
431     elliptic = args.get("ellipticCurveType").get<std::string>();
432   }
433
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);
443     } else {
444       ret = ckmc_create_key_pair_dsa(size, priv_name.c_str(),
445                                      pub_name.c_str(), priv_policy, pub_policy);
446     }
447
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.");
452       } else {
453         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create key pair.");
454       }
455       common::tools::ReportError(result, &response->get<picojson::object>());
456     } else {
457       common::tools::ReportSuccess(response->get<picojson::object>());
458     }
459   };
460
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());
465   };
466
467   TaskQueue::GetInstance().Queue<picojson::value>(
468       generate,
469       generate_response,
470       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
471 }
472
473 void KeyManagerInstance::GetCertificate(const picojson::value& args,
474                                         picojson::object& out) {
475   LoggerD("Enter");
476
477   const std::string& alias = args.get("name").get<std::string>();
478
479   std::string pass;
480   if (args.get("password").is<std::string>()) {
481     pass = args.get("password").get<std::string>();
482   }
483
484   ckmc_cert_s* cert = nullptr;
485   int ret = ckmc_get_cert(alias.c_str(), pass.c_str(), &cert);
486
487   if (CKMC_ERROR_NONE != ret) {
488     LoggerE("Failed to get certificate: %d", ret);
489     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
490     switch (ret) {
491       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
492         result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Certificate alias not found");
493         break;
494       case CKMC_ERROR_INVALID_PARAMETER:
495         result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed");
496         break;
497       default:
498         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificate");
499     }
500
501     ReportError(result, &out);
502   } else {
503     picojson::value result = picojson::value(picojson::object());
504     picojson::object& obj = result.get<picojson::object>();
505
506     //if cert was retrieved it is extractable from db
507     obj["extractable"] = picojson::value(true);
508     obj["name"] = picojson::value(alias);
509     if (!pass.empty()) {
510       obj["password"] = picojson::value(pass);
511     }
512
513     RawBuffer raw_cert (cert->raw_cert, cert->raw_cert + cert->cert_size);
514     obj["rawCert"] = picojson::value(RawBufferToBase64(raw_cert));
515
516     ReportSuccess(result, out);
517   }
518 }
519
520 void KeyManagerInstance::SaveCertificate(const picojson::value& args,
521                                          picojson::object& out) {
522   LoggerD("Enter");
523
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>();
530
531   std::string password;
532
533   if (password_value.is<std::string>()) {
534     password = password_value.get<std::string>();
535   }
536
537   auto save_certificate = [raw_buffer, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
538     LoggerD("Enter save_certificate");
539
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 };
542
543     int ret = ckmc_save_cert(alias.c_str(), certificate, policy);
544
545     PlatformResult success(ErrorCode::NO_ERROR);
546
547     switch (ret) {
548       case CKMC_ERROR_NONE:
549         break;
550
551       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
552         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
553         break;
554
555       case CKMC_ERROR_INVALID_PARAMETER:
556         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to save certificate");
557         break;
558
559       default:
560         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save certificate");
561         break;
562     }
563
564     if (success) {
565       common::tools::ReportSuccess(result->get<picojson::object>());
566     } else {
567       LoggerE("Failed to save certificate: %d", ret);
568       common::tools::ReportError(success, &result->get<picojson::object>());
569     }
570
571     delete raw_buffer;
572   };
573
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());
578   };
579
580   TaskQueue::GetInstance().Queue<picojson::value>(
581       save_certificate,
582       save_certificate_result,
583       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
584
585   ReportSuccess(out);
586 }
587
588 void KeyManagerInstance::LoadCertificateFromFile(const picojson::value& args,
589                                                  picojson::object& out) {
590   LoggerD("Enter");
591
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>();
598
599   std::string password;
600
601   if (password_value.is<std::string>()) {
602     password = password_value.get<std::string>();
603   }
604
605   auto load_certificate = [file_uri, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
606     LoggerD("Enter load_certificate");
607
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;
612
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);
618       }
619       certificate_data = RawBufferToBase64(ToRawBuffer(certificate));
620       ckmc_cert_free(certificate);
621     } else {
622       LoggerE("Failed to load certificate: %d", ret);
623     }
624
625     PlatformResult success(ErrorCode::NO_ERROR);
626
627     switch (ret) {
628       case CKMC_ERROR_NONE:
629         break;
630
631       case CKMC_ERROR_FILE_ACCESS_DENIED:
632         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "File not found");
633         break;
634
635       case CKMC_ERROR_INVALID_PARAMETER:
636       case CKMC_ERROR_INVALID_FORMAT:
637         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to load certificate");
638         break;
639
640       default:
641         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to load certificate");
642         break;
643     }
644
645     if (success) {
646       common::tools::ReportSuccess(picojson::value(certificate_data), result->get<picojson::object>());
647     } else {
648       common::tools::ReportError(success, &result->get<picojson::object>());
649     }
650   };
651
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());
656   };
657
658   TaskQueue::GetInstance().Queue<picojson::value>(
659       load_certificate,
660       load_certificate_result,
661       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
662
663   ReportSuccess(out);
664 }
665
666 void KeyManagerInstance::SaveData(const picojson::value& args,
667                                   picojson::object& out) {
668   LoggerD("Enter");
669
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>();
676
677   std::string password;
678
679   if (password_value.is<std::string>()) {
680     password = password_value.get<std::string>();
681   }
682
683   auto save_data = [raw_buffer, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
684     LoggerD("Enter save_data");
685
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 };
688
689     int ret = ckmc_save_data(alias.c_str(), raw_data, policy);
690
691     PlatformResult success(ErrorCode::NO_ERROR);
692
693     switch (ret) {
694       case CKMC_ERROR_NONE:
695         break;
696
697       case CKMC_ERROR_INVALID_PARAMETER:
698         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to save data");
699         break;
700
701       default:
702         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save data");
703         break;
704     }
705
706     if (success) {
707       common::tools::ReportSuccess(result->get<picojson::object>());
708     } else {
709       LoggerE("Failed to save data: %d", ret);
710       common::tools::ReportError(success, &result->get<picojson::object>());
711     }
712
713     delete raw_buffer;
714   };
715
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());
720   };
721
722   TaskQueue::GetInstance().Queue<picojson::value>(
723       save_data,
724       save_data_result,
725       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
726
727   ReportSuccess(out);
728 }
729
730 void KeyManagerInstance::GetData(const picojson::value& args,
731                                  picojson::object& out) {
732   LoggerD("Enter");
733
734   const auto& data_alias = args.get("name").get<std::string>();
735   const auto& password_value = args.get("password");
736
737   std::string password;
738
739   if (password_value.is<std::string>()) {
740     password = password_value.get<std::string>();
741   }
742
743   ckmc_raw_buffer_s* data = nullptr;
744   int ret = ckmc_get_data(data_alias.c_str(), password.c_str(), &data);
745
746   if (CKMC_ERROR_NONE == ret) {
747     picojson::object result;
748
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)));
754
755     ckmc_buffer_free(data);
756     ReportSuccess(picojson::value{result}, out);
757   } else {
758     LoggerE("Failed to get data: %d", ret);
759
760     PlatformResult error(ErrorCode::UNKNOWN_ERR, "Failed to get key");
761
762     switch (ret) {
763       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
764         error = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to find key");
765         break;
766
767       case CKMC_ERROR_INVALID_PARAMETER:
768         error = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Input parameter is invalid");
769         break;
770     }
771
772     ReportError(error, &out);
773   }
774 }
775
776 void KeyManagerInstance::CreateSignature(const picojson::value& args,
777                                          picojson::object& out) {
778   LoggerD("Enter");
779
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>());
786
787   std::string password;
788
789   if (password_value.is<std::string>()) {
790     password = password_value.get<std::string>();
791   }
792
793   auto create_certificate = [alias, raw_buffer, password, hash, padding](const std::shared_ptr<picojson::value>& result) {
794     LoggerD("Enter create_certificate");
795
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);
799
800     PlatformResult success(ErrorCode::NO_ERROR);
801
802     switch (ret) {
803       case CKMC_ERROR_NONE:
804         break;
805
806       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
807         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
808         break;
809
810       case CKMC_ERROR_INVALID_PARAMETER:
811         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to create signature");
812         break;
813
814       default:
815         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create signature");
816         break;
817     }
818
819     if (success) {
820       common::tools::ReportSuccess(picojson::value(RawBufferToBase64(ToRawBuffer(signature))), result->get<picojson::object>());
821       ckmc_buffer_free(signature);
822     } else {
823       LoggerE("Failed to create signature: %d", ret);
824       common::tools::ReportError(success, &result->get<picojson::object>());
825     }
826
827     delete raw_buffer;
828   };
829
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());
834   };
835
836   TaskQueue::GetInstance().Queue<picojson::value>(
837       create_certificate,
838       create_certificate_result,
839       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
840
841   ReportSuccess(out);
842 }
843
844 void KeyManagerInstance::VerifySignature(const picojson::value& args,
845                                          picojson::object& out) {
846   LoggerD("Enter");
847
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>());
855
856   std::string password;
857
858   if (password_value.is<std::string>()) {
859     password = password_value.get<std::string>();
860   }
861
862   auto verify_certificate = [alias, message, signature, password, hash, padding](const std::shared_ptr<picojson::value>& result) {
863     LoggerD("Enter verify_certificate");
864
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() };
867
868     int ret = ckmc_verify_signature(alias.c_str(), password.c_str(), message_buf, signature_buf, hash , padding);
869
870     PlatformResult success(ErrorCode::NO_ERROR);
871
872     switch (ret) {
873       case CKMC_ERROR_NONE:
874         break;
875
876       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
877         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
878         break;
879
880       case CKMC_ERROR_INVALID_PARAMETER:
881         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to verify signature");
882         break;
883
884       default:
885         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to verify signature");
886         break;
887     }
888
889     if (success) {
890       common::tools::ReportSuccess(result->get<picojson::object>());
891     } else {
892       LoggerE("Failed to verify signature: %d", ret);
893       common::tools::ReportError(success, &result->get<picojson::object>());
894     }
895
896     delete message;
897     delete signature;
898   };
899
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());
904   };
905
906   TaskQueue::GetInstance().Queue<picojson::value>(
907       verify_certificate,
908       verify_certificate_result,
909       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
910
911   ReportSuccess(out);
912 }
913
914 void KeyManagerInstance::LoadFromPKCS12File(const picojson::value& args,
915                                             picojson::object& out) {
916   LoggerD("Enter");
917
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>();
923
924   std::string password;
925
926   if (password_value.is<std::string>()) {
927     password = password_value.get<std::string>();
928   }
929
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;
934
935     int ret = ckmc_pkcs12_load(file.c_str(), password.c_str(), &pkcs12);
936
937     if (CKMC_ERROR_NONE == ret) {
938       SCOPE_EXIT {
939         ckmc_pkcs12_free(pkcs12);
940       };
941       ckmc_policy_s policy { const_cast<char*>(password.c_str()), true };
942
943       // it's safer to use ckmc_save_pkcs12() here, however JS API specifies
944       // two different aliases for private key and certificate
945       if (pkcs12->cert) {
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);
949         }
950       }
951
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);
956           // rollback
957           if (pkcs12->cert) {
958             ckmc_remove_cert(cert_alias.c_str());
959           }
960         }
961       }
962     } else {
963       LoggerE("Failed to load PKCS12 file: %d", ret);
964     }
965
966     PlatformResult success(ErrorCode::NO_ERROR);
967
968     switch (ret) {
969       case CKMC_ERROR_NONE:
970         break;
971
972       case CKMC_ERROR_FILE_ACCESS_DENIED:
973         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Certificate file not found");
974         break;
975
976       case CKMC_ERROR_INVALID_FORMAT:
977       case CKMC_ERROR_INVALID_PARAMETER:
978         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Certificate file has wrong format");
979         break;
980
981       case CKMC_ERROR_PERMISSION_DENIED:
982         success = PlatformResult(ErrorCode::IO_ERR, "Permission has been denied");
983         break;
984
985       default:
986         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to open certificate file");
987         break;
988     }
989
990     if (success) {
991       common::tools::ReportSuccess(result->get<picojson::object>());
992     } else {
993       common::tools::ReportError(success, &result->get<picojson::object>());
994     }
995   };
996
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());
1001   };
1002
1003   TaskQueue::GetInstance().Queue<picojson::value>(
1004       load_file,
1005       load_file_result,
1006       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
1007
1008   ReportSuccess(out);
1009 }
1010
1011 void KeyManagerInstance::AllowAccessControl(const picojson::value& args,
1012                                             picojson::object& out) {
1013   LoggerD("Enter");
1014
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;
1022   }
1023
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>());
1033       return;
1034     }
1035     pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1036
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.");
1042       } else {
1043         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to allow access.");
1044       }
1045       common::tools::ReportError(result, &response->get<picojson::object>());
1046     } else {
1047       common::tools::ReportSuccess(response->get<picojson::object>());
1048     }
1049   };
1050
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());
1055   };
1056
1057   TaskQueue::GetInstance().Queue<picojson::value>(
1058       allow,
1059       allow_response,
1060       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
1061 }
1062
1063 void KeyManagerInstance::DenyAccessControl(const picojson::value& args,
1064                                            picojson::object& out) {
1065   LoggerD("Enter");
1066
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>();
1070
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.");
1077       } else {
1078         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to deny access.");
1079       }
1080       common::tools::ReportError(result, &response->get<picojson::object>());
1081     } else {
1082       common::tools::ReportSuccess(response->get<picojson::object>());
1083     }
1084   };
1085
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());
1090   };
1091
1092   TaskQueue::GetInstance().Queue<picojson::value>(
1093       deny,
1094       deny_response,
1095       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
1096 }
1097
1098 void KeyManagerInstance::IsDataNameFound(const picojson::value& args,
1099                                            picojson::object& out){
1100   LoggerD("Entered");
1101
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;
1105
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.");
1112     }
1113
1114     common::tools::ReportError(result, &out);
1115     return;
1116   }
1117
1118   ckmc_alias_list_s* head = alias_list;
1119   while (head) {
1120     if (!strcmp(head->alias, data_name.c_str())) {
1121       data_found = true;
1122       break;
1123     }
1124     head = head->next;
1125   }
1126
1127   if (alias_list) {
1128     ckmc_alias_list_all_free(alias_list);
1129   }
1130
1131   LoggerD("Data name found: %d", data_found);
1132   if (data_found) {
1133     common::tools::ReportSuccess(out);
1134   } else {
1135     common::tools::ReportError(
1136         PlatformResult(ErrorCode::NOT_FOUND_ERR, "Data name not found."), &out);
1137   }
1138 }
1139
1140 } // namespace keymanager
1141 } // namespace extension