[PATCH 3/3] efi_loader: Extend PCR's for firmware measurements

Ilias Apalodimas ilias.apalodimas at linaro.org
Mon Nov 22 12:41:05 CET 2021


On Thu, Nov 18, 2021 at 11:47:51AM +0530, Ruchika Gupta wrote:
> Firmwares before U-Boot may be capable of doing tpm measurements
> and passing them to U-Boot in the form of eventlog. However there
> may be scenarios where the firmwares don't have TPM driver and
> are not capable of extending the measurements in the PCRs. To
> cater to such platforms, read the PCR0 to determine if the
> previous firmwares have extended the PCR0. If not, then extend
> the PCR's as the eventlog is parsed.
> 
> Signed-off-by: Ruchika Gupta <ruchika.gupta at linaro.org>
> ---
>  lib/efi_loader/efi_tcg2.c | 86 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 86 insertions(+)
> 
> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> index c97766eae3..cbd0c7d224 100644
> --- a/lib/efi_loader/efi_tcg2.c
> +++ b/lib/efi_loader/efi_tcg2.c
> @@ -178,6 +178,43 @@ static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
>  	return EFI_SUCCESS;
>  }
>  
> +/* tcg2_pcr_read - Read PCRs for a TPM2 device for a given tpml_digest_values
> + *
> + * @dev:		device
> + * @digest_list:	list of digest algorithms to extend
> + *
> + * @Return: status code
> + */
> +static efi_status_t tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
> +				    struct tpml_digest_values *digest_list)
> +{
> +	struct tpm_chip_priv *priv;
> +	unsigned int updates, pcr_select_min;
> +	u32 rc;
> +	size_t i;
> +
> +	priv = dev_get_uclass_priv(dev);
> +	if (!priv)
> +		return EFI_DEVICE_ERROR;
> +
> +	pcr_select_min = priv->pcr_select_min;
> +
> +	for (i = 0; i < digest_list->count; i++) {
> +		u16 hash_alg = digest_list->digests[i].hash_alg;
> +		u8 *digest = (u8 *)&digest_list->digests[i].digest;
> +
> +		rc = tpm2_pcr_read(dev, pcr_index, pcr_select_min,
> +				    hash_alg, digest, alg_to_len(hash_alg),
> +				    &updates);
> +		if (rc) {
> +			EFI_PRINT("Failed to read PCR\n");
> +			return EFI_DEVICE_ERROR;
> +		}
> +	}
> +
> +	return EFI_SUCCESS;
> +}
> +
>  /* tcg2_agile_log_append - Append an agile event to out eventlog
>   *
>   * @pcr_index:		PCR index
> @@ -1488,10 +1525,12 @@ static efi_status_t efi_init_event_log(struct udevice *dev)
>  	struct tcg_pcr_event *event_header = NULL;
>  	struct tpml_digest_values digest_list;
>  	size_t spec_event_size;
> +	bool extend_pcr = false;
>  	efi_status_t ret;
>  	u32 pcr, pos;
>  	u64 base;
>  	u32 sz;
> +	int i;
>  
>  	ret = platform_get_tpm2_device(&dev);
>  	if (ret != EFI_SUCCESS)
> @@ -1541,6 +1580,26 @@ static efi_status_t efi_init_event_log(struct udevice *dev)
>  			goto free_pool;
>  		}
>  
> +		ret = tcg2_pcr_read(dev, 0, &digest_list);
> +		if (ret) {
> +			log_err("Error reading PCR 0\n");
> +			goto free_pool;
> +		}
> +
> +		/*
> +		 * If PCR0 is 0, previous firmware didn't have the capability
> +		 * to extend the PCR. In this scenario, extend the PCR as
> +		 * the eventlog is parsed.
> +		 */
> +		for (i = 0; i < digest_list.count; i++) {
> +			u8 buffer[TPM2_DIGEST_LEN] =  { 0 };
> +			u16 hash_alg = digest_list.digests[i].hash_alg;
> +
> +			if (!memcmp((u8 *)&digest_list.digests[i].digest,
> +				    buffer, alg_to_len(hash_alg)))
> +				extend_pcr = true;
> +		}
> +
>  		while (pos < sz) {
>  			ret = tcg2_parse_event(dev, buffer, sz, &pos,
>  					       &digest_list, &pcr);
> @@ -1548,6 +1607,33 @@ static efi_status_t efi_init_event_log(struct udevice *dev)
>  				log_err("Error parsing event\n");
>  				goto free_pool;
>  			}
> +
> +			if (pcr != 0) {
> +				/*
> +				 * Eventlog passed by firmware should extend
> +				 * PCR0 only.

I don't get this comment.  The previous stage bootloader could extend any
PCR (0-7) as long as it adheres to the PC client spec right?
I think we just need the logic below here,  were we decide to start with an
empty eventlog if the prior stage boot loader doesn't expose one.

> +				 */
> +				log_err("Invalid PCR\n");
> +				goto free_pool;
> +			}
> +
> +			if (extend_pcr) {
> +				ret = tcg2_pcr_extend(dev, pcr, &digest_list);
> +				if (ret != EFI_SUCCESS) {
> +					log_err("Error in extending PCR\n");
> +					goto free_pool;
> +				}
> +
> +				/* Clear the digest for next event */
> +				for (i = 0; i < digest_list.count; i++) {
> +					u16 hash_alg =
> +						digest_list.digests[i].hash_alg;
> +					u8 *digest =
> +					   (u8 *)&digest_list.digests[i].digest;
> +
> +					memset(digest, 0, alg_to_len(hash_alg));
> +				}
> +			}
>  		}
>  
>  		memcpy(event_log.buffer, buffer, sz);
> -- 
> 2.25.1
> 


Cheers
/Ilias


More information about the U-Boot mailing list