[KeyManager] getCertificate and saveCertificate
[platform/core/api/webapi-plugins.git] / src / keymanager / keymanager_instance.cc
1 // Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "keymanager/keymanager_instance.h"
6
7 #include <functional>
8 #include <ckm/ckm-manager.h>
9 #include <glib.h>
10 #include <pcrecpp.h>
11
12 #include "common/logger.h"
13 #include "common/picojson.h"
14 #include "common/platform_result.h"
15
16 namespace extension {
17 namespace keymanager {
18
19 namespace {
20 const char* kTypeRSA = "RSA";
21 const char* kTypeECDSA = "ECDSA";
22 }
23
24 KeyManagerInstance::KeyManagerInstance() {
25   using std::placeholders::_1;
26   using std::placeholders::_2;
27
28   RegisterSyncHandler("KeyManager_getKeyAliasList",
29       std::bind(&KeyManagerInstance::GetKeyAliasList, this, _1, _2));
30   RegisterSyncHandler("KeyManager_getCertificatesAliasList",
31       std::bind(&KeyManagerInstance::GetCertificateAliasList, this, _1, _2));
32   RegisterSyncHandler("KeyManager_getDataAliasList",
33       std::bind(&KeyManagerInstance::GetDataAliasList, this, _1, _2));
34   RegisterSyncHandler("KeyManager_getKey",
35       std::bind(&KeyManagerInstance::GetKey, this, _1, _2));
36   RegisterSyncHandler("KeyManager_saveKey",
37       std::bind(&KeyManagerInstance::SaveKey, this, _1, _2));
38   RegisterSyncHandler("KeyManager_removeKey",
39       std::bind(&KeyManagerInstance::RemoveKey, this, _1, _2));
40   RegisterSyncHandler("KeyManager_generateKeyPair",
41       std::bind(&KeyManagerInstance::GenerateKeyPair, this, _1, _2));
42   RegisterSyncHandler("KeyManager_getCertificate",
43       std::bind(&KeyManagerInstance::GetCertificate, this, _1, _2));
44   RegisterSyncHandler("KeyManager_saveCertificate",
45       std::bind(&KeyManagerInstance::SaveCertificate, this, _1, _2));
46 }
47
48 KeyManagerInstance::~KeyManagerInstance() {
49 }
50
51 void KeyManagerInstance::GetAliasList(
52     std::function<int(CKM::AliasVector&)> coreFunc, picojson::object& out) {
53   LoggerD("Enter");
54   CKM::AliasVector result;
55   int ret = coreFunc(result);
56   if (ret != CKM_API_SUCCESS) {
57       LoggerE("Failed to fetch list of alias: %d", ret);
58       ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
59         "Failed to fetch list of alias"), &out);
60   } else {
61       picojson::array aliases;
62       for (auto& item: result) {
63           aliases.push_back(picojson::value(item));
64       }
65       picojson::value res(aliases);
66       ReportSuccess(res, out);
67   }
68 }
69
70 void KeyManagerInstance::GetKeyAliasList(const picojson::value& args,
71     picojson::object& out) {
72   LoggerD("Enter");
73   using std::placeholders::_1;
74   GetAliasList(
75       std::bind(&CKM::Manager::getKeyAliasVector, CKM::Manager::create(), _1),
76       out);
77 }
78
79 void KeyManagerInstance::GetCertificateAliasList(const picojson::value& args,
80     picojson::object& out) {
81   LoggerD("Enter");
82   using std::placeholders::_1;
83   GetAliasList(
84       std::bind(&CKM::Manager::getCertificateAliasVector, CKM::Manager::create(), _1),
85       out);
86 }
87
88 void KeyManagerInstance::GetDataAliasList(const picojson::value& args,
89     picojson::object& out) {
90   LoggerD("Enter");
91   using std::placeholders::_1;
92   GetAliasList(
93       std::bind(&CKM::Manager::getDataAliasVector, CKM::Manager::create(), _1),
94       out);
95 }
96
97 void KeyManagerInstance::SaveKey(const picojson::value& args,
98     picojson::object& out) {
99   LoggerD("Enter");
100
101   const picojson::value& key_object = args.get("key");
102   const std::string& alias = key_object.get("name").get<std::string>();
103   std::string password;
104   if (key_object.get("password").is<std::string>()) {
105     password = key_object.get("password").get<std::string>();
106   }
107   std::string base64 = args.get("rawKey").get<std::string>();
108   pcrecpp::RE_Options opt;
109   opt.set_multiline(true);
110   //remove first line and last line
111   pcrecpp::RE("-----[^-]*-----", opt).GlobalReplace("", &base64);
112   gsize len = 0;
113   guchar* raw_data = g_base64_decode(base64.c_str(), &len);
114   CKM::RawBuffer raw_buffer;
115   raw_buffer.assign(raw_data, raw_data + len);
116   g_free(raw_data);
117   CKM::Password pass(password.c_str());
118   CKM::KeyShPtr key = CKM::Key::create(raw_buffer, pass);
119   CKM::Policy policy(pass, key_object.get("extractable").get<bool>());
120   CKM::ManagerAsync::ObserverPtr observer(new SaveKeyObserver(this,
121     args.get("callbackId").get<double>()));
122   m_manager.saveKey(observer, alias, key, policy);
123
124   ReportSuccess(out);
125 }
126
127 void KeyManagerInstance::OnSaveKey(double callbackId,
128     const common::PlatformResult& result) {
129   LoggerD("Enter");
130   picojson::value::object dict;
131   dict["callbackId"] = picojson::value(callbackId);
132   if (result.IsError()) {
133     LoggerE("There was an error");
134     ReportError(result, &dict);
135   }
136   picojson::value res(dict);
137   PostMessage(res.serialize().c_str());
138 }
139
140 void KeyManagerInstance::RemoveKey(const picojson::value& args,
141     picojson::object& out) {
142   LoggerD("Enter");
143
144   const std::string& alias = args.get("key").get("name").get<std::string>();
145   int ret = CKM::Manager::create()->removeAlias(alias);
146   if (ret != CKM_API_SUCCESS) {
147     LoggerE("Failed to remove key alias: %d", ret);
148     if (ret == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
149       ReportError(common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
150         "Key alias not found"), &out);
151     } else {
152       ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
153         "Failed to remove key alias"), &out);
154     }
155   } else {
156     ReportSuccess(out);
157   }
158 }
159
160 void KeyManagerInstance::GenerateKeyPair(const picojson::value& args,
161     picojson::object& out) {
162   LoggerD("Enter");
163
164   const picojson::value& priv_key = args.get("privKeyName");
165   const picojson::value& pub_key = args.get("pubKeyName");
166   const std::string& priv_name = priv_key.get("name").get<std::string>();
167   const std::string& pub_name = pub_key.get("name").get<std::string>();
168   const std::string& type = args.get("type").get<std::string>();
169   int size = std::stoi(args.get("size").get<std::string>());
170
171   CKM::ManagerAsync::ObserverPtr observer(new CreateKeyObserver(this,
172     args.get("callbackId").get<double>()));
173
174   CKM::Password pass;
175   if (priv_key.get("password").is<std::string>()) {
176     pass = priv_key.get("password").get<std::string>().c_str();
177   }
178   CKM::Policy priv_policy(pass, priv_key.get("extractable").get<bool>());
179
180   if (pub_key.get("password").is<std::string>()) {
181     pass = pub_key.get("password").get<std::string>().c_str();
182   } else {
183     pass = "";
184   }
185   CKM::Policy pub_policy(pass, pub_key.get("extractable").get<bool>());
186
187   if (type == kTypeRSA) {
188     m_manager.createKeyPairRSA(observer, size, priv_name, pub_name, priv_policy, pub_policy);
189   } else if (type == kTypeECDSA) {
190     CKM::ElipticCurve eliptic = CKM::ElipticCurve::prime192v1;
191     if (args.get("ellipticCurveType").is<std::string>()) {
192       const std::string& eType = args.get("ellipticCurveType").get<std::string>();
193       if (eType == "PRIME256V1") {
194         eliptic = CKM::ElipticCurve::prime256v1;
195       } else if (eType == "EC_SECP384R1") {
196         eliptic = CKM::ElipticCurve::secp384r1;
197       }
198     }
199     m_manager.createKeyPairECDSA(observer, eliptic, priv_name, pub_name, priv_policy, pub_policy);
200   } else {
201     m_manager.createKeyPairDSA(observer, size, priv_name, pub_name, priv_policy, pub_policy);
202   }
203
204   ReportSuccess(out);
205 }
206
207 void KeyManagerInstance::OnCreateKeyPair(double callbackId,
208     const common::PlatformResult& result) {
209   LoggerD("Enter");
210   picojson::value::object dict;
211   dict["callbackId"] = picojson::value(callbackId);
212   if (result.IsError()) {
213     LoggerE("There was an error");
214     ReportError(result, &dict);
215   }
216   picojson::value res(dict);
217   PostMessage(res.serialize().c_str());
218 }
219
220 std::string RawBufferToBase64(const CKM::RawBuffer &buf) {
221   std::string result;
222   if (!buf.empty()) {
223     gchar* base64 = g_base64_encode(&buf[0], buf.size());
224     result = base64;
225     g_free(base64);
226   }
227   return result;
228 }
229
230 void KeyManagerInstance::GetKey(const picojson::value& args, picojson::object& out) {
231   LoggerD("Enter");
232   using CKM::KeyType;
233
234   const std::string& alias = args.get("name").get<std::string>();
235   CKM::Password pass;
236   if (args.get("password").is<std::string>()) {
237     pass = args.get("password").get<std::string>().c_str();
238   }
239
240   CKM::KeyShPtr key;
241   int ret = CKM::Manager::create()->getKey(alias, pass, key);
242   if (ret != CKM_API_SUCCESS) {
243     LoggerE("Failed to get key: %d", ret);
244     if (ret == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
245       ReportError(common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
246         "Key alias not found"), &out);
247     } else {
248       ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
249         "Failed to get key"), &out);
250     }
251   } else {
252     picojson::object dict;
253     dict["name"] = args.get("name");
254     if (args.get("password").is<std::string>()) {
255       dict["password"] = args.get("password");
256     }
257     switch (key->getType()) {
258       case KeyType::KEY_NONE:
259         dict["keyType"] = picojson::value("KEY_NONE");
260         break;
261       case KeyType::KEY_RSA_PUBLIC:
262         dict["keyType"] = picojson::value("KEY_RSA_PUBLIC");
263         break;
264       case KeyType::KEY_RSA_PRIVATE:
265         dict["keyType"] = picojson::value("KEY_RSA_PRIVATE");
266         break;
267       case KeyType::KEY_ECDSA_PUBLIC:
268         dict["keyType"] = picojson::value("KEY_ECDSA_PUBLIC");
269         break;
270       case KeyType::KEY_ECDSA_PRIVATE:
271         dict["keyType"] = picojson::value("KEY_ECDSA_PRIVATE");
272         break;
273       case KeyType::KEY_DSA_PUBLIC:
274         dict["keyType"] = picojson::value("KEY_DSA_PUBLIC");
275         break;
276       case KeyType::KEY_DSA_PRIVATE:
277         dict["keyType"] = picojson::value("KEY_DSA_PRIVATE");
278         break;
279       case KeyType::KEY_AES:
280         dict["keyType"] = picojson::value("KEY_AES");
281         break;
282     }
283     dict["rawKey"] = picojson::value(RawBufferToBase64(key->getDER()));
284     //if key was retrieved it is extractable from db
285     dict["extractable"] = picojson::value(true);
286
287     picojson::value res(dict);
288     ReportSuccess(res, out);
289   }
290 }
291
292 void KeyManagerInstance::GetCertificate(const picojson::value& args,
293     picojson::object& out) {
294   LoggerD("Enter");
295
296   CKM::Password pass;
297   if (args.get("password").is<std::string>()) {
298     pass = args.get("password").get<std::string>().c_str();
299   }
300   const std::string& alias = args.get("name").get<std::string>();
301   CKM::CertificateShPtr cert;
302   int ret = CKM::Manager::create()->getCertificate(alias, pass, cert);
303   if (ret != CKM_API_SUCCESS) {
304     LoggerE("Failed to get cert: %d", ret);
305     if (ret == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
306       ReportError(common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
307         "Cert alias not found"), &out);
308     } else {
309       ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
310         "Failed to get cert"), &out);
311     }
312   } else {
313     picojson::object dict;
314     dict["name"] = args.get("name");
315     if (args.get("password").is<std::string>()) {
316       dict["password"] = args.get("password");
317     }
318     //if cert was retrieved it is extractable from db
319     dict["extractable"] = picojson::value(true);
320     dict["rawCert"] = picojson::value(RawBufferToBase64(cert->getDER()));
321
322     picojson::value res(dict);
323     ReportSuccess(res, out);
324   }
325 }
326
327 void KeyManagerInstance::SaveCertificate(const picojson::value& args,
328     picojson::object& out) {
329   LoggerD("Enter");
330
331   const picojson::value& crt = args.get("certificate");
332   const std::string& alias = crt.get("name").get<std::string>();
333   std::string password;
334   if (crt.get("password").is<std::string>()) {
335     password = crt.get("password").get<std::string>();
336   }
337   std::string base64 = args.get("rawCert").get<std::string>();
338   pcrecpp::RE_Options opt;
339   opt.set_multiline(true);
340   //remove first line and last line
341   pcrecpp::RE("-----[^-]*-----", opt).GlobalReplace("", &base64);
342   gsize len = 0;
343   guchar* rawData = g_base64_decode(base64.c_str(), &len);
344   CKM::RawBuffer rawBuffer;
345   rawBuffer.assign(rawData, rawData + len);
346   g_free(rawData);
347   CKM::Password pass(password.c_str());
348   CKM::CertificateShPtr cert = CKM::Certificate::create(rawBuffer,
349       CKM::DataFormat::FORM_DER);
350   CKM::Policy policy(pass, crt.get("extractable").get<bool>());
351   CKM::ManagerAsync::ObserverPtr observer(new SaveCertObserver(this,
352     args.get("callbackId").get<double>()));
353   m_manager.saveCertificate(observer, alias, cert, policy);
354
355   ReportSuccess(out);
356 }
357
358 void KeyManagerInstance::OnSaveCert(double callbackId,
359     const common::PlatformResult& result) {
360   LoggerD("Enter");
361   picojson::value::object dict;
362   dict["callbackId"] = picojson::value(callbackId);
363   if (result.IsError()) {
364     LoggerE("There was an error");
365     ReportError(result, &dict);
366   }
367   picojson::value res(dict);
368   PostMessage(res.serialize().c_str());
369 }
370
371 } // namespace keymanager
372 } // namespace extension