@@ -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);
@@ -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
@@ -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);
@@ -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
@@ -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();
@@ -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);
@@ -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
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(+)