1 //
2 // Copyright (C) 2020 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/insecure_fallback_storage.h"
17
18 #include <fstream>
19
20 #include <android-base/logging.h>
21 #include <tss2/tss2_rc.h>
22
23 #include "host/commands/secure_env/json_serializable.h"
24 #include "host/commands/secure_env/tpm_random_source.h"
25
26 static constexpr char kEntries[] = "entries";
27 static constexpr char kKey[] = "key";
28 static constexpr char kValue[] = "value";
29
InsecureFallbackStorage(TpmResourceManager & resource_manager,const std::string & index_file)30 InsecureFallbackStorage::InsecureFallbackStorage(
31 TpmResourceManager& resource_manager, const std::string& index_file)
32 : resource_manager_(resource_manager), index_file_(index_file) {
33 index_ = ReadProtectedJsonFromFile(resource_manager_, index_file);
34 if (!index_.isMember(kEntries)
35 || index_[kEntries].type() != Json::arrayValue) {
36 if (index_.empty()) {
37 LOG(DEBUG) << "Initializing secure index file";
38 } else {
39 LOG(WARNING) << "Index file missing entries, likely corrupted.";
40 }
41 index_[kEntries] = Json::Value(Json::arrayValue);
42 } else {
43 LOG(DEBUG) << "Restoring index from file";
44 }
45 }
46
Allocate(const Json::Value & key,uint16_t size)47 bool InsecureFallbackStorage::Allocate(const Json::Value& key, uint16_t size) {
48 if (HasKey(key)) {
49 LOG(WARNING) << "Key " << key << " is already defined.";
50 return false;
51 }
52 if (size > sizeof(((TPM2B_MAX_NV_BUFFER*)nullptr)->buffer)) {
53 LOG(ERROR) << "Size " << size << " was too large.";
54 return false;
55 }
56 Json::Value entry(Json::objectValue);
57 entry[kKey] = key;
58 Json::Value value(Json::arrayValue);
59 for (int i = 0; i < size; i++) {
60 value.append(0);
61 }
62 entry[kValue] = value;
63 index_[kEntries].append(entry);
64
65 if (!WriteProtectedJsonToFile(resource_manager_, index_file_, index_)) {
66 LOG(ERROR) << "Failed to save changes to " << index_file_;
67 return false;
68 }
69 return true;
70 }
71
GetEntry(const Json::Value & key) const72 const Json::Value* InsecureFallbackStorage::GetEntry(
73 const Json::Value& key) const {
74 for (auto& entry : index_[kEntries]) {
75 if (!entry.isMember(kKey)) {
76 LOG(WARNING) << "Index was corrupted";
77 return nullptr;
78 }
79 if (entry[kKey] != key) {
80 continue;
81 }
82 if (!entry.isMember(kValue) || entry[kValue].type() != Json::arrayValue) {
83 LOG(WARNING) << "Index was corrupted";
84 return nullptr;
85 }
86 return &entry;
87 }
88 return nullptr;
89 }
90
GetEntry(const Json::Value & key)91 Json::Value* InsecureFallbackStorage::GetEntry(const Json::Value& key) {
92 return const_cast<Json::Value*>(
93 static_cast<const InsecureFallbackStorage&>(*this).GetEntry(key));
94 }
95
HasKey(const Json::Value & key) const96 bool InsecureFallbackStorage::HasKey(const Json::Value& key) const {
97 return static_cast<bool>(GetEntry(key));
98 }
99
Read(const Json::Value & key) const100 std::unique_ptr<TPM2B_MAX_NV_BUFFER> InsecureFallbackStorage::Read(
101 const Json::Value& key) const {
102 auto entry = GetEntry(key);
103 if (!entry) {
104 LOG(WARNING) << "Could not read from " << key;
105 return {};
106 }
107 const auto& value = (*entry)[kValue];
108 if (value.type() != Json::arrayValue) {
109 LOG(WARNING) << "Index was corrupted";
110 return {};
111 }
112 auto ret = std::make_unique<TPM2B_MAX_NV_BUFFER>();
113 if (value.size() > sizeof(ret->buffer)) {
114 LOG(ERROR) << "Index was corrupted: size of data was too large";
115 return {};
116 }
117 ret->size = value.size();
118 for (unsigned int i = 0; i < value.size(); i++) {
119 ret->buffer[i] = value[i].asUInt();
120 }
121 return ret;
122 }
123
Write(const Json::Value & key,const TPM2B_MAX_NV_BUFFER & data)124 bool InsecureFallbackStorage::Write(
125 const Json::Value& key, const TPM2B_MAX_NV_BUFFER& data) {
126 auto entry = GetEntry(key);
127 if (!entry) {
128 LOG(WARNING) << "Could not read from " << key;
129 return false;
130 }
131 auto& value = (*entry)[kValue];
132 if (value.type() != Json::arrayValue) {
133 LOG(WARNING) << "Index was corrupted";
134 return false;
135 }
136 if (data.size != value.size()) {
137 LOG(ERROR) << "Size of data given was incorrect";
138 return false;
139 };
140 for (unsigned int i = 0; i < value.size(); i++) {
141 value[i] = data.buffer[i];
142 }
143
144 if (!WriteProtectedJsonToFile(resource_manager_, index_file_, index_)) {
145 LOG(ERROR) << "Failed to save changes to " << index_file_;
146 return false;
147 }
148 return true;
149 }
150