diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-10-29 09:17:08 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-10-29 09:17:08 +0000 |
commit | d33ae248722ed674d4d34b72f1dd2c1b32ddff93 (patch) | |
tree | 447aa201598004d32411ea25ff31ea1e70abd7b8 | |
parent | 75ed6aeded6a7c22ee0e08a22c85e7ad1ff1fd4f (diff) | |
parent | 323f28019841d884a5e0117d860fcf631b087c68 (diff) | |
download | cuttlefish-aml_doc_341312010.tar.gz |
Snap for 11018792 from 323f28019841d884a5e0117d860fcf631b087c68 to mainline-documentsui-releaseaml_doc_341312010
Change-Id: Ic12e74965823893f4c8d9430d6d1401cbd850976
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; |