aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-10-29 09:17:08 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-10-29 09:17:08 +0000
commitd33ae248722ed674d4d34b72f1dd2c1b32ddff93 (patch)
tree447aa201598004d32411ea25ff31ea1e70abd7b8
parent75ed6aeded6a7c22ee0e08a22c85e7ad1ff1fd4f (diff)
parent323f28019841d884a5e0117d860fcf631b087c68 (diff)
downloadcuttlefish-aml_doc_341312010.tar.gz
Snap for 11018792 from 323f28019841d884a5e0117d860fcf631b087c68 to mainline-documentsui-releaseaml_doc_341312010
Change-Id: Ic12e74965823893f4c8d9430d6d1401cbd850976
-rw-r--r--common/libs/security/channel.cpp20
-rw-r--r--common/libs/security/channel.h11
-rw-r--r--common/libs/security/channel_sharedfd.cpp41
-rw-r--r--common/libs/security/channel_sharedfd.h6
-rw-r--r--common/libs/security/oemlock.h4
-rw-r--r--guest/hals/oemlock/remote/remote_oemlock.cpp11
-rw-r--r--host/commands/assemble_cvd/assemble_cvd.cc3
-rw-r--r--host/commands/assemble_cvd/disk_flags.cc4
-rw-r--r--host/commands/secure_env/Android.bp9
-rw-r--r--host/commands/secure_env/oemlock/oemlock.cpp102
-rw-r--r--host/commands/secure_env/oemlock/oemlock.h (renamed from host/commands/secure_env/oemlock.h)23
-rw-r--r--host/commands/secure_env/oemlock/oemlock_responder.cpp (renamed from host/commands/secure_env/oemlock_responder.cpp)40
-rw-r--r--host/commands/secure_env/oemlock/oemlock_responder.h (renamed from host/commands/secure_env/oemlock_responder.h)2
-rw-r--r--host/commands/secure_env/secure_env_linux_main.cpp40
-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
-rw-r--r--host/libs/config/data_image.cpp9
19 files changed, 485 insertions, 82 deletions
diff --git a/common/libs/security/channel.cpp b/common/libs/security/channel.cpp
index 009617da1..e2891aa2f 100644
--- a/common/libs/security/channel.cpp
+++ b/common/libs/security/channel.cpp
@@ -28,5 +28,25 @@ void MessageDestroyer::operator()(RawMessage* ptr) {
std::free(ptr);
}
+/**
+ * Allocates memory for a RawMessage carrying a message of size
+ * `payload_size`.
+ */
+Result<ManagedMessage> CreateMessage(uint32_t command, bool is_response, size_t payload_size) {
+ const auto bytes_to_allocate = sizeof(RawMessage) + payload_size;
+ auto memory = std::malloc(bytes_to_allocate);
+ CF_EXPECT(memory != nullptr,
+ "Cannot allocate " << bytes_to_allocate << " bytes for secure_env RPC message");
+ auto message = reinterpret_cast<RawMessage*>(memory);
+ message->command = command;
+ message->is_response = is_response;
+ message->payload_size = payload_size;
+ return ManagedMessage(message);
+}
+
+Result<ManagedMessage> CreateMessage(uint32_t command, size_t payload_size) {
+ return CreateMessage(command, false, payload_size);
+}
+
} // namespace secure_env
} // namespace cuttlefish \ No newline at end of file
diff --git a/common/libs/security/channel.h b/common/libs/security/channel.h
index bbfb86779..eb415e2a0 100644
--- a/common/libs/security/channel.h
+++ b/common/libs/security/channel.h
@@ -52,14 +52,21 @@ class MessageDestroyer {
/** An owning pointer for a RawMessage instance. */
using ManagedMessage = std::unique_ptr<RawMessage, MessageDestroyer>;
+/**
+ * Allocates memory for a RawMessage carrying a message of size
+ * `payload_size`.
+ */
+Result<ManagedMessage> CreateMessage(uint32_t command, bool is_response, size_t payload_size);
+Result<ManagedMessage> CreateMessage(uint32_t command, size_t payload_size);
+
/*
* Interface for communication channels that synchronously communicate
* HAL IPC/RPC calls.
*/
class Channel {
public:
- virtual Result<void> SendRequest(uint32_t command, void* message, size_t message_size) = 0;
- virtual Result<void> SendResponse(uint32_t command, void* message, size_t message_size) = 0;
+ virtual Result<void> SendRequest(RawMessage& message) = 0;
+ virtual Result<void> SendResponse(RawMessage& message) = 0;
virtual Result<ManagedMessage> ReceiveMessage() = 0;
virtual ~Channel() {}
};
diff --git a/common/libs/security/channel_sharedfd.cpp b/common/libs/security/channel_sharedfd.cpp
index c07d876b0..a152cf32b 100644
--- a/common/libs/security/channel_sharedfd.cpp
+++ b/common/libs/security/channel_sharedfd.cpp
@@ -20,35 +20,16 @@
namespace cuttlefish {
namespace secure_env {
-namespace {
-
-/**
- * Allocates memory for a RawMessage carrying a message of size
- * `payload_size`.
- */
-Result<ManagedMessage> CreateMessage(uint32_t command, bool is_response, size_t payload_size) {
- const auto bytes_to_allocate = sizeof(RawMessage) + payload_size;
- auto memory = std::malloc(bytes_to_allocate);
- CF_EXPECT(memory != nullptr,
- "Cannot allocate " << bytes_to_allocate << " bytes for secure_env RPC message");
- auto message = reinterpret_cast<RawMessage*>(memory);
- message->command = command;
- message->is_response = is_response;
- message->payload_size = payload_size;
- return ManagedMessage(message);
-}
-
-}
SharedFdChannel::SharedFdChannel(SharedFD input, SharedFD output)
: input_(std::move(input)), output_(std::move(output)) {}
-Result<void> SharedFdChannel::SendRequest(uint32_t command, void* message, size_t message_size) {
- return SendMessage(command, false, message, message_size);
+Result<void> SharedFdChannel::SendRequest(RawMessage& message) {
+ return SendMessage(message, false);
}
-Result<void> SharedFdChannel::SendResponse(uint32_t command, void* message, size_t message_size) {
- return SendMessage(command, true, message, message_size);
+Result<void> SharedFdChannel::SendResponse(RawMessage& message) {
+ return SendMessage(message, true);
}
Result<ManagedMessage> SharedFdChannel::ReceiveMessage() {
@@ -69,14 +50,12 @@ Result<ManagedMessage> SharedFdChannel::ReceiveMessage() {
return message;
}
-Result<void> SharedFdChannel::SendMessage(uint32_t command, bool response,
- void* message, size_t message_size) {
- auto to_send = CF_EXPECT(CreateMessage(command, response, message_size));
- memcpy(to_send->payload, message, message_size);
- auto write_size = sizeof(RawMessage) + message_size;
- auto to_send_bytes = reinterpret_cast<const char*>(to_send.get());
- auto written = WriteAll(output_, to_send_bytes, write_size);
- CF_EXPECT(written != -1,
+Result<void> SharedFdChannel::SendMessage(RawMessage& message, bool response) {
+ message.is_response = response;
+ auto write_size = sizeof(RawMessage) + message.payload_size;
+ auto message_bytes = reinterpret_cast<const char*>(&message);
+ auto written = WriteAll(output_, message_bytes, write_size);
+ CF_EXPECT(written == write_size,
"Could not write message: " << output_->StrError());
return {};
}
diff --git a/common/libs/security/channel_sharedfd.h b/common/libs/security/channel_sharedfd.h
index 3d0fdbcda..39f27490d 100644
--- a/common/libs/security/channel_sharedfd.h
+++ b/common/libs/security/channel_sharedfd.h
@@ -25,15 +25,15 @@ namespace secure_env {
class SharedFdChannel : public Channel {
public:
SharedFdChannel(SharedFD input, SharedFD output);
- Result<void> SendRequest(uint32_t command, void* message, size_t message_size) override;
- Result<void> SendResponse(uint32_t command, void* message, size_t message_size) override;
+ Result<void> SendRequest(RawMessage& message) override;
+ Result<void> SendResponse(RawMessage& message) override;
Result<ManagedMessage> ReceiveMessage() override;
private:
SharedFD input_;
SharedFD output_;
- Result<void> SendMessage(uint32_t command, bool response, void* message, size_t message_size);
+ Result<void> SendMessage(RawMessage& message, bool response);
};
} // namespace secure_env
diff --git a/common/libs/security/oemlock.h b/common/libs/security/oemlock.h
index ab980a90e..d5fb62d06 100644
--- a/common/libs/security/oemlock.h
+++ b/common/libs/security/oemlock.h
@@ -23,7 +23,9 @@ namespace secure_env {
enum class OemLockField : uint32_t {
ALLOWED_BY_CARRIER = 0,
- ALLOWED_BY_DEVICE = 1,
+ ALLOWED_BY_DEVICE,
+ ALLOWED,
+ LOCKED,
};
} // namespace secure_env
diff --git a/guest/hals/oemlock/remote/remote_oemlock.cpp b/guest/hals/oemlock/remote/remote_oemlock.cpp
index f427ec028..46727be62 100644
--- a/guest/hals/oemlock/remote/remote_oemlock.cpp
+++ b/guest/hals/oemlock/remote/remote_oemlock.cpp
@@ -65,7 +65,10 @@ OemLock::OemLock(secure_env::Channel& channel) : channel_(channel) {}
}
Result<void> OemLock::requestValue(secure_env::OemLockField field, bool *out) {
- CF_EXPECT(channel_.SendRequest(static_cast<uint32_t>(field), nullptr, 0),
+ auto message = CF_EXPECT(secure_env::CreateMessage(static_cast<uint32_t>(field), 0),
+ "Cannot allocate message for oemlock request: " <<
+ static_cast<uint32_t>(field));
+ CF_EXPECT(channel_.SendRequest(*message),
"Can't send get value request for field: " << static_cast<uint32_t>(field));
auto response = CF_EXPECT(channel_.ReceiveMessage(),
"Haven't received an answer for getting the field: " <<
@@ -75,7 +78,11 @@ Result<void> OemLock::requestValue(secure_env::OemLockField field, bool *out) {
}
Result<void> OemLock::setValue(secure_env::OemLockField field, bool value) {
- CF_EXPECT(channel_.SendRequest(static_cast<uint32_t>(field), &value, sizeof(bool)),
+ auto message = CF_EXPECT(secure_env::CreateMessage(static_cast<uint32_t>(field), sizeof(bool)),
+ "Cannot allocate message for oemlock request: " <<
+ static_cast<uint32_t>(field));
+ memcpy(message->payload, &value, sizeof(bool));
+ CF_EXPECT(channel_.SendRequest(*message),
"Can't send set value request for field: " << static_cast<uint32_t>(field));
auto response = CF_EXPECT(channel_.ReceiveMessage(),
"Haven't received an answer for setting the field: " <<
diff --git a/host/commands/assemble_cvd/assemble_cvd.cc b/host/commands/assemble_cvd/assemble_cvd.cc
index 9d285ecab..266547ae2 100644
--- a/host/commands/assemble_cvd/assemble_cvd.cc
+++ b/host/commands/assemble_cvd/assemble_cvd.cc
@@ -254,6 +254,9 @@ Result<const CuttlefishConfig*> InitFilesystemAndCreateConfig(
preserving.insert("persistent_composite.img");
preserving.insert("uboot_env.img");
preserving.insert("factory_reset_protected.img");
+ preserving.insert("misc.img");
+ preserving.insert("metadata.img");
+ preserving.insert("oemlock_insecure");
std::stringstream ss;
for (int i = 0; i < modem_simulator_count; i++) {
ss.clear();
diff --git a/host/commands/assemble_cvd/disk_flags.cc b/host/commands/assemble_cvd/disk_flags.cc
index dc6e4f2f2..beae35e48 100644
--- a/host/commands/assemble_cvd/disk_flags.cc
+++ b/host/commands/assemble_cvd/disk_flags.cc
@@ -901,8 +901,8 @@ class InitializeMetadataImage : public SetupFeature {
private:
std::unordered_set<SetupFeature*> Dependencies() const override { return {}; }
Result<void> ResultSetup() override {
- if (FileExists(instance_.metadata_image()) &&
- FileSize(instance_.metadata_image()) == instance_.blank_metadata_image_mb() << 20) {
+ if (FileExists(instance_.new_metadata_image()) &&
+ FileSize(instance_.new_metadata_image()) == instance_.blank_metadata_image_mb() << 20) {
return {};
}
diff --git a/host/commands/secure_env/Android.bp b/host/commands/secure_env/Android.bp
index 73d443b17..a18ab2679 100644
--- a/host/commands/secure_env/Android.bp
+++ b/host/commands/secure_env/Android.bp
@@ -77,8 +77,8 @@ common_libsecure_srcs = [
"insecure_fallback_storage.cpp",
"json_serializable.cpp",
"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 +95,18 @@ 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",
+ "oemlock/oemlock.cpp",
+ "oemlock/oemlock_responder.cpp",
+ "storage/insecure_json_storage.cpp",
],
defaults: ["cuttlefish_buildhost_only", "secure_env_defaults"],
}
diff --git a/host/commands/secure_env/oemlock/oemlock.cpp b/host/commands/secure_env/oemlock/oemlock.cpp
new file mode 100644
index 000000000..05709f6f7
--- /dev/null
+++ b/host/commands/secure_env/oemlock/oemlock.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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/oemlock/oemlock.h"
+
+namespace cuttlefish {
+namespace oemlock {
+namespace {
+
+constexpr char kStateKey[] = "oemlock_state";
+constexpr int kAllowedByCarrierBit = 0;
+constexpr int kAllowedByDeviceBit = 1;
+constexpr int kOemLockedBit = 2;
+
+// Default state is allowed_by_carrier = true
+// allowed_by_device = false
+// locked = true
+constexpr uint8_t kDefaultState = 0 | (1 << kAllowedByCarrierBit) | (1 << kOemLockedBit);
+
+Result<void> InitializeDefaultState(secure_env::Storage& storage) {
+ if (storage.Exists()) { return {}; };
+ auto data = CF_EXPECT(secure_env::CreateStorageData(&kDefaultState, sizeof(kDefaultState)));
+ CF_EXPECT(storage.Write(kStateKey, *data));
+ return {};
+}
+
+Result<bool> ReadFlag(secure_env::Storage& storage, int bit) {
+ auto data = CF_EXPECT(storage.Read(kStateKey));
+ auto state = CF_EXPECT(data->asUint8());
+ return (state >> bit) & 1;
+}
+
+Result<void> WriteFlag(secure_env::Storage& storage, int bit, bool value) {
+ auto data = CF_EXPECT(storage.Read(kStateKey));
+ auto state = CF_EXPECT(data->asUint8());
+ value ? state |= (1 << bit) : state &= ~(1 << bit);
+ auto data_to_write = CF_EXPECT(secure_env::CreateStorageData(&state, sizeof(state)));
+ CF_EXPECT(storage.Write(kStateKey, *data_to_write));
+ return {};
+}
+
+} // namespace
+
+OemLock::OemLock(secure_env::Storage& storage) : storage_(storage) {
+ auto result = InitializeDefaultState(storage_);
+ if (!result.ok()) {
+ LOG(FATAL) << "Failed to initialize default state for OemLock TEE storage: "
+ << result.error().Message();
+ }
+}
+
+Result<bool> OemLock::IsOemUnlockAllowedByCarrier() const {
+ return CF_EXPECT(ReadFlag(storage_, kAllowedByCarrierBit));
+}
+
+Result<bool> OemLock::IsOemUnlockAllowedByDevice() const {
+ return CF_EXPECT(ReadFlag(storage_, kAllowedByDeviceBit));
+}
+
+Result<bool> OemLock::IsOemUnlockAllowed() const {
+ auto data = CF_EXPECT(storage_.Read(kStateKey));
+ auto state = CF_EXPECT(data->asUint8());
+ const bool allowed_by_device = (state >> kAllowedByDeviceBit) & 1;
+ const bool allowed_by_carrier = (state >> kAllowedByCarrierBit) & 1;
+ return allowed_by_device && allowed_by_carrier;
+}
+
+Result<bool> OemLock::IsOemLocked() const {
+ return CF_EXPECT(ReadFlag(storage_, kOemLockedBit));
+}
+
+Result<void> OemLock::SetOemUnlockAllowedByCarrier(bool allowed) {
+ CF_EXPECT(WriteFlag(storage_, kAllowedByCarrierBit, allowed));
+ return {};
+}
+
+Result<void> OemLock::SetOemUnlockAllowedByDevice(bool allowed) {
+ CF_EXPECT(WriteFlag(storage_, kAllowedByDeviceBit, allowed));
+ return {};
+}
+
+Result<void> OemLock::SetOemLocked(bool locked) {
+ CF_EXPECT(WriteFlag(storage_, kOemLockedBit, locked));
+ return {};
+}
+
+} // namespace oemlock
+} // namespace cuttlefish \ No newline at end of file
diff --git a/host/commands/secure_env/oemlock.h b/host/commands/secure_env/oemlock/oemlock.h
index 8ac29ffb2..306ec78e4 100644
--- a/host/commands/secure_env/oemlock.h
+++ b/host/commands/secure_env/oemlock/oemlock.h
@@ -17,6 +17,10 @@
#pragma once
+#include "common/libs/utils/result.h"
+
+#include "host/commands/secure_env/storage/storage.h"
+
namespace cuttlefish {
namespace oemlock {
@@ -28,11 +32,20 @@ namespace oemlock {
*/
class OemLock {
public:
- virtual bool IsOemUnlockAllowedByCarrier() const = 0;
- virtual bool IsOemUnlockAllowedByDevice() const = 0;
- virtual void SetOemUnlockAllowedByCarrier(bool allowed) = 0;
- virtual void SetOemUnlockAllowedByDevice(bool allowed) = 0;
+ OemLock(secure_env::Storage& storage);
+
+ Result<bool> IsOemUnlockAllowedByCarrier() const;
+ Result<bool> IsOemUnlockAllowedByDevice() const;
+ Result<bool> IsOemUnlockAllowed() const;
+ Result<bool> IsOemLocked() const;
+ Result<void> SetOemUnlockAllowedByCarrier(bool allowed);
+ Result<void> SetOemUnlockAllowedByDevice(bool allowed);
+ // TODO(b/286558252): add ConfirmationUI token to the signature
+ Result<void> SetOemLocked(bool locked);
+
+ private:
+ secure_env::Storage& storage_;
};
} // namespace oemlock
-} // namespace cuttlefish \ No newline at end of file
+} // namespace cuttlefish
diff --git a/host/commands/secure_env/oemlock_responder.cpp b/host/commands/secure_env/oemlock/oemlock_responder.cpp
index 3f9ad50c0..be434ae3b 100644
--- a/host/commands/secure_env/oemlock_responder.cpp
+++ b/host/commands/secure_env/oemlock/oemlock_responder.cpp
@@ -13,9 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "host/commands/secure_env/oemlock_responder.h"
-
-#include <android-base/logging.h>
+#include "host/commands/secure_env/oemlock/oemlock_responder.h"
#include "common/libs/security/oemlock.h"
@@ -29,24 +27,41 @@ OemLockResponder::OemLockResponder(secure_env::Channel& channel,
Result<void> OemLockResponder::ProcessMessage() {
auto request = CF_EXPECT(channel_.ReceiveMessage(), "Could not receive message");
- bool allowed = false;
+ bool result = false;
switch(secure_env::OemLockField(request->command)) {
case secure_env::OemLockField::ALLOWED_BY_CARRIER: {
if (request->payload_size == 0) {
- allowed = oemlock_.IsOemUnlockAllowedByCarrier();
+ result = CF_EXPECT(oemlock_.IsOemUnlockAllowedByCarrier());
} else if (request->payload_size == sizeof(bool)) {
- allowed = *reinterpret_cast<bool*>(request->payload);
- oemlock_.SetOemUnlockAllowedByCarrier(allowed);
+ result = *reinterpret_cast<bool*>(request->payload);
+ CF_EXPECT(oemlock_.SetOemUnlockAllowedByCarrier(result));
}
break;
}
case secure_env::OemLockField::ALLOWED_BY_DEVICE: {
if (request->payload_size == 0) {
- allowed = oemlock_.IsOemUnlockAllowedByDevice();
+ result = CF_EXPECT(oemlock_.IsOemUnlockAllowedByDevice());
+ } else if (request->payload_size == sizeof(bool)) {
+ result = *reinterpret_cast<bool*>(request->payload);
+ CF_EXPECT(oemlock_.SetOemUnlockAllowedByDevice(result));
+ }
+ break;
+ }
+
+ case secure_env::OemLockField::ALLOWED: {
+ if (request->payload_size == 0) {
+ result = CF_EXPECT(oemlock_.IsOemUnlockAllowed());
+ }
+ break;
+ }
+
+ case secure_env::OemLockField::LOCKED: {
+ if (request->payload_size == 0) {
+ result = CF_EXPECT(oemlock_.IsOemLocked());
} else if (request->payload_size == sizeof(bool)) {
- allowed = *reinterpret_cast<bool*>(request->payload);
- oemlock_.SetOemUnlockAllowedByDevice(allowed);
+ result = *reinterpret_cast<bool*>(request->payload);
+ CF_EXPECT(oemlock_.SetOemLocked(result));
}
break;
}
@@ -55,7 +70,10 @@ Result<void> OemLockResponder::ProcessMessage() {
return CF_ERR("Unrecognized message id " << reinterpret_cast<uint32_t>(request->command));
}
- CF_EXPECT(channel_.SendResponse(request->command, &allowed, sizeof(bool)),
+ auto message = CF_EXPECT(secure_env::CreateMessage(request->command, sizeof(bool)),
+ "Failed to allocate message for oemlock response");
+ memcpy(message->payload, &result, sizeof(bool));
+ CF_EXPECT(channel_.SendResponse(*message),
"Could not answer to " << reinterpret_cast<uint32_t>(request->command) << " request");
return {};
diff --git a/host/commands/secure_env/oemlock_responder.h b/host/commands/secure_env/oemlock/oemlock_responder.h
index 3b02472a4..0b5fadbf2 100644
--- a/host/commands/secure_env/oemlock_responder.h
+++ b/host/commands/secure_env/oemlock/oemlock_responder.h
@@ -17,7 +17,7 @@
#include "common/libs/security/channel.h"
#include "common/libs/utils/result.h"
-#include "host/commands/secure_env/oemlock.h"
+#include "host/commands/secure_env/oemlock/oemlock.h"
namespace cuttlefish {
namespace oemlock {
diff --git a/host/commands/secure_env/secure_env_linux_main.cpp b/host/commands/secure_env/secure_env_linux_main.cpp
index 56428c901..1164ef2d8 100644
--- a/host/commands/secure_env/secure_env_linux_main.cpp
+++ b/host/commands/secure_env/secure_env_linux_main.cpp
@@ -39,12 +39,13 @@
#include "host/commands/secure_env/in_process_tpm.h"
#include "host/commands/secure_env/insecure_fallback_storage.h"
#include "host/commands/secure_env/keymaster_responder.h"
-#include "host/commands/secure_env/oemlock_responder.h"
-#include "host/commands/secure_env/oemlock.h"
+#include "host/commands/secure_env/oemlock/oemlock_responder.h"
+#include "host/commands/secure_env/oemlock/oemlock.h"
#include "host/commands/secure_env/proxy_keymaster_context.h"
#include "host/commands/secure_env/rust/kmr_ta.h"
#include "host/commands/secure_env/soft_gatekeeper.h"
-#include "host/commands/secure_env/soft_oemlock.h"
+#include "host/commands/secure_env/storage/insecure_json_storage.h"
+#include "host/commands/secure_env/storage/storage.h"
#include "host/commands/secure_env/tpm_gatekeeper.h"
#include "host/commands/secure_env/tpm_keymaster_context.h"
#include "host/commands/secure_env/tpm_keymaster_enforcement.h"
@@ -150,22 +151,27 @@ ChooseGatekeeperComponent() {
}
}
-fruit::Component<oemlock::OemLock> ChooseOemlockComponent() {
- if (FLAGS_oemlock_impl == "software") {
- return fruit::createComponent()
- .bind<oemlock::OemLock, oemlock::SoftOemLock>();
- } else if (FLAGS_oemlock_impl == "tpm") {
- LOG(FATAL) << "Oemlock doesn't support TPM implementation";
- abort();
- } else {
- LOG(FATAL) << "Invalid oemlock implementation: "
- << FLAGS_oemlock_impl;
- abort();
- }
+fruit::Component<secure_env::Storage, oemlock::OemLock> ChooseOemlockComponent() {
+ return fruit::createComponent()
+ .registerProvider([]() -> secure_env::Storage* {
+ if (FLAGS_oemlock_impl == "software") {
+ return new secure_env::InsecureJsonStorage("oemlock_insecure");
+ } else if (FLAGS_oemlock_impl == "tpm") {
+ LOG(FATAL) << "Oemlock doesn't support TPM implementation";
+ abort();
+ } else {
+ LOG(FATAL) << "Invalid oemlock implementation: "
+ << FLAGS_oemlock_impl;
+ abort();
+ }
+ })
+ .registerProvider([](secure_env::Storage& storage) -> oemlock::OemLock* {
+ return new oemlock::OemLock(storage);
+ });;
}
fruit::Component<TpmResourceManager, gatekeeper::GateKeeper,
- oemlock::OemLock, keymaster::KeymasterEnforcement>
+ secure_env::Storage, oemlock::OemLock, keymaster::KeymasterEnforcement>
SecureEnvComponent() {
return fruit::createComponent()
.registerProvider([]() -> Tpm* { // fruit will take ownership
@@ -224,7 +230,7 @@ int SecureEnvMain(int argc, char** argv) {
keymaster::SoftKeymasterLogger km_logger;
fruit::Injector<TpmResourceManager, gatekeeper::GateKeeper,
- oemlock::OemLock, keymaster::KeymasterEnforcement>
+ secure_env::Storage, oemlock::OemLock, keymaster::KeymasterEnforcement>
injector(SecureEnvComponent);
TpmResourceManager* resource_manager = injector.get<TpmResourceManager*>();
gatekeeper::GateKeeper* gatekeeper = injector.get<gatekeeper::GateKeeper*>();
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
diff --git a/host/libs/config/data_image.cpp b/host/libs/config/data_image.cpp
index 45dbad845..e3a6fe48d 100644
--- a/host/libs/config/data_image.cpp
+++ b/host/libs/config/data_image.cpp
@@ -307,16 +307,13 @@ class InitializeMiscImageImpl : public InitializeMiscImage {
private:
std::unordered_set<SetupFeature*> Dependencies() const override { return {}; }
bool Setup() override {
- bool misc_exists = FileHasContent(instance_.misc_image());
-
- if (misc_exists) {
- LOG(DEBUG) << "misc partition image: use existing at \""
- << instance_.misc_image() << "\"";
+ if (FileHasContent(instance_.new_misc_image())) {
+ LOG(DEBUG) << "misc partition image already exists";
return true;
}
LOG(DEBUG) << "misc partition image: creating empty at \""
- << instance_.misc_image() << "\"";
+ << instance_.new_misc_image() << "\"";
if (!CreateBlankImage(instance_.new_misc_image(), 1 /* mb */, "none")) {
LOG(ERROR) << "Failed to create misc image";
return false;