[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251210172027.109938-8-jarkko@kernel.org>
Date: Wed, 10 Dec 2025 19:20:25 +0200
From: Jarkko Sakkinen <jarkko@...nel.org>
To: linux-integrity@...r.kernel.org
Cc: Jarkko Sakkinen <jarkko@...nel.org>,
"David S . Miller" <davem@...emloft.net>,
Herbert Xu <herbert@...dor.apana.org.au>,
Peter Huewe <peterhuewe@....de>,
Jason Gunthorpe <jgg@...pe.ca>,
David Howells <dhowells@...hat.com>,
Paul Moore <paul@...l-moore.com>,
James Morris <jmorris@...ei.org>,
"Serge E. Hallyn" <serge@...lyn.com>,
James Bottomley <James.Bottomley@...senPartnership.com>,
Mimi Zohar <zohar@...ux.ibm.com>,
linux-kernel@...r.kernel.org (open list),
keyrings@...r.kernel.org (open list:KEYS/KEYRINGS),
linux-security-module@...r.kernel.org (open list:SECURITY SUBSYSTEM)
Subject: [PATCH v4 7/8] tpm: Send only one at most TPM2_GetRandom command
hwrng framework does not have a requirement that the all bytes requested
need to be provided. By enforcing such a requirement internally, TPM driver
can cause unpredictability in latency, as a single tpm_get_random() call
can result multiple TPM commands.
Especially, when TCG_TPM2_HMAC is enabled, extra roundtrips could have
significant effect to the system latency.
Add a wait-parameter to enforce the old behavior and set it to true only at
the call sites for TPM 1.2 keys. At the call sites of hwrng, set @wait to
false.
Cc: David S. Miller <davem@...emloft.net>
Cc: Herbert Xu <herbert@...dor.apana.org.au>
Signed-off-by: Jarkko Sakkinen <jarkko@...nel.org>
---
v4:
- Fixed grammar mistakes.
---
drivers/char/tpm/tpm-chip.c | 2 +-
drivers/char/tpm/tpm-interface.c | 11 +++++++++--
include/linux/tpm.h | 2 +-
security/keys/trusted-keys/trusted_tpm1.c | 8 ++++----
4 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 082b910ddf0d..8fca4373e2df 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -494,7 +494,7 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
- return tpm_get_random(chip, data, max);
+ return tpm_get_random(chip, data, max, false);
}
static bool tpm_is_hwrng_enabled(struct tpm_chip *chip)
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index ab52a1cb0a78..5cc2bbabd57a 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -604,9 +604,11 @@ static int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max)
* @chip: A &tpm_chip instance. Whenset to %NULL, the default chip is used.
* @out: Destination buffer for the acquired random bytes.
* @max: The maximum number of bytes to write to @out.
+ * @wait: Set to true when all of the @max bytes need to be acquired.
*
* Iterates pulling more bytes from TPM up until all of the @max bytes have been
- * received.
+ * received, when @wait it sets true. Otherwise, the queries for @max bytes from
+ * TPM exactly once, and returns the bytes that were received.
*
* Returns the number of random bytes read on success.
* Returns -EINVAL when @out is NULL, or @max is not between zero and
@@ -614,7 +616,7 @@ static int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max)
* Returns tpm_transmit_cmd() error codes when the TPM command results an
* error.
*/
-int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
+int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max, bool wait)
{
u32 num_bytes = max;
u8 *out_ptr = out;
@@ -647,6 +649,11 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
if (rc < 0)
goto err;
+ if (!wait) {
+ total = rc;
+ break;
+ }
+
out_ptr += rc;
total += rc;
num_bytes -= rc;
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index e68995df8796..177833d6b965 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -485,7 +485,7 @@ extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
struct tpm_digest *digest);
extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
struct tpm_digest *digests);
-extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max);
+int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max, bool wait);
extern struct tpm_chip *tpm_default_chip(void);
void tpm2_flush_context(struct tpm_chip *chip, u32 handle);
int tpm2_find_hash_alg(unsigned int crypto_id);
diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c
index 759c1ecb0435..f36f6a0b533f 100644
--- a/security/keys/trusted-keys/trusted_tpm1.c
+++ b/security/keys/trusted-keys/trusted_tpm1.c
@@ -361,7 +361,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s,
unsigned char ononce[TPM_NONCE_SIZE];
int ret;
- ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE);
+ ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE, true);
if (ret < 0)
return ret;
@@ -454,7 +454,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE);
sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);
- ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE);
+ ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE, true);
if (ret < 0)
goto out;
@@ -565,7 +565,7 @@ static int tpm_unseal(struct tpm_buf *tb,
}
ordinal = htonl(TPM_ORD_UNSEAL);
- ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE);
+ ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE, true);
if (ret < 0)
return ret;
@@ -938,7 +938,7 @@ static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob)
static int trusted_tpm_get_random(unsigned char *key, size_t key_len)
{
- return tpm_get_random(chip, key, key_len);
+ return tpm_get_random(chip, key, key_len, true);
}
static int __init init_digests(void)
--
2.39.5
Powered by blists - more mailing lists