Merge "[Application] Removed duplicated logic." into tizen_2.4
[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   picojson::value result{picojson::array{}};
188
189   if (CKMC_ERROR_NONE == ret) {
190     auto& aliases = result.get<picojson::array>();
191     ckmc_alias_list_s* head = alias_list;
192
193     while (head) {
194       aliases.push_back(picojson::value(head->alias ? head->alias : ""));
195       head = head->next;
196     }
197
198     if (alias_list) {
199       ckmc_alias_list_all_free(alias_list);
200     }
201   }
202
203   common::tools::ReportSuccess(result, *out);
204 }
205 }  // namespace
206
207 KeyManagerInstance::KeyManagerInstance() {
208   LoggerD("Enter");
209   using std::placeholders::_1;
210   using std::placeholders::_2;
211
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));
248 }
249
250 KeyManagerInstance::~KeyManagerInstance() {
251   LoggerD("Enter");
252 }
253
254 void KeyManagerInstance::GetKeyAliasList(const picojson::value& args,
255                                          picojson::object& out) {
256   LoggerD("Enter");
257   GetGenericAliasList(ckmc_get_key_alias_list, &out);
258 }
259
260 void KeyManagerInstance::GetCertificateAliasList(const picojson::value& args,
261                                                  picojson::object& out) {
262   LoggerD("Enter");
263   GetGenericAliasList(ckmc_get_cert_alias_list, &out);
264 }
265
266 void KeyManagerInstance::GetDataAliasList(const picojson::value& args,
267                                           picojson::object& out) {
268   LoggerD("Enter");
269   GetGenericAliasList(ckmc_get_data_alias_list, &out);
270 }
271
272 void KeyManagerInstance::GetKey(const picojson::value& args,
273                                 picojson::object& out) {
274   LoggerD("Enter");
275   const auto& key_alias = args.get("name").get<std::string>();
276   const auto& password_value = args.get("password");
277
278   std::string password;
279
280   if (password_value.is<std::string>()) {
281     password = password_value.get<std::string>();
282   }
283
284   ckmc_key_s* key = nullptr;
285   int ret = ckmc_get_key(key_alias.c_str(), password.c_str(), &key);
286
287   if (CKMC_ERROR_NONE == ret) {
288     picojson::object result;
289
290     result["name"] = picojson::value(key_alias);
291     if (key->password) {
292       result["password"] = picojson::value(key->password);
293     }
294
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)));
299
300     ckmc_key_free(key);
301     ReportSuccess(picojson::value{result}, out);
302   } else {
303     LoggerE("Failed to get key: %d", ret);
304
305     PlatformResult error(ErrorCode::UNKNOWN_ERR, "Failed to get key");
306
307     switch (ret) {
308       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
309         error = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to find key");
310         break;
311
312       case CKMC_ERROR_INVALID_PARAMETER:
313         error = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Input parameter is invalid");
314         break;
315     }
316
317     ReportError(error, &out);
318   }
319 }
320
321 void KeyManagerInstance::SaveKey(const picojson::value& args,
322                                  picojson::object& out) {
323   LoggerD("Enter");
324
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>();
330
331   std::string base64;
332   if (args.get("rawKey").is<std::string>()) {
333     base64 = args.get("rawKey").get<std::string>();
334   }
335
336   std::string pass;
337   if (key_obj.get("password").is<std::string>()) {
338     pass = key_obj.get("password").get<std::string>();
339   }
340
341   RawBuffer* raw_buffer = new RawBuffer(std::move(Base64ToRawBuffer(base64)));
342   ckmc_key_type_e key_type = StringToKeyType(type);
343
344   auto save = [alias, pass, key_type, extractable, raw_buffer]
345                (const std::shared_ptr<picojson::value>& response) -> void {
346
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()) };
351
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.");
358       } else {
359         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save key.");
360       }
361       common::tools::ReportError(result, &response->get<picojson::object>());
362     } else {
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);
371       }
372
373       common::tools::ReportSuccess(response->get<picojson::object>());
374     }
375
376     delete raw_buffer;
377   };
378
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());
384   };
385
386   TaskQueue::GetInstance().Queue<picojson::value>(
387       save,
388       save_response,
389       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
390 }
391
392 void KeyManagerInstance::RemoveAlias(const picojson::value& args,
393                                    picojson::object& out) {
394   LoggerD("Enter");
395
396   const std::string& alias = args.get("alias").get<std::string>();
397   int ret = ckmc_remove_alias(alias.c_str());
398
399   if (CKMC_ERROR_NONE != ret) {
400     LoggerE("Failed to remove alias [%d]", ret);
401     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
402     switch(ret) {
403       case CKMC_ERROR_INVALID_PARAMETER:
404         result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed");
405         break;
406       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
407         result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
408         break;
409       default:
410         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to remove alias");
411     }
412     ReportError(result, &out);
413   } else {
414     ReportSuccess(out);
415   }
416 }
417
418 void KeyManagerInstance::GenerateKeyPair(const picojson::value& args,
419                                          picojson::object& out) {
420   LoggerD("Enter");
421
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>();
429
430   std::string priv_pass;
431   if (priv_key.get("password").is<std::string>()) {
432     priv_pass = priv_key.get("password").get<std::string>();
433   }
434   bool priv_extractable = priv_key.get("extractable").get<bool>();
435
436   std::string pub_pass;
437   if (pub_key.get("password").is<std::string>()) {
438     pub_pass = pub_key.get("password").get<std::string>();
439   }
440   bool pub_extractable = pub_key.get("extractable").get<bool>();
441
442   std::string elliptic;
443   if (args.get("ellipticCurveType").is<std::string>()) {
444     elliptic = args.get("ellipticCurveType").get<std::string>();
445   }
446
447   auto generate =
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;
452
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 };
455
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");
466     } else {
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");
471     }
472
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.");
478       } else {
479         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create key pair.");
480       }
481       common::tools::ReportError(result, &response->get<picojson::object>());
482     } else {
483       common::tools::ReportSuccess(response->get<picojson::object>());
484     }
485   };
486
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());
492   };
493
494   TaskQueue::GetInstance().Queue<picojson::value>(
495       generate,
496       generate_response,
497       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
498
499   ReportSuccess(out);
500 }
501
502 void KeyManagerInstance::GetCertificate(const picojson::value& args,
503                                         picojson::object& out) {
504   LoggerD("Enter");
505
506   const std::string& alias = args.get("name").get<std::string>();
507
508   std::string pass;
509   if (args.get("password").is<std::string>()) {
510     pass = args.get("password").get<std::string>();
511   }
512
513   ckmc_cert_s* cert = nullptr;
514   int ret = ckmc_get_cert(alias.c_str(), pass.c_str(), &cert);
515
516   if (CKMC_ERROR_NONE != ret) {
517     LoggerE("Failed to get certificate: %d", ret);
518     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
519     switch (ret) {
520       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
521         result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Certificate alias not found");
522         break;
523       case CKMC_ERROR_INVALID_PARAMETER:
524         result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed");
525         break;
526       default:
527         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificate");
528     }
529
530     ReportError(result, &out);
531   } else {
532     picojson::value result = picojson::value(picojson::object());
533     picojson::object& obj = result.get<picojson::object>();
534
535     //if cert was retrieved it is extractable from db
536     obj["extractable"] = picojson::value(true);
537     obj["name"] = picojson::value(alias);
538     if (!pass.empty()) {
539       obj["password"] = picojson::value(pass);
540     }
541
542     RawBuffer raw_cert (cert->raw_cert, cert->raw_cert + cert->cert_size);
543     obj["rawCert"] = picojson::value(RawBufferToBase64(raw_cert));
544
545     ReportSuccess(result, out);
546   }
547 }
548
549 void KeyManagerInstance::SaveCertificate(const picojson::value& args,
550                                          picojson::object& out) {
551   LoggerD("Enter");
552
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>();
559
560   std::string password;
561
562   if (password_value.is<std::string>()) {
563     password = password_value.get<std::string>();
564   }
565
566   auto save_certificate = [raw_buffer, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
567     LoggerD("Enter save_certificate");
568
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 };
571
572     int ret = ckmc_save_cert(alias.c_str(), certificate, policy);
573
574     PlatformResult success(ErrorCode::NO_ERROR);
575
576     switch (ret) {
577       case CKMC_ERROR_NONE:
578         break;
579
580       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
581         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
582         break;
583
584       case CKMC_ERROR_INVALID_PARAMETER:
585         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to save certificate");
586         break;
587
588       default:
589         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save certificate");
590         break;
591     }
592
593     if (success) {
594       common::tools::ReportSuccess(result->get<picojson::object>());
595     } else {
596       LoggerE("Failed to save certificate: %d", ret);
597       common::tools::ReportError(success, &result->get<picojson::object>());
598     }
599
600     delete raw_buffer;
601   };
602
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());
607   };
608
609   TaskQueue::GetInstance().Queue<picojson::value>(
610       save_certificate,
611       save_certificate_result,
612       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
613
614   ReportSuccess(out);
615 }
616
617 void KeyManagerInstance::LoadCertificateFromFile(const picojson::value& args,
618                                                  picojson::object& out) {
619   LoggerD("Enter");
620
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>();
627
628   std::string password;
629
630   if (password_value.is<std::string>()) {
631     password = password_value.get<std::string>();
632   }
633
634   auto load_certificate = [file_uri, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
635     LoggerD("Enter load_certificate");
636
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;
641
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);
647       }
648       certificate_data = RawBufferToBase64(ToRawBuffer(certificate));
649       ckmc_cert_free(certificate);
650     } else {
651       LoggerE("Failed to load certificate: %d", ret);
652     }
653
654     PlatformResult success(ErrorCode::NO_ERROR);
655
656     switch (ret) {
657       case CKMC_ERROR_NONE:
658         break;
659
660       case CKMC_ERROR_FILE_ACCESS_DENIED:
661         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "File not found");
662         break;
663
664       case CKMC_ERROR_INVALID_PARAMETER:
665       case CKMC_ERROR_INVALID_FORMAT:
666         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to load certificate");
667         break;
668
669       default:
670         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to load certificate");
671         break;
672     }
673
674     if (success) {
675       common::tools::ReportSuccess(picojson::value(certificate_data), result->get<picojson::object>());
676     } else {
677       common::tools::ReportError(success, &result->get<picojson::object>());
678     }
679   };
680
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());
685   };
686
687   TaskQueue::GetInstance().Queue<picojson::value>(
688       load_certificate,
689       load_certificate_result,
690       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
691
692   ReportSuccess(out);
693 }
694
695 void KeyManagerInstance::SaveData(const picojson::value& args,
696                                   picojson::object& out) {
697   LoggerD("Enter");
698
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>();
705
706   std::string password;
707
708   if (password_value.is<std::string>()) {
709     password = password_value.get<std::string>();
710   }
711
712   auto save_data = [data_raw, password, extractable, alias](const std::shared_ptr<picojson::value>& result) {
713     LoggerD("Enter save_data");
714
715     unsigned char* data = new unsigned char[data_raw.size()];
716     std::copy(data_raw.begin(), data_raw.end(), data);
717
718     ckmc_raw_buffer_s raw_data { data, data_raw.size() };
719     ckmc_policy_s policy { const_cast<char*>(password.c_str()), extractable };
720
721     int ret = ckmc_save_data(alias.c_str(), raw_data, policy);
722
723     PlatformResult success(ErrorCode::NO_ERROR);
724
725     switch (ret) {
726       case CKMC_ERROR_NONE:
727         break;
728
729       case CKMC_ERROR_INVALID_PARAMETER:
730         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to save data");
731         break;
732
733       default:
734         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save data");
735         break;
736     }
737
738     if (success) {
739       common::tools::ReportSuccess(result->get<picojson::object>());
740     } else {
741       LoggerE("Failed to save data: %d", ret);
742       common::tools::ReportError(success, &result->get<picojson::object>());
743     }
744
745     delete data;
746   };
747
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());
752   };
753
754   TaskQueue::GetInstance().Queue<picojson::value>(
755       save_data,
756       save_data_result,
757       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
758
759   ReportSuccess(out);
760 }
761
762 void KeyManagerInstance::GetData(const picojson::value& args,
763                                  picojson::object& out) {
764   LoggerD("Enter");
765
766   const auto& data_alias = args.get("name").get<std::string>();
767   const auto& password_value = args.get("password");
768
769   std::string password;
770
771   if (password_value.is<std::string>()) {
772     password = password_value.get<std::string>();
773   }
774
775   ckmc_raw_buffer_s* data = nullptr;
776   int ret = ckmc_get_data(data_alias.c_str(), password.c_str(), &data);
777
778   if (CKMC_ERROR_NONE == ret) {
779     picojson::object result;
780
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));
786
787     ckmc_buffer_free(data);
788     ReportSuccess(picojson::value{result}, out);
789   } else {
790     LoggerE("Failed to get data: %d", ret);
791
792     PlatformResult error(ErrorCode::UNKNOWN_ERR, "Failed to get key");
793
794     switch (ret) {
795       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
796         error = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to find key");
797         break;
798
799       case CKMC_ERROR_INVALID_PARAMETER:
800         error = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Input parameter is invalid");
801         break;
802     }
803
804     ReportError(error, &out);
805   }
806 }
807
808 void KeyManagerInstance::CreateSignature(const picojson::value& args,
809                                          picojson::object& out) {
810   LoggerD("Enter");
811
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>());
818
819   std::string password;
820
821   if (password_value.is<std::string>()) {
822     password = password_value.get<std::string>();
823   }
824
825   auto create_certificate = [alias, raw_buffer, password, hash, padding](const std::shared_ptr<picojson::value>& result) {
826     LoggerD("Enter create_certificate");
827
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);
831
832     PlatformResult success(ErrorCode::NO_ERROR);
833
834     switch (ret) {
835       case CKMC_ERROR_NONE:
836         break;
837
838       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
839         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
840         break;
841
842       case CKMC_ERROR_INVALID_PARAMETER:
843         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to create signature");
844         break;
845
846       default:
847         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create signature");
848         break;
849     }
850
851     if (success) {
852       common::tools::ReportSuccess(picojson::value(RawBufferToBase64(ToRawBuffer(signature))), result->get<picojson::object>());
853       ckmc_buffer_free(signature);
854     } else {
855       LoggerE("Failed to create signature: %d", ret);
856       common::tools::ReportError(success, &result->get<picojson::object>());
857     }
858
859     delete raw_buffer;
860   };
861
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());
866   };
867
868   TaskQueue::GetInstance().Queue<picojson::value>(
869       create_certificate,
870       create_certificate_result,
871       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
872
873   ReportSuccess(out);
874 }
875
876 void KeyManagerInstance::VerifySignature(const picojson::value& args,
877                                          picojson::object& out) {
878   LoggerD("Enter");
879
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>());
887
888   std::string password;
889
890   if (password_value.is<std::string>()) {
891     password = password_value.get<std::string>();
892   }
893
894   auto verify_certificate = [alias, message, signature, password, hash, padding](const std::shared_ptr<picojson::value>& result) {
895     LoggerD("Enter verify_certificate");
896
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() };
899
900     int ret = ckmc_verify_signature(alias.c_str(), password.c_str(), message_buf, signature_buf, hash , padding);
901
902     PlatformResult success(ErrorCode::NO_ERROR);
903
904     switch (ret) {
905       case CKMC_ERROR_NONE:
906         break;
907
908       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
909         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
910         break;
911
912       case CKMC_ERROR_INVALID_PARAMETER:
913         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to verify signature");
914         break;
915
916       default:
917         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to verify signature");
918         break;
919     }
920
921     if (success) {
922       common::tools::ReportSuccess(result->get<picojson::object>());
923     } else {
924       LoggerE("Failed to verify signature: %d", ret);
925       common::tools::ReportError(success, &result->get<picojson::object>());
926     }
927
928     delete message;
929     delete signature;
930   };
931
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());
936   };
937
938   TaskQueue::GetInstance().Queue<picojson::value>(
939       verify_certificate,
940       verify_certificate_result,
941       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
942
943   ReportSuccess(out);
944 }
945
946 void KeyManagerInstance::LoadFromPKCS12File(const picojson::value& args,
947                                             picojson::object& out) {
948   LoggerD("Enter");
949
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>();
955
956   std::string password;
957
958   if (password_value.is<std::string>()) {
959     password = password_value.get<std::string>();
960   }
961
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;
966
967     int ret = ckmc_pkcs12_load(file.c_str(), password.c_str(), &pkcs12);
968
969     if (CKMC_ERROR_NONE == ret) {
970       SCOPE_EXIT {
971         ckmc_pkcs12_free(pkcs12);
972       };
973       ckmc_policy_s policy { const_cast<char*>(password.c_str()), true };
974
975       // it's safer to use ckmc_save_pkcs12() here, however JS API specifies
976       // two different aliases for private key and certificate
977       if (pkcs12->cert) {
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);
981         }
982       }
983
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);
988           // rollback
989           if (pkcs12->cert) {
990             ckmc_remove_cert(cert_alias.c_str());
991           }
992         }
993       }
994     } else {
995       LoggerE("Failed to load PKCS12 file: %d", ret);
996     }
997
998     PlatformResult success(ErrorCode::NO_ERROR);
999
1000     switch (ret) {
1001       case CKMC_ERROR_NONE:
1002         break;
1003
1004       case CKMC_ERROR_FILE_ACCESS_DENIED:
1005         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Certificate file not found");
1006         break;
1007
1008       case CKMC_ERROR_INVALID_FORMAT:
1009       case CKMC_ERROR_INVALID_PARAMETER:
1010         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Certificate file has wrong format");
1011         break;
1012
1013       case CKMC_ERROR_PERMISSION_DENIED:
1014         success = PlatformResult(ErrorCode::IO_ERR, "Permission has been denied");
1015         break;
1016
1017       default:
1018         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to open certificate file");
1019         break;
1020     }
1021
1022     if (success) {
1023       common::tools::ReportSuccess(result->get<picojson::object>());
1024     } else {
1025       common::tools::ReportError(success, &result->get<picojson::object>());
1026     }
1027   };
1028
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());
1033   };
1034
1035   TaskQueue::GetInstance().Queue<picojson::value>(
1036       load_file,
1037       load_file_result,
1038       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
1039
1040   ReportSuccess(out);
1041 }
1042
1043 void KeyManagerInstance::AllowAccessControl(const picojson::value& args,
1044                                             picojson::object& out) {
1045   LoggerD("Enter");
1046
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;
1054   }
1055
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>());
1065       return;
1066     }
1067     pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1068
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.");
1074       } else {
1075         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to allow access.");
1076       }
1077       common::tools::ReportError(result, &response->get<picojson::object>());
1078     } else {
1079       common::tools::ReportSuccess(response->get<picojson::object>());
1080     }
1081   };
1082
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());
1087   };
1088
1089   TaskQueue::GetInstance().Queue<picojson::value>(
1090       allow,
1091       allow_response,
1092       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
1093 }
1094
1095 void KeyManagerInstance::DenyAccessControl(const picojson::value& args,
1096                                            picojson::object& out) {
1097   LoggerD("Enter");
1098
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>();
1102
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.");
1109       } else {
1110         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to deny access.");
1111       }
1112       common::tools::ReportError(result, &response->get<picojson::object>());
1113     } else {
1114       common::tools::ReportSuccess(response->get<picojson::object>());
1115     }
1116   };
1117
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());
1122   };
1123
1124   TaskQueue::GetInstance().Queue<picojson::value>(
1125       deny,
1126       deny_response,
1127       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
1128 }
1129
1130 void KeyManagerInstance::IsDataNameFound(const picojson::value& args,
1131                                            picojson::object& out){
1132   LoggerD("Entered");
1133
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;
1137
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.");
1144     }
1145
1146     common::tools::ReportError(result, &out);
1147     return;
1148   }
1149
1150   ckmc_alias_list_s* head = alias_list;
1151   while (head) {
1152     if (!strcmp(head->alias, data_name.c_str())) {
1153       data_found = true;
1154       break;
1155     }
1156     head = head->next;
1157   }
1158
1159   if (alias_list) {
1160     ckmc_alias_list_all_free(alias_list);
1161   }
1162
1163   LoggerD("Data name found: %d", data_found);
1164   if (data_found) {
1165     common::tools::ReportSuccess(out);
1166   } else {
1167     common::tools::ReportError(
1168         PlatformResult(ErrorCode::NOT_FOUND_ERR, "Data name not found."), &out);
1169   }
1170 }
1171
1172 } // namespace keymanager
1173 } // namespace extension