Re: [PATCH v3 2/6] tpm: Support boot measurements

Ilias Apalodimas
2023-01-16T12:01:16Z

Hi Eddie

> +static inline u16 tpm2_algorithm_to_len(enum tpm2_algorithms a)
> +{
> + switch (a) {
> + case TPM2_ALG_SHA1:
> + return TPM2_SHA1_DIGEST_SIZE;
> + case TPM2_ALG_SHA256:
> + return TPM2_SHA256_DIGEST_SIZE;
> + case TPM2_ALG_SHA384:
> + return TPM2_SHA384_DIGEST_SIZE;
> + case TPM2_ALG_SHA512:
> + return TPM2_SHA512_DIGEST_SIZE;
> + default:
> + return 0;
> + }
> +}

Any reason we can't move the static 'const struct digest_info
hash_algo_list' from the efi_tcg.c here? We can then move the
functions defined in there alg_to_mask and alg_to_len.

And since alg_to_mask is really just a bitshift maybe replace that?

> +
> +#define tpm2_algorithm_to_mask(a) (1 << (a))
> +
> /* NV index attributes */
> enum tpm_index_attrs {
> TPMA_NV_PPWRITE = 1UL << 0,
> @@ -419,6 +481,142 @@ enum {
> HR_NV_INDEX = TPM_HT_NV_INDEX << HR_SHIFT,
> };
>
> +/**
> + * struct tcg2_event_log - Container for managing the platform event log
> + *
> + * @log: Address of the log
> + * @log_position: Current entry position
> + * @log_size: Log space available
> + */
> +struct tcg2_event_log {
> + u8 *log;
> + u32 log_position;
> + u32 log_size;
> +};
> +
> +/**
> + * Create a list of digests of the supported PCR banks for a given input data
> + *
> + * @dev TPM device
> + * @input Data
> + * @length Length of the data to calculate the digest
> + * @digest_list List of digests to fill in
> + *
> + * Return: zero on success, negative errno otherwise
> + */
> +int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
> + struct tpml_digest_values *digest_list);
> +
> +/**
> + * Get the event size of the specified digests
> + *
> + * @digest_list List of digests for the event
> + *
> + * Return: Size in bytes of the event
> + */
> +u32 tcg2_event_get_size(struct tpml_digest_values *digest_list);
> +
> +/**
> + * tcg2_log_append - Append an event to an event log
> + *
> + * @pcr_index Index of the PCR
> + * @event_type Type of event
> + * @digest_list List of digests to add
> + * @size Size of event
> + * @event Event data
> + * @log Log buffer to append the event to
> + */
> +void tcg2_log_append(u32 pcr_index, u32 event_type,
> + struct tpml_digest_values *digest_list, u32 size,
> + const u8 *event, u8 *log);
> +
> +/**
> + * Extend the PCR with specified digests
> + *
> + * @dev TPM device
> + * @pcr_index Index of the PCR
> + * @digest_list List of digests to extend
> + *
> + * Return: zero on success, negative errno otherwise
> + */
> +int tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
> + struct tpml_digest_values *digest_list);
> +
> +/**
> + * Measure data into the TPM PCRs and the platform event log.
> + *
> + * @dev TPM device
> + * @log Platform event log
> + * @pcr_index Index of the PCR
> + * @size Size of the data
> + * @data Pointer to the data
> + * @event_type Event log type
> + * @event_size Size of the event
> + * @event Pointer to the event
> + *
> + * Return: zero on success, negative errno otherwise
> + */
> +int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
> + u32 pcr_index, u32 size, const u8 *data, u32 event_type,
> + u32 event_size, const u8 *event);
> +
> +/**
> + * Measure an event into the platform event log.
> + *
> + * @dev TPM device
> + * @log Platform event log
> + * @pcr_index Index of the PCR
> + * @event_type Event log type
> + * @size Size of the event
> + * @event Pointer to the event
> + *
> + * Return: zero on success, negative errno otherwise
> + */
> +int tcg2_measure_event(struct udevice *dev, struct tcg2_event_log *elog,
> + u32 pcr_index, u32 event_type, u32 size,
> + const u8 *event);
> +
> +/**
> + * Begin measurements.
> + *
> + * Return: zero on success, negative errno otherwise
> + */
> +int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog);
> +
> +/**
> + * Stop measurements and record separator events.
> + */
> +void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
> + bool error);
> +
> +/**
> + * Get the platform event log address and size.
> + *
> + * @dev TPM device
> + * @addr Address of the log
> + * @size Size of the log
> + *
> + * Return: zero on success, negative errno otherwise
> + */
> +int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size);
> +
> +/**
> + * Get the first TPM2 device found.
> + *
> + * @dev TPM device
> + *
> + * Return: zero on success, negative errno otherwise
> + */
> +int tcg2_platform_get_tpm2(struct udevice **dev);
> +
> +/**
> + * Platform-specific function for handling TPM startup errors
> + *
> + * @dev TPM device
> + * @rc The TPM response code
> + */
> +void tcg2_platform_startup_error(struct udevice *dev, int rc);
> +
> /**
> * Issue a TPM2_Startup command.
> *
> @@ -538,6 +736,19 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
> u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
> void *buf, size_t prop_count);
>
> +/**
> + * 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, code of operation or negative errno on failure
> + */
> +int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
> + u32 *pcr_banks);
> +
> /**
> * Issue a TPM2_DictionaryAttackLockReset command.
> *
> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> index a525ebf75b..c0ac32a58e 100644
> --- a/lib/efi_loader/efi_tcg2.c
> +++ b/lib/efi_loader/efi_tcg2.c
> @@ -162,52 +162,6 @@ static bool is_tcg2_protocol_installed(void)
> return ret == EFI_SUCCESS;
> }
>
> -static u32 tcg_event_final_size(struct tpml_digest_values *digest_list)
> -{
> - u32 len;
> - size_t i;
> -
> - len = offsetof(struct tcg_pcr_event2, digests);
> - len += offsetof(struct tpml_digest_values, digests);
> - for (i = 0; i < digest_list->count; i++) {
> - u16 hash_alg = digest_list->digests[i].hash_alg;
> -
> - len += offsetof(struct tpmt_ha, digest);
> - len += alg_to_len(hash_alg);
> - }
> - len += sizeof(u32); /* tcg_pcr_event2 event_size*/
> -
> - return len;
> -}
> -
> -/* tcg2_pcr_extend - Extend 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_extend(struct udevice *dev, u32 pcr_index,
> - struct tpml_digest_values *digest_list)
> -{
> - u32 rc;
> - size_t i;
> -
> - for (i = 0; i < digest_list->count; i++) {
> - u32 alg = digest_list->digests[i].hash_alg;
> -
> - rc = tpm2_pcr_extend(dev, pcr_index, alg,
> - (u8 *)&digest_list->digests[i].digest,
> - alg_to_len(alg));
> - if (rc) {
> - EFI_PRINT("Failed to extend PCR\n");
> - return EFI_DEVICE_ERROR;
> - }
> - }
> -
> - return EFI_SUCCESS;
> -}
> -
> /* tcg2_pcr_read - Read PCRs for a TPM2 device for a given tpml_digest_values
> *
> * @dev: device
> @@ -246,61 +200,6 @@ static efi_status_t tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
> return EFI_SUCCESS;
> }
>
> -/* 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
> - *
> - */
> -static void put_event(u32 pcr_index, u32 event_type,
> - struct tpml_digest_values *digest_list, u32 size,
> - u8 event[], void *log)
> -{
> - size_t pos;
> - size_t i;
> - u32 event_size;
> -
> - /*
> - * 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);
> -
> - put_unaligned_le32(pcr_index, log);
> - pos = offsetof(struct tcg_pcr_event2, event_type);
> - put_unaligned_le32(event_type, (void *)((uintptr_t)log + pos));
> - pos = offsetof(struct tcg_pcr_event2, digests); /* count */
> - put_unaligned_le32(digest_list->count, (void *)((uintptr_t)log + pos));
> -
> - pos += offsetof(struct tpml_digest_values, digests);
> - 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;
> -
> - put_unaligned_le16(hash_alg, (void *)((uintptr_t)log + pos));
> - pos += offsetof(struct tpmt_ha, digest);
> - memcpy((void *)((uintptr_t)log + pos), digest, alg_to_len(hash_alg));
> - pos += alg_to_len(hash_alg);
> - }
> -
> - put_unaligned_le32(size, (void *)((uintptr_t)log + pos));
> - pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
> - memcpy((void *)((uintptr_t)log + pos), event, size);
> - pos += size;
> -
> - /*
> - * 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)
> - log_err("Appending to the EventLog failed\n");
> -}
> -
> /* tcg2_agile_log_append - Append an agile event to an eventlog
> *
> * @pcr_index: PCR index
> @@ -317,7 +216,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
> 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);
> + u32 event_size = size + tcg2_event_get_size(digest_list);
> struct efi_tcg2_final_events_table *final_event;
> efi_status_t ret = EFI_SUCCESS;
>
> @@ -328,7 +227,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
> event_log.truncated = true;
> return EFI_VOLUME_FULL;
> }
> - put_event(pcr_index, event_type, digest_list, size, event, log);
> + tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
> event_log.pos += event_size;
> event_log.last_event_size = event_size;
> }
> @@ -341,7 +240,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
> 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);
> + tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
>
> final_event = event_log.final_buffer;
> final_event->number_of_events++;
> @@ -350,27 +249,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
> *
> @@ -485,144 +363,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
> *
> @@ -638,7 +378,7 @@ static efi_status_t __get_active_pcr_banks(u32 *active_pcr_banks)
> efi_status_t ret;
> int err;
>
> - ret = platform_get_tpm2_device(&dev);
> + ret = tcg2_platform_get_tpm2(&dev);
> if (ret != EFI_SUCCESS)
> goto out;
>

We can get rid of this entirely and just define the
efi_tcg2_get_active_pcr_banks in the efi_tcg.c now.
__get_active_pcr_banks == tcg2_get_active_pcr_banks with the only
diffence being the udevice which is now an argument

> @@ -654,70 +394,6 @@ out:
> return ret;
> }
>
> * efi_tcg2_get_capability() - protocol capability information and state information
> *
> @@ -759,7 +435,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 +531,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;
> @@ -975,7 +651,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 +760,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 +795,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 +858,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;
>
> @@ -1438,7 +1114,7 @@ static efi_status_t tcg2_parse_event(struct udevice *dev, void *buffer,
> u32 count, size, event_size;
> size_t pos;
>
> - event_size = tcg_event_final_size(digest_list);
> + event_size = tcg2_event_get_size(digest_list);
> if (*offset >= log_size || *offset + event_size > log_size) {
> log_err("Event exceeds log size\n");
> return EFI_COMPROMISED_DATA;
> @@ -1739,7 +1415,7 @@ tcg2_measure_event(struct udevice *dev, u32 pcr_index, u32 event_type,
> 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;
>
> @@ -1789,7 +1465,7 @@ static efi_status_t efi_init_event_log(void)
> 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;
>
> @@ -2194,7 +1870,7 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
> if (tcg2_efi_app_invoked)
> return EFI_SUCCESS;
>
> - ret = platform_get_tpm2_device(&dev);
> + ret = tcg2_platform_get_tpm2(&dev);
> if (ret != EFI_SUCCESS)
> return EFI_SECURITY_VIOLATION;
>
> @@ -2244,7 +1920,7 @@ efi_status_t efi_tcg2_measure_efi_app_exit(void)
> 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 ret;
>
> @@ -2275,7 +1951,7 @@ efi_tcg2_notify_exit_boot_services(struct efi_event *event, void *context)
> goto out;
> }
>
> - ret = platform_get_tpm2_device(&dev);
> + ret = tcg2_platform_get_tpm2(&dev);
> if (ret != EFI_SUCCESS)
> goto out;
>
> @@ -2307,7 +1983,7 @@ efi_status_t efi_tcg2_notify_exit_boot_services_failed(void)
> if (!is_tcg2_protocol_installed())
> return EFI_SUCCESS;
>
> - ret = platform_get_tpm2_device(&dev);
> + ret = tcg2_platform_get_tpm2(&dev);
> if (ret != EFI_SUCCESS)
> goto out;
>
> @@ -2389,7 +2065,7 @@ efi_status_t efi_tcg2_do_initial_measurement(void)
> 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;
>
> @@ -2415,7 +2091,7 @@ efi_status_t efi_tcg2_register(void)
> struct efi_event *event;
> u32 err;
>
> - ret = platform_get_tpm2_device(&dev);
> + ret = tcg2_platform_get_tpm2(&dev);
> if (ret != EFI_SUCCESS) {
> log_warning("Unable to find TPMv2 device\n");
> return EFI_SUCCESS;
> diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> index 697b982e07..00e1b04d74 100644
> --- a/lib/tpm-v2.c
> +++ b/lib/tpm-v2.c
> @@ -4,13 +4,597 @@
> * Author: Miquel Raynal <miquel.raynal@bootlin.com>
> */
>
> +#include <asm/types.h>
> +#include <asm/io.h>
> #include <common.h>
> #include <dm.h>
> +#include <dm/of_access.h>
> #include <tpm-common.h>
> #include <tpm-v2.h>
> #include <linux/bitops.h>
> +#include <linux/unaligned/be_byteshift.h>
> +#include <linux/unaligned/generic.h>
> +#include <linux/unaligned/le_byteshift.h>
> +#include <u-boot/sha1.h>
> +#include <u-boot/sha256.h>
> +#include <u-boot/sha512.h>
> +#include <version_string.h>
> #include "tpm-utils.h"
>
> +static const enum tpm2_algorithms tcg2algos[] = {
> + TPM2_ALG_SHA1,
> + TPM2_ALG_SHA256,
> + TPM2_ALG_SHA384,
> + TPM2_ALG_SHA512,
> +};
> +
> +static int tcg2_get_active_pcr_banks(struct udevice *dev, u32 *active_pcr_banks)
> +{
> + u32 supported = 0;
> + u32 pcr_banks = 0;
> + u32 active = 0;
> + int rc;
> +
> + rc = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
> + if (rc)
> + return rc;
> +
> + *active_pcr_banks = active;
> +
> + return 0;
> +}
> +
> +u32 tcg2_event_get_size(struct tpml_digest_values *digest_list)
> +{
> + u32 len;
> + size_t i;
> +
> + len = offsetof(struct tcg_pcr_event2, digests);
> + len += offsetof(struct tpml_digest_values, digests);
> + for (i = 0; i < digest_list->count; ++i) {
> + u16 l = tpm2_algorithm_to_len(digest_list->digests[i].hash_alg);
> +
> + if (!l)
> + continue;
> +
> + len += l + offsetof(struct tpmt_ha, digest);
> + }
> + len += sizeof(u32);
> +
> + return len;
> +}
> +
> +int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
> + struct tpml_digest_values *digest_list)
> +{
> + u8 final[sizeof(union tpmu_ha)];
> + sha256_context ctx_256;
> + sha512_context ctx_512;
> + sha1_context ctx;
> + u32 active;
> + size_t i;
> + u32 len;
> + int rc;
> +
> + rc = tcg2_get_active_pcr_banks(dev, &active);
> + if (rc)
> + return rc;
> +
> + digest_list->count = 0;
> + for (i = 0; i < ARRAY_SIZE(tcg2algos); ++i) {
> + u32 mask = tpm2_algorithm_to_mask(tcg2algos[i]);
> +
> + if (!(active & mask))
> + continue;
> +
> + switch (tcg2algos[i]) {
> + case TPM2_ALG_SHA1:
> + sha1_starts(&ctx);
> + sha1_update(&ctx, input, length);
> + sha1_finish(&ctx, final);
> + len = TPM2_SHA1_DIGEST_SIZE;
> + break;
> + case TPM2_ALG_SHA256:
> + sha256_starts(&ctx_256);
> + sha256_update(&ctx_256, input, length);
> + sha256_finish(&ctx_256, final);
> + len = TPM2_SHA256_DIGEST_SIZE;
> + break;
> + case TPM2_ALG_SHA384:
> + sha384_starts(&ctx_512);
> + sha384_update(&ctx_512, input, length);
> + sha384_finish(&ctx_512, final);
> + len = TPM2_SHA384_DIGEST_SIZE;
> + break;
> + case TPM2_ALG_SHA512:
> + sha512_starts(&ctx_512);
> + sha512_update(&ctx_512, input, length);
> + sha512_finish(&ctx_512, final);
> + len = TPM2_SHA512_DIGEST_SIZE;
> + break;
> + default:
> + printf("%s: unsupported algorithm %x\n", __func__,
> + tcg2algos[i]);
> + continue;
> + }
> +
> + digest_list->digests[digest_list->count].hash_alg =
> + tcg2algos[i];
> + memcpy(&digest_list->digests[digest_list->count].digest, final,
> + len);
> + digest_list->count++;
> + }
> +
> + return 0;
> +}
> +
> +void tcg2_log_append(u32 pcr_index, u32 event_type,
> + struct tpml_digest_values *digest_list, u32 size,
> + const u8 *event, u8 *log)
> +{
> + size_t len;
> + size_t pos;
> + u32 i;
> +
> + pos = offsetof(struct tcg_pcr_event2, pcr_index);
> + put_unaligned_le32(pcr_index, log);
> + pos = offsetof(struct tcg_pcr_event2, event_type);
> + put_unaligned_le32(event_type, log + pos);
> + pos = offsetof(struct tcg_pcr_event2, digests) +
> + offsetof(struct tpml_digest_values, count);
> + put_unaligned_le32(digest_list->count, log + pos);
> +
> + pos = offsetof(struct tcg_pcr_event2, digests) +
> + offsetof(struct tpml_digest_values, digests);
> + for (i = 0; i < digest_list->count; ++i) {
> + u16 hash_alg = digest_list->digests[i].hash_alg;
> +
> + len = tpm2_algorithm_to_len(hash_alg);
> + if (!len)
> + continue;
> +
> + pos += offsetof(struct tpmt_ha, hash_alg);
> + put_unaligned_le16(hash_alg, log + pos);
> + pos += offsetof(struct tpmt_ha, digest);
> + memcpy(log + pos, (u8 *)&digest_list->digests[i].digest, len);
> + pos += len;
> + }
> +
> + put_unaligned_le32(size, log + pos);
> + pos += sizeof(u32);
> + memcpy(log + pos, event, size);
> +}
> +
> +static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index,
> + u32 event_type,
> + struct tpml_digest_values *digest_list,
> + u32 size, const u8 *event)
> +{
> + u32 event_size;
> + u8 *log;
> +
> + event_size = size + tcg2_event_get_size(digest_list);
> + if (elog->log_position + event_size > elog->log_size) {
> + printf("%s: log too large: %u + %u > %u\n", __func__,
> + elog->log_position, event_size, elog->log_size);
> + return -ENOBUFS;
> + }
> +
> + log = elog->log + elog->log_position;
> + elog->log_position += event_size;
> +
> + tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
> +
> + return 0;
> +}
> +
> +static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog)
> +{

I think we need to re-use efi_init_event_log here. The reason is that on
Arm devices TF-A is capable of constructing an eventlog and passing it
along in memory. That code takes that into account and tries to reuse the
existing EventLog passed from previous boot stages.

The main difference between the EFI function and this one
is the allocated memory of the EventLog itself. But even in this case, it
would be better to tweak the EFI code and do
create log -> Allocate EFI memory -> copy log and then use that for EFI

> + struct tcg_efi_spec_id_event *ev;
> + struct tcg_pcr_event *log;
> + u32 event_size;
> + u32 count = 0;
> + u32 log_size;
> + u32 active;
> + u32 mask;
> + size_t i;
> + u16 len;
> + int rc;
> +
> + rc = tcg2_get_active_pcr_banks(dev, &active);
> + if (rc)
> + return rc;
> +
> + event_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes);
> + for (i = 0; i < ARRAY_SIZE(tcg2algos); ++i) {
> + mask = tpm2_algorithm_to_mask(tcg2algos[i]);
> +
> + if (!(active & mask))
> + continue;
> +
> + switch (tcg2algos[i]) {
> + case TPM2_ALG_SHA1:
> + case TPM2_ALG_SHA256:
> + case TPM2_ALG_SHA384:
> + case TPM2_ALG_SHA512:
> + count++;
> + break;
> + default:
> + continue;
> + }
> + }
> +
> + event_size += 1 +
> + (sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count);
> + log_size = offsetof(struct tcg_pcr_event, event) + event_size;
> +
> + if (log_size > elog->log_size) {
> + printf("%s: log too large: %u > %u\n", __func__, log_size,
> + elog->log_size);
> + return -ENOBUFS;
> + }
> +
> + log = (struct tcg_pcr_event *)elog->log;
> + put_unaligned_le32(0, &log->pcr_index);
> + put_unaligned_le32(EV_NO_ACTION, &log->event_type);
> + memset(&log->digest, 0, sizeof(log->digest));
> + put_unaligned_le32(event_size, &log->event_size);
> +
> + ev = (struct tcg_efi_spec_id_event *)log->event;
> + strlcpy((char *)ev->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
> + sizeof(ev->signature));
> + put_unaligned_le32(0, &ev->platform_class);
> + ev->spec_version_minor = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
> + ev->spec_version_major = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
> + ev->spec_errata = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
> + ev->uintn_size = sizeof(size_t) / sizeof(u32);
> + put_unaligned_le32(count, &ev->number_of_algorithms);
> +
> + count = 0;
> + for (i = 0; i < ARRAY_SIZE(tcg2algos); ++i) {
> + mask = tpm2_algorithm_to_mask(tcg2algos[i]);
> +
> + if (!(active & mask))
> + continue;
> +
> + len = tpm2_algorithm_to_len(tcg2algos[i]);
> + if (!len)
> + continue;
> +
> + put_unaligned_le16(tcg2algos[i],
> + &ev->digest_sizes[count].algorithm_id);
> + put_unaligned_le16(len, &ev->digest_sizes[count].digest_size);
> + count++;
> + }
> +
> + *((u8 *)ev + (event_size - 1)) = 0;
> + elog->log_position = log_size;
> +
> + return 0;
> +}
> +
> +static void tcg2_log_find_end(struct tcg2_event_log *elog)
> +{
> + const u32 offset = offsetof(struct tcg_pcr_event2, digests) +
> + offsetof(struct tpml_digest_values, digests);
> + u32 event_size;
> + u32 count;
> + u16 algo;
> + u32 pos;
> + u16 len;
> + u8 *log;
> + u32 i;
> +
> + while (elog->log_position + offset < elog->log_size) {
> + log = elog->log + elog->log_position;
> +
> + pos = offsetof(struct tcg_pcr_event2, event_type);
> + if (!get_unaligned_le32(log + pos))
> + return;
> +
> + pos = offsetof(struct tcg_pcr_event2, digests) +
> + offsetof(struct tpml_digest_values, count);
> + count = get_unaligned_le32(log + pos);
> + if (count > ARRAY_SIZE(tcg2algos))
> + return;
> +
> + pos = offsetof(struct tcg_pcr_event2, digests) +
> + offsetof(struct tpml_digest_values, digests);
> + for (i = 0; i < count; ++i) {
> + pos += offsetof(struct tpmt_ha, hash_alg);
> + if (elog->log_position + pos + sizeof(u16) >=
> + elog->log_size)
> + return;
> +
> + algo = get_unaligned_le16(log + pos);
> + pos += offsetof(struct tpmt_ha, digest);
> + switch (algo) {
> + case TPM2_ALG_SHA1:
> + case TPM2_ALG_SHA256:
> + case TPM2_ALG_SHA384:
> + case TPM2_ALG_SHA512:
> + len = tpm2_algorithm_to_len(algo);
> + break;
> + default:
> + return;
> + }
> +
> + pos += len;
> + }
> +
> + if (elog->log_position + pos + sizeof(u32) >= elog->log_size)
> + return;
> +
> + event_size = get_unaligned_le32(log + pos);
> + pos += event_size + sizeof(u32);
> + if (elog->log_position + pos >= elog->log_size)
> + return;
> +
> + elog->log_position += pos;
> + }
> +}
> +
> +static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
> +{
> + struct tcg_efi_spec_id_event *event;
> + struct tcg_pcr_event *log;
> + u32 calc_size;
> + u32 active;
> + u32 count;
> + u32 evsz;
> + u32 mask;
> + u16 algo;
> + u16 len;
> + int rc;
> + u32 i;
> +
> + if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
> + return 0;
> +
> + log = (struct tcg_pcr_event *)elog->log;
> + if (get_unaligned_le32(&log->pcr_index) != 0 ||
> + get_unaligned_le32(&log->event_type) != EV_NO_ACTION)
> + return 0;
> +
> + for (i = 0; i < sizeof(log->digest); i++) {
> + if (log->digest[i])
> + return 0;
> + }
> +
> + evsz = get_unaligned_le32(&log->event_size);
> + if (evsz < offsetof(struct tcg_efi_spec_id_event, digest_sizes) ||
> + evsz + offsetof(struct tcg_pcr_event, event) > elog->log_size)
> + return 0;
> +
> + event = (struct tcg_efi_spec_id_event *)log->event;
> + if (memcmp(event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
> + sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03)))
> + return 0;
> +
> + if (event->spec_version_minor != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
> + event->spec_version_major != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
> + return 0;
> +
> + count = get_unaligned_le32(&event->number_of_algorithms);
> + if (count > ARRAY_SIZE(tcg2algos))
> + return 0;
> +
> + calc_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
> + (sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count) +
> + 1;
> + if (evsz != calc_size)
> + return 0;
> +
> + rc = tcg2_get_active_pcr_banks(dev, &active);
> + if (rc)
> + return rc;
> +
> + for (i = 0; i < count; ++i) {
> + algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id);
> + mask = tpm2_algorithm_to_mask(algo);
> +
> + if (!(active & mask))
> + return 0;
> +
> + switch (algo) {
> + case TPM2_ALG_SHA1:
> + case TPM2_ALG_SHA256:
> + case TPM2_ALG_SHA384:
> + case TPM2_ALG_SHA512:
> + len = get_unaligned_le16(&event->digest_sizes[i].digest_size);
> + if (tpm2_algorithm_to_len(algo) != len)
> + return 0;
> + break;
> + default:
> + return 0;
> + }
> + }
> +
> + elog->log_position = offsetof(struct tcg_pcr_event, event) + evsz;
> +
> + tcg2_log_find_end(elog);
> +
> + return 1;
> +}
> +
> +int tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
> + struct tpml_digest_values *digest_list)
> +{
> + u32 rc;
> + size_t i;
> +
> + for (i = 0; i < digest_list->count; i++) {
> + u32 alg = digest_list->digests[i].hash_alg;
> +
> + rc = tpm2_pcr_extend(dev, pcr_index, alg,
> + (u8 *)&digest_list->digests[i].digest,
> + tpm2_algorithm_to_len(alg));
> + if (rc) {
> + printf("%s: error pcr:%u alg:%08x\n", __func__,
> + pcr_index, alg);
> + return rc;
> + }
> + }
> +
> + return 0;
> +}
> +
> +int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
> + u32 pcr_index, u32 size, const u8 *data, u32 event_type,
> + u32 event_size, const u8 *event)
> +{
> + struct tpml_digest_values digest_list;
> + int rc;
> +
> + rc = tcg2_create_digest(dev, data, size, &digest_list);
> + if (rc)
> + return rc;
> +
> + rc = tcg2_pcr_extend(dev, pcr_index, &digest_list);
> + if (rc)
> + return rc;
> +
> + return tcg2_log_append_check(elog, pcr_index, event_type, &digest_list,
> + event_size, event);
> +}
> +
> +int tcg2_measure_event(struct udevice *dev, struct tcg2_event_log *elog,
> + u32 pcr_index, u32 event_type, u32 size,
> + const u8 *event)
> +{
> + struct tpml_digest_values digest_list;
> + int rc;
> +
> + rc = tcg2_create_digest(dev, event, size, &digest_list);
> + if (rc)
> + return rc;
> +
> + rc = tcg2_pcr_extend(dev, pcr_index, &digest_list);
> + if (rc)
> + return rc;
> +
> + return tcg2_log_append_check(elog, pcr_index, event_type, &digest_list,
> + size, event);
> +}

