From patchwork Tue May 21 15:26:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 13669511 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 A128B1465AF; Tue, 21 May 2024 15:27: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=1716305238; cv=none; b=YLHob7x7wRIWT1TS21So3JUeZrDFBLt7f5E6gB5hBmKrMM1MciHTnJA3IBJqhZrfkqXudI+Q81hobpB9i/1ObtsCv+6J4U9OGJhkLZJo4PkMeqkSg7MFLLpUHbnSkJlTBKKB4fturUz5YHhGmsiValvmmWeGybvf3urYGzlK6GA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716305238; c=relaxed/simple; bh=nn0VoJiLw3x3CMW67NfJ4kQdCy1dkZ6pA6m6663My+g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LSToZu1T64gBcX+kl5Orn52fPDrc8FslcAxpUjI4XT/3+vH40POFr4PiNYiIZO2j+3B7cDjNtGYE1AJpMsEev6iHqf2DnClFKP+FGVeZFtF595AaekqjtueXcTyls5XALH5up9wS6gs9bwwaMJmT7B2+Dsxml6k25iuejpBA/c4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bnogqpTF; 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="bnogqpTF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EBF83C2BD11; Tue, 21 May 2024 15:27:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1716305238; bh=nn0VoJiLw3x3CMW67NfJ4kQdCy1dkZ6pA6m6663My+g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bnogqpTFfB9ZxCiSnSB6DdFvqePmEIyAFNhb8JvYd21FgidSFxpWlaoLcvGtdUBbh WRpdaljYb6d2aMLmRygSxnS79cF+gQ5po2cTrwzw3P/XW+XkwumAjfSaxHC4QrMoq4 o4g4XFqiPQnmCfjfZpcVvs7WZ/SG7GCBH+U4sQ6fdpb2y1OAMY7vPYMVS7sxjHzm/M xquiukV7VQtDvJBqVWn8LfGTEbCx2JOfkBl85zlY6jElUCI2glvfPjAYob9Z5Zjl1o D7sTgSVLIL2RHBT6+0LA9RopL5BI2K9yayuI81nzzVpNDnBIPg3pLt771U+xsNvfYF 7kmXOi/iDbXww== From: Jarkko Sakkinen To: Herbert Xu Cc: linux-integrity@vger.kernel.org, keyrings@vger.kernel.org, Andreas.Fuchs@infineon.com, James Prestwood , David Woodhouse , Eric Biggers , James Bottomley , Jarkko Sakkinen , "David S. Miller" , linux-crypto@vger.kernel.org (open list:CRYPTO API), linux-kernel@vger.kernel.org (open list), Andrew Morton , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM) Subject: [PATCH v3 2/5] lib: Expand asn1_encode_integer() to variable size integers Date: Tue, 21 May 2024 18:26:44 +0300 Message-ID: <20240521152659.26438-3-jarkko@kernel.org> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20240521152659.26438-1-jarkko@kernel.org> References: <20240521152659.26438-1-jarkko@kernel.org> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Expand asn1_encode_integer() to variable size integers, meaning that it will get a blob in big-endian format as integer and length of the blob as parameters. This is required in order to encode RSA public key modulus. Signed-off-by: Jarkko Sakkinen --- v3: * Fix off-by-one in indices when returning zero: https://lore.kernel.org/linux-integrity/SN7PR18MB5314CFBD18B011F292809EBFE3EA2@SN7PR18MB5314.namprd18.prod.outlook.com/ --- include/linux/asn1_encoder.h | 3 +- lib/asn1_encoder.c | 185 ++++++++++++---------- security/keys/trusted-keys/trusted_tpm2.c | 4 +- 3 files changed, 103 insertions(+), 89 deletions(-) diff --git a/include/linux/asn1_encoder.h b/include/linux/asn1_encoder.h index 08cd0c2ad34f..ad5fb18db9e2 100644 --- a/include/linux/asn1_encoder.h +++ b/include/linux/asn1_encoder.h @@ -9,9 +9,10 @@ #include #define asn1_oid_len(oid) (sizeof(oid)/sizeof(u32)) + unsigned char * asn1_encode_integer(unsigned char *data, const unsigned char *end_data, - s64 integer); + const u8 *integer, int integer_len); unsigned char * asn1_encode_oid(unsigned char *data, const unsigned char *end_data, u32 oid[], int oid_len); diff --git a/lib/asn1_encoder.c b/lib/asn1_encoder.c index 0fd3c454a468..266e8042742e 100644 --- a/lib/asn1_encoder.c +++ b/lib/asn1_encoder.c @@ -9,12 +9,78 @@ #include #include #include +#include + +/** + * asn1_encode_length() - encode a length to follow an ASN.1 tag + * @data: pointer to encode at + * @data_len: pointer to remaining length (adjusted by routine) + * @len: length to encode + * + * This routine can encode lengths up to 65535 using the ASN.1 rules. + * It will accept a negative length and place a zero length tag + * instead (to keep the ASN.1 valid). This convention allows other + * encoder primitives to accept negative lengths as singalling the + * sequence will be re-encoded when the length is known. + */ +static int asn1_encode_length(unsigned char **data, int *data_len, int len) +{ + if (*data_len < 1) + return -EINVAL; + + if (len < 0) { + *((*data)++) = 0; + (*data_len)--; + return 0; + } + + if (len <= 0x7f) { + *((*data)++) = len; + (*data_len)--; + return 0; + } + + if (*data_len < 2) + return -EINVAL; + + if (len <= 0xff) { + *((*data)++) = 0x81; + *((*data)++) = len & 0xff; + *data_len -= 2; + return 0; + } + + if (*data_len < 3) + return -EINVAL; + + if (len <= 0xffff) { + *((*data)++) = 0x82; + *((*data)++) = (len >> 8) & 0xff; + *((*data)++) = len & 0xff; + *data_len -= 3; + return 0; + } + + if (WARN(len > 0xffffff, "ASN.1 length can't be > 0xffffff")) + return -EINVAL; + + if (*data_len < 4) + return -EINVAL; + *((*data)++) = 0x83; + *((*data)++) = (len >> 16) & 0xff; + *((*data)++) = (len >> 8) & 0xff; + *((*data)++) = len & 0xff; + *data_len -= 4; + + return 0; +} /** * asn1_encode_integer() - encode positive integer to ASN.1 - * @data: pointer to the pointer to the data - * @end_data: end of data pointer, points one beyond last usable byte in @data - * @integer: integer to be encoded + * @data: pointer to the pointer to the data + * @end_data: end of data pointer, points one beyond last usable byte in @data + * @integer: integer to be encoded + * @integer_len: length in bytes of the integer blob * * This is a simplified encoder: it only currently does * positive integers, but it should be simple enough to add the @@ -22,15 +88,17 @@ */ unsigned char * asn1_encode_integer(unsigned char *data, const unsigned char *end_data, - s64 integer) + const u8 *integer, int integer_len) { int data_len = end_data - data; - unsigned char *d = &data[2]; bool found = false; + unsigned char *d; + int encoded_len; + u8 *encoded; + int ret; int i; - if (WARN(integer < 0, - "BUG: integer encode only supports positive integers")) + if (WARN(!integer, "BUG: integer is null")) return ERR_PTR(-EINVAL); if (IS_ERR(data)) @@ -40,17 +108,22 @@ asn1_encode_integer(unsigned char *data, const unsigned char *end_data, if (data_len < 3) return ERR_PTR(-EINVAL); - /* remaining length where at d (the start of the integer encoding) */ - data_len -= 2; + (*data++) = _tag(UNIV, PRIM, INT); + data_len--; - data[0] = _tag(UNIV, PRIM, INT); - if (integer == 0) { - *d++ = 0; - goto out; + if (!memchr_inv(integer, 0, integer_len)) { + data[0] = 1; + data[1] = 0; + return &data[2]; } - for (i = sizeof(integer); i > 0 ; i--) { - int byte = integer >> (8 * (i - 1)); + encoded = kzalloc(integer_len, GFP_KERNEL); + if (!encoded) + return ERR_PTR(-ENOMEM); + d = encoded; + + for (i = 0; i < integer_len; i++) { + int byte = integer[i]; if (!found && byte == 0) continue; @@ -67,21 +140,23 @@ asn1_encode_integer(unsigned char *data, const unsigned char *end_data, * have len >= 1 */ *d++ = 0; - data_len--; } found = true; - if (data_len == 0) - return ERR_PTR(-EINVAL); - *d++ = byte; - data_len--; } - out: - data[1] = d - data - 2; + encoded_len = d - encoded; - return d; + ret = asn1_encode_length(&data, &data_len, encoded_len); + if (ret) { + kfree(encoded); + return ERR_PTR(ret); + } + + memcpy(data, encoded, encoded_len); + kfree(encoded); + return data + encoded_len; } EXPORT_SYMBOL_GPL(asn1_encode_integer); @@ -176,70 +251,6 @@ asn1_encode_oid(unsigned char *data, const unsigned char *end_data, } EXPORT_SYMBOL_GPL(asn1_encode_oid); -/** - * asn1_encode_length() - encode a length to follow an ASN.1 tag - * @data: pointer to encode at - * @data_len: pointer to remaining length (adjusted by routine) - * @len: length to encode - * - * This routine can encode lengths up to 65535 using the ASN.1 rules. - * It will accept a negative length and place a zero length tag - * instead (to keep the ASN.1 valid). This convention allows other - * encoder primitives to accept negative lengths as singalling the - * sequence will be re-encoded when the length is known. - */ -static int asn1_encode_length(unsigned char **data, int *data_len, int len) -{ - if (*data_len < 1) - return -EINVAL; - - if (len < 0) { - *((*data)++) = 0; - (*data_len)--; - return 0; - } - - if (len <= 0x7f) { - *((*data)++) = len; - (*data_len)--; - return 0; - } - - if (*data_len < 2) - return -EINVAL; - - if (len <= 0xff) { - *((*data)++) = 0x81; - *((*data)++) = len & 0xff; - *data_len -= 2; - return 0; - } - - if (*data_len < 3) - return -EINVAL; - - if (len <= 0xffff) { - *((*data)++) = 0x82; - *((*data)++) = (len >> 8) & 0xff; - *((*data)++) = len & 0xff; - *data_len -= 3; - return 0; - } - - if (WARN(len > 0xffffff, "ASN.1 length can't be > 0xffffff")) - return -EINVAL; - - if (*data_len < 4) - return -EINVAL; - *((*data)++) = 0x83; - *((*data)++) = (len >> 16) & 0xff; - *((*data)++) = (len >> 8) & 0xff; - *((*data)++) = len & 0xff; - *data_len -= 4; - - return 0; -} - /** * asn1_encode_tag() - add a tag for optional or explicit value * @data: pointer to place tag at diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c index 8b7dd73d94c1..ec59f9389a2d 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -38,6 +38,7 @@ static int tpm2_key_encode(struct trusted_key_payload *payload, u8 *end_work = scratch + SCRATCH_SIZE; u8 *priv, *pub; u16 priv_len, pub_len; + u32 key_handle; int ret; priv_len = get_unaligned_be16(src) + 2; @@ -77,7 +78,8 @@ static int tpm2_key_encode(struct trusted_key_payload *payload, goto err; } - work = asn1_encode_integer(work, end_work, options->keyhandle); + key_handle = cpu_to_be32(options->keyhandle); + work = asn1_encode_integer(work, end_work, (u8 *)&key_handle, 4); work = asn1_encode_octet_string(work, end_work, pub, pub_len); work = asn1_encode_octet_string(work, end_work, priv, priv_len); From patchwork Tue May 21 15:26:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 13669512 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 D54AA1448DA; Tue, 21 May 2024 15:27: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=1716305245; cv=none; b=MywJFdpPmlGjDe89iL4L+Trx6jmWdfk5azZ1Wqm7Pb2R2OQ1xgwChfEzgflDkqTp6e9b3tjIC/o/mUFOWV6JEgKdVMaaTogxwePTWZPSCsRFYvkczb74tVoDt4jAueZb7MFTfuQA9Z4RMFaOgxgT1ImudiCmSWM251/vXbzrho8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716305245; c=relaxed/simple; bh=n3cIMYf7xZGCzgAkDDAlFx85xEycCwosKadBNAn25Vw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oNomV9GpCObkx7LZSkOLR5NI/CY/p6BCv0muY4c5Ir4eSrKGTDs2dcxo7h2/SQRELTSFs975X4E1vILFwb7OS9ErLSNLOqVqgWhGLmmqlcIuQz+CHKtSpYGY+OhEad+vBBDKuQHwjMlnzSA5zLtp4CQKqdl/kTInNArx3wwqz/8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=s6XDKkwk; 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="s6XDKkwk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3E4E8C2BD11; Tue, 21 May 2024 15:27:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1716305244; bh=n3cIMYf7xZGCzgAkDDAlFx85xEycCwosKadBNAn25Vw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=s6XDKkwkJKXKxOR7+UIU7JQw1MCYE8FmLz/RrSSYYXzc1+8UfDRjppXtxknlb3VaB 7Gqz/L+hnDAAg4aeI3LPCziJcH0CkDTa6xZRuxgME+tpEsFxHl6b5HltUdlmlaTeaE uO/YarHQVgavvPQsuRVE2snzeo936BsF14s5CJ5Hv3ex3vmSMRtIHJL7h2K019rA/k dclf0bpwGr2dC4Grxfcv46arXJv8wqlgKk0FeeTah+XKtqHzTr+I4DRVQyGV2aBp5m ro38BXcoeoi7ryEc4TQ0A3gqFW1jrGQrolDHLvsUDNxP7Uv4o5laNAt9SFgiQIcbAd lOeSAePWCZ6Dw== From: Jarkko Sakkinen To: Herbert Xu Cc: linux-integrity@vger.kernel.org, keyrings@vger.kernel.org, Andreas.Fuchs@infineon.com, James Prestwood , David Woodhouse , Eric Biggers , James Bottomley , Jarkko Sakkinen , "David S. Miller" , linux-crypto@vger.kernel.org (open list:CRYPTO API), linux-kernel@vger.kernel.org (open list), Peter Huewe , Jason Gunthorpe , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM) Subject: [PATCH v3 3/5] KEYS: trusted: Move tpm2_key_decode() to the TPM driver Date: Tue, 21 May 2024 18:26:45 +0300 Message-ID: <20240521152659.26438-4-jarkko@kernel.org> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20240521152659.26438-1-jarkko@kernel.org> References: <20240521152659.26438-1-jarkko@kernel.org> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Move tpm2_key_decode() to the TPM driver and export the symbols to make them callable from trusted keys. It can re-used for asymmetric keys. Signed-off-by: Jarkko Sakkinen --- v2: Do not allocate blob twice. Use the one inside struct tpm2_key. --- drivers/char/tpm/Kconfig | 1 + drivers/char/tpm/Makefile | 5 + drivers/char/tpm/tpm2_key.c | 111 +++++++++++++++ .../char/tpm}/tpm2key.asn1 | 0 include/crypto/tpm2_key.h | 33 +++++ security/keys/trusted-keys/Makefile | 2 - security/keys/trusted-keys/trusted_tpm2.c | 127 +++--------------- 7 files changed, 167 insertions(+), 112 deletions(-) create mode 100644 drivers/char/tpm/tpm2_key.c rename {security/keys/trusted-keys => drivers/char/tpm}/tpm2key.asn1 (100%) create mode 100644 include/crypto/tpm2_key.h diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index e63a6a17793c..de2f4093c939 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -7,6 +7,7 @@ menuconfig TCG_TPM tristate "TPM Hardware Support" depends on HAS_IOMEM imply SECURITYFS + select ASN1 select CRYPTO select CRYPTO_HASH_INFO help diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 4c695b0388f3..071437058ef6 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -17,6 +17,11 @@ tpm-y += eventlog/tpm1.o tpm-y += eventlog/tpm2.o tpm-y += tpm-buf.o +# TPM2 Asymmetric Key +$(obj)/trusted_tpm2.o: $(obj)/tpm2key.asn1.h +tpm-y += tpm2key.asn1.o +tpm-y += tpm2_key.o + tpm-$(CONFIG_TCG_TPM2_HMAC) += tpm2-sessions.o tpm-$(CONFIG_ACPI) += tpm_ppi.o eventlog/acpi.o tpm-$(CONFIG_EFI) += eventlog/efi.o diff --git a/drivers/char/tpm/tpm2_key.c b/drivers/char/tpm/tpm2_key.c new file mode 100644 index 000000000000..0112362e432e --- /dev/null +++ b/drivers/char/tpm/tpm2_key.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include "tpm2key.asn1.h" + +#undef pr_fmt +#define pr_fmt(fmt) "tpm2_key: "fmt + +int tpm2_key_parent(void *context, size_t hdrlen, + unsigned char tag, + const void *value, size_t vlen) +{ + struct tpm2_key *ctx = context; + const u8 *v = value; + int i; + + ctx->parent = 0; + for (i = 0; i < vlen; i++) { + ctx->parent <<= 8; + ctx->parent |= v[i]; + } + + return 0; +} + +int tpm2_key_type(void *context, size_t hdrlen, + unsigned char tag, + const void *value, size_t vlen) +{ + enum OID oid = look_up_OID(value, vlen); + + if (oid != OID_TPMSealedData) { + char buffer[50]; + + sprint_oid(value, vlen, buffer, sizeof(buffer)); + pr_debug("OID is \"%s\" which is not TPMSealedData\n", + buffer); + return -EINVAL; + } + + return 0; +} + +int tpm2_key_pub(void *context, size_t hdrlen, + unsigned char tag, + const void *value, size_t vlen) +{ + struct tpm2_key *ctx = context; + + ctx->pub = value; + ctx->pub_len = vlen; + + return 0; +} + +int tpm2_key_priv(void *context, size_t hdrlen, + unsigned char tag, + const void *value, size_t vlen) +{ + struct tpm2_key *ctx = context; + + ctx->priv = value; + ctx->priv_len = vlen; + + return 0; +} + +/** + * tpm_key_decode() - Decode TPM2 ASN.1 key. + * @src: ASN.1 source. + * @src_len: ASN.1 source length. + * @key: TPM2 asymmetric key. + * @max_key_len: Maximum length of the TPM2 asymmetric key. + * + * Decodes TPM2 ASN.1 key on success. Returns POSIX error code on failure. + */ +int tpm2_key_decode(const u8 *src, u32 src_len, struct tpm2_key *key, + u32 max_key_len) +{ + struct tpm2_key ctx; + u32 blob_len; + int ret; + + memset(&ctx, 0, sizeof(ctx)); + + ret = asn1_ber_decoder(&tpm2key_decoder, &ctx, src, src_len); + if (ret < 0) + return ret; + + blob_len = ctx.priv_len + ctx.pub_len; + if (blob_len > max_key_len) + return -E2BIG; + + ctx.blob_len = blob_len; + ctx.blob = kmalloc(blob_len, GFP_KERNEL); + if (!ctx.blob) + return -ENOMEM; + + memcpy((void *)ctx.blob, ctx.priv, ctx.priv_len); + memcpy((void *)ctx.blob + ctx.priv_len, ctx.pub, ctx.pub_len); + ctx.priv = ctx.blob; + ctx.pub = ctx.blob + ctx.priv_len; + + memcpy(key, &ctx, sizeof(ctx)); + return 0; +} +EXPORT_SYMBOL_GPL(tpm2_key_decode); diff --git a/security/keys/trusted-keys/tpm2key.asn1 b/drivers/char/tpm/tpm2key.asn1 similarity index 100% rename from security/keys/trusted-keys/tpm2key.asn1 rename to drivers/char/tpm/tpm2key.asn1 diff --git a/include/crypto/tpm2_key.h b/include/crypto/tpm2_key.h new file mode 100644 index 000000000000..acf41b2e0c92 --- /dev/null +++ b/include/crypto/tpm2_key.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __LINUX_TPM2_KEY_H__ +#define __LINUX_TPM2_KEY_H__ + +#include + +/* + * TPM2 ASN.1 key + */ +struct tpm2_key { + u32 parent; + const u8 *blob; + u32 blob_len; + const u8 *pub; + u32 pub_len; + const u8 *priv; + u32 priv_len; +}; + +int tpm2_key_decode(const u8 *src, u32 src_len, struct tpm2_key *key, + u32 max_key_len); + +/** + * tpm2_key_free() - Release TPM2 asymmetric key resources and reset values + * @key: TPM2 asymmetric key. + */ +static inline void tpm2_key_destroy(struct tpm2_key *key) +{ + kfree(key->blob); + memset(key, 0, sizeof(*key)); +} + +#endif /* __LINUX_TPM2_KEY_H__ */ diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-keys/Makefile index f0f3b27f688b..2674d5c10fc9 100644 --- a/security/keys/trusted-keys/Makefile +++ b/security/keys/trusted-keys/Makefile @@ -7,9 +7,7 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o trusted-y += trusted_core.o trusted-$(CONFIG_TRUSTED_KEYS_TPM) += trusted_tpm1.o -$(obj)/trusted_tpm2.o: $(obj)/tpm2key.asn1.h trusted-$(CONFIG_TRUSTED_KEYS_TPM) += trusted_tpm2.o -trusted-$(CONFIG_TRUSTED_KEYS_TPM) += tpm2key.asn1.o trusted-$(CONFIG_TRUSTED_KEYS_TEE) += trusted_tee.o diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c index ec59f9389a2d..f255388d32b8 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -13,11 +13,10 @@ #include #include +#include #include -#include "tpm2key.asn1.h" - static struct tpm2_hash tpm2_hash_map[] = { {HASH_ALGO_SHA1, TPM_ALG_SHA1}, {HASH_ALGO_SHA256, TPM_ALG_SHA256}, @@ -28,9 +27,9 @@ static struct tpm2_hash tpm2_hash_map[] = { static u32 tpm2key_oid[] = { 2, 23, 133, 10, 1, 5 }; -static int tpm2_key_encode(struct trusted_key_payload *payload, - struct trusted_key_options *options, - u8 *src, u32 len) +static int tpm2_trusted_key_encode(struct trusted_key_payload *payload, + struct trusted_key_options *options, + u8 *src, u32 len) { const int SCRATCH_SIZE = PAGE_SIZE; u8 *scratch = kmalloc(SCRATCH_SIZE, GFP_KERNEL); @@ -100,106 +99,6 @@ static int tpm2_key_encode(struct trusted_key_payload *payload, return ret; } -struct tpm2_key_context { - u32 parent; - const u8 *pub; - u32 pub_len; - const u8 *priv; - u32 priv_len; -}; - -static int tpm2_key_decode(struct trusted_key_payload *payload, - struct trusted_key_options *options, - u8 **buf) -{ - int ret; - struct tpm2_key_context ctx; - u8 *blob; - - memset(&ctx, 0, sizeof(ctx)); - - ret = asn1_ber_decoder(&tpm2key_decoder, &ctx, payload->blob, - payload->blob_len); - if (ret < 0) - return ret; - - if (ctx.priv_len + ctx.pub_len > MAX_BLOB_SIZE) - return -EINVAL; - - blob = kmalloc(ctx.priv_len + ctx.pub_len + 4, GFP_KERNEL); - if (!blob) - return -ENOMEM; - - *buf = blob; - options->keyhandle = ctx.parent; - - memcpy(blob, ctx.priv, ctx.priv_len); - blob += ctx.priv_len; - - memcpy(blob, ctx.pub, ctx.pub_len); - - return 0; -} - -int tpm2_key_parent(void *context, size_t hdrlen, - unsigned char tag, - const void *value, size_t vlen) -{ - struct tpm2_key_context *ctx = context; - const u8 *v = value; - int i; - - ctx->parent = 0; - for (i = 0; i < vlen; i++) { - ctx->parent <<= 8; - ctx->parent |= v[i]; - } - - return 0; -} - -int tpm2_key_type(void *context, size_t hdrlen, - unsigned char tag, - const void *value, size_t vlen) -{ - enum OID oid = look_up_OID(value, vlen); - - if (oid != OID_TPMSealedData) { - char buffer[50]; - - sprint_oid(value, vlen, buffer, sizeof(buffer)); - pr_debug("OID is \"%s\" which is not TPMSealedData\n", - buffer); - return -EINVAL; - } - - return 0; -} - -int tpm2_key_pub(void *context, size_t hdrlen, - unsigned char tag, - const void *value, size_t vlen) -{ - struct tpm2_key_context *ctx = context; - - ctx->pub = value; - ctx->pub_len = vlen; - - return 0; -} - -int tpm2_key_priv(void *context, size_t hdrlen, - unsigned char tag, - const void *value, size_t vlen) -{ - struct tpm2_key_context *ctx = context; - - ctx->priv = value; - ctx->priv_len = vlen; - - return 0; -} - /** * tpm2_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer. * @@ -349,7 +248,8 @@ int tpm2_seal_trusted(struct tpm_chip *chip, goto out; } - blob_len = tpm2_key_encode(payload, options, &buf.data[offset], blob_len); + blob_len = tpm2_trusted_key_encode(payload, options, &buf.data[offset], + blob_len); out: tpm_buf_destroy(&sized); @@ -389,21 +289,27 @@ 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; - u8 *blob, *pub; + struct tpm2_key key; + struct tpm_buf buf; + const u8 *blob, *pub; int rc; u32 attrs; - rc = tpm2_key_decode(payload, options, &blob); + rc = tpm2_key_decode(payload->blob, payload->blob_len, &key, PAGE_SIZE); if (rc) { /* old form */ blob = payload->blob; payload->old_format = 1; + } else { + blob = key.blob; } + if (!blob) + return -ENOMEM; + /* new format carries keyhandle but old format doesn't */ if (!options->keyhandle) return -EINVAL; @@ -467,7 +373,8 @@ static int tpm2_load_cmd(struct tpm_chip *chip, out: if (blob != payload->blob) - kfree(blob); + tpm2_key_destroy(&key); + tpm_buf_destroy(&buf); if (rc > 0) From patchwork Tue May 21 15:26:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 13669513 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 4B3D7146D77; Tue, 21 May 2024 15:27:29 +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=1716305249; cv=none; b=Sm5+MZU+rZdjfBVLua8Hflg/mUJUnwHF8DQrHYU6gz01QHBq08IZGQ1/xFpUbFUZkTbRJYUttGgqa6QV+cOG0CIWIYunttLeM38qquSN3YtEVcpOw6lsuOjdireZugF/54xmxWIjF8ZEVWICWlcIkCY9fusbEymO+jEgerqFUpE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716305249; c=relaxed/simple; bh=zi66issw9MiUi8Zz5qR+3SdBH1g6liWWaQWZQngxkW0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jSnBVl1sVHg6w/rJHpkkYZRZtPZpvKNAGz8rvlQu/jE1MGyfVbtNy8ixhhffznqmsP+28sUrw7fKvhaqzKAClW+NBUcwcVDvGuVd2cbUUxcn4wcdL3YCSRCIN9c5/FXDm1Vt9rUQEMtsp5d1uSMlFmnTtnlMHzKTgHns3nqVr3w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mvatreaw; 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="mvatreaw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 76D73C2BD11; Tue, 21 May 2024 15:27:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1716305249; bh=zi66issw9MiUi8Zz5qR+3SdBH1g6liWWaQWZQngxkW0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mvatreawEq355t8Gw/Bq8zGwK0yyo+Qa7G7CsSNi9NDKp9fuv2UAPAM0px69HdEMY hGJkHOD4g2Xc60Q94jEDzaYykpHbH/F8pGTQnu1mzEST67YM5423/lVkGC4vbZPO8b lmgVD0Rqd+JD4v0VsnRPlWTu55CAfIZwZwET8tdt3SESlxkUKiH64GR6xMXhZ09HJi YszETIgyp75Z3JVZxD4INNKfgvRMKKH7wmvqsQK/35Vu8KAp8rDUppbtnzKiLIKoMj VzcX7BUHDZHYyUwi0wE1b8Jfte7iRuWbDCJClju6CAegZ7A/dg6DJk7N/wJxaQAfiA 8VkdDABmPGHUg== From: Jarkko Sakkinen To: Herbert Xu Cc: linux-integrity@vger.kernel.org, keyrings@vger.kernel.org, Andreas.Fuchs@infineon.com, James Prestwood , David Woodhouse , Eric Biggers , James Bottomley , Jarkko Sakkinen , "David S. Miller" , linux-crypto@vger.kernel.org (open list:CRYPTO API), linux-kernel@vger.kernel.org (open list), Peter Huewe , Jason Gunthorpe , James Bottomley , Mimi Zohar , David Howells , Paul Moore , James Morris , "Serge E. Hallyn" , linux-security-module@vger.kernel.org (open list:SECURITY SUBSYSTEM) Subject: [PATCH v3 4/5] tpm: tpm2_key: Extend parser to TPM_LoadableKey Date: Tue, 21 May 2024 18:26:46 +0300 Message-ID: <20240521152659.26438-5-jarkko@kernel.org> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20240521152659.26438-1-jarkko@kernel.org> References: <20240521152659.26438-1-jarkko@kernel.org> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Extend parser to TPM_LoadableKey. Add field for oid to struct tpm2_key so that callers can differentiate different key types. Signed-off-by: Jarkko Sakkinen --- v3: * Fixup klog messages: https://lore.kernel.org/linux-integrity/SN7PR18MB53140F4341BC441C1C11586EE3EA2@SN7PR18MB5314.namprd18.prod.outlook.com/ --- drivers/char/tpm/tpm2_key.c | 17 ++++++++++++----- include/crypto/tpm2_key.h | 2 ++ security/keys/trusted-keys/trusted_tpm2.c | 4 ++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/char/tpm/tpm2_key.c b/drivers/char/tpm/tpm2_key.c index 0112362e432e..06be1cc0156b 100644 --- a/drivers/char/tpm/tpm2_key.c +++ b/drivers/char/tpm/tpm2_key.c @@ -32,16 +32,23 @@ int tpm2_key_type(void *context, size_t hdrlen, const void *value, size_t vlen) { enum OID oid = look_up_OID(value, vlen); - - if (oid != OID_TPMSealedData) { + struct tpm2_key *key = context; + + switch (oid) { + case OID_TPMSealedData: + pr_debug("TPMSealedData\n"); + break; + case OID_TPMLoadableKey: + pr_debug("TPMLodableKey\n"); + break; + default: char buffer[50]; - sprint_oid(value, vlen, buffer, sizeof(buffer)); - pr_debug("OID is \"%s\" which is not TPMSealedData\n", - buffer); + pr_debug("Unknown OID \"%s\"\n", buffer); return -EINVAL; } + key->oid = oid; return 0; } diff --git a/include/crypto/tpm2_key.h b/include/crypto/tpm2_key.h index acf41b2e0c92..2d2434233000 100644 --- a/include/crypto/tpm2_key.h +++ b/include/crypto/tpm2_key.h @@ -2,12 +2,14 @@ #ifndef __LINUX_TPM2_KEY_H__ #define __LINUX_TPM2_KEY_H__ +#include #include /* * TPM2 ASN.1 key */ struct tpm2_key { + enum OID oid; u32 parent; const u8 *blob; u32 blob_len; diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c index f255388d32b8..ce4c667c3ee3 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -305,6 +305,10 @@ static int tpm2_load_cmd(struct tpm_chip *chip, payload->old_format = 1; } else { blob = key.blob; + if (key.oid != OID_TPMSealedData) { + tpm2_key_destroy(&key); + return -EINVAL; + } } if (!blob)