[PATCH 1/6] tpm: implement TPM2 function to get update counter
Jarkko Sakkinen
jarkko at kernel.org
Tue Aug 1 12:02:45 PDT 2023
The short summary is cryptic to say the least.
"update counter" does not map it to have anything to do with PCRs.
Why not "tpm: Read pcrUpdateCounter field from TPM2_PCR_Read"?
On Tue Aug 1, 2023 at 9:19 PM EEST, Tushar Sugandhi wrote:
> The TPM2_PCR_Read command returns TPM2_PCR_Read Response struct[1]. It
> contains pcrUpdateCounter member which contains the current value of TPM
> PCR update counter. The update counter provides the number of times the
> PCRs are updated, which is essential for tracking changes and verifying
> system integrity. Thus, subsystems (like IMA) should measure
> pcrUpdateCounter value. Although tpm2_pcr_read_out struct is returned
> by tpm2_pcr_read(), it is not used by it's caller function tpm_pcr_read().
> Further, TPM2_PCR_Read Response struct and pcrUpdateCounter is not
> available in tpm1_pcr_read().
>
> PcrUpdateCounter is only needed in a specific case (IMA for measurements).
> Changing tpm_pcr_read() and tpm2_pcr_read() function signature to return
> tpm2_pcr_read_out struct would be a more disruptive change, since these
> functions are used elsewhere too. Creating separate functions to get
> pcrUpdateCounter when needed would be a cleaner approach.
>
> Add a function, 'tpm2_pcr_get_update_counter()' to retrieve
> the update counter for a given PCR index and algorithm ID on a TPM2 chip.
>
> This function complements existing TPM functionalities such as reading
> and extending PCRs, and enhances the ability to monitor PCR status
> in the Linux Kernel.
>
> [1] https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf
> Section 22.4.2, Page 206.
>
> Signed-off-by: Tushar Sugandhi <tusharsu at linux.microsoft.com>
> ---
> drivers/char/tpm/tpm.h | 3 +++
> drivers/char/tpm/tpm2-cmd.c | 48 +++++++++++++++++++++++++++++++++++++
> 2 files changed, 51 insertions(+)
>
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 830014a26609..60489f21d3bd 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -288,6 +288,9 @@ static inline void tpm_add_ppi(struct tpm_chip *chip)
> int tpm2_get_timeouts(struct tpm_chip *chip);
> int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
> struct tpm_digest *digest, u16 *digest_size_ptr);
> +int tpm2_pcr_get_update_counter(struct tpm_chip *chip,
> + u32 pcr_idx, u16 alg_id,
> + u32 *update_counter);
tpm_pcr_read_update_cnt()
> int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
> struct tpm_digest *digests);
> int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max);
> diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
> index 93545be190a5..55f4e102289a 100644
> --- a/drivers/char/tpm/tpm2-cmd.c
> +++ b/drivers/char/tpm/tpm2-cmd.c
> @@ -216,6 +216,54 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
> return rc;
> }
>
> +/**
> + * tpm2_pcr_get_update_counter() - gets an update counter value for a PCR bank
> + * @chip: TPM chip to use
> + * @pcr_idx: PCR index used to retrieve the update counter
> + * @alg_id: alg id used to retrieve the update counter
> + * @update_counter: output update counter value
> + *
> + * Return: Same as with tpm_transmit_cmd.
> + */
> +int tpm2_pcr_get_update_counter(struct tpm_chip *chip,
> + u32 pcr_idx, u16 alg_id, u32 *update_counter)
> +{
> + int rc;
> + struct tpm_buf buf;
> + struct tpm2_pcr_read_out *read_out;
> + u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0};
> +
> + if (pcr_idx >= TPM2_PLATFORM_PCR)
> + return -EINVAL;
> +
> + if (!update_counter)
> + return -EINVAL;
> +
> + rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ);
> + if (rc)
> + return rc;
> +
> + pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
> +
> + tpm_buf_append_u32(&buf, 1);
> + tpm_buf_append_u16(&buf, alg_id);
> + tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN);
> + tpm_buf_append(&buf, (const unsigned char *)pcr_select,
> + sizeof(pcr_select));
> +
> + rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to read a pcr value");
> + if (rc)
> + goto out;
> +
> + read_out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE];
> +
> + *update_counter = be32_to_cpu(read_out->update_cnt);
> +
> +out:
> + tpm_buf_destroy(&buf);
> + return rc;
> +}
> +
> struct tpm2_null_auth_area {
> __be32 handle;
> __be16 nonce_size;
> --
> 2.25.1
BR, Jarkko
More information about the kexec
mailing list