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 <eaja...@linux.ibm.com>
Reviewed-by: Simon Glass <s...@chromium.org>
---
Changes since v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure

 boot/Kconfig    | 23 ++++++++++++++++
 boot/bootm.c    | 72 +++++++++++++++++++++++++++++++++++++++++++++++++
 cmd/booti.c     |  1 +
 cmd/bootm.c     |  2 ++
 cmd/bootz.c     |  1 +
 include/bootm.h | 11 ++++++++
 include/image.h |  1 +
 7 files changed, 111 insertions(+)

diff --git a/boot/Kconfig b/boot/Kconfig
index 5f491625c8..d0d5e5794c 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -629,6 +629,29 @@ config LEGACY_IMAGE_FORMAT
          loaded. If a board needs the legacy image format support in this
          case, enable it here.
 
+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
+
 config SUPPORT_RAW_INITRD
        bool "Enable raw initrd images"
        help
diff --git a/boot/bootm.c b/boot/bootm.c
index 2eec60ec7b..e3ef18166d 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -22,6 +22,7 @@
 #include <asm/global_data.h>
 #include <asm/io.h>
 #include <linux/sizes.h>
+#include <tpm-v2.h>
 #if defined(CONFIG_CMD_USB)
 #include <usb.h>
 #endif
@@ -659,6 +660,73 @@ int bootm_process_cmdline_env(int flags)
        return 0;
 }
 
+int bootm_measure(struct bootm_headers *images)
+{
+       int ret = 0;
+
+       /* Skip measurement if EFI is going to do it */
+       if (images->os.os == IH_OS_EFI &&
+           IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) &&
+           IS_ENABLED(CONFIG_BOOTM_EFI))
+               return ret;
+
+       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;
+
+               elog.log_size = 0;
+               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, 9, 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, 0, 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.
  *
@@ -710,6 +778,10 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int 
argc,
        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/cmd/booti.c b/cmd/booti.c
index 6ac39193db..659bb10549 100644
--- a/cmd/booti.c
+++ b/cmd/booti.c
@@ -127,6 +127,7 @@ int do_booti(struct cmd_tbl *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 37c2af96e0..0c4a713e02 100644
--- a/cmd/bootm.c
+++ b/cmd/bootm.c
@@ -161,6 +161,8 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
                BOOTM_STATE_OS_GO;
        if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
                states |= BOOTM_STATE_RAMDISK;
+       if (IS_ENABLED(CONFIG_MEASURED_BOOT))
+               states |= BOOTM_STATE_MEASURE;
        if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
                states |= BOOTM_STATE_OS_CMDLINE;
        ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images, 1);
diff --git a/cmd/bootz.c b/cmd/bootz.c
index f1423573d2..87922bfc3c 100644
--- a/cmd/bootz.c
+++ b/cmd/bootz.c
@@ -81,6 +81,7 @@ int do_bootz(struct cmd_tbl *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/include/bootm.h b/include/bootm.h
index 044a4797ed..76e8e38c82 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -55,6 +55,17 @@ ulong bootm_disable_interrupts(void);
 int bootm_find_images(int flag, int argc, char *const argv[], ulong start,
                      ulong size);
 
+/*
+ * Measure the boot images. Measurement is the process of hashing some binary
+ * data and storing it into secure memory, i.e. TPM PCRs. In addition, each
+ * measurement is logged into the platform event log such that the operating
+ * system can access it and perform attestation of the boot.
+ *
+ * @images:    The structure containing the various images to boot (linux,
+ *             initrd, dts, etc.)
+ */
+int bootm_measure(struct bootm_headers *images);
+
 int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
                    char *const argv[], int states, struct bootm_headers 
*images,
                    int boot_progress);
diff --git a/include/image.h b/include/image.h
index 7717a4c13d..f7414b5338 100644
--- a/include/image.h
+++ b/include/image.h
@@ -407,6 +407,7 @@ struct bootm_headers {
 #define BOOTM_STATE_OS_FAKE_GO 0x00000200      /* 'Almost' run the OS */
 #define BOOTM_STATE_OS_GO      0x00000400
 #define BOOTM_STATE_PRE_LOAD   0x00000800
+#define BOOTM_STATE_MEASURE    0x00001000
        int             state;
 
 #if defined(CONFIG_LMB) && !defined(USE_HOSTCC)
-- 
2.31.1

Reply via email to