From nobody Sat Feb 7 11:31:23 2026 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 29B8E2F0C78; Sun, 25 Jan 2026 19:25:43 +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=1769369144; cv=none; b=Dwxr6nA0F2JDy20fMq6++P0FK+fKNwcLjsXQqbof9g+Po/jMSVEy7aBy4iDGogD3gALbeagaSUT6lghFGd1kbwGnVJ6awW/6Ta2qKE+xP8NLwUK9AuwtMvRk5ddp+36nPsO8D1YIhSvfFkeAZS+s8ls9YP+atq1q1sEiq6b/Cxw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769369144; c=relaxed/simple; bh=PN1ONpQnK+SF5l97FwDLlbrYt2AY83T4hiKTu6AGHLU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PIWEwxOiEcc2tS7XNgwQBG97xdIM6wNjbo4lEbPoDRgrEV1zOtrkD5FQoNHnq9bt4at53F2CBPbumJeUD3qSEo7RrLvJO/j/2b1Aahu1skLroykgRmN0MPQeYIaurDLMTfLkbRuaddG4J8Du5yaIvZGEfE8FM6EiMUNt4Kwhdok= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Dg7bB5mR; 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="Dg7bB5mR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 32A5CC4CEF1; Sun, 25 Jan 2026 19:25:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769369143; bh=PN1ONpQnK+SF5l97FwDLlbrYt2AY83T4hiKTu6AGHLU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Dg7bB5mRCyWuA0nJNvLZFcsoA1GcvefGR04wiNY+U91Cr+gxGguOWpuXfXktMlMWG yPbZ2LqtDpjMm0h4Tr2RXsrqt28C3Uttpf61T2NpYmeGp6d8W4dN2pit1VXw0nI2EY h6PdPuIxPjTvvqfpoP2bd6mP0Rhmw0L49nCFqrI82vqpYo5oA//j0x3eGgjZkHiC8X rYToaLHpDMJW2ammMluxlfqgWrWzbBswVCe6rJJ8kAhM6ve64iCA1FNqSfXc8d0Uz3 xMGnkd9LJ2NwOkB/FfCrpFiuAhWajG1yFWhnHzthHo6Sp3Bj6j9eSlIK2xLSBJC0Uu a7h7GGT6MvsJg== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , Eric Biggers , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v9 01/11] KEYS: trusted: Use get_random-fallback for TPM Date: Sun, 25 Jan 2026 21:25:11 +0200 Message-ID: <20260125192526.782202-2-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260125192526.782202-1-jarkko@kernel.org> References: <20260125192526.782202-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" 1. tpm2_get_random() is costly when TCG_TPM2_HMAC is enabled and thus its use should be pooled rather than directly used. This both reduces latency and improves its predictability. 2. Linux is better off overall if every subsystem uses the same source for generating the random numbers required. Thus, unset '.get_random', which causes fallback to kernel_get_random(). One might argue that TPM RNG should be used for the generated trusted keys, so that they have matching entropy with the TPM internally generated objects. This argument does have some weight into it but as far cryptography goes, FIPS certification sets the exact bar, not which exact FIPS certified RNG will be used. Thus, the rational choice is obviously to pick the lowest latency path, which is kernel RNG. Finally, there is an actual defence in depth benefit when using kernel RNG as it helps to mitigate TPM firmware bugs concerning RNG implementation, given the obfuscation by the other entropy sources. Reviewed-by: Eric Biggers Signed-off-by: Jarkko Sakkinen --- v7: - A new patch. Simplifies follow up patches. --- security/keys/trusted-keys/trusted_tpm1.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trus= ted-keys/trusted_tpm1.c index 636acb66a4f6..7ce7e31bcdfb 100644 --- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -6,6 +6,16 @@ * See Documentation/security/keys/trusted-encrypted.rst */ =20 +/** + * DOC: Random Number Generation + * + * tpm_get_random() was previously used here as the RNG in order to have e= qual + * entropy with the objects fully inside the TPM. However, as far as goes, + * kernel RNG is equally fine, as long as long as it is FIPS certified. Al= so, + * using kernel RNG has the benefit of mitigating bugs in the TPM firmware + * associated with the RNG. + */ + #include #include #include @@ -936,11 +946,6 @@ static int trusted_tpm_unseal(struct trusted_key_paylo= ad *p, char *datablob) return ret; } =20 -static int trusted_tpm_get_random(unsigned char *key, size_t key_len) -{ - return tpm_get_random(chip, key, key_len); -} - static int __init init_digests(void) { int i; @@ -992,6 +997,5 @@ struct trusted_key_ops trusted_key_tpm_ops =3D { .init =3D trusted_tpm_init, .seal =3D trusted_tpm_seal, .unseal =3D trusted_tpm_unseal, - .get_random =3D trusted_tpm_get_random, .exit =3D trusted_tpm_exit, }; --=20 2.52.0 From nobody Sat Feb 7 11:31:23 2026 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 CB0FF2F12A5; Sun, 25 Jan 2026 19:25:48 +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=1769369148; cv=none; b=Qy6i4dtbDHljYchZZNbuetIGIGA11Gh+1/E39DvQ//ADxuQnS3DNxwspsMSLhNrauMWd54JMpFexltTyNpplgvFts6Scbfjz13PG6r5u8qB+KtZwxSnc/dlj/MRnMZnoCG176hp/nAsRJ3VpFURezey5E2OR+ILvCpPCHHgN9Oc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769369148; c=relaxed/simple; bh=8pp+fW6JLbhqi+9zPhmUF2VbrqvhQc+UaIFr3qgiAlo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uvtu7bkoVedKirWQEVWEXX0ckzNUa2r5aH0Bx/mKT4T/wEDqGfs12Gyd62/mkaakKwHzQRNj3H0FXSLSx1E9PUCHHkIKDLjBnavkhwwYf+WRhHTdXP/XHrOlE7WMItH3YGDRUapAwOfDtBGkC8FfqcyLQnMXrRjzr4Z7mZtgn/s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QpLG/fV0; 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="QpLG/fV0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E00E8C4CEF1; Sun, 25 Jan 2026 19:25:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769369148; bh=8pp+fW6JLbhqi+9zPhmUF2VbrqvhQc+UaIFr3qgiAlo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QpLG/fV07zyT+sqqUhkTdKAGXL4uFH/XW4PSZRgMRPr7aeUaE27UmQLCk8ZyFZuGB TOK3Iu3zc35mGPYpN9pYsA+cSNJkTvkxVHKJUWvdPG6FOkRHyQL2s86ny+ZEYBhURD KxZp9gnV+zyjXg09zftS5MvRzCEoEqKfLEExEd1UAT8ElaSmTVeSJzO9ojcrk3/EM1 6Q8Hh8lUJKocbkTfVAYajh4WWGzzrt5/6ZotNfVn/YrKZlA/knA+SedpeCH3Qy2fOi +ox2CRGcs3jxyuyV+a+pjmRecwg3LPywAqpL8JtXpY5W2PSkvtkWNKEhMHkKsKCVPC FYPKwqcunjPGA== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , Jonathan McDowell , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v9 02/11] KEYS: trusted: Use get_random_bytes_wait() instead of tpm_get_random() Date: Sun, 25 Jan 2026 21:25:12 +0200 Message-ID: <20260125192526.782202-3-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260125192526.782202-1-jarkko@kernel.org> References: <20260125192526.782202-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" Substitute the remaining tpm_get_random() calls in trusted_tpm1.c with get_random_bytes_wait() thus aligning random number generation for TPM 1.2 with the removal of '.get_random' callback. Reviewed-by: Jonathan McDowell Signed-off-by: Jarkko Sakkinen --- security/keys/trusted-keys/trusted_tpm1.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trus= ted-keys/trusted_tpm1.c index 7ce7e31bcdfb..3d75bb6f9689 100644 --- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -371,13 +371,10 @@ static int osap(struct tpm_buf *tb, struct osapsess *= s, unsigned char ononce[TPM_NONCE_SIZE]; int ret; =20 - ret =3D tpm_get_random(chip, ononce, TPM_NONCE_SIZE); + ret =3D get_random_bytes_wait(ononce, TPM_NONCE_SIZE); if (ret < 0) return ret; =20 - if (ret !=3D TPM_NONCE_SIZE) - return -EIO; - tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP); tpm_buf_append_u16(tb, type); tpm_buf_append_u32(tb, handle); @@ -464,15 +461,10 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keyt= ype, memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE); sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash); =20 - ret =3D tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE); + ret =3D get_random_bytes_wait(td->nonceodd, TPM_NONCE_SIZE); if (ret < 0) goto out; =20 - if (ret !=3D TPM_NONCE_SIZE) { - ret =3D -EIO; - goto out; - } - ordinal =3D htonl(TPM_ORD_SEAL); datsize =3D htonl(datalen); pcrsize =3D htonl(pcrinfosize); @@ -575,14 +567,10 @@ static int tpm_unseal(struct tpm_buf *tb, } =20 ordinal =3D htonl(TPM_ORD_UNSEAL); - ret =3D tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE); + ret =3D get_random_bytes_wait(nonceodd, TPM_NONCE_SIZE); if (ret < 0) return ret; =20 - if (ret !=3D TPM_NONCE_SIZE) { - pr_info("tpm_get_random failed (%d)\n", ret); - return -EIO; - } ret =3D TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE, enonce1, nonceodd, cont, sizeof(uint32_t), &ordinal, bloblen, blob, 0, 0); --=20 2.52.0 From nobody Sat Feb 7 11:31:23 2026 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 618392F12A5; Sun, 25 Jan 2026 19:25:53 +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=1769369153; cv=none; b=Vqsl+vjQpR0N3SroPRN+xDebMlSKYKI25ZXFjnmhXGnE7Bwxr7bsYbcXvyRlkb5H6dtlUG3tZxd7DRjsmG5YCvnSGSo8Vk85t1yFY75BoOFNFNfiyqEc7Wn8XfHFmjZBLEbQSRBhZj/vzqxCRgv/VMxdPsHGfxhqpCwUPz/SPiw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769369153; c=relaxed/simple; bh=A7Dkc+DU3z769vOotl5kpmSQoLZD3NfnQOUU5DEX3k8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UiDv08tV7s63EcNFnTme5kIhl8Eplr9wk307LQ8r47lvySFV6MSrdfVo5hgsQpdNuBB0RenjcC17fxbap5x01FtyPPUC2YuPULxivPNim4iDIn2+AB5EJe0cPjgw3x48FpBt1o9+PuUdoKO9KJS2+yKui5+MpLiKcg994W0wlBA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=U0/bjpmz; 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="U0/bjpmz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 80439C4CEF1; Sun, 25 Jan 2026 19:25:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769369153; bh=A7Dkc+DU3z769vOotl5kpmSQoLZD3NfnQOUU5DEX3k8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=U0/bjpmzDIq0I7qnOfhxWPqVL1cJ7u5GB7xmF+NGeK6WMygBiaonoRMwPPOxbX+AT ujz5TbpsM8UQn6JseNZcBC4C1Ly3WdG9OwzK9HLAanU/VlUOzulML52fJZ1ts7ct6R sJ+1TOoN/YTfE03OKG0UTRQWMJiM7eKAB28zTUxUF2T1r4Kb4kX1l9MzCX0oMLfJCq 0WJT+vhu4H+qxkuRHoTl7zFl0p0UERQGNvb0iuy3wFSvSAr0ldIsvOEHFRyvB2D1j5 dtMqLRIxPoBZ675HWYbPAZ7+lUifNHeSV0K2wP+44JQTSx5x90IVPoVMW4AxA+R+RC C1TyeMZwE6FIw== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , "David S. Miller" , Herbert Xu , Eric Biggers , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v9 03/11] tpm: Change tpm_get_random() opportunistic Date: Sun, 25 Jan 2026 21:25:13 +0200 Message-ID: <20260125192526.782202-4-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260125192526.782202-1-jarkko@kernel.org> References: <20260125192526.782202-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" 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. Thus, send TPM command only once and return bytes received instead of committing to the number of requested bytes. Cc: David S. Miller Cc: Herbert Xu Cc: Eric Biggers Signed-off-by: Jarkko Sakkinen --- v9: - Merge orchestration. v7: - Given that hwrng is now only caller for tpm_get_random(), remove the wait parameter. v4: - Fixed grammar mistakes. --- drivers/char/tpm/tpm-interface.c | 20 ++++-- drivers/char/tpm/tpm1-cmd.c | 66 ++++++++---------- drivers/char/tpm/tpm2-cmd.c | 115 +++++++++++++------------------ 3 files changed, 88 insertions(+), 113 deletions(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interf= ace.c index f745a098908b..d44bd8c44612 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -487,18 +487,24 @@ int tpm_pm_resume(struct device *dev) EXPORT_SYMBOL_GPL(tpm_pm_resume); =20 /** - * 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. When set to %NULL, the default chip is use= d. + * @out: Destination buffer for the acquired random bytes. + * @max: The maximum number of bytes to write to @out. + * + * Tries to pull bytes from the TPM. At most, @max bytes are returned. * - * 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) { int rc; =20 - if (!out || max > TPM_MAX_RNG_DATA) + if (!out || !max || max > TPM_MAX_RNG_DATA) return -EINVAL; =20 if (!chip) @@ -514,7 +520,7 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size= _t max) rc =3D tpm1_get_random(chip, out, max); =20 tpm_put_ops(chip); - return rc; + return rc !=3D 0 ? rc : -EIO; } EXPORT_SYMBOL_GPL(tpm_get_random); =20 diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c index b49a790f1bd5..3fe94f596f97 100644 --- a/drivers/char/tpm/tpm1-cmd.c +++ b/drivers/char/tpm/tpm1-cmd.c @@ -518,63 +518,51 @@ struct tpm1_get_random_out { } __packed; =20 /** - * 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 + * tpm1_get_random() - Get random bytes from the TPM's RNG * - * Return: - * * number of bytes read - * * -errno (positive TPM return codes are masked to -EIO) + * This is an internal function for tpm_get_random(). See its documentation + * for more information. */ 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 tpm1_get_random_out *resp; struct tpm_buf buf; - u32 total =3D 0; - int retries =3D 5; u32 recd; int rc; =20 + if (!dest || !max || max > TPM_MAX_RNG_DATA) + return -EINVAL; + rc =3D tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); if (rc) return rc; =20 - 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; - } + tpm_buf_append_u32(&buf, max); =20 - out =3D (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE]; + rc =3D tpm_transmit_cmd(chip, &buf, sizeof(resp->rng_data_len), "TPM_GetR= andom"); + if (rc) { + if (rc > 0) + rc =3D -EIO; + goto out; + } =20 - recd =3D be32_to_cpu(out->rng_data_len); - if (recd > num_bytes) { - rc =3D -EFAULT; - goto out; - } + resp =3D (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE]; =20 - 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); + recd =3D be32_to_cpu(resp->rng_data_len); + if (recd > max) { + rc =3D -EIO; + goto out; + } =20 - dest +=3D recd; - total +=3D recd; - num_bytes -=3D recd; + if (buf.length < TPM_HEADER_SIZE + sizeof(resp->rng_data_len) + recd) { + rc =3D -EIO; + goto out; + } =20 - tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); - } while (retries-- && total < max); + memcpy(dest, resp->rng_data, recd); + tpm_buf_destroy(&buf); + return recd; =20 - rc =3D total ? (int)total : -EIO; out: tpm_buf_destroy(&buf); return rc; diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 3a77be7ebf4a..5f15d8a93e23 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -244,98 +244,79 @@ struct tpm2_get_random_out { } __packed; =20 /** - * tpm2_get_random() - get random bytes from the TPM RNG + * tpm2_get_random() - Get random bytes from the TPM's 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) + * This is an internal function for tpm_get_random(). See its documentation + * for more information. */ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) { - struct tpm2_get_random_out *out; + struct tpm2_get_random_out *resp; struct tpm_header *head; struct tpm_buf buf; + off_t offset; 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; =20 - if (!num_bytes || max > TPM_MAX_RNG_DATA) + if (!dest || !max || max > TPM_MAX_RNG_DATA) return -EINVAL; =20 err =3D tpm2_start_auth_session(chip); if (err) return err; =20 - err =3D tpm_buf_init(&buf, 0, 0); + err =3D tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM); if (err) { tpm2_end_auth_session(chip); return err; } =20 - 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; - } + 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); =20 - 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; - } + err =3D tpm_buf_fill_hmac_session(chip, &buf); + if (err) { + tpm_buf_destroy(&buf); + return err; + } =20 - 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); + err =3D tpm_transmit_cmd(chip, &buf, offsetof(struct tpm2_get_random_out,= buffer), + "TPM2_GetRandom"); =20 - dest_ptr +=3D recd; - total +=3D recd; - num_bytes -=3D recd; - } while (retries-- && total < max); + err =3D tpm_buf_check_hmac_response(chip, &buf, err); + if (err) { + if (err > 0) + err =3D -EIO; =20 - tpm_buf_destroy(&buf); + 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= ) { + err =3D -EIO; + goto out; + } + + memcpy(dest, resp->buffer, recd); + return recd; =20 - return total ? total : -EIO; out: tpm_buf_destroy(&buf); tpm2_end_auth_session(chip); --=20 2.52.0 From nobody Sat Feb 7 11:31:23 2026 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 CAA162F0C78; Sun, 25 Jan 2026 19:25:57 +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=1769369157; cv=none; b=t2en38O96XG69PQscM/jE0DwB+ZKWTl9ZumNe3x8VnEnymr6qrQt1MlIL6GhLBFtBNn8bqBNaTsyhD5dlPCu3Jb/u4QIoklnCsW4bsBvZ/1kYmD+ZvpOG6Gwd2xDJxkQdjm9KCC4XPJP6zOfjvbsd313+K0OR2DRaXeOezqfEGI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769369157; c=relaxed/simple; bh=gjape427JNzLHhUzr7axo+sf4FV+4SSZgRTvzcK97t0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DmtrcD0GIUIWRonn11SpLQuXfwNU6QKXrnjTJTaDLA1rNQsvxegw0u/oFw7nPF4CYleeaaXlr4gAk9L5ejpIOcdE9zUFdKwaH0EjrEtR2oQTicfdAhlyAQEjNOHtm4UDFZF+86fTH5frjQQM2+TT+imR+LhGPlmjdhWVObFCisc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=M76CeO6t; 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="M76CeO6t" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 20AA6C2BC86; Sun, 25 Jan 2026 19:25:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769369157; bh=gjape427JNzLHhUzr7axo+sf4FV+4SSZgRTvzcK97t0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M76CeO6tPcBKib73EVdNVVekwque6eBz3qKAsx1YZ06wLbyp+mnl7Qk3MN2aO2FNQ 1w52Sl33U3vrAUxFn4d7WH8GMjO8qv9pPl6LAEH2kARdi5Qmys0I/v9l5azCIsYsGL Kzp7Pnl4Z8AhsLDiKNLN/qMrso5saoKxp6eZzekRo3QWbJogaUrVYb6FLVkv29BYO2 BnIf2ShbpxHTAIaG7HyUygiyjc+gg/cw8H3WmjTCmV3B6i13eHrWKgQX3DbuwTwXiH fDJDT1rC6XzLdbD51xy4c/RAuNdSgSKruitQoostf0yBzuLELAK8huAk9jvNCr3Oox kbYZnDiV66Nyg== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , Jonathan McDowell , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v9 04/11] tpm2-sessions: Define TPM2_NAME_MAX_SIZE Date: Sun, 25 Jan 2026 21:25:14 +0200 Message-ID: <20260125192526.782202-5-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260125192526.782202-1-jarkko@kernel.org> References: <20260125192526.782202-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" Define TPM2_NAME_MAX_SIZE, which describes the maximum size for hashes encoded as TPMT_HA, which the prime identifier used for persistent and transient keys in TPM2 protocol. Set its value to 'SHA512_DIGEST_SIZE + 2', as SHA512 has the largest digest size of the algorithms in TCG algorithm repository. In additionl, rename TPM2_NAME_SIZE as TPM2_NULL_NAME_SIZE in order to avoid any possible confusion. Reviewed-by: Jonathan McDowell Signed-off-by: Jarkko Sakkinen --- v6: - Rewrote the commit message. v2: - Rename TPM2_NAME_SIZE as TPM2_NULL_NAME_SIZE. --- drivers/char/tpm/tpm-sysfs.c | 2 +- drivers/char/tpm/tpm2-sessions.c | 2 +- include/linux/tpm.h | 37 +++++++++++++++++++++----------- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 94231f052ea7..4a6a27ee295d 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c @@ -314,7 +314,7 @@ static ssize_t null_name_show(struct device *dev, struc= t device_attribute *attr, char *buf) { struct tpm_chip *chip =3D to_tpm_chip(dev); - int size =3D TPM2_NAME_SIZE; + int size =3D TPM2_NULL_NAME_SIZE; =20 bin2hex(buf, chip->null_key_name, size); size *=3D 2; diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessi= ons.c index 4149379665c4..525b8622d1c3 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -137,7 +137,7 @@ struct tpm2_auth { * we must compute and remember */ u32 name_h[AUTH_MAX_NAMES]; - u8 name[AUTH_MAX_NAMES][2 + SHA512_DIGEST_SIZE]; + u8 name[AUTH_MAX_NAMES][TPM2_MAX_NAME_SIZE]; }; =20 #ifdef CONFIG_TCG_TPM2_HMAC diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 202da079d500..8b82290de99f 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -27,9 +27,33 @@ =20 #define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ =20 +/* + * SHA-512 is, as of today, the largest digest in the TCG algorithm reposi= tory. + */ #define TPM2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE + +/* + * A TPM name digest i.e., TPMT_HA, is a concatenation of TPM_ALG_ID of the + * name algorithm and hash of TPMT_PUBLIC. + */ +#define TPM2_MAX_NAME_SIZE (TPM2_MAX_DIGEST_SIZE + 2) + +/* + * The maximum number of PCR banks. + */ #define TPM2_MAX_PCR_BANKS 8 =20 +/* + * Fixed define for the size of a name. This is actually HASHALG size + * plus 2, so 32 for SHA256 + */ +#define TPM2_NULL_NAME_SIZE 34 + +/* + * The maximum size for an object context + */ +#define TPM2_MAX_CONTEXT_SIZE 4096 + struct tpm_chip; struct trusted_key_payload; struct trusted_key_options; @@ -139,17 +163,6 @@ struct tpm_chip_seqops { /* fixed define for the curve we use which is NIST_P256 */ #define EC_PT_SZ 32 =20 -/* - * fixed define for the size of a name. This is actually HASHALG size - * plus 2, so 32 for SHA256 - */ -#define TPM2_NAME_SIZE 34 - -/* - * The maximum size for an object context - */ -#define TPM2_MAX_CONTEXT_SIZE 4096 - struct tpm_chip { struct device dev; struct device devs; @@ -211,7 +224,7 @@ struct tpm_chip { /* saved context for NULL seed */ u8 null_key_context[TPM2_MAX_CONTEXT_SIZE]; /* name of NULL seed */ - u8 null_key_name[TPM2_NAME_SIZE]; + u8 null_key_name[TPM2_NULL_NAME_SIZE]; u8 null_ec_key_x[EC_PT_SZ]; u8 null_ec_key_y[EC_PT_SZ]; struct tpm2_auth *auth; --=20 2.52.0 From nobody Sat Feb 7 11:31:23 2026 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 02E4D2F3624; Sun, 25 Jan 2026 19:26:02 +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=1769369163; cv=none; b=i+Fasg4s/KmLDP0Nprd8DTLgQsLALIHhXC9kLKbBOnFcilhZ0s/y8dPiA1JAc0gQCN/kPS/JFoQsan95VQhFl+z0xZ3M/mt9IJd4i9tGwWfPoxB1EjKGDiAC7EbTg2uOT4+ao2MuXn8rxGOY4CHERYgzhVI9JvB7jsMtaXkxn2M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769369163; c=relaxed/simple; bh=wd/PVTcrKpAz5gWg6nlyquqYBSfSvIMeV0DjFCJN4ms=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KnQM+veMoiXA1Q2iVyuULc91TyNNqs/OcnHrX2L+6qs9eb/Ic5qG0TX5vLGSrqxaBj1v3F7KSf9AGrBA05FKWzCiKSJD1nHQsiESaLS8Kge/bOEmRzrV98K0AsTsxvhNSZjuX5ju/kTM6ETkrP20HZzO+RbUPYkqsZFWuZ6x6PM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FqKm7dcE; 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="FqKm7dcE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F291BC4CEF1; Sun, 25 Jan 2026 19:26:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769369162; bh=wd/PVTcrKpAz5gWg6nlyquqYBSfSvIMeV0DjFCJN4ms=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FqKm7dcEUtXj8VaL4SHDnYGjUU+r7eb+rrGeBiDaQS3nKCAZzUOAVKIRTaSc5igqX hsFanVDNpvaCKyHrG/fba9eISX+W1sXLlBeyyxYbpHMQlnSDoyYdQgg1A11lO953lR IhHgncmagL9NChyaJF4bkJncnNHVV5RS/Lum/zbCRAailtLqSo8t8u00C2E60kIBq+ yCuTr701dP6nplMo/1soVjdfV670KzrRe0fYE+PBvpNh1qJHlMM6EqiHAaGnPOdNlr Y+QcI4/edcXC7iOGn+LRK2cE7owPt2JEuqVF7y6WUVgA1ZJkWHNDQGd0J87Z6a59Lb C8duCl47KU9jg== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , Jonathan McDowell , James Bottomley , Jarkko Sakkinen , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v9 05/11] KEYS: trusted: Open code tpm2_buf_append() Date: Sun, 25 Jan 2026 21:25:15 +0200 Message-ID: <20260125192526.782202-6-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260125192526.782202-1-jarkko@kernel.org> References: <20260125192526.782202-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" From: Jarkko Sakkinen tpm2_buf_append_auth() has a single call site and most of its parameters are redundant. Open code it to the call site so that less cross-referencing is required while browsing the source code. Signed-off-by: Jarkko Sakkinen Reviewed-by: Jonathan McDowell --- v6: - Trimmed the patch by removing comment update as it is out of scope. --- security/keys/trusted-keys/trusted_tpm2.c | 40 ++++------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trus= ted-keys/trusted_tpm2.c index 6340823f8b53..4894aae6ef70 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -190,36 +190,6 @@ int tpm2_key_priv(void *context, size_t hdrlen, return 0; } =20 -/** - * tpm2_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer. - * - * @buf: an allocated tpm_buf instance - * @session_handle: session handle - * @nonce: the session nonce, may be NULL if not used - * @nonce_len: the session nonce length, may be 0 if not used - * @attributes: the session attributes - * @hmac: the session HMAC or password, may be NULL if not used - * @hmac_len: the session HMAC or password length, maybe 0 if not used - */ -static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle, - const u8 *nonce, u16 nonce_len, - u8 attributes, - const u8 *hmac, u16 hmac_len) -{ - tpm_buf_append_u32(buf, 9 + nonce_len + hmac_len); - tpm_buf_append_u32(buf, session_handle); - tpm_buf_append_u16(buf, nonce_len); - - if (nonce && nonce_len) - tpm_buf_append(buf, nonce, nonce_len); - - tpm_buf_append_u8(buf, attributes); - tpm_buf_append_u16(buf, hmac_len); - - if (hmac && hmac_len) - tpm_buf_append(buf, hmac, hmac_len); -} - /** * tpm2_seal_trusted() - seal the payload of a trusted key * @@ -518,9 +488,13 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, * could repeat our actions with the exfiltrated * password. */ - tpm2_buf_append_auth(&buf, options->policyhandle, - NULL /* nonce */, 0, 0, - options->blobauth, options->blobauth_len); + tpm_buf_append_u32(&buf, 9 + options->blobauth_len); + tpm_buf_append_u32(&buf, options->policyhandle); + tpm_buf_append_u16(&buf, 0); + tpm_buf_append_u8(&buf, 0); + tpm_buf_append_u16(&buf, options->blobauth_len); + tpm_buf_append(&buf, options->blobauth, options->blobauth_len); + if (tpm2_chip_auth(chip)) { tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, NULL, 0); } else { --=20 2.52.0 From nobody Sat Feb 7 11:31:23 2026 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 D44AB2F12A5; Sun, 25 Jan 2026 19:26:07 +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=1769369167; cv=none; b=O0BayPaFe/HRKld8FTSFsx0IvbHirYAmZbt7bMGSZEwBvdkbc7ZB57A4yIxzYZGIH1wI5JpzH1NGTXA5/MDjKiHV6JrVN9otNA5o5IdNe/2Qwdq+H/kDB9IcScqvPo383/ShLohbR3YdKM9YyBIHhJq907/HI5caddEyOIhuGUA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769369167; c=relaxed/simple; bh=5edvRXiZtKuCqYiyovDpX6TJD/qNz0z+e7B/kJJvrgk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FERsqGdVcdaKHKqRi6RF0uktgyTJ3ddI7kHyrkrab8DmponNc31plCn6BMn0hppUIf3nQ1DNPA6zeyJx5gryU5hi/70jA89KhwvmeSOV8JxfusSaCswAJf2SBQBGCwfEHq20hIyNWfl5RWcVq8sSXNT1E7XyesBCzGXxaZ/LV1g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=b1t1gwLw; 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="b1t1gwLw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 29489C4CEF1; Sun, 25 Jan 2026 19:26:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769369167; bh=5edvRXiZtKuCqYiyovDpX6TJD/qNz0z+e7B/kJJvrgk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=b1t1gwLw9B7EfCjDkrDVNY1HcosD7na6FOwZj2ckixl4xtS+5U6NrLKnqCD/yS1Uk WoTIm8hpBIA/pFJgolKmOgYBrHWy4vbfFtiBJH2PRiEdmCaX1MVt8U3oMqck6Ip00v 28dpdWSJ/x/V1VFlyoexVbO6wbQebvI+/1WRaeBkQo/mUvkTuqcnF8Z76SGgXAq0Xh xLKsnCCszI7wrJm51uySQ3EqeO4oLeEsyZfVq9eGUvhkCSO/H7uGBD0IrhXXmEYpMI tA5rnviJ6nMDWyu0MkOSAhn5sZf++9w+s9brH7jHSiih9Eo9iQIRqAzRIAJODJOFhT WHWOQUp4M2DHQ== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , Jonathan McDowell , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v9 06/11] KEYS: trusted: Remove dead branch from tpm2_unseal_cmd Date: Sun, 25 Jan 2026 21:25:16 +0200 Message-ID: <20260125192526.782202-7-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260125192526.782202-1-jarkko@kernel.org> References: <20260125192526.782202-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" TPM2_Unseal requires TPM2_ST_SESSIONS, and tpm2_unseal_cmd() always does set up either password or HMAC session. Remove the branch in tpm2_unseal_cmd() conditionally setting TPM2_ST_NO_SESSIONS. It is faulty but luckily it is never exercised at run-time, and thus does not cause regressions. Reviewed-by: Jonathan McDowell Signed-off-by: Jarkko Sakkinen --- security/keys/trusted-keys/trusted_tpm2.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trus= ted-keys/trusted_tpm2.c index 4894aae6ef70..ec84ea945d3b 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -451,10 +451,8 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, struct trusted_key_options *options, u32 blob_handle) { - struct tpm_header *head; struct tpm_buf buf; u16 data_len; - int offset; u8 *data; int rc; =20 @@ -495,14 +493,8 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, tpm_buf_append_u16(&buf, options->blobauth_len); tpm_buf_append(&buf, options->blobauth, options->blobauth_len); =20 - if (tpm2_chip_auth(chip)) { + if (tpm2_chip_auth(chip)) tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, 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); - } } =20 rc =3D tpm_buf_fill_hmac_session(chip, &buf); --=20 2.52.0 From nobody Sat Feb 7 11:31:23 2026 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 7E9902F12A5; Sun, 25 Jan 2026 19:26:12 +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=1769369172; cv=none; b=MUUzDEj/YyACz+wHlmJB7XCjQpNtpJQxntdt4aeCeSgQ7IST0F6jrvq6ON6k0hUeCr7TFf6q0rLqEGEV/RSNmB7QjMFWA12MQomWYSFZB/DAknojqpLJ1g+tWyNu4FKJUZoKObQJFzNnl3WxXiHKY6xhh5tDoAg8Rw+JJTUP+oY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769369172; c=relaxed/simple; bh=1n4vBoGt02A8efZiPGFlFGLtWMVhFN9okcGWVa1AK88=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GFaWCcZ54aLKAik0mLYz+SCtZgpTBjrCaQQZtplxq5ajfdSpgBUkbyqnX7MLOI/3ZUk0O5X0GSfaZGZwhlEk7ZNwifpLe/YqvTOYRbUYYslOf9yce5XMkLG8GVnC+njQfexv4cudkJbnVZD67zyjdVqqSD92hQNp9oHDN533c9U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TRsrTmdN; 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="TRsrTmdN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BC721C4CEF1; Sun, 25 Jan 2026 19:26:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769369172; bh=1n4vBoGt02A8efZiPGFlFGLtWMVhFN9okcGWVa1AK88=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TRsrTmdNo6KaVBZR5iAxfQBwb8G+koqIdhYQAiOa5VwZK7C1H+u3fPcezKJKOZ0A/ A1R9+po3kpUSngHSdCWjjNseGwCt6lc8WXU4XDtzzBGaof+yfaZ43ougtJxCetMjeZ A2ylA/733Xb6B4mwXwIrVHbSYpOTtDuVi4Ol84hy6R51RMITgVXkqLS0GAgNrXGQIv C3PmNAnF9uM13vp2CJ8BLoMTfgydDphMoURn9ubbJg/z4MF7pBNi6NS62V0O2owjk+ CMsLAnfPEfJqMS5fX9xMv8rG+XFbb19QX5ZBtn1d0aCeGqDkIHcVd4qGhiHWm+lPpj dskMvvvI1X8bw== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v9 07/11] KEYS: trusted: Re-orchestrate tpm2_read_public() calls Date: Sun, 25 Jan 2026 21:25:17 +0200 Message-ID: <20260125192526.782202-8-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260125192526.782202-1-jarkko@kernel.org> References: <20260125192526.782202-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" tpm2_load_cmd() and tpm2_unseal_cmd() use the same parent, and calls to tpm_buf_append_name() cause the exact same TPM2_ReadPublic command to be sent to the chip, causing unnecessary traffic. 1. Export tpm2_read_public in order to make it callable from 'trusted_tpm2'. 2. Re-orchestrate tpm2_seal_trusted() and tpm2_unseal_trusted() in order to halve the name resolutions required: 2a. Move tpm2_read_public() calls into trusted_tpm2. 2b. Pass TPM name to tpm_buf_append_name(). 2c. Rework tpm_buf_append_name() to use the pre-resolved name. Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm2-cmd.c | 3 +- drivers/char/tpm/tpm2-sessions.c | 95 +++++------------ include/linux/tpm.h | 10 +- security/keys/trusted-keys/trusted_tpm2.c | 122 ++++++++++++++-------- 4 files changed, 117 insertions(+), 113 deletions(-) diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 5f15d8a93e23..96a45391036c 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -202,7 +202,8 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, } =20 if (!disable_pcr_integrity) { - rc =3D tpm_buf_append_name(chip, &buf, pcr_idx, NULL); + rc =3D tpm_buf_append_name(chip, &buf, pcr_idx, (u8 *)&pcr_idx, + sizeof(u32)); if (rc) { tpm_buf_destroy(&buf); return rc; diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessi= ons.c index 525b8622d1c3..3bc3c31cf512 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -136,8 +136,8 @@ struct tpm2_auth { * handle, but they are part of the session by name, which * we must compute and remember */ - u32 name_h[AUTH_MAX_NAMES]; u8 name[AUTH_MAX_NAMES][TPM2_MAX_NAME_SIZE]; + u16 name_size_tbl[AUTH_MAX_NAMES]; }; =20 #ifdef CONFIG_TCG_TPM2_HMAC @@ -163,7 +163,17 @@ static int name_size(const u8 *name) } } =20 -static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) +/** + * tpm2_read_public: Resolve TPM name for a handle + * @chip: TPM chip to use. + * @handle: TPM handle. + * @name: A buffer for returning the name blob. Must have a + * capacity of 'SHA512_DIGET_SIZE + 2' bytes at minimum + * + * Returns size of TPM handle name of success. + * Returns tpm_transmit_cmd error codes when TPM2_ReadPublic fails. + */ +int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) { u32 mso =3D tpm2_handle_mso(handle); off_t offset =3D TPM_HEADER_SIZE; @@ -219,14 +229,16 @@ static int tpm2_read_public(struct tpm_chip *chip, u3= 2 handle, void *name) memcpy(name, &buf.data[offset], rc); return name_size_alg; } +EXPORT_SYMBOL_GPL(tpm2_read_public); #endif /* CONFIG_TCG_TPM2_HMAC */ =20 /** - * tpm_buf_append_name() - add a handle area to the buffer - * @chip: the TPM chip structure - * @buf: The buffer to be appended - * @handle: The handle to be appended - * @name: The name of the handle (may be NULL) + * tpm_buf_append_name() - Append a handle and store TPM name + * @chip: TPM chip to use. + * @buf: TPM buffer containing the TPM command in-transit. + * @handle: TPM handle to be appended. + * @name: TPM name of the handle + * @name_size: Size of the TPM name. * * In order to compute session HMACs, we need to know the names of the * objects pointed to by the handles. For most objects, this is simply @@ -243,15 +255,14 @@ static int tpm2_read_public(struct tpm_chip *chip, u3= 2 handle, void *name) * will be caused by an incorrect programming model and indicated by a * kernel message. * - * Ends the authorization session on failure. + * Returns zero on success. + * Returns -EIO when the authorization area state is malformed. */ int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf, - u32 handle, u8 *name) + u32 handle, u8 *name, u16 name_size) { #ifdef CONFIG_TCG_TPM2_HMAC - enum tpm2_mso_type mso =3D tpm2_handle_mso(handle); struct tpm2_auth *auth; - u16 name_size_alg; int slot; int ret; #endif @@ -276,36 +287,15 @@ int tpm_buf_append_name(struct tpm_chip *chip, struct= tpm_buf *buf, } tpm_buf_append_u32(buf, handle); auth->session +=3D 4; - - if (mso =3D=3D TPM2_MSO_PERSISTENT || - mso =3D=3D TPM2_MSO_VOLATILE || - mso =3D=3D TPM2_MSO_NVRAM) { - if (!name) { - ret =3D tpm2_read_public(chip, handle, auth->name[slot]); - if (ret < 0) - goto err; - - name_size_alg =3D ret; - } - } else { - if (name) { - dev_err(&chip->dev, "handle 0x%08x does not use a name\n", - handle); - ret =3D -EIO; - goto err; - } - } - - auth->name_h[slot] =3D handle; - if (name) - memcpy(auth->name[slot], name, name_size_alg); + memcpy(auth->name[slot], name, name_size); + auth->name_size_tbl[slot] =3D name_size; #endif return 0; =20 #ifdef CONFIG_TCG_TPM2_HMAC err: tpm2_end_auth_session(chip); - return tpm_ret_to_err(ret); + return ret; #endif } EXPORT_SYMBOL_GPL(tpm_buf_append_name); @@ -613,22 +603,8 @@ int tpm_buf_fill_hmac_session(struct tpm_chip *chip, s= truct tpm_buf *buf) attrs =3D chip->cc_attrs_tbl[i]; =20 handles =3D (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0); + offset_s +=3D handles * sizeof(u32); =20 - /* - * just check the names, it's easy to make mistakes. This - * would happen if someone added a handle via - * tpm_buf_append_u32() instead of tpm_buf_append_name() - */ - for (i =3D 0; i < handles; i++) { - u32 handle =3D tpm_buf_read_u32(buf, &offset_s); - - if (auth->name_h[i] !=3D handle) { - dev_err(&chip->dev, "invalid handle 0x%08x\n", handle); - ret =3D -EIO; - goto err; - } - } - /* point offset_s to the start of the sessions */ val =3D tpm_buf_read_u32(buf, &offset_s); /* point offset_p to the start of the parameters */ offset_p =3D offset_s + val; @@ -689,23 +665,8 @@ int tpm_buf_fill_hmac_session(struct tpm_chip *chip, s= truct tpm_buf *buf) /* ordinal is already BE */ sha256_update(&sctx, (u8 *)&head->ordinal, sizeof(head->ordinal)); /* add the handle names */ - for (i =3D 0; i < handles; i++) { - enum tpm2_mso_type mso =3D tpm2_handle_mso(auth->name_h[i]); - - if (mso =3D=3D TPM2_MSO_PERSISTENT || - mso =3D=3D TPM2_MSO_VOLATILE || - mso =3D=3D TPM2_MSO_NVRAM) { - ret =3D name_size(auth->name[i]); - if (ret < 0) - goto err; - - sha256_update(&sctx, auth->name[i], ret); - } else { - __be32 h =3D cpu_to_be32(auth->name_h[i]); - - sha256_update(&sctx, (u8 *)&h, 4); - } - } + for (i =3D 0; i < handles; i++) + sha256_update(&sctx, auth->name[i], auth->name_size_tbl[i]); if (offset_s !=3D tpm_buf_length(buf)) sha256_update(&sctx, &buf->data[offset_s], tpm_buf_length(buf) - offset_s); diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 8b82290de99f..7468709ad245 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -543,7 +543,7 @@ static inline struct tpm2_auth *tpm2_chip_auth(struct t= pm_chip *chip) } =20 int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf, - u32 handle, u8 *name); + u32 handle, u8 *name, u16 name_size); void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *bu= f, u8 attributes, u8 *passphrase, int passphraselen); @@ -557,6 +557,7 @@ int tpm_buf_fill_hmac_session(struct tpm_chip *chip, st= ruct tpm_buf *buf); int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf, int rc); void tpm2_end_auth_session(struct tpm_chip *chip); +int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name); #else #include =20 @@ -580,6 +581,13 @@ static inline int tpm_buf_check_hmac_response(struct t= pm_chip *chip, { return rc; } + +static inline int tpm2_read_public(struct tpm_chip *chip, u32 handle, + void *name) +{ + memcpy(name, &handle, sizeof(u32)); + return sizeof(u32); +} #endif /* CONFIG_TCG_TPM2_HMAC */ =20 #endif diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trus= ted-keys/trusted_tpm2.c index ec84ea945d3b..dbacebe7af56 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -203,8 +203,10 @@ int tpm2_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, struct trusted_key_options *options) { + u8 parent_name[TPM2_MAX_NAME_SIZE]; off_t offset =3D TPM_HEADER_SIZE; struct tpm_buf buf, sized; + u16 parent_name_size; int blob_len =3D 0; int hash; u32 flags; @@ -221,6 +223,12 @@ int tpm2_seal_trusted(struct tpm_chip *chip, if (rc) return rc; =20 + rc =3D tpm2_read_public(chip, options->keyhandle, parent_name); + if (rc < 0) + goto out_put; + + parent_name_size =3D rc; + rc =3D tpm2_start_auth_session(chip); if (rc) goto out_put; @@ -238,7 +246,8 @@ int tpm2_seal_trusted(struct tpm_chip *chip, goto out_put; } =20 - rc =3D tpm_buf_append_name(chip, &buf, options->keyhandle, NULL); + rc =3D tpm_buf_append_name(chip, &buf, options->keyhandle, parent_name, + parent_name_size); if (rc) goto out; =20 @@ -325,21 +334,25 @@ int tpm2_seal_trusted(struct tpm_chip *chip, } =20 /** - * tpm2_load_cmd() - execute a TPM2_Load command - * - * @chip: TPM chip to use - * @payload: the key data in clear and encrypted form - * @options: authentication values and other options - * @blob_handle: returned blob handle + * tpm2_load_cmd() - Execute TPM2_Load + * @chip: TPM chip to use. + * @payload: Key data in clear text. + * @options: Trusted key options. + * @parent_name: A cryptographic name, i.e. a TPMT_HA blob, of the + * parent key. + * @blob: The decoded payload for the key. + * @blob_handle: On success, will contain handle to the loaded keyedhash + * blob. * - * Return: 0 on success. - * -E2BIG on wrong payload size. - * -EPERM on tpm error status. - * < 0 error from tpm_send. + * Return -E2BIG when the blob size is too small for all the data. + * Returns tpm_transmit_cmd() error codes when either TPM2_Load fails. */ static int tpm2_load_cmd(struct tpm_chip *chip, struct trusted_key_payload *payload, struct trusted_key_options *options, + u8 *parent_name, + u16 parent_name_size, + const u8 *blob, u32 *blob_handle) { u8 *blob_ref __free(kfree) =3D NULL; @@ -347,27 +360,13 @@ static int tpm2_load_cmd(struct tpm_chip *chip, unsigned int private_len; unsigned int public_len; unsigned int blob_len; - u8 *blob, *pub; + const u8 *pub; int rc; u32 attrs; =20 - rc =3D tpm2_key_decode(payload, options, &blob); - if (rc) { - /* old form */ - blob =3D payload->blob; - payload->old_format =3D 1; - } else { - /* Bind for cleanup: */ - blob_ref =3D blob; - } - - /* new format carries keyhandle but old format doesn't */ - if (!options->keyhandle) - return -EINVAL; - /* must be big enough for at least the two be16 size counts */ if (payload->blob_len < 4) - return -EINVAL; + return -E2BIG; =20 private_len =3D get_unaligned_be16(blob); =20 @@ -403,7 +402,8 @@ static int tpm2_load_cmd(struct tpm_chip *chip, return rc; } =20 - rc =3D tpm_buf_append_name(chip, &buf, options->keyhandle, NULL); + rc =3D tpm_buf_append_name(chip, &buf, options->keyhandle, parent_name, + parent_name_size); if (rc) goto out; =20 @@ -437,18 +437,21 @@ static int tpm2_load_cmd(struct tpm_chip *chip, /** * tpm2_unseal_cmd() - execute a TPM2_Unseal command * - * @chip: TPM chip to use - * @payload: the key data in clear and encrypted form - * @options: authentication values and other options - * @blob_handle: blob handle + * @chip: TPM chip to use + * @payload: Key data in clear text. + * @options: Trusted key options. + * @parent_name: A cryptographic name, i.e. a TPMT_HA blob, of the + * parent key. + * @blob_handle: Handle to the loaded keyedhash blob. * - * Return: 0 on success - * -EPERM on tpm error status - * < 0 error from tpm_send + * Return -E2BIG when the blob size is too small for all the data. + * Returns tpm_transmit_cmd() error codes when either TPM2_Load fails. */ static int tpm2_unseal_cmd(struct tpm_chip *chip, struct trusted_key_payload *payload, struct trusted_key_options *options, + u8 *parent_name, + u16 parent_name_size, u32 blob_handle) { struct tpm_buf buf; @@ -466,7 +469,8 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, return rc; } =20 - rc =3D tpm_buf_append_name(chip, &buf, blob_handle, NULL); + rc =3D tpm_buf_append_name(chip, &buf, blob_handle, parent_name, + parent_name_size); if (rc) goto out; =20 @@ -539,30 +543,60 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, } =20 /** - * tpm2_unseal_trusted() - unseal the payload of a trusted key + * tpm2_unseal_trusted() - Unseal a trusted key + * @chip: TPM chip to use. + * @payload: Key data in clear text. + * @options: Trusted key options. * - * @chip: TPM chip to use - * @payload: the key data in clear and encrypted form - * @options: authentication values and other options - * - * Return: Same as with tpm_send. + * Return -E2BIG when the blob size is too small for all the data. + * Return -EINVAL when parent's key handle has not been set. + * Returns tpm_transmit_cmd() error codes when either TPM2_Load or TPM2_Un= seal + * fails. */ int tpm2_unseal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, struct trusted_key_options *options) { + u8 *blob_ref __free(kfree) =3D NULL; + u8 parent_name[TPM2_MAX_NAME_SIZE]; + u16 parent_name_size; u32 blob_handle; + u8 *blob; int rc; =20 + /* + * Try to decode the provided blob as an ASN.1 blob. Assume that the + * blob is in the legacy format if decoding does not end successfully. + */ + rc =3D tpm2_key_decode(payload, options, &blob); + if (rc) { + blob =3D payload->blob; + payload->old_format =3D 1; + } else { + blob_ref =3D blob; + } + + if (!options->keyhandle) + return -EINVAL; + rc =3D tpm_try_get_ops(chip); if (rc) return rc; =20 - rc =3D tpm2_load_cmd(chip, payload, options, &blob_handle); + rc =3D tpm2_read_public(chip, options->keyhandle, parent_name); + if (rc < 0) + goto out; + + parent_name_size =3D rc; + + rc =3D tpm2_load_cmd(chip, payload, options, parent_name, + parent_name_size, blob, &blob_handle); if (rc) goto out; =20 - rc =3D tpm2_unseal_cmd(chip, payload, options, blob_handle); + rc =3D tpm2_unseal_cmd(chip, payload, options, parent_name, + parent_name_size, blob_handle); + tpm2_flush_context(chip, blob_handle); =20 out: --=20 2.52.0 From nobody Sat Feb 7 11:31:23 2026 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 28DED2F3624; Sun, 25 Jan 2026 19:26:16 +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=1769369177; cv=none; b=NfSkGi3RRV2Qp756vkIie+Iw7zCVxIwJIRx6WKlqJmzho5sj/VSEs732irX3THIsc5iw2p57IKfkldM/58Q7+41VbEYDA2LvJrUxf1wgXSh2JuPZ8Zf+W3Twn3MpUAz5cvWgdtKLdfESOgUATOqYRKLHV0MDN2KFu3IEY9CjLJk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769369177; c=relaxed/simple; bh=aXQfxPS2rYt4dCKnmK7yVDCoe3TennDTezNwa0WX72g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Z9ZR8DhGYSfJns3xeUqQc+6QkOYTp0rCRKduh4IzFXSMzUDco8FFl/cN49/J8o5JiGKuOg9D/M/VBLJ2iDbvl5WxDeE1ZqEpO/voLE3mCjlR+cgxm08aVIwvY+brazdRQXevGIJTtgwbYO5KzAyXGxhaXz20L0oinZoJunX7QcM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=S/mIy7I/; 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="S/mIy7I/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2B9A0C19425; Sun, 25 Jan 2026 19:26:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769369176; bh=aXQfxPS2rYt4dCKnmK7yVDCoe3TennDTezNwa0WX72g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S/mIy7I/ZeyE8U4A5GZIaQPwAnN+VrhW5cmp3cVBX3MGmvHnmu9b77yoEpgxHDRG5 6pctP8Uh6ni6NVY1QedbgzmshDWziyvWl/LBDz9G9kbU9gDHknKJNELjl3meCX5us9 DWinjJ50hn2M/NjkUEFSPO25sdGJmnMJrOQ2YWLIL0v8HlafAfcvkpcQBrXsoH9ADp DX7lbXBAnNVGiUoWb0VGKDlVm7po6TunznGjeciytwYKXbm5PzK3Vsq8nBAAhfKhy7 JRM6GP5uvQEffOVe3+WMx8LJl9X2Ch6kda7Uqq99M2J2E22j6rtHcHLuvapqiXfbZe E467VfzICmguQ== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v9 08/11] tpm2-sessions: Remove the support for more than one authorization Date: Sun, 25 Jan 2026 21:25:18 +0200 Message-ID: <20260125192526.782202-9-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260125192526.782202-1-jarkko@kernel.org> References: <20260125192526.782202-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" Kernel uses at most a single HMAC authorization at a time. From that basis, remove the unused machinery for managing multiple authorizations. Signed-off-by: Jarkko Sakkinen --- v8: - Rewrote the commit message. - Added an inline comment explaining why unconditional sha256_update() call for the name is safe. --- drivers/char/tpm/tpm2-sessions.c | 40 ++++++++++++++------------------ 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessi= ons.c index 3bc3c31cf512..98cea20040cf 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -72,9 +72,6 @@ #include #include =20 -/* maximum number of names the TPM must remember for authorization */ -#define AUTH_MAX_NAMES 3 - #define AES_KEY_BYTES AES_KEYSIZE_128 #define AES_KEY_BITS (AES_KEY_BYTES*8) =20 @@ -136,8 +133,8 @@ struct tpm2_auth { * handle, but they are part of the session by name, which * we must compute and remember */ - u8 name[AUTH_MAX_NAMES][TPM2_MAX_NAME_SIZE]; - u16 name_size_tbl[AUTH_MAX_NAMES]; + u8 name[TPM2_MAX_NAME_SIZE]; + u16 name_size; }; =20 #ifdef CONFIG_TCG_TPM2_HMAC @@ -261,11 +258,14 @@ EXPORT_SYMBOL_GPL(tpm2_read_public); int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf, u32 handle, u8 *name, u16 name_size) { -#ifdef CONFIG_TCG_TPM2_HMAC struct tpm2_auth *auth; - int slot; int ret; -#endif + + if (tpm_buf_length(buf) !=3D TPM_HEADER_SIZE) { + dev_err(&chip->dev, "too many handles\n"); + ret =3D -EIO; + goto err; + } =20 if (!tpm2_chip_auth(chip)) { tpm_buf_append_handle(chip, buf, handle); @@ -273,12 +273,6 @@ int tpm_buf_append_name(struct tpm_chip *chip, struct = tpm_buf *buf, } =20 #ifdef CONFIG_TCG_TPM2_HMAC - slot =3D (tpm_buf_length(buf) - TPM_HEADER_SIZE) / 4; - if (slot >=3D AUTH_MAX_NAMES) { - dev_err(&chip->dev, "too many handles\n"); - ret =3D -EIO; - goto err; - } auth =3D chip->auth; if (auth->session !=3D tpm_buf_length(buf)) { dev_err(&chip->dev, "session state malformed"); @@ -287,16 +281,14 @@ int tpm_buf_append_name(struct tpm_chip *chip, struct= tpm_buf *buf, } tpm_buf_append_u32(buf, handle); auth->session +=3D 4; - memcpy(auth->name[slot], name, name_size); - auth->name_size_tbl[slot] =3D name_size; + memcpy(auth->name, name, name_size); + auth->name_size =3D name_size; #endif return 0; =20 -#ifdef CONFIG_TCG_TPM2_HMAC err: tpm2_end_auth_session(chip); return ret; -#endif } EXPORT_SYMBOL_GPL(tpm_buf_append_name); =20 @@ -662,14 +654,18 @@ int tpm_buf_fill_hmac_session(struct tpm_chip *chip, = struct tpm_buf *buf) } =20 sha256_init(&sctx); - /* ordinal is already BE */ sha256_update(&sctx, (u8 *)&head->ordinal, sizeof(head->ordinal)); - /* add the handle names */ - for (i =3D 0; i < handles; i++) - sha256_update(&sctx, auth->name[i], auth->name_size_tbl[i]); + + /* + * If tpm2_buf_append_name() has not been called, this is a no-op, as + * auth->name_size is zero. + */ + sha256_update(&sctx, auth->name, auth->name_size); + if (offset_s !=3D tpm_buf_length(buf)) sha256_update(&sctx, &buf->data[offset_s], tpm_buf_length(buf) - offset_s); + sha256_final(&sctx, cphash); =20 /* now calculate the hmac */ --=20 2.52.0 From nobody Sat Feb 7 11:31:23 2026 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 BEFCE2F290B; Sun, 25 Jan 2026 19:26:21 +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=1769369181; cv=none; b=Elu3GwZyfN/ULw8m9rEP51KCHTfJIhRkqG57i7f7QVtI5pRQI0M/GwLwHdEVDhjC8KdXEfO+YFhuOa67lSs6IxfztxsMNKGEZ2cg5HWYYGTeA+ujd8wxvB/w2tt0HdKUVsm7sSNgzIFwN0ulFpARtadlVnlPspjozbKME5s0TXc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769369181; c=relaxed/simple; bh=hAibMHKe5lsseOF7PKJqEcBja5cZhJFoF0G/DdHMARY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tyUzhKQs/un0WmQnT6+5G6JYSxNmlXLqlBUiyUP+TcF+dJLVkN954RhgGoUD/ifU39bQZaPKJwth59h/Vi60SWK4xW7dGq7OCsA3l+tF/zY9wInjLS6UYIaLkakxQYOno7phm5SWv3AB6ruxX7Tf7DFc7IX2BXfLD9AZzBFGpYQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=suYIXZY7; 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="suYIXZY7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 16CEAC4CEF1; Sun, 25 Jan 2026 19:26:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769369181; bh=hAibMHKe5lsseOF7PKJqEcBja5cZhJFoF0G/DdHMARY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=suYIXZY7/wLojcJL+p4F3tJFFEh1as8bXW+dBsQnVaIgej80di+VbbviLT/QscXHv zwsSbUe24KBwLH/0kGw1sUF0NJQjIbqPMQuk+ZyTZ7q+y37ag1vi0IRt7en01IZUxl i38PSr53GbuIac7WnRtUcHs6hu6Ygh3HgxCSvfVAGGZ9Cdspm/hu2dJOAVeEuMoz01 77oz0x1xk48xRAxXHgarnd+Zs7YYMqdqXS7DSC8Cg6keLdUjUNGamqPwCJartNvupt jBlG+Jvgozht0yoNa+AxETKD4F4fs2PJ67rlCSzsoyKDW2Aj678N0vc3xIlywDfIi+ oBxWmUwy37BiA== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v9 09/11] tpm-buf: Remove tpm_buf_append_handle Date: Sun, 25 Jan 2026 21:25:19 +0200 Message-ID: <20260125192526.782202-10-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260125192526.782202-1-jarkko@kernel.org> References: <20260125192526.782202-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" Since the number of handles is fixed to a single handle, eliminate all uses of buf->handles and deduce values during compile-time. Signed-off-by: Jarkko Sakkinen --- v2: - Streamline the code change and remove dead code. --- drivers/char/tpm/tpm-buf.c | 23 ----------------------- drivers/char/tpm/tpm2-cmd.c | 2 +- drivers/char/tpm/tpm2-sessions.c | 14 ++------------ include/linux/tpm.h | 2 -- 4 files changed, 3 insertions(+), 38 deletions(-) diff --git a/drivers/char/tpm/tpm-buf.c b/drivers/char/tpm/tpm-buf.c index dc882fc9fa9e..1d2b87455d3a 100644 --- a/drivers/char/tpm/tpm-buf.c +++ b/drivers/char/tpm/tpm-buf.c @@ -44,7 +44,6 @@ void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordi= nal) head->tag =3D cpu_to_be16(tag); head->length =3D cpu_to_be32(sizeof(*head)); head->ordinal =3D cpu_to_be32(ordinal); - buf->handles =3D 0; } EXPORT_SYMBOL_GPL(tpm_buf_reset); =20 @@ -146,26 +145,6 @@ void tpm_buf_append_u32(struct tpm_buf *buf, const u32= value) } EXPORT_SYMBOL_GPL(tpm_buf_append_u32); =20 -/** - * tpm_buf_append_handle() - Add a handle - * @chip: &tpm_chip instance - * @buf: &tpm_buf instance - * @handle: a TPM object handle - * - * Add a handle to the buffer, and increase the count tracking the number = of - * handles in the command buffer. Works only for command buffers. - */ -void tpm_buf_append_handle(struct tpm_chip *chip, struct tpm_buf *buf, u32= handle) -{ - if (buf->flags & TPM_BUF_TPM2B) { - dev_err(&chip->dev, "Invalid buffer type (TPM2B)\n"); - return; - } - - tpm_buf_append_u32(buf, handle); - buf->handles++; -} - /** * tpm_buf_read() - Read from a TPM buffer * @buf: &tpm_buf instance @@ -242,5 +221,3 @@ u32 tpm_buf_read_u32(struct tpm_buf *buf, off_t *offset) return be32_to_cpu(value); } EXPORT_SYMBOL_GPL(tpm_buf_read_u32); - - diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 96a45391036c..39ef6b7a0fbc 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -210,7 +210,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, } tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0); } else { - tpm_buf_append_handle(chip, &buf, pcr_idx); + tpm_buf_append_u32(&buf, pcr_idx); tpm_buf_append_auth(chip, &buf, NULL, 0); } =20 diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessi= ons.c index 98cea20040cf..016bed63a755 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -268,7 +268,7 @@ int tpm_buf_append_name(struct tpm_chip *chip, struct t= pm_buf *buf, } =20 if (!tpm2_chip_auth(chip)) { - tpm_buf_append_handle(chip, buf, handle); + tpm_buf_append_u32(buf, handle); return 0; } =20 @@ -295,17 +295,7 @@ EXPORT_SYMBOL_GPL(tpm_buf_append_name); void tpm_buf_append_auth(struct tpm_chip *chip, struct tpm_buf *buf, u8 *passphrase, int passphrase_len) { - /* offset tells us where the sessions area begins */ - int offset =3D buf->handles * 4 + TPM_HEADER_SIZE; - u32 len =3D 9 + passphrase_len; - - if (tpm_buf_length(buf) !=3D offset) { - /* not the first session so update the existing length */ - len +=3D get_unaligned_be32(&buf->data[offset]); - put_unaligned_be32(len, &buf->data[offset]); - } else { - tpm_buf_append_u32(buf, len); - } + tpm_buf_append_u32(buf, 9 + passphrase_len); /* auth handle */ tpm_buf_append_u32(buf, TPM2_RS_PW); /* nonce */ diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 7468709ad245..e8339f0c9a2e 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -397,7 +397,6 @@ struct tpm_buf { u32 flags; u32 length; u8 *data; - u8 handles; }; =20 enum tpm2_object_attributes { @@ -441,7 +440,6 @@ void tpm_buf_append_u32(struct tpm_buf *buf, const u32 = value); u8 tpm_buf_read_u8(struct tpm_buf *buf, off_t *offset); u16 tpm_buf_read_u16(struct tpm_buf *buf, off_t *offset); u32 tpm_buf_read_u32(struct tpm_buf *buf, off_t *offset); -void tpm_buf_append_handle(struct tpm_chip *chip, struct tpm_buf *buf, u32= handle); =20 /* * Check if TPM device is in the firmware upgrade mode. --=20 2.52.0 From nobody Sat Feb 7 11:31:23 2026 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 791262F12A5; Sun, 25 Jan 2026 19:26:26 +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=1769369186; cv=none; b=jPW3iF6CjQR1XQTs5q3t0RASoHKjwhYno3frSsCPUKG+SrGh+FbOuIsg0S9mFTT2cb2prsJiHaStT5KyjdB/rk7yEXZgME0zNCTKGPMLG0d1R4L4FphPKLmxVaDMYu0yejCZ+byvFSYUVzK+hLqXrayU3+/mCCzGnm180tCcq7s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769369186; c=relaxed/simple; bh=9w+/oURefUip/dy6+VaUNMG1zj0+wul0RQftvWiJcvI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gDkmT6dPfto5UWPhh+S2G4HQp7zkiULnSJCyPtpH4pY3jgqT3X3+OdD286T7UDnqduUlzB891Fvh+hAm5WjElOUmCV5QehrYXe0NhcL+4nP3UcKcI5U/6978wu6kuXad4gg9lSJyQuK9BFqWwXU3K4f5CA5tpOo9HOcEq49fR2M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=J+W1v6pf; 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="J+W1v6pf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C5322C4CEF1; Sun, 25 Jan 2026 19:26:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769369186; bh=9w+/oURefUip/dy6+VaUNMG1zj0+wul0RQftvWiJcvI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J+W1v6pfajC32luuFpH5LN1Lm2BUlpNawD1hLs2h2Q8sNLFU4FNS+XWfVqXXbsLWW XJjaNiEjgIH7mBuhvXdEKpfV1Ndho2+DPobBniPnaZy/E7nG4k+3RyZda8nb1bG6tC ers2pJ6K3m750SDNuIeLn9kQCxUINVqlxWtTpf5nw7I9t4ZqOq2Wst3zo6VQypm2jx ccWAJ8NQsN5wu15loQxM89WTtLH2TanIFlwQzpgW+2xlSZQgJYR5O9kF8y9Fn+9ISV xhDjfDTjB8KvZLfSAqpDdlX+GNiXXzaGYBNsGSGH4mQvbtJf8dJX6JbcG/eaP/xGcY Lb00MZz2hqdhw== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , Jonathan McDowell , James Bottomley , Jarkko Sakkinen , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v9 10/11] tpm-buf: Merge TPM_BUF_BOUNDARY_ERROR and TPM_BUF_OVERFLOW Date: Sun, 25 Jan 2026 21:25:20 +0200 Message-ID: <20260125192526.782202-11-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260125192526.782202-1-jarkko@kernel.org> References: <20260125192526.782202-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" From: Jarkko Sakkinen Merge TPM_BUF_BOUNDARY_ERROR and TPM_BUF_OVERFLOW into TPM_BUF_INVALID, given that they are identical. The only difference are the log messages. In addition, add a missing TPM_BUF_INVALID check to tpm_buf_append_handle() following the pattern from other functions in tpm-buf.c. Signed-off-by: Jarkko Sakkinen Reviewed-by: Jonathan McDowell --- drivers/char/tpm/tpm-buf.c | 10 ++++------ include/linux/tpm.h | 8 +++----- security/keys/trusted-keys/trusted_tpm2.c | 6 +++--- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/char/tpm/tpm-buf.c b/drivers/char/tpm/tpm-buf.c index 1d2b87455d3a..11b6bcf2f43d 100644 --- a/drivers/char/tpm/tpm-buf.c +++ b/drivers/char/tpm/tpm-buf.c @@ -103,13 +103,12 @@ EXPORT_SYMBOL_GPL(tpm_buf_length); */ void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_lengt= h) { - /* Return silently if overflow has already happened. */ - if (buf->flags & TPM_BUF_OVERFLOW) + if (buf->flags & TPM_BUF_INVALID) return; =20 if ((buf->length + new_length) > PAGE_SIZE) { WARN(1, "tpm_buf: write overflow\n"); - buf->flags |=3D TPM_BUF_OVERFLOW; + buf->flags |=3D TPM_BUF_INVALID; return; } =20 @@ -156,14 +155,13 @@ static void tpm_buf_read(struct tpm_buf *buf, off_t *= offset, size_t count, void { off_t next_offset; =20 - /* Return silently if overflow has already happened. */ - if (buf->flags & TPM_BUF_BOUNDARY_ERROR) + if (buf->flags & TPM_BUF_INVALID) return; =20 next_offset =3D *offset + count; if (next_offset > buf->length) { WARN(1, "tpm_buf: read out of boundary\n"); - buf->flags |=3D TPM_BUF_BOUNDARY_ERROR; + buf->flags |=3D TPM_BUF_INVALID; return; } =20 diff --git a/include/linux/tpm.h b/include/linux/tpm.h index e8339f0c9a2e..5a5d8e584e7b 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -382,12 +382,10 @@ struct tpm_header { } __packed; =20 enum tpm_buf_flags { - /* the capacity exceeded: */ - TPM_BUF_OVERFLOW =3D BIT(0), /* TPM2B format: */ - TPM_BUF_TPM2B =3D BIT(1), - /* read out of boundary: */ - TPM_BUF_BOUNDARY_ERROR =3D BIT(2), + TPM_BUF_TPM2B =3D BIT(0), + /* The buffer is in invalid and unusable state: */ + TPM_BUF_INVALID =3D BIT(1), }; =20 /* diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trus= ted-keys/trusted_tpm2.c index dbacebe7af56..8e694318b200 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -292,7 +292,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, /* creation PCR */ tpm_buf_append_u32(&buf, 0); =20 - if (buf.flags & TPM_BUF_OVERFLOW) { + if (buf.flags & TPM_BUF_INVALID) { rc =3D -E2BIG; tpm2_end_auth_session(chip); goto out; @@ -308,7 +308,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, goto out; =20 blob_len =3D tpm_buf_read_u32(&buf, &offset); - if (blob_len > MAX_BLOB_SIZE || buf.flags & TPM_BUF_BOUNDARY_ERROR) { + if (blob_len > MAX_BLOB_SIZE || buf.flags & TPM_BUF_INVALID) { rc =3D -E2BIG; goto out; } @@ -412,7 +412,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip, =20 tpm_buf_append(&buf, blob, blob_len); =20 - if (buf.flags & TPM_BUF_OVERFLOW) { + if (buf.flags & TPM_BUF_INVALID) { rc =3D -E2BIG; tpm2_end_auth_session(chip); goto out; --=20 2.52.0 From nobody Sat Feb 7 11:31:23 2026 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 800BC2F12A5; Sun, 25 Jan 2026 19:26:31 +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=1769369191; cv=none; b=c98dAHzVz4zmcCqy1Y9TAcnFaOJUhNgGlJDwBSJ+wPBQW5sW0FGWFXdAXhUTIudv44exyaUCOO2PkF+FbV1fln5rIfVJTmZoqA/XUPSl2yBxuJNs+4fIJVv1Ly450703fDwJJyd87Fd/hcbbCWRrEpsZsywz3fYaJxj6PenjHRs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769369191; c=relaxed/simple; bh=S1k/E3edQq0/7U0WnsXms/JU1iPafIt09BZ3DQeXn8k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qIy9iufUvvC+DdaanorxWyH1gG97rfbFtvrbpg8TXGFXfku5soZCKkkxDyVOcH4jNm8eLlS10PkgbIdjjTKT0+T6tcsl67YjloLzsN/FeA836cxvb1+c3c75gQ98NbIZ3C9qaCs9G0l9IEXWjbA8xBwjog6TylY0FiWdMSfrXzk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=E+KFn88r; 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="E+KFn88r" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7D907C4CEF1; Sun, 25 Jan 2026 19:26:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769369191; bh=S1k/E3edQq0/7U0WnsXms/JU1iPafIt09BZ3DQeXn8k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=E+KFn88rl9hFG0Ru5KliBB1UVrVBkCSdVAeERklpCZ2a8C3x7Pt9+PGgaDqaOpMwc JWW1qwDdmtZPwOIK81GR1srh4y68E0kMsHwq8EvlTlMbXzx4YGoQfweJbK8x6vsKB5 Nrlz23udSqISdsgQr4FTOgYpNBQmUJee8VlZljmvcN0gCRFH4zBX0yM68JvWMNbi8Y zD8qsA1tGh+WTzuIujiiWADdCJ5ylQVLwDbAIHCtTpYIFOnzysROAO6EYJ2tZ0Mu8O vgMlWOyn7DfQfszaSHAo6SXCsASeU8iXWofRTHTGDrwphP6Nq0zEuYWB687y4KT752 TcpGVaRRqPXHA== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , Ross Philipson , Stefan Berger , James Bottomley , Jarkko Sakkinen , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v9 11/11] tpm-buf: Implement managed allocations Date: Sun, 25 Jan 2026 21:25:21 +0200 Message-ID: <20260125192526.782202-12-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260125192526.782202-1-jarkko@kernel.org> References: <20260125192526.782202-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" From: Jarkko Sakkinen Decouple kzalloc from buffer creation, so that a managed allocation can be used: struct tpm_buf *buf __free(kfree) buf =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); if (!buf) return -ENOMEM; tpm_buf_init(buf, TPM_BUFSIZE); Alternatively, stack allocations are also possible: u8 buf_data[512]; struct tpm_buf *buf =3D (struct tpm_buf *)buf_data; tpm_buf_init(buf, sizeof(buf_data)); This is achieved by embedding buffer's header inside the allocated blob, instead of having an outer wrapper. Cc: Ross Philipson Signed-off-by: Jarkko Sakkinen Reviewed-by: Stefan Berger --- drivers/char/tpm/tpm-buf.c | 123 +++++---- drivers/char/tpm/tpm-sysfs.c | 21 +- drivers/char/tpm/tpm.h | 1 - drivers/char/tpm/tpm1-cmd.c | 163 +++++------- drivers/char/tpm/tpm2-cmd.c | 298 ++++++++++------------ drivers/char/tpm/tpm2-sessions.c | 142 +++++------ drivers/char/tpm/tpm2-space.c | 44 ++-- drivers/char/tpm/tpm_vtpm_proxy.c | 30 +-- include/linux/tpm.h | 20 +- security/keys/trusted-keys/trusted_tpm1.c | 36 +-- security/keys/trusted-keys/trusted_tpm2.c | 173 ++++++------- 11 files changed, 499 insertions(+), 552 deletions(-) diff --git a/drivers/char/tpm/tpm-buf.c b/drivers/char/tpm/tpm-buf.c index 11b6bcf2f43d..042da92f94e1 100644 --- a/drivers/char/tpm/tpm-buf.c +++ b/drivers/char/tpm/tpm-buf.c @@ -7,81 +7,107 @@ #include #include =20 -/** - * tpm_buf_init() - Allocate and initialize a TPM command - * @buf: A &tpm_buf - * @tag: TPM_TAG_RQU_COMMAND, TPM2_ST_NO_SESSIONS or TPM2_ST_SESSIONS - * @ordinal: A command ordinal - * - * Return: 0 or -ENOMEM - */ -int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) +static void __tpm_buf_size_invariant(struct tpm_buf *buf, u16 buf_size) { - buf->data =3D (u8 *)__get_free_page(GFP_KERNEL); - if (!buf->data) - return -ENOMEM; - - tpm_buf_reset(buf, tag, ordinal); - return 0; + u32 buf_size_2 =3D (u32)buf->capacity + (u32)sizeof(*buf); + + if (!buf->capacity) { + if (buf_size > TPM_BUFSIZE) { + WARN(1, "%s: size overflow: %u\n", __func__, buf_size); + buf->flags |=3D TPM_BUF_INVALID; + } + } else { + if (buf_size !=3D buf_size_2) { + WARN(1, "%s: size mismatch: %u !=3D %u\n", __func__, buf_size, + buf_size_2); + buf->flags |=3D TPM_BUF_INVALID; + } + } } -EXPORT_SYMBOL_GPL(tpm_buf_init); =20 -/** - * tpm_buf_reset() - Initialize a TPM command - * @buf: A &tpm_buf - * @tag: TPM_TAG_RQU_COMMAND, TPM2_ST_NO_SESSIONS or TPM2_ST_SESSIONS - * @ordinal: A command ordinal - */ -void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal) +static void __tpm_buf_reset(struct tpm_buf *buf, u16 buf_size, u16 tag, u3= 2 ordinal) { struct tpm_header *head =3D (struct tpm_header *)buf->data; =20 + __tpm_buf_size_invariant(buf, buf_size); + + if (buf->flags & TPM_BUF_INVALID) + return; + WARN_ON(tag !=3D TPM_TAG_RQU_COMMAND && tag !=3D TPM2_ST_NO_SESSIONS && tag !=3D TPM2_ST_SESSIONS && tag !=3D 0); =20 buf->flags =3D 0; buf->length =3D sizeof(*head); + buf->capacity =3D buf_size - sizeof(*buf); head->tag =3D cpu_to_be16(tag); head->length =3D cpu_to_be32(sizeof(*head)); head->ordinal =3D cpu_to_be32(ordinal); } -EXPORT_SYMBOL_GPL(tpm_buf_reset); + +static void __tpm_buf_reset_sized(struct tpm_buf *buf, u16 buf_size) +{ + __tpm_buf_size_invariant(buf, buf_size); + + if (buf->flags & TPM_BUF_INVALID) + return; + + buf->flags =3D TPM_BUF_TPM2B; + buf->length =3D 2; + buf->capacity =3D buf_size - sizeof(*buf); + buf->data[0] =3D 0; + buf->data[1] =3D 0; +} =20 /** - * tpm_buf_init_sized() - Allocate and initialize a sized (TPM2B) buffer - * @buf: A @tpm_buf - * - * Return: 0 or -ENOMEM + * tpm_buf_init() - Initialize a TPM command + * @buf: A &tpm_buf + * @buf_size: Size of the buffer. */ -int tpm_buf_init_sized(struct tpm_buf *buf) +void tpm_buf_init(struct tpm_buf *buf, u16 buf_size) { - buf->data =3D (u8 *)__get_free_page(GFP_KERNEL); - if (!buf->data) - return -ENOMEM; + memset(buf, 0, buf_size); + __tpm_buf_reset(buf, buf_size, TPM_TAG_RQU_COMMAND, 0); +} +EXPORT_SYMBOL_GPL(tpm_buf_init); =20 - tpm_buf_reset_sized(buf); - return 0; +/** + * tpm_buf_init_sized() - Initialize a sized buffer + * @buf: A &tpm_buf + * @buf_size: Size of the buffer. + */ +void tpm_buf_init_sized(struct tpm_buf *buf, u16 buf_size) +{ + memset(buf, 0, buf_size); + __tpm_buf_reset_sized(buf, buf_size); } EXPORT_SYMBOL_GPL(tpm_buf_init_sized); =20 /** - * tpm_buf_reset_sized() - Initialize a sized buffer + * tpm_buf_reset() - Re-initialize a TPM command * @buf: A &tpm_buf + * @tag: TPM_TAG_RQU_COMMAND, TPM2_ST_NO_SESSIONS or TPM2_ST_SESSIONS + * @ordinal: A command ordinal */ -void tpm_buf_reset_sized(struct tpm_buf *buf) +void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal) { - buf->flags =3D TPM_BUF_TPM2B; - buf->length =3D 2; - buf->data[0] =3D 0; - buf->data[1] =3D 0; + u16 buf_size =3D buf->capacity + sizeof(*buf); + + __tpm_buf_reset(buf, buf_size, tag, ordinal); } -EXPORT_SYMBOL_GPL(tpm_buf_reset_sized); +EXPORT_SYMBOL_GPL(tpm_buf_reset); =20 -void tpm_buf_destroy(struct tpm_buf *buf) +/** + * tpm_buf_reset_sized() - Re-initialize a sized buffer + * @buf: A &tpm_buf + */ +void tpm_buf_reset_sized(struct tpm_buf *buf) { - free_page((unsigned long)buf->data); + u16 buf_size =3D buf->capacity + sizeof(*buf); + + __tpm_buf_reset_sized(buf, buf_size); } -EXPORT_SYMBOL_GPL(tpm_buf_destroy); +EXPORT_SYMBOL_GPL(tpm_buf_reset_sized); =20 /** * tpm_buf_length() - Return the number of bytes consumed by the data @@ -89,8 +115,11 @@ EXPORT_SYMBOL_GPL(tpm_buf_destroy); * * Return: The number of bytes consumed by the buffer */ -u32 tpm_buf_length(struct tpm_buf *buf) +u16 tpm_buf_length(struct tpm_buf *buf) { + if (buf->flags & TPM_BUF_INVALID) + return 0; + return buf->length; } EXPORT_SYMBOL_GPL(tpm_buf_length); @@ -103,10 +132,12 @@ EXPORT_SYMBOL_GPL(tpm_buf_length); */ void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_lengt= h) { + u32 total_length =3D (u32)buf->length + (u32)new_length; + if (buf->flags & TPM_BUF_INVALID) return; =20 - if ((buf->length + new_length) > PAGE_SIZE) { + if (total_length > (u32)buf->capacity) { WARN(1, "tpm_buf: write overflow\n"); buf->flags |=3D TPM_BUF_INVALID; return; diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 4a6a27ee295d..0f321c307bc6 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c @@ -32,28 +32,29 @@ struct tpm_readpubek_out { static ssize_t pubek_show(struct device *dev, struct device_attribute *att= r, char *buf) { - struct tpm_buf tpm_buf; struct tpm_readpubek_out *out; int i; char *str =3D buf; struct tpm_chip *chip =3D to_tpm_chip(dev); char anti_replay[20]; =20 + struct tpm_buf *tpm_buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL= ); + if (!tpm_buf) + return -ENOMEM; + memset(&anti_replay, 0, sizeof(anti_replay)); =20 if (tpm_try_get_ops(chip)) return 0; =20 - if (tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK)) - goto out_ops; - - tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay)); + tpm_buf_init(tpm_buf, TPM_BUFSIZE); + tpm_buf_reset(tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK); + tpm_buf_append(tpm_buf, anti_replay, sizeof(anti_replay)); =20 - if (tpm_transmit_cmd(chip, &tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE, - "attempting to read the PUBEK")) - goto out_buf; + if (tpm_transmit_cmd(chip, tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE, "TPM= _ReadPubek")) + goto out_ops; =20 - out =3D (struct tpm_readpubek_out *)&tpm_buf.data[10]; + out =3D (struct tpm_readpubek_out *)&tpm_buf->data[10]; str +=3D sprintf(str, "Algorithm: %4ph\n" @@ -71,8 +72,6 @@ static ssize_t pubek_show(struct device *dev, struct devi= ce_attribute *attr, for (i =3D 0; i < 256; i +=3D 16) str +=3D sprintf(str, "%16ph\n", &out->modulus[i]); =20 -out_buf: - tpm_buf_destroy(&tpm_buf); out_ops: tpm_put_ops(chip); return str - buf; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 02c07fef41ba..5395927c62fc 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -32,7 +32,6 @@ #endif =20 #define TPM_MINOR 224 /* officially assigned */ -#define TPM_BUFSIZE 4096 #define TPM_NUM_DEVICES 65536 #define TPM_RETRY 50 =20 diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c index 3fe94f596f97..a04abe13a764 100644 --- a/drivers/char/tpm/tpm1-cmd.c +++ b/drivers/char/tpm/tpm1-cmd.c @@ -323,20 +323,14 @@ unsigned long tpm1_calc_ordinal_duration(struct tpm_c= hip *chip, u32 ordinal) */ static int tpm1_startup(struct tpm_chip *chip) { - struct tpm_buf buf; - int rc; - - dev_info(&chip->dev, "starting up the TPM manually\n"); - - rc =3D tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP); - if (rc < 0) - return rc; - - tpm_buf_append_u16(&buf, TPM_ST_CLEAR); - - rc =3D tpm_transmit_cmd(chip, &buf, 0, "attempting to start the TPM"); - tpm_buf_destroy(&buf); - return rc; + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP); + tpm_buf_append_u16(buf, TPM_ST_CLEAR); + return tpm_transmit_cmd(chip, buf, 0, "TPM_Startup"); } =20 int tpm1_get_timeouts(struct tpm_chip *chip) @@ -463,50 +457,47 @@ int tpm1_get_timeouts(struct tpm_chip *chip) int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash, const char *log_msg) { - struct tpm_buf buf; - int rc; - - rc =3D tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND); - if (rc) - return rc; - - tpm_buf_append_u32(&buf, pcr_idx); - tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE); - - rc =3D tpm_transmit_cmd(chip, &buf, TPM_DIGEST_SIZE, log_msg); - tpm_buf_destroy(&buf); - return rc; + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND); + tpm_buf_append_u32(buf, pcr_idx); + tpm_buf_append(buf, hash, TPM_DIGEST_SIZE); + return tpm_transmit_cmd(chip, buf, TPM_DIGEST_SIZE, log_msg); } =20 #define TPM_ORD_GET_CAP 101 ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, const char *desc, size_t min_cap_length) { - struct tpm_buf buf; int rc; =20 - rc =3D tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP); =20 if (subcap_id =3D=3D TPM_CAP_VERSION_1_1 || subcap_id =3D=3D TPM_CAP_VERSION_1_2) { - tpm_buf_append_u32(&buf, subcap_id); - tpm_buf_append_u32(&buf, 0); + tpm_buf_append_u32(buf, subcap_id); + tpm_buf_append_u32(buf, 0); } else { if (subcap_id =3D=3D TPM_CAP_FLAG_PERM || subcap_id =3D=3D TPM_CAP_FLAG_VOL) - tpm_buf_append_u32(&buf, TPM_CAP_FLAG); + tpm_buf_append_u32(buf, TPM_CAP_FLAG); else - tpm_buf_append_u32(&buf, TPM_CAP_PROP); + tpm_buf_append_u32(buf, TPM_CAP_PROP); =20 - tpm_buf_append_u32(&buf, 4); - tpm_buf_append_u32(&buf, subcap_id); + tpm_buf_append_u32(buf, 4); + tpm_buf_append_u32(buf, subcap_id); } - rc =3D tpm_transmit_cmd(chip, &buf, min_cap_length, desc); + rc =3D tpm_transmit_cmd(chip, buf, min_cap_length, desc); if (!rc) - *cap =3D *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4]; - tpm_buf_destroy(&buf); + *cap =3D *(cap_t *)&buf->data[TPM_HEADER_SIZE + 4]; return rc; } EXPORT_SYMBOL_GPL(tpm1_getcap); @@ -526,74 +517,61 @@ struct tpm1_get_random_out { int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max) { struct tpm1_get_random_out *resp; - struct tpm_buf buf; u32 recd; int rc; =20 if (!dest || !max || max > TPM_MAX_RNG_DATA) return -EINVAL; =20 - rc =3D tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; =20 - tpm_buf_append_u32(&buf, max); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); + tpm_buf_append_u32(buf, max); =20 - rc =3D tpm_transmit_cmd(chip, &buf, sizeof(resp->rng_data_len), "TPM_GetR= andom"); + rc =3D tpm_transmit_cmd(chip, buf, sizeof(resp->rng_data_len), "TPM_GetRa= ndom"); if (rc) { if (rc > 0) rc =3D -EIO; - goto out; + return rc; } =20 - resp =3D (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE]; + resp =3D (struct tpm1_get_random_out *)&buf->data[TPM_HEADER_SIZE]; =20 recd =3D be32_to_cpu(resp->rng_data_len); - if (recd > max) { - rc =3D -EIO; - goto out; - } + if (recd > max) + return -EIO; =20 - if (buf.length < TPM_HEADER_SIZE + sizeof(resp->rng_data_len) + recd) { - rc =3D -EIO; - goto out; - } + if (buf->length < TPM_HEADER_SIZE + sizeof(resp->rng_data_len) + recd) + return -EIO; =20 memcpy(dest, resp->rng_data, recd); - tpm_buf_destroy(&buf); return recd; - -out: - tpm_buf_destroy(&buf); - return rc; } =20 #define TPM_ORD_PCRREAD 21 int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) { - struct tpm_buf buf; int rc; =20 - rc =3D tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCRREAD); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; =20 - tpm_buf_append_u32(&buf, pcr_idx); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCRREAD); + tpm_buf_append_u32(buf, pcr_idx); =20 - rc =3D tpm_transmit_cmd(chip, &buf, TPM_DIGEST_SIZE, - "attempting to read a pcr value"); + rc =3D tpm_transmit_cmd(chip, buf, TPM_DIGEST_SIZE, "TPM_PCRRead"); if (rc) - goto out; - - if (tpm_buf_length(&buf) < TPM_DIGEST_SIZE) { - rc =3D -EFAULT; - goto out; - } + return rc; =20 - memcpy(res_buf, &buf.data[TPM_HEADER_SIZE], TPM_DIGEST_SIZE); + if (buf->length < TPM_DIGEST_SIZE) + return -EFAULT; =20 -out: - tpm_buf_destroy(&buf); + memcpy(res_buf, &buf->data[TPM_HEADER_SIZE], TPM_DIGEST_SIZE); return rc; } =20 @@ -607,16 +585,13 @@ int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx,= u8 *res_buf) */ static int tpm1_continue_selftest(struct tpm_chip *chip) { - struct tpm_buf buf; - int rc; - - rc =3D tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; =20 - rc =3D tpm_transmit_cmd(chip, &buf, 0, "continue selftest"); - tpm_buf_destroy(&buf); - return rc; + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST); + return tpm_transmit_cmd(chip, buf, 0, "TPM_ContinueSelfTest"); } =20 /** @@ -730,22 +705,24 @@ int tpm1_auto_startup(struct tpm_chip *chip) int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr) { u8 dummy_hash[TPM_DIGEST_SIZE] =3D { 0 }; - struct tpm_buf buf; unsigned int try; int rc; =20 + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; =20 /* for buggy tpm, flush pcrs with extend to selected dummy */ if (tpm_suspend_pcr) rc =3D tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash, "extending dummy pcr before suspend"); =20 - rc =3D tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); - if (rc) - return rc; + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); + /* now do the actual savestate */ for (try =3D 0; try < TPM_RETRY; try++) { - rc =3D tpm_transmit_cmd(chip, &buf, 0, NULL); + rc =3D tpm_transmit_cmd(chip, buf, 0, NULL); /* * If the TPM indicates that it is too busy to respond to * this command then retry before giving up. It can take @@ -760,7 +737,7 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_susp= end_pcr) break; tpm_msleep(TPM_TIMEOUT_RETRY); =20 - tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); } =20 if (rc) @@ -770,8 +747,6 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_susp= end_pcr) dev_warn(&chip->dev, "TPM savestate took %dms\n", try * TPM_TIMEOUT_RETRY); =20 - tpm_buf_destroy(&buf); - return rc; } =20 diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 39ef6b7a0fbc..7455c492fc66 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -119,12 +119,15 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, { int i; int rc; - struct tpm_buf buf; struct tpm2_pcr_read_out *out; u8 pcr_select[TPM2_PCR_SELECT_MIN] =3D {0}; u16 digest_size; u16 expected_digest_size =3D 0; =20 + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (pcr_idx >=3D TPM2_PLATFORM_PCR) return -EINVAL; =20 @@ -139,36 +142,31 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, expected_digest_size =3D chip->allocated_banks[i].digest_size; } =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ); - if (rc) - return rc; + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ); =20 pcr_select[pcr_idx >> 3] =3D 1 << (pcr_idx & 0x7); =20 - tpm_buf_append_u32(&buf, 1); - tpm_buf_append_u16(&buf, digest->alg_id); - tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN); - tpm_buf_append(&buf, (const unsigned char *)pcr_select, + tpm_buf_append_u32(buf, 1); + tpm_buf_append_u16(buf, digest->alg_id); + tpm_buf_append_u8(buf, TPM2_PCR_SELECT_MIN); + tpm_buf_append(buf, (const unsigned char *)pcr_select, sizeof(pcr_select)); =20 - rc =3D tpm_transmit_cmd(chip, &buf, 0, "attempting to read a pcr value"); + rc =3D tpm_transmit_cmd(chip, buf, 0, "TPM2_PCR_Read"); if (rc) - goto out; + return rc; =20 - out =3D (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE]; + out =3D (struct tpm2_pcr_read_out *)&buf->data[TPM_HEADER_SIZE]; digest_size =3D be16_to_cpu(out->digest_size); if (digest_size > sizeof(digest->digest) || - (!digest_size_ptr && digest_size !=3D expected_digest_size)) { - rc =3D -EINVAL; - goto out; - } + (!digest_size_ptr && digest_size !=3D expected_digest_size)) + return -EINVAL; =20 if (digest_size_ptr) *digest_size_ptr =3D digest_size; =20 memcpy(digest->digest, out->digest, digest_size); -out: - tpm_buf_destroy(&buf); return rc; } =20 @@ -184,57 +182,53 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digests) { - struct tpm_buf buf; int rc; int i; =20 + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (!disable_pcr_integrity) { rc =3D tpm2_start_auth_session(chip); if (rc) return rc; } =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND); - if (rc) { - if (!disable_pcr_integrity) - tpm2_end_auth_session(chip); - return rc; - } + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND); =20 if (!disable_pcr_integrity) { - rc =3D tpm_buf_append_name(chip, &buf, pcr_idx, (u8 *)&pcr_idx, + rc =3D tpm_buf_append_name(chip, buf, pcr_idx, (u8 *)&pcr_idx, sizeof(u32)); - if (rc) { - tpm_buf_destroy(&buf); + if (rc) return rc; - } - tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0); + tpm_buf_append_hmac_session(chip, buf, 0, NULL, 0); } else { - tpm_buf_append_u32(&buf, pcr_idx); - tpm_buf_append_auth(chip, &buf, NULL, 0); + tpm_buf_append_u32(buf, pcr_idx); + tpm_buf_append_auth(chip, buf, NULL, 0); } =20 - tpm_buf_append_u32(&buf, chip->nr_allocated_banks); + tpm_buf_append_u32(buf, chip->nr_allocated_banks); =20 for (i =3D 0; i < chip->nr_allocated_banks; i++) { - tpm_buf_append_u16(&buf, digests[i].alg_id); - tpm_buf_append(&buf, (const unsigned char *)&digests[i].digest, + tpm_buf_append_u16(buf, digests[i].alg_id); + tpm_buf_append(buf, (const unsigned char *)&digests[i].digest, chip->allocated_banks[i].digest_size); } + if (buf->flags & TPM_BUF_INVALID) + return -EINVAL; =20 if (!disable_pcr_integrity) { - rc =3D tpm_buf_fill_hmac_session(chip, &buf); - if (rc) { - tpm_buf_destroy(&buf); + rc =3D tpm_buf_fill_hmac_session(chip, buf); + if (rc) return rc; - } } =20 - rc =3D tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value"); - if (!disable_pcr_integrity) - rc =3D tpm_buf_check_hmac_response(chip, &buf, rc); + rc =3D tpm_transmit_cmd(chip, buf, 0, "TPM2_PCR_Extend"); =20 - tpm_buf_destroy(&buf); + if (!disable_pcr_integrity) + rc =3D tpm_buf_check_hmac_response(chip, buf, rc); =20 return rc; } @@ -254,7 +248,6 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, si= ze_t max) { struct tpm2_get_random_out *resp; struct tpm_header *head; - struct tpm_buf buf; off_t offset; u32 recd; int err; @@ -266,32 +259,32 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, = size_t max) if (err) return err; =20 - err =3D tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM); - if (err) { + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { tpm2_end_auth_session(chip); - return err; + return -ENOMEM; } =20 + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM); if (tpm2_chip_auth(chip)) { - tpm_buf_append_hmac_session(chip, &buf, + 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 =3D (struct tpm_header *)buf->data; head->tag =3D cpu_to_be16(TPM2_ST_NO_SESSIONS); } - tpm_buf_append_u16(&buf, max); + tpm_buf_append_u16(buf, max); =20 - err =3D tpm_buf_fill_hmac_session(chip, &buf); - if (err) { - tpm_buf_destroy(&buf); + err =3D tpm_buf_fill_hmac_session(chip, buf); + if (err) return err; - } =20 - err =3D tpm_transmit_cmd(chip, &buf, offsetof(struct tpm2_get_random_out,= buffer), + err =3D tpm_transmit_cmd(chip, buf, offsetof(struct tpm2_get_random_out, = buffer), "TPM2_GetRandom"); =20 - err =3D tpm_buf_check_hmac_response(chip, &buf, err); + err =3D tpm_buf_check_hmac_response(chip, buf, err); if (err) { if (err > 0) err =3D -EIO; @@ -299,17 +292,17 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, = size_t max) goto out; } =20 - head =3D (struct tpm_header *)buf.data; + head =3D (struct tpm_header *)buf->data; offset =3D TPM_HEADER_SIZE; =20 /* Skip the parameter size field: */ if (be16_to_cpu(head->tag) =3D=3D TPM2_ST_SESSIONS) offset +=3D 4; =20 - resp =3D (struct tpm2_get_random_out *)&buf.data[offset]; + resp =3D (struct tpm2_get_random_out *)&buf->data[offset]; recd =3D min_t(u32, be16_to_cpu(resp->size), max); =20 - if (tpm_buf_length(&buf) < + if (tpm_buf_length(buf) < TPM_HEADER_SIZE + offsetof(struct tpm2_get_random_out, buffer) + recd= ) { err =3D -EIO; goto out; @@ -319,7 +312,6 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, si= ze_t max) return recd; =20 out: - tpm_buf_destroy(&buf); tpm2_end_auth_session(chip); return err; } @@ -331,20 +323,18 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, = size_t max) */ void tpm2_flush_context(struct tpm_chip *chip, u32 handle) { - struct tpm_buf buf; - int rc; - - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT); - if (rc) { + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n", handle); return; } =20 - tpm_buf_append_u32(&buf, handle); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT); + tpm_buf_append_u32(buf, handle); =20 - tpm_transmit_cmd(chip, &buf, 0, "flushing context"); - tpm_buf_destroy(&buf); + tpm_transmit_cmd(chip, buf, 0, "TPM2_FlushContext"); } EXPORT_SYMBOL_GPL(tpm2_flush_context); =20 @@ -371,19 +361,20 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 pr= operty_id, u32 *value, const char *desc) { struct tpm2_get_cap_out *out; - struct tpm_buf buf; int rc; =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); - if (rc) - return rc; - tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES); - tpm_buf_append_u32(&buf, property_id); - tpm_buf_append_u32(&buf, 1); - rc =3D tpm_transmit_cmd(chip, &buf, 0, NULL); + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); + tpm_buf_append_u32(buf, TPM2_CAP_TPM_PROPERTIES); + tpm_buf_append_u32(buf, property_id); + tpm_buf_append_u32(buf, 1); + rc =3D tpm_transmit_cmd(chip, buf, 0, NULL); if (!rc) { - out =3D (struct tpm2_get_cap_out *) - &buf.data[TPM_HEADER_SIZE]; + out =3D (struct tpm2_get_cap_out *)&buf->data[TPM_HEADER_SIZE]; /* * To prevent failing boot up of some systems, Infineon TPM2.0 * returns SUCCESS on TPM2_Startup in field upgrade mode. Also @@ -395,7 +386,6 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 prop= erty_id, u32 *value, else rc =3D -ENODATA; } - tpm_buf_destroy(&buf); return rc; } EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt); @@ -412,15 +402,14 @@ EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt); */ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) { - struct tpm_buf buf; - int rc; - - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN); - if (rc) + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) return; - tpm_buf_append_u16(&buf, shutdown_type); - tpm_transmit_cmd(chip, &buf, 0, "stopping the TPM"); - tpm_buf_destroy(&buf); + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN); + tpm_buf_append_u16(buf, shutdown_type); + tpm_transmit_cmd(chip, buf, 0, "TPM2_Shutdown"); } =20 /** @@ -438,20 +427,19 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdow= n_type) */ static int tpm2_do_selftest(struct tpm_chip *chip) { - struct tpm_buf buf; int full; int rc; =20 - for (full =3D 0; full < 2; full++) { - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST); - if (rc) - return rc; - - tpm_buf_append_u8(&buf, full); - rc =3D tpm_transmit_cmd(chip, &buf, 0, - "attempting the self test"); - tpm_buf_destroy(&buf); + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; =20 + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST); + for (full =3D 0; full < 2; full++) { + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST); + tpm_buf_append_u8(buf, full); + rc =3D tpm_transmit_cmd(chip, buf, 0, "TPM2_SelfTest"); if (rc =3D=3D TPM2_RC_TESTING) rc =3D TPM2_RC_SUCCESS; if (rc =3D=3D TPM2_RC_INITIALIZE || rc =3D=3D TPM2_RC_SUCCESS) @@ -476,23 +464,24 @@ static int tpm2_do_selftest(struct tpm_chip *chip) int tpm2_probe(struct tpm_chip *chip) { struct tpm_header *out; - struct tpm_buf buf; int rc; =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); - if (rc) - return rc; - tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES); - tpm_buf_append_u32(&buf, TPM_PT_TOTAL_COMMANDS); - tpm_buf_append_u32(&buf, 1); - rc =3D tpm_transmit_cmd(chip, &buf, 0, NULL); + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); + tpm_buf_append_u32(buf, TPM2_CAP_TPM_PROPERTIES); + tpm_buf_append_u32(buf, TPM_PT_TOTAL_COMMANDS); + tpm_buf_append_u32(buf, 1); + rc =3D tpm_transmit_cmd(chip, buf, 0, NULL); /* We ignore TPM return codes on purpose. */ if (rc >=3D 0) { - out =3D (struct tpm_header *)buf.data; + out =3D (struct tpm_header *)buf->data; if (be16_to_cpu(out->tag) =3D=3D TPM2_ST_NO_SESSIONS) chip->flags |=3D TPM_CHIP_FLAG_TPM2; } - tpm_buf_destroy(&buf); return 0; } EXPORT_SYMBOL_GPL(tpm2_probe); @@ -532,7 +521,6 @@ struct tpm2_pcr_selection { ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) { struct tpm2_pcr_selection pcr_selection; - struct tpm_buf buf; void *marker; void *end; void *pcr_select_offset; @@ -544,39 +532,37 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) int rc; int i =3D 0; =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; =20 - tpm_buf_append_u32(&buf, TPM2_CAP_PCRS); - tpm_buf_append_u32(&buf, 0); - tpm_buf_append_u32(&buf, 1); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); + tpm_buf_append_u32(buf, TPM2_CAP_PCRS); + tpm_buf_append_u32(buf, 0); + tpm_buf_append_u32(buf, 1); =20 - rc =3D tpm_transmit_cmd(chip, &buf, 9, "get tpm pcr allocation"); + rc =3D tpm_transmit_cmd(chip, buf, 9, "TPM2_GetCapability(PCRS)"); if (rc) - goto out; + return rc; =20 - nr_possible_banks =3D be32_to_cpup( - (__be32 *)&buf.data[TPM_HEADER_SIZE + 5]); + nr_possible_banks =3D be32_to_cpup((__be32 *)&buf->data[TPM_HEADER_SIZE += 5]); if (nr_possible_banks > TPM2_MAX_PCR_BANKS) { pr_err("tpm: out of bank capacity: %u > %u\n", nr_possible_banks, TPM2_MAX_PCR_BANKS); - rc =3D -ENOMEM; - goto out; + return -ENOMEM; } =20 - marker =3D &buf.data[TPM_HEADER_SIZE + 9]; + marker =3D &buf->data[TPM_HEADER_SIZE + 9]; =20 - rsp_len =3D be32_to_cpup((__be32 *)&buf.data[2]); - end =3D &buf.data[rsp_len]; + rsp_len =3D be32_to_cpup((__be32 *)&buf->data[2]); + end =3D &buf->data[rsp_len]; =20 for (i =3D 0; i < nr_possible_banks; i++) { pcr_select_offset =3D marker + offsetof(struct tpm2_pcr_selection, size_of_select); - if (pcr_select_offset >=3D end) { - rc =3D -EFAULT; - break; - } + if (pcr_select_offset >=3D end) + return -EFAULT; =20 memcpy(&pcr_selection, marker, sizeof(pcr_selection)); hash_alg =3D be16_to_cpu(pcr_selection.hash_alg); @@ -588,7 +574,7 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) =20 rc =3D tpm2_init_bank_info(chip, nr_alloc_banks); if (rc < 0) - break; + return rc; =20 nr_alloc_banks++; } @@ -600,21 +586,21 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) } =20 chip->nr_allocated_banks =3D nr_alloc_banks; -out: - tpm_buf_destroy(&buf); - - return rc; + return 0; } =20 int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) { - struct tpm_buf buf; u32 nr_commands; __be32 *attrs; u32 cc; int i; int rc; =20 + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + rc =3D tpm2_get_tpm_pt(chip, TPM_PT_TOTAL_COMMANDS, &nr_commands, NULL); if (rc) goto out; @@ -631,30 +617,24 @@ int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) goto out; } =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); - if (rc) - goto out; - - tpm_buf_append_u32(&buf, TPM2_CAP_COMMANDS); - tpm_buf_append_u32(&buf, TPM2_CC_FIRST); - tpm_buf_append_u32(&buf, nr_commands); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); + tpm_buf_append_u32(buf, TPM2_CAP_COMMANDS); + tpm_buf_append_u32(buf, TPM2_CC_FIRST); + tpm_buf_append_u32(buf, nr_commands); =20 - rc =3D tpm_transmit_cmd(chip, &buf, 9 + 4 * nr_commands, NULL); - if (rc) { - tpm_buf_destroy(&buf); + rc =3D tpm_transmit_cmd(chip, buf, 9 + 4 * nr_commands, NULL); + if (rc) goto out; - } =20 - if (nr_commands !=3D - be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE + 5])) { + if (nr_commands !=3D be32_to_cpup((__be32 *)&buf->data[TPM_HEADER_SIZE + = 5])) { rc =3D -EFAULT; - tpm_buf_destroy(&buf); goto out; } =20 chip->nr_commands =3D nr_commands; =20 - attrs =3D (__be32 *)&buf.data[TPM_HEADER_SIZE + 9]; + attrs =3D (__be32 *)&buf->data[TPM_HEADER_SIZE + 9]; for (i =3D 0; i < nr_commands; i++, attrs++) { chip->cc_attrs_tbl[i] =3D be32_to_cpup(attrs); cc =3D chip->cc_attrs_tbl[i] & 0xFFFF; @@ -666,8 +646,6 @@ int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) } } =20 - tpm_buf_destroy(&buf); - out: if (rc > 0) rc =3D -ENODEV; @@ -688,20 +666,14 @@ EXPORT_SYMBOL_GPL(tpm2_get_cc_attrs_tbl); =20 static int tpm2_startup(struct tpm_chip *chip) { - struct tpm_buf buf; - int rc; - - dev_info(&chip->dev, "starting up the TPM manually\n"); - - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP); - if (rc < 0) - return rc; - - tpm_buf_append_u16(&buf, TPM2_SU_CLEAR); - rc =3D tpm_transmit_cmd(chip, &buf, 0, "attempting to start the TPM"); - tpm_buf_destroy(&buf); - - return rc; + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP); + tpm_buf_append_u16(buf, TPM2_SU_CLEAR); + return tpm_transmit_cmd(chip, buf, 0, "TPM2_Startup"); } =20 /** diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessi= ons.c index 016bed63a755..0926da478932 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -175,7 +175,6 @@ int tpm2_read_public(struct tpm_chip *chip, u32 handle,= void *name) u32 mso =3D tpm2_handle_mso(handle); off_t offset =3D TPM_HEADER_SIZE; int rc, name_size_alg; - struct tpm_buf buf; =20 if (mso !=3D TPM2_MSO_PERSISTENT && mso !=3D TPM2_MSO_VOLATILE && mso !=3D TPM2_MSO_NVRAM) { @@ -183,47 +182,41 @@ int tpm2_read_public(struct tpm_chip *chip, u32 handl= e, void *name) return sizeof(u32); } =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; =20 - tpm_buf_append_u32(&buf, handle); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC); + tpm_buf_append_u32(buf, handle); =20 - rc =3D tpm_transmit_cmd(chip, &buf, 0, "TPM2_ReadPublic"); - if (rc) { - tpm_buf_destroy(&buf); + rc =3D tpm_transmit_cmd(chip, buf, 0, "TPM2_ReadPublic"); + if (rc) return tpm_ret_to_err(rc); - } =20 /* Skip TPMT_PUBLIC: */ - offset +=3D tpm_buf_read_u16(&buf, &offset); + offset +=3D tpm_buf_read_u16(buf, &offset); =20 /* * Ensure space for the length field of TPM2B_NAME and hashAlg field of * TPMT_HA (the extra four bytes). */ - if (offset + 4 > tpm_buf_length(&buf)) { - tpm_buf_destroy(&buf); + if (offset + 4 > tpm_buf_length(buf)) return -EIO; - } =20 - rc =3D tpm_buf_read_u16(&buf, &offset); - name_size_alg =3D name_size(&buf.data[offset]); + rc =3D tpm_buf_read_u16(buf, &offset); + name_size_alg =3D name_size(&buf->data[offset]); =20 if (name_size_alg < 0) return name_size_alg; =20 - if (rc !=3D name_size_alg) { - tpm_buf_destroy(&buf); + if (rc !=3D name_size_alg) return -EIO; - } =20 - if (offset + rc > tpm_buf_length(&buf)) { - tpm_buf_destroy(&buf); + if (offset + rc > tpm_buf_length(buf)) return -EIO; - } =20 - memcpy(name, &buf.data[offset], rc); + memcpy(name, &buf->data[offset], rc); return name_size_alg; } EXPORT_SYMBOL_GPL(tpm2_read_public); @@ -929,7 +922,6 @@ static int tpm2_load_null(struct tpm_chip *chip, u32 *n= ull_key) int tpm2_start_auth_session(struct tpm_chip *chip) { struct tpm2_auth *auth; - struct tpm_buf buf; u32 null_key; int rc; =20 @@ -938,6 +930,10 @@ int tpm2_start_auth_session(struct tpm_chip *chip) return 0; } =20 + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + auth =3D kzalloc(sizeof(*auth), GFP_KERNEL); if (!auth) return -ENOMEM; @@ -948,41 +944,37 @@ int tpm2_start_auth_session(struct tpm_chip *chip) =20 auth->session =3D TPM_HEADER_SIZE; =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_START_AUTH_SESS); - if (rc) - goto out; - + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_START_AUTH_SESS); /* salt key handle */ - tpm_buf_append_u32(&buf, null_key); + tpm_buf_append_u32(buf, null_key); /* bind key handle */ - tpm_buf_append_u32(&buf, TPM2_RH_NULL); + tpm_buf_append_u32(buf, TPM2_RH_NULL); /* nonce caller */ get_random_bytes(auth->our_nonce, sizeof(auth->our_nonce)); - tpm_buf_append_u16(&buf, sizeof(auth->our_nonce)); - tpm_buf_append(&buf, auth->our_nonce, sizeof(auth->our_nonce)); + tpm_buf_append_u16(buf, sizeof(auth->our_nonce)); + tpm_buf_append(buf, auth->our_nonce, sizeof(auth->our_nonce)); =20 /* append encrypted salt and squirrel away unencrypted in auth */ - tpm_buf_append_salt(&buf, chip, auth); + tpm_buf_append_salt(buf, chip, auth); /* session type (HMAC, audit or policy) */ - tpm_buf_append_u8(&buf, TPM2_SE_HMAC); + tpm_buf_append_u8(buf, TPM2_SE_HMAC); =20 /* symmetric encryption parameters */ /* symmetric algorithm */ - tpm_buf_append_u16(&buf, TPM_ALG_AES); + tpm_buf_append_u16(buf, TPM_ALG_AES); /* bits for symmetric algorithm */ - tpm_buf_append_u16(&buf, AES_KEY_BITS); + tpm_buf_append_u16(buf, AES_KEY_BITS); /* symmetric algorithm mode (must be CFB) */ - tpm_buf_append_u16(&buf, TPM_ALG_CFB); + tpm_buf_append_u16(buf, TPM_ALG_CFB); /* hash algorithm for session */ - tpm_buf_append_u16(&buf, TPM_ALG_SHA256); + tpm_buf_append_u16(buf, TPM_ALG_SHA256); =20 - rc =3D tpm_ret_to_err(tpm_transmit_cmd(chip, &buf, 0, "StartAuthSession")= ); + rc =3D tpm_ret_to_err(tpm_transmit_cmd(chip, buf, 0, "TPM2_StartAuthSessi= on")); tpm2_flush_context(chip, null_key); =20 if (rc =3D=3D TPM2_RC_SUCCESS) - rc =3D tpm2_parse_start_auth_session(auth, &buf); - - tpm_buf_destroy(&buf); + rc =3D tpm2_parse_start_auth_session(auth, buf); =20 if (rc =3D=3D TPM2_RC_SUCCESS) { chip->auth =3D auth; @@ -1204,18 +1196,18 @@ static int tpm2_create_primary(struct tpm_chip *chi= p, u32 hierarchy, u32 *handle, u8 *name) { int rc; - struct tpm_buf buf; - struct tpm_buf template; =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE_PRIMARY); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; =20 - rc =3D tpm_buf_init_sized(&template); - if (rc) { - tpm_buf_destroy(&buf); - return rc; - } + struct tpm_buf *template __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNE= L); + if (!template) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE_PRIMARY); + tpm_buf_init_sized(template, TPM_BUFSIZE); =20 /* * create the template. Note: in order for userspace to @@ -1227,75 +1219,71 @@ static int tpm2_create_primary(struct tpm_chip *chi= p, u32 hierarchy, */ =20 /* key type */ - tpm_buf_append_u16(&template, TPM_ALG_ECC); + tpm_buf_append_u16(template, TPM_ALG_ECC); =20 /* name algorithm */ - tpm_buf_append_u16(&template, TPM_ALG_SHA256); + tpm_buf_append_u16(template, TPM_ALG_SHA256); =20 /* object properties */ - tpm_buf_append_u32(&template, TPM2_OA_NULL_KEY); + tpm_buf_append_u32(template, TPM2_OA_NULL_KEY); =20 /* sauth policy (empty) */ - tpm_buf_append_u16(&template, 0); + tpm_buf_append_u16(template, 0); =20 /* BEGIN parameters: key specific; for ECC*/ =20 /* symmetric algorithm */ - tpm_buf_append_u16(&template, TPM_ALG_AES); + tpm_buf_append_u16(template, TPM_ALG_AES); =20 /* bits for symmetric algorithm */ - tpm_buf_append_u16(&template, AES_KEY_BITS); + tpm_buf_append_u16(template, AES_KEY_BITS); =20 /* algorithm mode (must be CFB) */ - tpm_buf_append_u16(&template, TPM_ALG_CFB); + tpm_buf_append_u16(template, TPM_ALG_CFB); =20 /* scheme (NULL means any scheme) */ - tpm_buf_append_u16(&template, TPM_ALG_NULL); + tpm_buf_append_u16(template, TPM_ALG_NULL); =20 /* ECC Curve ID */ - tpm_buf_append_u16(&template, TPM2_ECC_NIST_P256); + tpm_buf_append_u16(template, TPM2_ECC_NIST_P256); =20 /* KDF Scheme */ - tpm_buf_append_u16(&template, TPM_ALG_NULL); + tpm_buf_append_u16(template, TPM_ALG_NULL); =20 /* unique: key specific; for ECC it is two zero size points */ - tpm_buf_append_u16(&template, 0); - tpm_buf_append_u16(&template, 0); + tpm_buf_append_u16(template, 0); + tpm_buf_append_u16(template, 0); =20 /* END parameters */ =20 /* primary handle */ - tpm_buf_append_u32(&buf, hierarchy); - tpm_buf_append_empty_auth(&buf, TPM2_RS_PW); + tpm_buf_append_u32(buf, hierarchy); + tpm_buf_append_empty_auth(buf, TPM2_RS_PW); =20 /* sensitive create size is 4 for two empty buffers */ - tpm_buf_append_u16(&buf, 4); + tpm_buf_append_u16(buf, 4); =20 /* sensitive create auth data (empty) */ - tpm_buf_append_u16(&buf, 0); + tpm_buf_append_u16(buf, 0); =20 /* sensitive create sensitive data (empty) */ - tpm_buf_append_u16(&buf, 0); + tpm_buf_append_u16(buf, 0); =20 /* the public template */ - tpm_buf_append(&buf, template.data, template.length); - tpm_buf_destroy(&template); + tpm_buf_append(buf, template->data, template->length); =20 /* outside info (empty) */ - tpm_buf_append_u16(&buf, 0); + tpm_buf_append_u16(buf, 0); =20 /* creation PCR (none) */ - tpm_buf_append_u32(&buf, 0); + tpm_buf_append_u32(buf, 0); =20 - rc =3D tpm_transmit_cmd(chip, &buf, 0, - "attempting to create NULL primary"); + rc =3D tpm_transmit_cmd(chip, buf, 0, "TPM2_CreatePrimary"); =20 if (rc =3D=3D TPM2_RC_SUCCESS) - rc =3D tpm2_parse_create_primary(chip, &buf, handle, hierarchy, + rc =3D tpm2_parse_create_primary(chip, buf, handle, hierarchy, name); =20 - tpm_buf_destroy(&buf); - return rc; } =20 diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index 60354cd53b5c..cbf86ff5931f 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -71,24 +71,25 @@ void tpm2_del_space(struct tpm_chip *chip, struct tpm_s= pace *space) int tpm2_load_context(struct tpm_chip *chip, u8 *buf, unsigned int *offset, u32 *handle) { - struct tpm_buf tbuf; struct tpm2_context *ctx; unsigned int body_size; int rc; =20 - rc =3D tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD); - if (rc) - return rc; + struct tpm_buf *tbuf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!tbuf) + return -ENOMEM; + + tpm_buf_init(tbuf, TPM_BUFSIZE); + tpm_buf_reset(tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD); =20 ctx =3D (struct tpm2_context *)&buf[*offset]; body_size =3D sizeof(*ctx) + be16_to_cpu(ctx->blob_size); - tpm_buf_append(&tbuf, &buf[*offset], body_size); + tpm_buf_append(tbuf, &buf[*offset], body_size); =20 - rc =3D tpm_transmit_cmd(chip, &tbuf, 4, NULL); + rc =3D tpm_transmit_cmd(chip, tbuf, 4, NULL); if (rc < 0) { dev_warn(&chip->dev, "%s: failed with a system error %d\n", __func__, rc); - tpm_buf_destroy(&tbuf); return -EFAULT; } else if (tpm2_rc_value(rc) =3D=3D TPM2_RC_HANDLE || rc =3D=3D TPM2_RC_REFERENCE_H0) { @@ -103,64 +104,55 @@ int tpm2_load_context(struct tpm_chip *chip, u8 *buf, * flushed outside the space */ *handle =3D 0; - tpm_buf_destroy(&tbuf); return -ENOENT; } else if (tpm2_rc_value(rc) =3D=3D TPM2_RC_INTEGRITY) { - tpm_buf_destroy(&tbuf); return -EINVAL; } else if (rc > 0) { dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n", __func__, rc); - tpm_buf_destroy(&tbuf); return -EFAULT; } =20 - *handle =3D be32_to_cpup((__be32 *)&tbuf.data[TPM_HEADER_SIZE]); + *handle =3D be32_to_cpup((__be32 *)&tbuf->data[TPM_HEADER_SIZE]); *offset +=3D body_size; - - tpm_buf_destroy(&tbuf); return 0; } =20 int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf, unsigned int buf_size, unsigned int *offset) { - struct tpm_buf tbuf; unsigned int body_size; int rc; =20 - rc =3D tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE); - if (rc) - return rc; + struct tpm_buf *tbuf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!tbuf) + return -ENOMEM; =20 - tpm_buf_append_u32(&tbuf, handle); + tpm_buf_init(tbuf, TPM_BUFSIZE); + tpm_buf_reset(tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE); + tpm_buf_append_u32(tbuf, handle); =20 - rc =3D tpm_transmit_cmd(chip, &tbuf, 0, NULL); + rc =3D tpm_transmit_cmd(chip, tbuf, 0, NULL); if (rc < 0) { dev_warn(&chip->dev, "%s: failed with a system error %d\n", __func__, rc); - tpm_buf_destroy(&tbuf); return -EFAULT; } else if (tpm2_rc_value(rc) =3D=3D TPM2_RC_REFERENCE_H0) { - tpm_buf_destroy(&tbuf); return -ENOENT; } else if (rc) { dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n", __func__, rc); - tpm_buf_destroy(&tbuf); return -EFAULT; } =20 - body_size =3D tpm_buf_length(&tbuf) - TPM_HEADER_SIZE; + body_size =3D tpm_buf_length(tbuf) - TPM_HEADER_SIZE; if ((*offset + body_size) > buf_size) { dev_warn(&chip->dev, "%s: out of backing storage\n", __func__); - tpm_buf_destroy(&tbuf); return -ENOMEM; } =20 - memcpy(&buf[*offset], &tbuf.data[TPM_HEADER_SIZE], body_size); + memcpy(&buf[*offset], &tbuf->data[TPM_HEADER_SIZE], body_size); *offset +=3D body_size; - tpm_buf_destroy(&tbuf); return 0; } =20 diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_= proxy.c index 0818bb517805..682dfc93845d 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -395,40 +395,36 @@ static bool vtpm_proxy_tpm_req_canceled(struct tpm_ch= ip *chip, u8 status) =20 static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) { - struct tpm_buf buf; int rc; const struct tpm_header *header; struct proxy_dev *proxy_dev =3D dev_get_drvdata(&chip->dev); =20 + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); if (chip->flags & TPM_CHIP_FLAG_TPM2) - rc =3D tpm_buf_init(&buf, TPM2_ST_SESSIONS, - TPM2_CC_SET_LOCALITY); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_SET_LOCALITY); else - rc =3D tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, - TPM_ORD_SET_LOCALITY); - if (rc) - return rc; - tpm_buf_append_u8(&buf, locality); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SET_LOCALITY); + + tpm_buf_append_u8(buf, locality); =20 proxy_dev->state |=3D STATE_DRIVER_COMMAND; =20 - rc =3D tpm_transmit_cmd(chip, &buf, 0, "attempting to set locality"); + rc =3D tpm_transmit_cmd(chip, buf, 0, "attempting to set locality"); =20 proxy_dev->state &=3D ~STATE_DRIVER_COMMAND; =20 - if (rc < 0) { - locality =3D rc; - goto out; - } + if (rc < 0) + return rc; =20 - header =3D (const struct tpm_header *)buf.data; + header =3D (const struct tpm_header *)buf->data; rc =3D be32_to_cpu(header->return_code); if (rc) locality =3D -1; =20 -out: - tpm_buf_destroy(&buf); - return locality; } =20 diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 5a5d8e584e7b..01216156a1ec 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -25,7 +25,8 @@ #include #include =20 -#define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ +#define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ +#define TPM_BUFSIZE 4096 =20 /* * SHA-512 is, as of today, the largest digest in the TCG algorithm reposi= tory. @@ -389,12 +390,14 @@ enum tpm_buf_flags { }; =20 /* - * A string buffer type for constructing TPM commands. + * A buffer for constructing and parsing TPM commands, responses and sized + * (TPM2B) buffers. */ struct tpm_buf { - u32 flags; - u32 length; - u8 *data; + u8 flags; + u16 length; + u16 capacity; + u8 data[]; }; =20 enum tpm2_object_attributes { @@ -425,12 +428,11 @@ struct tpm2_hash { unsigned int tpm_id; }; =20 -int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal); +void tpm_buf_init(struct tpm_buf *buf, u16 buf_size); +void tpm_buf_init_sized(struct tpm_buf *buf, u16 buf_size); void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal); -int tpm_buf_init_sized(struct tpm_buf *buf); void tpm_buf_reset_sized(struct tpm_buf *buf); -void tpm_buf_destroy(struct tpm_buf *buf); -u32 tpm_buf_length(struct tpm_buf *buf); +u16 tpm_buf_length(struct tpm_buf *buf); void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_lengt= h); void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value); void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value); diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trus= ted-keys/trusted_tpm1.c index 3d75bb6f9689..368e420c18af 100644 --- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -320,9 +320,10 @@ static int TSS_checkhmac2(unsigned char *buffer, * For key specific tpm requests, we will generate and send our * own TPM command packets using the drivers send function. */ -static int trusted_tpm_send(unsigned char *cmd, size_t buflen) +static int trusted_tpm_send(void *cmd, size_t cmd_len) { - struct tpm_buf buf; + u8 buf_data[512]; + struct tpm_buf *buf =3D (struct tpm_buf *)buf_data; int rc; =20 if (!chip) @@ -332,11 +333,10 @@ static int trusted_tpm_send(unsigned char *cmd, size_= t buflen) if (rc) return rc; =20 - buf.flags =3D 0; - buf.length =3D buflen; - buf.data =3D cmd; + tpm_buf_init(buf, sizeof(buf_data)); + tpm_buf_append(buf, cmd, cmd_len); dump_tpm_buf(cmd); - rc =3D tpm_transmit_cmd(chip, &buf, 4, "sending data"); + rc =3D tpm_transmit_cmd(chip, buf, 4, "sending data"); dump_tpm_buf(cmd); =20 if (rc > 0) @@ -622,23 +622,23 @@ static int tpm_unseal(struct tpm_buf *tb, static int key_seal(struct trusted_key_payload *p, struct trusted_key_options *o) { - struct tpm_buf tb; int ret; =20 - ret =3D tpm_buf_init(&tb, 0, 0); - if (ret) - return ret; + struct tpm_buf *tb __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!tb) + return -ENOMEM; + + tpm_buf_init(tb, TPM_BUFSIZE); =20 /* include migratable flag at end of sealed key */ p->key[p->key_len] =3D p->migratable; =20 - ret =3D tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth, + ret =3D tpm_seal(tb, o->keytype, o->keyhandle, o->keyauth, p->key, p->key_len + 1, p->blob, &p->blob_len, o->blobauth, o->pcrinfo, o->pcrinfo_len); if (ret < 0) pr_info("srkseal failed (%d)\n", ret); =20 - tpm_buf_destroy(&tb); return ret; } =20 @@ -648,14 +648,15 @@ static int key_seal(struct trusted_key_payload *p, static int key_unseal(struct trusted_key_payload *p, struct trusted_key_options *o) { - struct tpm_buf tb; int ret; =20 - ret =3D tpm_buf_init(&tb, 0, 0); - if (ret) - return ret; + struct tpm_buf *tb __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!tb) + return -ENOMEM; + + tpm_buf_init(tb, TPM_BUFSIZE); =20 - ret =3D tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len, + ret =3D tpm_unseal(tb, o->keyhandle, o->keyauth, p->blob, p->blob_len, o->blobauth, p->key, &p->key_len); if (ret < 0) pr_info("srkunseal failed (%d)\n", ret); @@ -663,7 +664,6 @@ static int key_unseal(struct trusted_key_payload *p, /* pull migratable flag out of sealed key */ p->migratable =3D p->key[--p->key_len]; =20 - tpm_buf_destroy(&tb); return ret; } =20 diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trus= ted-keys/trusted_tpm2.c index 8e694318b200..05c255e67e06 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -205,7 +205,6 @@ int tpm2_seal_trusted(struct tpm_chip *chip, { u8 parent_name[TPM2_MAX_NAME_SIZE]; off_t offset =3D TPM_HEADER_SIZE; - struct tpm_buf buf, sized; u16 parent_name_size; int blob_len =3D 0; int hash; @@ -233,98 +232,100 @@ int tpm2_seal_trusted(struct tpm_chip *chip, if (rc) goto out_put; =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); - if (rc) { + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { + rc =3D -ENOMEM; tpm2_end_auth_session(chip); goto out_put; } =20 - rc =3D tpm_buf_init_sized(&sized); - if (rc) { - tpm_buf_destroy(&buf); - tpm2_end_auth_session(chip); - goto out_put; - } + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); =20 - rc =3D tpm_buf_append_name(chip, &buf, options->keyhandle, parent_name, + rc =3D tpm_buf_append_name(chip, buf, options->keyhandle, parent_name, parent_name_size); if (rc) - goto out; + goto out_put; =20 - tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT, + tpm_buf_append_hmac_session(chip, buf, TPM2_SA_DECRYPT, options->keyauth, TPM_DIGEST_SIZE); =20 + struct tpm_buf *sized __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!sized) { + rc =3D -ENOMEM; + tpm2_end_auth_session(chip); + goto out_put; + } + /* sensitive */ - tpm_buf_append_u16(&sized, options->blobauth_len); + tpm_buf_init_sized(sized, TPM_BUFSIZE); + tpm_buf_append_u16(sized, options->blobauth_len); =20 if (options->blobauth_len) - tpm_buf_append(&sized, options->blobauth, options->blobauth_len); + tpm_buf_append(sized, options->blobauth, options->blobauth_len); =20 - tpm_buf_append_u16(&sized, payload->key_len); - tpm_buf_append(&sized, payload->key, payload->key_len); - tpm_buf_append(&buf, sized.data, sized.length); + tpm_buf_append_u16(sized, payload->key_len); + tpm_buf_append(sized, payload->key, payload->key_len); + tpm_buf_append(buf, sized->data, sized->length); =20 /* public */ - tpm_buf_reset_sized(&sized); - tpm_buf_append_u16(&sized, TPM_ALG_KEYEDHASH); - tpm_buf_append_u16(&sized, hash); + tpm_buf_init_sized(sized, TPM_BUFSIZE); + tpm_buf_append_u16(sized, TPM_ALG_KEYEDHASH); + tpm_buf_append_u16(sized, hash); =20 /* key properties */ flags =3D 0; flags |=3D options->policydigest_len ? 0 : TPM2_OA_USER_WITH_AUTH; flags |=3D payload->migratable ? 0 : (TPM2_OA_FIXED_TPM | TPM2_OA_FIXED_P= ARENT); - tpm_buf_append_u32(&sized, flags); + tpm_buf_append_u32(sized, flags); =20 /* policy */ - tpm_buf_append_u16(&sized, options->policydigest_len); + tpm_buf_append_u16(sized, options->policydigest_len); if (options->policydigest_len) - tpm_buf_append(&sized, options->policydigest, options->policydigest_len); + tpm_buf_append(sized, options->policydigest, options->policydigest_len); =20 /* public parameters */ - tpm_buf_append_u16(&sized, TPM_ALG_NULL); - tpm_buf_append_u16(&sized, 0); + tpm_buf_append_u16(sized, TPM_ALG_NULL); + tpm_buf_append_u16(sized, 0); =20 - tpm_buf_append(&buf, sized.data, sized.length); + tpm_buf_append(buf, sized->data, sized->length); =20 /* outside info */ - tpm_buf_append_u16(&buf, 0); + tpm_buf_append_u16(buf, 0); =20 /* creation PCR */ - tpm_buf_append_u32(&buf, 0); + tpm_buf_append_u32(buf, 0); =20 - if (buf.flags & TPM_BUF_INVALID) { + if (buf->flags & TPM_BUF_INVALID) { rc =3D -E2BIG; tpm2_end_auth_session(chip); goto out; } =20 - rc =3D tpm_buf_fill_hmac_session(chip, &buf); + rc =3D tpm_buf_fill_hmac_session(chip, buf); if (rc) goto out; =20 - rc =3D tpm_transmit_cmd(chip, &buf, 4, "sealing data"); - rc =3D tpm_buf_check_hmac_response(chip, &buf, rc); + rc =3D tpm_transmit_cmd(chip, buf, 4, "sealing data"); + rc =3D tpm_buf_check_hmac_response(chip, buf, rc); if (rc) goto out; =20 - blob_len =3D tpm_buf_read_u32(&buf, &offset); - if (blob_len > MAX_BLOB_SIZE || buf.flags & TPM_BUF_INVALID) { + blob_len =3D tpm_buf_read_u32(buf, &offset); + if (blob_len > MAX_BLOB_SIZE || buf->flags & TPM_BUF_INVALID) { rc =3D -E2BIG; goto out; } - if (buf.length - offset < blob_len) { + if (buf->length - offset < blob_len) { rc =3D -EFAULT; goto out; } =20 - blob_len =3D tpm2_key_encode(payload, options, &buf.data[offset], blob_le= n); + blob_len =3D tpm2_key_encode(payload, options, &buf->data[offset], blob_l= en); if (blob_len < 0) rc =3D blob_len; =20 out: - tpm_buf_destroy(&sized); - tpm_buf_destroy(&buf); - if (!rc) payload->blob_len =3D blob_len; =20 @@ -356,7 +357,6 @@ static int tpm2_load_cmd(struct tpm_chip *chip, u32 *blob_handle) { u8 *blob_ref __free(kfree) =3D NULL; - struct tpm_buf buf; unsigned int private_len; unsigned int public_len; unsigned int blob_len; @@ -396,40 +396,39 @@ static int tpm2_load_cmd(struct tpm_chip *chip, if (rc) return rc; =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD); - if (rc) { + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { tpm2_end_auth_session(chip); - return rc; + return -ENOMEM; } =20 - rc =3D tpm_buf_append_name(chip, &buf, options->keyhandle, parent_name, + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD); + + rc =3D tpm_buf_append_name(chip, buf, options->keyhandle, parent_name, parent_name_size); if (rc) - goto out; + return rc; =20 - tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth, + tpm_buf_append_hmac_session(chip, buf, 0, options->keyauth, TPM_DIGEST_SIZE); =20 - tpm_buf_append(&buf, blob, blob_len); + tpm_buf_append(buf, blob, blob_len); =20 - if (buf.flags & TPM_BUF_INVALID) { - rc =3D -E2BIG; + if (buf->flags & TPM_BUF_INVALID) { tpm2_end_auth_session(chip); - goto out; + return -E2BIG; } =20 - rc =3D tpm_buf_fill_hmac_session(chip, &buf); + rc =3D tpm_buf_fill_hmac_session(chip, buf); if (rc) - goto out; + return rc; =20 - rc =3D tpm_transmit_cmd(chip, &buf, 4, "loading blob"); - rc =3D tpm_buf_check_hmac_response(chip, &buf, rc); + rc =3D tpm_transmit_cmd(chip, buf, 4, "loading blob"); + rc =3D tpm_buf_check_hmac_response(chip, buf, rc); if (!rc) *blob_handle =3D be32_to_cpup( - (__be32 *) &buf.data[TPM_HEADER_SIZE]); - -out: - tpm_buf_destroy(&buf); + (__be32 *)&buf->data[TPM_HEADER_SIZE]); =20 return tpm_ret_to_err(rc); } @@ -454,28 +453,28 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, u16 parent_name_size, u32 blob_handle) { - struct tpm_buf buf; u16 data_len; u8 *data; int rc; =20 + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + rc =3D tpm2_start_auth_session(chip); if (rc) return rc; =20 - rc =3D tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); - if (rc) { - tpm2_end_auth_session(chip); - return rc; - } + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); =20 - rc =3D tpm_buf_append_name(chip, &buf, blob_handle, parent_name, + rc =3D tpm_buf_append_name(chip, buf, blob_handle, parent_name, parent_name_size); if (rc) - goto out; + return rc; =20 if (!options->policyhandle) { - tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, + tpm_buf_append_hmac_session(chip, buf, TPM2_SA_ENCRYPT, options->blobauth, options->blobauth_len); } else { @@ -490,37 +489,33 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, * could repeat our actions with the exfiltrated * password. */ - tpm_buf_append_u32(&buf, 9 + options->blobauth_len); - tpm_buf_append_u32(&buf, options->policyhandle); - tpm_buf_append_u16(&buf, 0); - tpm_buf_append_u8(&buf, 0); - tpm_buf_append_u16(&buf, options->blobauth_len); - tpm_buf_append(&buf, options->blobauth, options->blobauth_len); + tpm_buf_append_u32(buf, 9 + options->blobauth_len); + tpm_buf_append_u32(buf, options->policyhandle); + tpm_buf_append_u16(buf, 0); + tpm_buf_append_u8(buf, 0); + tpm_buf_append_u16(buf, options->blobauth_len); + tpm_buf_append(buf, options->blobauth, options->blobauth_len); =20 if (tpm2_chip_auth(chip)) - tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, NULL, 0); + tpm_buf_append_hmac_session(chip, buf, TPM2_SA_ENCRYPT, NULL, 0); } =20 - rc =3D tpm_buf_fill_hmac_session(chip, &buf); + rc =3D tpm_buf_fill_hmac_session(chip, buf); if (rc) - goto out; + return rc; =20 - rc =3D tpm_transmit_cmd(chip, &buf, 6, "unsealing"); - rc =3D tpm_buf_check_hmac_response(chip, &buf, rc); + rc =3D tpm_transmit_cmd(chip, buf, 6, "unsealing"); + rc =3D tpm_buf_check_hmac_response(chip, buf, rc); =20 if (!rc) { data_len =3D be16_to_cpup( - (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]); - if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE) { - rc =3D -EFAULT; - goto out; - } + (__be16 *)&buf->data[TPM_HEADER_SIZE + 4]); + if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE) + return -EFAULT; =20 - if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 6 + data_len) { - rc =3D -EFAULT; - goto out; - } - data =3D &buf.data[TPM_HEADER_SIZE + 6]; + if (tpm_buf_length(buf) < TPM_HEADER_SIZE + 6 + data_len) + return -EFAULT; + data =3D &buf->data[TPM_HEADER_SIZE + 6]; =20 if (payload->old_format) { /* migratable flag is at the end of the key */ @@ -537,8 +532,6 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, } } =20 -out: - tpm_buf_destroy(&buf); return tpm_ret_to_err(rc); } =20 --=20 2.52.0