tpmdd-devel Archive on lore.kernel.org
 help / color / Atom feed
From: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
To: denkenz-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org
Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	keyrings-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: [PATCH 23/23] TPM: Add an asymmetric key subtype for handling TPM-based keys
Date: Tue, 21 Aug 2018 16:59:25 +0100
Message-ID: <153486716525.13066.18042327896429419884.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>

Add an asymmetric key subtype for handling keys that have to be loaded into
the TPM to be used.

A key can be created by something like:

	keyctl add asymmetric "a" "tpm_create parent=40000000,095c2a76085f6aa9327c62f72a3d1348f62b99db keyauth=095c2a76085f6aa9327c62f72a3d1348f62b99db" @s

where "parent=<parent_key_handle>,<parent_key_secret>" and
"keyauth=<new_key_secret>".

The above will ask the TPM to create a key and return the TPM_KEY struct as a
blob with the private key encrypted by the parent key (in the above case, the
SRK).

Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---

 crypto/asymmetric_keys/Kconfig          |    7 +
 crypto/asymmetric_keys/Makefile         |    1 
 crypto/asymmetric_keys/tpm_key.c        |   73 +++++++++++
 crypto/asymmetric_keys/tpm_key.h        |   19 +++
 crypto/asymmetric_keys/tpm_key_parser.c |  212 +++++++++++++++++++++++++++++++
 5 files changed, 312 insertions(+)
 create mode 100644 crypto/asymmetric_keys/tpm_key.c
 create mode 100644 crypto/asymmetric_keys/tpm_key.h
 create mode 100644 crypto/asymmetric_keys/tpm_key_parser.c

diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 4870f28403f5..97d1bb714617 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -67,4 +67,11 @@ config SIGNED_PE_FILE_VERIFICATION
 	  This option provides support for verifying the signature(s) on a
 	  signed PE binary.
 
+config ASYMMETRIC_TPM_KEY_SUBTYPE
+	tristate "Asymmetric TPM-based public-key crypto algorithm subtype"
+	depends on TCG_TPM
+	help
+	  This option provides support for TPM hardware-based asymmetric public
+	  key type handling.
+
 endif # ASYMMETRIC_KEY_TYPE
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index e47fcd9ac5e8..690c16a517a9 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
 asymmetric_keys-y := asymmetric_type.o signature.o
 
 obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
+obj-$(CONFIG_ASYMMETRIC_TPM_KEY_SUBTYPE) += tpm_key.o tpm_key_parser.o
 obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
 
 #
