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