/* * Copyright 2020 Toyota Connected North America * * 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 "secure_storage.h" #include #include "engine.h" #include "logging.h" static SecureStorage* pInstance_; static std::mutex mutex_; void SecureStorage::deleteIt(const char* key) { GetInstance("keyring")->keyring_.deleteItem(key); } void SecureStorage::deleteAll() { GetInstance("keyring")->keyring_.deleteKeyring(); } void SecureStorage::write(const char* key, const char* value) { GetInstance("keyring")->keyring_.addItem(key, value); } flutter::EncodableValue SecureStorage::read(const char* key) { auto str = GetInstance("keyring")->keyring_.getItem(key); if (str.empty()) { return flutter::EncodableValue(); } return flutter::EncodableValue(str); } flutter::EncodableValue SecureStorage::readAll() { auto result = flutter::EncodableMap{}; auto document = GetInstance("keyring")->keyring_.readFromKeyring(); if (document.IsObject()) { for (rapidjson::Value::ConstMemberIterator itr = document.MemberBegin(); itr != document.MemberEnd(); ++itr) { result.emplace(flutter::EncodableValue(itr->name.GetString()), flutter::EncodableValue(itr->value.GetString())); } } return flutter::EncodableValue(result); } flutter::EncodableValue SecureStorage::containsKey(const char* key) { auto document = GetInstance("keyring")->keyring_.readFromKeyring(); return flutter::EncodableValue(document.HasMember(key)); } void SecureStorage::OnPlatformMessage(const FlutterPlatformMessage* message, void* userdata) { std::unique_ptr> result; auto engine = reinterpret_cast(userdata); auto& codec = flutter::StandardMethodCodec::GetInstance(); auto obj = codec.DecodeMethodCall(message->message, message->message_size); auto method = obj->method_name(); if (obj->arguments()->IsNull()) { result = codec.EncodeErrorEnvelope("argument_error", "Invalid Arguments"); engine->SendPlatformMessageResponse(message->response_handle, result->data(), result->size()); return; } auto args = std::get_if(obj->arguments()); std::string keyString; auto it = args->find(flutter::EncodableValue(kKey)); if (it != args->end() && !it->second.IsNull()) { keyString = std::get(it->second); } std::string valueString; it = args->find(flutter::EncodableValue(kValue)); if (it != args->end() && !it->second.IsNull()) { valueString = std::get(it->second); } if (method == kWrite) { SPDLOG_DEBUG("secure_storage: [Write] key: {}, value: {}", keyString, valueString); write(keyString.c_str(), valueString.c_str()); auto val = flutter::EncodableValue(true); result = codec.EncodeSuccessEnvelope(&val); } else if (method == kRead) { SPDLOG_DEBUG("secure_storage: [Read] key: {}", keyString); auto val = read(keyString.c_str()); result = codec.EncodeSuccessEnvelope(&val); } else if (method == kReadAll) { SPDLOG_DEBUG("secure_storage: [ReadAll]"); auto val = readAll(); result = codec.EncodeSuccessEnvelope(&val); } else if (method == kDelete) { SPDLOG_DEBUG("secure_storage: [Delete]"); deleteIt(keyString.c_str()); auto val = flutter::EncodableValue(true); result = codec.EncodeSuccessEnvelope(&val); } else if (method == kDeleteAll) { SPDLOG_DEBUG("secure_storage: [DeleteAll]"); deleteAll(); auto val = flutter::EncodableValue(true); result = codec.EncodeSuccessEnvelope(&val); } else if (method == kContainsKey) { SPDLOG_DEBUG("secure_storage: [ContainsKey]"); auto val = containsKey(keyString.c_str()); result = codec.EncodeSuccessEnvelope(&val); } else { spdlog::error("secure_storage: {} is unhandled", method); result = codec.EncodeErrorEnvelope("unhandled_method", "Unhandled Method"); } engine->SendPlatformMessageResponse(message->response_handle, result->data(), result->size()); } SecureStorage* SecureStorage::GetInstance(const std::string& value) { std::lock_guard lock(mutex_); if (pInstance_ == nullptr) { pInstance_ = new SecureStorage(value); } return pInstance_; }