diff mbox series

[v2,2/6] efi_loader: add secure boot variable measurement

Message ID 20210714130006.17837-3-masahisa.kojima@linaro.org
State Superseded
Headers show
Series add measurement support | expand

Commit Message

Masahisa Kojima July 14, 2021, 1 p.m. UTC
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" and "dbx".

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 v2:
- missing null check for getting variable data
- some minor fix for readability

 include/efi_tcg2.h        |  20 ++++++
 lib/efi_loader/efi_tcg2.c | 139 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 159 insertions(+)

-- 
2.17.1

Comments

Heinrich Schuchardt July 15, 2021, 6:44 a.m. UTC | #1
On 7/14/21 3:00 PM, 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" and "dbx".

>

> 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 v2:

> - missing null check for getting variable data

> - some minor fix for readability

>

>   include/efi_tcg2.h        |  20 ++++++

>   lib/efi_loader/efi_tcg2.c | 139 ++++++++++++++++++++++++++++++++++++++

>   2 files changed, 159 insertions(+)

>

> diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h

> index bcfb98168a..8d7b77c087 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


Please, make this

struct struct_name - Brief description

Cf.
https://www.kernel.org/doc/html/latest/doc-guide/kernel-doc.html#structure-union-and-enumeration-documentation

> + * @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..12db6f6b7c 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,92 @@ 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)));

> +	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++) {

> +		data = efi_get_var(secure_variables[i].name,

> +				   secure_variables[i].guid,

> +				   &data_size);

> +		if (data == NULL) {

> +			log_info("%ls not found\n", secure_variables[i].name);


log_debug() seems adequate here as this function will be called even if
the board is not yet provisioned.

> +			continue;

> +		}

> +

> +		ret = tcg2_measure_variable(dev, 7,

> +					    EV_EFI_VARIABLE_DRIVER_CONFIG,

> +					    secure_variables[i].name,

> +					    secure_variables[i].guid,

> +					    data_size, (u8 *)data);

> +		free(data);

> +		if (ret != EFI_SUCCESS)

> +			goto error;

> +	}

> +

> +	/*

> +	 * TODO: add DBT and DBR measurement support when u-boot supports


"dbt" and "dbr" are lower case.

> +	 * these variables.

> +	 */


Adding them to secure_variables[] now would not harm.

Best regards

Heinrich

> +

> +error:

> +	return ret;

> +}

> +

