summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu-Ping Wu <yupingso@chromium.org>2020-04-01 16:36:48 +0800
committerCommit Bot <commit-bot@chromium.org>2020-04-20 15:21:06 +0000
commitecf8073bd306ca45d7b6551efe094f9a555f9985 (patch)
tree37d2fd86a0b04b6cc54b13d80cf06201c0cf32b0
parentcc719d12112eadb578480b26e323f0760e0c13f6 (diff)
downloadvboot-ecf8073bd306ca45d7b6551efe094f9a555f9985.tar.gz
vboot: Add vb2api_phone_recovery_enabled() to vboot API
In order to implement a kill switch for phone recovery in recovery UI, add VB2_SECDATA_KERNEL_FLAGS to enum vb2_secdata_kernel_flags, and add VB2_SECDATA_KERNEL_FLAG_PHONE_RECOVERY_DISABLED to the flags to indicate whether to disable phone recovery. Set this flag to 1 in vb2api_kernel_phase1(). Also add vb2api_phone_recovery_enabled() to vboot API. BRANCH=none BUG=b:146399181, b:147744345 TEST=make runtests Change-Id: I65c8faa593f5f90dd762f0092058048983c5b3a2 Signed-off-by: Yu-Ping Wu <yupingso@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2131236 Reviewed-by: Joel Kitching <kitching@chromium.org>
-rw-r--r--firmware/2lib/2kernel.c6
-rw-r--r--firmware/2lib/2misc.c6
-rw-r--r--firmware/2lib/2secdata_kernel.c36
-rw-r--r--firmware/2lib/include/2api.h8
-rw-r--r--firmware/2lib/include/2secdata.h17
-rw-r--r--firmware/2lib/include/2secdata_struct.h4
-rw-r--r--tests/vb2_kernel_tests.c3
-rw-r--r--tests/vb2_misc_tests.c20
-rw-r--r--tests/vb2_secdata_kernel_tests.c23
9 files changed, 111 insertions, 12 deletions
diff --git a/firmware/2lib/2kernel.c b/firmware/2lib/2kernel.c
index 84c90d70..fc9158a4 100644
--- a/firmware/2lib/2kernel.c
+++ b/firmware/2lib/2kernel.c
@@ -126,6 +126,7 @@ vb2_error_t vb2api_kernel_phase1(struct vb2_context *ctx)
struct vb2_shared_data *sd = vb2_get_sd(ctx);
struct vb2_workbuf wb;
struct vb2_packed_key *packed_key;
+ uint32_t secdata_flags;
vb2_error_t rv;
vb2_workbuf_from_ctx(ctx, &wb);
@@ -142,6 +143,11 @@ vb2_error_t vb2api_kernel_phase1(struct vb2_context *ctx)
return rv;
}
+ /* Disable phone recovery */
+ secdata_flags = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS);
+ secdata_flags |= VB2_SECDATA_KERNEL_FLAG_PHONE_RECOVERY_DISABLED;
+ vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, secdata_flags);
+
/* Read kernel version from secdata. */
sd->kernel_version_secdata =
vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
diff --git a/firmware/2lib/2misc.c b/firmware/2lib/2misc.c
index 7a2def3c..86b88d90 100644
--- a/firmware/2lib/2misc.c
+++ b/firmware/2lib/2misc.c
@@ -500,6 +500,12 @@ void vb2api_export_vbsd(struct vb2_context *ctx, void *dest)
_Static_assert(VB2_VBSD_SIZE == sizeof(VbSharedDataHeader),
"VB2_VBSD_SIZE incorrect");
+int vb2api_phone_recovery_enabled(struct vb2_context *ctx)
+{
+ return !(vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS) &
+ VB2_SECDATA_KERNEL_FLAG_PHONE_RECOVERY_DISABLED);
+}
+
enum vb2_dev_default_boot vb2_get_dev_boot_target(
struct vb2_context *ctx)
{
diff --git a/firmware/2lib/2secdata_kernel.c b/firmware/2lib/2secdata_kernel.c
index 27342f38..8b3cf59c 100644
--- a/firmware/2lib/2secdata_kernel.c
+++ b/firmware/2lib/2secdata_kernel.c
@@ -32,7 +32,7 @@ uint8_t vb2_secdata_kernel_crc(struct vb2_context *ctx)
} else {
struct vb2_secdata_kernel_v1 *sec
= (void *)ctx->secdata_kernel;
- offset = offsetof(struct vb2_secdata_kernel_v1, reserved0);
+ offset = offsetof(struct vb2_secdata_kernel_v1, flags);
size = sec->struct_size - offset;
}
@@ -180,6 +180,8 @@ uint32_t vb2_secdata_kernel_get(struct vb2_context *ctx,
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
const char *msg;
+ const struct vb2_secdata_kernel_v0 *v0 = (void *)ctx->secdata_kernel;
+ const struct vb2_secdata_kernel_v1 *v1 = (void *)ctx->secdata_kernel;
if (!(sd->status & VB2_SD_STATUS_SECDATA_KERNEL_INIT)) {
msg = "get before init";
@@ -188,15 +190,14 @@ uint32_t vb2_secdata_kernel_get(struct vb2_context *ctx,
switch (param) {
case VB2_SECDATA_KERNEL_VERSIONS:
+ return is_v0(ctx) ? v0->kernel_versions : v1->kernel_versions;
+ case VB2_SECDATA_KERNEL_FLAGS:
if (is_v0(ctx)) {
- struct vb2_secdata_kernel_v0 *sec =
- (void *)ctx->secdata_kernel;
- return sec->kernel_versions;
- } else {
- struct vb2_secdata_kernel_v1 *sec =
- (void *)ctx->secdata_kernel;
- return sec->kernel_versions;
+ VB2_DEBUG("VB2_SECDATA_KERNEL_FLAGS not supported for "
+ "secdata_kernel v0, return 0\n");
+ return 0;
}
+ return v1->flags;
default:
msg = "invalid param";
}
@@ -230,15 +231,30 @@ void vb2_secdata_kernel_set(struct vb2_context *ctx,
ptr = is_v0(ctx) ? &v0->kernel_versions : &v1->kernel_versions;
VB2_DEBUG("secdata_kernel versions updated from %#x to %#x\n",
*ptr, value);
+ *ptr = value;
break;
+ case VB2_SECDATA_KERNEL_FLAGS:
+ if (is_v0(ctx)) {
+ VB2_DEBUG("VB2_SECDATA_KERNEL_FLAGS not supported for "
+ "secdata_kernel v0, silently ignore\n");
+ return;
+ }
+
+ /* Make sure flags is in valid range */
+ if (value > UINT8_MAX) {
+ msg = "flags out of range";
+ goto fail;
+ }
+ VB2_DEBUG("secdata_kernel flags updated from %#x to %#x\n",
+ v1->flags, value);
+ v1->flags = value;
+ break;
default:
msg = "invalid param";
goto fail;
}
- *ptr = value;
-
if (is_v0(ctx))
v0->crc8 = vb2_secdata_kernel_crc(ctx);
else
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h
index 969be2fa..5c21989f 100644
--- a/firmware/2lib/include/2api.h
+++ b/firmware/2lib/include/2api.h
@@ -842,6 +842,14 @@ uint32_t vb2api_get_recovery_reason(struct vb2_context *ctx);
*/
uint32_t vb2api_get_locale_id(struct vb2_context *ctx);
+/**
+ * Whether phone recovery is enabled or not.
+ *
+ * @param ctx Vboot context
+ * @return 1 if enabled, 0 if disabled.
+ */
+int vb2api_phone_recovery_enabled(struct vb2_context *ctx);
+
/*****************************************************************************/
/* APIs provided by the caller to verified boot */
diff --git a/firmware/2lib/include/2secdata.h b/firmware/2lib/include/2secdata.h
index 96e21f76..e0409b7b 100644
--- a/firmware/2lib/include/2secdata.h
+++ b/firmware/2lib/include/2secdata.h
@@ -81,6 +81,23 @@ void vb2_secdata_firmware_set(struct vb2_context *ctx,
enum vb2_secdata_kernel_param {
/* Kernel versions */
VB2_SECDATA_KERNEL_VERSIONS = 0,
+
+ /* Flags; see vb2_secdata_kernel_flags */
+ VB2_SECDATA_KERNEL_FLAGS,
+};
+
+/* Flags for kernel space */
+enum vb2_secdata_kernel_flags {
+ /*
+ * Phone recovery is disabled.
+ *
+ * RW firmware currently sets this flag to disable phone recovery on
+ * first boot (see function vb2api_kernel_phase1()). A future RW update
+ * will flip this flag back to 0 when phone recovery is ready. In the
+ * case that there are TPM communication issues, phone recovery is
+ * enabled by the default value of 0. See b/147744345 for details.
+ */
+ VB2_SECDATA_KERNEL_FLAG_PHONE_RECOVERY_DISABLED = (1 << 0),
};
/**
diff --git a/firmware/2lib/include/2secdata_struct.h b/firmware/2lib/include/2secdata_struct.h
index d8b5340f..76140434 100644
--- a/firmware/2lib/include/2secdata_struct.h
+++ b/firmware/2lib/include/2secdata_struct.h
@@ -89,8 +89,8 @@ struct vb2_secdata_kernel_v1 {
/* 8-bit CRC for everything below */
uint8_t crc8;
- /* Reserved for future expansion */
- uint8_t reserved0;
+ /* Flags; see vb2_secdata_kernel_flags */
+ uint8_t flags;
/* Kernel versions */
uint32_t kernel_versions;
diff --git a/tests/vb2_kernel_tests.c b/tests/vb2_kernel_tests.c
index d92f1591..ddef912a 100644
--- a/tests/vb2_kernel_tests.c
+++ b/tests/vb2_kernel_tests.c
@@ -213,6 +213,9 @@ static void phase1_tests(void)
" key data");
TEST_EQ(sd->kernel_version_secdata, 0x20002,
" secdata_kernel version");
+ /* Make sure phone recovery is disabled */
+ TEST_EQ(vb2api_phone_recovery_enabled(ctx), 0,
+ " phone recovery disabled");
/* Bad secdata_fwmp causes failure in normal mode only */
reset_common_data(FOR_PHASE1);
diff --git a/tests/vb2_misc_tests.c b/tests/vb2_misc_tests.c
index 4c56c8f1..f5cc90c0 100644
--- a/tests/vb2_misc_tests.c
+++ b/tests/vb2_misc_tests.c
@@ -831,6 +831,25 @@ static void get_recovery_reason_tests(void)
TEST_EQ(vb2api_get_recovery_reason(ctx), 4, "correct recovery reason");
}
+static void phone_recovery_enabled_tests(void)
+{
+ /* Phone recovery enabled */
+ reset_common_data();
+ vb2api_secdata_kernel_create(ctx);
+ vb2_secdata_kernel_init(ctx);
+ TEST_EQ(vb2api_phone_recovery_enabled(ctx), 1,
+ "phone recovery enabled");
+
+ /* Phone recovery disabled */
+ reset_common_data();
+ vb2api_secdata_kernel_create(ctx);
+ vb2_secdata_kernel_init(ctx);
+ vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS,
+ VB2_SECDATA_KERNEL_FLAG_PHONE_RECOVERY_DISABLED);
+ TEST_EQ(vb2api_phone_recovery_enabled(ctx), 0,
+ "phone recovery disabled");
+}
+
static void dev_default_boot_tests(void)
{
/* No default boot */
@@ -958,6 +977,7 @@ int main(int argc, char* argv[])
need_reboot_for_display_tests();
clear_recovery_tests();
get_recovery_reason_tests();
+ phone_recovery_enabled_tests();
dev_default_boot_tests();
dev_boot_allowed_tests();
diff --git a/tests/vb2_secdata_kernel_tests.c b/tests/vb2_secdata_kernel_tests.c
index 06f8474b..327018dc 100644
--- a/tests/vb2_secdata_kernel_tests.c
+++ b/tests/vb2_secdata_kernel_tests.c
@@ -214,6 +214,22 @@ static void secdata_kernel_access_test_v10(void)
v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
TEST_EQ(v, 0x123456ff, "Versions changed");
+ /* Read/write flags */
+ vb2api_secdata_kernel_create(ctx);
+ vb2_secdata_kernel_init(ctx);
+ ctx->flags = 0;
+ v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS);
+ TEST_EQ(v, 0, "Flags created 0");
+ test_changed(ctx, 0, "Get doesn't change data");
+ vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, 0x12);
+ test_changed(ctx, 1, "Set changes data");
+ vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, 0x12);
+ test_changed(ctx, 0, "Set again doesn't change data");
+ v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS);
+ TEST_EQ(v, 0x12, "Flags changed");
+ TEST_ABORT(vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, 0x100),
+ "Bad flags");
+
/* Invalid field fails */
TEST_ABORT(vb2_secdata_kernel_get(ctx, -1), "Get invalid");
TEST_ABORT(vb2_secdata_kernel_set(ctx, -1, 456), "Set invalid");
@@ -284,6 +300,13 @@ static void secdata_kernel_access_test_v02(void)
v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
TEST_EQ(v, 0x123456ff, "Versions changed");
+ /* Read/write flags: should be no-op for v0 */
+ TEST_EQ(vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS), 0,
+ "Get flags");
+ vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, 0x1);
+ TEST_EQ(vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS), 0,
+ "Get flags again");
+
/* Invalid field fails */
TEST_ABORT(vb2_secdata_kernel_get(ctx, -1), "Get invalid");
TEST_ABORT(vb2_secdata_kernel_set(ctx, -1, 456), "Set invalid");