-// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "keymanager/keymanager_instance.h"
-#include <functional>
-#include <ckm/ckm-manager.h>
+#include <ckmc/ckmc-manager.h>
#include <glib.h>
-#include <pcrecpp.h>
-#include <fstream>
+#include <pkgmgr-info.h>
#include "common/logger.h"
-#include "common/picojson.h"
+#include "common/optional.h"
#include "common/platform_result.h"
+#include "common/scope_exit.h"
+#include "common/task-queue.h"
+#include "common/tools.h"
+#include "common/current_application.h"
namespace extension {
namespace keymanager {
+using common::ErrorCode;
+using common::optional;
+using common::PlatformResult;
+using common::TaskQueue;
+
namespace {
-const char* kTypeRSA = "RSA";
-const char* kTypeECDSA = "ECDSA";
+
+typedef std::vector<unsigned char> RawBuffer;
+
+typedef int (*AliasListFunction)(ckmc_alias_list_s**);
+
+void GetGenericAliasList(AliasListFunction func, picojson::object* out) {
+ LoggerD("Enter");
+
+ ckmc_alias_list_s* alias_list = nullptr;
+ int ret = func(&alias_list);
+
+ picojson::value result{picojson::array{}};
+
+ if (CKMC_ERROR_NONE == ret) {
+ auto& aliases = result.get<picojson::array>();
+
+ picojson::value resultElem = picojson::value(picojson::object());
+ picojson::object& obj = resultElem.get<picojson::object>();
+ ckmc_alias_list_s* head = alias_list;
+
+ while (head) {
+ //aliases.push_back(picojson::value(head->alias ? head->alias : ""));
+ if(head->alias) {
+ char* tokenized = strtok(head->alias," ");
+ obj["packageId"] = picojson::value(tokenized);
+ tokenized = strtok(NULL," ");
+ obj["name"] = picojson::value(tokenized);
+
+ aliases.push_back(resultElem);
+ }
+
+ head = head->next;
+ }
+
+ if (alias_list) {
+ ckmc_alias_list_all_free(alias_list);
+ }
+ }
+
+ common::tools::ReportSuccess(result, *out);
}
+} // namespace
KeyManagerInstance::KeyManagerInstance() {
+ LoggerD("Enter");
using std::placeholders::_1;
using std::placeholders::_2;
- RegisterSyncHandler("KeyManager_getKeyAliasList",
- std::bind(&KeyManagerInstance::GetKeyAliasList, this, _1, _2));
- RegisterSyncHandler("KeyManager_getCertificatesAliasList",
- std::bind(&KeyManagerInstance::GetCertificateAliasList, this, _1, _2));
RegisterSyncHandler("KeyManager_getDataAliasList",
std::bind(&KeyManagerInstance::GetDataAliasList, this, _1, _2));
- RegisterSyncHandler("KeyManager_getKey",
- std::bind(&KeyManagerInstance::GetKey, this, _1, _2));
- RegisterSyncHandler("KeyManager_saveKey",
- std::bind(&KeyManagerInstance::SaveKey, this, _1, _2));
- RegisterSyncHandler("KeyManager_removeKey",
- std::bind(&KeyManagerInstance::RemoveKey, this, _1, _2));
- RegisterSyncHandler("KeyManager_generateKeyPair",
- std::bind(&KeyManagerInstance::GenerateKeyPair, this, _1, _2));
- RegisterSyncHandler("KeyManager_getCertificate",
- std::bind(&KeyManagerInstance::GetCertificate, this, _1, _2));
- RegisterSyncHandler("KeyManager_saveCertificate",
- std::bind(&KeyManagerInstance::SaveCertificate, this, _1, _2));
- RegisterSyncHandler("KeyManager_loadCertificateFromFile",
- std::bind(&KeyManagerInstance::LoadCertificateFromFile, this, _1, _2));
-}
-KeyManagerInstance::~KeyManagerInstance() {
-}
+ RegisterSyncHandler("KeyManager_saveData",
+ std::bind(&KeyManagerInstance::SaveData, this, _1, _2));
-void KeyManagerInstance::GetAliasList(
- std::function<int(CKM::AliasVector&)> coreFunc, picojson::object& out) {
- LoggerD("Enter");
- CKM::AliasVector result;
- int ret = coreFunc(result);
- if (ret != CKM_API_SUCCESS) {
- LoggerE("Failed to fetch list of alias: %d", ret);
- ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
- "Failed to fetch list of alias"), &out);
- } else {
- picojson::array aliases;
- for (auto& item: result) {
- aliases.push_back(picojson::value(item));
- }
- picojson::value res(aliases);
- ReportSuccess(res, out);
- }
-}
+ RegisterSyncHandler("KeyManager_getData",
+ std::bind(&KeyManagerInstance::GetData, this, _1, _2));
-void KeyManagerInstance::GetKeyAliasList(const picojson::value& args,
- picojson::object& out) {
- LoggerD("Enter");
- using std::placeholders::_1;
- GetAliasList(
- std::bind(&CKM::Manager::getKeyAliasVector, CKM::Manager::create(), _1),
- out);
-}
+ RegisterSyncHandler("KeyManager_removeAlias",
+ std::bind(&KeyManagerInstance::RemoveAlias, this, _1, _2));
-void KeyManagerInstance::GetCertificateAliasList(const picojson::value& args,
- picojson::object& out) {
- LoggerD("Enter");
- using std::placeholders::_1;
- GetAliasList(
- std::bind(&CKM::Manager::getCertificateAliasVector, CKM::Manager::create(), _1),
- out);
+ RegisterSyncHandler("KeyManager_setPermissions",
+ std::bind(&KeyManagerInstance::SetPermission, this, _1, _2));
}
void KeyManagerInstance::GetDataAliasList(const picojson::value& args,
- picojson::object& out) {
+ picojson::object& out) {
LoggerD("Enter");
- using std::placeholders::_1;
- GetAliasList(
- std::bind(&CKM::Manager::getDataAliasVector, CKM::Manager::create(), _1),
- out);
+ GetGenericAliasList(ckmc_get_data_alias_list, &out);
}
-void KeyManagerInstance::SaveKey(const picojson::value& args,
- picojson::object& out) {
- LoggerD("Enter");
-
- const picojson::value& key_object = args.get("key");
- const std::string& alias = key_object.get("name").get<std::string>();
- std::string password;
- if (key_object.get("password").is<std::string>()) {
- password = key_object.get("password").get<std::string>();
+PlatformResult KeyManagerInstance::GetError(int ret) {
+ char* error = get_error_message(ret);
+ if(CKMC_ERROR_NONE == ret) {
+ return PlatformResult(ErrorCode::NO_ERROR);
}
- std::string base64 = args.get("rawKey").get<std::string>();
- pcrecpp::RE_Options opt;
- opt.set_multiline(true);
- //remove first line and last line
- pcrecpp::RE("-----[^-]*-----", opt).GlobalReplace("", &base64);
- gsize len = 0;
- guchar* raw_data = g_base64_decode(base64.c_str(), &len);
- CKM::RawBuffer raw_buffer;
- raw_buffer.assign(raw_data, raw_data + len);
- g_free(raw_data);
- CKM::Password pass(password.c_str());
- CKM::KeyShPtr key = CKM::Key::create(raw_buffer, pass);
- CKM::Policy policy(pass, key_object.get("extractable").get<bool>());
- CKM::ManagerAsync::ObserverPtr observer(new SaveKeyObserver(this,
- args.get("callbackId").get<double>()));
- m_manager.saveKey(observer, alias, key, policy);
-
- ReportSuccess(out);
-}
-
-void KeyManagerInstance::OnSaveKey(double callbackId,
- const common::PlatformResult& result) {
- LoggerD("Enter");
- picojson::value::object dict;
- dict["callbackId"] = picojson::value(callbackId);
- if (result.IsError()) {
- LoggerE("There was an error");
- ReportError(result, &dict);
+ else if(CKMC_ERROR_INVALID_PARAMETER == ret) {
+ LoggerD("%s", error);
+ return PlatformResult(ErrorCode::INVALID_VALUES_ERR, error);
+ }
+ else if(CKMC_ERROR_DB_ALIAS_UNKNOWN == ret) {
+ LoggerD("%s",error);
+ return PlatformResult(ErrorCode::NOT_FOUND_ERR, error);
+ }
+ else if(CKMC_ERROR_AUTHENTICATION_FAILED == ret) {
+ LoggerD("%s",error);
+ return PlatformResult(ErrorCode::VERIFICATION_ERR, error);
+ }
+ else {
+ LoggerD("%s", error);
+ return PlatformResult(ErrorCode::UNKNOWN_ERR, error);
}
- picojson::value res(dict);
- PostMessage(res.serialize().c_str());
}
-void KeyManagerInstance::RemoveKey(const picojson::value& args,
- picojson::object& out) {
+void KeyManagerInstance::SaveData(const picojson::value& args,
+ picojson::object& out) {
LoggerD("Enter");
- const std::string& alias = args.get("key").get("name").get<std::string>();
- int ret = CKM::Manager::create()->removeAlias(alias);
- if (ret != CKM_API_SUCCESS) {
- LoggerE("Failed to remove key alias: %d", ret);
- if (ret == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
- ReportError(common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
- "Key alias not found"), &out);
- } else {
- ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
- "Failed to remove key alias"), &out);
- }
- } else {
- ReportSuccess(out);
+ std::string data_raw = args.get("rawData").get<std::string>();
+ std::string alias = args.get("aliasName").get<std::string>();
+ const auto& password_value = args.get("password");
+
+ double callback_id = args.get("callbackId").get<double>();
+
+ const char* password = nullptr;
+
+ if (password_value.is<std::string>()) {
+ password = (password_value.get<std::string>()).c_str();
+ LoggerE("password %s ", password);
}
-}
-void KeyManagerInstance::GenerateKeyPair(const picojson::value& args,
- picojson::object& out) {
- LoggerD("Enter");
+ auto save_data = [data_raw, password, alias](const std::shared_ptr<picojson::value>& result) {
- const picojson::value& priv_key = args.get("privKeyName");
- const picojson::value& pub_key = args.get("pubKeyName");
- const std::string& priv_name = priv_key.get("name").get<std::string>();
- const std::string& pub_name = pub_key.get("name").get<std::string>();
- const std::string& type = args.get("type").get<std::string>();
- int size = std::stoi(args.get("size").get<std::string>());
+ unsigned char* data = new unsigned char[data_raw.size()];
+ std::copy(data_raw.begin(), data_raw.end(), data);
- CKM::ManagerAsync::ObserverPtr observer(new CreateKeyObserver(this,
- args.get("callbackId").get<double>()));
+ ckmc_raw_buffer_s raw_data { data, data_raw.size() };
+ ckmc_policy_s policy { const_cast<char*>(password), true };
- CKM::Password pass;
- if (priv_key.get("password").is<std::string>()) {
- pass = priv_key.get("password").get<std::string>().c_str();
- }
- CKM::Policy priv_policy(pass, priv_key.get("extractable").get<bool>());
+ int ret = ckmc_save_data(alias.c_str(), raw_data, policy);
- if (pub_key.get("password").is<std::string>()) {
- pass = pub_key.get("password").get<std::string>().c_str();
- } else {
- pass = "";
- }
- CKM::Policy pub_policy(pass, pub_key.get("extractable").get<bool>());
-
- if (type == kTypeRSA) {
- m_manager.createKeyPairRSA(observer, size, priv_name, pub_name, priv_policy, pub_policy);
- } else if (type == kTypeECDSA) {
- CKM::ElipticCurve eliptic = CKM::ElipticCurve::prime192v1;
- if (args.get("ellipticCurveType").is<std::string>()) {
- const std::string& eType = args.get("ellipticCurveType").get<std::string>();
- if (eType == "PRIME256V1") {
- eliptic = CKM::ElipticCurve::prime256v1;
- } else if (eType == "EC_SECP384R1") {
- eliptic = CKM::ElipticCurve::secp384r1;
- }
+ PlatformResult success = GetError(ret);
+
+ if (success) {
+ common::tools::ReportSuccess(result->get<picojson::object>());
+ } else {
+ LoggerE("Failed to save data: %d", ret);
+ common::tools::ReportError(success, &result->get<picojson::object>());
}
- m_manager.createKeyPairECDSA(observer, eliptic, priv_name, pub_name, priv_policy, pub_policy);
- } else {
- m_manager.createKeyPairDSA(observer, size, priv_name, pub_name, priv_policy, pub_policy);
- }
+
+ delete[] data;
+ };
+
+ auto save_data_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
+ result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
+ Instance::PostMessage(this, result->serialize().c_str());
+ };
+
+ auto queue_data = std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+ TaskQueue::GetInstance().Queue<picojson::value>(
+ save_data,
+ save_data_result,
+ queue_data);
ReportSuccess(out);
}
-void KeyManagerInstance::OnCreateKeyPair(double callbackId,
- const common::PlatformResult& result) {
+void KeyManagerInstance::GetData(const picojson::value& args,
+ picojson::object& out) {
LoggerD("Enter");
- picojson::value::object dict;
- dict["callbackId"] = picojson::value(callbackId);
- if (result.IsError()) {
- LoggerE("There was an error");
- ReportError(result, &dict);
- }
- picojson::value res(dict);
- PostMessage(res.serialize().c_str());
-}
-std::string RawBufferToBase64(const CKM::RawBuffer &buf) {
- std::string result;
- if (!buf.empty()) {
- gchar* base64 = g_base64_encode(&buf[0], buf.size());
- result = base64;
- g_free(base64);
- }
- return result;
-}
+ const auto& data_alias = args.get("name").get<std::string>();
+ const auto& password_value = args.get("password");
-void KeyManagerInstance::GetKey(const picojson::value& args, picojson::object& out) {
- LoggerD("Enter");
- using CKM::KeyType;
+ const char* password = nullptr;
- const std::string& alias = args.get("name").get<std::string>();
- CKM::Password pass;
- if (args.get("password").is<std::string>()) {
- pass = args.get("password").get<std::string>().c_str();
+ if (password_value.is<std::string>()) {
+ password = (password_value.get<std::string>()).c_str();
}
- CKM::KeyShPtr key;
- int ret = CKM::Manager::create()->getKey(alias, pass, key);
- if (ret != CKM_API_SUCCESS) {
- LoggerE("Failed to get key: %d", ret);
- if (ret == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
- ReportError(common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
- "Key alias not found"), &out);
- } else {
- ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
- "Failed to get key"), &out);
- }
- } else {
- picojson::object dict;
- dict["name"] = args.get("name");
- if (args.get("password").is<std::string>()) {
- dict["password"] = args.get("password");
- }
- switch (key->getType()) {
- case KeyType::KEY_NONE:
- dict["keyType"] = picojson::value("KEY_NONE");
- break;
- case KeyType::KEY_RSA_PUBLIC:
- dict["keyType"] = picojson::value("KEY_RSA_PUBLIC");
- break;
- case KeyType::KEY_RSA_PRIVATE:
- dict["keyType"] = picojson::value("KEY_RSA_PRIVATE");
- break;
- case KeyType::KEY_ECDSA_PUBLIC:
- dict["keyType"] = picojson::value("KEY_ECDSA_PUBLIC");
- break;
- case KeyType::KEY_ECDSA_PRIVATE:
- dict["keyType"] = picojson::value("KEY_ECDSA_PRIVATE");
- break;
- case KeyType::KEY_DSA_PUBLIC:
- dict["keyType"] = picojson::value("KEY_DSA_PUBLIC");
- break;
- case KeyType::KEY_DSA_PRIVATE:
- dict["keyType"] = picojson::value("KEY_DSA_PRIVATE");
- break;
- case KeyType::KEY_AES:
- dict["keyType"] = picojson::value("KEY_AES");
- break;
- }
- dict["rawKey"] = picojson::value(RawBufferToBase64(key->getDER()));
- //if key was retrieved it is extractable from db
- dict["extractable"] = picojson::value(true);
+ LoggerD("data_alias: %s", data_alias.c_str());
- picojson::value res(dict);
- ReportSuccess(res, out);
- }
-}
+ ckmc_raw_buffer_s* data = nullptr;
+ int ret = ckmc_get_data(data_alias.c_str(), password, &data);
-void KeyManagerInstance::GetCertificate(const picojson::value& args,
- picojson::object& out) {
- LoggerD("Enter");
+ if (CKMC_ERROR_NONE == ret) {
+ picojson::object result;
- CKM::Password pass;
- if (args.get("password").is<std::string>()) {
- pass = args.get("password").get<std::string>().c_str();
- }
- const std::string& alias = args.get("name").get<std::string>();
- CKM::CertificateShPtr cert;
- int ret = CKM::Manager::create()->getCertificate(alias, pass, cert);
- if (ret != CKM_API_SUCCESS) {
- LoggerE("Failed to get cert: %d", ret);
- if (ret == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
- ReportError(common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
- "Cert alias not found"), &out);
- } else {
- ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
- "Failed to get cert"), &out);
- }
- } else {
- picojson::object dict;
- dict["name"] = args.get("name");
- if (args.get("password").is<std::string>()) {
- dict["password"] = args.get("password");
- }
- //if cert was retrieved it is extractable from db
- dict["extractable"] = picojson::value(true);
- dict["rawCert"] = picojson::value(RawBufferToBase64(cert->getDER()));
+ result["rawData"] = picojson::value(std::string (data->data, data->data + data->size));
- picojson::value res(dict);
- ReportSuccess(res, out);
- }
-}
+ ckmc_buffer_free(data);
+ ReportSuccess(picojson::value{result}, out);
+ } else {
+ LoggerE("Failed to get data: %d", ret);
-void KeyManagerInstance::SaveCertificate(const picojson::value& args,
- picojson::object& out) {
- LoggerD("Enter");
+ PlatformResult error = GetError(ret);
- const picojson::value& crt = args.get("certificate");
- const std::string& alias = crt.get("name").get<std::string>();
- std::string password;
- if (crt.get("password").is<std::string>()) {
- password = crt.get("password").get<std::string>();
+ ReportError(error, &out);
}
- std::string base64 = args.get("rawCert").get<std::string>();
-
- SaveCert(base64,
- password,
- alias,
- crt.get("extractable").get<bool>(),
- args.get("callbackId").get<double>());
- ReportSuccess(out);
}
-void KeyManagerInstance::SaveCert(std::string &base64,
- const std::string &password,
- const std::string &alias,
- bool extractable,
- double callbackId) {
+KeyManagerInstance::~KeyManagerInstance() {
LoggerD("Enter");
- pcrecpp::RE_Options opt;
- opt.set_multiline(true);
- //remove first line and last line
- pcrecpp::RE("-----[^-]*-----", opt).GlobalReplace("", &base64);
- gsize len = 0;
- guchar* rawData = g_base64_decode(base64.c_str(), &len);
- CKM::RawBuffer rawBuffer;
- rawBuffer.assign(rawData, rawData + len);
- g_free(rawData);
- CKM::Password pass(password.c_str());
- CKM::CertificateShPtr cert = CKM::Certificate::create(rawBuffer,
- CKM::DataFormat::FORM_DER);
- CKM::Policy policy(pass, extractable);
- CKM::ManagerAsync::ObserverPtr observer(new SaveCertObserver(this,
- callbackId));
- m_manager.saveCertificate(observer, alias, cert, policy);
}
-void KeyManagerInstance::OnSaveCert(double callbackId,
- const common::PlatformResult& result) {
+void KeyManagerInstance::RemoveAlias(const picojson::value& args,
+ picojson::object& out) {
LoggerD("Enter");
- picojson::value::object dict;
- dict["callbackId"] = picojson::value(callbackId);
- if (result.IsError()) {
- LoggerE("There was an error");
- ReportError(result, &dict);
+
+ const std::string& alias = args.get("aliasName").get<std::string>();
+ int ret = ckmc_remove_alias(alias.c_str());
+
+ if (CKMC_ERROR_NONE != ret) {
+ LoggerE("Failed to remove alias [%d]", ret);
+ PlatformResult result = GetError(ret);
+ ReportError(result, &out);
+ } else {
+ ReportSuccess(out);
}
- picojson::value res(dict);
- PostMessage(res.serialize().c_str());
}
-void KeyManagerInstance::LoadCertificateFromFile(const picojson::value& args,
- picojson::object& out) {
+void KeyManagerInstance::SetPermission(const picojson::value& args,
+ picojson::object& out) {
LoggerD("Enter");
- const picojson::value& crt = args.get("certificate");
- const std::string& file = args.get("fileURI").get<std::string>();
- std::string password;
- if (crt.get("password").is<std::string>()) {
- password = crt.get("password").get<std::string>();
+ const std::string& data_name = args.get("aliasName").get<std::string>();
+ const std::string& id = args.get("packageId").get<std::string>();
+ const double callback_id = args.get("callbackId").get<double>();
+ const std::string& access = args.get("permissionType").get<std::string>();
+
+ int permissions = CKMC_PERMISSION_NONE;
+ if( "NONE" == access) {
+ permissions = CKMC_PERMISSION_NONE;
+ }
+ else if ("READ" == access) {
+ permissions = CKMC_PERMISSION_READ;
+ }
+ else if ("REMOVE" == access) {
+ permissions = CKMC_PERMISSION_REMOVE;
+ }
+ else if("READ_REMOVE" == access) {
+ permissions = CKMC_PERMISSION_READ | CKMC_PERMISSION_REMOVE;
}
- LoadFileCert* reader = new LoadFileCert(this,
- args.get("callbackId").get<double>(),
- password,
- crt.get("name").get<std::string>(),
- crt.get("extractable").get<bool>());
- reader->LoadFileAsync(file);
- ReportSuccess(out);
-}
+ auto set_permissions = [data_name, id, permissions](const std::shared_ptr<picojson::value>& response) -> void {
+ int ret = ckmc_set_permission(data_name.c_str(), id.c_str(), permissions);
-void KeyManagerInstance::OnCertFileLoaded(LoadFileCert* reader,
- const common::PlatformResult& result) {
- LoggerD("Enter");
+ if (CKMC_ERROR_NONE != ret) {
+ PlatformResult result = GetError(ret);
+ common::tools::ReportError(result, &response->get<picojson::object>());
+ } else {
+ common::tools::ReportSuccess(response->get<picojson::object>());
+ }
+ };
- if (result.IsError()) {
- LoggerE("There was an error");
- picojson::value::object dict;
- dict["callbackId"] = picojson::value(reader->callbackId);
- ReportError(result, &dict);
- picojson::value res(dict);
- PostMessage(res.serialize().c_str());
- } else {
- SaveCert(reader->fileContent, reader->password, reader->alias,
- reader->extractable, reader->callbackId);
- }
- delete reader;
+ auto set_permissions_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+ picojson::object& obj = response->get<picojson::object>();
+ obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+ Instance::PostMessage(this, response->serialize().c_str());
+ };
+
+ auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+ TaskQueue::GetInstance().Queue<picojson::value>(
+ set_permissions,
+ set_permissions_response,
+ std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
}
} // namespace keymanager