aboutsummaryrefslogtreecommitdiff
path: root/host
diff options
context:
space:
mode:
authorDmitrii Merkurev <dimorinny@google.com>2023-06-11 19:03:30 +0100
committerDmitrii Merkurev <dimorinny@google.com>2023-10-26 17:35:51 +0000
commit61677e8fa3b63657881876a577dd3e5a282b5475 (patch)
tree8db357c31ba1d51c68ced97f3aeef89d2a8f26d4 /host
parent1ec6fb25e34c708d89f00d7cb8e193824d2f8a7b (diff)
downloadcuttlefish-61677e8fa3b63657881876a577dd3e5a282b5475.tar.gz
Introduce key(string):value(binary) storage
This is needed to reuse existing gatekeeper TPM NV storage logic in oemlock. Also introduced insecure json implementation for software oemlock implementation (in case TPM isn't available) Bug: 282160400 Bug: 307584049 Test: atest VtsHalOemLockTargetTest with other local changes Signed-off-by: Dmitrii Merkurev <dimorinny@google.com> (cherry picked from https://android-review.googlesource.com/q/commit:ec2fc895b6d3d656d2a1d67b1bce86cfd8bc9253) Merged-In: I843c5937b48a06d763f7cee46fd4bfb10f31aeaa Change-Id: I843c5937b48a06d763f7cee46fd4bfb10f31aeaa
Diffstat (limited to 'host')
-rw-r--r--host/commands/secure_env/Android.bp6
-rw-r--r--host/commands/secure_env/storage/insecure_json_storage.cpp88
-rw-r--r--host/commands/secure_env/storage/insecure_json_storage.h37
-rw-r--r--host/commands/secure_env/storage/storage.cpp48
-rw-r--r--host/commands/secure_env/storage/storage.h69
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