[PATCH v6 3/6] tpm: Support boot measurements

Ilias Apalodimas ilias.apalodimas at linaro.org
Thu Feb 23 10:02:00 CET 2023


Hi Eddie,

  	final_event->number_of_events++;
> @@ -350,66 +142,6 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
>  	return ret;
>  }
>
> -/**
> - * platform_get_tpm_device() - retrieve TPM device
> - *
> - * This function retrieves the udevice implementing a TPM
> - *
> - * This function may be overridden if special initialization is needed.
> - *
> - * @dev:	udevice
> - * Return:	status code
> - */
> -__weak efi_status_t platform_get_tpm2_device(struct udevice **dev)
> -{
> -	for_each_tpm_device(*dev) {
> -		/* Only support TPMv2 devices */
> -		if (tpm_get_version(*dev) == TPM_V2)
> -			return EFI_SUCCESS;
> -	}
> -
> -	return EFI_NOT_FOUND;
> -}
> -
> -/**
> - * platform_get_eventlog() - retrieve the eventlog address and size
> - *
> - * This function retrieves the eventlog address and size if the underlying
> - * firmware has done some measurements and passed them.
> - *
> - * This function may be overridden based on platform specific method of
> - * passing the eventlog address and size.
> - *
> - * @dev:	udevice
> - * @addr:	eventlog address
> - * @sz:		eventlog size
> - * Return:	status code
> - */
> -__weak efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr,
> -					  u32 *sz)
> -{
> -	const u64 *basep;
> -	const u32 *sizep;
> -
> -	basep = dev_read_prop(dev, "tpm_event_log_addr", NULL);
> -	if (!basep)
> -		return EFI_NOT_FOUND;
> -
> -	*addr = be64_to_cpup((__force __be64 *)basep);
> -
> -	sizep = dev_read_prop(dev, "tpm_event_log_size", NULL);
> -	if (!sizep)
> -		return EFI_NOT_FOUND;
> -
> -	*sz = be32_to_cpup((__force __be32 *)sizep);
> -	if (*sz == 0) {
> -		log_debug("event log empty\n");
> -		return EFI_NOT_FOUND;
> -	}
> -
> -	return EFI_SUCCESS;
> -}
> -
>  /**
>   * tpm2_get_max_command_size() - get the supported max command size
>   *
> @@ -485,239 +217,6 @@ static int tpm2_get_manufacturer_id(struct udevice *dev, u32 *manufacturer_id)
>  	return 0;
>  }
>
> -/**
> - * tpm2_get_num_pcr() - get the number of PCRs
> - *
> - * @dev:		TPM device
> - * @manufacturer_id:	output buffer for the number
> - *
> - * Return: 0 on success, -1 on error
> - */
> -static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
> -{
> -	u8 response[TPM2_RESPONSE_BUFFER_SIZE];
> -	u32 ret;
> -
> -	memset(response, 0, sizeof(response));
> -	ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
> -				  TPM2_PT_PCR_COUNT, response, 1);
> -	if (ret)
> -		return -1;
> -
> -	*num_pcr = get_unaligned_be32(response + properties_offset);
> -	if (*num_pcr > TPM2_MAX_PCRS)
> -		return -1;
> -
> -	return 0;
> -}
> -
> -/**
> - * is_active_pcr() - Check if a supported algorithm is active
> - *
> - * @dev:		TPM device
> - * @selection:		struct of PCR information
> - *
> - * Return: true if PCR is active
> - */
> -static bool is_active_pcr(struct tpms_pcr_selection *selection)
> -{
> -	int i;
> -	/*
> -	 * check the pcr_select. If at least one of the PCRs supports the
> -	 * algorithm add it on the active ones
> -	 */
> -	for (i = 0; i < selection->size_of_select; i++) {
> -		if (selection->pcr_select[i])
> -			return true;
> -	}
> -
> -	return false;
> -}
> -
> -/**
> - * tpm2_get_pcr_info() - get the supported, active PCRs and number of banks
> - *
> - * @dev:		TPM device
> - * @supported_pcr:	bitmask with the algorithms supported
> - * @active_pcr:		bitmask with the active algorithms
> - * @pcr_banks:		number of PCR banks
> - *
> - * Return: 0 on success, -1 on error
> - */
> -static int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr,
> -			     u32 *active_pcr, u32 *pcr_banks)
> -{
> -	u8 response[TPM2_RESPONSE_BUFFER_SIZE];
> -	struct tpml_pcr_selection pcrs;
> -	u32 ret, num_pcr;
> -	size_t i;
> -	int tpm_ret;
> -
> -	*supported_pcr = 0;
> -	*active_pcr = 0;
> -	*pcr_banks = 0;
> -	memset(response, 0, sizeof(response));
> -	ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
> -	if (ret)
> -		goto out;
> -
> -	pcrs.count = get_unaligned_be32(response);
> -	/*
> -	 * We only support 5 algorithms for now so check against that
> -	 * instead of TPM2_NUM_PCR_BANKS
> -	 */
> -	if (pcrs.count > MAX_HASH_COUNT || pcrs.count < 1)
> -		goto out;
> -
> -	tpm_ret = tpm2_get_num_pcr(dev, &num_pcr);
> -	if (tpm_ret)
> -		goto out;
> -
> -	for (i = 0; i < pcrs.count; i++) {
> -		/*
> -		 * Definition of TPMS_PCR_SELECTION Structure
> -		 * hash: u16
> -		 * size_of_select: u8
> -		 * pcr_select: u8 array
> -		 *
> -		 * The offsets depend on the number of the device PCRs
> -		 * so we have to calculate them based on that
> -		 */
> -		u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
> -			i * offsetof(struct tpms_pcr_selection, pcr_select) +
> -			i * ((num_pcr + 7) / 8);
> -		u32 size_select_offset =
> -			hash_offset + offsetof(struct tpms_pcr_selection,
> -					       size_of_select);
> -		u32 pcr_select_offset =
> -			hash_offset + offsetof(struct tpms_pcr_selection,
> -					       pcr_select);
> -
> -		pcrs.selection[i].hash =
> -			get_unaligned_be16(response + hash_offset);
> -		pcrs.selection[i].size_of_select =
> -			__get_unaligned_be(response + size_select_offset);
> -		if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX)
> -			goto out;
> -		/* copy the array of pcr_select */
> -		memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
> -		       pcrs.selection[i].size_of_select);
> -	}
> -
> -	for (i = 0; i < pcrs.count; i++) {
> -		u32 hash_mask = alg_to_mask(pcrs.selection[i].hash);
> -
> -		if (hash_mask) {
> -			*supported_pcr |= hash_mask;
> -			if (is_active_pcr(&pcrs.selection[i]))
> -				*active_pcr |= hash_mask;
> -		} else {
> -			EFI_PRINT("Unknown algorithm %x\n", pcrs.selection[i].hash);
> -		}
> -	}
> -
> -	*pcr_banks = pcrs.count;
> -
> -	return 0;
> -out:
> -	return -1;
> -}
> -
> -/**
> - * __get_active_pcr_banks() - returns the currently active PCR banks
> - *
> - * @active_pcr_banks:		pointer for receiving the bitmap of currently
> - *				active PCR banks
> - *
> - * Return:	status code
> - */
> -static efi_status_t __get_active_pcr_banks(u32 *active_pcr_banks)
> -{
> -	struct udevice *dev;
> -	u32 active = 0, supported = 0, pcr_banks = 0;
> -	efi_status_t ret;
> -	int err;
> -
> -	ret = platform_get_tpm2_device(&dev);
> -	if (ret != EFI_SUCCESS)
> -		goto out;
> -
> -	err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
> -	if (err) {
> -		ret = EFI_DEVICE_ERROR;
> -		goto out;
> -	}
> -
> -	*active_pcr_banks = active;
> -
> -out:
> -	return ret;
> -}
> -
> -/* tcg2_create_digest - create a list of digests of the supported PCR banks
> - *			for a given memory range
> - *
> - * @input:		input memory
> - * @length:		length of buffer to calculate the digest
> - * @digest_list:	list of digests to fill in
> - *
> - * Return:		status code
> - */
> -static efi_status_t tcg2_create_digest(const u8 *input, u32 length,
> -				       struct tpml_digest_values *digest_list)
> -{
> -	sha1_context ctx;
> -	sha256_context ctx_256;
> -	sha512_context ctx_512;
> -	u8 final[TPM2_SHA512_DIGEST_SIZE];
> -	efi_status_t ret;
> -	u32 active;
> -	size_t i;
> -
> -	ret = __get_active_pcr_banks(&active);
> -	if (ret != EFI_SUCCESS)
> -		return ret;
> -
> -	digest_list->count = 0;
> -	for (i = 0; i < MAX_HASH_COUNT; i++) {
> -		u16 hash_alg = hash_algo_list[i].hash_alg;
> -
> -		if (!(active & alg_to_mask(hash_alg)))
> -			continue;
> -		switch (hash_alg) {
> -		case TPM2_ALG_SHA1:
> -			sha1_starts(&ctx);
> -			sha1_update(&ctx, input, length);
> -			sha1_finish(&ctx, final);
> -			break;
> -		case TPM2_ALG_SHA256:
> -			sha256_starts(&ctx_256);
> -			sha256_update(&ctx_256, input, length);
> -			sha256_finish(&ctx_256, final);
> -			break;
> -		case TPM2_ALG_SHA384:
> -			sha384_starts(&ctx_512);
> -			sha384_update(&ctx_512, input, length);
> -			sha384_finish(&ctx_512, final);
> -			break;
> -		case TPM2_ALG_SHA512:
> -			sha512_starts(&ctx_512);
> -			sha512_update(&ctx_512, input, length);
> -			sha512_finish(&ctx_512, final);
> -			break;
> -		default:
> -			EFI_PRINT("Unsupported algorithm %x\n", hash_alg);
> -			return EFI_INVALID_PARAMETER;
> -		}
> -		digest_list->digests[digest_list->count].hash_alg = hash_alg;
> -		memcpy(&digest_list->digests[digest_list->count].digest, final,
> -		       (u32)alg_to_len(hash_alg));
> -		digest_list->count++;
> -	}
> -
> -	return EFI_SUCCESS;
> -}
> -
>  /**
>   * efi_tcg2_get_capability() - protocol capability information and state information
>   *
> @@ -759,7 +258,7 @@ efi_tcg2_get_capability(struct efi_tcg2_protocol *this,
>  	capability->protocol_version.major = 1;
>  	capability->protocol_version.minor = 1;
>
> -	efi_ret = platform_get_tpm2_device(&dev);
> +	efi_ret = tcg2_platform_get_tpm2(&dev);
>  	if (efi_ret != EFI_SUCCESS) {
>  		capability->supported_event_logs = 0;
>  		capability->hash_algorithm_bitmap = 0;
> @@ -855,7 +354,7 @@ efi_tcg2_get_eventlog(struct efi_tcg2_protocol *this,
>  		goto out;
>  	}
>
> -	ret = platform_get_tpm2_device(&dev);
> +	ret = tcg2_platform_get_tpm2(&dev);
>  	if (ret != EFI_SUCCESS) {
>  		event_log_location = NULL;
>  		event_log_last_entry = NULL;
> @@ -890,6 +389,7 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
>  	struct efi_image_regions *regs = NULL;
>  	void *new_efi = NULL;
>  	u8 hash[TPM2_SHA512_DIGEST_SIZE];
> +	struct udevice *dev;
>  	efi_status_t ret;
>  	u32 active;
>  	int i;
> @@ -905,16 +405,20 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
>  		goto out;
>  	}
>
> -	ret = __get_active_pcr_banks(&active);
> +	ret = tcg2_platform_get_tpm2(&dev);
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
> +	ret = tcg2_get_active_pcr_banks(dev, &active);
>  	if (ret != EFI_SUCCESS) {
>  		goto out;
>  	}
>
>  	digest_list->count = 0;
> -	for (i = 0; i < MAX_HASH_COUNT; i++) {
> -		u16 hash_alg = hash_algo_list[i].hash_alg;
> +	for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); i++) {
> +		u16 hash_alg = tpm2_supported_algorithms[i];
>
> -		if (!(active & alg_to_mask(hash_alg)))
> +		if (!(active & tpm2_algorithm_to_mask(hash_alg)))
>  			continue;
>  		switch (hash_alg) {
>  		case TPM2_ALG_SHA1:
> @@ -935,7 +439,7 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
>  		}
>  		digest_list->digests[digest_list->count].hash_alg = hash_alg;
>  		memcpy(&digest_list->digests[digest_list->count].digest, hash,
> -		       (u32)alg_to_len(hash_alg));
> +		       (u32)tpm2_algorithm_to_len(hash_alg));
>  		digest_list->count++;
>  	}
>
> @@ -975,7 +479,7 @@ efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size,
>  	if (!is_tcg2_protocol_installed())
>  		return EFI_SUCCESS;
>
> -	ret = platform_get_tpm2_device(&dev);
> +	ret = tcg2_platform_get_tpm2(&dev);
>  	if (ret != EFI_SUCCESS)
>  		return EFI_SECURITY_VIOLATION;
>
> @@ -1084,7 +588,7 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags,
>  		goto out;
>  	}
>
> -	ret = platform_get_tpm2_device(&dev);
> +	ret = tcg2_platform_get_tpm2(&dev);
>  	if (ret != EFI_SUCCESS)
>  		goto out;
>
> @@ -1119,7 +623,7 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags,
>  		ret = tcg2_hash_pe_image((void *)(uintptr_t)data_to_hash,
>  					 data_to_hash_len, &digest_list);
>  	} else {
> -		ret = tcg2_create_digest((u8 *)(uintptr_t)data_to_hash,
> +		ret = tcg2_create_digest(dev, (u8 *)(uintptr_t)data_to_hash,
>  					 data_to_hash_len, &digest_list);
>  	}
>
> @@ -1182,7 +686,7 @@ efi_tcg2_submit_command(struct efi_tcg2_protocol *this,
>  		goto out;
>  	}
>
> -	ret = platform_get_tpm2_device(&dev);
> +	ret = tcg2_platform_get_tpm2(&dev);
>  	if (ret != EFI_SUCCESS)
>  		goto out;
>
> @@ -1211,6 +715,7 @@ static efi_status_t EFIAPI
>  efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this,
>  			      u32 *active_pcr_banks)
>  {
> +	struct udevice *dev;
>  	efi_status_t ret;
>
>  	if (!this || !active_pcr_banks) {
> @@ -1218,8 +723,12 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this,
>  		goto out;
>  	}
>
> +	ret = tcg2_platform_get_tpm2(&dev);
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
>  	EFI_ENTRY("%p, %p", this, active_pcr_banks);
> -	ret = __get_active_pcr_banks(active_pcr_banks);
> +	ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);
>
>  out:
>  	return EFI_EXIT(ret);
> @@ -1270,397 +779,6 @@ static const struct efi_tcg2_protocol efi_tcg2_protocol = {
>  	.get_result_of_set_active_pcr_banks = efi_tcg2_get_result_of_set_active_pcr_banks,
>  };
>
> -/**
> - * parse_event_log_header() -  Parse and verify the event log header fields
> - *
> - * @buffer:			Pointer to the start of the eventlog
> - * @size:			Size of the eventlog
> - * @pos:			Return offset of the next event in buffer right
> - *				after the event header i.e specID
> - *
> - * Return:	status code
> - */
> -static efi_status_t parse_event_log_header(void *buffer, u32 size, u32 *pos)
> -{
> -	struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
> -	int i = 0;
> -
> -	if (size < sizeof(*event_header))
> -		return EFI_COMPROMISED_DATA;
> -
> -	if (get_unaligned_le32(&event_header->pcr_index) != 0 ||
> -	    get_unaligned_le32(&event_header->event_type) != EV_NO_ACTION)
> -		return EFI_COMPROMISED_DATA;
> -
> -	for (i = 0; i < sizeof(event_header->digest); i++) {
> -		if (event_header->digest[i])
> -			return EFI_COMPROMISED_DATA;
> -	}
> -
> -	*pos += sizeof(*event_header);
> -
> -	return EFI_SUCCESS;
> -}
> -
> -/**
> - * parse_specid_event() -  Parse and verify the specID Event in the eventlog
> - *
> - * @dev:		udevice
> - * @buffer:		Pointer to the start of the eventlog
> - * @log_size:		Size of the eventlog
> - * @pos:		[in] Offset of specID event in the eventlog buffer
> - *			[out] Return offset of the next event in the buffer
> - *			after the specID
> - * @digest_list:	list of digests in the event
> - *
> - * Return:		status code
> - * @pos			Offset in the eventlog where the specID event ends
> - * @digest_list:	list of digests in the event
> - */
> -static efi_status_t parse_specid_event(struct udevice *dev, void *buffer,
> -				       u32 log_size, u32 *pos,
> -				       struct tpml_digest_values *digest_list)
> -{
> -	struct tcg_efi_spec_id_event *spec_event;
> -	struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
> -	size_t spec_event_size;
> -	u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
> -	u32 spec_active = 0;
> -	u16 hash_alg;
> -	u8 vendor_sz;
> -	int err, i;
> -
> -	if (*pos >= log_size || (*pos + sizeof(*spec_event)) > log_size)
> -		return EFI_COMPROMISED_DATA;
> -
> -	/* Check specID event data */
> -	spec_event = (struct tcg_efi_spec_id_event *)((uintptr_t)buffer + *pos);
> -	/* Check for signature */
> -	if (memcmp(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
> -		   sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03))) {
> -		log_err("specID Event: Signature mismatch\n");
> -		return EFI_COMPROMISED_DATA;
> -	}
> -
> -	if (spec_event->spec_version_minor !=
> -			TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
> -	    spec_event->spec_version_major !=
> -			TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
> -		return EFI_COMPROMISED_DATA;
> -
> -	if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
> -	    spec_event->number_of_algorithms < 1) {
> -		log_err("specID Event: Number of algorithms incorrect\n");
> -		return EFI_COMPROMISED_DATA;
> -	}
> -
> -	alg_count = spec_event->number_of_algorithms;
> -
> -	err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
> -	if (err)
> -		return EFI_DEVICE_ERROR;
> -
> -	digest_list->count = 0;
> -	/*
> -	 * We have to take care that the sequence of algorithms that we record
> -	 * in digest_list matches the sequence in eventlog.
> -	 */
> -	for (i = 0; i < alg_count; i++) {
> -		hash_alg =
> -		  get_unaligned_le16(&spec_event->digest_sizes[i].algorithm_id);
> -
> -		if (!(supported & alg_to_mask(hash_alg))) {
> -			log_err("specID Event: Unsupported algorithm\n");
> -			return EFI_COMPROMISED_DATA;
> -		}
> -		digest_list->digests[digest_list->count++].hash_alg = hash_alg;
> -
> -		spec_active |= alg_to_mask(hash_alg);
> -	}
> -
> -	/*
> -	 * TCG specification expects the event log to have hashes for all
> -	 * active PCR's
> -	 */
> -	if (spec_active != active) {
> -		/*
> -		 * Previous stage bootloader should know all the active PCR's
> -		 * and use them in the Eventlog.
> -		 */
> -		log_err("specID Event: All active hash alg not present\n");
> -		return EFI_COMPROMISED_DATA;
> -	}
> -
> -	/*
> -	 * the size of the spec event and placement of vendor_info_size
> -	 * depends on supported algoriths
> -	 */
> -	spec_event_size =
> -		offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
> -		alg_count * sizeof(spec_event->digest_sizes[0]);
> -
> -	if (*pos + spec_event_size >= log_size)
> -		return EFI_COMPROMISED_DATA;
> -
> -	vendor_sz = *(uint8_t *)((uintptr_t)buffer + *pos + spec_event_size);
> -
> -	spec_event_size += sizeof(vendor_sz) + vendor_sz;
> -	*pos += spec_event_size;
> -
> -	if (get_unaligned_le32(&event_header->event_size) != spec_event_size) {
> -		log_err("specID event: header event size mismatch\n");
> -		/* Right way to handle this can be to call SetActive PCR's */
> -		return EFI_COMPROMISED_DATA;
> -	}
> -
> -	return EFI_SUCCESS;
> -}
> -
> -/**
> - * tcg2_parse_event() -  Parse the event in the eventlog
> - *
> - * @dev:		udevice
> - * @buffer:		Pointer to the start of the eventlog
> - * @log_size:		Size of the eventlog
> - * @offset:		[in] Offset of the event in the eventlog buffer
> - *			[out] Return offset of the next event in the buffer
> - * @digest_list:	list of digests in the event
> - * @pcr			Index of the PCR in the event
> - *
> - * Return:		status code
> - */
> -static efi_status_t tcg2_parse_event(struct udevice *dev, void *buffer,
> -				     u32 log_size, u32 *offset,
> -				     struct tpml_digest_values *digest_list,
> -				     u32 *pcr)
> -{
> -	struct tcg_pcr_event2 *event = NULL;
> -	u32 count, size, event_size;
> -	size_t pos;
> -
> -	event_size = tcg_event_final_size(digest_list);
> -	if (*offset >= log_size || *offset + event_size > log_size) {
> -		log_err("Event exceeds log size\n");
> -		return EFI_COMPROMISED_DATA;
> -	}
> -
> -	event = (struct tcg_pcr_event2 *)((uintptr_t)buffer + *offset);
> -	*pcr = get_unaligned_le32(&event->pcr_index);
> -
> -	/* get the count */
> -	count = get_unaligned_le32(&event->digests.count);
> -	if (count != digest_list->count)
> -		return EFI_COMPROMISED_DATA;
> -
> -	pos = offsetof(struct tcg_pcr_event2, digests);
> -	pos += offsetof(struct tpml_digest_values, digests);
> -
> -	for (int i = 0; i < digest_list->count; i++) {
> -		u16 alg;
> -		u16 hash_alg = digest_list->digests[i].hash_alg;
> -		u8 *digest = (u8 *)&digest_list->digests[i].digest;
> -
> -		alg = get_unaligned_le16((void *)((uintptr_t)event + pos));
> -
> -		if (alg != hash_alg)
> -			return EFI_COMPROMISED_DATA;
> -
> -		pos += offsetof(struct tpmt_ha, digest);
> -		memcpy(digest, (void *)((uintptr_t)event + pos), alg_to_len(hash_alg));
> -		pos += alg_to_len(hash_alg);
> -	}
> -
> -	size = get_unaligned_le32((void *)((uintptr_t)event + pos));
> -	event_size += size;
> -	pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
> -	pos += size;
> -
> -	/* make sure the calculated buffer is what we checked against */
> -	if (pos != event_size)
> -		return EFI_COMPROMISED_DATA;
> -
> -	if (pos > log_size)
> -		return EFI_COMPROMISED_DATA;
> -
> -	*offset += pos;
> -
> -	return EFI_SUCCESS;
> -}
> -
> -/**
> - * tcg2_get_fw_eventlog() -  Get the eventlog address and size
> - *
> - * If the previous firmware has passed some eventlog, this function get it's
> - * location and check for it's validity.
> - *
> - * @dev:		udevice
> - * @log_buffer:		eventlog address
> - * @log_sz:		eventlog size
> - *
> - * Return:	status code
> - */
> -static efi_status_t tcg2_get_fw_eventlog(struct udevice *dev, void *log_buffer,
> -					 size_t *log_sz)
> -{
> -	struct tpml_digest_values digest_list;
> -	void *buffer;
> -	efi_status_t ret;
> -	u32 pcr, pos;
> -	u64 base;
> -	u32 sz;
> -	bool extend_pcr = false;
> -	int i;
> -
> -	ret = platform_get_eventlog(dev, &base, &sz);
> -	if (ret != EFI_SUCCESS)
> -		return ret;
> -
> -	if (sz > TPM2_EVENT_LOG_SIZE)
> -		return EFI_VOLUME_FULL;
> -
> -	buffer = (void *)(uintptr_t)base;
> -	pos = 0;
> -	/* Parse the eventlog to check for its validity */
> -	ret = parse_event_log_header(buffer, sz, &pos);
> -	if (ret)
> -		return ret;
> -
> -	ret = parse_specid_event(dev, buffer, sz, &pos, &digest_list);
> -	if (ret) {
> -		log_err("Error parsing SPEC ID Event\n");
> -		return ret;
> -	}
> -
> -	ret = tcg2_pcr_read(dev, 0, &digest_list);
> -	if (ret) {
> -		log_err("Error reading PCR 0\n");
> -		return ret;
> -	}
> -
> -	/*
> -	 * 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 hash_buf[TPM2_SHA512_DIGEST_SIZE] = { 0 };
> -		u16 hash_alg = digest_list.digests[i].hash_alg;
> -
> -		if (!memcmp((u8 *)&digest_list.digests[i].digest, hash_buf,
> -			    alg_to_len(hash_alg)))
> -			extend_pcr = true;
> -	}
> -
> -	while (pos < sz) {
> -		ret = tcg2_parse_event(dev, buffer, sz, &pos, &digest_list,
> -				       &pcr);
> -		if (ret) {
> -			log_err("Error parsing event\n");
> -			return ret;
> -		}
> -		if (extend_pcr) {
> -			ret = tcg2_pcr_extend(dev, pcr, &digest_list);
> -			if (ret != EFI_SUCCESS) {
> -				log_err("Error in extending PCR\n");
> -				return ret;
> -			}
> -
> -			/* 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(log_buffer, buffer, sz);
> -	*log_sz = sz;
> -
> -	return ret;
> -}
> -
> -/**
> - * create_specid_event() - Create the first event in the eventlog
> - *
> - * @dev:			tpm device
> - * @event_header:		Pointer to the final event header
> - * @event_size:			final spec event size
> - *
> - * Return:	status code
> - */
> -static efi_status_t create_specid_event(struct udevice *dev, void *buffer,
> -					size_t *event_size)
> -{
> -	struct tcg_efi_spec_id_event *spec_event;
> -	size_t spec_event_size;
> -	efi_status_t ret = EFI_DEVICE_ERROR;
> -	u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
> -	int err;
> -	size_t i;
> -
> -	/*
> -	 * Create Spec event. This needs to be the first event in the log
> -	 * according to the TCG EFI protocol spec
> -	 */
> -
> -	/* Setup specID event data */
> -	spec_event = (struct tcg_efi_spec_id_event *)buffer;
> -	memcpy(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
> -	       sizeof(spec_event->signature));
> -	put_unaligned_le32(0, &spec_event->platform_class); /* type client */
> -	spec_event->spec_version_minor =
> -		TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
> -	spec_event->spec_version_major =
> -		TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
> -	spec_event->spec_errata =
> -		TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
> -	spec_event->uintn_size = sizeof(efi_uintn_t) / sizeof(u32);
> -
> -	err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
> -
> -	if (err)
> -		goto out;
> -
> -	for (i = 0; i < pcr_count; i++) {
> -		u16 hash_alg = hash_algo_list[i].hash_alg;
> -		u16 hash_len = hash_algo_list[i].hash_len;
> -
> -		if (active & alg_to_mask(hash_alg)) {
> -			put_unaligned_le16(hash_alg,
> -					   &spec_event->digest_sizes[alg_count].algorithm_id);
> -			put_unaligned_le16(hash_len,
> -					   &spec_event->digest_sizes[alg_count].digest_size);
> -			alg_count++;
> -		}
> -	}
> -
> -	spec_event->number_of_algorithms = alg_count;
> -	if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
> -	    spec_event->number_of_algorithms < 1)
> -		goto out;
> -
> -	/*
> -	 * the size of the spec event and placement of vendor_info_size
> -	 * depends on supported algoriths
> -	 */
> -	spec_event_size =
> -		offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
> -		spec_event->number_of_algorithms * sizeof(spec_event->digest_sizes[0]);
> -	/* no vendor info for us */
> -	memset(buffer + spec_event_size, 0, 1);
> -	/* add a byte for vendor_info_size in the spec event */
> -	spec_event_size += 1;
> -	*event_size = spec_event_size;
> -
> -	return EFI_SUCCESS;
> -
> -out:
> -	return ret;
> -}
> -
>  /**
>   * tcg2_uninit - remove the final event table and free efi memory on failures
>   */
> @@ -1722,7 +840,7 @@ out:
>  }
>
>  /**
> - * tcg2_measure_event() - common function to add event log and extend PCR
> + * measure_event() - common function to add event log and extend PCR
>   *
>   * @dev:		TPM device
>   * @pcr_index:		PCR index
> @@ -1732,14 +850,13 @@ out:
>   *
>   * Return:	status code
>   */
> -static efi_status_t
> -tcg2_measure_event(struct udevice *dev, u32 pcr_index, u32 event_type,
> -		   u32 size, u8 event[])
> +static efi_status_t 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);
> +	ret = tcg2_create_digest(dev, event, size, &digest_list);
>  	if (ret != EFI_SUCCESS)
>  		goto out;
>
> @@ -1766,9 +883,8 @@ static efi_status_t efi_append_scrtm_version(struct udevice *dev)
>  {
>  	efi_status_t ret;
>
> -	ret = tcg2_measure_event(dev, 0, EV_S_CRTM_VERSION,
> -				 strlen(version_string) + 1,
> -				 (u8 *)version_string);
> +	ret = measure_event(dev, 0, EV_S_CRTM_VERSION,
> +			    strlen(version_string) + 1, (u8 *)version_string);
>
>  	return ret;
>  }
> @@ -1784,12 +900,11 @@ static efi_status_t efi_init_event_log(void)
>  	 * vendor_info_size is currently set to 0, we need to change the length
>  	 * and allocate the flexible array member if this changes
>  	 */
> -	struct tcg_pcr_event *event_header = NULL;
> +	struct tcg2_event_log elog;
>  	struct udevice *dev;
> -	size_t spec_event_size;
>  	efi_status_t ret;
>
> -	ret = platform_get_tpm2_device(&dev);
> +	ret = tcg2_platform_get_tpm2(&dev);
>  	if (ret != EFI_SUCCESS)
>  		return ret;
>
> @@ -1808,7 +923,6 @@ static efi_status_t efi_init_event_log(void)
>  	 * The log header is defined to be in SHA1 event log entry format.
>  	 * Setup event header
>  	 */
> -	event_header =  (struct tcg_pcr_event *)event_log.buffer;
>  	event_log.pos = 0;
>  	event_log.last_event_size = 0;
>  	event_log.get_event_called = false;
> @@ -1819,34 +933,19 @@ static efi_status_t efi_init_event_log(void)
>  	 * Check if earlier firmware have passed any eventlog. Different
>  	 * platforms can use different ways to do so.
>  	 */
> -	ret = tcg2_get_fw_eventlog(dev, event_log.buffer, &event_log.pos);
> +	ret = tcg2_init_log(dev, &elog);
> +	if (ret != EFI_SUCCESS)
> +		goto free_pool;

So I think this is the last bit we need to change in order to support EFI
properly.  I read the email regarding the newly added reserved memory memory
to the TPM node and it's fine, but that won't work for the existing U-Boot
dtbs.  Since this was working out of the box, I'd still prefer to keep that
working even if that entry is missing.

If you look at this function, there is an efi_allocate_pool() call a few
lines above.  What this does is allocate the EventLog memory for EFI.
Note here that this *has* to be EFI memory since the kernel's efi-stub
can still call into the firmware (and in fact it does, that's who we measure
the initrd in > 5.18 kernels).  After the allocation it looks for those DT
entries, and if tpm_event_log_addr is found it parses the EventLog and
1. Extends the PCRs
2. Adds the events into the Eventlog

The reason for that is that TF-A (the Arm first stage boot loader),
doesn't have any TPM drivers.  So U-Boot is trying to be 'smart' here.
We are grabbing the EventLog from the previous bootloader and if PCR0!=0 we
replay that into the hardware and re-create the EventLog.

[...]

Thanks!
/Ilias
>


More information about the U-Boot mailing list