diff options
author | Yu-Ping Wu <yupingso@chromium.org> | 2020-04-01 16:36:48 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-04-20 15:21:06 +0000 |
commit | ecf8073bd306ca45d7b6551efe094f9a555f9985 (patch) | |
tree | 37d2fd86a0b04b6cc54b13d80cf06201c0cf32b0 | |
parent | cc719d12112eadb578480b26e323f0760e0c13f6 (diff) | |
download | vboot-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.c | 6 | ||||
-rw-r--r-- | firmware/2lib/2misc.c | 6 | ||||
-rw-r--r-- | firmware/2lib/2secdata_kernel.c | 36 | ||||
-rw-r--r-- | firmware/2lib/include/2api.h | 8 | ||||
-rw-r--r-- | firmware/2lib/include/2secdata.h | 17 | ||||
-rw-r--r-- | firmware/2lib/include/2secdata_struct.h | 4 | ||||
-rw-r--r-- | tests/vb2_kernel_tests.c | 3 | ||||
-rw-r--r-- | tests/vb2_misc_tests.c | 20 | ||||
-rw-r--r-- | tests/vb2_secdata_kernel_tests.c | 23 |
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"); |