Message ID | 20210806070215.19887-3-masahisa.kojima@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | add measurement support | expand |
On Fri, Aug 06, 2021 at 04:02:12PM +0900, 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> > --- > Changes in v3: > - modify log output > > Changes in v2: > - use efi_create_indexed_name() for "Boot####" variable > > include/efi_loader.h | 4 ++ > include/tpm-v2.h | 18 ++++- > lib/efi_loader/efi_boottime.c | 20 ++++++ > lib/efi_loader/efi_tcg2.c | 121 ++++++++++++++++++++++++++++++++++ > 4 files changed, 162 insertions(+), 1 deletion(-) > > diff --git a/include/efi_loader.h b/include/efi_loader.h > index a120d94431..345cbb72c4 100644 > --- a/include/efi_loader.h > +++ b/include/efi_loader.h > @@ -499,6 +499,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); I don't think that we need to have EFIAPI specifiers for those functions as they are not api's. > /* 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 247b386967..325c73006e 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 0b98e91813..13ab139222 100644 > --- a/lib/efi_loader/efi_boottime.c > +++ b/lib/efi_loader/efi_boottime.c > @@ -2994,6 +2994,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) { > + log_warning("tcg2 measurement fails(0x%lx)\n", > + ret); > + } > + } > + } > + > /* call the image! */ > if (setjmp(&exit_jmp)) { > /* > @@ -3252,6 +3262,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) { > + log_warning("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 a2e9587cd0..7dd30c2bc9 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 > @@ -1385,6 +1386,126 @@ 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 *boot_index; > + u16 var_name[] = L"BootOrder"; > + u16 boot_name[] = L"Boot####"; > + 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) { > + ret = EFI_NOT_FOUND; > + goto error; > + } What if BootOrder is not defined, but BootNext is defined? -Takahiro Akashi > + > + 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); > + boot_index = boot_order; > + for (i = 0; i < count; i++) { > + efi_create_indexed_name(boot_name, sizeof(boot_name), > + "Boot", *boot_index++); > + > + 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 > * > -- > 2.17.1 >
On Tue, 10 Aug 2021 at 11:19, AKASHI Takahiro <takahiro.akashi@linaro.org> wrote: > > On Fri, Aug 06, 2021 at 04:02:12PM +0900, 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> > > --- > > Changes in v3: > > - modify log output > > > > Changes in v2: > > - use efi_create_indexed_name() for "Boot####" variable > > > > include/efi_loader.h | 4 ++ > > include/tpm-v2.h | 18 ++++- > > lib/efi_loader/efi_boottime.c | 20 ++++++ > > lib/efi_loader/efi_tcg2.c | 121 ++++++++++++++++++++++++++++++++++ > > 4 files changed, 162 insertions(+), 1 deletion(-) > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h > > index a120d94431..345cbb72c4 100644 > > --- a/include/efi_loader.h > > +++ b/include/efi_loader.h > > @@ -499,6 +499,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); > > I don't think that we need to have EFIAPI specifiers for those functions > as they are not api's. Yes, I will remove EFIAPI specifiers. > > > /* 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 247b386967..325c73006e 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 0b98e91813..13ab139222 100644 > > --- a/lib/efi_loader/efi_boottime.c > > +++ b/lib/efi_loader/efi_boottime.c > > @@ -2994,6 +2994,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) { > > + log_warning("tcg2 measurement fails(0x%lx)\n", > > + ret); > > + } > > + } > > + } > > + > > /* call the image! */ > > if (setjmp(&exit_jmp)) { > > /* > > @@ -3252,6 +3262,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) { > > + log_warning("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 a2e9587cd0..7dd30c2bc9 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 > > @@ -1385,6 +1386,126 @@ 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 *boot_index; > > + u16 var_name[] = L"BootOrder"; > > + u16 boot_name[] = L"Boot####"; > > + 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) { > > + ret = EFI_NOT_FOUND; > > + goto error; > > + } > > What if BootOrder is not defined, but BootNext is defined? TCG PC Client PFP spec does not require to measure the case when the system boots with BootNext. So in this case, BootNext is defined but BootOrder is not defined, no measurement occurs for boot variables. Thanks, Masahisa Kojima > > -Takahiro Akashi > > > + > > + 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); > > + boot_index = boot_order; > > + for (i = 0; i < count; i++) { > > + efi_create_indexed_name(boot_name, sizeof(boot_name), > > + "Boot", *boot_index++); > > + > > + 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 > > * > > -- > > 2.17.1 > >
On Wed, Aug 11, 2021 at 12:05:39PM +0900, Masahisa Kojima wrote: > On Tue, 10 Aug 2021 at 11:19, AKASHI Takahiro > <takahiro.akashi@linaro.org> wrote: > > > > On Fri, Aug 06, 2021 at 04:02:12PM +0900, 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> > > > --- > > > Changes in v3: > > > - modify log output > > > > > > Changes in v2: > > > - use efi_create_indexed_name() for "Boot####" variable > > > > > > include/efi_loader.h | 4 ++ > > > include/tpm-v2.h | 18 ++++- > > > lib/efi_loader/efi_boottime.c | 20 ++++++ > > > lib/efi_loader/efi_tcg2.c | 121 ++++++++++++++++++++++++++++++++++ > > > 4 files changed, 162 insertions(+), 1 deletion(-) > > > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h > > > index a120d94431..345cbb72c4 100644 > > > --- a/include/efi_loader.h > > > +++ b/include/efi_loader.h > > > @@ -499,6 +499,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); > > > > I don't think that we need to have EFIAPI specifiers for those functions > > as they are not api's. > > Yes, I will remove EFIAPI specifiers. > > > > > > /* 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 247b386967..325c73006e 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 0b98e91813..13ab139222 100644 > > > --- a/lib/efi_loader/efi_boottime.c > > > +++ b/lib/efi_loader/efi_boottime.c > > > @@ -2994,6 +2994,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) { > > > + log_warning("tcg2 measurement fails(0x%lx)\n", > > > + ret); > > > + } > > > + } > > > + } > > > + > > > /* call the image! */ > > > if (setjmp(&exit_jmp)) { > > > /* > > > @@ -3252,6 +3262,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) { > > > + log_warning("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 a2e9587cd0..7dd30c2bc9 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 > > > @@ -1385,6 +1386,126 @@ 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 *boot_index; > > > + u16 var_name[] = L"BootOrder"; > > > + u16 boot_name[] = L"Boot####"; > > > + 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) { > > > + ret = EFI_NOT_FOUND; > > > + goto error; > > > + } > > > > What if BootOrder is not defined, but BootNext is defined? > > TCG PC Client PFP spec does not require to measure the case > when the system boots with BootNext. > So in this case, BootNext is defined but BootOrder is not defined, > no measurement occurs for boot variables. I simply wonder why the spec does care about BootOrder, but not BootNext. Let take another case; BootNext, BootOrder and BootXXXX are all defined, and the system boots up by BootNext. In this case, we will have measurement for boot variables. Why do we need this although we don't take measurement in case of BootNext & !BootOrder? -Takahiro Akashi > Thanks, > Masahisa Kojima > > > > > -Takahiro Akashi > > > > > + > > > + 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); > > > + boot_index = boot_order; > > > + for (i = 0; i < count; i++) { > > > + efi_create_indexed_name(boot_name, sizeof(boot_name), > > > + "Boot", *boot_index++); > > > + > > > + 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 > > > * > > > -- > > > 2.17.1 > > >
On Wed, 11 Aug 2021 at 15:50, AKASHI Takahiro <takahiro.akashi@linaro.org> wrote: > > On Wed, Aug 11, 2021 at 12:05:39PM +0900, Masahisa Kojima wrote: > > On Tue, 10 Aug 2021 at 11:19, AKASHI Takahiro > > <takahiro.akashi@linaro.org> wrote: > > > > > > On Fri, Aug 06, 2021 at 04:02:12PM +0900, 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> > > > > --- > > > > Changes in v3: > > > > - modify log output > > > > > > > > Changes in v2: > > > > - use efi_create_indexed_name() for "Boot####" variable > > > > > > > > include/efi_loader.h | 4 ++ > > > > include/tpm-v2.h | 18 ++++- > > > > lib/efi_loader/efi_boottime.c | 20 ++++++ > > > > lib/efi_loader/efi_tcg2.c | 121 ++++++++++++++++++++++++++++++++++ > > > > 4 files changed, 162 insertions(+), 1 deletion(-) > > > > > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h > > > > index a120d94431..345cbb72c4 100644 > > > > --- a/include/efi_loader.h > > > > +++ b/include/efi_loader.h > > > > @@ -499,6 +499,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); > > > > > > I don't think that we need to have EFIAPI specifiers for those functions > > > as they are not api's. > > > > Yes, I will remove EFIAPI specifiers. > > > > > > > > > /* 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 247b386967..325c73006e 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 0b98e91813..13ab139222 100644 > > > > --- a/lib/efi_loader/efi_boottime.c > > > > +++ b/lib/efi_loader/efi_boottime.c > > > > @@ -2994,6 +2994,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) { > > > > + log_warning("tcg2 measurement fails(0x%lx)\n", > > > > + ret); > > > > + } > > > > + } > > > > + } > > > > + > > > > /* call the image! */ > > > > if (setjmp(&exit_jmp)) { > > > > /* > > > > @@ -3252,6 +3262,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) { > > > > + log_warning("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 a2e9587cd0..7dd30c2bc9 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 > > > > @@ -1385,6 +1386,126 @@ 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 *boot_index; > > > > + u16 var_name[] = L"BootOrder"; > > > > + u16 boot_name[] = L"Boot####"; > > > > + 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) { > > > > + ret = EFI_NOT_FOUND; > > > > + goto error; > > > > + } > > > > > > What if BootOrder is not defined, but BootNext is defined? > > > > TCG PC Client PFP spec does not require to measure the case > > when the system boots with BootNext. > > So in this case, BootNext is defined but BootOrder is not defined, > > no measurement occurs for boot variables. > > I simply wonder why the spec does care about BootOrder, but not BootNext. > Let take another case; BootNext, BootOrder and BootXXXX are all defined, > and the system boots up by BootNext. In this case, we will have measurement > for boot variables. Why do we need this although we don't take measurement > in case of BootNext & !BootOrder? Good point, Akashi-san. In my understanding, TCG spec(Measured Boot) tries to cover the typical boot flow, system boot with BootNext is a bit special use case. Host Platform Configuration(BootOrder and BootXXXX, etc.) are measured into PCR[1], and next boot image(OS Loader, etc.) is measured in PCR[4]. So at least boot image is measured in BootNext & !BootOrder case. This is also related to the usage of PCRs in the later process such as attestation. Thanks, Masahisa Kojima > > -Takahiro Akashi > > > > Thanks, > > Masahisa Kojima > > > > > > > > -Takahiro Akashi > > > > > > > + > > > > + 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); > > > > + boot_index = boot_order; > > > > + for (i = 0; i < count; i++) { > > > > + efi_create_indexed_name(boot_name, sizeof(boot_name), > > > > + "Boot", *boot_index++); > > > > + > > > > + 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 > > > > * > > > > -- > > > > 2.17.1 > > > >
diff --git a/include/efi_loader.h b/include/efi_loader.h index a120d94431..345cbb72c4 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -499,6 +499,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 247b386967..325c73006e 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 0b98e91813..13ab139222 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2994,6 +2994,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) { + log_warning("tcg2 measurement fails(0x%lx)\n", + ret); + } + } + } + /* call the image! */ if (setjmp(&exit_jmp)) { /* @@ -3252,6 +3262,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) { + log_warning("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 a2e9587cd0..7dd30c2bc9 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 @@ -1385,6 +1386,126 @@ 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 *boot_index; + u16 var_name[] = L"BootOrder"; + u16 boot_name[] = L"Boot####"; + 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) { + 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); + boot_index = boot_order; + for (i = 0; i < count; i++) { + efi_create_indexed_name(boot_name, sizeof(boot_name), + "Boot", *boot_index++); + + 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> --- Changes in v3: - modify log output Changes in v2: - use efi_create_indexed_name() for "Boot####" variable include/efi_loader.h | 4 ++ include/tpm-v2.h | 18 ++++- lib/efi_loader/efi_boottime.c | 20 ++++++ lib/efi_loader/efi_tcg2.c | 121 ++++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+), 1 deletion(-) -- 2.17.1