aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitrii Merkurev <dimorinny@google.com>2023-06-13 14:56:59 +0100
committerDmitrii Merkurev <dimorinny@google.com>2023-10-26 17:36:19 +0000
commit129eecf8e64117e4f77931207d0a39e1a7c60e48 (patch)
tree97ea307f0fae41de5c50757712dfe85c81c3f534
parent61677e8fa3b63657881876a577dd3e5a282b5475 (diff)
downloadcuttlefish-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.h4
-rw-r--r--host/commands/assemble_cvd/assemble_cvd.cc1
-rw-r--r--host/commands/secure_env/Android.bp3
-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)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.cpp40
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*>();