]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
tpm: Compare HMAC values in constant time
authorEric Biggers <ebiggers@kernel.org>
Fri, 1 Aug 2025 21:24:21 +0000 (14:24 -0700)
committerJarkko Sakkinen <jarkko@kernel.org>
Fri, 10 Oct 2025 05:21:45 +0000 (08:21 +0300)
In tpm_buf_check_hmac_response(), compare the HMAC values in constant
time using crypto_memneq() instead of in variable time using memcmp().

This is worthwhile to follow best practices and to be consistent with
MAC comparisons elsewhere in the kernel.  However, in this driver the
side channel seems to have been benign: the HMAC input data is
guaranteed to always be unique, which makes the usual MAC forgery via
timing side channel not possible.  Specifically, the HMAC input data in
tpm_buf_check_hmac_response() includes the "our_nonce" field, which was
generated by the kernel earlier, remains under the control of the
kernel, and is unique for each call to tpm_buf_check_hmac_response().

Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
drivers/char/tpm/Kconfig
drivers/char/tpm/tpm2-sessions.c

index 99c6fde288105fcc1ea3f30b0387e86e51355fa2..8a8f692b60880c1914d3d52c0256befbfd109b79 100644 (file)
@@ -33,6 +33,7 @@ config TCG_TPM2_HMAC
        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
index bdb119453dfbe4dcc3c0827e528d0c28c15ee53d..5fbd62ee50903aa11280bef724138c8bfa94c93a 100644 (file)
@@ -71,6 +71,7 @@
 #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
@@ -829,12 +830,11 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
        /* 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) {