[coreboot-gerrit] Patch set updated for coreboot: chromeos/vboot: provide support for x86 memory init verification

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Wed Feb 3 16:55:16 CET 2016


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/13574

-gerrit

commit 3c65b1436450eb604c186b51032d1e827cd2b21f
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Fri Jan 22 15:26:04 2016 -0600

    chromeos/vboot: provide support for x86 memory init verification
    
    For x86 systems which resume through the reset vector one needs to
    ensure the the RW slot taken at resume time matches the one at
    boot time. The reason is that any assets pulled out of the boot
    media need to match how the platform previously booted. To do
    that one needs obtain the hash digest of the chosen slot, and it
    needs to be saved in a secure place on the normal boot path. On
    resume one needs to retrieve the hash digest back to compare it
    with the chosen slot. If they don't match resuming won't be
    possible.
    
    BUG=chrome-os-partner:46049
    BRANCH=glados
    TEST=Suspended and resumed on chell. Also, tested with an EC build
         which returns a bad hash to ensure that is properly caught.
    CQ-DEPEND=CL:323460
    
    Change-Id: I90ce26813b67f46913aa4026b42d9490a564bb6c
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: 01a42c0ecfc6d60d1d2e5e36a86781d91d5c47a9
    Original-Change-Id: I6c6bdce7e06712bc06cc620a3d7a6a6250c59c95
    Original-Signed-off-by: Aaron Durbin <adurbin at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/323500
    Original-Reviewed-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Reviewed-by: Duncan Laurie <dlaurie at chromium.org>
---
 src/Kconfig                                        |  9 +++
 .../google/chromeos/vboot2/vboot_logic.c           | 70 +++++++++++++++++++++-
 src/vendorcode/google/chromeos/vboot_common.h      | 18 ++++++
 3 files changed, 96 insertions(+), 1 deletion(-)

diff --git a/src/Kconfig b/src/Kconfig
index 3f02843..feefc91 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -503,6 +503,15 @@ config HAVE_ACPI_RESUME
 	bool
 	default n
 
+config RESUME_PATH_SAME_AS_BOOT
+	bool
+	default y if ARCH_X86
+	depends on HAVE_ACPI_RESUME
+	help
+	  This option indicates that when a system resumes it takes the
+	  same path as a regular boot. e.g. an x86 system runs from the
+	  reset vector at 0xfffffff0 on both resume and warm/cold boot.
+
 config HAVE_HARD_RESET
 	bool
 	default n
diff --git a/src/vendorcode/google/chromeos/vboot2/vboot_logic.c b/src/vendorcode/google/chromeos/vboot2/vboot_logic.c
index b72de93..0d08d6a 100644
--- a/src/vendorcode/google/chromeos/vboot2/vboot_logic.c
+++ b/src/vendorcode/google/chromeos/vboot2/vboot_logic.c
@@ -26,6 +26,9 @@
 #include "../chromeos.h"
 #include "misc.h"
 
+/* The max hash size to expect is for SHA512. */
+#define VBOOT_MAX_HASH_SIZE VB2_SHA512_DIGEST_SIZE
+
 #define TODO_BLOCK_SIZE 1024
 
 static int is_slot_a(struct vb2_context *ctx)
@@ -111,15 +114,77 @@ int vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size)
 	return VB2_ERROR_UNKNOWN;
 }
 
