From nobody Fri Dec 19 15:01:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B810B3587C9; Fri, 5 Dec 2025 15:20:08 +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=1764948008; cv=none; b=elJU1junAWKVvL7kyHpvZuVQq7yRAv766bIWc5K2Z/JHu3uUfIfyugdm1EmD5+4f18MQL8cpIPr6a1N+VfEcgdEG4r1xVp2D6RrNl0PDKcCECcfQMW8TqXYqjsl6gCZ8QtfEZU57GbRn9xSSAmBN3z8mhQwFTqW2V7wu8S0maMo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764948008; c=relaxed/simple; bh=xHj2/V6DKjy3AVCP76Hz2u1MumruVT5HgUnwvMteiuk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CILg6UtJPfLZ0YuabvcaTdxZ3wmgLTipTISYmWgFiC4zLrc3AfMYfdIWvaR5rj8xaMZkSZshWTAFLRW5ODowRTyS7y3YT1FvIzVvTPUaN6IQDfO6n4k68xThwMRHSiKxKmPo6Sy9qVOOSJDyyNg9FKsD+3F8HMlZdIg+KxnhJTk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=m10dXQek; 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="m10dXQek" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 403CDC4AF0B; Fri, 5 Dec 2025 15:20:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1764948007; bh=xHj2/V6DKjy3AVCP76Hz2u1MumruVT5HgUnwvMteiuk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=m10dXQek5O6lKHyxFKIjdzLN4Ry0kG9AcFVN9rpdhCD424hb5gAY5Cd1H31WS0cT9 4pAyjXXuK+6QrVzp/+hkEec5eWtoC/3ZUGrcWa4vGdz2Nu/BDeUYu+L+9L5i00TP0O YGeCcoZ1UFkPOGd76a60DI65aUixseUe4WPRWOAa8Rj19lYRRRcIMI/kNWuMSCF5vd NP8A7cti0UTq/NzdahDZL2oeeGIAz7zRNvcrgEKpALoLpLmM/99q07AoLCpnCuY5D4 VR8wqPT2EEsJ0JxYJYajq4D7rpxopuGYb67zfP3zFq/Ve1WFSyeJ/unQEOBAs31xQ7 jYaq7nvy+ZHhQ== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , Peter Huewe , Jason Gunthorpe , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , linux-kernel@vger.kernel.org (open list), keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM) Subject: [PATCH v4 1/4] KEYS: trusted: Re-orchestrate tpm2_read_public() calls Date: Fri, 5 Dec 2025 17:19:50 +0200 Message-ID: <20251205151955.298182-2-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251205151955.298182-1-jarkko@kernel.org> References: <20251205151955.298182-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 --- v3: - No changes. v2: - No changes. --- 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 | 124 ++++++++++++++-------- 4 files changed, 118 insertions(+), 114 deletions(-) diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 3a77be7ebf4a..1f561ad3bdcf 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 4149379665c4..e33be09446ff 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][2 + SHA512_DIGEST_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 202da079d500..319ba75dd79a 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -530,7 +530,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); @@ -544,6 +544,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 @@ -567,6 +568,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 a7ea4a1c3bed..88bafbcc011a 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -233,8 +233,10 @@ int tpm2_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, struct trusted_key_options *options) { + u8 parent_name[2 + SHA512_DIGEST_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; @@ -251,6 +253,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; @@ -268,7 +276,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 @@ -355,21 +364,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; @@ -377,27 +390,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 @@ -433,7 +432,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 @@ -465,20 +465,23 @@ static int tpm2_load_cmd(struct tpm_chip *chip, } =20 /** - * tpm2_unseal_cmd() - execute a TPM2_Unload command + * tpm2_unseal_cmd() - Execute TPM2_Unload * - * @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_header *head; @@ -498,7 +501,8 @@ static int tpm2_unseal_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 @@ -573,30 +577,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[2 + SHA512_DIGEST_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 Fri Dec 19 15:01:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5003A359FB4; Fri, 5 Dec 2025 15:20:14 +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=1764948014; cv=none; b=WeoSIIlykKPibse5FB4UjzWx1iyggDNBmvztQqIJ+LPVEfzkfBDfK+qndpu+YmaEXT58oBVwn4Ei68Egl/KvGnaZGvAFmtcMbrGgheXsg8/Pq7YeYttRWG6XHmpXkyCSyL79ujR7CPu2kX5RDIr6Fa5BB8s2Fxr77NgwUeLC+vw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764948014; c=relaxed/simple; bh=+r2lrr+CoTmPdJVkwpntjiQOQKZeyePdUgxx8XW0PCU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=J4yt1+dV3TSLJR5AzsA+0RJkNkYFyaxxa8oNzAeJoArCqdPUKqtzDizQkaQOZMekTw2vqnfwJxxSalRg7NPiyGTwh5qty0n+Kt/ratnoGegKrWOVq/1rz9xHzDhqncrHbhw8wZIPFGamLxDSj1G+DHX5y+HMsOwvCfsv/AqWDRM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nGeckSBK; 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="nGeckSBK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F35C6C4CEF1; Fri, 5 Dec 2025 15:20:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1764948013; bh=+r2lrr+CoTmPdJVkwpntjiQOQKZeyePdUgxx8XW0PCU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nGeckSBK5V9Z2s/w5O2DTXVrjefvGJZWQUMt9muqS/NHz72cqyJ+HzjX0Ri01i5N7 Ehjx74jVTd29ZgggDg1mk3Z/WEf1b6TYY+X2fSukCPZNqFVd65CcHRH8IltTfRenCn hh2/Uv8oSNKegclvI9N5BMqOwl6bQP6Pam5nim5ZPHmDEcv9PcFXOzmKj+ZGM9RrjB P5YqNd+W58Mzbh1h5G0Zj/UD7/77oLCLJEKvHCVBEPEzlzhJ4dICyC10Z/yCsclvbz vGXvRBY9Nb5rjpD+RRgr5NB2U2m4MtBgO2w0FMpECZNDT4xhACtcgIKNHSq3SdOBul yekwlLg41yK2Q== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , Peter Huewe , Jason Gunthorpe , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , linux-kernel@vger.kernel.org (open list), keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM) Subject: [PATCH v4 2/4] KEYS: trusted: Store parent's name to the encoded keys Date: Fri, 5 Dec 2025 17:19:51 +0200 Message-ID: <20251205151955.298182-3-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251205151955.298182-1-jarkko@kernel.org> References: <20251205151955.298182-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" Extend TPMKey ASN.1 speciication [1] with an optional 'parentName' attribute containing TPM name of the parent key (in other words, TPMT_HA blob). The life-cycle for trusted keys will now proceed as follows: 1. Encode parent's name to the 'paretName' during tpm2_key_encode(). 2. During tpm2_unseal_trusted, read parent's name from 'parentName'. When the attribute is not available, fallback on doing tpm2_read_public(). In other words, in the common (i.e., not loading a legacy key blob), tpm2_read_public() will now only happen at the time when a key is first created. In addition, move tpm2_read_public() to 'tpm2-cmd.c' and make its body unconditional so that the binary format of the saved keys is not dependent on kernel configuration. [1] https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.txt Signed-off-by: Jarkko Sakkinen --- v3: - Fixed three low-hanging fruit issues I found myself. v2: - A new patch. --- drivers/char/tpm/tpm2-cmd.c | 90 ++++++++++++++++++++++ drivers/char/tpm/tpm2-sessions.c | 92 ---------------------- include/linux/tpm.h | 9 +-- security/keys/trusted-keys/tpm2key.asn1 | 17 ++++- security/keys/trusted-keys/trusted_tpm2.c | 93 ++++++++++++++++------- 5 files changed, 173 insertions(+), 128 deletions(-) diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 1f561ad3bdcf..360bc014d895 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -793,3 +793,93 @@ int tpm2_find_cc(struct tpm_chip *chip, u32 cc) =20 return -1; } + +/* + * Name Size based on TPM algorithm (assumes no hash bigger than 255) + */ +static int name_size(const u8 *name) +{ + u16 hash_alg =3D get_unaligned_be16(name); + + switch (hash_alg) { + case TPM_ALG_SHA1: + return SHA1_DIGEST_SIZE + 2; + case TPM_ALG_SHA256: + return SHA256_DIGEST_SIZE + 2; + case TPM_ALG_SHA384: + return SHA384_DIGEST_SIZE + 2; + case TPM_ALG_SHA512: + return SHA512_DIGEST_SIZE + 2; + default: + pr_warn("tpm: unsupported name algorithm: 0x%04x\n", hash_alg); + return -EINVAL; + } +} + +/** + * 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; + int rc, name_size_alg; + struct tpm_buf buf; + + if (mso !=3D TPM2_MSO_PERSISTENT && mso !=3D TPM2_MSO_VOLATILE && + mso !=3D TPM2_MSO_NVRAM) { + memcpy(name, &handle, sizeof(u32)); + return sizeof(u32); + } + + rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC); + if (rc) + return rc; + + tpm_buf_append_u32(&buf, handle); + + rc =3D tpm_transmit_cmd(chip, &buf, 0, "TPM2_ReadPublic"); + if (rc) { + tpm_buf_destroy(&buf); + return tpm_ret_to_err(rc); + } + + /* Skip TPMT_PUBLIC: */ + offset +=3D tpm_buf_read_u16(&buf, &offset); + + /* + * 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); + return -EIO; + } + + rc =3D tpm_buf_read_u16(&buf, &offset); + name_size_alg =3D name_size(&buf.data[offset]); + + if (name_size_alg < 0) + return name_size_alg; + + if (rc !=3D name_size_alg) { + tpm_buf_destroy(&buf); + return -EIO; + } + + if (offset + rc > tpm_buf_length(&buf)) { + tpm_buf_destroy(&buf); + return -EIO; + } + + memcpy(name, &buf.data[offset], rc); + return name_size_alg; +} +EXPORT_SYMBOL_GPL(tpm2_read_public); diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessi= ons.c index e33be09446ff..c8b44b1a6cb6 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -140,98 +140,6 @@ struct tpm2_auth { u16 name_size_tbl[AUTH_MAX_NAMES]; }; =20 -#ifdef CONFIG_TCG_TPM2_HMAC -/* - * Name Size based on TPM algorithm (assumes no hash bigger than 255) - */ -static int name_size(const u8 *name) -{ - u16 hash_alg =3D get_unaligned_be16(name); - - switch (hash_alg) { - case TPM_ALG_SHA1: - return SHA1_DIGEST_SIZE + 2; - case TPM_ALG_SHA256: - return SHA256_DIGEST_SIZE + 2; - case TPM_ALG_SHA384: - return SHA384_DIGEST_SIZE + 2; - case TPM_ALG_SHA512: - return SHA512_DIGEST_SIZE + 2; - default: - pr_warn("tpm: unsupported name algorithm: 0x%04x\n", hash_alg); - return -EINVAL; - } -} - -/** - * 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; - int rc, name_size_alg; - struct tpm_buf buf; - - if (mso !=3D TPM2_MSO_PERSISTENT && mso !=3D TPM2_MSO_VOLATILE && - mso !=3D TPM2_MSO_NVRAM) { - memcpy(name, &handle, sizeof(u32)); - return sizeof(u32); - } - - rc =3D tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC); - if (rc) - return rc; - - tpm_buf_append_u32(&buf, handle); - - rc =3D tpm_transmit_cmd(chip, &buf, 0, "TPM2_ReadPublic"); - if (rc) { - tpm_buf_destroy(&buf); - return tpm_ret_to_err(rc); - } - - /* Skip TPMT_PUBLIC: */ - offset +=3D tpm_buf_read_u16(&buf, &offset); - - /* - * 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); - return -EIO; - } - - rc =3D tpm_buf_read_u16(&buf, &offset); - name_size_alg =3D name_size(&buf.data[offset]); - - if (name_size_alg < 0) - return name_size_alg; - - if (rc !=3D name_size_alg) { - tpm_buf_destroy(&buf); - return -EIO; - } - - if (offset + rc > tpm_buf_length(&buf)) { - tpm_buf_destroy(&buf); - return -EIO; - } - - memcpy(name, &buf.data[offset], rc); - return name_size_alg; -} -EXPORT_SYMBOL_GPL(tpm2_read_public); -#endif /* CONFIG_TCG_TPM2_HMAC */ - /** * tpm_buf_append_name() - Append a handle and store TPM name * @chip: TPM chip to use. diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 319ba75dd79a..704fceb46a40 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -478,6 +478,7 @@ extern int tpm_get_random(struct tpm_chip *chip, u8 *da= ta, size_t max); extern struct tpm_chip *tpm_default_chip(void); void tpm2_flush_context(struct tpm_chip *chip, u32 handle); int tpm2_find_hash_alg(unsigned int crypto_id); +int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name); =20 static inline void tpm_buf_append_empty_auth(struct tpm_buf *buf, u32 hand= le) { @@ -544,7 +545,6 @@ 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 @@ -568,13 +568,6 @@ 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/tpm2key.asn1 b/security/keys/truste= d-keys/tpm2key.asn1 index f57f869ad600..70cca3b7c3d4 100644 --- a/security/keys/trusted-keys/tpm2key.asn1 +++ b/security/keys/trusted-keys/tpm2key.asn1 @@ -1,11 +1,26 @@ --- --- ASN.1 for TPM 2.0 keys --- +TPMPolicy ::=3D SEQUENCE { + commandCode [0] EXPLICIT INTEGER, + commandPolicy [1] EXPLICIT OCTET STRING +} + +TPMAuthPolicy ::=3D SEQUENCE { + name [0] EXPLICIT UTF8String OPTIONAL, + policy [1] EXPLICIT SEQUENCE OF TPMPolicy +} =20 TPMKey ::=3D SEQUENCE { type OBJECT IDENTIFIER ({tpm2_key_type}), emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL, + policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL, + secret [2] EXPLICIT OCTET STRING OPTIONAL, + authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL, + description [4] EXPLICIT UTF8String OPTIONAL, + rsaParent [5] EXPLICIT BOOLEAN OPTIONAL, + parentName [6] EXPLICIT OCTET STRING OPTIONAL ({tpm2_key_parent_name}), parent INTEGER ({tpm2_key_parent}), pubkey OCTET STRING ({tpm2_key_pub}), privkey OCTET STRING ({tpm2_key_priv}) - } +} diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trus= ted-keys/trusted_tpm2.c index 88bafbcc011a..07f04cc010bc 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -20,16 +20,26 @@ =20 static u32 tpm2key_oid[] =3D { 2, 23, 133, 10, 1, 5 }; =20 +enum tpm_key_tag { + TPM_KEY_TAG_EMPTY_AUTH =3D 0, + TPM_KEY_TAG_POLICY =3D 1, + TPM_KEY_TAG_SECRET =3D 2, + TPM_KEY_TAG_AUTH_POLICY =3D 3, + TPM_KEY_TAG_DESCRIPTION =3D 4, + TPM_KEY_TAG_RSA_PARENT =3D 5, + TPM_KEY_TAG_PARENT_NAME =3D 6, +}; + static int tpm2_key_encode(struct trusted_key_payload *payload, struct trusted_key_options *options, - u8 *src, u32 len) + u8 *src, u32 len, u8 *parent_name, + u16 parent_name_size) { const int SCRATCH_SIZE =3D PAGE_SIZE; - u8 *scratch =3D kmalloc(SCRATCH_SIZE, GFP_KERNEL); - u8 *work =3D scratch, *work1; - u8 *end_work =3D scratch + SCRATCH_SIZE; - u8 *priv, *pub; + u8 *end_work, *name_end; u16 priv_len, pub_len; + u8 *work, *work1; + u8 *priv, *pub; int ret; =20 priv_len =3D get_unaligned_be16(src) + 2; @@ -40,23 +50,41 @@ static int tpm2_key_encode(struct trusted_key_payload *= payload, pub_len =3D get_unaligned_be16(src) + 2; pub =3D src; =20 + u8 *scratch __free(kfree) =3D kmalloc(SCRATCH_SIZE, GFP_KERNEL); if (!scratch) return -ENOMEM; =20 + work =3D scratch; + end_work =3D scratch + SCRATCH_SIZE; + work =3D asn1_encode_oid(work, end_work, tpm2key_oid, asn1_oid_len(tpm2key_oid)); =20 if (options->blobauth_len =3D=3D 0) { - unsigned char bool[3], *w =3D bool; - /* tag 0 is emptyAuth */ - w =3D asn1_encode_boolean(w, w + sizeof(bool), true); - if (WARN(IS_ERR(w), "BUG: Boolean failed to encode")) { - ret =3D PTR_ERR(w); - goto err; + u8 *bool_end; + u8 bool[3]; + + bool_end =3D asn1_encode_boolean(&bool[0], &bool[sizeof(bool)], + true); + if (IS_ERR(bool_end)) { + pr_err("BUG: Boolean failed to encode\n"); + return PTR_ERR(bool_end); } - work =3D asn1_encode_tag(work, end_work, 0, bool, w - bool); + + work =3D asn1_encode_tag(work, end_work, TPM_KEY_TAG_EMPTY_AUTH, + bool, bool_end - bool); } =20 + u8 *name_encoded __free(kfree) =3D kmalloc(SCRATCH_SIZE, GFP_KERNEL); + if (!name_encoded) + return -ENOMEM; + + name_end =3D asn1_encode_octet_string(&name_encoded[0], + &name_encoded[SCRATCH_SIZE], + parent_name, parent_name_size); + work =3D asn1_encode_tag(work, end_work, TPM_KEY_TAG_PARENT_NAME, + name_encoded, name_end - name_encoded); + /* * Assume both octet strings will encode to a 2 byte definite length * @@ -65,8 +93,7 @@ static int tpm2_key_encode(struct trusted_key_payload *pa= yload, */ if (WARN(work - scratch + pub_len + priv_len + 14 > SCRATCH_SIZE, "BUG: scratch buffer is too small")) { - ret =3D -EINVAL; - goto err; + return -EINVAL; } =20 work =3D asn1_encode_integer(work, end_work, options->keyhandle); @@ -79,15 +106,10 @@ static int tpm2_key_encode(struct trusted_key_payload = *payload, if (IS_ERR(work1)) { ret =3D PTR_ERR(work1); pr_err("BUG: ASN.1 encoder failed with %d\n", ret); - goto err; + return ret; } =20 - kfree(scratch); return work1 - payload->blob; - -err: - kfree(scratch); - return ret; } =20 struct tpm2_key_context { @@ -96,11 +118,13 @@ struct tpm2_key_context { u32 pub_len; const u8 *priv; u32 priv_len; + const u8 *name; + u32 name_len; }; =20 static int tpm2_key_decode(struct trusted_key_payload *payload, struct trusted_key_options *options, - u8 **buf) + u8 **buf, u8 *parent_name, u16 *parent_name_size) { int ret; struct tpm2_key_context ctx; @@ -127,6 +151,8 @@ static int tpm2_key_decode(struct trusted_key_payload *= payload, blob +=3D ctx.priv_len; =20 memcpy(blob, ctx.pub, ctx.pub_len); + memcpy(parent_name, ctx.name, ctx.name_len); + *parent_name_size =3D ctx.name_len; =20 return 0; } @@ -190,6 +216,16 @@ int tpm2_key_priv(void *context, size_t hdrlen, return 0; } =20 +int tpm2_key_parent_name(void *context, size_t hdrlen, unsigned char tag, + const void *value, size_t vlen) +{ + struct tpm2_key_context *ctx =3D context; + + ctx->name =3D value; + ctx->name_len =3D vlen; + + return 0; +} /** * tpm2_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer. * @@ -347,7 +383,8 @@ int tpm2_seal_trusted(struct tpm_chip *chip, 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_len, parent_name, parent_name_size); if (blob_len < 0) rc =3D blob_len; =20 @@ -602,7 +639,7 @@ int tpm2_unseal_trusted(struct tpm_chip *chip, * 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); + rc =3D tpm2_key_decode(payload, options, &blob, &parent_name[0], &parent_= name_size); if (rc) { blob =3D payload->blob; payload->old_format =3D 1; @@ -617,11 +654,13 @@ int tpm2_unseal_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; + if (!parent_name_size) { + rc =3D tpm2_read_public(chip, options->keyhandle, parent_name); + if (rc < 0) + goto out; =20 - parent_name_size =3D rc; + parent_name_size =3D rc; + } =20 rc =3D tpm2_load_cmd(chip, payload, options, parent_name, parent_name_size, blob, &blob_handle); --=20 2.52.0 From nobody Fri Dec 19 15:01:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5147D35A93C; Fri, 5 Dec 2025 15:20:18 +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=1764948019; cv=none; b=O6trYPLslFLObdhccmPWsgntHCCabty83d8ObM+AdYr19rqJOMjFdAQ4ekec/Y1cY4wG26EmiP59PaKkygl7c8hv/Uk3c6pm8RsHV7LYmmtyg29XeGBpmH/WS9jA4JHypkXlYxlP9fUM/Y/JRUEZ0vjgwkNJSg23BzWGm16gEu8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764948019; c=relaxed/simple; bh=0DrduLHOvQ6wuIuzL/EBUrku6LUri3yCavX2EZycS/8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ep3WZ549NSMrXVV5cio6r3duyLqFzOnaNalBnuljh69AQhYrbmajck6wwE2JUfoaMxxnf6mabs+icU6bT1N+Zd0OII9mf7KOfuVX3s7M/k5j04qUhkYRiYgEgdbtrirYJaufBQSM4eNPAt27fnKWB+FmmV3XMY5EOSnGW47upac= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QxXNAJWE; 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="QxXNAJWE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DEF57C4CEF1; Fri, 5 Dec 2025 15:20:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1764948018; bh=0DrduLHOvQ6wuIuzL/EBUrku6LUri3yCavX2EZycS/8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QxXNAJWEFZAHUjCIBp4zwDBxN/VWLYBZXc3v+ZOGTOkgWbrICMArBfEBA/ZY6lRd6 x+YoNSr/PbmlTkUobi4YFyBJEyBSPL15BcEGW6H9IuTWYu0jFSE7OMJ7b7ktqhLRmn 2n1V/owewBIcqqpJVFKCfCUXgR+1LvnlGyOFEA9BzL4rkPaeUyG/WDLanWjPdMpohQ aWO0qaUPgCQOM87T/WBKqojzFNG60aqgwMj7UA4NSkgAk3ED9O8stzqqsVaXeLzVmb dsOJSbEd6DVYDdNHXBa0yI71zchFoIJq4eb5Db4xPpi90Cgm3ao0+AB5mPUPVoM/3Z +N0PCzYWXqFIg== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , Jonathan McDowell , Peter Huewe , Jarkko Sakkinen , Jason Gunthorpe , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , linux-kernel@vger.kernel.org (open list), keyrings@vger.kernel.org (open list:KEYS-TRUSTED), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM) Subject: [PATCH v4 3/4] KEYS: trusted: Open code tpm2_buf_append() Date: Fri, 5 Dec 2025 17:19:52 +0200 Message-ID: <20251205151955.298182-4-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251205151955.298182-1-jarkko@kernel.org> References: <20251205151955.298182-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 only single call site and most of its parameters are redundant. Open code it to the call site. Remove illegit FIXME comment as there is no categorized bug and replace it with more sane comment about implementation (i.e. "non-opionated inline comment"). Signed-off-by: Jarkko Sakkinen Reviewed-by: Jonathan McDowell --- security/keys/trusted-keys/trusted_tpm2.c | 51 ++++------------------- 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trus= ted-keys/trusted_tpm2.c index 07f04cc010bc..3b5dbbc2d257 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -226,36 +226,6 @@ int tpm2_key_parent_name(void *context, size_t hdrlen,= unsigned char tag, =20 return 0; } -/** - * 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 * @@ -549,19 +519,16 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, options->blobauth_len); } else { /* - * FIXME: The policy session was generated outside the - * kernel so we don't known the nonce and thus can't - * calculate a HMAC on it. Therefore, the user can - * only really use TPM2_PolicyPassword and we must - * send down the plain text password, which could be - * intercepted. We can still encrypt the returned - * key, but that's small comfort since the interposer - * could repeat our actions with the exfiltrated - * password. + * The policy session is generated outside the kernel, and thus + * the password will end up being unencrypted on the bus, as + * HMAC nonce cannot be calculated for it. */ - 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 Fri Dec 19 15:01:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5BA0A32827F; Fri, 5 Dec 2025 15:20:24 +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=1764948024; cv=none; b=XbVPm4Ke01cNL5dJa1JsD1JQ/ITCyFnhGCXWPX7+vj19GkV82azs9xWqxbcpzLN+lQIUC6gIjSORw7A0j4I1fCmpm7wmFC9d8z/Fx9X0hgM671ikN+Wb7Kglfr1OlOPO9PPfPBJxwMKi+k43a9FOSPUnm6VKkGnyryKHhcgB4Rg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764948024; c=relaxed/simple; bh=3sMilHnTa3OfMr6J4hL8Qm9CoLASXmf5Ou9zS3NXsBk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PLMaZO/DBk39ZKgyoxr9969MQkpUPNE1B2R6vv/eWGq8++MaI7tsZK4KTMSjKXKlJ6aQ5vVvOfTMG/bae42B4NbRWbE/Djs4SlsLpTAGhBTBOKrwsAwVJmD8efQcODh5wOSjkCGptO4OB4iOH9iMCkHgdcRNqaLmYQ33zrP8H2k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uUwXPJVc; 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="uUwXPJVc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 39DAEC4CEF1; Fri, 5 Dec 2025 15:20:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1764948023; bh=3sMilHnTa3OfMr6J4hL8Qm9CoLASXmf5Ou9zS3NXsBk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uUwXPJVcLpyvbJXARGbCnFecz+XjahfeTUH1Ei91utgKtY/ggovcRmjvoDC7EW5uI CV7o0IFX5m/qGLrp/4BwNx0zq/4pHbg7ZZBmb3ws0s32AagKTC9Y76eS47V/r+FPxa Jnrv8vw5Hqb2cDsYH4xn9kXnPKrTUsbTxa5P0txNU49jOwoe0GrME5BS9Yc6Mlj5AZ q41Hjtjdi8NQakK1UGyAYcHswqvZrNJ6LzQR41h+RIpQvhzpr/nzdTNGIExRrh6BzW ybVo9L6R6+Ec54p3PPSx9HQBYWwqdYZXcKvOEsQ6aOHi3GsuCth7rvoxfqbve6T5FP JSQ/PgtwlBtyA== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , Peter Huewe , Jason Gunthorpe , linux-kernel@vger.kernel.org (open list) Subject: [PATCH v4 4/4] tpm2-sessions: Enforce single authorized handle Date: Fri, 5 Dec 2025 17:19:53 +0200 Message-ID: <20251205151955.298182-5-jarkko@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251205151955.298182-1-jarkko@kernel.org> References: <20251205151955.298182-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" Eliminate AUTH_MAX_NAMES and replace array of names with a buffer for single TPM name, as this what call sites expect at worst. Benefits are obvious i.e., removing dead code is usually a good idea :-) Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm2-sessions.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessi= ons.c index c8b44b1a6cb6..8bfe2875faf2 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][2 + SHA512_DIGEST_SIZE]; - u16 name_size_tbl[AUTH_MAX_NAMES]; + u8 name[2 + SHA512_DIGEST_SIZE]; + u16 name_size; }; =20 /** @@ -182,7 +179,7 @@ int tpm_buf_append_name(struct tpm_chip *chip, struct t= pm_buf *buf, =20 #ifdef CONFIG_TCG_TPM2_HMAC slot =3D (tpm_buf_length(buf) - TPM_HEADER_SIZE) / 4; - if (slot >=3D AUTH_MAX_NAMES) { + if (slot > 0) { dev_err(&chip->dev, "too many handles\n"); ret =3D -EIO; goto err; @@ -195,8 +192,8 @@ int tpm_buf_append_name(struct tpm_chip *chip, struct t= pm_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 @@ -573,8 +570,7 @@ int tpm_buf_fill_hmac_session(struct tpm_chip *chip, st= ruct 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++) - sha256_update(&sctx, auth->name[i], auth->name_size_tbl[i]); + 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); --=20 2.52.0