diff --git a/crypto/asymmetric_keys/tpm_key.c b/crypto/asymmetric_keys/tpm_key.c
new file mode 100644
index 000000000000..bfddedc9db32
--- /dev/null
+++ b/crypto/asymmetric_keys/tpm_key.c
@@ -0,0 +1,73 @@
+/* In-TPM asymmetric public-key crypto subtype
+ *
+ * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "TPK: "fmt
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/tpm.h>
+#include <keys/asymmetric-subtype.h>
+#include "tpm_key.h"
+
+MODULE_LICENSE("GPL");
+
+/*
+ * Provide a part of a description of the key for /proc/keys.
+ */
+static void tpm_key_describe(const struct key *asymmetric_key,
+			     struct seq_file *m)
+{
+	struct tpm_asymmetric_key *key = asymmetric_key->payload.data;
+	struct tpm_wrapped_key *wrap;
+
+	if (key && key->wrapped_key) {
+		wrap = key->wrapped_key;
+		seq_printf(m, "TPM.RSA %*phN",
+			   wrap->pubkey_len, wrap->data + wrap->pubkey_offset);
+	}
+}
+
+/*
+ * Destroy a TPM-based key.
+ */
+static void tpm_key_destroy(void *payload)
+{
+	struct tpm_asymmetric_key *key = payload;
+
+	if (key) {
+		kfree(key->wrapped_key);
+		kfree(key);
+		tpm_library_unuse();
+	}
+}
+
+/*
+ * Verify a signature using a TPM-based key.
+ */
+static int tpm_key_verify_signature(const struct key *key,
+				    const struct public_key_signature *sig)
+{
+	return -EOPNOTSUPP;
+}
+
+/*
+ * Public key algorithm asymmetric key subtype
+ */
+struct asymmetric_key_subtype tpm_key_subtype = {
+	.owner			= THIS_MODULE,
+	.name			= "tpm_key",
+	.describe		= tpm_key_describe,
+	.destroy		= tpm_key_destroy,
+	.verify_signature	= tpm_key_verify_signature,
+};
+EXPORT_SYMBOL_GPL(tpm_key_subtype);
diff --git a/crypto/asymmetric_keys/tpm_key.h b/crypto/asymmetric_keys/tpm_key.h
new file mode 100644
index 000000000000..712221fee874
--- /dev/null
+++ b/crypto/asymmetric_keys/tpm_key.h
@@ -0,0 +1,19 @@
+/* TPM-based public key algorithm internals
+ *
+ * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+struct tpm_asymmetric_key {
+	struct tpm_wrapped_key *wrapped_key;
+	u32	parent_tpm_handle;
+	u8	parent_authdata[TPM_DIGEST_SIZE];
+	u8	key_authdata[TPM_DIGEST_SIZE];
+};
+
+extern struct asymmetric_key_subtype tpm_key_subtype;
diff --git a/crypto/asymmetric_keys/tpm_key_parser.c b/crypto/asymmetric_keys/tpm_key_parser.c
new file mode 100644
index 000000000000..efb53172b43d
--- /dev/null
+++ b/crypto/asymmetric_keys/tpm_key_parser.c
@@ -0,0 +1,212 @@
+/* Instantiate a TPM key.
+ *
+ * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#define DEBUG
+#define pr_fmt(fmt) "TPKP: "fmt
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/tpm.h>
+#include <linux/parser.h>
+#include <keys/asymmetric-subtype.h>
+#include <keys/asymmetric-parser.h>
+#include "asymmetric_keys.h"
+#include "tpm_key.h"
+
+
+enum tpm_key_create_token {
+	opt_crt_err = -1,
+	opt_crt_parent,
+	opt_crt_keyauth,
+};
+
+static const match_table_t tpm_key_create_tokens = {
+	{ opt_crt_parent,	"parent=%x,%s"},
+	{ opt_crt_keyauth,	"keyauth=%s"},
+	{ opt_crt_err,		NULL}
+};
+
+/*
+ * Attempt to parse a key creation request.
+ */
+static int tpm_key_create(struct tpm_asymmetric_key *key, char *data)
+{
+	enum tpm_key_create_token token;
+	struct tpm_chip *chip;
+	unsigned long tmp, got = 0;
+	substring_t args[MAX_OPT_ARGS];
+	uint32_t key_handle;
+	char *p;
+	int ret;
+
+	pr_devel("==>%s(,%s)\n", __func__, data);
+
+	while ((p = strsep(&data, " \t"))) {
+		if (*p == '\0' || *p == ' ' || *p == '\t')
+			continue;
+		token = match_token(p, tpm_key_create_tokens, args);
+		switch (token) {
+		case opt_crt_parent:
+			pr_devel("parent %ld %ld\n",
+				 args[0].to - args[0].from,
+				 args[1].to - args[1].from);
+			*args[0].to = 0;
+			ret = kstrtoul(args[0].from, 16, &tmp);
+			if (ret < 0) {
+				pr_devel("bad parent handle\n");
+				return -EINVAL;
+			}
+			key->parent_tpm_handle = tmp;
+			if (args[1].to - args[1].from != TPM_DIGEST_SIZE * 2) {
+				pr_devel("parent auth wrong size\n");
+				return -EINVAL;
+			}
+			if (hex2bin(key->parent_authdata, args[1].from,
+				    TPM_DIGEST_SIZE) < 0) {
+				pr_devel("parent auth bad hex\n");
+				return -EINVAL;
+			}
+			break;
+
+		case opt_crt_keyauth:
+			pr_devel("keyauth\n");
+			if (args[1].to - args[1].from != TPM_DIGEST_SIZE * 2)
+				return -EINVAL;
+			if (hex2bin(key->parent_authdata, args[1].from,
+				    TPM_DIGEST_SIZE) < 0)
+				return -EINVAL;
+			break;
+
+		case opt_crt_err:
+			pr_devel("Unknown token %s\n", p);
+			return -EINVAL;
+		}
+		got |= 1 << token;
+	}
+
+	if ((got & 3) != 3) {
+		pr_devel("Missing mandatory args\n");
+		return -EINVAL;
+	}
+
+	chip = tpm_chip_find_get(TPM_ANY_NUM);
+	if (!chip)
+		return -ENODEV;
+
+	/* Create a key and retrieve the partially encrypted blob. */
+	ret = tpm_create_wrap_key(chip, TPM_ET_SRK, key->parent_tpm_handle,
+				  key->parent_authdata,
+				  key->key_authdata,
+				  NULL,
+				  &key->wrapped_key);
+	if (ret == -EBADMSG)
+		ret = -EIO;
+
+	/* Attempt to load the key back as a check */
+	ret = tpm_load_key2(chip, TPM_ET_SRK, key->parent_tpm_handle,
+			    key->parent_authdata, key->wrapped_key,
+			    &key_handle);
+	if (ret != 0) {
+		pr_devel("Couldn't load key back\n");
+		goto out;
+	}
+
+	ret = tpm_flush_specific(chip, key_handle, TPM_RT_KEY);
+	if (ret != 0)
+		pr_devel("Couldn't flush key handle\n");
+
+out:
+	tpm_chip_put(chip);
+	pr_devel("<==%s() = %d\n", __func__, ret);
+	return ret;
+}
+
+/*
+ * Attempt to parse a data blob for a key as a TPM key specification.
+ *
+ * We expect one of the following in the prep data:
+ *
+ *	tpm_create parent=<key>,<auth> keyauth=<hex> [options...]
+ *	tpm_load parent=<key>,<auth> data=<hex> [options...]
+ */
+static int tpm_key_preparse(struct key_preparsed_payload *prep)
+{
+	struct tpm_asymmetric_key *key;
+	char *data;
+	int ret;
+
+	pr_devel("==>%s()\n", __func__);
+
+	ret = tpm_library_use();
+	if (ret < 0)
+		goto out;
+
+	ret = -ENOMEM;
+	key = kzalloc(sizeof(*key), GFP_KERNEL);
+	if (!key)
+		goto out_free_tpmlib;
+	data = kmalloc(prep->datalen + 1, GFP_KERNEL);
+	if (!data)
+		goto out_free_key;
+
+	memcpy(data, prep->data, prep->datalen);
+	data[prep->datalen] = 0;
+	if (memcmp(data, "tpm_create ", 11) == 0) {
+		ret = tpm_key_create(key, data + 11);
+	} else {
+		ret = -EBADMSG;
+		goto out_free_data;
+	}
+
+	/* We're pinning the module by being linked against it */
+	__module_get(tpm_key_subtype.owner);
+	prep->type_data[0] = &tpm_key_subtype;
+	//prep->type_data[1] = kids;
+	prep->payload[0] = key;
+	//prep->description = desc;
+	prep->quotalen = 100;
+	key = NULL;
+	tpm_library_use();
+
+out_free_data:
+	kfree(data);
+out_free_key:
+	kfree(key);
+out_free_tpmlib:
+	tpm_library_unuse();
+out:
+	return ret;
+}
+
+static struct asymmetric_key_parser tpm_key_parser = {
+	.owner	= THIS_MODULE,
+	.name	= "tpm",
+	.parse	= tpm_key_preparse,
+};
+
+/*
+ * Module stuff
+ */
+static int __init tpm_key_init(void)
+{
+	return register_asymmetric_key_parser(&tpm_key_parser);
+}
+
+static void __exit tpm_key_exit(void)
+{
+	unregister_asymmetric_key_parser(&tpm_key_parser);
+}
+
+module_init(tpm_key_init);
+module_exit(tpm_key_exit);
+
+MODULE_DESCRIPTION("TPM key parser");
+MODULE_LICENSE("GPL");


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

  parent reply index

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-21 15:56 tpm: Provide a TPM access library David Howells
     [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
2018-08-21 15:56   ` [PATCH 01/23] TPM: Add new TPMs to the tail of the list to prevent inadvertent change of dev David Howells
     [not found]     ` <153486701644.13066.13372706238885253812.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
2018-08-21 18:30       ` Jason Gunthorpe
     [not found]         ` <20180821183004.GB25543-uk2M96/98Pc@public.gmane.org>
2018-08-24  6:24           ` Jarkko Sakkinen
     [not found]             ` <20180824062434.GB3584-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2018-08-24  6:25               ` Jarkko Sakkinen
     [not found]                 ` <20180824062557.GC3584-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2018-08-24 11:22                   ` Mimi Zohar
2018-08-24  6:19       ` Jarkko Sakkinen
2018-08-21 15:57   ` [PATCH 02/23] TPM: Provide a facility for a userspace TPM emulator David Howells
     [not found]     ` <153486702302.13066.15889029286852815542.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
2018-08-21 18:31       ` Jason Gunthorpe
     [not found]         ` <20180821183140.GD25543-uk2M96/98Pc@public.gmane.org>
2018-08-24  6:29           ` Jarkko Sakkinen
2018-08-21 15:57   ` [PATCH 03/23] TPM: Provide a platform driver for the user emulator driver David Howells
     [not found]     ` <153486702979.13066.16900998092976336647.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
2018-08-24  6:30       ` Jarkko Sakkinen
2018-08-21 15:57   ` [PATCH 04/23] TPM: Expose struct tpm_chip and related find_get and put functions David Howells
     [not found]     ` <153486703636.13066.16209594327379341518.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
2018-08-21 18:31       ` Jason Gunthorpe
     [not found]     ` <20180821183108.GC25543-uk2M96/98Pc@public.gmane.org>
2018-08-21 18:35       ` David Howells
2018-08-21 15:57   ` [PATCH 05/23] TPM: Use struct tpm_chip rather than chip number as interface parameter David Howells
     [not found]     ` <153486704294.13066.8818198038331415342.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
2018-08-24  7:42       ` Jarkko Sakkinen
2018-08-21 15:57   ` [PATCH 06/23] TPM: Move ordinal values from interface file to header with other ordinals David Howells
2018-08-21 15:57   ` [PATCH 07/23] TPM: Consolidate tpm_send(), transmit_cmd() and tpm_transmit() David Howells
2018-08-21 15:57   ` [PATCH 08/23] TPMLIB: Break TPM bits out of security/keys/trusted.c David Howells
     [not found]     ` <153486706322.13066.3105842100625841410.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
2018-08-24  7:52       ` Jarkko Sakkinen
     [not found]         ` <20180824075227.GG3584-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2018-08-24  8:49           ` Jarkko Sakkinen
     [not found]         ` <20180824084930.GA10266-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2018-08-24  9:33           ` David Howells
     [not found]             ` <25340.1535103190-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
2018-08-27  8:25               ` Jarkko Sakkinen
2018-08-21 15:57   ` [PATCH 09/23] TPMLIB: Do some source cleanups David Howells
2018-08-21 15:57   ` [PATCH 10/23] TPMLIB: Better format calls to TSS_*hmac*() David Howells
2018-08-21 15:58   ` [PATCH 11/23] TPMLIB: Put banner comments on public TPM library functions David Howells
2018-08-21 15:58   ` [PATCH 12/23] TPMLIB: Create tpm_{even, odd}_nonce structs to represent nonces David Howells
2018-08-21 15:58   ` [PATCH 13/23] TPMLIB: Rename store8() and storebytes() David Howells
2018-08-21 15:58   ` [PATCH 14/23] TPMLIB: Make store_s() take a void* data argument, not unsigned char* David Howells
2018-08-21 15:58   ` [PATCH 15/23] TPMLIB: Use __be32 rather than int32_t and use cpu_to_beX() and co David Howells
2018-08-21 15:58   ` [PATCH 16/23] TPMLIB: Put more comments into the HMAC generation functions David Howells
2018-08-21 15:58   ` [PATCH 17/23] TPMLIB: Provide a wrapper to load bytes out of the reply David Howells
2018-08-21 15:58   ` [PATCH 18/23] TPMLIB: Encapsulate XOR-based encryption with authkey derivative David Howells
2018-08-21 15:58   ` [PATCH 19/23] TPMLIB: Add some debugging code David Howells
2018-08-21 15:59   ` [PATCH 20/23] TPMLIB: Implement call to TPM_CreateWrapKey David Howells
2018-08-21 15:59   ` [PATCH 21/23] TPMLIB: Implement call to TPM_LoadKey2 David Howells
2018-08-21 15:59   ` [PATCH 22/23] TPMLIB: Provide call for TPM_FlushSpecific David Howells
2018-08-21 15:59   ` David Howells [this message]
2018-08-22 14:19   ` tpm: Provide a TPM access library Jarkko Sakkinen
     [not found] ` <20180822141956.GA28110-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2018-08-22 14:45   ` David Howells
     [not found]     ` <13611.1534949106-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
2018-08-23 22:49       ` Jarkko Sakkinen

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=153486716525.13066.18042327896429419884.stgit@warthog.procyon.org.uk \
    --to=dhowells-h+wxahxf7alqt0dzr+alfa@public.gmane.org \
    --cc=denkenz-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org \
    --cc=jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org \
    --cc=keyrings-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-integrity-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-security-module-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

tpmdd-devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/tpmdd-devel/0 tpmdd-devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 tpmdd-devel tpmdd-devel/ https://lore.kernel.org/tpmdd-devel \
		tpmdd-devel@lists.sourceforge.net tpmdd-devel@archiver.kernel.org
	public-inbox-index tpmdd-devel


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/net.sourceforge.lists.tpmdd-devel


AGPL code for this site: git clone https://public-inbox.org/ public-inbox