1 //
2 // Copyright (C) 2023 The Android Open Source Project
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 #include "host/commands/secure_env/storage/insecure_json_storage.h"
17 
18 #include <fstream>
19 
20 #include <android-base/file.h>
21 #include <json/json.h>
22 
23 #include "common/libs/utils/base64.h"
24 #include "common/libs/utils/files.h"
25 #include "common/libs/utils/json.h"
26 
27 namespace cuttlefish {
28 namespace secure_env {
29 namespace {
30 
ReadJson(const std::string & path)31 Result<Json::Value> ReadJson(const std::string& path) {
32   std::string json;
33   CF_EXPECT(android::base::ReadFileToString(path, &json));
34   return CF_EXPECT(ParseJson(json));
35 }
36 
WriteJson(const std::string & path,const Json::Value & root)37 Result<void> WriteJson(const std::string& path, const Json::Value& root) {
38   Json::StreamWriterBuilder builder;
39   auto json = Json::writeString(builder, root);
40   CF_EXPECT(android::base::WriteStringToFile(json, path));
41   return {};
42 }
43 
44 } // namespace
45 
InsecureJsonStorage(std::string path)46 InsecureJsonStorage::InsecureJsonStorage(std::string path) : path_(std::move(path)) {}
47 
Exists() const48 bool InsecureJsonStorage::Exists() const {
49   return ReadJson(path_).ok();
50 }
51 
HasKey(const std::string & key) const52 Result<bool> InsecureJsonStorage::HasKey(const std::string& key) const {
53   if (!FileHasContent(path_)) {
54     return false;
55   }
56   return CF_EXPECT(ReadJson(path_)).isMember(key);
57 }
58 
Read(const std::string & key) const59 Result<ManagedStorageData> InsecureJsonStorage::Read(const std::string& key) const {
60   auto root = CF_EXPECT(ReadJson(path_));
61   CF_EXPECT(root.isMember(key), "Key: " << key << " not found in " << path_);
62 
63   std::vector<uint8_t> base64_buffer;
64   CF_EXPECT(DecodeBase64(root[key].asString(), &base64_buffer),
65             "Failed to decode base64 to read key: " << key);
66   auto storage_data = CF_EXPECT(CreateStorageData(base64_buffer.size()));
67   std::memcpy(storage_data->payload, reinterpret_cast<unsigned char *>(base64_buffer.data()),
68               base64_buffer.size());
69   return storage_data;
70 }
71 
Write(const std::string & key,const StorageData & data)72 Result<void> InsecureJsonStorage::Write(const std::string& key, const StorageData& data) {
73   Json::Value root;
74   if (FileHasContent(path_)) {
75     root = CF_EXPECT(ReadJson(path_));
76   }
77 
78   std::string value_base64;
79   CF_EXPECT(EncodeBase64(data.payload, data.size, &value_base64),
80             "Failed to encode base64 to write key: " << key);
81   root[key] = value_base64;
82 
83   CF_EXPECT(WriteJson(path_, root));
84   return {};
85 }
86 
87 }  // namespace oemlock
88 }  // namespace cuttlefish
89