diff mbox series

[u-boot,v2019.04-aspeed-openbmc,3/4] bootm: Support boot measurement

Message ID 20230125173025.3725606-4-eajames@linux.ibm.com
State New
Headers show
Series tpm: Support boot measurements | expand

Commit Message

Eddie James Jan. 25, 2023, 5:30 p.m. UTC
Add a configuration option to measure the boot through the bootm
function. Add the measurement state to the booti and bootz paths
as well.

Signed-off-by: Eddie James <eajames@linux.ibm.com>
---
 cmd/booti.c     |  1 +
 cmd/bootm.c     |  1 +
 cmd/bootz.c     |  1 +
 common/Kconfig  | 23 ++++++++++++++++++
 common/bootm.c  | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/bootm.h |  2 ++
 include/image.h |  1 +
 7 files changed, 93 insertions(+)
diff mbox series

Patch

diff --git a/cmd/booti.c b/cmd/booti.c
index 04353b68ec..a7ea670d1e 100644
--- a/cmd/booti.c
+++ b/cmd/booti.c
@@ -82,6 +82,7 @@  int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
 			      BOOTM_STATE_RAMDISK |
 #endif
+			      BOOTM_STATE_MEASURE |
 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
 			      BOOTM_STATE_OS_GO,
 			      &images, 1);
diff --git a/cmd/bootm.c b/cmd/bootm.c
index c3a063474a..313d895ead 100644
--- a/cmd/bootm.c
+++ b/cmd/bootm.c
@@ -128,6 +128,7 @@  int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
 		BOOTM_STATE_RAMDISK |
 #endif
+		BOOTM_STATE_MEASURE |
 #if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
 		BOOTM_STATE_OS_CMDLINE |
 #endif
diff --git a/cmd/bootz.c b/cmd/bootz.c
index 0e75509ee9..e8622aa4e7 100644
--- a/cmd/bootz.c
+++ b/cmd/bootz.c
@@ -78,6 +78,7 @@  int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
 			      BOOTM_STATE_RAMDISK |
 #endif
+			      BOOTM_STATE_MEASURE |
 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
 			      BOOTM_STATE_OS_GO,
 			      &images, 1);
diff --git a/common/Kconfig b/common/Kconfig
index 1a1951f874..6483add286 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -794,6 +794,29 @@  config TPL_HASH
 
 endmenu
 
+config MEASURED_BOOT
+	bool "Measure boot images and configuration to TPM and event log"
+	depends on HASH && TPM_V2
+	help
+	  This option enables measurement of the boot process. Measurement
+	  involves creating cryptographic hashes of the binary images that
+	  are booting and storing them in the TPM. In addition, a log of
+	  these hashes is stored in memory for the OS to verify the booted
+	  images and configuration. Enable this if the OS has configured
+	  some memory area for the event log and you intend to use some
+	  attestation tools on your system.
+
+if MEASURED_BOOT
+	config MEASURE_DEVICETREE
+	bool "Measure the devicetree image"
+	default y if MEASURED_BOOT
+	help
+	  On some platforms, the devicetree is not static as it may contain
+	  random MAC addresses or other such data that changes each boot.
+	  Therefore, it should not be measured into the TPM. In that case,
+	  disable the measurement here.
+endif # MEASURED_BOOT
+
 menu "Update support"
 
 config UPDATE_TFTP
diff --git a/common/bootm.c b/common/bootm.c
index 3adbceaa38..5ef7b3064f 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -18,6 +18,7 @@ 
 #include <lzma/LzmaTypes.h>
 #include <lzma/LzmaDec.h>
 #include <lzma/LzmaTools.h>
+#include <tpm-v2.h>
 #if defined(CONFIG_CMD_USB)
 #include <usb.h>
 #endif
@@ -599,6 +600,66 @@  static void fixup_silent_linux(void)
 }
 #endif /* CONFIG_SILENT_CONSOLE */
 
+int bootm_measure(struct bootm_headers *images)
+{
+	int ret = 0;
+
+	if (IS_ENABLED(CONFIG_MEASURED_BOOT)) {
+		struct tcg2_event_log elog;
+		struct udevice *dev;
+		void *initrd_buf;
+		void *image_buf;
+		const char *s;
+		u32 rd_len;
+
+		ret = tcg2_measurement_init(&dev, &elog);
+		if (ret)
+			return ret;
+
+		image_buf = map_sysmem(images->os.image_start,
+				       images->os.image_len);
+		ret = tcg2_measure_data(dev, &elog, 8, images->os.image_len,
+					image_buf, EV_COMPACT_HASH,
+					strlen("linux") + 1, (u8 *)"linux");
+		if (ret)
+			goto unmap_image;
+
+		rd_len = images->rd_end - images->rd_start;
+		initrd_buf = map_sysmem(images->rd_start, rd_len);
+		ret = tcg2_measure_data(dev, &elog, 8, rd_len, initrd_buf,
+					EV_COMPACT_HASH, strlen("initrd") + 1,
+					(u8 *)"initrd");
+		if (ret)
+			goto unmap_initrd;
+
+		if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) {
+			ret = tcg2_measure_data(dev, &elog, 9, images->ft_len,
+						(u8 *)images->ft_addr,
+						EV_TABLE_OF_DEVICES,
+						strlen("dts") + 1,
+						(u8 *)"dts");
+			if (ret)
+				goto unmap_initrd;
+		}
+
+		s = env_get("bootargs");
+		if (!s)
+			s = "";
+		ret = tcg2_measure_data(dev, &elog, 1, strlen(s) + 1, (u8 *)s,
+					EV_PLATFORM_CONFIG_FLAGS,
+					strlen(s) + 1, (u8 *)s);
+
+unmap_initrd:
+		unmap_sysmem(initrd_buf);
+
+unmap_image:
+		unmap_sysmem(image_buf);
+		tcg2_measurement_term(dev, &elog, ret != 0);
+	}
+
+	return ret;
+}
+
 /**
  * Execute selected states of the bootm command.
  *
@@ -646,6 +707,9 @@  int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
 	if (!ret && (states & BOOTM_STATE_FINDOTHER))
 		ret = bootm_find_other(cmdtp, flag, argc, argv);
 
+	if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !ret && (states & BOOTM_STATE_MEASURE))
+		bootm_measure(images);
+
 	/* Load the OS */
 	if (!ret && (states & BOOTM_STATE_LOADOS)) {
 		iflag = bootm_disable_interrupts();
diff --git a/include/bootm.h b/include/bootm.h
index e2cc6d4b99..fe70c1e824 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -52,6 +52,8 @@  ulong bootm_disable_interrupts(void);
 /* This is a special function used by booti/bootz */
 int bootm_find_images(int flag, int argc, char * const argv[]);
 
+int bootm_measure(struct bootm_headers *images);
+
 int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
 		    int states, bootm_headers_t *images, int boot_progress);
 
diff --git a/include/image.h b/include/image.h
index 937c7eee8f..41cb147571 100644
--- a/include/image.h
+++ b/include/image.h
@@ -420,6 +420,7 @@  typedef struct bootm_headers {
 #define	BOOTM_STATE_OS_PREP	(0x00000100)
 #define	BOOTM_STATE_OS_FAKE_GO	(0x00000200)	/* 'Almost' run the OS */
 #define	BOOTM_STATE_OS_GO	(0x00000400)
+#define BOOTM_STATE_MEASURE	(0x00001000)
 	int		state;
 
 #ifdef CONFIG_LMB