From nobody Wed Oct 1 22:30:47 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 34F072C2ABF; Tue, 30 Sep 2025 22:17:56 +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=1759270677; cv=none; b=nBS0SGLd1SFQb/rXFl+0Ey72xP/c/bIG/tVPUyv9viEraJWMLw0aLpb9JxKts3ZWzpZiEuZ6ug9yChvZHutOnJCBbqOpHCtcIcMkIovlYw/vo7oy/3CKj9gpEiEL5hmq8z6x2YbAItH82devZ0zZJFa6NRYE+wqXy8zfDy4VOkI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759270677; c=relaxed/simple; bh=FdDsuRKvnWZQHWm3A6me0amaNwoGof61ZNMUbbgkdT0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=W+n9ZLxas/Ou5gtXNyb9U9WLW9kcdwRRwaW1JfkTYJm/o0wtXAec6kfQVZ+j5gk8FvMVqQWpduywvr1aaTKPQDeTn27wtAs4zk1z6PDjIJoLT5aWShqZY5JAtEyo0S7uXrypHYa1N5zuvDaTVXUH0E7aiANBGAsHOjebSoAr/B8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cFbadoHF; 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="cFbadoHF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 05CC6C4CEF0; Tue, 30 Sep 2025 22:17:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1759270676; bh=FdDsuRKvnWZQHWm3A6me0amaNwoGof61ZNMUbbgkdT0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cFbadoHFtfj2Hpn/C20WBEHhA/pp/iBIAbvey8MYaPoVMG4vdo4R5JdUwClPwOId7 WAzdqTU0bC040jQvNR67rdYxA26QacYlhFJ4inuCIAEJGBG1QyrP9E21MxxlHe/Ap5 GY5f/kJGWLMza4TLbZKjJVP/wwRX8NqcikYvR+CNAVEHDww3ciESQ+2CXarDJeYTMs 2Ms2p8l3FWMSImH2rUiyp/WRBUJl605+TFn42PTc9vnHomWb/ZLk96RN8lNhN3EwX3 kEIwb1aeqFUWHpc3mNi3RM0OEhz3kU9Do/vTDvNFLMau0GrFdIjNxP2niCTjQDdIPx D1CkpUie77pxw== From: Jarkko Sakkinen To: linux-integrity@vger.kernel.org Cc: dpsmith@apertussolutions.com, ross.philipson@oracle.com, Jarkko Sakkinen , Stefan Berger , Peter Huewe , Jarkko Sakkinen , Jason Gunthorpe , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , James Bottomley , Mimi Zohar , linux-kernel@vger.kernel.org (open list), keyrings@vger.kernel.org (open list:KEYS/KEYRINGS), linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM) Subject: [PATCH v4 9/9] tpm-buf: Enable managed and stack allocations. Date: Wed, 1 Oct 2025 01:17:07 +0300 Message-Id: <20250930221707.1373912-10-jarkko@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250930221707.1373912-1-jarkko@kernel.org> References: <20250930221707.1373912-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 done trivially: 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)); Reviewed-by: Stefan Berger Signed-off-by: Jarkko Sakkinen --- v4: - Since every single tpm_transmit_cmd() call site needs to be changed anyhow, use 'dest' parameter more structured and actually useful way, and pick the string TCG 1.2 and 2.0 specifications. - tpm1-cmd: Remove useless rc declarations and repliace them with trivial "return tpm_transmit_cmd" statement. - Reverted spurious changes in include/linux/tpm.h. - Use concisely TPM_BUFSIZE instead of PAGE_SIZE. v3: - A new patch from the earlier series with more scoped changes and less abstract commit message. --- drivers/char/tpm/tpm-buf.c | 122 +++++---- drivers/char/tpm/tpm-sysfs.c | 21 +- drivers/char/tpm/tpm.h | 1 - drivers/char/tpm/tpm1-cmd.c | 162 +++++------- drivers/char/tpm/tpm2-cmd.c | 299 ++++++++++------------ drivers/char/tpm/tpm2-sessions.c | 122 +++++---- drivers/char/tpm/tpm2-space.c | 44 ++-- drivers/char/tpm/tpm_vtpm_proxy.c | 30 +-- include/linux/tpm.h | 18 +- security/keys/trusted-keys/trusted_tpm1.c | 34 ++- security/keys/trusted-keys/trusted_tpm2.c | 176 ++++++------- 11 files changed, 486 insertions(+), 543 deletions(-) diff --git a/drivers/char/tpm/tpm-buf.c b/drivers/char/tpm/tpm-buf.c index 1b9dee0d0681..a3bf3c3d0c48 100644 --- a/drivers/char/tpm/tpm-buf.c +++ b/drivers/char/tpm/tpm-buf.c @@ -7,82 +7,109 @@ #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); + buf->handles =3D 0; head->tag =3D cpu_to_be16(tag); head->length =3D cpu_to_be32(sizeof(*head)); head->ordinal =3D cpu_to_be32(ordinal); +} + +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->handles =3D 0; + buf->data[0] =3D 0; + buf->data[1] =3D 0; } -EXPORT_SYMBOL_GPL(tpm_buf_reset); =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 @@ -92,6 +119,9 @@ EXPORT_SYMBOL_GPL(tpm_buf_destroy); */ u32 tpm_buf_length(struct tpm_buf *buf) { + if (buf->flags & TPM_BUF_INVALID) + return 0; + return buf->length; } EXPORT_SYMBOL_GPL(tpm_buf_length); @@ -104,10 +134,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 94231f052ea7..f5dcadb1ab3c 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 769fa6b00c54..eaff2055b541 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 5c49bdff33de..10cb5d008c9f 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,45 @@ 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; + 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_append(&buf, hash, TPM_DIGEST_SIZE); - - rc =3D tpm_transmit_cmd(chip, &buf, TPM_DIGEST_SIZE, log_msg); - tpm_buf_destroy(&buf); - return rc; + 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); @@ -531,81 +520,69 @@ int tpm1_get_random(struct tpm_chip *chip, u8 *dest, = size_t max) { struct tpm1_get_random_out *out; u32 num_bytes =3D min_t(u32, max, TPM_MAX_RNG_DATA); - struct tpm_buf buf; u32 total =3D 0; int retries =3D 5; u32 recd; int rc; =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_init(buf, TPM_BUFSIZE); do { - tpm_buf_append_u32(&buf, num_bytes); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); + tpm_buf_append_u32(buf, num_bytes); =20 - rc =3D tpm_transmit_cmd(chip, &buf, sizeof(out->rng_data_len), - "attempting get random"); + rc =3D tpm_transmit_cmd(chip, buf, sizeof(out->rng_data_len), "TPM_GetRa= ndom"); if (rc) { if (rc > 0) rc =3D -EIO; - goto out; + return rc; } =20 - out =3D (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE]; + out =3D (struct tpm1_get_random_out *)&buf->data[TPM_HEADER_SIZE]; =20 recd =3D be32_to_cpu(out->rng_data_len); - if (recd > num_bytes) { - rc =3D -EFAULT; - goto out; - } + if (recd > num_bytes) + return -EFAULT; + + if (buf->length < TPM_HEADER_SIZE + + sizeof(out->rng_data_len) + recd) + return -EFAULT; =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); =20 dest +=3D recd; total +=3D recd; num_bytes -=3D recd; - - tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); } while (retries-- && total < max); =20 rc =3D total ? (int)total : -EIO; -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 @@ -619,16 +596,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 /** @@ -742,22 +716,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 @@ -772,7 +748,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) @@ -782,7 +758,5 @@ 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; } diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index e548b0ac7654..768719bbbf04 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -104,12 +104,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 @@ -124,36 +127,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 rc; =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 @@ -169,46 +167,45 @@ 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) { - tpm_buf_append_name(chip, &buf, pcr_idx, NULL); - tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0); + tpm_buf_append_name(chip, buf, pcr_idx, NULL); + tpm_buf_append_hmac_session(chip, buf, 0, NULL, 0); } else { - tpm_buf_append_handle(&buf, pcr_idx); - tpm_buf_append_auth(chip, &buf, NULL, 0); + tpm_buf_append_handle(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) - tpm_buf_fill_hmac_session(chip, &buf); - rc =3D tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value"); + tpm_buf_fill_hmac_session(chip, buf); + rc =3D tpm_transmit_cmd(chip, buf, 0, "TPM2_PCR_Extend"); if (!disable_pcr_integrity) - rc =3D tpm_buf_check_hmac_response(chip, &buf, rc); - - tpm_buf_destroy(&buf); + rc =3D tpm_buf_check_hmac_response(chip, buf, rc); =20 return rc; } @@ -233,7 +230,6 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, si= ze_t max) { struct tpm2_get_random_out *out; struct tpm_header *head; - struct tpm_buf buf; u32 recd; u32 num_bytes =3D max; int err; @@ -245,51 +241,50 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, = size_t max) if (!num_bytes || max > TPM_MAX_RNG_DATA) return -EINVAL; =20 + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + err =3D tpm2_start_auth_session(chip); if (err) return err; =20 - err =3D tpm_buf_init(&buf, 0, 0); - if (err) { - tpm2_end_auth_session(chip); - return err; - } - + tpm_buf_init(buf, TPM_BUFSIZE); do { - tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM); + 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 { - offset =3D buf.handles * 4 + TPM_HEADER_SIZE; - head =3D (struct tpm_header *)buf.data; - if (tpm_buf_length(&buf) =3D=3D offset) + 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); - tpm_buf_fill_hmac_session(chip, &buf); - err =3D tpm_transmit_cmd(chip, &buf, + tpm_buf_append_u16(buf, num_bytes); + tpm_buf_fill_hmac_session(chip, buf); + 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); + "TPM2_GetRandom"); + err =3D tpm_buf_check_hmac_response(chip, buf, err); if (err) { if (err > 0) err =3D -EIO; goto out; } =20 - head =3D (struct tpm_header *)buf.data; + 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; =20 - out =3D (struct tpm2_get_random_out *)&buf.data[offset]; + 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) < + if (tpm_buf_length(buf) < TPM_HEADER_SIZE + offsetof(struct tpm2_get_random_out, buffer) + recd) { @@ -303,11 +298,9 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, s= ize_t max) num_bytes -=3D recd; } while (retries-- && total < max); =20 - tpm_buf_destroy(&buf); - return total ? total : -EIO; + out: - tpm_buf_destroy(&buf); tpm2_end_auth_session(chip); return err; } @@ -319,20 +312,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 @@ -359,19 +350,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 @@ -383,7 +375,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); @@ -400,15 +391,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 /** @@ -426,20 +416,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) @@ -464,23 +453,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); @@ -520,7 +510,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; @@ -532,39 +521,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: unexpected number of banks: %u > %u", 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); @@ -576,7 +563,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++; } @@ -588,21 +575,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; @@ -619,30 +606,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; @@ -654,8 +635,6 @@ int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) } } =20 - tpm_buf_destroy(&buf); - out: if (rc > 0) rc =3D -ENODEV; @@ -676,20 +655,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 bbc05f0997a8..378b8d21b10c 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -182,19 +182,18 @@ static int tpm2_parse_read_public(char *name, struct = tpm_buf *buf) =20 static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name) { - struct tpm_buf buf; int rc; =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); - rc =3D tpm_transmit_cmd(chip, &buf, 0, "read public"); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC); + tpm_buf_append_u32(buf, handle); + rc =3D tpm_transmit_cmd(chip, buf, 0, "TPM2_ReadPublic"); if (rc =3D=3D TPM2_RC_SUCCESS) - rc =3D tpm2_parse_read_public(name, &buf); - - tpm_buf_destroy(&buf); + rc =3D tpm2_parse_read_public(name, buf); =20 return rc; } @@ -924,7 +923,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 @@ -933,6 +931,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; @@ -943,41 +945,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; @@ -1199,18 +1197,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 @@ -1222,75 +1220,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 0ad5e18355e0..4229c71940cb 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -70,24 +70,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) { @@ -102,64 +103,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 e86c22b30153..2ea181a35786 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -26,7 +26,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 #define TPM2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE #define TPM2_MAX_PCR_BANKS 8 @@ -377,13 +378,15 @@ 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; u8 handles; + u16 length; + u16 capacity; + u8 data[]; }; =20 enum tpm2_object_attributes { @@ -414,11 +417,10 @@ 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); 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); diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trus= ted-keys/trusted_tpm1.c index 636acb66a4f6..3ac204a902de 100644 --- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -310,9 +310,8 @@ 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 buflen) { - struct tpm_buf buf; int rc; =20 if (!chip) @@ -322,15 +321,12 @@ 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; dump_tpm_buf(cmd); - rc =3D tpm_transmit_cmd(chip, &buf, 4, "sending data"); + rc =3D tpm_transmit_cmd(chip, cmd, 4, "sending data"); dump_tpm_buf(cmd); =20 + /* Convert TPM error to -EPERM. */ if (rc > 0) - /* TPM error */ rc =3D -EPERM; =20 tpm_put_ops(chip); @@ -624,23 +620,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 @@ -650,14 +646,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); @@ -665,7 +662,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 119d5152c0db..0a99bd051a25 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -212,13 +212,20 @@ int tpm2_seal_trusted(struct tpm_chip *chip, struct trusted_key_options *options) { off_t offset =3D TPM_HEADER_SIZE; - struct tpm_buf buf, sized; int blob_len =3D 0; u32 hash; u32 flags; int i; int rc; =20 + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + struct tpm_buf *sized __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!sized) + return -ENOMEM; + for (i =3D 0; i < ARRAY_SIZE(tpm2_hash_map); i++) { if (options->hash =3D=3D tpm2_hash_map[i].crypto_id) { hash =3D tpm2_hash_map[i].tpm_id; @@ -240,91 +247,79 @@ 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) { - tpm2_end_auth_session(chip); - goto out_put; - } - - rc =3D tpm_buf_init_sized(&sized); - if (rc) { - tpm_buf_destroy(&buf); - tpm2_end_auth_session(chip); - goto out_put; - } - - tpm_buf_append_name(chip, &buf, options->keyhandle, NULL); - tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT, + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_init_sized(sized, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); + tpm_buf_append_name(chip, buf, options->keyhandle, NULL); + tpm_buf_append_hmac_session(chip, buf, TPM2_SA_DECRYPT, options->keyauth, TPM_DIGEST_SIZE); =20 /* sensitive */ - tpm_buf_append_u16(&sized, options->blobauth_len); + 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 - tpm_buf_fill_hmac_session(chip, &buf); - rc =3D tpm_transmit_cmd(chip, &buf, 4, "sealing data"); - rc =3D tpm_buf_check_hmac_response(chip, &buf, rc); + tpm_buf_fill_hmac_session(chip, buf); + 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); - if (blob_len < 0) - rc =3D blob_len; + blob_len =3D tpm2_key_encode(payload, options, &buf->data[offset], + blob_len); =20 out: - tpm_buf_destroy(&sized); - tpm_buf_destroy(&buf); - + if (blob_len < 0) + rc =3D blob_len; if (!rc) payload->blob_len =3D blob_len; =20 @@ -351,7 +346,6 @@ static int tpm2_load_cmd(struct tpm_chip *chip, struct trusted_key_options *options, u32 *blob_handle) { - struct tpm_buf buf; unsigned int private_len; unsigned int public_len; unsigned int blob_len; @@ -359,6 +353,10 @@ static int tpm2_load_cmd(struct tpm_chip *chip, int rc; u32 attrs; =20 + struct tpm_buf *buf __free(kfree) =3D kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + rc =3D tpm2_key_decode(payload, options, &blob); if (rc) { /* old form */ @@ -402,35 +400,30 @@ 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) { - tpm2_end_auth_session(chip); - return rc; - } - - tpm_buf_append_name(chip, &buf, options->keyhandle, NULL); - tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth, + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD); + tpm_buf_append_name(chip, buf, options->keyhandle, NULL); + 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) { + if (buf->flags & TPM_BUF_INVALID) { rc =3D -E2BIG; tpm2_end_auth_session(chip); goto out; } =20 - tpm_buf_fill_hmac_session(chip, &buf); - rc =3D tpm_transmit_cmd(chip, &buf, 4, "loading blob"); - rc =3D tpm_buf_check_hmac_response(chip, &buf, rc); + tpm_buf_fill_hmac_session(chip, buf); + 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]); + (__be32 *)&buf->data[TPM_HEADER_SIZE]); =20 out: if (blob !=3D payload->blob) kfree(blob); - tpm_buf_destroy(&buf); =20 return tpm_ret_to_err(rc); } @@ -453,26 +446,25 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, u32 blob_handle) { struct tpm_header *head; - struct tpm_buf buf; u16 data_len; int offset; 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_append_name(chip, &buf, blob_handle, NULL); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); + tpm_buf_append_name(chip, buf, blob_handle, NULL); =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 { @@ -481,39 +473,35 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, * the password will end up being unencrypted on the bus, as * HMAC nonce cannot be calculated for it. */ - 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); 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); } else { - offset =3D buf.handles * 4 + TPM_HEADER_SIZE; - head =3D (struct tpm_header *)buf.data; - if (tpm_buf_length(&buf) =3D=3D offset) + 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 - tpm_buf_fill_hmac_session(chip, &buf); - rc =3D tpm_transmit_cmd(chip, &buf, 6, "unsealing"); - rc =3D tpm_buf_check_hmac_response(chip, &buf, rc); + tpm_buf_fill_hmac_session(chip, buf); + 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 */ @@ -530,8 +518,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.39.5