Address !chip->auth
Subsystems (5)
Jarkko Sakkinen
maintainerv3 cover Address !chip->auth
Unless tpm2_sessions_init() is called, then chip->auth ends up being a null pointer, which is ignored by authenticated sessions code. These patches aim to fully address the bug, and hopefully still make into 6.10-rc7.
Tested on x86-64 with:
- TCG_TPM2_HMAC disabled.
- TCG_TPM2_HMAC enabled.
- TCG_TPM2_HMAC enabled, and "/* rc = tpm2_sessions_init(chip); */".
For drivers that do not initialize with tpm2_chip_bootstrap(), the lack of auth sessions is reported once per power cycle by:
"tpm tpm0: auth session is not active"
This is expected output for the following drivers:
* tpm_ftpm_tee.c
* tpm_i2c_nuvoton.c
* tpm_ibmvtpm.c
* tpm_tis_i2c_cr50.c
* tpm_vtpm_proxy.c
They need to later on enable auth sessions, if they eager to. This patch set only fixes any collateral damage of not doing so.
v3
* Address:
https://lore.kernel.org/linux-integrity/922603265d61011dbb23f18a04525ae973b83ffd.camel@HansenPartnership.com/
* Git: https://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd.git/log/?h=auth-null-3
* Did a full QA run given the changes in config flag handling.
v2:
* Rebase to commit 8a9c6c40432e ("Merge tag 'io_uring-6.10-20240703' of git://git.kernel.dk/linux").
* Couple of cosmetic fixes.
Jarkko Sakkinen (3):
tpm: Address !chip->auth in tpm2_*_auth_session()
tpm: Address !chip->auth in tpm_buf_append_name()
tpm: Address !chip->auth in tpm_buf_append_hmac_session*()
drivers/char/tpm/Makefile | 2 +- drivers/char/tpm/tpm2-sessions.c | 415 ++++++++++++++++++------------- include/linux/tpm.h | 74 ++---- 3 files changed, 257 insertions(+), 234 deletions(-)
Signature · 1 line
2.45.2
Jarkko Sakkinen
maintainerPATCH v3 1/3 tpm: Address !chip->auth in tpm2_*_auth_session()
Unless tpm_chip_bootstrap() was called by the driver, !chip->auth can cause a null derefence in tpm2_*_auth_session(). Thus, address !chip->auth in tpm2_*_auth_session().
---
v2:
* Use dev_warn_once() instead of pr_warn_once().
--- drivers/char/tpm/tpm2-sessions.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
drivers/char/tpm/tpm2-sessions.c +12 -2
@@ -824,8 +824,13 @@ EXPORT_SYMBOL(tpm_buf_check_hmac_response);*/ void tpm2_end_auth_session (struct tpm_chip *chip) { -tpm2_flush_context (chip, chip->auth->handle); -memzero_explicit (chip->auth,sizeof (*chip->auth)); +struct tpm2_auth *auth = chip->auth; + +if (!auth) +return ; + +tpm2_flush_context (chip, auth->handle); +memzero_explicit (auth,sizeof (*auth)); }EXPORT_SYMBOL (tpm2_end_auth_session);
@@ -907,6 +912,11 @@ int tpm2_start_auth_session(struct tpm_chip *chip)int rc;u32 null_key; +if (!auth) { +dev_warn_once (&chip->dev,"auth session is not active\n" ); +return 0 ; + } + rc =tpm2_load_null (chip, &null_key);if (rc) goto out;
Signature · 1 line
2.45.2
Jarkko Sakkinen
maintainerPATCH v3 2/3 tpm: Address !chip->auth in tpm_buf_append_name()
In reply to Jarkko SakkinenUnless tpm_chip_bootstrap() was called by the driver, !chip->auth can cause a null derefence in tpm_buf_append_name(). Thus, address !chip->auth in tpm_buf_append_name() and remove the fallback implementation for !TCG_TPM2_HMAC.
---
v3:
* Address:
https://lore.kernel.org/linux-integrity/922603265d61011dbb23f18a04525ae973b83ffd.camel@HansenPartnership.com/
v2:
* N/A
--- drivers/char/tpm/Makefile | 2 +- drivers/char/tpm/tpm2-sessions.c | 217 +++++++++++++++++-------------- include/linux/tpm.h | 14 +- 3 files changed, 121 insertions(+), 112 deletions(-)
drivers/char/tpm/Makefile +1 -1
@@ -16,8 +16,8 @@ tpm-y += eventlog/common.o tpm-y += eventlog/tpm1.o tpm-y += eventlog/tpm2.o tpm-y += tpm-buf.o +tpm-y += tpm2-sessions.o -tpm-$(CONFIG_TCG_TPM2_HMAC) += tpm2-sessions.o tpm-$(CONFIG_ACPI) += tpm_ppi.o eventlog/acpi.o tpm-$(CONFIG_EFI) += eventlog/efi.o tpm-$(CONFIG_OF) += eventlog/of.o
drivers/char/tpm/tpm2-sessions.c +116 -101
244 lines not on this page · raw message
include/linux/tpm.h +4 -10
@@ -490,11 +490,13 @@ static inline void tpm_buf_append_empty_auth(struct tpm_buf *buf, u32 handle) { }#endif -#ifdef CONFIG_TCG_TPM2_HMAC -int tpm2_start_auth_session (struct tpm_chip *chip);void tpm_buf_append_name (struct tpm_chip *chip,struct tpm_buf *buf,u32 handle,u8 *name); + +#ifdef CONFIG_TCG_TPM2_HMAC + +int tpm2_start_auth_session (struct tpm_chip *chip);void tpm_buf_append_hmac_session (struct tpm_chip *chip,struct tpm_buf *buf,u8 attributes,u8 *passphrase,int passphraselen);
@@ -521,14 +523,6 @@ 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_append_name (struct tpm_chip *chip, -struct tpm_buf *buf, -u32 handle,u8 *name) -{ -tpm_buf_append_u32 (buf, handle); -/* count the number of handles in the upper bits of flags */ - buf->handles++; -} static inline void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf, u8 attributes, u8 *passphrase,
Signature · 1 line
2.45.2
Jarkko Sakkinen
maintainerPATCH v3 3/3 tpm: Address !chip->auth in tpm_buf_append_hmac_session*()
In reply to Jarkko SakkinenUnless tpm_chip_bootstrap() was called by the driver, !chip->auth can cause a null derefence in tpm_buf_hmac_session*(). Thus, address !chip->auth in tpm_buf_hmac_session*() and remove the fallback implementation for !TCG_TPM2_HMAC.
---
v3:
* Address:
https://lore.kernel.org/linux-integrity/922603265d61011dbb23f18a04525ae973b83ffd.camel@HansenPartnership.com/
v2:
* Use auth in place of chip->auth.
--- drivers/char/tpm/tpm2-sessions.c | 184 ++++++++++++++++++------------- include/linux/tpm.h | 68 ++++-------- 2 files changed, 128 insertions(+), 124 deletions(-)
drivers/char/tpm/tpm2-sessions.c +108 -76
@@ -270,6 +270,108 @@ void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf, }EXPORT_SYMBOL_GPL (tpm_buf_append_name); +/** +* tpm_buf_append_hmac_session() - Append a TPM session element +* @chip: the TPM chip structure +* @buf: The buffer to be appended +* @attributes: The session attributes +* @passphrase: The session authority (NULL if none) +* @passphrase_len: The length of the session authority (0 if none) +* +* This fills in a session structure in the TPM command buffer, except +* for the HMAC which cannot be computed until the command buffer is +* complete. The type of session is controlled by the @attributes, +* the main ones of which are TPM2_SA_CONTINUE_SESSION which means the +* session won't terminate after tpm_buf_check_hmac_response(), +* TPM2_SA_DECRYPT which means this buffers first parameter should be +* encrypted with a session key and TPM2_SA_ENCRYPT, which means the +* response buffer's first parameter needs to be decrypted (confusing, +* but the defines are written from the point of view of the TPM). +* +* Any session appended by this command must be finalized by calling +* tpm_buf_fill_hmac_session() otherwise the HMAC will be incorrect +* and the TPM will reject the command. +* +* As with most tpm_buf operations, success is assumed because failure +* will be caused by an incorrect programming model and indicated by a +* kernel message. +*/ +void tpm_buf_append_hmac_session (struct tpm_chip *chip,struct tpm_buf *buf, +u8 attributes,u8 *passphrase, +int passphrase_len) +{ +u8 __maybe_unused nonce[SHA256_DIGEST_SIZE ]; +struct tpm2_auth __maybe_unused *auth; +u32 __maybe_unused len; + +if (!__and (IS_ENABLED (CONFIG_TCG_TPM2_HMAC ), chip->auth)) { +/* offset tells us where the sessions area begins */ +int offset = buf->handles *4 +TPM_HEADER_SIZE ; +u32 len =9 + passphrase_len; + +if (tpm_buf_length (buf) != offset) { +/* not the first session so update the existing length */ + len +=get_unaligned_be32 (&buf->data[offset]); +put_unaligned_be32 (len, &buf->data[offset]); + }else { +tpm_buf_append_u32 (buf, len); + } +/* auth handle */ +tpm_buf_append_u32 (buf,TPM2_RS_PW ); +/* nonce */ +tpm_buf_append_u16 (buf,0 ); +/* attributes */ +tpm_buf_append_u8 (buf,0 ); +/* passphrase */ +tpm_buf_append_u16 (buf, passphrase_len); +tpm_buf_append (buf, passphrase, passphrase_len); +return ; + } + +#ifdef CONFIG_TCG_TPM2_HMAC +/* +* The Architecture Guide requires us to strip trailing zeros +* before computing the HMAC +*/ +while (passphrase && passphrase_len >0 && passphrase[passphrase_len -1 ] =='\0' ) + passphrase_len--; + + auth = chip->auth; + auth->attrs = attributes; + auth->passphrase_len = passphrase_len; +if (passphrase_len) +memcpy (auth->passphrase, passphrase, passphrase_len); + +if (auth->session !=tpm_buf_length (buf)) { +/* we're not the first session */ + len =get_unaligned_be32 (&buf->data[auth->session]); +if (4 + len + auth->session !=tpm_buf_length (buf)) { +WARN (1 ,"session length mismatch, cannot append" ); +return ; + } + +/* add our new session */ + len +=9 +2 *SHA256_DIGEST_SIZE ; +put_unaligned_be32 (len, &buf->data[auth->session]); + }else { +tpm_buf_append_u32 (buf,9 +2 *SHA256_DIGEST_SIZE ); + } + +/* random number for our nonce */ +get_random_bytes (nonce,sizeof (nonce)); +memcpy (auth->our_nonce, nonce,sizeof (nonce)); +tpm_buf_append_u32 (buf, auth->handle); +/* our new nonce */ +tpm_buf_append_u16 (buf,SHA256_DIGEST_SIZE ); +tpm_buf_append (buf, nonce,SHA256_DIGEST_SIZE ); +tpm_buf_append_u8 (buf, auth->attrs); +/* and put a placeholder for the hmac */ +tpm_buf_append_u16 (buf,SHA256_DIGEST_SIZE ); +tpm_buf_append (buf, nonce,SHA256_DIGEST_SIZE ); +#endif /* CONFIG_TCG_TPM2_HMAC */ +} +EXPORT_SYMBOL_GPL (tpm_buf_append_hmac_session); +#ifdef CONFIG_TCG_TPM2_HMAC static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy,
@@ -455,82 +557,6 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip)crypto_free_kpp (kpp); } -/** -* tpm_buf_append_hmac_session() - Append a TPM session element -* @chip: the TPM chip structure -* @buf: The buffer to be appended -* @attributes: The session attributes -* @passphrase: The session authority (NULL if none) -* @passphrase_len: The length of the session authority (0 if none) -* -* This fills in a session structure in the TPM command buffer, except -* for the HMAC which cannot be computed until the command buffer is -* complete. The type of session is controlled by the @attributes, -* the main ones of which are TPM2_SA_CONTINUE_SESSION which means the -* session won't terminate after tpm_buf_check_hmac_response(), -* TPM2_SA_DECRYPT which means this buffers first parameter should be -* encrypted with a session key and TPM2_SA_ENCRYPT, which means the -* response buffer's first parameter needs to be decrypted (confusing, -* but the defines are written from the point of view of the TPM). -* -* Any session appended by this command must be finalized by calling -* tpm_buf_fill_hmac_session() otherwise the HMAC will be incorrect -* and the TPM will reject the command. -* -* As with most tpm_buf operations, success is assumed because failure -* will be caused by an incorrect programming model and indicated by a -* kernel message. -*/ -void tpm_buf_append_hmac_session (struct tpm_chip *chip,struct tpm_buf *buf, -u8 attributes,u8 *passphrase, -int passphrase_len) -{ -u8 nonce[SHA256_DIGEST_SIZE ]; -u32 len; -struct tpm2_auth *auth = chip->auth; - -/* -* The Architecture Guide requires us to strip trailing zeros -* before computing the HMAC -*/ -while (passphrase && passphrase_len >0 - && passphrase[passphrase_len -1 ] =='\0' ) - passphrase_len--; - - auth->attrs = attributes; - auth->passphrase_len = passphrase_len; -if (passphrase_len) -memcpy (auth->passphrase, passphrase, passphrase_len); - -if (auth->session !=tpm_buf_length (buf)) { -/* we're not the first session */ - len =get_unaligned_be32 (&buf->data[auth->session]); -if (4 + len + auth->session !=tpm_buf_length (buf)) { -WARN (1 ,"session length mismatch, cannot append" ); -return ; - } - -/* add our new session */ - len +=9 +2 *SHA256_DIGEST_SIZE ; -put_unaligned_be32 (len, &buf->data[auth->session]); - }else { -tpm_buf_append_u32 (buf,9 +2 *SHA256_DIGEST_SIZE ); - } - -/* random number for our nonce */ -get_random_bytes (nonce,sizeof (nonce)); -memcpy (auth->our_nonce, nonce,sizeof (nonce)); -tpm_buf_append_u32 (buf, auth->handle); -/* our new nonce */ -tpm_buf_append_u16 (buf,SHA256_DIGEST_SIZE ); -tpm_buf_append (buf, nonce,SHA256_DIGEST_SIZE ); -tpm_buf_append_u8 (buf, auth->attrs); -/* and put a placeholder for the hmac */ -tpm_buf_append_u16 (buf,SHA256_DIGEST_SIZE ); -tpm_buf_append (buf, nonce,SHA256_DIGEST_SIZE ); -} -EXPORT_SYMBOL (tpm_buf_append_hmac_session); -/** * tpm_buf_fill_hmac_session() - finalize the session HMAC * @chip: the TPM chip structure
@@ -561,6 +587,9 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)u8 cphash[SHA256_DIGEST_SIZE ];struct sha256_state sctx; +if (!auth) +return ; +/* save the command code in BE format */ auth->ordinal = head->ordinal;
@@ -719,6 +748,9 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,u32 cc =be32_to_cpu (auth->ordinal);int parm_len, len, i, handles; +if (!auth) +return rc; +if (auth->session >=TPM_HEADER_SIZE ) {WARN (1 ,"tpm session not filled correctly\n" ); goto out;
include/linux/tpm.h +20 -48
87 lines not on this page · raw message
Signature · 1 line
2.45.2