[PATCH] efi_loader: fix FinalEvents table if an EFI uses GetEventLog

Heinrich Schuchardt xypron.glpk at gmx.de
Wed Nov 17 11:01:55 CET 2021


On 11/17/21 10:10, Ilias Apalodimas wrote:
> As described in the TCG spec [1] in sections 7.1.1 and 7.1.2 the FinalEvent
> table should include events after GetEventLog has been called.  This
> currently works for us as long as the kernel is the only EFI application
> calling that.  Specifically we only implement what's described in 7.1.1.
>
> So refactor the code a bit and support EFI application calling GetEventLog.
> Events will now be logged in both the EventLog and FinalEvent table as long
> as ExitBootServices haven't been invoked.
>
> [1] https://trustedcomputinggroup.org/wp-content/uploads/EFI-Protocol-Specification-rev13-160330final.pdf
>
> Signed-off-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
> ---
>   lib/efi_loader/efi_tcg2.c | 90 ++++++++++++++++++++++++++-------------
>   1 file changed, 61 insertions(+), 29 deletions(-)
>
> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> index 189e4a5ba59c..215f4b2b04b8 100644
> --- a/lib/efi_loader/efi_tcg2.c
> +++ b/lib/efi_loader/efi_tcg2.c
> @@ -34,6 +34,7 @@ struct event_log_buffer {
>   	size_t final_pos; /* final events config table position */
>   	size_t last_event_size;
>   	bool get_event_called;
> +	bool ebs_called;

Please, add documentation for the elements of the structure. Not every
reader will be aware of ebs_called referring to ExitBootServices().

>   	bool truncated;
>   };
>
> @@ -186,39 +187,29 @@ static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
>   	return EFI_SUCCESS;
>   }
>
> -/* tcg2_agile_log_append - Append an agile event to out eventlog
> +/* put_event - Append an agile event to an eventlog
>    *
>    * @pcr_index:		PCR index
>    * @event_type:		type of event added
>    * @digest_list:	list of digest algorithms to add
>    * @size:		size of event
>    * @event:		event to add
> + * @log:		log buffer to append the event
>    *
> - * @Return: status code
>    */
> -static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
> -					  struct tpml_digest_values *digest_list,
> -					  u32 size, u8 event[])
> +static void put_event(u32 pcr_index, u32 event_type,
> +		      struct tpml_digest_values *digest_list, u32 size,
> +		      u8 event[], void *log)
>   {
> -	void *log = (void *)((uintptr_t)event_log.buffer + event_log.pos);
>   	size_t pos;
>   	size_t i;
>   	u32 event_size;
>
> -	if (event_log.get_event_called)
> -		log = (void *)((uintptr_t)event_log.final_buffer +
> -			       event_log.final_pos);
> -
>   	/*
>   	 * size refers to the length of event[] only, we need to check against
>   	 * the final tcg_pcr_event2 size
>   	 */
>   	event_size = size + tcg_event_final_size(digest_list);
> -	if (event_log.pos + event_size > TPM2_EVENT_LOG_SIZE ||
> -	    event_log.final_pos + event_size > TPM2_EVENT_LOG_SIZE) {
> -		event_log.truncated = true;
> -		return EFI_VOLUME_FULL;
> -	}
>
>   	put_unaligned_le32(pcr_index, log);
>   	pos = offsetof(struct tcg_pcr_event2, event_type);
> @@ -242,25 +233,64 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
>   	memcpy((void *)((uintptr_t)log + pos), event, size);
>   	pos += size;
>
> -	/* make sure the calculated buffer is what we checked against */
> +	/*
> +	 * make sure the calculated buffer is what we checked against
> +	 * This check should never fail.  It checks the code above is
> +	 * calculating the right length for the event we are adding
> +	 * */
>   	if (pos != event_size)
> -		return EFI_INVALID_PARAMETER;
> +		log_err("Appending to the EventLog failed\n");
>
> -	/* if GetEventLog hasn't been called update the normal log */
> -	if (!event_log.get_event_called) {
> -		event_log.pos += pos;
> -		event_log.last_event_size = pos;
> -	} else {
> -	/* if GetEventLog has been called update config table log */
> -		struct efi_tcg2_final_events_table *final_event;
> +}
>
> -		final_event =
> -			(struct efi_tcg2_final_events_table *)(event_log.final_buffer);
> -		final_event->number_of_events++;
> -		event_log.final_pos += pos;
> +/* tcg2_agile_log_append - Append an agile event to an eventlog
> + *
> + * @pcr_index:		PCR index
> + * @event_type:		type of event added
> + * @digest_list:	list of digest algorithms to add
> + * @size:		size of event
> + * @event:		event to add
> + * @log:		log buffer to append the event
> + *
> + * @Return: status code
> + */
> +static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
> +					  struct tpml_digest_values *digest_list,
> +					  u32 size, u8 event[])
> +{
> +	void *log = (void *)((uintptr_t)event_log.buffer + event_log.pos);
> +	u32 event_size = size + tcg_event_final_size(digest_list);
> +	struct efi_tcg2_final_events_table *final_event;
> +	efi_status_t ret = EFI_SUCCESS;
> +
> +	/* if ExitBootServices hasn't been called update the normal log */
> +	if (!event_log.ebs_called) {
> +		if (event_log.truncated ||
> +		    event_log.pos + event_size > TPM2_EVENT_LOG_SIZE) {
> +			event_log.truncated = true;
> +			return EFI_VOLUME_FULL;
> +		}
> +		put_event(pcr_index, event_type, digest_list, size, event, log);
> +		event_log.pos += event_size;
> +		event_log.last_event_size = event_size;
>   	}
>
> -	return EFI_SUCCESS;
> +	if (!event_log.get_event_called)
> +		return ret;
> +
> +	/* if GetEventLog has been called update FinalEventLog as well */
> +	if (event_log.final_pos + event_size > TPM2_EVENT_LOG_SIZE)
> +		return EFI_VOLUME_FULL;
> +
> +	log = (void *)((uintptr_t)event_log.final_buffer + event_log.final_pos);
> +	put_event(pcr_index, event_type, digest_list, size, event, log);
> +
> +	final_event =
> +		(struct efi_tcg2_final_events_table *)event_log.final_buffer;
> +	final_event->number_of_events++;
> +	event_log.final_pos += event_size;
> +
> +	return ret;
>   }
>
>   /**
> @@ -1303,6 +1333,7 @@ static efi_status_t efi_init_event_log(void)
>   	event_log.pos = 0;
>   	event_log.last_event_size = 0;
>   	event_log.get_event_called = false;
> +	event_log.ebs_called = false;
>   	event_log.truncated = false;
>
>   	/*
> @@ -1792,6 +1823,7 @@ efi_tcg2_notify_exit_boot_services(struct efi_event *event, void *context)
>
>   	EFI_ENTRY("%p, %p", event, context);

This is called in EFI_EVENT_GROUP_EXIT_BOOT_SERVICES.

This implies that whatever happens in
EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES is measured normally. Does
this conform to the TCG2 standard?

>
> +	event_log.ebs_called = true;

How should a failed call to ExitBootServices() be handled?
E.g. invalid memory map?

Best regards

Heinrich

>   	ret = platform_get_tpm2_device(&dev);
>   	if (ret != EFI_SUCCESS)
>   		goto out;
>



More information about the U-Boot mailing list