There's a static efi_status_t tcg2_measure_event(...) left in efi_tcg.c
which breaks compilation. WE should just use the one you added in tpm-v2.c

> +
> +int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog)
> +{
> + int rc;
> +
> + rc = tcg2_platform_get_tpm2(dev);
> + if (rc)
> + return rc;
> +
> + rc = tpm_init(*dev);
> + if (rc)
> + return rc;
> +
> + rc = tpm2_startup(*dev, TPM2_SU_CLEAR);
> + if (rc) {
> + tcg2_platform_startup_error(*dev, rc);
> + return rc;
> + }
> +
> + rc = tpm2_self_test(*dev, TPMI_YES);
> + if (rc)
> + printf("%s: self test error, continuing.\n", __func__);
> +
> + rc = tcg2_platform_get_log(*dev, (void **)&elog->log, &elog->log_size);
> + if (rc) {
> + tcg2_measurement_term(*dev, elog, true);
> + return rc;
> + }
> +
> + elog->log_position = 0;
> + rc = tcg2_log_parse(*dev, elog);
> + if (rc < 0) {
> + tcg2_measurement_term(*dev, elog, true);
> + return rc;
> + }
> +
> + if (!rc) {
> + rc = tcg2_log_init(*dev, elog);
> + if (rc) {
> + tcg2_measurement_term(*dev, elog, true);
> + return rc;
> + }
> + }
> +
> + rc = tcg2_measure_event(*dev, elog, 0, EV_S_CRTM_VERSION,
> + strlen(version_string) + 1,
> + (u8 *)version_string);
> + if (rc) {
> + tcg2_measurement_term(*dev, elog, true);
> + return rc;
> + }
> +
> + return 0;
> +}
> +
> +void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
> + bool error)
> +{
> + u32 event = error ? 0x1 : 0xffffffff;
> + int i;
> +
> + for (i = 0; i < 8; ++i)
> + tcg2_measure_event(dev, elog, i, EV_SEPARATOR, sizeof(event),
> + (const u8 *)&event);
> +
> + if (elog->log)
> + unmap_physmem(elog->log, MAP_NOCACHE);
> +}
> +
> +__weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
> +{
> + const __be32 *addr_prop;
> + const __be32 *size_prop;
> + int asize;
> + int ssize;
> +
> + *addr = NULL;
> + *size = 0;
> +
> + addr_prop = dev_read_prop(dev, "linux,sml-base", &asize);
> + size_prop = dev_read_prop(dev, "linux,sml-size", &ssize);
> + if (addr_prop && size_prop) {
> + u64 a = of_read_number(addr_prop, asize / sizeof(__be32));
> + u64 s = of_read_number(size_prop, ssize / sizeof(__be32));
> +
> + *addr = map_physmem(a, s, MAP_NOCACHE);
> + *size = (u32)s;
> + } else {
> + struct ofnode_phandle_args args;
> + phys_addr_t a;
> + phys_size_t s;
> +
> + if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
> + 0, &args))
> + return -ENODEV;
> +
> + a = ofnode_get_addr_size(args.node, "reg", &s);
> + if (a == FDT_ADDR_T_NONE)
> + return -ENOMEM;
> +
> + *addr = map_physmem(a, s, MAP_NOCACHE);
> + *size = (u32)s;
> + }
> +
> + return 0;
> +}
> +
> +__weak int tcg2_platform_get_tpm2(struct udevice **dev)
> +{
> + for_each_tpm_device(*dev) {
> + if (tpm_get_version(*dev) == TPM_V2)
> + return 0;
> + }
> +
> + return -ENODEV;
> +}
> +
> +__weak void tcg2_platform_startup_error(struct udevice *dev, int rc) {}
> +
> u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
> {
> const u8 command_v2[12] = {
> @@ -342,6 +926,130 @@ u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
> return 0;
> }
>
> +static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
> +{
> + u8 response[(sizeof(struct tpms_capability_data) -
> + offsetof(struct tpms_capability_data, data))];
> + u32 properties_offset =
> + offsetof(struct tpml_tagged_tpm_property, tpm_property) +
> + offsetof(struct tpms_tagged_property, value);
> + 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 ret;
> +
> + *num_pcr = get_unaligned_be32(response + properties_offset);
> + if (*num_pcr > TPM2_MAX_PCRS) {
> + printf("%s: too many pcrs: %u\n", __func__, *num_pcr);
> + return -E2BIG;
> + }
> +
> + return 0;
> +}
> +
> +static bool tpm2_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;
> +}
> +
> +int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
> + u32 *pcr_banks)
> +{
> + u8 response[(sizeof(struct tpms_capability_data) -
> + offsetof(struct tpms_capability_data, data))];
> + struct tpml_pcr_selection pcrs;
> + u32 num_pcr;
> + size_t i;
> + u32 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)
> + return ret;
> +
> + 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 > ARRAY_SIZE(tcg2algos) || pcrs.count < 1) {
> + printf("%s: too many pcrs: %u\n", __func__, pcrs.count);
> + return -EMSGSIZE;
> + }
> +
> + ret = tpm2_get_num_pcr(dev, &num_pcr);
> + if (ret)
> + return ret;
> +
> + 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) {
> + printf("%s: pcrs selection too large: %u\n", __func__,
> + pcrs.selection[i].size_of_select);
> + return -ENOBUFS;
> + }
> + /* 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 = tpm2_algorithm_to_mask(pcrs.selection[i].hash);
> +
> + if (hash_mask) {
> + *supported_pcr |= hash_mask;
> + if (tpm2_is_active_pcr(&pcrs.selection[i]))
> + *active_pcr |= hash_mask;
> + } else {
> + printf("%s: unknown algorithm %x\n", __func__,
> + pcrs.selection[i].hash);
> + }
> + }
> +
> + *pcr_banks = pcrs.count;
> +
> + return 0;
> +}
> +
> u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
> {
> u8 command_v2[COMMAND_BUFFER_SIZE] = {
> --
> 2.31.1
>

Regards
/Ilias