+static int handle_digest_result(void *slot_hash, size_t slot_hash_sz)
+{
+	int is_resume;
+
+	/*
+	 * Nothing to do since resuming on the platform doesn't require
+	 * vboot verification again.
+	 */
+	if (!IS_ENABLED(CONFIG_RESUME_PATH_SAME_AS_BOOT))
+		return 0;
+
+	/*
+	 * Assume that if vboot doesn't start in bootblock verified
+	 * RW memory init code is not employed. i.e. memory init code
+	 * lives in RO CBFS.
+	 */
+	if (!IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
+		return 0;
+
+	is_resume = vboot_platform_is_resuming();
+
+	if (is_resume > 0) {
+		uint8_t saved_hash[VBOOT_MAX_HASH_SIZE];
+		const size_t saved_hash_sz = sizeof(saved_hash);
+
+		assert(slot_hash_sz == saved_hash_sz);
+
+		printk(BIOS_DEBUG, "Platform is resuming.\n");
+
+		if (vboot_retrieve_hash(saved_hash, saved_hash_sz)) {
+			printk(BIOS_ERR, "Couldn't retrieve saved hash.\n");
+			return -1;
+		}
+
+		if (memcmp(saved_hash, slot_hash, slot_hash_sz)) {
+			printk(BIOS_ERR, "Hash mismatch on resume.\n");
+			return -1;
+		}
+	} else if (is_resume < 0)
+		printk(BIOS_ERR, "Unable to determine if platform resuming.\n");
+
+	printk(BIOS_DEBUG, "Saving vboot hash.\n");
+
+	/* Always save the hash for the current boot. */
+	if (vboot_save_hash(slot_hash, slot_hash_sz)) {
+		printk(BIOS_ERR, "Error saving vboot hash.\n");
+		/* Though this is an error don't report it up since it could
+		 * lead to a reboot loop. The consequence of this is that
+		 * we will most likely fail resuming because of EC issues or
+		 * the hash digest not matching. */
+		return 0;
+	}
+
+	return 0;
+}
+
 static int hash_body(struct vb2_context *ctx, struct region_device *fw_main)
 {
 	uint64_t load_ts;
 	uint32_t expected_size;
 	uint8_t block[TODO_BLOCK_SIZE];
+	uint8_t hash_digest[VBOOT_MAX_HASH_SIZE];
+	const size_t hash_digest_sz = sizeof(hash_digest);
 	size_t block_size = sizeof(block);
 	size_t offset;
 	int rv;
 
+	/* Clear the full digest so that any hash digests less than the
+	 * max have trailing zeros. */
+	memset(hash_digest, 0, hash_digest_sz);
+
 	/*
 	 * Since loading the firmware and calculating its hash is intertwined,
 	 * we use this little trick to measure them separately and pretend it
@@ -160,12 +225,15 @@ static int hash_body(struct vb2_context *ctx, struct region_device *fw_main)
 	timestamp_add_now(TS_DONE_HASHING);
 
 	/* Check the result (with RSA signature verification) */
-	rv = vb2api_check_hash(ctx);
+	rv = vb2api_check_hash_get_digest(ctx, hash_digest, hash_digest_sz);
 	if (rv)
 		return rv;
 
 	timestamp_add_now(TS_END_HASH_BODY);
 
+	if (handle_digest_result(hash_digest, hash_digest_sz))
+		return VB2_ERROR_UNKNOWN;
+
 	return VB2_SUCCESS;
 }
 
diff --git a/src/vendorcode/google/chromeos/vboot_common.h b/src/vendorcode/google/chromeos/vboot_common.h
index fbffc29..a658d62 100644
--- a/src/vendorcode/google/chromeos/vboot_common.h
+++ b/src/vendorcode/google/chromeos/vboot_common.h
@@ -46,6 +46,24 @@ int vboot_recovery_reason(void);
 
 void vboot_reboot(void);
 
+/*
+ * Save the provided hash digest to a secure location to check against in
+ * the resume path. Returns 0 on success, < 0 on error.
+ */
+int vboot_save_hash(void *digest, size_t digest_size);
+
+/*
+ * Retrieve the previously saved hash digest.  Returns 0 on success,
+ * < 0 on error.
+ */
+int vboot_retrieve_hash(void *digest, size_t digest_size);
+
+/*
+ * Determine if the platform is resuming from suspend. Returns 0 when
+ * not resuming, > 0 if resuming, and < 0 on error.
+ */
+int vboot_platform_is_resuming(void);
+
 /* Main logic for verified boot. verstage() is the stage entry point
  * while the verstage_main() is just the core logic. */
 void verstage_main(void);



More information about the coreboot-gerrit mailing list