// // Copyright (C) 2020 The Android Open Source Project // // 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 "host/commands/secure_env/insecure_fallback_storage.h" #include #include #include #include "host/commands/secure_env/json_serializable.h" #include "host/commands/secure_env/tpm_random_source.h" static constexpr char kEntries[] = "entries"; static constexpr char kKey[] = "key"; static constexpr char kValue[] = "value"; InsecureFallbackStorage::InsecureFallbackStorage( TpmResourceManager& resource_manager, const std::string& index_file) : resource_manager_(resource_manager), index_file_(index_file) { index_ = ReadProtectedJsonFromFile(resource_manager_, index_file); if (!index_.isMember(kEntries) || index_[kEntries].type() != Json::arrayValue) { if (index_.empty()) { LOG(DEBUG) << "Initializing secure index file"; } else { LOG(WARNING) << "Index file missing entries, likely corrupted."; } index_[kEntries] = Json::Value(Json::arrayValue); } else { LOG(DEBUG) << "Restoring index from file"; } } bool InsecureFallbackStorage::Allocate(const Json::Value& key, uint16_t size) { if (HasKey(key)) { LOG(WARNING) << "Key " << key << " is already defined."; return false; } if (size > sizeof(((TPM2B_MAX_NV_BUFFER*)nullptr)->buffer)) { LOG(ERROR) << "Size " << size << " was too large."; return false; } Json::Value entry(Json::objectValue); entry[kKey] = key; Json::Value value(Json::arrayValue); for (int i = 0; i < size; i++) { value.append(0); } entry[kValue] = value; index_[kEntries].append(entry); if (!WriteProtectedJsonToFile(resource_manager_, index_file_, index_)) { LOG(ERROR) << "Failed to save changes to " << index_file_; return false; } return true; } const Json::Value* InsecureFallbackStorage::GetEntry( const Json::Value& key) const { for (auto& entry : index_[kEntries]) { if (!entry.isMember(kKey)) { LOG(WARNING) << "Index was corrupted"; return nullptr; } if (entry[kKey] != key) { continue; } if (!entry.isMember(kValue) || entry[kValue].type() != Json::arrayValue) { LOG(WARNING) << "Index was corrupted"; return nullptr; } return &entry; } return nullptr; } Json::Value* InsecureFallbackStorage::GetEntry(const Json::Value& key) { return const_cast( static_cast(*this).GetEntry(key)); } bool InsecureFallbackStorage::HasKey(const Json::Value& key) const { return static_cast(GetEntry(key)); } std::unique_ptr InsecureFallbackStorage::Read( const Json::Value& key) const { auto entry = GetEntry(key); if (!entry) { LOG(WARNING) << "Could not read from " << key; return {}; } const auto& value = (*entry)[kValue]; if (value.type() != Json::arrayValue) { LOG(WARNING) << "Index was corrupted"; return {}; } auto ret = std::make_unique(); if (value.size() > sizeof(ret->buffer)) { LOG(ERROR) << "Index was corrupted: size of data was too large"; return {}; } ret->size = value.size(); for (unsigned int i = 0; i < value.size(); i++) { ret->buffer[i] = value[i].asUInt(); } return ret; } bool InsecureFallbackStorage::Write( const Json::Value& key, const TPM2B_MAX_NV_BUFFER& data) { auto entry = GetEntry(key); if (!entry) { LOG(WARNING) << "Could not read from " << key; return false; } auto& value = (*entry)[kValue]; if (value.type() != Json::arrayValue) { LOG(WARNING) << "Index was corrupted"; return false; } if (data.size != value.size()) { LOG(ERROR) << "Size of data given was incorrect"; return false; }; for (unsigned int i = 0; i < value.size(); i++) { value[i] = data.buffer[i]; } if (!WriteProtectedJsonToFile(resource_manager_, index_file_, index_)) { LOG(ERROR) << "Failed to save changes to " << index_file_; return false; } return true; }