Message ID | 20210707133638.12630-4-masahisa.kojima@linaro.org |
---|---|
State | New |
Headers | show |
Series | add measurement support | expand |
Hi Kojima-san, > +{ [...] > + u16 *boot_order; > + u16 var_name[] = L"BootOrder"; > + u16 boot_name[] = L"Boot0000"; > + u16 hexmap[] = L"0123456789ABCDEF"; > + u8 *bootvar; > + efi_uintn_t var_data_size; > + u32 count, i; > + efi_status_t ret; > + > + boot_order = efi_get_var(var_name, &efi_global_variable_guid, > + &var_data_size); > + if (!boot_order) { > + log_info("BootOrder not defined\n"); > + ret = EFI_NOT_FOUND; > + goto error; > + } > + > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, var_name, > + &efi_global_variable_guid, var_data_size, > + (u8 *)boot_order); > + if (ret != EFI_SUCCESS) > + goto error; > + > + count = var_data_size / sizeof(*boot_order); > + for (i = 0; i < count; i++) { > + boot_name[4] = hexmap[(boot_order[i] & 0xf000) >> 12]; > + boot_name[5] = hexmap[(boot_order[i] & 0x0f00) >> 8]; > + boot_name[6] = hexmap[(boot_order[i] & 0x00f0) >> 4]; > + boot_name[7] = hexmap[(boot_order[i] & 0x000f)]; Can you use efi_create_indexed_name() instead? [...] > + for (pcr_index = 0; pcr_index <= 7; pcr_index++) { > + ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR, > + sizeof(event), (u8 *)&event); I assume adding a separator event on all these PCRs is described on the standard? > + if (ret != EFI_SUCCESS) > + goto out; > + } > + > + tcg2_efi_app_invoked = true; > +out: > + return ret; > +} > + > +/** > + * efi_tcg2_measure_efi_app_exit() - measure efi app exit > + * > + * Return: status code > + */ > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void) > +{ > + efi_status_t ret; > + struct udevice *dev; > + > + ret = platform_get_tpm2_device(&dev); > + if (ret != EFI_SUCCESS) > + return ret; > + > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > + strlen(EFI_RETURNING_FROM_EFI_APPLICATION), Do we need a NUL terminator on this string or not? Regards /Ilias
On Thu, 8 Jul 2021 at 03:56, Ilias Apalodimas <ilias.apalodimas@linaro.org> wrote: > > Hi Kojima-san, > > +{ > > [...] > > > + u16 *boot_order; > > + u16 var_name[] = L"BootOrder"; > > + u16 boot_name[] = L"Boot0000"; > > + u16 hexmap[] = L"0123456789ABCDEF"; > > + u8 *bootvar; > > + efi_uintn_t var_data_size; > > + u32 count, i; > > + efi_status_t ret; > > + > > + boot_order = efi_get_var(var_name, &efi_global_variable_guid, > > + &var_data_size); > > + if (!boot_order) { > > + log_info("BootOrder not defined\n"); > > + ret = EFI_NOT_FOUND; > > + goto error; > > + } > > + > > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, var_name, > > + &efi_global_variable_guid, var_data_size, > > + (u8 *)boot_order); > > + if (ret != EFI_SUCCESS) > > + goto error; > > + > > + count = var_data_size / sizeof(*boot_order); > > + for (i = 0; i < count; i++) { > > + boot_name[4] = hexmap[(boot_order[i] & 0xf000) >> 12]; > > + boot_name[5] = hexmap[(boot_order[i] & 0x0f00) >> 8]; > > + boot_name[6] = hexmap[(boot_order[i] & 0x00f0) >> 4]; > > + boot_name[7] = hexmap[(boot_order[i] & 0x000f)]; > > Can you use efi_create_indexed_name() instead? I have not noticed this utility function, thank you. > > [...] > > + for (pcr_index = 0; pcr_index <= 7; pcr_index++) { > > + ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR, > > + sizeof(event), (u8 *)&event); > > I assume adding a separator event on all these PCRs is described on the > standard? Yes, TCG spec requires EV_SEPARATOR event prior to the first invocation of the first Ready to Boot call. Spec also says EV_SEPARATOR must be the last entry for PCR0, 1, 2, 3, 6. > > > + if (ret != EFI_SUCCESS) > > + goto out; > > + } > > + > > + tcg2_efi_app_invoked = true; > > +out: > > + return ret; > > +} > > + > > +/** > > + * efi_tcg2_measure_efi_app_exit() - measure efi app exit > > + * > > + * Return: status code > > + */ > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void) > > +{ > > + efi_status_t ret; > > + struct udevice *dev; > > + > > + ret = platform_get_tpm2_device(&dev); > > + if (ret != EFI_SUCCESS) > > + return ret; > > + > > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > > + strlen(EFI_RETURNING_FROM_EFI_APPLICATION), > > Do we need a NUL terminator on this string or not? No, TCG spec says "the actual log entries SHALL NOT include the quote characters or a NUL terminator." Thanks, Masahisa Kojima > > > Regards > /Ilias
On 7/7/21 3:36 PM, Masahisa Kojima wrote: > TCG PC Client PFP spec requires to measure "Boot####" > and "BootOrder" variables, EV_SEPARATOR event prior > to the Ready to Boot invocation. > Since u-boot does not implement Ready to Boot event, > these measurements are performed when efi_start_image() is called. > > TCG spec also requires to measure "Calling EFI Application from > Boot Option" for each boot attempt, and "Returning from EFI > Application from Boot Option" if a boot device returns control > back to the Boot Manager. > > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> > --- > include/efi_loader.h | 4 ++ > include/tpm-v2.h | 18 ++++- > lib/efi_loader/efi_boottime.c | 20 ++++++ > lib/efi_loader/efi_tcg2.c | 123 ++++++++++++++++++++++++++++++++++ > 4 files changed, 164 insertions(+), 1 deletion(-) > > diff --git a/include/efi_loader.h b/include/efi_loader.h > index 0a9c82a257..281ffff30f 100644 > --- a/include/efi_loader.h > +++ b/include/efi_loader.h > @@ -407,6 +407,10 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size); > efi_status_t efi_init_variables(void); > /* Notify ExitBootServices() is called */ > void efi_variables_boot_exit_notify(void); > +/* Measure efi application invocation */ > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void); > +/* Measure efi application exit */ > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void); > /* Called by bootefi to initialize root node */ > efi_status_t efi_root_node_register(void); > /* Called by bootefi to initialize runtime */ > diff --git a/include/tpm-v2.h b/include/tpm-v2.h > index 3e48e35861..8a7b7f1874 100644 > --- a/include/tpm-v2.h > +++ b/include/tpm-v2.h > @@ -73,7 +73,7 @@ struct udevice; > /* > * event types, cf. > * "TCG PC Client Platform Firmware Profile Specification", Family "2.0" > - * rev 1.04, June 3, 2019 > + * Level 00 Version 1.05 Revision 23, May 7, 2021 > */ > #define EV_EFI_EVENT_BASE ((u32)0x80000000) > #define EV_EFI_VARIABLE_DRIVER_CONFIG ((u32)0x80000001) > @@ -85,8 +85,24 @@ struct udevice; > #define EV_EFI_ACTION ((u32)0x80000007) > #define EV_EFI_PLATFORM_FIRMWARE_BLOB ((u32)0x80000008) > #define EV_EFI_HANDOFF_TABLES ((u32)0x80000009) > +#define EV_EFI_PLATFORM_FIRMWARE_BLOB2 ((u32)0x8000000A) > +#define EV_EFI_HANDOFF_TABLES2 ((u32)0x8000000B) > +#define EV_EFI_VARIABLE_BOOT2 ((u32)0x8000000C) > #define EV_EFI_HCRTM_EVENT ((u32)0x80000010) > #define EV_EFI_VARIABLE_AUTHORITY ((u32)0x800000E0) > +#define EV_EFI_SPDM_FIRMWARE_BLOB ((u32)0x800000E1) > +#define EV_EFI_SPDM_FIRMWARE_CONFIG ((u32)0x800000E2) > + > +#define EFI_CALLING_EFI_APPLICATION \ > + "Calling EFI Application from Boot Option" > +#define EFI_RETURNING_FROM_EFI_APPLICATION \ > + "Returning from EFI Application from Boot Option" > +#define EFI_EXIT_BOOT_SERVICES_INVOCATION \ > + "Exit Boot Services Invocation" > +#define EFI_EXIT_BOOT_SERVICES_FAILED \ > + "Exit Boot Services Returned with Failure" > +#define EFI_EXIT_BOOT_SERVICES_SUCCEEDED \ > + "Exit Boot Services Returned with Success" Which spec defines if the string in the event log shall be utf-8 or utf-16? Best regards Heinrich > > /* TPMS_TAGGED_PROPERTY Structure */ > struct tpms_tagged_property { > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > index f6d5ba05e3..2914800c56 100644 > --- a/lib/efi_loader/efi_boottime.c > +++ b/lib/efi_loader/efi_boottime.c > @@ -2993,6 +2993,16 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, > image_obj->exit_status = &exit_status; > image_obj->exit_jmp = &exit_jmp; > > + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { > + ret = efi_tcg2_measure_efi_app_invocation(); > + if (ret != EFI_SUCCESS) { > + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", > + ret); > + } > + } > + } > + > /* call the image! */ > if (setjmp(&exit_jmp)) { > /* > @@ -3251,6 +3261,16 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, > exit_status != EFI_SUCCESS) > efi_delete_image(image_obj, loaded_image_protocol); > > + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { > + ret = efi_tcg2_measure_efi_app_exit(); > + if (ret != EFI_SUCCESS) { > + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", > + ret); > + } > + } > + } > + > /* Make sure entry/exit counts for EFI world cross-overs match */ > EFI_EXIT(exit_status); > > diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c > index 2a248bd62a..6e903e3cb3 100644 > --- a/lib/efi_loader/efi_tcg2.c > +++ b/lib/efi_loader/efi_tcg2.c > @@ -35,6 +35,7 @@ struct event_log_buffer { > }; > > static struct event_log_buffer event_log; > +static bool tcg2_efi_app_invoked; > /* > * When requesting TPM2_CAP_TPM_PROPERTIES the value is on a standard offset. > * Since the current tpm2_get_capability() response buffers starts at > @@ -1383,6 +1384,128 @@ static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index, > return ret; > } > > +/** > + * tcg2_measure_boot_variable() - measure boot variables > + * > + * @dev: TPM device > + * > + * Return: status code > + */ > +static efi_status_t tcg2_measure_boot_variable(struct udevice *dev) > +{ > + u16 *boot_order; > + u16 var_name[] = L"BootOrder"; > + u16 boot_name[] = L"Boot0000"; > + u16 hexmap[] = L"0123456789ABCDEF"; > + u8 *bootvar; > + efi_uintn_t var_data_size; > + u32 count, i; > + efi_status_t ret; > + > + boot_order = efi_get_var(var_name, &efi_global_variable_guid, > + &var_data_size); > + if (!boot_order) { > + log_info("BootOrder not defined\n"); > + ret = EFI_NOT_FOUND; > + goto error; > + } > + > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, var_name, > + &efi_global_variable_guid, var_data_size, > + (u8 *)boot_order); > + if (ret != EFI_SUCCESS) > + goto error; > + > + count = var_data_size / sizeof(*boot_order); > + for (i = 0; i < count; i++) { > + boot_name[4] = hexmap[(boot_order[i] & 0xf000) >> 12]; > + boot_name[5] = hexmap[(boot_order[i] & 0x0f00) >> 8]; > + boot_name[6] = hexmap[(boot_order[i] & 0x00f0) >> 4]; > + boot_name[7] = hexmap[(boot_order[i] & 0x000f)]; > + > + bootvar = efi_get_var(boot_name, &efi_global_variable_guid, > + &var_data_size); > + > + if (!bootvar) { > + log_info("%ls not found\n", boot_name); > + continue; > + } > + > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, > + boot_name, > + &efi_global_variable_guid, > + var_data_size, bootvar); > + free(bootvar); > + if (ret != EFI_SUCCESS) > + goto error; > + } > + > +error: > + free(boot_order); > + return ret; > +} > + > +/** > + * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation > + * > + * Return: status code > + */ > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void) > +{ > + efi_status_t ret; > + u32 pcr_index; > + struct udevice *dev; > + u32 event = 0; > + > + if (tcg2_efi_app_invoked) > + return EFI_SUCCESS; > + > + ret = platform_get_tpm2_device(&dev); > + if (ret != EFI_SUCCESS) > + return ret; > + > + ret = tcg2_measure_boot_variable(dev); > + if (ret != EFI_SUCCESS) > + goto out; > + > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > + strlen(EFI_CALLING_EFI_APPLICATION), > + (u8 *)EFI_CALLING_EFI_APPLICATION); > + if (ret != EFI_SUCCESS) > + goto out; > + > + for (pcr_index = 0; pcr_index <= 7; pcr_index++) { > + ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR, > + sizeof(event), (u8 *)&event); > + if (ret != EFI_SUCCESS) > + goto out; > + } > + > + tcg2_efi_app_invoked = true; > +out: > + return ret; > +} > + > +/** > + * efi_tcg2_measure_efi_app_exit() - measure efi app exit > + * > + * Return: status code > + */ > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void) > +{ > + efi_status_t ret; > + struct udevice *dev; > + > + ret = platform_get_tpm2_device(&dev); > + if (ret != EFI_SUCCESS) > + return ret; > + > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > + strlen(EFI_RETURNING_FROM_EFI_APPLICATION), > + (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION); > + return ret; > +} > + > /** > * tcg2_measure_secure_boot_variable() - measure secure boot variables > * >
On Fri, 9 Jul 2021 at 02:46, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote: > > On 7/7/21 3:36 PM, Masahisa Kojima wrote: > > TCG PC Client PFP spec requires to measure "Boot####" > > and "BootOrder" variables, EV_SEPARATOR event prior > > to the Ready to Boot invocation. > > Since u-boot does not implement Ready to Boot event, > > these measurements are performed when efi_start_image() is called. > > > > TCG spec also requires to measure "Calling EFI Application from > > Boot Option" for each boot attempt, and "Returning from EFI > > Application from Boot Option" if a boot device returns control > > back to the Boot Manager. > > > > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> > > --- > > include/efi_loader.h | 4 ++ > > include/tpm-v2.h | 18 ++++- > > lib/efi_loader/efi_boottime.c | 20 ++++++ > > lib/efi_loader/efi_tcg2.c | 123 ++++++++++++++++++++++++++++++++++ > > 4 files changed, 164 insertions(+), 1 deletion(-) > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h > > index 0a9c82a257..281ffff30f 100644 > > --- a/include/efi_loader.h > > +++ b/include/efi_loader.h > > @@ -407,6 +407,10 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size); > > efi_status_t efi_init_variables(void); > > /* Notify ExitBootServices() is called */ > > void efi_variables_boot_exit_notify(void); > > +/* Measure efi application invocation */ > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void); > > +/* Measure efi application exit */ > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void); > > /* Called by bootefi to initialize root node */ > > efi_status_t efi_root_node_register(void); > > /* Called by bootefi to initialize runtime */ > > diff --git a/include/tpm-v2.h b/include/tpm-v2.h > > index 3e48e35861..8a7b7f1874 100644 > > --- a/include/tpm-v2.h > > +++ b/include/tpm-v2.h > > @@ -73,7 +73,7 @@ struct udevice; > > /* > > * event types, cf. > > * "TCG PC Client Platform Firmware Profile Specification", Family "2.0" > > - * rev 1.04, June 3, 2019 > > + * Level 00 Version 1.05 Revision 23, May 7, 2021 > > */ > > #define EV_EFI_EVENT_BASE ((u32)0x80000000) > > #define EV_EFI_VARIABLE_DRIVER_CONFIG ((u32)0x80000001) > > @@ -85,8 +85,24 @@ struct udevice; > > #define EV_EFI_ACTION ((u32)0x80000007) > > #define EV_EFI_PLATFORM_FIRMWARE_BLOB ((u32)0x80000008) > > #define EV_EFI_HANDOFF_TABLES ((u32)0x80000009) > > +#define EV_EFI_PLATFORM_FIRMWARE_BLOB2 ((u32)0x8000000A) > > +#define EV_EFI_HANDOFF_TABLES2 ((u32)0x8000000B) > > +#define EV_EFI_VARIABLE_BOOT2 ((u32)0x8000000C) > > #define EV_EFI_HCRTM_EVENT ((u32)0x80000010) > > #define EV_EFI_VARIABLE_AUTHORITY ((u32)0x800000E0) > > +#define EV_EFI_SPDM_FIRMWARE_BLOB ((u32)0x800000E1) > > +#define EV_EFI_SPDM_FIRMWARE_CONFIG ((u32)0x800000E2) > > + > > +#define EFI_CALLING_EFI_APPLICATION \ > > + "Calling EFI Application from Boot Option" > > +#define EFI_RETURNING_FROM_EFI_APPLICATION \ > > + "Returning from EFI Application from Boot Option" > > +#define EFI_EXIT_BOOT_SERVICES_INVOCATION \ > > + "Exit Boot Services Invocation" > > +#define EFI_EXIT_BOOT_SERVICES_FAILED \ > > + "Exit Boot Services Returned with Failure" > > +#define EFI_EXIT_BOOT_SERVICES_SUCCEEDED \ > > + "Exit Boot Services Returned with Success" > > Which spec defines if the string in the event log shall be utf-8 or utf-16? TCG PC Client PFP spec does not clearly define the character encoding. In my understanding, the string derived from UEFI spec such as UEFI variable name uses utf-16(CHAR16). Other strings like "Calling EFI Application from Boot Option" defind in TCG PC Client spec use 1 byte ASCII encoding. EDK2 implementation also uses 1 byte ASCII encoding for these strings, and tpm2-tools::tpm2_eventlog command can handles properly. Thanks, Masahisa Kojima > > Best regards > > Heinrich > > > > > /* TPMS_TAGGED_PROPERTY Structure */ > > struct tpms_tagged_property { > > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > > index f6d5ba05e3..2914800c56 100644 > > --- a/lib/efi_loader/efi_boottime.c > > +++ b/lib/efi_loader/efi_boottime.c > > @@ -2993,6 +2993,16 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, > > image_obj->exit_status = &exit_status; > > image_obj->exit_jmp = &exit_jmp; > > > > + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > > + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { > > + ret = efi_tcg2_measure_efi_app_invocation(); > > + if (ret != EFI_SUCCESS) { > > + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", > > + ret); > > + } > > + } > > + } > > + > > /* call the image! */ > > if (setjmp(&exit_jmp)) { > > /* > > @@ -3251,6 +3261,16 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, > > exit_status != EFI_SUCCESS) > > efi_delete_image(image_obj, loaded_image_protocol); > > > > + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > > + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { > > + ret = efi_tcg2_measure_efi_app_exit(); > > + if (ret != EFI_SUCCESS) { > > + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", > > + ret); > > + } > > + } > > + } > > + > > /* Make sure entry/exit counts for EFI world cross-overs match */ > > EFI_EXIT(exit_status); > > > > diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c > > index 2a248bd62a..6e903e3cb3 100644 > > --- a/lib/efi_loader/efi_tcg2.c > > +++ b/lib/efi_loader/efi_tcg2.c > > @@ -35,6 +35,7 @@ struct event_log_buffer { > > }; > > > > static struct event_log_buffer event_log; > > +static bool tcg2_efi_app_invoked; > > /* > > * When requesting TPM2_CAP_TPM_PROPERTIES the value is on a standard offset. > > * Since the current tpm2_get_capability() response buffers starts at > > @@ -1383,6 +1384,128 @@ static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index, > > return ret; > > } > > > > +/** > > + * tcg2_measure_boot_variable() - measure boot variables > > + * > > + * @dev: TPM device > > + * > > + * Return: status code > > + */ > > +static efi_status_t tcg2_measure_boot_variable(struct udevice *dev) > > +{ > > + u16 *boot_order; > > + u16 var_name[] = L"BootOrder"; > > + u16 boot_name[] = L"Boot0000"; > > + u16 hexmap[] = L"0123456789ABCDEF"; > > + u8 *bootvar; > > + efi_uintn_t var_data_size; > > + u32 count, i; > > + efi_status_t ret; > > + > > + boot_order = efi_get_var(var_name, &efi_global_variable_guid, > > + &var_data_size); > > + if (!boot_order) { > > + log_info("BootOrder not defined\n"); > > + ret = EFI_NOT_FOUND; > > + goto error; > > + } > > + > > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, var_name, > > + &efi_global_variable_guid, var_data_size, > > + (u8 *)boot_order); > > + if (ret != EFI_SUCCESS) > > + goto error; > > + > > + count = var_data_size / sizeof(*boot_order); > > + for (i = 0; i < count; i++) { > > + boot_name[4] = hexmap[(boot_order[i] & 0xf000) >> 12]; > > + boot_name[5] = hexmap[(boot_order[i] & 0x0f00) >> 8]; > > + boot_name[6] = hexmap[(boot_order[i] & 0x00f0) >> 4]; > > + boot_name[7] = hexmap[(boot_order[i] & 0x000f)]; > > + > > + bootvar = efi_get_var(boot_name, &efi_global_variable_guid, > > + &var_data_size); > > + > > + if (!bootvar) { > > + log_info("%ls not found\n", boot_name); > > + continue; > > + } > > + > > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, > > + boot_name, > > + &efi_global_variable_guid, > > + var_data_size, bootvar); > > + free(bootvar); > > + if (ret != EFI_SUCCESS) > > + goto error; > > + } > > + > > +error: > > + free(boot_order); > > + return ret; > > +} > > + > > +/** > > + * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation > > + * > > + * Return: status code > > + */ > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void) > > +{ > > + efi_status_t ret; > > + u32 pcr_index; > > + struct udevice *dev; > > + u32 event = 0; > > + > > + if (tcg2_efi_app_invoked) > > + return EFI_SUCCESS; > > + > > + ret = platform_get_tpm2_device(&dev); > > + if (ret != EFI_SUCCESS) > > + return ret; > > + > > + ret = tcg2_measure_boot_variable(dev); > > + if (ret != EFI_SUCCESS) > > + goto out; > > + > > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > > + strlen(EFI_CALLING_EFI_APPLICATION), > > + (u8 *)EFI_CALLING_EFI_APPLICATION); > > + if (ret != EFI_SUCCESS) > > + goto out; > > + > > + for (pcr_index = 0; pcr_index <= 7; pcr_index++) { > > + ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR, > > + sizeof(event), (u8 *)&event); > > + if (ret != EFI_SUCCESS) > > + goto out; > > + } > > + > > + tcg2_efi_app_invoked = true; > > +out: > > + return ret; > > +} > > + > > +/** > > + * efi_tcg2_measure_efi_app_exit() - measure efi app exit > > + * > > + * Return: status code > > + */ > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void) > > +{ > > + efi_status_t ret; > > + struct udevice *dev; > > + > > + ret = platform_get_tpm2_device(&dev); > > + if (ret != EFI_SUCCESS) > > + return ret; > > + > > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > > + strlen(EFI_RETURNING_FROM_EFI_APPLICATION), > > + (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION); > > + return ret; > > +} > > + > > /** > > * tcg2_measure_secure_boot_variable() - measure secure boot variables > > * > > >
Hi Heinrich, > > > TCG spec also requires to measure "Calling EFI Application from > > > Boot Option" for each boot attempt, and "Returning from EFI > > > Application from Boot Option" if a boot device returns control > > > back to the Boot Manager. I would like to hear your opinion regarding "Calling EFI Application from Boot Option" measurement. My current(v1 patch series) implementation considers both "bootefi bootmgr" and "bootefi $image_addr" cases, so I do this "Calling EFI Application from Boot Option" measurement at efi_boottime.c::efi_start_image(). Do I need to implement only the case UEFI application boot from bootmgr? If yes, I will move the timing of this measurement at efi_bootmgr.c::efi_bootmgr_load(). As a reference, in edk2, this measurement is performed in ready_to_boot event handler, ready_to_boot handler is called upon the user selects the boot option in boot manager. What do you think? Thanks, Masahisa Kojima On Fri, 9 Jul 2021 at 11:44, Masahisa Kojima <masahisa.kojima@linaro.org> wrote: > > On Fri, 9 Jul 2021 at 02:46, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote: > > > > On 7/7/21 3:36 PM, Masahisa Kojima wrote: > > > TCG PC Client PFP spec requires to measure "Boot####" > > > and "BootOrder" variables, EV_SEPARATOR event prior > > > to the Ready to Boot invocation. > > > Since u-boot does not implement Ready to Boot event, > > > these measurements are performed when efi_start_image() is called. > > > > > > TCG spec also requires to measure "Calling EFI Application from > > > Boot Option" for each boot attempt, and "Returning from EFI > > > Application from Boot Option" if a boot device returns control > > > back to the Boot Manager. > > > > > > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> > > > --- > > > include/efi_loader.h | 4 ++ > > > include/tpm-v2.h | 18 ++++- > > > lib/efi_loader/efi_boottime.c | 20 ++++++ > > > lib/efi_loader/efi_tcg2.c | 123 ++++++++++++++++++++++++++++++++++ > > > 4 files changed, 164 insertions(+), 1 deletion(-) > > > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h > > > index 0a9c82a257..281ffff30f 100644 > > > --- a/include/efi_loader.h > > > +++ b/include/efi_loader.h > > > @@ -407,6 +407,10 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size); > > > efi_status_t efi_init_variables(void); > > > /* Notify ExitBootServices() is called */ > > > void efi_variables_boot_exit_notify(void); > > > +/* Measure efi application invocation */ > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void); > > > +/* Measure efi application exit */ > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void); > > > /* Called by bootefi to initialize root node */ > > > efi_status_t efi_root_node_register(void); > > > /* Called by bootefi to initialize runtime */ > > > diff --git a/include/tpm-v2.h b/include/tpm-v2.h > > > index 3e48e35861..8a7b7f1874 100644 > > > --- a/include/tpm-v2.h > > > +++ b/include/tpm-v2.h > > > @@ -73,7 +73,7 @@ struct udevice; > > > /* > > > * event types, cf. > > > * "TCG PC Client Platform Firmware Profile Specification", Family "2.0" > > > - * rev 1.04, June 3, 2019 > > > + * Level 00 Version 1.05 Revision 23, May 7, 2021 > > > */ > > > #define EV_EFI_EVENT_BASE ((u32)0x80000000) > > > #define EV_EFI_VARIABLE_DRIVER_CONFIG ((u32)0x80000001) > > > @@ -85,8 +85,24 @@ struct udevice; > > > #define EV_EFI_ACTION ((u32)0x80000007) > > > #define EV_EFI_PLATFORM_FIRMWARE_BLOB ((u32)0x80000008) > > > #define EV_EFI_HANDOFF_TABLES ((u32)0x80000009) > > > +#define EV_EFI_PLATFORM_FIRMWARE_BLOB2 ((u32)0x8000000A) > > > +#define EV_EFI_HANDOFF_TABLES2 ((u32)0x8000000B) > > > +#define EV_EFI_VARIABLE_BOOT2 ((u32)0x8000000C) > > > #define EV_EFI_HCRTM_EVENT ((u32)0x80000010) > > > #define EV_EFI_VARIABLE_AUTHORITY ((u32)0x800000E0) > > > +#define EV_EFI_SPDM_FIRMWARE_BLOB ((u32)0x800000E1) > > > +#define EV_EFI_SPDM_FIRMWARE_CONFIG ((u32)0x800000E2) > > > + > > > +#define EFI_CALLING_EFI_APPLICATION \ > > > + "Calling EFI Application from Boot Option" > > > +#define EFI_RETURNING_FROM_EFI_APPLICATION \ > > > + "Returning from EFI Application from Boot Option" > > > +#define EFI_EXIT_BOOT_SERVICES_INVOCATION \ > > > + "Exit Boot Services Invocation" > > > +#define EFI_EXIT_BOOT_SERVICES_FAILED \ > > > + "Exit Boot Services Returned with Failure" > > > +#define EFI_EXIT_BOOT_SERVICES_SUCCEEDED \ > > > + "Exit Boot Services Returned with Success" > > > > Which spec defines if the string in the event log shall be utf-8 or utf-16? > > TCG PC Client PFP spec does not clearly define the character encoding. > In my understanding, the string derived from UEFI spec such as > UEFI variable name uses utf-16(CHAR16). > Other strings like "Calling EFI Application from Boot Option" defind in TCG PC > Client spec use 1 byte ASCII encoding. > > EDK2 implementation also uses 1 byte ASCII encoding for these strings, > and tpm2-tools::tpm2_eventlog command can handles properly. > > Thanks, > Masahisa Kojima > > > > > Best regards > > > > Heinrich > > > > > > > > /* TPMS_TAGGED_PROPERTY Structure */ > > > struct tpms_tagged_property { > > > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > > > index f6d5ba05e3..2914800c56 100644 > > > --- a/lib/efi_loader/efi_boottime.c > > > +++ b/lib/efi_loader/efi_boottime.c > > > @@ -2993,6 +2993,16 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, > > > image_obj->exit_status = &exit_status; > > > image_obj->exit_jmp = &exit_jmp; > > > > > > + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > > > + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { > > > + ret = efi_tcg2_measure_efi_app_invocation(); > > > + if (ret != EFI_SUCCESS) { > > > + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", > > > + ret); > > > + } > > > + } > > > + } > > > + > > > /* call the image! */ > > > if (setjmp(&exit_jmp)) { > > > /* > > > @@ -3251,6 +3261,16 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, > > > exit_status != EFI_SUCCESS) > > > efi_delete_image(image_obj, loaded_image_protocol); > > > > > > + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > > > + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { > > > + ret = efi_tcg2_measure_efi_app_exit(); > > > + if (ret != EFI_SUCCESS) { > > > + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", > > > + ret); > > > + } > > > + } > > > + } > > > + > > > /* Make sure entry/exit counts for EFI world cross-overs match */ > > > EFI_EXIT(exit_status); > > > > > > diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c > > > index 2a248bd62a..6e903e3cb3 100644 > > > --- a/lib/efi_loader/efi_tcg2.c > > > +++ b/lib/efi_loader/efi_tcg2.c > > > @@ -35,6 +35,7 @@ struct event_log_buffer { > > > }; > > > > > > static struct event_log_buffer event_log; > > > +static bool tcg2_efi_app_invoked; > > > /* > > > * When requesting TPM2_CAP_TPM_PROPERTIES the value is on a standard offset. > > > * Since the current tpm2_get_capability() response buffers starts at > > > @@ -1383,6 +1384,128 @@ static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index, > > > return ret; > > > } > > > > > > +/** > > > + * tcg2_measure_boot_variable() - measure boot variables > > > + * > > > + * @dev: TPM device > > > + * > > > + * Return: status code > > > + */ > > > +static efi_status_t tcg2_measure_boot_variable(struct udevice *dev) > > > +{ > > > + u16 *boot_order; > > > + u16 var_name[] = L"BootOrder"; > > > + u16 boot_name[] = L"Boot0000"; > > > + u16 hexmap[] = L"0123456789ABCDEF"; > > > + u8 *bootvar; > > > + efi_uintn_t var_data_size; > > > + u32 count, i; > > > + efi_status_t ret; > > > + > > > + boot_order = efi_get_var(var_name, &efi_global_variable_guid, > > > + &var_data_size); > > > + if (!boot_order) { > > > + log_info("BootOrder not defined\n"); > > > + ret = EFI_NOT_FOUND; > > > + goto error; > > > + } > > > + > > > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, var_name, > > > + &efi_global_variable_guid, var_data_size, > > > + (u8 *)boot_order); > > > + if (ret != EFI_SUCCESS) > > > + goto error; > > > + > > > + count = var_data_size / sizeof(*boot_order); > > > + for (i = 0; i < count; i++) { > > > + boot_name[4] = hexmap[(boot_order[i] & 0xf000) >> 12]; > > > + boot_name[5] = hexmap[(boot_order[i] & 0x0f00) >> 8]; > > > + boot_name[6] = hexmap[(boot_order[i] & 0x00f0) >> 4]; > > > + boot_name[7] = hexmap[(boot_order[i] & 0x000f)]; > > > + > > > + bootvar = efi_get_var(boot_name, &efi_global_variable_guid, > > > + &var_data_size); > > > + > > > + if (!bootvar) { > > > + log_info("%ls not found\n", boot_name); > > > + continue; > > > + } > > > + > > > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, > > > + boot_name, > > > + &efi_global_variable_guid, > > > + var_data_size, bootvar); > > > + free(bootvar); > > > + if (ret != EFI_SUCCESS) > > > + goto error; > > > + } > > > + > > > +error: > > > + free(boot_order); > > > + return ret; > > > +} > > > + > > > +/** > > > + * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation > > > + * > > > + * Return: status code > > > + */ > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void) > > > +{ > > > + efi_status_t ret; > > > + u32 pcr_index; > > > + struct udevice *dev; > > > + u32 event = 0; > > > + > > > + if (tcg2_efi_app_invoked) > > > + return EFI_SUCCESS; > > > + > > > + ret = platform_get_tpm2_device(&dev); > > > + if (ret != EFI_SUCCESS) > > > + return ret; > > > + > > > + ret = tcg2_measure_boot_variable(dev); > > > + if (ret != EFI_SUCCESS) > > > + goto out; > > > + > > > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > > > + strlen(EFI_CALLING_EFI_APPLICATION), > > > + (u8 *)EFI_CALLING_EFI_APPLICATION); > > > + if (ret != EFI_SUCCESS) > > > + goto out; > > > + > > > + for (pcr_index = 0; pcr_index <= 7; pcr_index++) { > > > + ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR, > > > + sizeof(event), (u8 *)&event); > > > + if (ret != EFI_SUCCESS) > > > + goto out; > > > + } > > > + > > > + tcg2_efi_app_invoked = true; > > > +out: > > > + return ret; > > > +} > > > + > > > +/** > > > + * efi_tcg2_measure_efi_app_exit() - measure efi app exit > > > + * > > > + * Return: status code > > > + */ > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void) > > > +{ > > > + efi_status_t ret; > > > + struct udevice *dev; > > > + > > > + ret = platform_get_tpm2_device(&dev); > > > + if (ret != EFI_SUCCESS) > > > + return ret; > > > + > > > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > > > + strlen(EFI_RETURNING_FROM_EFI_APPLICATION), > > > + (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION); > > > + return ret; > > > +} > > > + > > > /** > > > * tcg2_measure_secure_boot_variable() - measure secure boot variables > > > * > > > > >
On 13.07.21 10:31, Masahisa Kojima wrote: > Hi Heinrich, > >>>> TCG spec also requires to measure "Calling EFI Application from >>>> Boot Option" for each boot attempt, and "Returning from EFI >>>> Application from Boot Option" if a boot device returns control >>>> back to the Boot Manager. > > I would like to hear your opinion regarding > "Calling EFI Application from Boot Option" measurement. > > My current(v1 patch series) implementation considers > both "bootefi bootmgr" and "bootefi $image_addr" cases, > so I do this "Calling EFI Application from Boot Option" measurement > at efi_boottime.c::efi_start_image(). > Do I need to implement only the case UEFI application boot from bootmgr? > If yes, I will move the timing of this measurement at > efi_bootmgr.c::efi_bootmgr_load(). > > As a reference, in edk2, this measurement is performed in > ready_to_boot event handler, ready_to_boot handler is called > upon the user selects the boot option in boot manager. When booting you can call bootefi $driver1 booefii $driver2 bootefi bootmgr in sequence. Any of the binaries can call LoadImage(), StartImage() multiple times to execute further images. E.g. I am loading iPXE. By default it loads GRUB from an iSCSI drive but I can choose in the menu or the iPXE console to invoke another UEFI binary. I suggest to measure any image no matter how it is invoked. The measurement must depend on the sequence of invocation. Best regards Heinrich > > What do you think? > > Thanks, > Masahisa Kojima > > > > > > On Fri, 9 Jul 2021 at 11:44, Masahisa Kojima <masahisa.kojima@linaro.org> wrote: >> >> On Fri, 9 Jul 2021 at 02:46, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote: >>> >>> On 7/7/21 3:36 PM, Masahisa Kojima wrote: >>>> TCG PC Client PFP spec requires to measure "Boot####" >>>> and "BootOrder" variables, EV_SEPARATOR event prior >>>> to the Ready to Boot invocation. >>>> Since u-boot does not implement Ready to Boot event, >>>> these measurements are performed when efi_start_image() is called. >>>> >>>> TCG spec also requires to measure "Calling EFI Application from >>>> Boot Option" for each boot attempt, and "Returning from EFI >>>> Application from Boot Option" if a boot device returns control >>>> back to the Boot Manager. >>>> >>>> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> >>>> --- >>>> include/efi_loader.h | 4 ++ >>>> include/tpm-v2.h | 18 ++++- >>>> lib/efi_loader/efi_boottime.c | 20 ++++++ >>>> lib/efi_loader/efi_tcg2.c | 123 ++++++++++++++++++++++++++++++++++ >>>> 4 files changed, 164 insertions(+), 1 deletion(-) >>>> >>>> diff --git a/include/efi_loader.h b/include/efi_loader.h >>>> index 0a9c82a257..281ffff30f 100644 >>>> --- a/include/efi_loader.h >>>> +++ b/include/efi_loader.h >>>> @@ -407,6 +407,10 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size); >>>> efi_status_t efi_init_variables(void); >>>> /* Notify ExitBootServices() is called */ >>>> void efi_variables_boot_exit_notify(void); >>>> +/* Measure efi application invocation */ >>>> +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void); >>>> +/* Measure efi application exit */ >>>> +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void); >>>> /* Called by bootefi to initialize root node */ >>>> efi_status_t efi_root_node_register(void); >>>> /* Called by bootefi to initialize runtime */ >>>> diff --git a/include/tpm-v2.h b/include/tpm-v2.h >>>> index 3e48e35861..8a7b7f1874 100644 >>>> --- a/include/tpm-v2.h >>>> +++ b/include/tpm-v2.h >>>> @@ -73,7 +73,7 @@ struct udevice; >>>> /* >>>> * event types, cf. >>>> * "TCG PC Client Platform Firmware Profile Specification", Family "2.0" >>>> - * rev 1.04, June 3, 2019 >>>> + * Level 00 Version 1.05 Revision 23, May 7, 2021 >>>> */ >>>> #define EV_EFI_EVENT_BASE ((u32)0x80000000) >>>> #define EV_EFI_VARIABLE_DRIVER_CONFIG ((u32)0x80000001) >>>> @@ -85,8 +85,24 @@ struct udevice; >>>> #define EV_EFI_ACTION ((u32)0x80000007) >>>> #define EV_EFI_PLATFORM_FIRMWARE_BLOB ((u32)0x80000008) >>>> #define EV_EFI_HANDOFF_TABLES ((u32)0x80000009) >>>> +#define EV_EFI_PLATFORM_FIRMWARE_BLOB2 ((u32)0x8000000A) >>>> +#define EV_EFI_HANDOFF_TABLES2 ((u32)0x8000000B) >>>> +#define EV_EFI_VARIABLE_BOOT2 ((u32)0x8000000C) >>>> #define EV_EFI_HCRTM_EVENT ((u32)0x80000010) >>>> #define EV_EFI_VARIABLE_AUTHORITY ((u32)0x800000E0) >>>> +#define EV_EFI_SPDM_FIRMWARE_BLOB ((u32)0x800000E1) >>>> +#define EV_EFI_SPDM_FIRMWARE_CONFIG ((u32)0x800000E2) >>>> + >>>> +#define EFI_CALLING_EFI_APPLICATION \ >>>> + "Calling EFI Application from Boot Option" >>>> +#define EFI_RETURNING_FROM_EFI_APPLICATION \ >>>> + "Returning from EFI Application from Boot Option" >>>> +#define EFI_EXIT_BOOT_SERVICES_INVOCATION \ >>>> + "Exit Boot Services Invocation" >>>> +#define EFI_EXIT_BOOT_SERVICES_FAILED \ >>>> + "Exit Boot Services Returned with Failure" >>>> +#define EFI_EXIT_BOOT_SERVICES_SUCCEEDED \ >>>> + "Exit Boot Services Returned with Success" >>> >>> Which spec defines if the string in the event log shall be utf-8 or utf-16? >> >> TCG PC Client PFP spec does not clearly define the character encoding. >> In my understanding, the string derived from UEFI spec such as >> UEFI variable name uses utf-16(CHAR16). >> Other strings like "Calling EFI Application from Boot Option" defind in TCG PC >> Client spec use 1 byte ASCII encoding. >> >> EDK2 implementation also uses 1 byte ASCII encoding for these strings, >> and tpm2-tools::tpm2_eventlog command can handles properly. >> >> Thanks, >> Masahisa Kojima >> >>> >>> Best regards >>> >>> Heinrich >>> >>>> >>>> /* TPMS_TAGGED_PROPERTY Structure */ >>>> struct tpms_tagged_property { >>>> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c >>>> index f6d5ba05e3..2914800c56 100644 >>>> --- a/lib/efi_loader/efi_boottime.c >>>> +++ b/lib/efi_loader/efi_boottime.c >>>> @@ -2993,6 +2993,16 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, >>>> image_obj->exit_status = &exit_status; >>>> image_obj->exit_jmp = &exit_jmp; >>>> >>>> + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { >>>> + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { >>>> + ret = efi_tcg2_measure_efi_app_invocation(); >>>> + if (ret != EFI_SUCCESS) { >>>> + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", >>>> + ret); >>>> + } >>>> + } >>>> + } >>>> + >>>> /* call the image! */ >>>> if (setjmp(&exit_jmp)) { >>>> /* >>>> @@ -3251,6 +3261,16 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, >>>> exit_status != EFI_SUCCESS) >>>> efi_delete_image(image_obj, loaded_image_protocol); >>>> >>>> + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { >>>> + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { >>>> + ret = efi_tcg2_measure_efi_app_exit(); >>>> + if (ret != EFI_SUCCESS) { >>>> + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", >>>> + ret); >>>> + } >>>> + } >>>> + } >>>> + >>>> /* Make sure entry/exit counts for EFI world cross-overs match */ >>>> EFI_EXIT(exit_status); >>>> >>>> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c >>>> index 2a248bd62a..6e903e3cb3 100644 >>>> --- a/lib/efi_loader/efi_tcg2.c >>>> +++ b/lib/efi_loader/efi_tcg2.c >>>> @@ -35,6 +35,7 @@ struct event_log_buffer { >>>> }; >>>> >>>> static struct event_log_buffer event_log; >>>> +static bool tcg2_efi_app_invoked; >>>> /* >>>> * When requesting TPM2_CAP_TPM_PROPERTIES the value is on a standard offset. >>>> * Since the current tpm2_get_capability() response buffers starts at >>>> @@ -1383,6 +1384,128 @@ static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index, >>>> return ret; >>>> } >>>> >>>> +/** >>>> + * tcg2_measure_boot_variable() - measure boot variables >>>> + * >>>> + * @dev: TPM device >>>> + * >>>> + * Return: status code >>>> + */ >>>> +static efi_status_t tcg2_measure_boot_variable(struct udevice *dev) >>>> +{ >>>> + u16 *boot_order; >>>> + u16 var_name[] = L"BootOrder"; >>>> + u16 boot_name[] = L"Boot0000"; >>>> + u16 hexmap[] = L"0123456789ABCDEF"; >>>> + u8 *bootvar; >>>> + efi_uintn_t var_data_size; >>>> + u32 count, i; >>>> + efi_status_t ret; >>>> + >>>> + boot_order = efi_get_var(var_name, &efi_global_variable_guid, >>>> + &var_data_size); >>>> + if (!boot_order) { >>>> + log_info("BootOrder not defined\n"); >>>> + ret = EFI_NOT_FOUND; >>>> + goto error; >>>> + } >>>> + >>>> + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, var_name, >>>> + &efi_global_variable_guid, var_data_size, >>>> + (u8 *)boot_order); >>>> + if (ret != EFI_SUCCESS) >>>> + goto error; >>>> + >>>> + count = var_data_size / sizeof(*boot_order); >>>> + for (i = 0; i < count; i++) { >>>> + boot_name[4] = hexmap[(boot_order[i] & 0xf000) >> 12]; >>>> + boot_name[5] = hexmap[(boot_order[i] & 0x0f00) >> 8]; >>>> + boot_name[6] = hexmap[(boot_order[i] & 0x00f0) >> 4]; >>>> + boot_name[7] = hexmap[(boot_order[i] & 0x000f)]; >>>> + >>>> + bootvar = efi_get_var(boot_name, &efi_global_variable_guid, >>>> + &var_data_size); >>>> + >>>> + if (!bootvar) { >>>> + log_info("%ls not found\n", boot_name); >>>> + continue; >>>> + } >>>> + >>>> + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, >>>> + boot_name, >>>> + &efi_global_variable_guid, >>>> + var_data_size, bootvar); >>>> + free(bootvar); >>>> + if (ret != EFI_SUCCESS) >>>> + goto error; >>>> + } >>>> + >>>> +error: >>>> + free(boot_order); >>>> + return ret; >>>> +} >>>> + >>>> +/** >>>> + * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation >>>> + * >>>> + * Return: status code >>>> + */ >>>> +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void) >>>> +{ >>>> + efi_status_t ret; >>>> + u32 pcr_index; >>>> + struct udevice *dev; >>>> + u32 event = 0; >>>> + >>>> + if (tcg2_efi_app_invoked) >>>> + return EFI_SUCCESS; >>>> + >>>> + ret = platform_get_tpm2_device(&dev); >>>> + if (ret != EFI_SUCCESS) >>>> + return ret; >>>> + >>>> + ret = tcg2_measure_boot_variable(dev); >>>> + if (ret != EFI_SUCCESS) >>>> + goto out; >>>> + >>>> + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, >>>> + strlen(EFI_CALLING_EFI_APPLICATION), >>>> + (u8 *)EFI_CALLING_EFI_APPLICATION); >>>> + if (ret != EFI_SUCCESS) >>>> + goto out; >>>> + >>>> + for (pcr_index = 0; pcr_index <= 7; pcr_index++) { >>>> + ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR, >>>> + sizeof(event), (u8 *)&event); >>>> + if (ret != EFI_SUCCESS) >>>> + goto out; >>>> + } >>>> + >>>> + tcg2_efi_app_invoked = true; >>>> +out: >>>> + return ret; >>>> +} >>>> + >>>> +/** >>>> + * efi_tcg2_measure_efi_app_exit() - measure efi app exit >>>> + * >>>> + * Return: status code >>>> + */ >>>> +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void) >>>> +{ >>>> + efi_status_t ret; >>>> + struct udevice *dev; >>>> + >>>> + ret = platform_get_tpm2_device(&dev); >>>> + if (ret != EFI_SUCCESS) >>>> + return ret; >>>> + >>>> + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, >>>> + strlen(EFI_RETURNING_FROM_EFI_APPLICATION), >>>> + (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION); >>>> + return ret; >>>> +} >>>> + >>>> /** >>>> * tcg2_measure_secure_boot_variable() - measure secure boot variables >>>> * >>>> >>>
On Tue, Jul 13, 2021 at 04:24:52PM +0200, Heinrich Schuchardt wrote: > > > On 13.07.21 10:31, Masahisa Kojima wrote: > > Hi Heinrich, > > > > > > > TCG spec also requires to measure "Calling EFI Application from > > > > > Boot Option" for each boot attempt, and "Returning from EFI > > > > > Application from Boot Option" if a boot device returns control > > > > > back to the Boot Manager. > > > > I would like to hear your opinion regarding > > "Calling EFI Application from Boot Option" measurement. > > > > My current(v1 patch series) implementation considers > > both "bootefi bootmgr" and "bootefi $image_addr" cases, > > so I do this "Calling EFI Application from Boot Option" measurement > > at efi_boottime.c::efi_start_image(). > > Do I need to implement only the case UEFI application boot from bootmgr? > > If yes, I will move the timing of this measurement at > > efi_bootmgr.c::efi_bootmgr_load(). > > > > As a reference, in edk2, this measurement is performed in > > ready_to_boot event handler, ready_to_boot handler is called > > upon the user selects the boot option in boot manager. > > When booting you can call > > bootefi $driver1 > booefii $driver2 > bootefi bootmgr > > in sequence. > > Any of the binaries can call LoadImage(), StartImage() multiple times to > execute further images. E.g. I am loading iPXE. By default it loads GRUB > from an iSCSI drive but I can choose in the menu or the iPXE console to > invoke another UEFI binary. > > I suggest to measure any image no matter how it is invoked. The > measurement must depend on the sequence of invocation. Moreover, booting from the default path, like /EFI/BOOT/BOOTAA64.EFI, is only implemented by using bootefi <addr> syntax. -Takahiro Akashi > Best regards > > Heinrich > > > > > What do you think? > > > > Thanks, > > Masahisa Kojima > > > > > > > > > > > > On Fri, 9 Jul 2021 at 11:44, Masahisa Kojima <masahisa.kojima@linaro.org> wrote: > > > > > > On Fri, 9 Jul 2021 at 02:46, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote: > > > > > > > > On 7/7/21 3:36 PM, Masahisa Kojima wrote: > > > > > TCG PC Client PFP spec requires to measure "Boot####" > > > > > and "BootOrder" variables, EV_SEPARATOR event prior > > > > > to the Ready to Boot invocation. > > > > > Since u-boot does not implement Ready to Boot event, > > > > > these measurements are performed when efi_start_image() is called. > > > > > > > > > > TCG spec also requires to measure "Calling EFI Application from > > > > > Boot Option" for each boot attempt, and "Returning from EFI > > > > > Application from Boot Option" if a boot device returns control > > > > > back to the Boot Manager. > > > > > > > > > > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> > > > > > --- > > > > > include/efi_loader.h | 4 ++ > > > > > include/tpm-v2.h | 18 ++++- > > > > > lib/efi_loader/efi_boottime.c | 20 ++++++ > > > > > lib/efi_loader/efi_tcg2.c | 123 ++++++++++++++++++++++++++++++++++ > > > > > 4 files changed, 164 insertions(+), 1 deletion(-) > > > > > > > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h > > > > > index 0a9c82a257..281ffff30f 100644 > > > > > --- a/include/efi_loader.h > > > > > +++ b/include/efi_loader.h > > > > > @@ -407,6 +407,10 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size); > > > > > efi_status_t efi_init_variables(void); > > > > > /* Notify ExitBootServices() is called */ > > > > > void efi_variables_boot_exit_notify(void); > > > > > +/* Measure efi application invocation */ > > > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void); > > > > > +/* Measure efi application exit */ > > > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void); > > > > > /* Called by bootefi to initialize root node */ > > > > > efi_status_t efi_root_node_register(void); > > > > > /* Called by bootefi to initialize runtime */ > > > > > diff --git a/include/tpm-v2.h b/include/tpm-v2.h > > > > > index 3e48e35861..8a7b7f1874 100644 > > > > > --- a/include/tpm-v2.h > > > > > +++ b/include/tpm-v2.h > > > > > @@ -73,7 +73,7 @@ struct udevice; > > > > > /* > > > > > * event types, cf. > > > > > * "TCG PC Client Platform Firmware Profile Specification", Family "2.0" > > > > > - * rev 1.04, June 3, 2019 > > > > > + * Level 00 Version 1.05 Revision 23, May 7, 2021 > > > > > */ > > > > > #define EV_EFI_EVENT_BASE ((u32)0x80000000) > > > > > #define EV_EFI_VARIABLE_DRIVER_CONFIG ((u32)0x80000001) > > > > > @@ -85,8 +85,24 @@ struct udevice; > > > > > #define EV_EFI_ACTION ((u32)0x80000007) > > > > > #define EV_EFI_PLATFORM_FIRMWARE_BLOB ((u32)0x80000008) > > > > > #define EV_EFI_HANDOFF_TABLES ((u32)0x80000009) > > > > > +#define EV_EFI_PLATFORM_FIRMWARE_BLOB2 ((u32)0x8000000A) > > > > > +#define EV_EFI_HANDOFF_TABLES2 ((u32)0x8000000B) > > > > > +#define EV_EFI_VARIABLE_BOOT2 ((u32)0x8000000C) > > > > > #define EV_EFI_HCRTM_EVENT ((u32)0x80000010) > > > > > #define EV_EFI_VARIABLE_AUTHORITY ((u32)0x800000E0) > > > > > +#define EV_EFI_SPDM_FIRMWARE_BLOB ((u32)0x800000E1) > > > > > +#define EV_EFI_SPDM_FIRMWARE_CONFIG ((u32)0x800000E2) > > > > > + > > > > > +#define EFI_CALLING_EFI_APPLICATION \ > > > > > + "Calling EFI Application from Boot Option" > > > > > +#define EFI_RETURNING_FROM_EFI_APPLICATION \ > > > > > + "Returning from EFI Application from Boot Option" > > > > > +#define EFI_EXIT_BOOT_SERVICES_INVOCATION \ > > > > > + "Exit Boot Services Invocation" > > > > > +#define EFI_EXIT_BOOT_SERVICES_FAILED \ > > > > > + "Exit Boot Services Returned with Failure" > > > > > +#define EFI_EXIT_BOOT_SERVICES_SUCCEEDED \ > > > > > + "Exit Boot Services Returned with Success" > > > > > > > > Which spec defines if the string in the event log shall be utf-8 or utf-16? > > > > > > TCG PC Client PFP spec does not clearly define the character encoding. > > > In my understanding, the string derived from UEFI spec such as > > > UEFI variable name uses utf-16(CHAR16). > > > Other strings like "Calling EFI Application from Boot Option" defind in TCG PC > > > Client spec use 1 byte ASCII encoding. > > > > > > EDK2 implementation also uses 1 byte ASCII encoding for these strings, > > > and tpm2-tools::tpm2_eventlog command can handles properly. > > > > > > Thanks, > > > Masahisa Kojima > > > > > > > > > > > Best regards > > > > > > > > Heinrich > > > > > > > > > > > > > > /* TPMS_TAGGED_PROPERTY Structure */ > > > > > struct tpms_tagged_property { > > > > > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > > > > > index f6d5ba05e3..2914800c56 100644 > > > > > --- a/lib/efi_loader/efi_boottime.c > > > > > +++ b/lib/efi_loader/efi_boottime.c > > > > > @@ -2993,6 +2993,16 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, > > > > > image_obj->exit_status = &exit_status; > > > > > image_obj->exit_jmp = &exit_jmp; > > > > > > > > > > + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > > > > > + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { > > > > > + ret = efi_tcg2_measure_efi_app_invocation(); > > > > > + if (ret != EFI_SUCCESS) { > > > > > + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", > > > > > + ret); > > > > > + } > > > > > + } > > > > > + } > > > > > + > > > > > /* call the image! */ > > > > > if (setjmp(&exit_jmp)) { > > > > > /* > > > > > @@ -3251,6 +3261,16 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, > > > > > exit_status != EFI_SUCCESS) > > > > > efi_delete_image(image_obj, loaded_image_protocol); > > > > > > > > > > + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > > > > > + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { > > > > > + ret = efi_tcg2_measure_efi_app_exit(); > > > > > + if (ret != EFI_SUCCESS) { > > > > > + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", > > > > > + ret); > > > > > + } > > > > > + } > > > > > + } > > > > > + > > > > > /* Make sure entry/exit counts for EFI world cross-overs match */ > > > > > EFI_EXIT(exit_status); > > > > > > > > > > diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c > > > > > index 2a248bd62a..6e903e3cb3 100644 > > > > > --- a/lib/efi_loader/efi_tcg2.c > > > > > +++ b/lib/efi_loader/efi_tcg2.c > > > > > @@ -35,6 +35,7 @@ struct event_log_buffer { > > > > > }; > > > > > > > > > > static struct event_log_buffer event_log; > > > > > +static bool tcg2_efi_app_invoked; > > > > > /* > > > > > * When requesting TPM2_CAP_TPM_PROPERTIES the value is on a standard offset. > > > > > * Since the current tpm2_get_capability() response buffers starts at > > > > > @@ -1383,6 +1384,128 @@ static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index, > > > > > return ret; > > > > > } > > > > > > > > > > +/** > > > > > + * tcg2_measure_boot_variable() - measure boot variables > > > > > + * > > > > > + * @dev: TPM device > > > > > + * > > > > > + * Return: status code > > > > > + */ > > > > > +static efi_status_t tcg2_measure_boot_variable(struct udevice *dev) > > > > > +{ > > > > > + u16 *boot_order; > > > > > + u16 var_name[] = L"BootOrder"; > > > > > + u16 boot_name[] = L"Boot0000"; > > > > > + u16 hexmap[] = L"0123456789ABCDEF"; > > > > > + u8 *bootvar; > > > > > + efi_uintn_t var_data_size; > > > > > + u32 count, i; > > > > > + efi_status_t ret; > > > > > + > > > > > + boot_order = efi_get_var(var_name, &efi_global_variable_guid, > > > > > + &var_data_size); > > > > > + if (!boot_order) { > > > > > + log_info("BootOrder not defined\n"); > > > > > + ret = EFI_NOT_FOUND; > > > > > + goto error; > > > > > + } > > > > > + > > > > > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, var_name, > > > > > + &efi_global_variable_guid, var_data_size, > > > > > + (u8 *)boot_order); > > > > > + if (ret != EFI_SUCCESS) > > > > > + goto error; > > > > > + > > > > > + count = var_data_size / sizeof(*boot_order); > > > > > + for (i = 0; i < count; i++) { > > > > > + boot_name[4] = hexmap[(boot_order[i] & 0xf000) >> 12]; > > > > > + boot_name[5] = hexmap[(boot_order[i] & 0x0f00) >> 8]; > > > > > + boot_name[6] = hexmap[(boot_order[i] & 0x00f0) >> 4]; > > > > > + boot_name[7] = hexmap[(boot_order[i] & 0x000f)]; > > > > > + > > > > > + bootvar = efi_get_var(boot_name, &efi_global_variable_guid, > > > > > + &var_data_size); > > > > > + > > > > > + if (!bootvar) { > > > > > + log_info("%ls not found\n", boot_name); > > > > > + continue; > > > > > + } > > > > > + > > > > > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, > > > > > + boot_name, > > > > > + &efi_global_variable_guid, > > > > > + var_data_size, bootvar); > > > > > + free(bootvar); > > > > > + if (ret != EFI_SUCCESS) > > > > > + goto error; > > > > > + } > > > > > + > > > > > +error: > > > > > + free(boot_order); > > > > > + return ret; > > > > > +} > > > > > + > > > > > +/** > > > > > + * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation > > > > > + * > > > > > + * Return: status code > > > > > + */ > > > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void) > > > > > +{ > > > > > + efi_status_t ret; > > > > > + u32 pcr_index; > > > > > + struct udevice *dev; > > > > > + u32 event = 0; > > > > > + > > > > > + if (tcg2_efi_app_invoked) > > > > > + return EFI_SUCCESS; > > > > > + > > > > > + ret = platform_get_tpm2_device(&dev); > > > > > + if (ret != EFI_SUCCESS) > > > > > + return ret; > > > > > + > > > > > + ret = tcg2_measure_boot_variable(dev); > > > > > + if (ret != EFI_SUCCESS) > > > > > + goto out; > > > > > + > > > > > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > > > > > + strlen(EFI_CALLING_EFI_APPLICATION), > > > > > + (u8 *)EFI_CALLING_EFI_APPLICATION); > > > > > + if (ret != EFI_SUCCESS) > > > > > + goto out; > > > > > + > > > > > + for (pcr_index = 0; pcr_index <= 7; pcr_index++) { > > > > > + ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR, > > > > > + sizeof(event), (u8 *)&event); > > > > > + if (ret != EFI_SUCCESS) > > > > > + goto out; > > > > > + } > > > > > + > > > > > + tcg2_efi_app_invoked = true; > > > > > +out: > > > > > + return ret; > > > > > +} > > > > > + > > > > > +/** > > > > > + * efi_tcg2_measure_efi_app_exit() - measure efi app exit > > > > > + * > > > > > + * Return: status code > > > > > + */ > > > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void) > > > > > +{ > > > > > + efi_status_t ret; > > > > > + struct udevice *dev; > > > > > + > > > > > + ret = platform_get_tpm2_device(&dev); > > > > > + if (ret != EFI_SUCCESS) > > > > > + return ret; > > > > > + > > > > > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > > > > > + strlen(EFI_RETURNING_FROM_EFI_APPLICATION), > > > > > + (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION); > > > > > + return ret; > > > > > +} > > > > > + > > > > > /** > > > > > * tcg2_measure_secure_boot_variable() - measure secure boot variables > > > > > * > > > > > > > > >
Hi Heinrich, Akashi-san, Thank you for your comment. I will keep current implementation. Thanks, Masahisa Kojima On Wed, 14 Jul 2021 at 08:54, AKASHI Takahiro <takahiro.akashi@linaro.org> wrote: > > On Tue, Jul 13, 2021 at 04:24:52PM +0200, Heinrich Schuchardt wrote: > > > > > > On 13.07.21 10:31, Masahisa Kojima wrote: > > > Hi Heinrich, > > > > > > > > > TCG spec also requires to measure "Calling EFI Application from > > > > > > Boot Option" for each boot attempt, and "Returning from EFI > > > > > > Application from Boot Option" if a boot device returns control > > > > > > back to the Boot Manager. > > > > > > I would like to hear your opinion regarding > > > "Calling EFI Application from Boot Option" measurement. > > > > > > My current(v1 patch series) implementation considers > > > both "bootefi bootmgr" and "bootefi $image_addr" cases, > > > so I do this "Calling EFI Application from Boot Option" measurement > > > at efi_boottime.c::efi_start_image(). > > > Do I need to implement only the case UEFI application boot from bootmgr? > > > If yes, I will move the timing of this measurement at > > > efi_bootmgr.c::efi_bootmgr_load(). > > > > > > As a reference, in edk2, this measurement is performed in > > > ready_to_boot event handler, ready_to_boot handler is called > > > upon the user selects the boot option in boot manager. > > > > When booting you can call > > > > bootefi $driver1 > > booefii $driver2 > > bootefi bootmgr > > > > in sequence. > > > > Any of the binaries can call LoadImage(), StartImage() multiple times to > > execute further images. E.g. I am loading iPXE. By default it loads GRUB > > from an iSCSI drive but I can choose in the menu or the iPXE console to > > invoke another UEFI binary. > > > > I suggest to measure any image no matter how it is invoked. The > > measurement must depend on the sequence of invocation. > > Moreover, > booting from the default path, like /EFI/BOOT/BOOTAA64.EFI, > is only implemented by using bootefi <addr> syntax. > > -Takahiro Akashi > > > > Best regards > > > > Heinrich > > > > > > > > What do you think? > > > > > > Thanks, > > > Masahisa Kojima > > > > > > > > > > > > > > > > > > On Fri, 9 Jul 2021 at 11:44, Masahisa Kojima <masahisa.kojima@linaro.org> wrote: > > > > > > > > On Fri, 9 Jul 2021 at 02:46, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote: > > > > > > > > > > On 7/7/21 3:36 PM, Masahisa Kojima wrote: > > > > > > TCG PC Client PFP spec requires to measure "Boot####" > > > > > > and "BootOrder" variables, EV_SEPARATOR event prior > > > > > > to the Ready to Boot invocation. > > > > > > Since u-boot does not implement Ready to Boot event, > > > > > > these measurements are performed when efi_start_image() is called. > > > > > > > > > > > > TCG spec also requires to measure "Calling EFI Application from > > > > > > Boot Option" for each boot attempt, and "Returning from EFI > > > > > > Application from Boot Option" if a boot device returns control > > > > > > back to the Boot Manager. > > > > > > > > > > > > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> > > > > > > --- > > > > > > include/efi_loader.h | 4 ++ > > > > > > include/tpm-v2.h | 18 ++++- > > > > > > lib/efi_loader/efi_boottime.c | 20 ++++++ > > > > > > lib/efi_loader/efi_tcg2.c | 123 ++++++++++++++++++++++++++++++++++ > > > > > > 4 files changed, 164 insertions(+), 1 deletion(-) > > > > > > > > > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h > > > > > > index 0a9c82a257..281ffff30f 100644 > > > > > > --- a/include/efi_loader.h > > > > > > +++ b/include/efi_loader.h > > > > > > @@ -407,6 +407,10 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size); > > > > > > efi_status_t efi_init_variables(void); > > > > > > /* Notify ExitBootServices() is called */ > > > > > > void efi_variables_boot_exit_notify(void); > > > > > > +/* Measure efi application invocation */ > > > > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void); > > > > > > +/* Measure efi application exit */ > > > > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void); > > > > > > /* Called by bootefi to initialize root node */ > > > > > > efi_status_t efi_root_node_register(void); > > > > > > /* Called by bootefi to initialize runtime */ > > > > > > diff --git a/include/tpm-v2.h b/include/tpm-v2.h > > > > > > index 3e48e35861..8a7b7f1874 100644 > > > > > > --- a/include/tpm-v2.h > > > > > > +++ b/include/tpm-v2.h > > > > > > @@ -73,7 +73,7 @@ struct udevice; > > > > > > /* > > > > > > * event types, cf. > > > > > > * "TCG PC Client Platform Firmware Profile Specification", Family "2.0" > > > > > > - * rev 1.04, June 3, 2019 > > > > > > + * Level 00 Version 1.05 Revision 23, May 7, 2021 > > > > > > */ > > > > > > #define EV_EFI_EVENT_BASE ((u32)0x80000000) > > > > > > #define EV_EFI_VARIABLE_DRIVER_CONFIG ((u32)0x80000001) > > > > > > @@ -85,8 +85,24 @@ struct udevice; > > > > > > #define EV_EFI_ACTION ((u32)0x80000007) > > > > > > #define EV_EFI_PLATFORM_FIRMWARE_BLOB ((u32)0x80000008) > > > > > > #define EV_EFI_HANDOFF_TABLES ((u32)0x80000009) > > > > > > +#define EV_EFI_PLATFORM_FIRMWARE_BLOB2 ((u32)0x8000000A) > > > > > > +#define EV_EFI_HANDOFF_TABLES2 ((u32)0x8000000B) > > > > > > +#define EV_EFI_VARIABLE_BOOT2 ((u32)0x8000000C) > > > > > > #define EV_EFI_HCRTM_EVENT ((u32)0x80000010) > > > > > > #define EV_EFI_VARIABLE_AUTHORITY ((u32)0x800000E0) > > > > > > +#define EV_EFI_SPDM_FIRMWARE_BLOB ((u32)0x800000E1) > > > > > > +#define EV_EFI_SPDM_FIRMWARE_CONFIG ((u32)0x800000E2) > > > > > > + > > > > > > +#define EFI_CALLING_EFI_APPLICATION \ > > > > > > + "Calling EFI Application from Boot Option" > > > > > > +#define EFI_RETURNING_FROM_EFI_APPLICATION \ > > > > > > + "Returning from EFI Application from Boot Option" > > > > > > +#define EFI_EXIT_BOOT_SERVICES_INVOCATION \ > > > > > > + "Exit Boot Services Invocation" > > > > > > +#define EFI_EXIT_BOOT_SERVICES_FAILED \ > > > > > > + "Exit Boot Services Returned with Failure" > > > > > > +#define EFI_EXIT_BOOT_SERVICES_SUCCEEDED \ > > > > > > + "Exit Boot Services Returned with Success" > > > > > > > > > > Which spec defines if the string in the event log shall be utf-8 or utf-16? > > > > > > > > TCG PC Client PFP spec does not clearly define the character encoding. > > > > In my understanding, the string derived from UEFI spec such as > > > > UEFI variable name uses utf-16(CHAR16). > > > > Other strings like "Calling EFI Application from Boot Option" defind in TCG PC > > > > Client spec use 1 byte ASCII encoding. > > > > > > > > EDK2 implementation also uses 1 byte ASCII encoding for these strings, > > > > and tpm2-tools::tpm2_eventlog command can handles properly. > > > > > > > > Thanks, > > > > Masahisa Kojima > > > > > > > > > > > > > > Best regards > > > > > > > > > > Heinrich > > > > > > > > > > > > > > > > > /* TPMS_TAGGED_PROPERTY Structure */ > > > > > > struct tpms_tagged_property { > > > > > > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > > > > > > index f6d5ba05e3..2914800c56 100644 > > > > > > --- a/lib/efi_loader/efi_boottime.c > > > > > > +++ b/lib/efi_loader/efi_boottime.c > > > > > > @@ -2993,6 +2993,16 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, > > > > > > image_obj->exit_status = &exit_status; > > > > > > image_obj->exit_jmp = &exit_jmp; > > > > > > > > > > > > + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > > > > > > + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { > > > > > > + ret = efi_tcg2_measure_efi_app_invocation(); > > > > > > + if (ret != EFI_SUCCESS) { > > > > > > + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", > > > > > > + ret); > > > > > > + } > > > > > > + } > > > > > > + } > > > > > > + > > > > > > /* call the image! */ > > > > > > if (setjmp(&exit_jmp)) { > > > > > > /* > > > > > > @@ -3251,6 +3261,16 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, > > > > > > exit_status != EFI_SUCCESS) > > > > > > efi_delete_image(image_obj, loaded_image_protocol); > > > > > > > > > > > > + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > > > > > > + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { > > > > > > + ret = efi_tcg2_measure_efi_app_exit(); > > > > > > + if (ret != EFI_SUCCESS) { > > > > > > + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", > > > > > > + ret); > > > > > > + } > > > > > > + } > > > > > > + } > > > > > > + > > > > > > /* Make sure entry/exit counts for EFI world cross-overs match */ > > > > > > EFI_EXIT(exit_status); > > > > > > > > > > > > diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c > > > > > > index 2a248bd62a..6e903e3cb3 100644 > > > > > > --- a/lib/efi_loader/efi_tcg2.c > > > > > > +++ b/lib/efi_loader/efi_tcg2.c > > > > > > @@ -35,6 +35,7 @@ struct event_log_buffer { > > > > > > }; > > > > > > > > > > > > static struct event_log_buffer event_log; > > > > > > +static bool tcg2_efi_app_invoked; > > > > > > /* > > > > > > * When requesting TPM2_CAP_TPM_PROPERTIES the value is on a standard offset. > > > > > > * Since the current tpm2_get_capability() response buffers starts at > > > > > > @@ -1383,6 +1384,128 @@ static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index, > > > > > > return ret; > > > > > > } > > > > > > > > > > > > +/** > > > > > > + * tcg2_measure_boot_variable() - measure boot variables > > > > > > + * > > > > > > + * @dev: TPM device > > > > > > + * > > > > > > + * Return: status code > > > > > > + */ > > > > > > +static efi_status_t tcg2_measure_boot_variable(struct udevice *dev) > > > > > > +{ > > > > > > + u16 *boot_order; > > > > > > + u16 var_name[] = L"BootOrder"; > > > > > > + u16 boot_name[] = L"Boot0000"; > > > > > > + u16 hexmap[] = L"0123456789ABCDEF"; > > > > > > + u8 *bootvar; > > > > > > + efi_uintn_t var_data_size; > > > > > > + u32 count, i; > > > > > > + efi_status_t ret; > > > > > > + > > > > > > + boot_order = efi_get_var(var_name, &efi_global_variable_guid, > > > > > > + &var_data_size); > > > > > > + if (!boot_order) { > > > > > > + log_info("BootOrder not defined\n"); > > > > > > + ret = EFI_NOT_FOUND; > > > > > > + goto error; > > > > > > + } > > > > > > + > > > > > > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, var_name, > > > > > > + &efi_global_variable_guid, var_data_size, > > > > > > + (u8 *)boot_order); > > > > > > + if (ret != EFI_SUCCESS) > > > > > > + goto error; > > > > > > + > > > > > > + count = var_data_size / sizeof(*boot_order); > > > > > > + for (i = 0; i < count; i++) { > > > > > > + boot_name[4] = hexmap[(boot_order[i] & 0xf000) >> 12]; > > > > > > + boot_name[5] = hexmap[(boot_order[i] & 0x0f00) >> 8]; > > > > > > + boot_name[6] = hexmap[(boot_order[i] & 0x00f0) >> 4]; > > > > > > + boot_name[7] = hexmap[(boot_order[i] & 0x000f)]; > > > > > > + > > > > > > + bootvar = efi_get_var(boot_name, &efi_global_variable_guid, > > > > > > + &var_data_size); > > > > > > + > > > > > > + if (!bootvar) { > > > > > > + log_info("%ls not found\n", boot_name); > > > > > > + continue; > > > > > > + } > > > > > > + > > > > > > + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, > > > > > > + boot_name, > > > > > > + &efi_global_variable_guid, > > > > > > + var_data_size, bootvar); > > > > > > + free(bootvar); > > > > > > + if (ret != EFI_SUCCESS) > > > > > > + goto error; > > > > > > + } > > > > > > + > > > > > > +error: > > > > > > + free(boot_order); > > > > > > + return ret; > > > > > > +} > > > > > > + > > > > > > +/** > > > > > > + * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation > > > > > > + * > > > > > > + * Return: status code > > > > > > + */ > > > > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void) > > > > > > +{ > > > > > > + efi_status_t ret; > > > > > > + u32 pcr_index; > > > > > > + struct udevice *dev; > > > > > > + u32 event = 0; > > > > > > + > > > > > > + if (tcg2_efi_app_invoked) > > > > > > + return EFI_SUCCESS; > > > > > > + > > > > > > + ret = platform_get_tpm2_device(&dev); > > > > > > + if (ret != EFI_SUCCESS) > > > > > > + return ret; > > > > > > + > > > > > > + ret = tcg2_measure_boot_variable(dev); > > > > > > + if (ret != EFI_SUCCESS) > > > > > > + goto out; > > > > > > + > > > > > > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > > > > > > + strlen(EFI_CALLING_EFI_APPLICATION), > > > > > > + (u8 *)EFI_CALLING_EFI_APPLICATION); > > > > > > + if (ret != EFI_SUCCESS) > > > > > > + goto out; > > > > > > + > > > > > > + for (pcr_index = 0; pcr_index <= 7; pcr_index++) { > > > > > > + ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR, > > > > > > + sizeof(event), (u8 *)&event); > > > > > > + if (ret != EFI_SUCCESS) > > > > > > + goto out; > > > > > > + } > > > > > > + > > > > > > + tcg2_efi_app_invoked = true; > > > > > > +out: > > > > > > + return ret; > > > > > > +} > > > > > > + > > > > > > +/** > > > > > > + * efi_tcg2_measure_efi_app_exit() - measure efi app exit > > > > > > + * > > > > > > + * Return: status code > > > > > > + */ > > > > > > +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void) > > > > > > +{ > > > > > > + efi_status_t ret; > > > > > > + struct udevice *dev; > > > > > > + > > > > > > + ret = platform_get_tpm2_device(&dev); > > > > > > + if (ret != EFI_SUCCESS) > > > > > > + return ret; > > > > > > + > > > > > > + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, > > > > > > + strlen(EFI_RETURNING_FROM_EFI_APPLICATION), > > > > > > + (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION); > > > > > > + return ret; > > > > > > +} > > > > > > + > > > > > > /** > > > > > > * tcg2_measure_secure_boot_variable() - measure secure boot variables > > > > > > * > > > > > > > > > > >
diff --git a/include/efi_loader.h b/include/efi_loader.h index 0a9c82a257..281ffff30f 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -407,6 +407,10 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size); efi_status_t efi_init_variables(void); /* Notify ExitBootServices() is called */ void efi_variables_boot_exit_notify(void); +/* Measure efi application invocation */ +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void); +/* Measure efi application exit */ +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void); /* Called by bootefi to initialize root node */ efi_status_t efi_root_node_register(void); /* Called by bootefi to initialize runtime */ diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 3e48e35861..8a7b7f1874 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -73,7 +73,7 @@ struct udevice; /* * event types, cf. * "TCG PC Client Platform Firmware Profile Specification", Family "2.0" - * rev 1.04, June 3, 2019 + * Level 00 Version 1.05 Revision 23, May 7, 2021 */ #define EV_EFI_EVENT_BASE ((u32)0x80000000) #define EV_EFI_VARIABLE_DRIVER_CONFIG ((u32)0x80000001) @@ -85,8 +85,24 @@ struct udevice; #define EV_EFI_ACTION ((u32)0x80000007) #define EV_EFI_PLATFORM_FIRMWARE_BLOB ((u32)0x80000008) #define EV_EFI_HANDOFF_TABLES ((u32)0x80000009) +#define EV_EFI_PLATFORM_FIRMWARE_BLOB2 ((u32)0x8000000A) +#define EV_EFI_HANDOFF_TABLES2 ((u32)0x8000000B) +#define EV_EFI_VARIABLE_BOOT2 ((u32)0x8000000C) #define EV_EFI_HCRTM_EVENT ((u32)0x80000010) #define EV_EFI_VARIABLE_AUTHORITY ((u32)0x800000E0) +#define EV_EFI_SPDM_FIRMWARE_BLOB ((u32)0x800000E1) +#define EV_EFI_SPDM_FIRMWARE_CONFIG ((u32)0x800000E2) + +#define EFI_CALLING_EFI_APPLICATION \ + "Calling EFI Application from Boot Option" +#define EFI_RETURNING_FROM_EFI_APPLICATION \ + "Returning from EFI Application from Boot Option" +#define EFI_EXIT_BOOT_SERVICES_INVOCATION \ + "Exit Boot Services Invocation" +#define EFI_EXIT_BOOT_SERVICES_FAILED \ + "Exit Boot Services Returned with Failure" +#define EFI_EXIT_BOOT_SERVICES_SUCCEEDED \ + "Exit Boot Services Returned with Success" /* TPMS_TAGGED_PROPERTY Structure */ struct tpms_tagged_property { diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index f6d5ba05e3..2914800c56 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2993,6 +2993,16 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, image_obj->exit_status = &exit_status; image_obj->exit_jmp = &exit_jmp; + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { + ret = efi_tcg2_measure_efi_app_invocation(); + if (ret != EFI_SUCCESS) { + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", + ret); + } + } + } + /* call the image! */ if (setjmp(&exit_jmp)) { /* @@ -3251,6 +3261,16 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, exit_status != EFI_SUCCESS) efi_delete_image(image_obj, loaded_image_protocol); + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { + ret = efi_tcg2_measure_efi_app_exit(); + if (ret != EFI_SUCCESS) { + EFI_PRINT("tcg2 measurement fails(0x%lx)\n", + ret); + } + } + } + /* Make sure entry/exit counts for EFI world cross-overs match */ EFI_EXIT(exit_status); diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 2a248bd62a..6e903e3cb3 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -35,6 +35,7 @@ struct event_log_buffer { }; static struct event_log_buffer event_log; +static bool tcg2_efi_app_invoked; /* * When requesting TPM2_CAP_TPM_PROPERTIES the value is on a standard offset. * Since the current tpm2_get_capability() response buffers starts at @@ -1383,6 +1384,128 @@ static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index, return ret; } +/** + * tcg2_measure_boot_variable() - measure boot variables + * + * @dev: TPM device + * + * Return: status code + */ +static efi_status_t tcg2_measure_boot_variable(struct udevice *dev) +{ + u16 *boot_order; + u16 var_name[] = L"BootOrder"; + u16 boot_name[] = L"Boot0000"; + u16 hexmap[] = L"0123456789ABCDEF"; + u8 *bootvar; + efi_uintn_t var_data_size; + u32 count, i; + efi_status_t ret; + + boot_order = efi_get_var(var_name, &efi_global_variable_guid, + &var_data_size); + if (!boot_order) { + log_info("BootOrder not defined\n"); + ret = EFI_NOT_FOUND; + goto error; + } + + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, var_name, + &efi_global_variable_guid, var_data_size, + (u8 *)boot_order); + if (ret != EFI_SUCCESS) + goto error; + + count = var_data_size / sizeof(*boot_order); + for (i = 0; i < count; i++) { + boot_name[4] = hexmap[(boot_order[i] & 0xf000) >> 12]; + boot_name[5] = hexmap[(boot_order[i] & 0x0f00) >> 8]; + boot_name[6] = hexmap[(boot_order[i] & 0x00f0) >> 4]; + boot_name[7] = hexmap[(boot_order[i] & 0x000f)]; + + bootvar = efi_get_var(boot_name, &efi_global_variable_guid, + &var_data_size); + + if (!bootvar) { + log_info("%ls not found\n", boot_name); + continue; + } + + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, + boot_name, + &efi_global_variable_guid, + var_data_size, bootvar); + free(bootvar); + if (ret != EFI_SUCCESS) + goto error; + } + +error: + free(boot_order); + return ret; +} + +/** + * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation + * + * Return: status code + */ +efi_status_t EFIAPI efi_tcg2_measure_efi_app_invocation(void) +{ + efi_status_t ret; + u32 pcr_index; + struct udevice *dev; + u32 event = 0; + + if (tcg2_efi_app_invoked) + return EFI_SUCCESS; + + ret = platform_get_tpm2_device(&dev); + if (ret != EFI_SUCCESS) + return ret; + + ret = tcg2_measure_boot_variable(dev); + if (ret != EFI_SUCCESS) + goto out; + + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, + strlen(EFI_CALLING_EFI_APPLICATION), + (u8 *)EFI_CALLING_EFI_APPLICATION); + if (ret != EFI_SUCCESS) + goto out; + + for (pcr_index = 0; pcr_index <= 7; pcr_index++) { + ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR, + sizeof(event), (u8 *)&event); + if (ret != EFI_SUCCESS) + goto out; + } + + tcg2_efi_app_invoked = true; +out: + return ret; +} + +/** + * efi_tcg2_measure_efi_app_exit() - measure efi app exit + * + * Return: status code + */ +efi_status_t EFIAPI efi_tcg2_measure_efi_app_exit(void) +{ + efi_status_t ret; + struct udevice *dev; + + ret = platform_get_tpm2_device(&dev); + if (ret != EFI_SUCCESS) + return ret; + + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, + strlen(EFI_RETURNING_FROM_EFI_APPLICATION), + (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION); + return ret; +} + /** * tcg2_measure_secure_boot_variable() - measure secure boot variables *
TCG PC Client PFP spec requires to measure "Boot####" and "BootOrder" variables, EV_SEPARATOR event prior to the Ready to Boot invocation. Since u-boot does not implement Ready to Boot event, these measurements are performed when efi_start_image() is called. TCG spec also requires to measure "Calling EFI Application from Boot Option" for each boot attempt, and "Returning from EFI Application from Boot Option" if a boot device returns control back to the Boot Manager. Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> --- include/efi_loader.h | 4 ++ include/tpm-v2.h | 18 ++++- lib/efi_loader/efi_boottime.c | 20 ++++++ lib/efi_loader/efi_tcg2.c | 123 ++++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+), 1 deletion(-) -- 2.17.1