2024-05-23 21:26:09

by Jarkko Sakkinen

[permalink] [raw]
Subject: [PATCH v5 0/5] KEYS: asymmetric: tpm2_key_rsa

## Overview

Introduce tpm2_key_rsa module, which implements asymmetric TPM2 RSA key.
The feature can be enabled with the CONFIG_ASYMMETRIC_TPM2_KEY_RSA_SUBTYPE
kconfig option. This feature allows the private key to be uploaded to
the TPM2 for signing, and software can use the public key to verify
the signatures.

The idea in the design is to over time to have submodule per key type
For instance, tpm2_key_ecdsa could be one potential future addition in
the future. Perhaps, it might sense to consider at that point also a
top-level tpm2_key module. The gist is that the naming convention is
free from potential future bottlencks.

### Testing

tpm2_createprimary --hierarchy o -G rsa2048 -c owner.txt
tpm2_evictcontrol -c owner.txt 0x81000001
tpm2_getcap handles-persistent
openssl genrsa -out private.pem 2048
tpm2_import -C 0x81000001 -G rsa -i private.pem -u key.pub -r key.priv
tpm2_encodeobject -C 0x81000001 -u key.pub -r key.priv -o key.priv.pem
openssl asn1parse -inform pem -in key.priv.pem -noout -out key.priv.der
serial=`cat key.priv.der | keyctl padd asymmetric tpm @u`
echo "abcdefg" > plaintext.txt
keyctl pkey_encrypt $serial 0 plaintext.txt enc=pkcs1 > encrypted.dat
keyctl pkey_decrypt $serial 0 encrypted.dat enc=pkcs1 > decrypted.dat
keyctl pkey_sign $serial 0 plaintext.txt enc=pkcs1 hash=sha256 > signed.dat
keyctl pkey_verify $serial 0 plaintext.txt signed.dat enc=pkcs1 hash=sha256

## References

- v4: https://lore.kernel.org/linux-integrity/[email protected]/
- v3: https://lore.kernel.org/linux-integrity/[email protected]/
- v2: https://lore.kernel.org/linux-integrity/[email protected]/
- v1: https://lore.kernel.org/linux-integrity/[email protected]/
- Derived from https://lore.kernel.org/all/[email protected]/

James Prestwood (1):
keys: asymmetric: ASYMMETRIC_TPM2_KEY_RSA_SUBTYPE

Jarkko Sakkinen (4):
crypto: rsa-pkcs1pad: export rsa1_asn_lookup()
KEYS: trusted: Change -EINVAL to -E2BIG
KEYS: trusted: Move tpm2_key_decode() to the TPM driver
tpm: tpm2_key: Extend parser to TPM_LoadableKey

crypto/asymmetric_keys/Kconfig | 15 +
crypto/asymmetric_keys/Makefile | 1 +
crypto/asymmetric_keys/tpm2_key_rsa.c | 680 ++++++++++++++++++
crypto/rsa-pkcs1pad.c | 16 +-
drivers/char/tpm/Kconfig | 1 +
drivers/char/tpm/Makefile | 5 +
drivers/char/tpm/tpm2_key.c | 118 +++
.../char/tpm}/tpm2key.asn1 | 0
include/crypto/rsa-pkcs1pad.h | 20 +
include/crypto/tpm2_key.h | 35 +
include/linux/tpm.h | 2 +
security/keys/trusted-keys/Makefile | 2 -
security/keys/trusted-keys/trusted_tpm2.c | 131 +---
13 files changed, 908 insertions(+), 118 deletions(-)
create mode 100644 crypto/asymmetric_keys/tpm2_key_rsa.c
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/rsa-pkcs1pad.h
create mode 100644 include/crypto/tpm2_key.h

--
2.45.1



2024-05-23 21:26:23

by Jarkko Sakkinen

[permalink] [raw]
Subject: [PATCH v5 1/5] crypto: rsa-pkcs1pad: export rsa1_asn_lookup()

ASN.1 template is required for TPM2 asymmetric keys, as it needs to be
piggy-packed with the input data before applying TPM2_RSA_Decrypt. This
patch prepares crypto subsystem for the addition of those keys.

Signed-off-by: Jarkko Sakkinen <[email protected]>
---
crypto/rsa-pkcs1pad.c | 16 ++++++++++------
include/crypto/rsa-pkcs1pad.h | 20 ++++++++++++++++++++
2 files changed, 30 insertions(+), 6 deletions(-)
create mode 100644 include/crypto/rsa-pkcs1pad.h

diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index cd501195f34a..00b6c14f861c 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -7,6 +7,7 @@

#include <crypto/algapi.h>
#include <crypto/akcipher.h>
+#include <crypto/rsa-pkcs1pad.h>
#include <crypto/internal/akcipher.h>
#include <crypto/internal/rsa.h>
#include <linux/err.h>
@@ -79,11 +80,7 @@ static const u8 rsa_digest_info_sha3_512[] = {
0x05, 0x00, 0x04, 0x40
};

