[coreboot-gerrit] Patch set updated for coreboot: commonlib: Add function to hash contents of a CBFS region.

Aaron Durbin (adurbin@chromium.org) gerrit at coreboot.org
Tue Jan 5 17:42:15 CET 2016


Aaron Durbin (adurbin at chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12786

-gerrit

commit 480424082c6ba5d93a4d4a5bda7b9563096abcd1
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Tue Dec 15 15:57:11 2015 -0600

    commonlib: Add function to hash contents of a CBFS region.
    
    Provide a common routine to hash the contents of a cbfs
    region. The cbfs region is hashed in the following order:
    1. potential cbfs header at offset 0
    2. potential cbfs header retlative offset at cbfs size - 4
    3. For each file the metadata of the file.
    4. For each non-empty file the data of the file.
    
    BUG=chrome-os-partner:48412
    BUG=chromium:445938
    BRANCH=None
    TEST=Utilized in chromeos cros_bundle_firmware as well as at
          runtime during vboot verification on glados.
    
    Change-Id: Ie1e5db5b8a80d9465e88d3f69f5367d887bdf73f
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 Makefile.inc                                |   2 +
 src/commonlib/cbfs.c                        | 158 +++++++++++++++++++++++++++-
 src/commonlib/include/commonlib/cbfs.h      |  12 +++
 src/vendorcode/amd/pi/Makefile.inc          |   1 +
 src/vendorcode/google/chromeos/Makefile.inc |   2 -
 5 files changed, 168 insertions(+), 7 deletions(-)

diff --git a/Makefile.inc b/Makefile.inc
index 000ad63..76a828a 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -301,6 +301,8 @@ endif
 
 CPPFLAGS_common := -Isrc -Isrc/include -Isrc/commonlib/include -I$(obj)
 CPPFLAGS_common += -Isrc/device/oprom/include
+VB_SOURCE ?= 3rdparty/vboot
+CPPFLAGS_common += -I$(VB_SOURCE)/firmware/include
 CPPFLAGS_common += -include $(src)/include/kconfig.h
 
 CFLAGS_common += -pipe -g -nostdinc
diff --git a/src/commonlib/cbfs.c b/src/commonlib/cbfs.c
index 06d31ed..56faf28 100644
--- a/src/commonlib/cbfs.c
+++ b/src/commonlib/cbfs.c
@@ -108,6 +108,19 @@ int cbfs_for_each_file(const struct region_device *cbfs,
 	return -1;
 }
 
+static int cbfsf_file_type(struct cbfsf *fh, uint32_t *ftype)
+{
+	const size_t sz = sizeof(*ftype);
+
+	if (rdev_readat(&fh->metadata, ftype,
+			offsetof(struct cbfs_file, type), sz) != sz)
+		return -1;
+
+	*ftype = read_be32(ftype);
+
+	return 0;
+}
+
 int cbfs_locate(struct cbfsf *fh, const struct region_device *cbfs,
 		const char *name, uint32_t *type)
 {
@@ -148,13 +161,9 @@ int cbfs_locate(struct cbfsf *fh, const struct region_device *cbfs,
 		if (type != NULL) {
 			uint32_t ftype;
 
-			if (rdev_readat(&fh->metadata, &ftype,
-					offsetof(struct cbfs_file, type),
-					sizeof(ftype)) != sizeof(ftype))
+			if (cbfsf_file_type(fh, &ftype))
 				break;
 
-			ftype = read_be32(&ftype);
-
 			if (*type != ftype) {
 				DEBUG(" Unmatched type %x at %zx\n", ftype,
 					rdev_relative_offset(cbfs,
@@ -174,3 +183,142 @@ int cbfs_locate(struct cbfsf *fh, const struct region_device *cbfs,
 	LOG("'%s' not found.\n", name);
 	return -1;
 }
+
+static int cbfs_extend_hash_buffer(struct vb2_digest_context *ctx,
+					void *buf, size_t sz)
+{
+	return vb2_digest_extend(ctx, buf, sz);
+}
+
+static int cbfs_extend_hash(struct vb2_digest_context *ctx,
+				const struct region_device *rdev)
+{
+	uint8_t buffer[1024];
+	size_t sz_left;
+	size_t offset;
+
+	sz_left = region_device_sz(rdev);
+	offset = 0;
+
+	while (sz_left) {
+		int rv;
+		size_t block_sz = MIN(sz_left, sizeof(buffer));
+
+		if (rdev_readat(rdev, buffer, offset, block_sz) != block_sz)
+			return VB2_ERROR_UNKNOWN;
+
+		rv = cbfs_extend_hash_buffer(ctx, buffer, block_sz);
+
+		if (rv)
+			return rv;
+
+		sz_left -= block_sz;
+		offset += block_sz;
+	}
+
+	return VB2_SUCCESS;
+}
+
+/* Include offsets of child regions within the parent into the hash. */
+static int cbfs_extend_hash_with_offset(struct vb2_digest_context *ctx,
+					const struct region_device *p,
+					const struct region_device *c)
+{
+	int32_t soffset;
+	int rv;
+
+	soffset = rdev_relative_offset(p, c);
+
+	if (soffset < 0)
+		return VB2_ERROR_UNKNOWN;
+
+	/* All offsets in big endian format. */
+	write_be32(&soffset, soffset);
+
+	rv = cbfs_extend_hash_buffer(ctx, &soffset, sizeof(soffset));
+
+	if (rv)
+		return rv;
+
+	return cbfs_extend_hash(ctx, c);
+}
+
+/* Hash in the potential CBFS header sitting at the beginning of the CBFS
+ * region as well as relative offset at the end. */
+static int cbfs_extend_hash_master_header(struct vb2_digest_context *ctx,
+					const struct region_device *cbfs)
+{
+	struct region_device rdev;
+	int rv;
+
+	if (rdev_chain(&rdev, cbfs, 0, sizeof(struct cbfs_header)))
+		return VB2_ERROR_UNKNOWN;
+
+	rv = cbfs_extend_hash_with_offset(ctx, cbfs, &rdev);
+
+	if (rv)
+		return rv;
+
+	/* Include potential relative offset at end of region. */
+	if (rdev_chain(&rdev, cbfs, region_device_sz(cbfs) - sizeof(int32_t),
+			sizeof(int32_t)))
+		return VB2_ERROR_UNKNOWN;
+
+	return cbfs_extend_hash_with_offset(ctx, cbfs, &rdev);
+}
+
+int cbfs_vb2_hash_contents(const struct region_device *cbfs,
+				enum vb2_hash_algorithm hash_alg, void *digest,
+				size_t digest_sz)
+{
+	struct vb2_digest_context ctx;
+	int rv;
+	struct cbfsf f;
+	struct cbfsf *prev;
+	struct cbfsf *fh;
+
+	rv = vb2_digest_init(&ctx, hash_alg);
+
+	if (rv)
+		return rv;
+
+	rv = cbfs_extend_hash_master_header(&ctx, cbfs);
+	if (rv)
+		return rv;
+
+	prev = NULL;
+	fh = &f;
+
+	while (1) {
+		uint32_t ftype;
+
+		rv = cbfs_for_each_file(cbfs, prev, fh);
+		prev = fh;
+
+		if (rv < 0)
+			return VB2_ERROR_UNKNOWN;
+
+		/* End of CBFS. */
+		if (rv > 0)
+			break;
+
+		rv = cbfs_extend_hash_with_offset(&ctx, cbfs, &fh->metadata);
+
+		if (rv)
+			return rv;
+
+		/* Include data contents in hash if file is non-empty. */
+		if (cbfsf_file_type(fh, &ftype))
+			return VB2_ERROR_UNKNOWN;
+
+		if (ftype == CBFS_TYPE_DELETED || ftype == CBFS_TYPE_DELETED2)
+			continue;
+
+		rv = cbfs_extend_hash_with_offset(&ctx, cbfs, &fh->data);
+
+		if (rv)
+			return rv;
+	}
+
+	return vb2_digest_finalize(&ctx, digest, digest_sz);
+}
diff --git a/src/commonlib/include/commonlib/cbfs.h b/src/commonlib/include/commonlib/cbfs.h
index b0a468c..c74dd70 100644
--- a/src/commonlib/include/commonlib/cbfs.h
+++ b/src/commonlib/include/commonlib/cbfs.h
@@ -18,6 +18,9 @@
 
 #include <commonlib/cbfs_serialized.h>
 #include <commonlib/region.h>
+/* TODO: remove me! This is for vboot_handoff.c's benefit. */
+#define NEED_VB20_INTERNALS
+#include <vb2_api.h>
 
 /* Object representing cbfs files. */
 struct cbfsf {
@@ -52,4 +55,13 @@ static inline void cbfs_file_metadata(struct region_device *metadata,
 int cbfs_for_each_file(const struct region_device *cbfs,
 			const struct cbfsf *prev, struct cbfsf *fh);
 
+/*
+ * Perform the vb2 hash over the CBFS region skipping empty file contents.
+ * Caller is responsible for providing the hash algorithm as well as storage
+ * for the final digest. Return 0 on success or non-zero on error.
+ */
+int cbfs_vb2_hash_contents(const struct region_device *cbfs,
+				enum vb2_hash_algorithm hash_alg, void *digest,
+				size_t digest_sz);
+
 #endif
diff --git a/src/vendorcode/amd/pi/Makefile.inc b/src/vendorcode/amd/pi/Makefile.inc
index bb383b9..79d6171 100644
--- a/src/vendorcode/amd/pi/Makefile.inc
+++ b/src/vendorcode/amd/pi/Makefile.inc
@@ -62,6 +62,7 @@ AGESA_INC += -I$(src)/southbridge/amd/pi/hudson
 AGESA_INC += -I$(src)/arch/x86/include
 AGESA_INC += -I$(src)/include
 AGESA_INC += -I$(src)/commonlib/include
+AGESA_INC += -I$(VB_SOURCE)/firmware/include
 
 AGESA_CFLAGS += -march=amdfam10 -mno-3dnow -fno-zero-initialized-in-bss -fno-strict-aliasing
 CFLAGS_x86_32 += $(AGESA_CFLAGS)
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
index ef84798..00fcd2f 100644
--- a/src/vendorcode/google/chromeos/Makefile.inc
+++ b/src/vendorcode/google/chromeos/Makefile.inc
@@ -49,6 +49,4 @@ else
 CFLAGS_common += -DMOCK_TPM=0
 endif
 
-VB_SOURCE ?= 3rdparty/vboot
 subdirs-$(CONFIG_VBOOT_VERIFY_FIRMWARE) += vboot2
-CPPFLAGS_common += -I$(VB_SOURCE)/firmware/include



More information about the coreboot-gerrit mailing list