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