-static const struct rsa_asn1_template {
- const char *name;
- const u8 *data;
- size_t size;
-} rsa_asn1_templates[] = {
+static const struct rsa_asn1_template rsa_asn1_templates[] = {
#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
_(md5),
_(sha1),
@@ -101,7 +98,13 @@ static const struct rsa_asn1_template {
{ NULL }
};

-static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
+/**
+ * rsa_lookup_asn1() - Lookup the ASN.1 digest info given the hash
+ * name: hash algorithm name
+ *
+ * Returns the ASN.1 digest info on success, and NULL on failure.
+ */
+const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
{
const struct rsa_asn1_template *p;

@@ -110,6 +113,7 @@ static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
return p;
return NULL;
}
+EXPORT_SYMBOL_GPL(rsa_lookup_asn1);

struct pkcs1pad_ctx {
struct crypto_akcipher *child;
diff --git a/include/crypto/rsa-pkcs1pad.h b/include/crypto/rsa-pkcs1pad.h
new file mode 100644
index 000000000000..32c7453ff644
--- /dev/null
+++ b/include/crypto/rsa-pkcs1pad.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * RSA padding templates.
+ */
+
+#ifndef _CRYPTO_RSA_PKCS1PAD_H
+#define _CRYPTO_RSA_PKCS1PAD_H
+
+/*
+ * Hash algorithm name to ASN.1 template mapping.
+ */
+struct rsa_asn1_template {
+ const char *name;
+ const u8 *data;
+ size_t size;
+};
+
+const struct rsa_asn1_template *rsa_lookup_asn1(const char *name);
+
+#endif /* _CRYPTO_RSA_PKCS1PAD_H */
--
2.45.1


2024-05-23 21:26:36

by Jarkko Sakkinen

[permalink] [raw]
Subject: [PATCH v5 2/5] KEYS: trusted: Change -EINVAL to -E2BIG

Report -E2BIG instead of -EINVAL when too large size for the key blob is
requested.

Signed-off-by: Jarkko Sakkinen <[email protected]>
---
security/keys/trusted-keys/trusted_tpm2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
index d478096cb5c1..7317e07440c3 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -122,7 +122,7 @@ static int tpm2_key_decode(struct trusted_key_payload *payload,
return ret;

if (ctx.priv_len + ctx.pub_len > MAX_BLOB_SIZE)
- return -EINVAL;
+ return -E2BIG;

blob = kmalloc(ctx.priv_len + ctx.pub_len + 4, GFP_KERNEL);
if (!blob)
--
2.45.1


2024-05-23 21:26:52

by Jarkko Sakkinen

[permalink] [raw]
Subject: [PATCH v5 3/5] KEYS: trusted: Move tpm2_key_decode() to the TPM driver

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 <[email protected]>
---
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..7662b2cb85bf
--- /dev/null
+++ b/drivers/char/tpm/tpm2_key.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/oid_registry.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <crypto/tpm2_key.h>
+#include <asm/unaligned.h>
+#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: Cap the maximum length for the blob allocation.
+ *
+ * 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 <linux/slab.h>
+
+/*
+ * 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 7317e07440c3..e0bd1a2fc2ca 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -13,11 +13,10 @@

#include <keys/trusted-type.h>
#include <keys/trusted_tpm.h>
+#include <crypto/tpm2_key.h>

#include <asm/unaligned.h>

-#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 const u8 OID_TPMSealedData_ASN1[] = {0x06, 0x06, 0x67, 0x81, 0x05, 0x0a, 0x01, 0x05};

-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);
@@ -98,106 +97,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 -E2BIG;
-
- 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.
*
@@ -347,7 +246,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);
@@ -387,21 +287,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;
@@ -465,7 +371,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)
--
2.45.1


2024-05-23 21:27:26

by Jarkko Sakkinen

[permalink] [raw]
Subject: [PATCH v5 4/5] tpm: tpm2_key: Extend parser to TPM_LoadableKey

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 <[email protected]>
---
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 7662b2cb85bf..b5c07288eff5 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 <linux/oid_registry.h>
#include <linux/slab.h>

/*
* 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 e0bd1a2fc2ca..5b4555dd13e5 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -303,6 +303,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)
--
2.45.1


2024-05-24 09:20:20

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH v5 0/5] KEYS: asymmetric: tpm2_key_rsa

On Fri May 24, 2024 at 12:25 AM EEST, Jarkko Sakkinen wrote:
> ## Overview
>
> Introduce tpm2_key_rsa module, which implements asymmetric TPM2 RSA key.
> The feature can be enabled with the CONFIG_ASYMMETRIC_TPM2_KEY_RSA_SUBTYPE
> kconfig option. This feature allows the private key to be uploaded to
> the TPM2 for signing, and software can use the public key to verify
> the signatures.

Since barely v6.9 is out I wrote over night also tpm2_key_ecdsa i.e.
ECC/ECDSA based module :-)

It was a good idea. I realized e.g. actually documented in the API
fact that I should return -EBADMSG as legit undetected. Also found
a memory corruption bugs.

I renamed extract_pub to probe because that made me sort of realized
the role better too. Some of the code could later on put to up-level
struct tpm2_key but it is not a functional requirement.

I.e. top-level does raw parsing and then these modules check each
that if this is for them (e.g. ECDSA) then eat it. Otherwise, pass
over.

I did do some rudimentary testing and it seems to be quite good, and
my pattern seems to work. I.e. different modules for RSA and ECDSA
fit well how asymmetric keys are probed and allows to do as a sysadmin
appropriate configuration for the use case.

My biggest concern is undocumented parameters API in akcipher.

BR, Jarkko