public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
To: Masahisa Kojima <masahisa.kojima@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>,
	Alexander Graf <agraf@csgraf.de>,
	Ilias Apalodimas <ilias.apalodimas@linaro.org>,
	Simon Glass <sjg@chromium.org>,
	Dhananjay Phadke <dphadke@linux.microsoft.com>,
	u-boot@lists.denx.de
Subject: Re: [PATCH v3 1/5] efi_loader: add secure boot variable measurement
Date: Tue, 10 Aug 2021 10:44:20 +0900	[thread overview]
Message-ID: <20210810014420.GA11600@laputa> (raw)
In-Reply-To: <20210806070215.19887-2-masahisa.kojima@linaro.org>

Kojima-san,

On Fri, Aug 06, 2021 at 04:02:11PM +0900, Masahisa Kojima wrote:
> TCG PC Client PFP spec requires to measure the secure
> boot policy before validating the UEFI image.
> This commit adds the secure boot variable measurement
> of "SecureBoot", "PK", "KEK", "db", "dbx", "dbt", and "dbr".
> 
> Note that this implementation assumes that secure boot
> variables are pre-configured and not be set/updated in runtime.
> 
> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> ---
> Changes in v3:
> - add "dbt" and "dbr" measurement
> - accept empty variable measurement for "SecureBoot", "PK",
>   "KEK", "db" and "dbx" as TCG2 spec requires
> - fix comment format
> 
> Changes in v2:
> - missing null check for getting variable data
> - some minor fix for readability
> 
>  include/efi_tcg2.h        |  20 +++++
>  lib/efi_loader/efi_tcg2.c | 165 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 185 insertions(+)
> 
> diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
> index bcfb98168a..497ba3ce94 100644
> --- a/include/efi_tcg2.h
> +++ b/include/efi_tcg2.h
> @@ -142,6 +142,26 @@ struct efi_tcg2_final_events_table {
>  	struct tcg_pcr_event2 event[];
>  };
>  
> +/**
> + * struct tdUEFI_VARIABLE_DATA - event log structure of UEFI variable
> + * @variable_name:		The vendorGUID parameter in the
> + *				GetVariable() API.
> + * @unicode_name_length:	The length in CHAR16 of the Unicode name of
> + *				the variable.
> + * @variable_data_length:	The size of the variable data.
> + * @unicode_name:		The CHAR16 unicode name of the variable
> + *				without NULL-terminator.
> + * @variable_data:		The data parameter of the efi variable
> + *				in the GetVariable() API.
> + */
> +struct efi_tcg2_uefi_variable_data {
> +	efi_guid_t variable_name;
> +	u64 unicode_name_length;
> +	u64 variable_data_length;
> +	u16 unicode_name[1];
> +	u8 variable_data[1];
> +};
> +
>  struct efi_tcg2_protocol {
>  	efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this,
>  					       struct efi_tcg2_boot_service_capability *capability);
> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> index 1319a8b378..a2e9587cd0 100644
> --- a/lib/efi_loader/efi_tcg2.c
> +++ b/lib/efi_loader/efi_tcg2.c
> @@ -78,6 +78,19 @@ static const struct digest_info hash_algo_list[] = {
>  	},
>  };
>  
> +struct variable_info {
> +	u16		*name;
> +	const efi_guid_t	*guid;
> +};
> +
> +static struct variable_info secure_variables[] = {
> +	{L"SecureBoot", &efi_global_variable_guid},
> +	{L"PK", &efi_global_variable_guid},
> +	{L"KEK", &efi_global_variable_guid},
> +	{L"db", &efi_guid_image_security_database},
> +	{L"dbx", &efi_guid_image_security_database},
> +};
> +
>  #define MAX_HASH_COUNT ARRAY_SIZE(hash_algo_list)
>  
>  /**
> @@ -1264,6 +1277,39 @@ free_pool:
>  	return ret;
>  }
>  
> +/**
> + * tcg2_measure_event() - common function to add event log and extend PCR
> + *
> + * @dev:		TPM device
> + * @pcr_index:		PCR index
> + * @event_type:		type of event added
> + * @size:		event size
> + * @event:		event data
> + *
> + * Return:	status code
> + */
> +static efi_status_t EFIAPI
> +tcg2_measure_event(struct udevice *dev, u32 pcr_index, u32 event_type,
> +		   u32 size, u8 event[])
> +{
> +	struct tpml_digest_values digest_list;
> +	efi_status_t ret;
> +
> +	ret = tcg2_create_digest(event, size, &digest_list);
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
> +	ret = tcg2_pcr_extend(dev, pcr_index, &digest_list);
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
> +	ret = tcg2_agile_log_append(pcr_index, event_type, &digest_list,
> +				    size, event);
> +
> +out:
> +	return ret;
> +}
> +
>  /**
>   * efi_append_scrtm_version - Append an S-CRTM EV_S_CRTM_VERSION event on the
>   *			      eventlog and extend the PCRs
> @@ -1294,6 +1340,118 @@ out:
>  	return ret;
>  }
>  
> +/**
> + * tcg2_measure_variable() - add variable event log and extend PCR
> + *
> + * @dev:		TPM device
> + * @pcr_index:		PCR index
> + * @event_type:		type of event added
> + * @var_name:		variable name
> + * @guid:		guid
> + * @data_size:		variable data size
> + * @data:		variable data
> + *
> + * Return:	status code
> + */
> +static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index,
> +					  u32 event_type, u16 *var_name,
> +					  const efi_guid_t *guid,
> +					  efi_uintn_t data_size, u8 *data)
> +{
> +	u32 event_size;
> +	efi_status_t ret;
> +	struct efi_tcg2_uefi_variable_data *event;
> +
> +	event_size = sizeof(event->variable_name) +
> +		     sizeof(event->unicode_name_length) +
> +		     sizeof(event->variable_data_length) +
> +		     (u16_strlen(var_name) * sizeof(u16)) + data_size;
> +	event = malloc(event_size);
> +	if (!event)
> +		return EFI_OUT_OF_RESOURCES;
> +
> +	guidcpy(&event->variable_name, guid);
> +	event->unicode_name_length = u16_strlen(var_name);
> +	event->variable_data_length = data_size;
> +	memcpy(event->unicode_name, var_name,
> +	       (event->unicode_name_length * sizeof(u16)));
> +	if (data) {
> +		memcpy((u16 *)event->unicode_name + event->unicode_name_length,
> +		       data, data_size);
> +	}
> +	ret = tcg2_measure_event(dev, pcr_index, event_type, event_size,
> +				 (u8 *)event);
> +	free(event);
> +	return ret;
> +}
> +
> +/**
> + * tcg2_measure_secure_boot_variable() - measure secure boot variables
> + *
> + * @dev:	TPM device
> + *
> + * Return:	status code
> + */
> +static efi_status_t tcg2_measure_secure_boot_variable(struct udevice *dev)
> +{
> +	u8 *data;
> +	efi_uintn_t data_size;
> +	u32 count, i;
> +	efi_status_t ret;
> +
> +	count = ARRAY_SIZE(secure_variables);
> +	for (i = 0; i < count; i++) {
> +		/*
> +		 * According to the TCG2 PC Client PFP spec, "SecureBoot",
> +		 * "PK", "KEK", "db" and "dbx" variables must be measured
> +		 * even if they are empty.
> +		 */
> +		data = efi_get_var(secure_variables[i].name,
> +				   secure_variables[i].guid,
> +				   &data_size);
> +
> +		ret = tcg2_measure_variable(dev, 7,
> +					    EV_EFI_VARIABLE_DRIVER_CONFIG,
> +					    secure_variables[i].name,
> +					    secure_variables[i].guid,
> +					    data_size, data);
> +		free(data);
> +		if (ret != EFI_SUCCESS)
> +			goto error;
> +	}
> +
> +	/*
> +	 * TCG2 PC Client PFP spec says "dbt" and "dbr" are
> +	 * measured if present and not empty.
> +	 */

The current implementation of secure boot doesn't support neither
dbt or dbr. Do we have to measure them now?
I think that EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION bit in
osIndicationSupported should always be checked first.

> +	data = efi_get_var(L"dbt",
> +			   &efi_global_variable_guid,
> +			   &data_size);
> +	if (data) {
> +		ret = tcg2_measure_variable(dev, 7,
> +					    EV_EFI_VARIABLE_DRIVER_CONFIG,
> +					    L"dbt",
> +					    &efi_global_variable_guid,

=> efi_guid_image_security_database

> +					    data_size, data);
> +		free(data);
> +	}
> +
> +	data = efi_get_var(L"dbr",
> +			   &efi_global_variable_guid,
> +			   &data_size);
> +	if (data) {
> +		ret = tcg2_measure_variable(dev, 7,
> +					    EV_EFI_VARIABLE_DRIVER_CONFIG,
> +					    L"dbr",
> +					    &efi_global_variable_guid,

ditto for dbr

-Takahiro Akashi

> +					    data_size, data);
> +		free(data);
> +	}
> +
> +error:
> +	return ret;
> +}
> +
>  /**
>   * efi_tcg2_register() - register EFI_TCG2_PROTOCOL
>   *
> @@ -1328,6 +1486,13 @@ efi_status_t efi_tcg2_register(void)
>  		tcg2_uninit();
>  		goto fail;
>  	}
> +
> +	ret = tcg2_measure_secure_boot_variable(dev);
> +	if (ret != EFI_SUCCESS) {
> +		tcg2_uninit();
> +		goto fail;
> +	}
> +
>  	return ret;
>  
>  fail:
> -- 
> 2.17.1
> 

  reply	other threads:[~2021-08-10  1:44 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-06  7:02 [PATCH v3 0/5] add measurement support Masahisa Kojima
2021-08-06  7:02 ` [PATCH v3 1/5] efi_loader: add secure boot variable measurement Masahisa Kojima
2021-08-10  1:44   ` AKASHI Takahiro [this message]
2021-08-11  2:59     ` Masahisa Kojima
2021-08-06  7:02 ` [PATCH v3 2/5] efi_loader: add " Masahisa Kojima
2021-08-10  2:19   ` AKASHI Takahiro
2021-08-11  3:05     ` Masahisa Kojima
2021-08-11  6:50       ` AKASHI Takahiro
2021-08-11  8:36         ` Masahisa Kojima
2021-08-06  7:02 ` [PATCH v3 3/5] efi_loader: add ExitBootServices() measurement Masahisa Kojima
2021-08-06  7:02 ` [PATCH v3 4/5] efi_loader: refactor efi_append_scrtm_version() Masahisa Kojima
2021-08-06  7:02 ` [PATCH v3 5/5] efi_loader: add comment for efi_tcg2.h Masahisa Kojima
2021-08-11  9:29 ` [PATCH v3 0/5] add measurement support Heinrich Schuchardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210810014420.GA11600@laputa \
    --to=takahiro.akashi@linaro.org \
    --cc=agraf@csgraf.de \
    --cc=dphadke@linux.microsoft.com \
    --cc=ilias.apalodimas@linaro.org \
    --cc=masahisa.kojima@linaro.org \
    --cc=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    --cc=xypron.glpk@gmx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox