From 6e9722e9a7bfe1bbad649937c811076acf86e1fd Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Sun, 30 Nov 2025 21:07:12 +0200 Subject: tpm2-sessions: Fix out of range indexing in name_size 'name_size' does not have any range checks, and it just directly indexes with TPM_ALG_ID, which could lead into memory corruption at worst. Address the issue by only processing known values and returning -EINVAL for unrecognized values. Make also 'tpm_buf_append_name' and 'tpm_buf_fill_hmac_session' fallible so that errors are detected before causing any spurious TPM traffic. End also the authorization session on failure in both of the functions, as the session state would be then by definition corrupted. Cc: stable@vger.kernel.org # v6.10+ Fixes: 1085b8276bb4 ("tpm: Add the rest of the session HMAC API") Reviewed-by: Jonathan McDowell Signed-off-by: Jarkko Sakkinen --- include/linux/tpm.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 3d8f7d1ce2b8..aa816b144ab3 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -529,8 +529,8 @@ static inline struct tpm2_auth *tpm2_chip_auth(struct tpm_chip *chip) #endif } -void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf, - u32 handle, u8 *name); +int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf, + u32 handle, u8 *name); void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf, u8 attributes, u8 *passphrase, int passphraselen); @@ -563,7 +563,7 @@ static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip, #ifdef CONFIG_TCG_TPM2_HMAC int tpm2_start_auth_session(struct tpm_chip *chip); -void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf); +int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf); int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf, int rc); void tpm2_end_auth_session(struct tpm_chip *chip); @@ -577,10 +577,13 @@ static inline int tpm2_start_auth_session(struct tpm_chip *chip) static inline void tpm2_end_auth_session(struct tpm_chip *chip) { } -static inline void tpm_buf_fill_hmac_session(struct tpm_chip *chip, - struct tpm_buf *buf) + +static inline int tpm_buf_fill_hmac_session(struct tpm_chip *chip, + struct tpm_buf *buf) { + return 0; } + static inline int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf, int rc) -- cgit v1.2.3 From bc677a9216e1396322e42692e9c01cce04a7afc0 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Tue, 30 Sep 2025 16:07:35 +0300 Subject: tpm2-sessions: Remove 'attributes' parameter from tpm_buf_append_auth Remove 'attributes' parameter from 'tpm_buf_append_auth', as it is not used by the function. Fixes: 27184f8905ba ("tpm: Opt-in in disable PCR integrity protection") Signed-off-by: Jarkko Sakkinen Reviewed-by: Jonathan McDowell --- drivers/char/tpm/tpm2-cmd.c | 2 +- drivers/char/tpm/tpm2-sessions.c | 5 ++--- include/linux/tpm.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 34e3599f094f..ce0a1c6b0596 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -210,7 +210,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0); } else { tpm_buf_append_handle(chip, &buf, pcr_idx); - tpm_buf_append_auth(chip, &buf, 0, NULL, 0); + tpm_buf_append_auth(chip, &buf, NULL, 0); } tpm_buf_append_u32(&buf, chip->nr_allocated_banks); diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index 3f389e2f6f58..4149379665c4 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -311,7 +311,7 @@ err: EXPORT_SYMBOL_GPL(tpm_buf_append_name); void tpm_buf_append_auth(struct tpm_chip *chip, struct tpm_buf *buf, - u8 attributes, u8 *passphrase, int passphrase_len) + u8 *passphrase, int passphrase_len) { /* offset tells us where the sessions area begins */ int offset = buf->handles * 4 + TPM_HEADER_SIZE; @@ -372,8 +372,7 @@ void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf, #endif if (!tpm2_chip_auth(chip)) { - tpm_buf_append_auth(chip, buf, attributes, passphrase, - passphrase_len); + tpm_buf_append_auth(chip, buf, passphrase, passphrase_len); return; } diff --git a/include/linux/tpm.h b/include/linux/tpm.h index aa816b144ab3..afa51723296a 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -535,7 +535,7 @@ void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf, u8 attributes, u8 *passphrase, int passphraselen); void tpm_buf_append_auth(struct tpm_chip *chip, struct tpm_buf *buf, - u8 attributes, u8 *passphrase, int passphraselen); + u8 *passphrase, int passphraselen); static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip, struct tpm_buf *buf, u8 attributes, -- cgit v1.2.3 From b7960b90486139022d2d39caad90db252c469bab Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Tue, 30 Sep 2025 23:44:19 +0300 Subject: tpm2-sessions: Open code tpm_buf_append_hmac_session() Open code 'tpm_buf_append_hmac_session_opt' to the call site, as it only masks a call sequence and does otherwise nothing particularly useful. Signed-off-by: Jarkko Sakkinen Reviewed-by: Jonathan McDowell --- drivers/char/tpm/tpm2-cmd.c | 14 +++++++++++--- include/linux/tpm.h | 23 ----------------------- security/keys/trusted-keys/trusted_tpm2.c | 12 ++++++++++-- 3 files changed, 21 insertions(+), 28 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index ce0a1c6b0596..3a77be7ebf4a 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -282,9 +282,17 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) do { tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM); - tpm_buf_append_hmac_session_opt(chip, &buf, TPM2_SA_ENCRYPT - | TPM2_SA_CONTINUE_SESSION, - NULL, 0); + if (tpm2_chip_auth(chip)) { + tpm_buf_append_hmac_session(chip, &buf, + TPM2_SA_ENCRYPT | + TPM2_SA_CONTINUE_SESSION, + NULL, 0); + } else { + offset = buf.handles * 4 + TPM_HEADER_SIZE; + head = (struct tpm_header *)buf.data; + if (tpm_buf_length(&buf) == offset) + head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); + } tpm_buf_append_u16(&buf, num_bytes); err = tpm_buf_fill_hmac_session(chip, &buf); if (err) { diff --git a/include/linux/tpm.h b/include/linux/tpm.h index afa51723296a..202da079d500 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -536,29 +536,6 @@ void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf, int passphraselen); void tpm_buf_append_auth(struct tpm_chip *chip, struct tpm_buf *buf, u8 *passphrase, int passphraselen); -static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip, - struct tpm_buf *buf, - u8 attributes, - u8 *passphrase, - int passphraselen) -{ - struct tpm_header *head; - int offset; - - if (tpm2_chip_auth(chip)) { - tpm_buf_append_hmac_session(chip, buf, attributes, passphrase, passphraselen); - } else { - offset = buf->handles * 4 + TPM_HEADER_SIZE; - head = (struct tpm_header *)buf->data; - - /* - * If the only sessions are optional, the command tag must change to - * TPM2_ST_NO_SESSIONS. - */ - if (tpm_buf_length(buf) == offset) - head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); - } -} #ifdef CONFIG_TCG_TPM2_HMAC diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c index 5b205279584b..a7ea4a1c3bed 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -481,8 +481,10 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, struct trusted_key_options *options, u32 blob_handle) { + struct tpm_header *head; struct tpm_buf buf; u16 data_len; + int offset; u8 *data; int rc; @@ -519,8 +521,14 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, tpm2_buf_append_auth(&buf, options->policyhandle, NULL /* nonce */, 0, 0, options->blobauth, options->blobauth_len); - tpm_buf_append_hmac_session_opt(chip, &buf, TPM2_SA_ENCRYPT, - NULL, 0); + if (tpm2_chip_auth(chip)) { + tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, NULL, 0); + } else { + offset = buf.handles * 4 + TPM_HEADER_SIZE; + head = (struct tpm_header *)buf.data; + if (tpm_buf_length(&buf) == offset) + head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); + } } rc = tpm_buf_fill_hmac_session(chip, &buf); -- cgit v1.2.3