>   /**

>    * efi_tcg2_register() - register EFI_TCG2_PROTOCOL

>    *

> @@ -1328,6 +1460,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:

>
Simon Glass July 20, 2021, 6:33 p.m. UTC | #2
Hi,

On Wed, 14 Jul 2021 at 06:59, Masahisa Kojima
<masahisa.kojima@linaro.org> 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" and "dbx".

>

> 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 v2:

> - missing null check for getting variable data

> - some minor fix for readability

>

>  include/efi_tcg2.h        |  20 ++++++

>  lib/efi_loader/efi_tcg2.c | 139 ++++++++++++++++++++++++++++++++++++++

>  2 files changed, 159 insertions(+)


It looks like this code should be in lib/tpm or similar as much of it
is not specific to EFI?

Regards,
Simon
Masahisa Kojima July 21, 2021, 1:51 a.m. UTC | #3
Hi Simon,

On Wed, 21 Jul 2021 at 03:34, Simon Glass <sjg@chromium.org> wrote:
>

> Hi,

>

> On Wed, 14 Jul 2021 at 06:59, Masahisa Kojima

> <masahisa.kojima@linaro.org> 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" and "dbx".

> >

> > 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 v2:

> > - missing null check for getting variable data

> > - some minor fix for readability

> >

> >  include/efi_tcg2.h        |  20 ++++++

> >  lib/efi_loader/efi_tcg2.c | 139 ++++++++++++++++++++++++++++++++++++++

> >  2 files changed, 159 insertions(+)

>

> It looks like this code should be in lib/tpm or similar as much of it

> is not specific to EFI?


Yes, it is not directly related to EFI, but I think very small amount
of code will
be moved to lib/tpm or similar place.
lib/efi_loader/efi_tcg2.c currently implement two specs,
TCG EFI Protocol spec and TCG PC Client PFP spec.
There are many duplication in these specs, I think it is difficult to split
lib/efi_loader/efi_tcg2.c file into separate file.
In addition, efi tcg2 eventlog is currently created and initialized
during the efi init.

The major purpose of my patch series is extending measurement support,
I would like to implement these measurement in efi_tcg2.c for now.

In near future, u-boot must consider to support eventlog handoff from former
firmware such as trusted firmware, so current eventlog buffer preparation
in efi init will be modified. Then I would like to discuss implementation of
lib/efi_loader/efi_tcg2.c at that time.

Thanks,
Masahisa Kojima

>

> Regards,

> Simon
Simon Glass July 21, 2021, 2:42 a.m. UTC | #4
Hi Masahisa,

On Tue, 20 Jul 2021 at 19:51, Masahisa Kojima
<masahisa.kojima@linaro.org> wrote:
>

> Hi Simon,

>

> On Wed, 21 Jul 2021 at 03:34, Simon Glass <sjg@chromium.org> wrote:

> >

> > Hi,

> >

> > On Wed, 14 Jul 2021 at 06:59, Masahisa Kojima

> > <masahisa.kojima@linaro.org> 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" and "dbx".

> > >

> > > 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 v2:

> > > - missing null check for getting variable data

> > > - some minor fix for readability

> > >

> > >  include/efi_tcg2.h        |  20 ++++++

> > >  lib/efi_loader/efi_tcg2.c | 139 ++++++++++++++++++++++++++++++++++++++

> > >  2 files changed, 159 insertions(+)

> >

> > It looks like this code should be in lib/tpm or similar as much of it

> > is not specific to EFI?

>

> Yes, it is not directly related to EFI, but I think very small amount

> of code will

> be moved to lib/tpm or similar place.

> lib/efi_loader/efi_tcg2.c currently implement two specs,

> TCG EFI Protocol spec and TCG PC Client PFP spec.

> There are many duplication in these specs, I think it is difficult to split

> lib/efi_loader/efi_tcg2.c file into separate file.

> In addition, efi tcg2 eventlog is currently created and initialized

> during the efi init.

>

> The major purpose of my patch series is extending measurement support,

> I would like to implement these measurement in efi_tcg2.c for now.

>

> In near future, u-boot must consider to support eventlog handoff from former

> firmware such as trusted firmware, so current eventlog buffer preparation

> in efi init will be modified. Then I would like to discuss implementation of

> lib/efi_loader/efi_tcg2.c at that time.


OK thank you. Let's see how it goes.

Regards,
Simon
Masahisa Kojima Aug. 6, 2021, 2:24 a.m. UTC | #5
On Thu, 15 Jul 2021 at 15:44, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>

>

>

> On 7/14/21 3:00 PM, 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" and "dbx".

> >

> > 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 v2:

> > - missing null check for getting variable data

> > - some minor fix for readability

> >

> >   include/efi_tcg2.h        |  20 ++++++

> >   lib/efi_loader/efi_tcg2.c | 139 ++++++++++++++++++++++++++++++++++++++

> >   2 files changed, 159 insertions(+)

> >

> > diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h

> > index bcfb98168a..8d7b77c087 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

>

> Please, make this

>

> struct struct_name - Brief description

>

> Cf.

> https://www.kernel.org/doc/html/latest/doc-guide/kernel-doc.html#structure-union-and-enumeration-documentation

>

> > + * @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..12db6f6b7c 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,92 @@ 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)));

> > +     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++) {

> > +             data = efi_get_var(secure_variables[i].name,

> > +                                secure_variables[i].guid,

> > +                                &data_size);

> > +             if (data == NULL) {

> > +                     log_info("%ls not found\n", secure_variables[i].name);

>

> log_debug() seems adequate here as this function will be called even if

> the board is not yet provisioned.


Sorry but my v1 patch was correct, NULL checking for data is not required.
According to the TCG2 Client PFP spec, "PK", "KEK", "db" and "dbx" variables
must be measured even if these variables are empty.
So I will remove this NULL checking in v3 patch.

>

> > +                     continue;

> > +             }

> > +

> > +             ret = tcg2_measure_variable(dev, 7,

> > +                                         EV_EFI_VARIABLE_DRIVER_CONFIG,

> > +                                         secure_variables[i].name,

> > +                                         secure_variables[i].guid,

> > +                                         data_size, (u8 *)data);

> > +             free(data);

> > +             if (ret != EFI_SUCCESS)

> > +                     goto error;

> > +     }

> > +

> > +     /*

> > +      * TODO: add DBT and DBR measurement support when u-boot supports

>

> "dbt" and "dbr" are lower case.

>

> > +      * these variables.

> > +      */

>

> Adding them to secure_variables[] now would not harm.


Yes, I will add "dbt" and "dbr".
"dbt" and "dbr" must be measured if present and not empty according to TCG spec,
unlike "PK", "KEK", "db" and "dbx"(it must be measured even if they are empty).

Thanks,
Masahisa Kojima

>

> Best regards

>

> Heinrich

>

> > +

> > +error:

> > +     return ret;

> > +}

> > +

> >   /**

> >    * efi_tcg2_register() - register EFI_TCG2_PROTOCOL

> >    *

> > @@ -1328,6 +1460,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:

> >
diff mbox series

Patch

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index bcfb98168a..8d7b77c087 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
+ * @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..12db6f6b7c 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,92 @@  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)));
+	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++) {
+		data = efi_get_var(secure_variables[i].name,
+				   secure_variables[i].guid,
+				   &data_size);
+		if (data == NULL) {
+			log_info("%ls not found\n", secure_variables[i].name);
+			continue;
+		}
+
+		ret = tcg2_measure_variable(dev, 7,
+					    EV_EFI_VARIABLE_DRIVER_CONFIG,
+					    secure_variables[i].name,
+					    secure_variables[i].guid,
+					    data_size, (u8 *)data);
+		free(data);
+		if (ret != EFI_SUCCESS)
+			goto error;
+	}
+
+	/*
+	 * TODO: add DBT and DBR measurement support when u-boot supports
+	 * these variables.
+	 */
+
+error:
+	return ret;
+}
+
 /**
  * efi_tcg2_register() - register EFI_TCG2_PROTOCOL
  *
@@ -1328,6 +1460,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: