diff options
Diffstat (limited to 'lib/efi_loader')
-rw-r--r-- | lib/efi_loader/Kconfig | 19 | ||||
-rw-r--r-- | lib/efi_loader/efi_capsule.c | 48 | ||||
-rw-r--r-- | lib/efi_loader/efi_setup.c | 7 | ||||
-rw-r--r-- | lib/efi_loader/efi_tcg2.c | 73 | ||||
-rw-r--r-- | lib/efi_loader/efi_var_mem.c | 4 | ||||
-rw-r--r-- | lib/efi_loader/efi_variable.c | 3 |
6 files changed, 135 insertions, 19 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c56904afc2..c5835e6ef6 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -226,6 +226,14 @@ config EFI_CAPSULE_AUTHENTICATE Select this option if you want to enable capsule authentication +config EFI_CAPSULE_MAX + int "Max value for capsule index" + default 15 + range 0 65535 + help + Select the max capsule index value used for capsule report + variables. This value is used to create CapsuleMax variable. + config EFI_DEVICE_PATH_TO_TEXT bool "Device path to text protocol" default y @@ -346,6 +354,17 @@ config EFI_TCG2_PROTOCOL_EVENTLOG_SIZE this is going to be allocated twice. One for the eventlog it self and one for the configuration table that is required from the spec +config EFI_TCG2_PROTOCOL_MEASURE_DTB + bool "Measure DTB with EFI_TCG2_PROTOCOL" + depends on EFI_TCG2_PROTOCOL + help + When enabled, the DTB image passed to the booted EFI image is + measured using the EFI TCG2 protocol. Do not enable this feature if + the passed DTB contains data that change across platform reboots + and cannot be used has a predictable measurement. Otherwise + this feature allows better measurement of the system boot + sequence. + config EFI_LOAD_FILE2_INITRD bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk" default y diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 0997cd248f..d5d3ede7ae 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -45,17 +45,7 @@ const efi_guid_t fwu_guid_os_request_fw_accept = static struct efi_file_handle *bootdev_root; #endif -/** - * get_last_capsule - get the last capsule index - * - * Retrieve the index of the capsule invoked last time from "CapsuleLast" - * variable. - * - * Return: - * * > 0 - the last capsule index invoked - * * 0xffff - on error, or no capsule invoked yet - */ -static __maybe_unused unsigned int get_last_capsule(void) +static __maybe_unused unsigned int get_capsule_index(const u16 *variable_name) { u16 value16[11]; /* "CapsuleXXXX": non-null-terminated */ char value[5]; @@ -65,7 +55,7 @@ static __maybe_unused unsigned int get_last_capsule(void) int i; size = sizeof(value16); - ret = efi_get_variable_int(u"CapsuleLast", &efi_guid_capsule_report, + ret = efi_get_variable_int(variable_name, &efi_guid_capsule_report, NULL, &size, value16, NULL); if (ret != EFI_SUCCESS || size != 22 || u16_strncmp(value16, u"Capsule", 7)) @@ -85,6 +75,35 @@ err: } /** + * get_last_capsule - get the last capsule index + * + * Retrieve the index of the capsule invoked last time from "CapsuleLast" + * variable. + * + * Return: + * * > 0 - the last capsule index invoked + * * 0xffff - on error, or no capsule invoked yet + */ +static __maybe_unused unsigned int get_last_capsule(void) +{ + return get_capsule_index(u"CapsuleLast"); +} + +/** + * get_max_capsule - get the max capsule index + * + * Retrieve the max capsule index value from "CapsuleMax" variable. + * + * Return: + * * > 0 - the max capsule index + * * 0xffff - on error, or "CapsuleMax" variable does not exist + */ +static __maybe_unused unsigned int get_max_capsule(void) +{ + return get_capsule_index(u"CapsuleMax"); +} + +/** * set_capsule_result - set a result variable * @capsule: Capsule * @return_status: Return status @@ -1290,7 +1309,7 @@ efi_status_t efi_launch_capsules(void) { struct efi_capsule_header *capsule = NULL; u16 **files; - unsigned int nfiles, index, i; + unsigned int nfiles, index, index_max, i; efi_status_t ret; bool capsule_update = true; bool update_status = true; @@ -1299,6 +1318,7 @@ efi_status_t efi_launch_capsules(void) if (check_run_capsules() != EFI_SUCCESS) return EFI_SUCCESS; + index_max = get_max_capsule(); index = get_last_capsule(); /* @@ -1317,7 +1337,7 @@ efi_status_t efi_launch_capsules(void) /* Launch capsules */ for (i = 0, ++index; i < nfiles; i++, index++) { log_debug("Applying %ls\n", files[i]); - if (index > 0xffff) + if (index > index_max) index = 0; ret = efi_capsule_read_file(files[i], &capsule); if (ret == EFI_SUCCESS) { diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 69aaefab63..58d4e13402 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -130,12 +130,17 @@ static efi_status_t efi_init_capsule(void) efi_status_t ret = EFI_SUCCESS; if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)) { + u16 var_name16[12]; + + efi_create_indexed_name(var_name16, sizeof(var_name16), + "Capsule", CONFIG_EFI_CAPSULE_MAX); + ret = efi_set_variable_int(u"CapsuleMax", &efi_guid_capsule_report, EFI_VARIABLE_READ_ONLY | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - 22, u"CapsuleFFFF", false); + 22, var_name16, false); if (ret != EFI_SUCCESS) printf("EFI: cannot initialize CapsuleMax variable\n"); } diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 918e9a2686..2dcc317157 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -2175,6 +2175,79 @@ out1: return ret; } +/* Return the byte size of reserved map area in DTB or -1 upon error */ +static ssize_t size_of_rsvmap(void *dtb) +{ + struct fdt_reserve_entry e; + ssize_t size_max; + ssize_t size; + u8 *rsvmap_base; + + rsvmap_base = (u8 *)dtb + fdt_off_mem_rsvmap(dtb); + size_max = fdt_totalsize(dtb) - fdt_off_mem_rsvmap(dtb); + size = 0; + + do { + memcpy(&e, rsvmap_base + size, sizeof(e)); + size += sizeof(e); + if (size > size_max) + return -1; + } while (e.size); + + return size; +} + +/** + * efi_tcg2_measure_dtb() - measure DTB passed to the OS + * + * @dtb: pointer to the device tree blob + * + * Return: status code + */ +efi_status_t efi_tcg2_measure_dtb(void *dtb) +{ + struct uefi_platform_firmware_blob2 *blob; + struct fdt_header *header; + sha256_context hash_ctx; + struct udevice *dev; + ssize_t rsvmap_size; + efi_status_t ret; + u32 event_size; + + if (!is_tcg2_protocol_installed()) + return EFI_SUCCESS; + + ret = platform_get_tpm2_device(&dev); + if (ret != EFI_SUCCESS) + return EFI_SECURITY_VIOLATION; + + rsvmap_size = size_of_rsvmap(dtb); + if (rsvmap_size < 0) + return EFI_SECURITY_VIOLATION; + + event_size = sizeof(*blob) + sizeof(EFI_DTB_EVENT_STRING) + SHA256_SUM_LEN; + blob = calloc(1, event_size); + if (!blob) + return EFI_OUT_OF_RESOURCES; + + blob->blob_description_size = sizeof(EFI_DTB_EVENT_STRING); + memcpy(blob->data, EFI_DTB_EVENT_STRING, blob->blob_description_size); + + /* Measure populated areas of the DTB */ + header = dtb; + sha256_starts(&hash_ctx); + sha256_update(&hash_ctx, (u8 *)header, sizeof(struct fdt_header)); + sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_dt_struct(dtb), fdt_size_dt_strings(dtb)); + sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_dt_strings(dtb), fdt_size_dt_struct(dtb)); + sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_mem_rsvmap(dtb), rsvmap_size); + sha256_finish(&hash_ctx, blob->data + blob->blob_description_size); + + ret = tcg2_measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob); + + free(blob); + return ret; +} + /** * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation * diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c index e1058e3c6a..d6b65aed12 100644 --- a/lib/efi_loader/efi_var_mem.c +++ b/lib/efi_loader/efi_var_mem.c @@ -41,11 +41,13 @@ efi_var_mem_compare(struct efi_var_entry *var, const efi_guid_t *guid, i < sizeof(efi_guid_t) && match; ++i) match = (guid1[i] == guid2[i]); - for (data = var->name, var_name = name;; ++data, ++var_name) { + for (data = var->name, var_name = name;; ++data) { if (match) match = (*data == *var_name); if (!*data) break; + if (*var_name) + ++var_name; } ++data; diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 4c85cfa607..5804f69954 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -366,9 +366,6 @@ efi_status_t efi_query_variable_info_int(u32 attributes, EFI_VARIABLE_RUNTIME_ACCESS) return EFI_INVALID_PARAMETER; - if (attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) - return EFI_UNSUPPORTED; - if (attributes & ~(u32)EFI_VARIABLE_MASK) return EFI_INVALID_PARAMETER; |