diff options
Diffstat (limited to 'host')
-rw-r--r-- | host/commands/secure_env/Android.bp | 6 | ||||
-rw-r--r-- | host/commands/secure_env/storage/insecure_json_storage.cpp | 88 | ||||
-rw-r--r-- | host/commands/secure_env/storage/insecure_json_storage.h | 37 | ||||
-rw-r--r-- | host/commands/secure_env/storage/storage.cpp | 48 | ||||
-rw-r--r-- | host/commands/secure_env/storage/storage.h | 69 |
5 files changed, 248 insertions, 0 deletions
diff --git a/host/commands/secure_env/Android.bp b/host/commands/secure_env/Android.bp index 73d443b17..0bd3690b7 100644 --- a/host/commands/secure_env/Android.bp +++ b/host/commands/secure_env/Android.bp @@ -79,6 +79,7 @@ common_libsecure_srcs = [ "keymaster_responder.cpp", "oemlock_responder.cpp", "primary_key_builder.cpp", + "storage/storage.cpp", "tpm_attestation_record.cpp", "tpm_auth.cpp", "tpm_commands.cpp", @@ -95,11 +96,16 @@ common_libsecure_srcs = [ "tpm_serialize.cpp", ] +// Things blocking us to use oemlock on windows: +// 1. Missing transport implementation +// 2. Missing file utils +// 3. Base64 isn't supported (need for software oemlock implementation) cc_library_host_static { name: "libsecure_env_linux", srcs: common_libsecure_srcs + [ "confui_sign_server.cpp", "device_tpm.cpp", + "storage/insecure_json_storage.cpp", ], defaults: ["cuttlefish_buildhost_only", "secure_env_defaults"], } diff --git a/host/commands/secure_env/storage/insecure_json_storage.cpp b/host/commands/secure_env/storage/insecure_json_storage.cpp new file mode 100644 index 000000000..a85e7e427 --- /dev/null +++ b/host/commands/secure_env/storage/insecure_json_storage.cpp @@ -0,0 +1,88 @@ +// +// Copyright (C) 2023 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/storage/insecure_json_storage.h" + +#include <fstream> + +#include <android-base/file.h> +#include <json/json.h> + +#include "common/libs/utils/base64.h" +#include "common/libs/utils/files.h" +#include "common/libs/utils/json.h" + +namespace cuttlefish { +namespace secure_env { +namespace { + +Result<Json::Value> ReadJson(const std::string& path) { + std::string json; + CF_EXPECT(android::base::ReadFileToString(path, &json)); + return CF_EXPECT(ParseJson(json)); +} + +Result<void> WriteJson(const std::string& path, const Json::Value& root) { + Json::StreamWriterBuilder builder; + auto json = Json::writeString(builder, root); + CF_EXPECT(android::base::WriteStringToFile(json, path)); + return {}; +} + +} // namespace + +InsecureJsonStorage::InsecureJsonStorage(std::string path) : path_(std::move(path)) {} + +bool InsecureJsonStorage::Exists() const { + return ReadJson(path_).ok(); +} + +Result<bool> InsecureJsonStorage::HasKey(const std::string& key) const { + if (!FileHasContent(path_)) { + return false; + } + return CF_EXPECT(ReadJson(path_)).isMember(key); +} + +Result<ManagedStorageData> InsecureJsonStorage::Read(const std::string& key) const { + auto root = CF_EXPECT(ReadJson(path_)); + CF_EXPECT(root.isMember(key), "Key: " << key << " not found in " << path_); + + std::vector<uint8_t> base64_buffer; + CF_EXPECT(DecodeBase64(root[key].asString(), &base64_buffer), + "Failed to decode base64 to read key: " << key); + auto storage_data = CF_EXPECT(CreateStorageData(base64_buffer.size())); + std::memcpy(storage_data->payload, reinterpret_cast<unsigned char *>(base64_buffer.data()), + base64_buffer.size()); + return storage_data; +} + +Result<void> InsecureJsonStorage::Write(const std::string& key, const StorageData& data) { + Json::Value root; + if (FileHasContent(path_)) { + root = CF_EXPECT(ReadJson(path_)); + } + + std::string value_base64; + CF_EXPECT(EncodeBase64(data.payload, data.size, &value_base64), + "Failed to encode base64 to write key: " << key); + root[key] = value_base64; + + CF_EXPECT(WriteJson(path_, root)); + return {}; +} + +} // namespace oemlock +} // namespace cuttlefish diff --git a/host/commands/secure_env/storage/insecure_json_storage.h b/host/commands/secure_env/storage/insecure_json_storage.h new file mode 100644 index 000000000..f811774cd --- /dev/null +++ b/host/commands/secure_env/storage/insecure_json_storage.h @@ -0,0 +1,37 @@ +// +// Copyright (C) 2023 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. + +#pragma once + +#include "host/commands/secure_env/storage/storage.h" + +namespace cuttlefish { +namespace secure_env { + +class InsecureJsonStorage : public secure_env::Storage { + public: + InsecureJsonStorage(std::string path); + + Result<bool> HasKey(const std::string& key) const override; + Result<ManagedStorageData> Read(const std::string& key) const override; + Result<void> Write(const std::string& key, const StorageData& data) override; + bool Exists() const override; + + private: + std::string path_; +}; + +} // namespace secure_env +} // namespace cuttlefish diff --git a/host/commands/secure_env/storage/storage.cpp b/host/commands/secure_env/storage/storage.cpp new file mode 100644 index 000000000..5c7cb2f11 --- /dev/null +++ b/host/commands/secure_env/storage/storage.cpp @@ -0,0 +1,48 @@ +/* + * Copyright 2023 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/storage/storage.h" + +#include "keymaster/android_keymaster_utils.h" + +namespace cuttlefish { +namespace secure_env { + +void StorageDataDestroyer::operator()(StorageData* ptr) { + { + keymaster::Eraser(ptr, sizeof(StorageData) + ptr->size); + } + std::free(ptr); +} + +Result<ManagedStorageData> CreateStorageData(size_t size) { + const auto bytes_to_allocate = sizeof(StorageData) + size; + auto memory = std::malloc(bytes_to_allocate); + CF_EXPECT(memory != nullptr, + "Cannot allocate " << bytes_to_allocate << " bytes for storage data"); + auto data = reinterpret_cast<StorageData*>(memory); + data->size = size; + return ManagedStorageData(data); +} + +Result<ManagedStorageData> CreateStorageData(const void* data, size_t size) { + auto managed_data = CF_EXPECT(CreateStorageData(size)); + std::memcpy(managed_data->payload, data, size); + return managed_data; +} + +} // namespace secure_env +} // namespace cuttlefish diff --git a/host/commands/secure_env/storage/storage.h b/host/commands/secure_env/storage/storage.h new file mode 100644 index 000000000..6815c3476 --- /dev/null +++ b/host/commands/secure_env/storage/storage.h @@ -0,0 +1,69 @@ +// +// Copyright (C) 2023 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. + +#pragma once + +#include <any> +#include <string> + +#include "common/libs/utils/result.h" + +namespace cuttlefish { +namespace secure_env { + +struct StorageData { + uint32_t size; + uint8_t payload[0]; + + Result<uint8_t> asUint8() { + CF_EXPECT(size == sizeof(uint8_t), "Size of payload is not matched with uint8 size"); + return *reinterpret_cast<uint8_t*>(payload); + } +}; + +/** + * A destroyer for StorageData instances created with + * CreateStorageData. Wipes memory from the StorageData instances. + */ +class StorageDataDestroyer { + public: + void operator()(StorageData* ptr); +}; + +/** An owning pointer for a StorageData instance. */ +using ManagedStorageData = std::unique_ptr<StorageData, StorageDataDestroyer>; + +/** + * Allocates memory for a StorageData carrying a message of size + * `size`. + */ +Result<ManagedStorageData> CreateStorageData(size_t size); +Result<ManagedStorageData> CreateStorageData(const void* data, size_t size); + +/** + * Storage abstraction to store binary blobs associated with string key +*/ +class Storage { + public: + virtual Result<bool> HasKey(const std::string& key) const = 0; + virtual Result<ManagedStorageData> Read(const std::string& key) const = 0; + virtual Result<void> Write(const std::string& key, const StorageData& data) = 0; + virtual bool Exists() const = 0; + + virtual ~Storage() = default; +}; + +} // namespace secure_env +} // namespace cuttlefish |