From nobody Tue Dec 16 14:48:25 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 45A8B2D46A2; Sun, 14 Dec 2025 15:38:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765726727; cv=none; b=MB9NpvypUmp+dEUz0wjp/TIzTjPJ3LXQK32D1Hc+PZ3IzHjDqJR81Ijx4aTfUdhVYIvbzr+VMaOjHOxzcq6NOHspbKbKBSN72Gc+6GI5DHahzQArmNUKDRNTLszloki2eUGFPkmETjZGokH343Gbe5frw9EV4vrBaZiGYPHVG08= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765726727; c=relaxed/simple; bh=Mozwb/ufEVYIus8jRSCpreuld3E4Xlc6MGew+knHMTY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=W841JjvEbKKkl5vmATkVf8mghqNri8BCLvT+zLaNCJOP1HNWKeAlbY2oRzON51+pLWsKYB2ee7qqrc5HquR+0mwTcfNf7qS6fXAwHtbamZO8aBKTRJsY52FR4gDNfLE3dZFTNzbC8lIEMtQdrGBgDYRsThJEzWBPmNDgCO9k+Mo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=r6MmUqH5; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="r6MmUqH5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8C04FC4CEFB; Sun, 14 Dec 2025 15:38:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1765726726; bh=Mozwb/ufEVYIus8jRSCpreuld3E4Xlc6MGew+knHMTY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r6MmUqH50ksVwaI1JyeyD3V5/2goGWKgOX+4XJHzleBoqoOZ18+tY6n7joPcDCGX2 vzmO+8qCCPQozn+qsIsmkQeHF8cqGVKHwzq7cecSG2fmZNJ6WYzNatSNHuYFl6PkZW ON0FY0DubhBceHCjWo0ikuYpe+ApLA6nT/jslKCP/8csGArPCnYtNvUb3XjCBjJgDd 5n9LlF0iOz0/unT9PUhJVPhiArinUkb2Yng4Hk7mVKQrsyrWP0EFi7O5eoW3je/IlN PpIy5lp8TYKtgsjT02N/CaQ1n0vKo8pOUDRDutTCcq+anQDTxJwZgEW4JxCYXeqe72 VF1gssYdayEHg== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Ross Philipson , Jarkko Sakkinen , Peter Huewe , Jason Gunthorpe , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , linux-kernel@vger.kernel.org (open list), keyrings@vger.kernel.org (open list:KEYS/KEYRINGS), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM) Subject: [PATCH v6 06/11] tpm: Orchestrate TPM commands in tpm_get_random() Date: Sun, 14 Dec 2025 17:38:03 +0200 Message-Id: <20251214153808.73831-7-jarkko@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20251214153808.73831-1-jarkko@kernel.org> References: <20251214153808.73831-1-jarkko@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" tpm1_get_random() and tpm2_get_random() contain duplicate orchestration code. Consolidate orchestration to tpm_get_random(). Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm-interface.c | 175 +++++++++++++++++++++++++++++-- drivers/char/tpm/tpm.h | 2 - drivers/char/tpm/tpm1-cmd.c | 69 ------------ drivers/char/tpm/tpm2-cmd.c | 104 ------------------ 4 files changed, 164 insertions(+), 186 deletions(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interf= ace.c index f745a098908b..d157be738612 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -26,7 +26,7 @@ #include #include #include - +#include #include "tpm.h" =20 /* @@ -486,19 +486,153 @@ int tpm_pm_resume(struct device *dev) } EXPORT_SYMBOL_GPL(tpm_pm_resume); =20 +struct tpm1_get_random_out { + __be32 rng_data_len; + u8 rng_data[TPM_MAX_RNG_DATA]; +} __packed; + +static int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max) +{ + struct tpm1_get_random_out *resp; + struct tpm_buf buf; + u32 recd; + int rc; + + if (!out || !max || max > TPM_MAX_RNG_DATA) + return -EINVAL; + + rc =3D tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GETRANDOM); + if (rc) + return rc; + + tpm_buf_append_u32(&buf, max); + + rc =3D tpm_transmit_cmd(chip, &buf, sizeof(resp->rng_data_len), "TPM_GetR= andom"); + if (rc) { + if (rc > 0) + rc =3D -EIO; + goto err; + } + + resp =3D (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE]; + + recd =3D be32_to_cpu(resp->rng_data_len); + if (recd > max) { + rc =3D -EIO; + goto err; + } + + if (buf.length < TPM_HEADER_SIZE + sizeof(resp->rng_data_len) + recd) { + rc =3D -EIO; + goto err; + } + + memcpy(out, resp->rng_data, recd); + tpm_buf_destroy(&buf); + return recd; + +err: + tpm_buf_destroy(&buf); + return rc; +} + +struct tpm2_get_random_out { + __be16 size; + u8 buffer[TPM_MAX_RNG_DATA]; +} __packed; + +static int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max) +{ + struct tpm2_get_random_out *resp; + struct tpm_header *head; + struct tpm_buf buf; + off_t offset; + u32 recd; + int ret; + + if (!out || !max || max > TPM_MAX_RNG_DATA) + return -EINVAL; + + ret =3D tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM); + if (ret) + return ret; + + if (tpm2_chip_auth(chip)) { + tpm_buf_append_hmac_session(chip, &buf, + TPM2_SA_ENCRYPT | TPM2_SA_CONTINUE_SESSION, + NULL, 0); + } else { + head =3D (struct tpm_header *)buf.data; + head->tag =3D cpu_to_be16(TPM2_ST_NO_SESSIONS); + } + tpm_buf_append_u16(&buf, max); + + ret =3D tpm_buf_fill_hmac_session(chip, &buf); + if (ret) { + tpm_buf_destroy(&buf); + return ret; + } + + ret =3D tpm_transmit_cmd(chip, &buf, offsetof(struct tpm2_get_random_out,= buffer), + "TPM2_GetRandom"); + + ret =3D tpm_buf_check_hmac_response(chip, &buf, ret); + if (ret) { + if (ret > 0) + ret =3D -EIO; + + goto out; + } + + head =3D (struct tpm_header *)buf.data; + offset =3D TPM_HEADER_SIZE; + + /* Skip the parameter size field: */ + if (be16_to_cpu(head->tag) =3D=3D TPM2_ST_SESSIONS) + offset +=3D 4; + + resp =3D (struct tpm2_get_random_out *)&buf.data[offset]; + recd =3D min_t(u32, be16_to_cpu(resp->size), max); + + if (tpm_buf_length(&buf) < + TPM_HEADER_SIZE + offsetof(struct tpm2_get_random_out, buffer) + recd= ) { + ret =3D -EIO; + goto out; + } + + memcpy(out, resp->buffer, recd); + return recd; + +out: + tpm2_end_auth_session(chip); + tpm_buf_destroy(&buf); + return ret; +} + /** - * tpm_get_random() - get random bytes from the TPM's RNG - * @chip: a &struct tpm_chip instance, %NULL for the default chip - * @out: destination buffer for the random bytes - * @max: the max number of bytes to write to @out + * tpm_get_random() - Get random bytes from the TPM's RNG + * @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. + * + * Iterates pulling more bytes from TPM up until all of the @max bytes hav= e been + * received. * - * Return: number of random bytes read or a negative error value. + * Returns the number of random bytes read on success. + * Returns -EINVAL when @out is NULL, or @max is not between zero and + * %TPM_MAX_RNG_DATA. + * 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) { + u32 num_bytes =3D max; + u8 *out_ptr =3D out; + int retries =3D 5; + int total =3D 0; int rc; =20 - if (!out || max > TPM_MAX_RNG_DATA) + if (!out || !max || max > TPM_MAX_RNG_DATA) return -EINVAL; =20 if (!chip) @@ -508,11 +642,30 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, si= ze_t max) if (rc) return rc; =20 - if (chip->flags & TPM_CHIP_FLAG_TPM2) - rc =3D tpm2_get_random(chip, out, max); - else - rc =3D tpm1_get_random(chip, out, max); + if (chip->flags & TPM_CHIP_FLAG_TPM2) { + rc =3D tpm2_start_auth_session(chip); + if (rc) + return rc; + } + + do { + if (chip->flags & TPM_CHIP_FLAG_TPM2) + rc =3D tpm2_get_random(chip, out_ptr, num_bytes); + else + rc =3D tpm1_get_random(chip, out_ptr, num_bytes); + + if (rc < 0) + goto err; + + out_ptr +=3D rc; + total +=3D rc; + num_bytes -=3D rc; + } while (retries-- && total < max); + + tpm_put_ops(chip); + return total ? total : -EIO; =20 +err: tpm_put_ops(chip); return rc; } diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 02c07fef41ba..f698d01401de 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -251,7 +251,6 @@ int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,= const u8 *hash, int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf); ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, const char *desc, size_t min_cap_length); -int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max); int tpm1_get_pcr_allocation(struct tpm_chip *chip); unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal= ); int tpm_pm_suspend(struct device *dev); @@ -291,7 +290,6 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digest, u16 *digest_size_ptr); int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digests); -int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max); ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, const char *desc); =20 diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c index b49a790f1bd5..0604e11c9778 100644 --- a/drivers/char/tpm/tpm1-cmd.c +++ b/drivers/char/tpm/tpm1-cmd.c @@ -511,75 +511,6 @@ ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_= id, cap_t *cap, } EXPORT_SYMBOL_GPL(tpm1_getcap); =20 -#define TPM_ORD_GET_RANDOM 70 -struct tpm1_get_random_out { - __be32 rng_data_len; - u8 rng_data[TPM_MAX_RNG_DATA]; -} __packed; - -/** - * tpm1_get_random() - get random bytes from the TPM's RNG - * @chip: a &struct tpm_chip instance - * @dest: destination buffer for the random bytes - * @max: the maximum number of bytes to write to @dest - * - * Return: - * * number of bytes read - * * -errno (positive TPM return codes are masked to -EIO) - */ -int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max) -{ - struct tpm1_get_random_out *out; - u32 num_bytes =3D min_t(u32, max, TPM_MAX_RNG_DATA); - struct tpm_buf buf; - u32 total =3D 0; - int retries =3D 5; - u32 recd; - int rc; - - rc =3D tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); - if (rc) - return rc; - - do { - tpm_buf_append_u32(&buf, num_bytes); - - rc =3D tpm_transmit_cmd(chip, &buf, sizeof(out->rng_data_len), - "attempting get random"); - if (rc) { - if (rc > 0) - rc =3D -EIO; - goto out; - } - - out =3D (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE]; - - recd =3D be32_to_cpu(out->rng_data_len); - if (recd > num_bytes) { - rc =3D -EFAULT; - goto out; - } - - if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + - sizeof(out->rng_data_len) + recd) { - rc =3D -EFAULT; - goto out; - } - memcpy(dest, out->rng_data, recd); - - dest +=3D recd; - total +=3D recd; - num_bytes -=3D recd; - - tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); - } while (retries-- && total < max); - - rc =3D total ? (int)total : -EIO; -out: - tpm_buf_destroy(&buf); - return rc; -} - #define TPM_ORD_PCRREAD 21 int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) { diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 1f561ad3bdcf..461e85c3abe5 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -239,110 +239,6 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_id= x, return rc; } =20 -struct tpm2_get_random_out { - __be16 size; - u8 buffer[TPM_MAX_RNG_DATA]; -} __packed; - -/** - * tpm2_get_random() - get random bytes from the TPM RNG - * - * @chip: a &tpm_chip instance - * @dest: destination buffer - * @max: the max number of random bytes to pull - * - * Return: - * size of the buffer on success, - * -errno otherwise (positive TPM return codes are masked to -EIO) - */ -int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) -{ - struct tpm2_get_random_out *out; - struct tpm_header *head; - struct tpm_buf buf; - u32 recd; - u32 num_bytes =3D max; - int err; - int total =3D 0; - int retries =3D 5; - u8 *dest_ptr =3D dest; - off_t offset; - - if (!num_bytes || max > TPM_MAX_RNG_DATA) - return -EINVAL; - - err =3D tpm2_start_auth_session(chip); - if (err) - return err; - - err =3D tpm_buf_init(&buf, 0, 0); - if (err) { - tpm2_end_auth_session(chip); - return err; - } - - do { - tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM); - if (tpm2_chip_auth(chip)) { - tpm_buf_append_hmac_session(chip, &buf, - TPM2_SA_ENCRYPT | - TPM2_SA_CONTINUE_SESSION, - NULL, 0); - } else { - offset =3D buf.handles * 4 + TPM_HEADER_SIZE; - head =3D (struct tpm_header *)buf.data; - if (tpm_buf_length(&buf) =3D=3D offset) - head->tag =3D cpu_to_be16(TPM2_ST_NO_SESSIONS); - } - tpm_buf_append_u16(&buf, num_bytes); - err =3D tpm_buf_fill_hmac_session(chip, &buf); - if (err) { - tpm_buf_destroy(&buf); - return err; - } - - err =3D tpm_transmit_cmd(chip, &buf, - offsetof(struct tpm2_get_random_out, - buffer), - "attempting get random"); - err =3D tpm_buf_check_hmac_response(chip, &buf, err); - if (err) { - if (err > 0) - err =3D -EIO; - goto out; - } - - head =3D (struct tpm_header *)buf.data; - offset =3D TPM_HEADER_SIZE; - /* Skip the parameter size field: */ - if (be16_to_cpu(head->tag) =3D=3D TPM2_ST_SESSIONS) - offset +=3D 4; - - out =3D (struct tpm2_get_random_out *)&buf.data[offset]; - recd =3D min_t(u32, be16_to_cpu(out->size), num_bytes); - if (tpm_buf_length(&buf) < - TPM_HEADER_SIZE + - offsetof(struct tpm2_get_random_out, buffer) + - recd) { - err =3D -EFAULT; - goto out; - } - memcpy(dest_ptr, out->buffer, recd); - - dest_ptr +=3D recd; - total +=3D recd; - num_bytes -=3D recd; - } while (retries-- && total < max); - - tpm_buf_destroy(&buf); - - return total ? total : -EIO; -out: - tpm_buf_destroy(&buf); - tpm2_end_auth_session(chip); - return err; -} - /** * tpm2_flush_context() - execute a TPM2_FlushContext command * @chip: TPM chip to use --=20 2.39.5