
Hi Eddie,
On Thu, 12 Jan 2023 at 09:16, Eddie James eajames@linux.ibm.com wrote:
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
boot/Kconfig | 23 ++++++++++++++++ boot/bootm.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ cmd/booti.c | 1 + cmd/bootm.c | 2 ++ cmd/bootz.c | 1 + include/bootm.h | 2 ++ include/image.h | 1 + 7 files changed, 100 insertions(+)
diff --git a/boot/Kconfig b/boot/Kconfig index 30bc182fcd..e90d61412e 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -587,6 +587,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 15fce8ad95..c8423f2c60 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,72 @@ 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)) {
Isn't this an EFI feature? I would expect MEASURED_BOOT to be a generic U-Boot feature that can be used by non-EFI code.
So I believe what we need here is some sort of API for measuring things, enabled by MEASURED_BOOT, with EFI providing its implementation (in lib/efi_loader/). Driver model would be a good approach I think, or perhaps a linker list as is done with the environment / partitions?
In any case, adding EFI code into bootm is a non-starter.
The first thing is to define what the API is, e.g. with a header file called measured_boot.h or similar.
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.
@@ -710,6 +777,9 @@ 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..06d8b1acd8 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -55,6 +55,8 @@ ulong bootm_disable_interrupts(void); int bootm_find_images(int flag, int argc, char *const argv[], ulong start, ulong size);
+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 bed75ce1b3..bd74e74a75 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
Regards, Simon