To prevent timing attacks, HMAC value comparison needs to be constant time. Replace the memcmp() with the correct function, crypto_memneq().
Fixes: 1085b8276bb4 ("tpm: Add the rest of the session HMAC API") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers ebiggers@kernel.org --- drivers/char/tpm/Kconfig | 1 + drivers/char/tpm/tpm2-sessions.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index dddd702b2454a..f9d8a4e966867 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -31,10 +31,11 @@ config TCG_TPM2_HMAC bool "Use HMAC and encrypted transactions on the TPM bus" default X86_64 select CRYPTO_ECDH select CRYPTO_LIB_AESCFB select CRYPTO_LIB_SHA256 + select CRYPTO_LIB_UTILS help Setting this causes us to deploy a scheme which uses request and response HMACs in addition to encryption for communicating with the TPM to prevent or detect bus snooping and interposer attacks (see tpm-security.rst). Saying Y diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index bdb119453dfbe..5fbd62ee50903 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -69,10 +69,11 @@ #include <linux/unaligned.h> #include <crypto/kpp.h> #include <crypto/ecdh.h> #include <crypto/hash.h> #include <crypto/hmac.h> +#include <crypto/utils.h>
/* maximum number of names the TPM must remember for authorization */ #define AUTH_MAX_NAMES 3
#define AES_KEY_BYTES AES_KEYSIZE_128 @@ -827,16 +828,15 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf, sha256_update(&sctx, auth->our_nonce, sizeof(auth->our_nonce)); sha256_update(&sctx, &auth->attrs, 1); /* we're done with the rphash, so put our idea of the hmac there */ tpm2_hmac_final(&sctx, auth->session_key, sizeof(auth->session_key) + auth->passphrase_len, rphash); - if (memcmp(rphash, &buf->data[offset_s], SHA256_DIGEST_SIZE) == 0) { - rc = 0; - } else { + if (crypto_memneq(rphash, &buf->data[offset_s], SHA256_DIGEST_SIZE)) { dev_err(&chip->dev, "TPM: HMAC check failed\n"); goto out; } + rc = 0;
/* now do response decryption */ if (auth->attrs & TPM2_SA_ENCRYPT) { /* need key and IV */ tpm2_KDFa(auth->session_key, SHA256_DIGEST_SIZE