diff options
author | Dmitrii Merkurev <dimorinny@google.com> | 2023-06-13 14:56:59 +0100 |
---|---|---|
committer | Dmitrii Merkurev <dimorinny@google.com> | 2023-10-26 17:36:19 +0000 |
commit | 129eecf8e64117e4f77931207d0a39e1a7c60e48 (patch) | |
tree | 97ea307f0fae41de5c50757712dfe85c81c3f534 | |
parent | 61677e8fa3b63657881876a577dd3e5a282b5475 (diff) | |
download | cuttlefish-129eecf8e64117e4f77931207d0a39e1a7c60e48.tar.gz |
Use introduced json binary storage to store oemlock state
Alongside with that introduce LOCKED/UNLOCKED state and
single RPC to check unlock is allowed to reduce amount of
calls we need to execute on bootloader side
Bug: 282160400
Bug: 307584049
Test: Test: atest VtsHalOemLockTargetTest
Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
(cherry picked from https://android-review.googlesource.com/q/commit:dbcf615d82d79ff6a686c9a8f4abbb084a9c2960)
Merged-In: Ia554a16eede741c7e6c4253d0aa4a5dc3674e405
Change-Id: Ia554a16eede741c7e6c4253d0aa4a5dc3674e405
-rw-r--r-- | common/libs/security/oemlock.h | 4 | ||||
-rw-r--r-- | host/commands/assemble_cvd/assemble_cvd.cc | 1 | ||||
-rw-r--r-- | host/commands/secure_env/Android.bp | 3 | ||||
-rw-r--r-- | host/commands/secure_env/oemlock/oemlock.cpp | 102 | ||||
-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) | 37 | ||||
-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.cpp | 40 |
8 files changed, 176 insertions, 36 deletions
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/host/commands/assemble_cvd/assemble_cvd.cc b/host/commands/assemble_cvd/assemble_cvd.cc index cfaac2991..266547ae2 100644 --- a/host/commands/assemble_cvd/assemble_cvd.cc +++ b/host/commands/assemble_cvd/assemble_cvd.cc @@ -256,6 +256,7 @@ Result<const CuttlefishConfig*> InitFilesystemAndCreateConfig( 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/secure_env/Android.bp b/host/commands/secure_env/Android.bp index 0bd3690b7..a18ab2679 100644 --- a/host/commands/secure_env/Android.bp +++ b/host/commands/secure_env/Android.bp @@ -77,7 +77,6 @@ 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", @@ -105,6 +104,8 @@ cc_library_host_static { 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 698be32ff..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; } @@ -57,7 +72,7 @@ Result<void> OemLockResponder::ProcessMessage() { auto message = CF_EXPECT(secure_env::CreateMessage(request->command, sizeof(bool)), "Failed to allocate message for oemlock response"); - memcpy(message->payload, &allowed, sizeof(bool)); + memcpy(message->payload, &result, sizeof(bool)); CF_EXPECT(channel_.SendResponse(*message), "Could not answer to " << reinterpret_cast<uint32_t>(request->command) << " request"); 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*>(); |