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 <jwerner@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2038245
Reviewed-by: Joel Kitching <kitching@chromium.org>
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h
index 5470b30..2a87ab1 100644
--- a/firmware/2lib/include/2api.h
+++ b/firmware/2lib/include/2api.h
@@ -744,6 +744,20 @@
 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.
  *
  * @param ctx           Vboot2 context
diff --git a/firmware/lib20/api_kernel.c b/firmware/lib20/api_kernel.c
index 3748420..1e96f28 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_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 c81c3fe..da12f02 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 @@
 	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)