[KeyManager] Implementation of createSignature().
[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
22 #include "common/logger.h"
23 #include "common/optional.h"
24 #include "common/platform_result.h"
25 #include "common/scope_exit.h"
26 #include "common/task-queue.h"
27 #include "common/tools.h"
28 #include "common/virtual_fs.h"
29
30 namespace extension {
31 namespace keymanager {
32
33 using common::ErrorCode;
34 using common::optional;
35 using common::PlatformResult;
36 using common::TaskQueue;
37 using common::VirtualFs;
38
39 namespace {
40
41 typedef std::vector<unsigned char> RawBuffer;
42
43 const char* kTypeRSA = "RSA";
44 const char* kTypeECDSA = "ECDSA";
45
46 RawBuffer Base64ToRawBuffer(const std::string& base64) {
47   LoggerD("Enter");
48
49   gsize len = 0;
50   guchar* raw_data = g_base64_decode(base64.c_str(), &len);
51   RawBuffer raw_buffer;
52
53   if (raw_data) {
54     raw_buffer.assign(raw_data, raw_data + len);
55     g_free(raw_data);
56   }
57
58   return raw_buffer;
59 }
60
61 std::string RawBufferToBase64(const RawBuffer& buf) {
62   LoggerD("Enter");
63
64   std::string result;
65
66   if (!buf.empty()) {
67     gchar* base64 = g_base64_encode(&buf[0], buf.size());
68     result = base64;
69     g_free(base64);
70   }
71
72   return result;
73 }
74
75 ckmc_ec_type_e GetEllipticCurveType(const std::string& type) {
76   LoggerD("Enter");
77
78   if ("EC_PRIME256V1" == type) {
79     return CKMC_EC_PRIME256V1;
80   } else if ("EC_SECP384R1" == type) {
81     return CKMC_EC_SECP384R1;
82   } else {
83     return CKMC_EC_PRIME192V1;
84   }
85 }
86
87 ckmc_key_type_e StringToKeyType(const std::string& type) {
88   LoggerD("Enter");
89
90   if ("KEY_RSA_PUBLIC" == type) {
91     return CKMC_KEY_RSA_PUBLIC;
92   } else if ("KEY_RSA_PRIVATE" == type) {
93     return CKMC_KEY_RSA_PRIVATE;
94   } else if ("KEY_ECDSA_PUBLIC" == type) {
95     return CKMC_KEY_ECDSA_PUBLIC;
96   } else if ("KEY_ECDSA_PRIVATE" == type) {
97     return CKMC_KEY_ECDSA_PRIVATE;
98   } else if ("KEY_DSA_PUBLIC" == type) {
99     return CKMC_KEY_DSA_PUBLIC;
100   } else if ("KEY_DSA_PRIVATE" == type) {
101     return CKMC_KEY_DSA_PRIVATE;
102   } else if ("KEY_AES" == type) {
103     return CKMC_KEY_AES;
104   } else {
105     return CKMC_KEY_NONE;
106   }
107 }
108
109 std::string KeyTypeToString(ckmc_key_type_e type) {
110   LoggerD("Enter");
111
112   switch (type) {
113     case CKMC_KEY_NONE:
114       return "KEY_NONE";
115
116     case CKMC_KEY_RSA_PUBLIC:
117       return "KEY_RSA_PUBLIC";
118
119     case CKMC_KEY_RSA_PRIVATE:
120       return "KEY_RSA_PRIVATE";
121
122     case CKMC_KEY_ECDSA_PUBLIC:
123       return "KEY_ECDSA_PUBLIC";
124
125     case CKMC_KEY_ECDSA_PRIVATE:
126       return "KEY_ECDSA_PRIVATE";
127
128     case CKMC_KEY_DSA_PUBLIC:
129       return "KEY_DSA_PUBLIC";
130
131     case CKMC_KEY_DSA_PRIVATE:
132       return "KEY_DSA_PRIVATE";
133
134     case CKMC_KEY_AES:
135       return "KEY_AES";
136   }
137
138   LoggerE("Unknown key type");
139   return "KEY_UNKNOWN";
140 }
141
142 ckmc_hash_algo_e StringToHashAlgorithm(const std::string& str) {
143   if ("HASH_SHA1" == str) {
144     return CKMC_HASH_SHA1;
145   } else if ("HASH_SHA256" == str) {
146     return CKMC_HASH_SHA256;
147   } else if ("HASH_SHA384" == str) {
148     return CKMC_HASH_SHA384;
149   } else if ("HASH_SHA512" == str) {
150     return CKMC_HASH_SHA512;
151   }
152
153   return CKMC_HASH_NONE;
154 }
155
156 ckmc_rsa_padding_algo_e StringToRsaPadding(const std::string& str) {
157   if ("PADDING_PKCS1" == str) {
158     return CKMC_PKCS1_PADDING;
159   } else if ("PADDING_X931" == str) {
160     return CKMC_X931_PADDING;
161   }
162
163   return CKMC_NONE_PADDING;
164 }
165
166 RawBuffer ToRawBuffer(const ckmc_key_s* key) {
167   return RawBuffer(key->raw_key, key->raw_key + key->key_size);
168 }//
169
170 RawBuffer ToRawBuffer(const ckmc_raw_buffer_s* buffer) {
171   return RawBuffer(buffer->data, buffer->data + buffer->size);
172 }
173
174 typedef int (*AliasListFunction)(ckmc_alias_list_s**);
175
176 void GetGenericAliasList(AliasListFunction func, picojson::object* out) {
177   LoggerD("Enter");
178
179   ckmc_alias_list_s* alias_list = nullptr;
180   int ret = func(&alias_list);
181
182   if (CKMC_ERROR_NONE == ret) {
183     picojson::value result{picojson::array{}};
184     auto& aliases = result.get<picojson::array>();
185     ckmc_alias_list_s* head = alias_list;
186
187     while (head) {
188       aliases.push_back(picojson::value(alias_list->alias ? alias_list->alias : ""));
189       head = head->next;
190     }
191
192     if (alias_list) {
193       ckmc_alias_list_all_free(alias_list);
194     }
195
196     common::tools::ReportSuccess(result, *out);
197   } else {
198     LoggerE("Failed to get alias list: %d", ret);
199     common::tools::ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get alias list"), out);
200   }
201 }
202
203 }  // namespace
204
205 KeyManagerInstance::KeyManagerInstance() {
206   LoggerD("Enter");
207   using std::placeholders::_1;
208   using std::placeholders::_2;
209
210   RegisterSyncHandler("KeyManager_getKeyAliasList",
211       std::bind(&KeyManagerInstance::GetKeyAliasList, this, _1, _2));
212   RegisterSyncHandler("KeyManager_getCertificatesAliasList",
213       std::bind(&KeyManagerInstance::GetCertificateAliasList, this, _1, _2));
214   RegisterSyncHandler("KeyManager_getDataAliasList",
215       std::bind(&KeyManagerInstance::GetDataAliasList, this, _1, _2));
216   RegisterSyncHandler("KeyManager_getKey",
217       std::bind(&KeyManagerInstance::GetKey, this, _1, _2));
218   RegisterSyncHandler("KeyManager_saveKey",
219       std::bind(&KeyManagerInstance::SaveKey, this, _1, _2));
220   RegisterSyncHandler("KeyManager_removeAlias",
221       std::bind(&KeyManagerInstance::RemoveAlias, this, _1, _2));
222   RegisterSyncHandler("KeyManager_generateKeyPair",
223       std::bind(&KeyManagerInstance::GenerateKeyPair, this, _1, _2));
224   RegisterSyncHandler("KeyManager_getCertificate",
225       std::bind(&KeyManagerInstance::GetCertificate, this, _1, _2));
226   RegisterSyncHandler("KeyManager_saveCertificate",
227       std::bind(&KeyManagerInstance::SaveCertificate, this, _1, _2));
228   RegisterSyncHandler("KeyManager_loadCertificateFromFile",
229       std::bind(&KeyManagerInstance::LoadCertificateFromFile, this, _1, _2));
230   RegisterSyncHandler("KeyManager_saveData",
231       std::bind(&KeyManagerInstance::SaveData, this, _1, _2));
232   RegisterSyncHandler("KeyManager_getData",
233       std::bind(&KeyManagerInstance::GetData, this, _1, _2));
234   RegisterSyncHandler("KeyManager_createSignature",
235       std::bind(&KeyManagerInstance::CreateSignature, this, _1, _2));
236   RegisterSyncHandler("KeyManager_verifySignature",
237       std::bind(&KeyManagerInstance::VerifySignature, this, _1, _2));
238   RegisterSyncHandler("KeyManager_loadFromPKCS12File",
239       std::bind(&KeyManagerInstance::LoadFromPKCS12File, this, _1, _2));
240   RegisterSyncHandler("KeyManager_allowAccessControl",
241       std::bind(&KeyManagerInstance::AllowAccessControl, this, _1, _2));
242   RegisterSyncHandler("KeyManager_denyAccessControl",
243       std::bind(&KeyManagerInstance::DenyAccessControl, this, _1, _2));
244 }
245
246 KeyManagerInstance::~KeyManagerInstance() {
247   LoggerD("Enter");
248 }
249
250 void KeyManagerInstance::GetKeyAliasList(const picojson::value& args,
251                                          picojson::object& out) {
252   LoggerD("Enter");
253   GetGenericAliasList(ckmc_get_key_alias_list, &out);
254 }
255
256 void KeyManagerInstance::GetCertificateAliasList(const picojson::value& args,
257                                                  picojson::object& out) {
258   LoggerD("Enter");
259   GetGenericAliasList(ckmc_get_cert_alias_list, &out);
260 }
261
262 void KeyManagerInstance::GetDataAliasList(const picojson::value& args,
263                                           picojson::object& out) {
264   LoggerD("Enter");
265   GetGenericAliasList(ckmc_get_data_alias_list, &out);
266 }
267
268 void KeyManagerInstance::GetKey(const picojson::value& args,
269                                 picojson::object& out) {
270   LoggerD("Enter");
271   const auto& key_alias = args.get("name").get<std::string>();
272   const auto& password_value = args.get("password");
273
274   std::string password;
275
276   if (password_value.is<std::string>()) {
277     password = password_value.get<std::string>();
278   }
279
280   ckmc_key_s* key = nullptr;
281   int ret = ckmc_get_key(key_alias.c_str(), password.c_str(), &key);
282
283   if (CKMC_ERROR_NONE == ret) {
284     picojson::object result;
285
286     result["name"] = picojson::value(key_alias);
287     result["password"] = picojson::value(key->password);
288     // if key was retrieved it is extractable from DB
289     result["extractable"] = picojson::value(true);
290     result["keyType"] = picojson::value(KeyTypeToString(key->key_type));
291     result["rawKey"] = picojson::value(RawBufferToBase64(ToRawBuffer(key)));
292
293     ckmc_key_free(key);
294     ReportSuccess(picojson::value{result}, out);
295   } else {
296     LoggerE("Failed to get key: %d", ret);
297
298     PlatformResult error(ErrorCode::UNKNOWN_ERR, "Failed to get key");
299
300     switch (ret) {
301       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
302         error = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to find key");
303         break;
304
305       case CKMC_ERROR_INVALID_PARAMETER:
306         error = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Input parameter is invalid");
307         break;
308     }
309
310     ReportError(error, &out);
311   }
312 }
313
314 void KeyManagerInstance::SaveKey(const picojson::value& args,
315                                  picojson::object& out) {
316   LoggerD("Enter");
317
318   const picojson::value& key_obj = args.get("key");
319   const std::string& alias = key_obj.get("name").get<std::string>();
320   const std::string& type = key_obj.get("keyType").get<std::string>();
321   bool extractable = key_obj.get("extractable").get<bool>();
322   const double callback_id = args.get("callbackId").get<double>();
323
324   std::string base64;
325   if (args.get("rawKey").is<std::string>()) {
326     base64 = args.get("rawKey").get<std::string>();
327   }
328
329   std::string pass;
330   if (key_obj.get("password").is<std::string>()) {
331     pass = key_obj.get("password").get<std::string>();
332   }
333
334   RawBuffer* raw_buffer = new RawBuffer(std::move(Base64ToRawBuffer(base64)));
335   ckmc_key_type_e key_type = StringToKeyType(type);
336
337   auto save = [alias, pass, key_type, extractable, raw_buffer]
338                (const std::shared_ptr<picojson::value>& response) -> void {
339
340     ckmc_policy_s policy { const_cast<char*>(pass.c_str()), extractable };
341     ckmc_key_s key { const_cast<unsigned char*>(&(*raw_buffer)[0]),
342       raw_buffer->size(), key_type, const_cast<char*>(pass.c_str()) };
343
344     int ret = ckmc_save_key(alias.c_str(), key, policy);
345     if (CKMC_ERROR_NONE != ret) {
346       PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
347       if (CKMC_ERROR_INVALID_PARAMETER == ret) {
348         result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
349       } else {
350         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to save key.");
351       }
352       common::tools::ReportError(result, &response->get<picojson::object>());
353     } else {
354       common::tools::ReportSuccess(response->get<picojson::object>());
355     }
356
357     delete raw_buffer;
358   };
359
360   auto save_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
361     picojson::object& obj = response->get<picojson::object>();
362     obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
363     this->PostMessage(response->serialize().c_str());
364   };
365
366   TaskQueue::GetInstance().Queue<picojson::value>(
367       save,
368       save_response,
369       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
370 }
371
372 void KeyManagerInstance::RemoveAlias(const picojson::value& args,
373                                    picojson::object& out) {
374   LoggerD("Enter");
375
376   const std::string& alias = args.get("alias").get<std::string>();
377   int ret = ckmc_remove_alias(alias.c_str());
378
379   if (CKMC_ERROR_NONE != ret) {
380     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
381     switch(ret) {
382       case CKMC_ERROR_INVALID_PARAMETER:
383         result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed");
384         break;
385       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
386         result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
387         break;
388       default:
389         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to remove alias");
390     }
391     ReportError(result, &out);
392   } else {
393     ReportSuccess(out);
394   }
395 }
396
397 void KeyManagerInstance::GenerateKeyPair(const picojson::value& args,
398                                          picojson::object& out) {
399   LoggerD("Enter");
400
401   const picojson::value& priv_key = args.get("privKeyName");
402   const picojson::value& pub_key = args.get("pubKeyName");
403   const std::string& priv_name = priv_key.get("name").get<std::string>();
404   const std::string& pub_name = pub_key.get("name").get<std::string>();
405   const std::string& type = args.get("type").get<std::string>();
406   const int size = std::stoi(args.get("size").get<std::string>());
407   const double callback_id = args.get("callbackId").get<double>();
408
409   std::string priv_pass;
410   if (priv_key.get("password").is<std::string>()) {
411     priv_pass = priv_key.get("password").get<std::string>();
412   }
413   bool extractable = priv_key.get("extractable").get<bool>();
414   ckmc_policy_s priv_policy { const_cast<char*>(priv_pass.c_str()), extractable };
415
416   std::string pub_pass;
417   if (pub_key.get("password").is<std::string>()) {
418     pub_pass = pub_key.get("password").get<std::string>();
419   }
420   extractable = pub_key.get("extractable").get<bool>();
421   ckmc_policy_s pub_policy { const_cast<char*>(pub_pass.c_str()), extractable };
422
423   std::string elliptic;
424   if (args.get("ellipticCurveType").is<std::string>()) {
425     elliptic = args.get("ellipticCurveType").get<std::string>();
426   }
427
428   auto generate = [size, priv_policy, pub_policy, priv_name, pub_name, type, elliptic]
429                    (const std::shared_ptr<picojson::value>& response) -> void {
430     int ret = CKMC_ERROR_NONE;
431     if (kTypeRSA == type) {
432       ret = ckmc_create_key_pair_rsa(size, priv_name.c_str(),
433                                      pub_name.c_str(), priv_policy, pub_policy);
434     } else if (kTypeECDSA == type) {
435       ret = ckmc_create_key_pair_ecdsa(GetEllipticCurveType(elliptic), priv_name.c_str(),
436                                        pub_name.c_str(), priv_policy, pub_policy);
437     } else {
438       ret = ckmc_create_key_pair_dsa(size, priv_name.c_str(),
439                                      pub_name.c_str(), priv_policy, pub_policy);
440     }
441
442     if (CKMC_ERROR_NONE != ret) {
443       PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
444       if (CKMC_ERROR_INVALID_PARAMETER == ret) {
445         result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value passed.");
446       } else {
447         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create key pair.");
448       }
449       common::tools::ReportError(result, &response->get<picojson::object>());
450     } else {
451       common::tools::ReportSuccess(response->get<picojson::object>());
452     }
453   };
454
455   auto generate_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
456     picojson::object& obj = response->get<picojson::object>();
457     obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
458     this->PostMessage(response->serialize().c_str());
459   };
460
461   TaskQueue::GetInstance().Queue<picojson::value>(
462       generate,
463       generate_response,
464       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
465 }
466
467 void KeyManagerInstance::GetCertificate(const picojson::value& args,
468                                         picojson::object& out) {
469   LoggerD("Enter");
470
471   const std::string& alias = args.get("name").get<std::string>();
472
473   std::string pass;
474   if (args.get("password").is<std::string>()) {
475     pass = args.get("password").get<std::string>();
476   }
477
478   ckmc_cert_s* cert = nullptr;
479   int ret = ckmc_get_cert(alias.c_str(), pass.c_str(), &cert);
480
481   if (CKMC_ERROR_NONE != ret) {
482     LoggerE("Failed to get certificate: %d", ret);
483     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
484     switch (ret) {
485       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
486         result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Certificate alias not found");
487         break;
488       case CKMC_ERROR_INVALID_PARAMETER:
489         result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed");
490         break;
491       default:
492         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificate");
493     }
494
495     ReportError(result, &out);
496   } else {
497     picojson::value result = picojson::value(picojson::object());
498     picojson::object& obj = result.get<picojson::object>();
499
500     //if cert was retrieved it is extractable from db
501     obj["extractable"] = picojson::value(true);
502     obj["name"] = picojson::value(alias);
503     if (!pass.empty()) {
504       obj["password"] = picojson::value(pass);
505     }
506
507     RawBuffer raw_cert (cert->raw_cert, cert->raw_cert + cert->cert_size);
508     obj["rawCert"] = picojson::value(RawBufferToBase64(raw_cert));
509
510     ReportSuccess(result, out);
511   }
512 }
513
514 void KeyManagerInstance::SaveCertificate(const picojson::value& args,
515                                          picojson::object& out) {
516   LoggerD("Enter");
517 }
518
519 void KeyManagerInstance::LoadCertificateFromFile(const picojson::value& args,
520                                                  picojson::object& out) {
521   LoggerD("Enter");
522 }
523
524 void KeyManagerInstance::SaveData(const picojson::value& args,
525                                   picojson::object& out) {
526   LoggerD("Enter");
527 }
528
529 void KeyManagerInstance::GetData(const picojson::value& args,
530                                  picojson::object& out) {
531   LoggerD("Enter");
532
533   const auto& data_alias = args.get("name").get<std::string>();
534   const auto& password_value = args.get("password");
535
536   std::string password;
537
538   if (password_value.is<std::string>()) {
539     password = password_value.get<std::string>();
540   }
541
542   ckmc_raw_buffer_s* data = nullptr;
543   int ret = ckmc_get_data(data_alias.c_str(), password.c_str(), &data);
544
545   if (CKMC_ERROR_NONE == ret) {
546     picojson::object result;
547
548     result["name"] = picojson::value(data_alias);
549     result["password"] = picojson::value(password);
550     // if key was retrieved it is extractable from DB
551     result["extractable"] = picojson::value(true);
552     result["rawData"] = picojson::value(RawBufferToBase64(ToRawBuffer(data)));
553
554     ckmc_buffer_free(data);
555     ReportSuccess(picojson::value{result}, out);
556   } else {
557     LoggerE("Failed to get data: %d", ret);
558
559     PlatformResult error(ErrorCode::UNKNOWN_ERR, "Failed to get key");
560
561     switch (ret) {
562       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
563         error = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to find key");
564         break;
565
566       case CKMC_ERROR_INVALID_PARAMETER:
567         error = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Input parameter is invalid");
568         break;
569     }
570
571     ReportError(error, &out);
572   }
573 }
574
575 void KeyManagerInstance::CreateSignature(const picojson::value& args,
576                                          picojson::object& out) {
577   LoggerD("Enter");
578
579   const auto& alias = args.get("privKeyAlias").get<std::string>();
580   RawBuffer* raw_buffer = new RawBuffer(std::move(Base64ToRawBuffer(args.get("message").get<std::string>())));
581   const auto& password_value = args.get("password");
582   double callback_id = args.get("callbackId").get<double>();
583   ckmc_hash_algo_e hash = StringToHashAlgorithm(args.get("hashAlgorithmType").get<std::string>());
584   ckmc_rsa_padding_algo_e padding = StringToRsaPadding(args.get("padding").get<std::string>());
585
586   std::string password;
587
588   if (password_value.is<std::string>()) {
589     password = password_value.get<std::string>();
590   }
591
592   auto create_certificate = [alias, raw_buffer, password, hash, padding](const std::shared_ptr<picojson::value>& result) {
593     LoggerD("Enter create_certificate");
594
595     ckmc_raw_buffer_s* signature = nullptr;
596     ckmc_raw_buffer_s message = { const_cast<unsigned char*>(&(*raw_buffer)[0]), raw_buffer->size() };
597     int ret = ckmc_create_signature(alias.c_str(), password.c_str(), message, hash, padding, &signature);
598
599     PlatformResult success(ErrorCode::NO_ERROR);
600
601     switch (ret) {
602       case CKMC_ERROR_NONE:
603         break;
604
605       case CKMC_ERROR_DB_ALIAS_UNKNOWN:
606         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found");
607         break;
608
609       case CKMC_ERROR_INVALID_PARAMETER:
610         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to create signature");
611         break;
612
613       default:
614         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create signature");
615         break;
616     }
617
618     if (success) {
619       common::tools::ReportSuccess(picojson::value(RawBufferToBase64(ToRawBuffer(signature))), result->get<picojson::object>());
620       ckmc_buffer_free(signature);
621     } else {
622       LoggerE("Failed to create signature: %d", ret);
623       common::tools::ReportError(success, &result->get<picojson::object>());
624     }
625
626     delete raw_buffer;
627   };
628
629   auto create_certificate_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
630     LoggerD("Enter create_certificate_result");
631     result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
632     this->PostMessage(result->serialize().c_str());
633   };
634
635   TaskQueue::GetInstance().Queue<picojson::value>(
636       create_certificate,
637       create_certificate_result,
638       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
639
640   ReportSuccess(out);
641 }
642
643 void KeyManagerInstance::VerifySignature(const picojson::value& args,
644                                          picojson::object& out) {
645   LoggerD("Enter");
646 }
647
648 void KeyManagerInstance::LoadFromPKCS12File(const picojson::value& args,
649                                             picojson::object& out) {
650   LoggerD("Enter");
651
652   const auto& file_uri = args.get("fileURI").get<std::string>();
653   const auto& key_alias = args.get("privKeyName").get<std::string>();
654   const auto& cert_alias = args.get("certificateName").get<std::string>();
655   const auto& password_value = args.get("password");
656   double callback_id = args.get("callbackId").get<double>();
657
658   std::string password;
659
660   if (password_value.is<std::string>()) {
661     password = password_value.get<std::string>();
662   }
663
664   auto load_file = [file_uri, password, cert_alias, key_alias](const std::shared_ptr<picojson::value>& result) {
665     LoggerD("Enter load_file");
666     std::string file = VirtualFs::GetInstance().GetRealPath(file_uri);
667     ckmc_pkcs12_s* pkcs12 = nullptr;
668
669     int ret = ckmc_pkcs12_load(file.c_str(), password.c_str(), &pkcs12);
670
671     if (CKMC_ERROR_NONE == ret) {
672       SCOPE_EXIT {
673         ckmc_pkcs12_free(pkcs12);
674       };
675       ckmc_policy_s policy { const_cast<char*>(password.c_str()), true };
676
677       // it's safer to use ckmc_save_pkcs12() here, however JS API specifies
678       // two different aliases for private key and certificate
679       if (pkcs12->cert) {
680         ret = ckmc_save_cert(cert_alias.c_str(), *pkcs12->cert, policy);
681         if (CKMC_ERROR_NONE != ret) {
682           LoggerE("Failed to save certificate: %d", ret);
683         }
684       }
685
686       if (CKMC_ERROR_NONE == ret && pkcs12->priv_key) {
687         ret = ckmc_save_key(key_alias.c_str(), *pkcs12->priv_key, policy);
688         if (CKMC_ERROR_NONE != ret) {
689           LoggerE("Failed to save private key: %d", ret);
690           // rollback
691           if (pkcs12->cert) {
692             ckmc_remove_cert(cert_alias.c_str());
693           }
694         }
695       }
696     } else {
697       LoggerE("Failed to load PKCS12 file: %d", ret);
698     }
699
700     PlatformResult success(ErrorCode::NO_ERROR);
701
702     switch (ret) {
703       case CKMC_ERROR_NONE:
704         break;
705
706       case CKMC_ERROR_FILE_ACCESS_DENIED:
707         success = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Certificate file not found");
708         break;
709
710       case CKMC_ERROR_INVALID_FORMAT:
711       case CKMC_ERROR_INVALID_PARAMETER:
712         success = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Certificate file has wrong format");
713         break;
714
715       case CKMC_ERROR_PERMISSION_DENIED:
716         success = PlatformResult(ErrorCode::IO_ERR, "Permission has been denied");
717         break;
718
719       default:
720         success = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to open certificate file");
721         break;
722     }
723
724     if (success) {
725       common::tools::ReportSuccess(result->get<picojson::object>());
726     } else {
727       common::tools::ReportError(success, &result->get<picojson::object>());
728     }
729   };
730
731   auto load_file_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
732     LoggerD("Enter load_file_result");
733     result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
734     this->PostMessage(result->serialize().c_str());
735   };
736
737   TaskQueue::GetInstance().Queue<picojson::value>(
738       load_file,
739       load_file_result,
740       std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
741
742   ReportSuccess(out);
743 }
744
745 void KeyManagerInstance::AllowAccessControl(const picojson::value& args,
746                                             picojson::object& out) {
747   LoggerD("Enter");
748
749   const std::string& data_name = args.get("dataName").get<std::string>();
750   const std::string& id = args.get("id").get<std::string>();
751   const double callback_id = args.get("callbackId").get<double>();
752   const std::string& access = args.get("accessControlType").get<std::string>();
753   ckmc_access_right_e granted = CKMC_AR_READ;
754   if ("READ_REMOVE" == access) {
755     granted = CKMC_AR_READ_REMOVE;
756   }
757
758   auto allow = [data_name, id, granted](const std::shared_ptr<picojson::value>& response) -> void {
759     int ret = ckmc_allow_access(data_name.c_str(), id.c_str(), granted);
760     if (CKMC_ERROR_NONE != ret) {
761       PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
762       if (CKMC_ERROR_DB_ALIAS_UNKNOWN == ret) {
763         result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found.");
764       } else {
765         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to allow access.");
766       }
767       common::tools::ReportError(result, &response->get<picojson::object>());
768     } else {
769       common::tools::ReportSuccess(response->get<picojson::object>());
770     }
771   };
772
773   auto allow_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
774     picojson::object& obj = response->get<picojson::object>();
775     obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
776     this->PostMessage(response->serialize().c_str());
777   };
778
779   TaskQueue::GetInstance().Queue<picojson::value>(
780       allow,
781       allow_response,
782       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
783 }
784
785 void KeyManagerInstance::DenyAccessControl(const picojson::value& args,
786                                            picojson::object& out) {
787   LoggerD("Enter");
788
789   const std::string& data_name = args.get("dataName").get<std::string>();
790   const std::string& id = args.get("id").get<std::string>();
791   const double callback_id = args.get("callbackId").get<double>();
792
793   auto deny = [data_name, id](const std::shared_ptr<picojson::value>& response) -> void {
794     int ret = ckmc_deny_access(data_name.c_str(), id.c_str());
795     if (CKMC_ERROR_NONE != ret) {
796       PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
797       if (CKMC_ERROR_DB_ALIAS_UNKNOWN == ret) {
798         result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alias not found.");
799       } else {
800         result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to deny access.");
801       }
802       common::tools::ReportError(result, &response->get<picojson::object>());
803     } else {
804       common::tools::ReportSuccess(response->get<picojson::object>());
805     }
806   };
807
808   auto deny_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
809     picojson::object& obj = response->get<picojson::object>();
810     obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
811     this->PostMessage(response->serialize().c_str());
812   };
813
814   TaskQueue::GetInstance().Queue<picojson::value>(
815       deny,
816       deny_response,
817       std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
818 }
819
820 } // namespace keymanager
821 } // namespace extension