From 821b5486a5df9ab403e6ac227c0a4f1ade2c0400 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 4 Feb 2020 17:44:33 -0800 Subject: 2lib: Add vb2api_is_developer_signed() to replace old dev key check This patch removes the old check for developer keys from the firmware verification path and instead inserts a similar (but faster) check into vb2api_kernel_phase1(). This has the advantage that we can export the check function to the calling firmware which could use it to display this information in a more user-visible manner. BRANCH=None BUG=None TEST=Booted in normal and recovery mode with developer keys, confirmed they were recognized. Change-Id: I00af0d10e31b2789574c8e4f1875ccd8d01eb0d5 Signed-off-by: Julius Werner Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2038245 Reviewed-by: Joel Kitching --- firmware/2lib/include/2api.h | 14 ++++++++++++ firmware/lib20/api_kernel.c | 29 ++++++++++++++++++++++++ firmware/lib20/misc.c | 54 -------------------------------------------- 3 files changed, 43 insertions(+), 54 deletions(-) diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h index 5470b308..2a87ab12 100644 --- a/firmware/2lib/include/2api.h +++ b/firmware/2lib/include/2api.h @@ -743,6 +743,20 @@ vb2_gbb_flags_t vb2api_gbb_get_flags(struct vb2_context *ctx); */ uint32_t vb2api_get_firmware_size(struct vb2_context *ctx); +/** + * Check if this firmware was bundled with the well-known public developer key + * set (more specifically, checks the recovery key in recovery mode and the + * kernel subkey from the firmware preamble in other modes). This is a best + * effort check that could be misled by a specifically crafted key. + * + * May only be called after vb2api_kernel_phase1() has run. + * + * @param ctx Vboot context + * + * @return 1 for developer keys, 0 for any others. + */ +int vb2api_is_developer_signed(struct vb2_context *ctx); + /** * If no display is available, set DISPLAY_REQUEST in nvdata. * diff --git a/firmware/lib20/api_kernel.c b/firmware/lib20/api_kernel.c index 3748420f..1e96f281 100644 --- a/firmware/lib20/api_kernel.c +++ b/firmware/lib20/api_kernel.c @@ -16,6 +16,32 @@ #include "vb2_common.h" #include "vboot_struct.h" +int vb2api_is_developer_signed(struct vb2_context *ctx) +{ + struct vb2_shared_data *sd = vb2_get_sd(ctx); + + if (!sd->kernel_key_offset || !sd->kernel_key_size) { + VB2_REC_OR_DIE(ctx, "Cannot call this before kernel_phase1!\n"); + return 0; + } + + struct vb2_public_key key; + if (vb2_unpack_key(&key, vb2_member_of(sd, sd->kernel_key_offset))) + return 0; + + /* This is a debugging aid, not a security-relevant feature. There's no + reason to hardcode the whole key or waste time computing a hash. Just + spot check the starting bytes of the pseudorandom part of the key. */ + uint32_t devkey_n0inv = ctx->flags & VB2_CONTEXT_RECOVERY_MODE ? + 0x18cebcf5 : /* recovery_key.vbpubk @0x24 */ + 0xe0cd87d9; /* kernel_subkey.vbpubk @0x24 */ + + if (key.n0inv == devkey_n0inv) + return 1; + + return 0; +} + vb2_error_t vb2api_kernel_phase1(struct vb2_context *ctx) { struct vb2_shared_data *sd = vb2_get_sd(ctx); @@ -82,6 +108,9 @@ vb2_error_t vb2api_kernel_phase1(struct vb2_context *ctx) vb2_set_workbuf_used(ctx, vb2_offset_of(sd, wb.buf)); + if (vb2api_is_developer_signed(ctx)) + VB2_DEBUG("This is developer-signed firmware.\n"); + return VB2_SUCCESS; } diff --git a/firmware/lib20/misc.c b/firmware/lib20/misc.c index c81c3fed..da12f028 100644 --- a/firmware/lib20/misc.c +++ b/firmware/lib20/misc.c @@ -14,57 +14,6 @@ #include "2sysincludes.h" #include "vb2_common.h" -/* - * The blob below is the sha1 digest calculated over the packed developer - * root public key structure. - */ - -static const uint8_t dev_key_digest[] = { - 0xb1, 0x1d, 0x74, 0xed, 0xd2, 0x86, 0xc1, 0x44, - 0xe1, 0x13, 0x5b, 0x49, 0xe7, 0xf0, 0xbc, 0x20, - 0xcf, 0x04, 0x1f, 0x10, -}; - -/** - * Determine if the root key is the developer key checked into the - * vboot_reference repository. Has no effect on boot; just logs this to the - * debug console. - * - * @param root Root key - */ -static void vb2_report_dev_firmware(struct vb2_public_key *root) -{ - struct vb2_digest_context dc; - uint8_t digest[sizeof(dev_key_digest)]; - int size = root->arrsize * 4; - - if (!root->arrsize) - return; /* Must be a test run. */ - - if (vb2_digest_init(&dc, VB2_HASH_SHA1) != VB2_SUCCESS) - return; - - if (vb2_digest_extend(&dc, (uint8_t *)&root->arrsize, - sizeof(root->arrsize)) != VB2_SUCCESS) - return; - - if (vb2_digest_extend(&dc, (uint8_t *)&root->n0inv, - sizeof(root->n0inv)) != VB2_SUCCESS) - return; - - if (vb2_digest_extend(&dc, (uint8_t *)root->n, size) != VB2_SUCCESS) - return; - - if (vb2_digest_extend(&dc, (uint8_t *)root->rr, size) != VB2_SUCCESS) - return; - - if (vb2_digest_finalize(&dc, digest, sizeof(digest)) != VB2_SUCCESS) - return; - - if (!memcmp(digest, dev_key_digest, sizeof(dev_key_digest))) - VB2_DEBUG("This is developer signed firmware\n"); -} - vb2_error_t vb2_load_fw_keyblock(struct vb2_context *ctx) { struct vb2_shared_data *sd = vb2_get_sd(ctx); @@ -98,9 +47,6 @@ vb2_error_t vb2_load_fw_keyblock(struct vb2_context *ctx) if (rv) return rv; - /* If that's the checked-in root key, this is dev-signed firmware */ - vb2_report_dev_firmware(&root_key); - /* Load the firmware keyblock header after the root key */ kb = vb2_workbuf_alloc(&wb, sizeof(*kb)); if (!kb) -- cgit v1.2.1