diff options
author | Eddie James <eajames@linux.ibm.com> | 2023-10-24 10:43:50 -0500 |
---|---|---|
committer | Ilias Apalodimas <ilias.apalodimas@linaro.org> | 2023-10-27 13:15:57 +0300 |
commit | dec166d6b2c28d971394ebe1bc0ac70b88b575c0 (patch) | |
tree | ef358001d2c0b68a23a24bb42fbf2c96b187f22c /boot | |
parent | 97707f12fdabf5fab5942504dab711a665854942 (diff) |
bootm: Support boot measurement
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>
Reviewed-by: Simon Glass <sjg@chromium.org>
Ilias: Added some info on Kconfig explaining this is when booting !EFI
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Diffstat (limited to 'boot')
-rw-r--r-- | boot/Kconfig | 32 | ||||
-rw-r--r-- | boot/bootm.c | 74 |
2 files changed, 106 insertions, 0 deletions
diff --git a/boot/Kconfig b/boot/Kconfig index a01e6cb8aa..fbc49c5bca 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -685,6 +685,38 @@ 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 when booting without EFI" + depends on HASH && TPM_V2 + help + This option enables measurement of the boot process when booting + without UEFI . 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. + + config MEASURE_IGNORE_LOG + bool "Ignore the existing event log" + default n + help + On platforms that use an event log memory region that persists + through system resets and are the first stage bootloader, then + this option should be enabled to ignore any existing data in the + event log memory region. +endif # MEASURED_BOOT + config SUPPORT_RAW_INITRD bool "Enable raw initrd images" help diff --git a/boot/bootm.c b/boot/bootm.c index b1c3afe0a3..11b6b3c292 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 @@ -673,6 +674,75 @@ 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; + bool ign; + + elog.log_size = 0; + ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG); + ret = tcg2_measurement_init(&dev, &elog, ign); + 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. * @@ -724,6 +794,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(); |