tpmdd-devel Archive on lore.kernel.org
 help / color / Atom feed
* tpm: Provide a TPM access library
@ 2018-08-21 15:56 David Howells
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
       [not found] ` <20180822141956.GA28110-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
  0 siblings, 2 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:56 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA


Hi Denis, Jarkko, James,

I managed to recover the TPM library patchset that I was working on about four
years ago in the process of trying to write an asymmetric key subtype that
could use the TPM.

Here it is in it's original glory for reference.  I ended up leaving it
because Jarkko's tpm-2 stuff broke it and I had other things to work on.  If
it's deemed worthwhile, I can try to forward port it to current Linus/mastet.

Note that one or two of the preliminary patches may be upstream.

The patches can also be found here:

	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=tpm-lib

Thanks,
David
---
David Howells (23):
      TPM: Add new TPMs to the tail of the list to prevent inadvertent change of dev
      TPM: Provide a facility for a userspace TPM emulator
      TPM: Provide a platform driver for the user emulator driver
      TPM: Expose struct tpm_chip and related find_get and put functions
      TPM: Use struct tpm_chip rather than chip number as interface parameter
      TPM: Move ordinal values from interface file to header with other ordinals
      TPM: Consolidate tpm_send(), transmit_cmd() and tpm_transmit()
      TPMLIB: Break TPM bits out of security/keys/trusted.c
      TPMLIB: Do some source cleanups
      TPMLIB: Better format calls to TSS_*hmac*()
      TPMLIB: Put banner comments on public TPM library functions
      TPMLIB: Create tpm_{even,odd}_nonce structs to represent nonces
      TPMLIB: Rename store8() and storebytes()
      TPMLIB: Make store_s() take a void* data argument, not unsigned char*
      TPMLIB: Use __be32 rather than int32_t and use cpu_to_beX() and co.
      TPMLIB: Put more comments into the HMAC generation functions
      TPMLIB: Provide a wrapper to load bytes out of the reply
      TPMLIB: Encapsulate XOR-based encryption with authkey derivative
      TPMLIB: Add some debugging code
      TPMLIB: Implement call to TPM_CreateWrapKey
      TPMLIB: Implement call to TPM_LoadKey2
      TPMLIB: Provide call for TPM_FlushSpecific
      TPM: Add an asymmetric key subtype for handling TPM-based keys


 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 +++++
 drivers/char/tpm/Kconfig                |   13 
 drivers/char/tpm/Makefile               |    3 
 drivers/char/tpm/tpm-dev.c              |   17 
 drivers/char/tpm/tpm-interface.c        |  304 ++++----
 drivers/char/tpm/tpm-library.c          | 1216 +++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm-library.h          |  119 +++
 drivers/char/tpm/tpm-sysfs.c            |   33 -
 drivers/char/tpm/tpm.h                  |   15 
 drivers/char/tpm/tpm_infineon.c         |    6 
 drivers/char/tpm/tpm_user_emul.c        |  694 ++++++++++++++++++
 include/linux/tpm.h                     |  123 +++
 include/linux/tpm_command.h             |   22 -
 include/linux/wait.h                    |   11 
 security/integrity/ima/ima.h            |    2 
 security/integrity/ima/ima_crypto.c     |    4 
 security/integrity/ima/ima_init.c       |   19 
 security/integrity/ima/ima_queue.c      |    4 
 security/keys/trusted.c                 |  690 +-----------------
 security/keys/trusted.h                 |   80 --
 24 files changed, 2712 insertions(+), 975 deletions(-)
 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
 create mode 100644 drivers/char/tpm/tpm-library.c
 create mode 100644 drivers/char/tpm/tpm-library.h
 create mode 100644 drivers/char/tpm/tpm_user_emul.c


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 01/23] TPM: Add new TPMs to the tail of the list to prevent inadvertent change of dev
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
@ 2018-08-21 15:56   ` David Howells
       [not found]     ` <153486701644.13066.13372706238885253812.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
  2018-08-21 15:57   ` [PATCH 02/23] TPM: Provide a facility for a userspace TPM emulator David Howells
                     ` (22 subsequent siblings)
  23 siblings, 1 reply; 42+ messages in thread
From: David Howells @ 2018-08-21 15:56 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Add newly registered TPMs to the tail of the list, not the beginning, so that
things that are specifying TPM_ANY_NUM don't find that the device they're
using has inadvertently changed.  Adding a second device would break IMA, for
instance.

Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Reviewed-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Signed-off-by: Peter Huewe <peterhuewe-Mmb7MZpHnFY@public.gmane.org>
cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---

 drivers/char/tpm/tpm-interface.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 6af17002a115..cfb9089887bd 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -1122,7 +1122,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
 
 	/* Make chip available */
 	spin_lock(&driver_lock);
-	list_add_rcu(&chip->list, &tpm_chip_list);
+	list_add_tail_rcu(&chip->list, &tpm_chip_list);
 	spin_unlock(&driver_lock);
 
 	return chip;


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 02/23] TPM: Provide a facility for a userspace TPM emulator
       [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
@ 2018-08-21 15:57   ` David Howells
       [not found]     ` <153486702302.13066.15889029286852815542.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
  2018-08-21 15:57   ` [PATCH 03/23] TPM: Provide a platform driver for the user emulator driver David Howells
                     ` (21 subsequent siblings)
  23 siblings, 1 reply; 42+ messages in thread
From: David Howells @ 2018-08-21 15:57 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Provide a misc device file (/dev/tpm_emul) by which a userspace TPM emulator
can set up a virtual TPM device under the control of the TPM frontend.  The
way this works is:

 (1) The emulator opens /dev/tpm_emul which is provided by the tpm_user
     driver.

 (2) tpm_user registers a TPM device and the tpm driver creates a /dev/tpmN
     misc device for the trousers package and suchlike to access.

 (3) The emulator sits in read() on the emulator device waiting for a command
     to come through.

 (4) tpm_user passes requests from /dev/tpmN to the emulator's read() call.

 (5) The emulator processes the request.

 (6) The emulator either write()'s the reply or calls ioctl(fd,0,0) to cancel
     the command.

 (7) The emulator goes back to read() to wait for the next command.

 (8) tpm_user passes the reply back to the tpm driver which passes it back to
     /dev/tpmN.

When the emulator closes /dev/tpm_emul, the TPM driver is unregistered and the
/dev/tpmN misc device is then removed.  Any outstanding requests are aborted
and -EIO will be returned from then on.  Multiple TPMs can be registered.

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

 drivers/char/tpm/Kconfig         |   13 +
 drivers/char/tpm/Makefile        |    1 
 drivers/char/tpm/tpm_user_emul.c |  672 ++++++++++++++++++++++++++++++++++++++
 include/linux/wait.h             |   11 +
 4 files changed, 697 insertions(+)
 create mode 100644 drivers/char/tpm/tpm_user_emul.c

diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index c54cac3f8bc8..c33ebd8504ec 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -122,4 +122,17 @@ config TCG_XEN
 	  To compile this driver as a module, choose M here; the module
 	  will be called xen-tpmfront.
 
+config TCG_USER_EMUL
+	tristate "Userspace TPM emulation interface for development purposes"
+	depends on DEBUG_KERNEL
+	---help---
+	  Provide a userspace TPM emulation interface through a misc device
+	  interface (/dev/tpm_emul).  This can be used to enable development of
+	  TPM-based services by providing a target TPM that can be safely
+	  trashed or for computers that don't have a physical TPM.
+
+	  This driver should _NOT_ be included in production kernels as it
+	  might be possible to use it to fool various kernel security features
+	  (such as IMA).
+
 endif # TCG_TPM
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 4d85dd681b81..b179052cd81b 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
 obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
 obj-$(CONFIG_TCG_ST33_I2C) += tpm_i2c_stm_st33.o
 obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o
+obj-$(CONFIG_TCG_USER_EMUL) += tpm_user_emul.o
diff --git a/drivers/char/tpm/tpm_user_emul.c b/drivers/char/tpm/tpm_user_emul.c
new file mode 100644
index 000000000000..b96350592bca
--- /dev/null
+++ b/drivers/char/tpm/tpm_user_emul.c
@@ -0,0 +1,672 @@
+/* TPM userspace emulation driver
+ *
+ * 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) "TPM_USER: "fmt
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include "tpm.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>");
+
+#define TIS_SHORT_TIMEOUT 750	/* ms */
+#define TIS_LONG_TIMEOUT 2000	/* 2 sec */
+
+#define kenter(FMT, ...) \
+	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+
+/*
+ * Packet of data going to/from the TPM.  We only permit one command
+ * at a time, so we don't need to deal with chains of packets.
+ */
+struct tpm_user_packet {
+	unsigned	size;
+	unsigned	cancellation;
+	u8		buffer[];
+};
+
+/*
+ * Emulator state.
+ */
+enum tpm_user_status {
+	TPM_USER_INITIALISING,
+	TPM_USER_IDLE,
+	TPM_USER_SENDING,
+	TPM_USER_AWAITING_REPLY,
+	TPM_USER_CANCELLING,
+	TPM_USER_GOT_REPLY,
+	TPM_USER_CANCELLED,
+	TPM_USER_EIO,
+};
+
+struct tpm_user_state {
+	struct work_struct	initialiser_work;
+	struct completion	initialiser_done;
+	struct file		*file;
+	struct platform_device	*pdev;
+	struct tpm_chip		*chip;
+	wait_queue_head_t	wq;
+	struct tpm_user_packet	*to_emulator_q;
+	struct tpm_user_packet	*from_emulator_q;
+	spinlock_t		lock;
+	enum tpm_user_status	status;
+	int			initialiser_error;
+};
+
+/*
+ * Read the emulator status.
+ */
+static u8 tpm_user_status(struct tpm_chip *chip)
+{
+	struct tpm_user_state *state = chip->vendor.priv;
+	enum tpm_user_status status = ACCESS_ONCE(state->status);
+
+	if (status == TPM_USER_GOT_REPLY)
+		return 1;
+	if (status == TPM_USER_CANCELLED ||
+	    status == TPM_USER_EIO)
+		return 2;
+	return 0;
+}
+
+/*
+ * Find out if a request has been cancelled.
+ */
+static bool tpm_user_is_req_cancelled(struct tpm_chip *chip, u8 status)
+{
+	struct tpm_user_state *state = chip->vendor.priv;
+	struct tpm_user_packet *pkt = NULL;
+
+	if (status != 2)
+		return false;
+
+	spin_lock(&state->lock);
+	if (state->status == TPM_USER_CANCELLED) {
+		pkt = state->from_emulator_q;
+		state->from_emulator_q = NULL;
+		state->status = TPM_USER_IDLE;
+	}
+	spin_unlock(&state->lock);
+	kfree(pkt);
+	return true;
+}
+
+/*
+ * Send data to the emulator.
+ */
+static int tpm_user_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	struct tpm_user_state *state = chip->vendor.priv;
+	struct tpm_user_packet *pkt;
+	int ret;
+
+	kenter(",%*phN,%zu", min_t(int, len, 16), buf, len);
+
+	pkt = kmalloc(sizeof(struct tpm_user_packet) + len, GFP_KERNEL);
+	if (!pkt)
+		return -ENOMEM;
+	pkt->size = len;
+	memcpy(pkt->buffer, buf, len);
+
+	spin_lock(&state->lock);
+	switch (state->status) {
+	case TPM_USER_IDLE:
+		state->to_emulator_q = pkt;
+		state->status = TPM_USER_SENDING;
+		ret = 0;
+		break;
+	default:
+		dev_err(chip->dev, "Sending in state %u\n", state->status);
+	case TPM_USER_EIO:
+		kfree(pkt);
+		ret = -EIO;
+		break;
+	}
+	spin_unlock(&state->lock);
+	if (ret == 0)
+		wake_up(&state->wq);
+	return ret;
+}
+
+/*
+ * Allow the TPM emulator to read requests from the driver
+ */
+static ssize_t tpm_user_read(struct file *file, char __user *buffer,
+			     size_t buflen, loff_t *pos)
+{
+	struct tpm_user_state *state = file->private_data;
+	struct tpm_user_packet *pkt;
+	unsigned long copied;
+	ssize_t ret;
+
+	kenter("{%u},,%zu,", state->status, buflen);
+
+again:
+	mutex_lock(&file_inode(file)->i_mutex);
+
+	ret = -EAGAIN;
+	spin_lock(&state->lock);
+	if (state->status == TPM_USER_EIO) {
+		ret = -EIO;
+		goto out;
+	}
+
+	if (state->status != TPM_USER_SENDING) {
+		if (file->f_flags & O_NONBLOCK)
+			goto out;
+		pr_devel("sleeping\n");
+		wait_event_cmd_interruptible(
+			state->wq,
+			state->status == TPM_USER_SENDING ||
+			state->status == TPM_USER_EIO,
+			spin_unlock(&state->lock),
+			spin_lock(&state->lock));
+		pr_devel("woken\n");
+
+		ret = -ERESTARTSYS;
+		if (signal_pending(current))
+			goto out;
+		ret = -EIO;
+		if (state->status == TPM_USER_EIO)
+			goto out;
+	}
+
+	pkt = state->to_emulator_q;
+	pr_devel("dequeued send(%u)\n", pkt->size);
+	ret = -EMSGSIZE;
+	if (pkt->size > buflen)
+		goto out;
+
+	/* Claim responsibility for the packet. */
+	state->status = TPM_USER_AWAITING_REPLY;
+	state->to_emulator_q = NULL;
+	spin_unlock(&state->lock);
+
+	copied = copy_to_user(buffer, pkt->buffer, pkt->size);
+	spin_lock(&state->lock);
+
+	if (copied != 0) {
+		/* Ugh - the emulator went splat.  Discard the request and
+		 * reject all further requests. */
+		kfree(pkt);
+		dev_err(state->chip->dev, "Emulator EFAULT in read\n");
+		state->status = TPM_USER_EIO;
+		ret = -EFAULT;
+	} else if (state->status == TPM_USER_CANCELLING) {
+		pr_devel("cancel\n");
+		state->status = TPM_USER_CANCELLED;
+		ret = -ECANCELED;
+	} else {
+		ret = pkt->size;
+	}
+
+out:
+	spin_unlock(&state->lock);
+	mutex_unlock(&file_inode(file)->i_mutex);
+	if (ret == -ECANCELED)
+		goto again;
+	kleave(" = %zd", ret);
+	return ret;
+}
+
+/*
+ * Allow the TPM emulator to respond to requests
+ *
+ * The buffer is should contain a packet with at least TPM_HEADER_SIZE bytes of
+ * data in it.
+ */
+static ssize_t tpm_user_write(struct file *file,
+			      const char __user *data,
+			      size_t datalen,
+			      loff_t *pos)
+{
+	struct tpm_user_state *state = file->private_data;
+	struct tpm_user_packet *pkt;
+	unsigned expected;
+	__be32 tmpbe;
+	ssize_t ret;
+
+	kenter("{%u},,%zu,", state->status, datalen);
+
+	/* Sanity checking the reply before we get any locks. */
+	if (datalen == 0) {
+		dev_err(state->chip->dev, "Empty reply\n");
+		return -EMSGSIZE;
+	}
+
+	if (datalen < TPM_HEADER_SIZE) {
+		dev_err(state->chip->dev, "Data packet missing TPM header\n");
+		return -EMSGSIZE;
+	}
+
+	pkt = kmalloc(sizeof(struct tpm_user_packet) + datalen, GFP_KERNEL);
+	if (!pkt)
+		return -ENOMEM;
+	pkt->size = datalen;
+	ret = -EFAULT;
+	if (copy_from_user(pkt->buffer, data, datalen) != 0)
+		goto err_free;
+
+	pr_debug("got reply %*phN\n", min_t(int, datalen, 16), pkt->buffer);
+
+	memcpy(&tmpbe, pkt->buffer + 2, sizeof(tmpbe));
+	expected = be32_to_cpu(tmpbe);
+	if (expected != datalen) {
+		dev_err(state->chip->dev, "Data packet size (%zu) != expected (%x)\n",
+			datalen, expected);
+		ret = -EMSGSIZE;
+		goto err_free;
+	}
+
+	mutex_lock(&file_inode(file)->i_mutex);
+	spin_lock(&state->lock);
+
+	switch (state->status) {
+	case TPM_USER_AWAITING_REPLY:
+		BUG_ON(state->from_emulator_q != NULL);
+		state->from_emulator_q = pkt;
+		state->status = TPM_USER_GOT_REPLY;
+		pkt = NULL;
+		ret = datalen;
+		break;
+
+	case TPM_USER_CANCELLING:
+		state->status = TPM_USER_CANCELLED;
+		ret = -ECANCELED;
+		break;
+
+	case TPM_USER_EIO:
+		ret = -EIO;
+		break;
+
+	default:
+		dev_err(state->chip->dev, "Reply unexpected in state (%u)\n",
+			state->status);
+		ret = -EPROTO;
+		break;
+	}
+
+	spin_unlock(&state->lock);
+	mutex_unlock(&file_inode(file)->i_mutex);
+	if (ret != -EPROTO)
+		wake_up(&state->wq);
+err_free:
+	kfree(pkt);
+	kleave(" = %zd", ret);
+	return ret;
+}
+
+/*
+ * Allow the TPM emulator to cancel a request with ioctl(fd,0,0).
+ */
+static long tpm_user_ioctl(struct file *file, unsigned cmd, unsigned long data)
+{
+	struct tpm_user_state *state = file->private_data;
+	long ret;
+
+	kenter("{%u},%x,%lx", state->status, cmd, data);
+
+	if (cmd != 0 && data != 0)
+		return -ENOIOCTLCMD;
+
+	mutex_lock(&file_inode(file)->i_mutex);
+	spin_lock(&state->lock);
+
+	switch (state->status) {
+	case TPM_USER_AWAITING_REPLY:
+	case TPM_USER_CANCELLING:
+		state->status = TPM_USER_CANCELLED;
+		ret = 0;
+		break;
+
+	case TPM_USER_EIO:
+		ret = -EIO;
+		break;
+
+	default:
+		dev_err(state->chip->dev,
+			"Cancellation unexpected in state (%u)\n",
+			state->status);
+		ret = -EPROTO;
+		break;
+	}
+
+	spin_unlock(&state->lock);
+	mutex_unlock(&file_inode(file)->i_mutex);
+	wake_up(&state->wq);
+	kleave(" = %ld", ret);
+	return ret;
+}
+
+/*
+ * Receive data from the emulator.
+ */
+static int tpm_user_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	struct tpm_user_state *state = chip->vendor.priv;
+	struct tpm_user_packet *pkt;
+	int ret;
+
+	kenter("{%u},,%zu", state->status, count);
+
+	spin_lock(&state->lock);
+
+	pkt = state->from_emulator_q;
+	state->from_emulator_q = NULL;
+	switch (state->status) {
+	case TPM_USER_GOT_REPLY:
+		state->status = TPM_USER_IDLE;
+		BUG_ON(!pkt);
+		ret = pkt->size;
+		break;
+
+	case TPM_USER_CANCELLED:
+		state->status = TPM_USER_IDLE;
+		ret = -ECANCELED;
+		break;
+
+	case TPM_USER_EIO:
+		ret = -EIO;
+		break;
+
+	default:
+		dev_err(chip->dev, "TPM data recv in unexpected state (%u)\n",
+			state->status);
+		ret = -EIO;
+		break;
+	}
+
+	spin_unlock(&state->lock);
+
+	if (pkt) {
+		if (ret > 0) {
+			if (pkt->size > count) {
+				dev_err(chip->dev, "Received excess data\n");
+				ret = -EIO;
+			} else {
+				memcpy(buf, pkt->buffer, pkt->size);
+			}
+		}
+		kfree(pkt);
+	}
+
+	kleave(" = %d", ret);
+	return ret;
+}
+
+/*
+ * Abort the current request.
+ */
+static void tpm_user_cancel(struct tpm_chip *chip)
+{
+	struct tpm_user_state *state = chip->vendor.priv;
+
+	kenter("{%u}", state->status);
+
+	spin_lock(&state->lock);
+
+	switch (state->status) {
+	case TPM_USER_SENDING:
+	case TPM_USER_AWAITING_REPLY:
+	case TPM_USER_GOT_REPLY:
+		kfree(state->to_emulator_q);
+		state->to_emulator_q = NULL;
+		kfree(state->from_emulator_q);
+		state->from_emulator_q = NULL;
+		state->status = TPM_USER_CANCELLING;
+		break;
+	default:
+		break;
+	}
+
+	if (state->status == TPM_USER_CANCELLING) {
+		DECLARE_WAITQUEUE(waiter, current);
+
+		for (;;) {
+			prepare_to_wait(&state->wq,
+					&waiter, TASK_UNINTERRUPTIBLE);
+			if (state->status == TPM_USER_CANCELLED ||
+			    state->status == TPM_USER_EIO)
+				break;
+			spin_unlock(&state->lock);
+			schedule_timeout(10 * HZ);
+			spin_lock(&state->lock);
+		}
+		finish_wait(&state->wq, &waiter);
+
+		if (state->status != TPM_USER_CANCELLED)
+			state->status = TPM_USER_EIO;
+		else
+			state->status = TPM_USER_IDLE;
+	}
+
+	spin_unlock(&state->lock);
+}
+
+/*
+ * Allow the TPM emulator to wait for a request
+ */
+static unsigned int tpm_user_poll(struct file *file,
+				  struct poll_table_struct *poll)
+{
+	struct tpm_user_state *state = file->private_data;
+	enum tpm_user_status status = ACCESS_ONCE(state->status);
+	unsigned mask;
+
+	poll_wait(file, &state->wq, poll);
+	mask = 0;
+
+	switch (status) {
+	case TPM_USER_SENDING:
+		return POLLIN;
+	case TPM_USER_AWAITING_REPLY:
+		return POLLOUT;
+	case TPM_USER_CANCELLING:
+		return POLLPRI;
+	case TPM_USER_EIO:
+		return POLLERR;
+	default:
+		return 0;
+	}
+}
+
+static const struct tpm_class_ops tpm_user_class = {
+	.status			= tpm_user_status,
+	.recv			= tpm_user_recv,
+	.send			= tpm_user_send,
+	.cancel			= tpm_user_cancel,
+	.req_complete_mask	= 1,
+	.req_complete_val	= 1,
+	.req_canceled		= tpm_user_is_req_cancelled,
+};
+
+/*
+ * Asynchronous initialiser.  We have to do it this way because we get timeouts
+ * and run a selftest on the TPM - which means doing reads and writes on the
+ * file.
+ */
+static void tpm_user_initialiser(struct work_struct *work)
+{
+	struct tpm_user_state *state =
+		container_of(work, struct tpm_user_state, initialiser_work);
+	struct platform_device *pdev;
+	struct tpm_chip *chip;
+	int ret = -ENODEV;
+
+	kenter("");
+
+	pdev = platform_device_register_simple("tpm_user", -1, NULL, 0);
+	if (IS_ERR(pdev)) {
+		ret = PTR_ERR(pdev);
+		goto err_dev;
+	}
+	state->pdev = pdev;
+
+	pr_devel("Registering TPM\n");
+
+	ret = -ENODEV;
+	chip = tpm_register_hardware(&pdev->dev, &tpm_user_class);
+	if (!chip)
+		goto err_reg;
+
+	chip->vendor.priv = state;
+	init_waitqueue_head(&chip->vendor.read_queue);
+	init_waitqueue_head(&chip->vendor.int_queue);
+	INIT_LIST_HEAD(&chip->vendor.list);
+	state->chip = chip;
+
+	/* Default timeouts */
+	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+	/* We will need to operate the communication channel */
+	spin_lock(&state->lock);
+	ret = -EIO;
+	if (state->status == TPM_USER_EIO)
+		goto err_tpm_locked;
+	state->status = TPM_USER_IDLE;
+	spin_unlock(&state->lock);
+
+	/* Not all variants of the emulator support getting the timeout */
+	pr_devel("Getting timeouts\n");
+	if (tpm_get_timeouts(chip))
+		dev_err(&pdev->dev, "Could not get TPM timeouts and durations\n");
+
+	pr_devel("Performing selftest\n");
+	ret = tpm_do_selftest(chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "TPM self test failed\n");
+		goto err_tpm;
+	}
+
+	ret = 0;
+out:
+	state->initialiser_error = ret;
+	kleave(" = %d", ret);
+	complete(&state->initialiser_done);
+	return;
+
+err_tpm:
+	spin_lock(&state->lock);
+	if (state->status != TPM_USER_EIO)
+		state->status = TPM_USER_EIO;
+err_tpm_locked:
+	spin_unlock(&state->lock);
+	wake_up(&state->wq);
+	tpm_remove_hardware(chip->dev);
+err_reg:
+	platform_device_unregister(pdev);
+err_dev:
+	goto out;
+}
+
+/*
+ * Allow the TPM emulator to create a virtual TPM.
+ */
+static int tpm_user_open(struct inode *inode, struct file *file)
+{
+	struct tpm_user_state *state;
+
+	kenter("");
+
+	state = kzalloc(sizeof(struct tpm_user_state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+	state->file = file;
+	state->status = TPM_USER_INITIALISING;
+	spin_lock_init(&state->lock);
+	INIT_WORK(&state->initialiser_work, tpm_user_initialiser);
+	init_completion(&state->initialiser_done);
+	init_waitqueue_head(&state->wq);
+
+	file->private_data = state;
+
+	/* The TPM registration must be done in another thread because the the
+	 * process will involve self-testing the TPM and will thus need to
+	 * communicate through this file.
+	 */
+	schedule_work(&state->initialiser_work);
+	kleave(" = 0");
+	return 0;
+}
+
+/*
+ * Release and clean up a virtual TPM.
+ */
+static int tpm_user_release(struct inode *inode, struct file *file)
+{
+	struct tpm_user_state *state = file->private_data;
+	int ret;
+
+	kenter("");
+
+	pr_devel("forcing EIO state\n");
+	spin_lock(&state->lock);
+	state->status = TPM_USER_EIO;
+	spin_unlock(&state->lock);
+	wake_up(&state->wq);
+
+	wait_for_completion(&state->initialiser_done);
+
+	ret = state->initialiser_error;
+	if (ret == 0) {
+		pr_devel("removing bits\n");
+		tpm_remove_hardware(state->chip->dev);
+		platform_device_unregister(state->pdev);
+	}
+	kfree(state->to_emulator_q);
+	kfree(state->from_emulator_q);
+	kfree(state);
+	kleave(" = %d", ret);
+	return ret;
+}
+
+static const struct file_operations tpm_user_fops = {
+	.owner		= THIS_MODULE,
+	.open		= tpm_user_open,
+	.release	= tpm_user_release,
+	.read		= tpm_user_read,
+	.write		= tpm_user_write,
+	.unlocked_ioctl	= tpm_user_ioctl,
+	.poll		= tpm_user_poll,
+	.llseek		= noop_llseek,
+};
+
+static struct miscdevice tpm_user_dev = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "tpm_emul",
+	.fops	= &tpm_user_fops,
+};
+
+/*
+ * Initialise a device
+ */
+static __init int tpm_user_mod_init(void)
+{
+	return misc_register(&tpm_user_dev);
+}
+device_initcall(tpm_user_mod_init);
+
+static __exit void tpm_user_mod_exit(void)
+{
+	misc_deregister(&tpm_user_dev);
+}
+module_exit(tpm_user_mod_exit);
diff --git a/include/linux/wait.h b/include/linux/wait.h
index bd68819f0815..8b443229997e 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -294,6 +294,10 @@ do {									\
 	(void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0,	\
 			    cmd1; schedule(); cmd2)
 
+#define __wait_event_cmd_interruptible(wq, condition, cmd1, cmd2)	\
+	(void)___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, 0,	\
+			    cmd1; schedule(); cmd2)
+
 /**
  * wait_event_cmd - sleep until a condition gets true
  * @wq: the waitqueue to wait on
@@ -315,6 +319,13 @@ do {									\
 	__wait_event_cmd(wq, condition, cmd1, cmd2);			\
 } while (0)
 
+#define wait_event_cmd_interruptible(wq, condition, cmd1, cmd2)		\
+do {									\
+	if (condition)							\
+		break;							\
+	__wait_event_cmd_interruptible(wq, condition, cmd1, cmd2);	\
+} while (0)
+
 #define __wait_event_interruptible(wq, condition)			\
 	___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, 0,		\
 		      schedule())


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 03/23] TPM: Provide a platform driver for the user emulator driver
       [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
  2018-08-21 15:57   ` [PATCH 02/23] TPM: Provide a facility for a userspace TPM emulator David Howells
@ 2018-08-21 15:57   ` David Howells
       [not found]     ` <153486702979.13066.16900998092976336647.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
  2018-08-21 15:57   ` [PATCH 04/23] TPM: Expose struct tpm_chip and related find_get and put functions David Howells
                     ` (20 subsequent siblings)
  23 siblings, 1 reply; 42+ messages in thread
From: David Howells @ 2018-08-21 15:57 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Provide a platform driver for the user emulator driver.  This seems to be
necessary to stop tpm_chip_find_get() from blowing up because it assumes
unconditionally that any device will have a driver attached:

		if (try_module_get(pos->dev->driver->owner)) {

However, this doesn't then work right because if I remove the TPM device and
re-add it, the tpm ID isn't recycled (ie, /dev/tpm0 becomes unavailable and
the new TPM is /dev/tpm1).

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

 drivers/char/tpm/tpm_user_emul.c |   24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/char/tpm/tpm_user_emul.c b/drivers/char/tpm/tpm_user_emul.c
index b96350592bca..e5b13358c71e 100644
--- a/drivers/char/tpm/tpm_user_emul.c
+++ b/drivers/char/tpm/tpm_user_emul.c
@@ -656,17 +656,39 @@ static struct miscdevice tpm_user_dev = {
 	.fops	= &tpm_user_fops,
 };
 
+static struct platform_driver tpm_user_drv = {
+	.driver = {
+		.name	= "tpm_user",
+		.owner	= THIS_MODULE,
+		/* .pm	= &tpm_user_pm, -- do we need pm since there's no h/w? */
+	},
+};
+
 /*
  * Initialise a device
  */
 static __init int tpm_user_mod_init(void)
 {
-	return misc_register(&tpm_user_dev);
+	int ret;
+
+	ret = platform_driver_register(&tpm_user_drv);
+	if (ret < 0)
+		return ret;
+
+	ret = misc_register(&tpm_user_dev);
+	if (ret < 0)
+		goto error_dev;
+	return 0;
+
+error_dev:
+	platform_driver_unregister(&tpm_user_drv);
+	return ret;
 }
 device_initcall(tpm_user_mod_init);
 
 static __exit void tpm_user_mod_exit(void)
 {
 	misc_deregister(&tpm_user_dev);
+	platform_driver_unregister(&tpm_user_drv);
 }
 module_exit(tpm_user_mod_exit);


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 04/23] TPM: Expose struct tpm_chip and related find_get and put functions
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (2 preceding siblings ...)
  2018-08-21 15:57   ` [PATCH 03/23] TPM: Provide a platform driver for the user emulator driver David Howells
@ 2018-08-21 15:57   ` David Howells
       [not found]     ` <153486703636.13066.16209594327379341518.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
       [not found]     ` <20180821183108.GC25543-uk2M96/98Pc@public.gmane.org>
  2018-08-21 15:57   ` [PATCH 05/23] TPM: Use struct tpm_chip rather than chip number as interface parameter David Howells
                     ` (19 subsequent siblings)
  23 siblings, 2 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:57 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Expose struct tpm_chip and related find_get and put functions so that
TPM-using code can make sure it uses the same TPM for any related set of
operations.

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

 drivers/char/tpm/tpm-interface.c |   19 ++++++++++++++++---
 drivers/char/tpm/tpm.h           |    5 -----
 include/linux/tpm.h              |   10 ++++++++++
 3 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index cfb9089887bd..b8f1df5b64fe 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -636,10 +636,11 @@ static int tpm_continue_selftest(struct tpm_chip *chip)
 	return rc;
 }
 
-/*
- * tpm_chip_find_get - return tpm_chip for given chip number
+/**
+ * tpm_chip_find_get - Look up a TPM chip by device index
+ * @chip_num: The index number of the chip to use or TPM_ANY_NUM
  */
-static struct tpm_chip *tpm_chip_find_get(int chip_num)
+struct tpm_chip *tpm_chip_find_get(int chip_num)
 {
 	struct tpm_chip *pos, *chip = NULL;
 
@@ -656,6 +657,18 @@ static struct tpm_chip *tpm_chip_find_get(int chip_num)
 	rcu_read_unlock();
 	return chip;
 }
+EXPORT_SYMBOL_GPL(tpm_chip_find_get);
+
+/**
+ * tpm_chip_put - Release a previously looked up TPM chip
+ * @chip: The chip to release
+ */
+void tpm_chip_put(struct tpm_chip *chip)
+{
+	if (chip)
+		module_put(chip->dev->driver->owner);
+}
+EXPORT_SYMBOL_GPL(tpm_chip_put);
 
 #define TPM_ORDINAL_PCRREAD cpu_to_be32(21)
 #define READ_PCR_RESULT_SIZE 30
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index e4d0888d2eab..df6ffceb3429 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -115,11 +115,6 @@ struct tpm_chip {
 
 #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
 
-static inline void tpm_chip_put(struct tpm_chip *chip)
-{
-	module_put(chip->dev->driver->owner);
-}
-
 static inline int tpm_read_index(int base, int index)
 {
 	outb(index, base);
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 8350c538b486..44c8cad7132d 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -46,11 +46,21 @@ struct tpm_class_ops {
 
 #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)
 
+extern struct tpm_chip *tpm_chip_find_get(int chip_num);
+extern void tpm_chip_put(struct tpm_chip *chip);
+
 extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
 extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
 extern int tpm_send(u32 chip_num, void *cmd, size_t buflen);
 extern int tpm_get_random(u32 chip_num, u8 *data, size_t max);
 #else
+static inline struct tpm_chip *tpm_chip_find_get(int chip_num)
+{
+	return NULL;
+}
+static inline void tpm_chip_put(struct tpm_chip *chip)
+{
+}
 static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
 	return -ENODEV;
 }


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 05/23] TPM: Use struct tpm_chip rather than chip number as interface parameter
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (3 preceding siblings ...)
  2018-08-21 15:57   ` [PATCH 04/23] TPM: Expose struct tpm_chip and related find_get and put functions David Howells
@ 2018-08-21 15:57   ` David Howells
       [not found]     ` <153486704294.13066.8818198038331415342.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
  2018-08-21 15:57   ` [PATCH 06/23] TPM: Move ordinal values from interface file to header with other ordinals David Howells
                     ` (18 subsequent siblings)
  23 siblings, 1 reply; 42+ messages in thread
From: David Howells @ 2018-08-21 15:57 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Use struct tpm_chip rather than chip number as interface parameter for most
interface functions.  This allows the client to be sure about the consistency
of what device it uses.

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

 drivers/char/tpm/tpm-interface.c    |   76 ++++++++-------------------------
 drivers/char/tpm/tpm-sysfs.c        |    2 -
 include/linux/tpm.h                 |   16 ++++---
 security/integrity/ima/ima.h        |    2 -
 security/integrity/ima/ima_crypto.c |    4 +-
 security/integrity/ima/ima_init.c   |   19 +++++---
 security/integrity/ima/ima_queue.c  |    4 +-
 security/keys/trusted.c             |   80 ++++++++++++++++++++++-------------
 8 files changed, 96 insertions(+), 107 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index b8f1df5b64fe..29c2ce5cfc69 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -678,25 +678,9 @@ static struct tpm_input_header pcrread_header = {
 	.ordinal = TPM_ORDINAL_PCRREAD
 };
 
-int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
-{
-	int rc;
-	struct tpm_cmd_t cmd;
-
-	cmd.header.in = pcrread_header;
-	cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
-	rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
-			  "attempting to read a pcr value");
-
-	if (rc == 0)
-		memcpy(res_buf, cmd.params.pcrread_out.pcr_result,
-		       TPM_DIGEST_SIZE);
-	return rc;
-}
-
 /**
  * tpm_pcr_read - read a pcr value
- * @chip_num:	tpm idx # or ANY
+ * @chip:	The chip to pass the request to
  * @pcr_idx:	pcr idx to retrieve
  * @res_buf:	TPM_PCR value
  *		size of res_buf is 20 bytes (or NULL if you don't care)
@@ -705,23 +689,26 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
  * isn't, protect against the chip disappearing, by incrementing
  * the module usage count.
  */
-int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
+int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
 {
-	struct tpm_chip *chip;
 	int rc;
+	struct tpm_cmd_t cmd;
 
-	chip = tpm_chip_find_get(chip_num);
-	if (chip == NULL)
-		return -ENODEV;
-	rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf);
-	tpm_chip_put(chip);
+	cmd.header.in = pcrread_header;
+	cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
+	rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
+			  "attempting to read a pcr value");
+
+	if (rc == 0)
+		memcpy(res_buf, cmd.params.pcrread_out.pcr_result,
+		       TPM_DIGEST_SIZE);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_pcr_read);
 
 /**
  * tpm_pcr_extend - extend pcr value with hash
- * @chip_num:	tpm idx # or AN&
+ * @chip:	The chip to pass the request to
  * @pcr_idx:	pcr idx to extend
  * @hash:	hash value used to extend pcr value
  *
@@ -737,24 +724,15 @@ static struct tpm_input_header pcrextend_header = {
 	.ordinal = TPM_ORD_PCR_EXTEND
 };
 
-int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
+int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
 {
 	struct tpm_cmd_t cmd;
-	int rc;
-	struct tpm_chip *chip;
-
-	chip = tpm_chip_find_get(chip_num);
-	if (chip == NULL)
-		return -ENODEV;
 
 	cmd.header.in = pcrextend_header;
 	cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
 	memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
-	rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
-			  "attempting extend a PCR value");
-
-	tpm_chip_put(chip);
-	return rc;
+	return transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
+			    "attempting extend a PCR value");
 }
 EXPORT_SYMBOL_GPL(tpm_pcr_extend);
 
@@ -821,19 +799,9 @@ int tpm_do_selftest(struct tpm_chip *chip)
 }
 EXPORT_SYMBOL_GPL(tpm_do_selftest);
 
-int tpm_send(u32 chip_num, void *cmd, size_t buflen)
+int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
 {
-	struct tpm_chip *chip;
-	int rc;
-
-	chip = tpm_chip_find_get(chip_num);
-	if (chip == NULL)
-		return -ENODEV;
-
-	rc = transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd");
-
-	tpm_chip_put(chip);
-	return rc;
+	return transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd");
 }
 EXPORT_SYMBOL_GPL(tpm_send);
 
@@ -1010,15 +978,14 @@ static struct tpm_input_header tpm_getrandom_header = {
 
 /**
  * tpm_get_random() - Get random bytes from the tpm's RNG
- * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @chip: The chip to pass the request to
  * @out: destination buffer for the random bytes
  * @max: the max number of bytes to write to @out
  *
  * Returns < 0 on error and the number of bytes read on success
  */
-int tpm_get_random(u32 chip_num, u8 *out, size_t max)
+int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
 {
-	struct tpm_chip *chip;
 	struct tpm_cmd_t tpm_cmd;
 	u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
 	int err, total = 0, retries = 5;
@@ -1027,10 +994,6 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
 	if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
 		return -EINVAL;
 
-	chip = tpm_chip_find_get(chip_num);
-	if (chip == NULL)
-		return -ENODEV;
-
 	do {
 		tpm_cmd.header.in = tpm_getrandom_header;
 		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
@@ -1049,7 +1012,6 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
 		num_bytes -= recd;
 	} while (retries-- && total < max);
 
-	tpm_chip_put(chip);
 	return total ? total : -EIO;
 }
 EXPORT_SYMBOL_GPL(tpm_get_random);
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index 01730a27ae07..507d8ab37ef1 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -120,7 +120,7 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,
 
 	num_pcrs = be32_to_cpu(cap.num_pcrs);
 	for (i = 0; i < num_pcrs; i++) {
-		rc = tpm_pcr_read_dev(chip, i, digest);
+		rc = tpm_pcr_read(chip, i, digest);
 		if (rc)
 			break;
 		str += sprintf(str, "PCR-%02d: ", i);
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 44c8cad7132d..c213e09b7d81 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -49,10 +49,10 @@ struct tpm_class_ops {
 extern struct tpm_chip *tpm_chip_find_get(int chip_num);
 extern void tpm_chip_put(struct tpm_chip *chip);
 
-extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
-extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
-extern int tpm_send(u32 chip_num, void *cmd, size_t buflen);
-extern int tpm_get_random(u32 chip_num, u8 *data, size_t max);
+extern int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
+extern int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
+extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen);
+extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max);
 #else
 static inline struct tpm_chip *tpm_chip_find_get(int chip_num)
 {
@@ -61,16 +61,16 @@ static inline struct tpm_chip *tpm_chip_find_get(int chip_num)
 static inline void tpm_chip_put(struct tpm_chip *chip)
 {
 }
-static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
+static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) {
 	return -ENODEV;
 }
-static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) {
+static inline int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) {
 	return -ENODEV;
 }
-static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) {
+static inline int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen) {
 	return -ENODEV;
 }
-static inline int tpm_get_random(u32 chip_num, u8 *data, size_t max) {
+static inline int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max) {
 	return -ENODEV;
 }
 #endif
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 8e4bb883fc13..8f932e53a449 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -44,8 +44,8 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
 #define IMA_TEMPLATE_IMA_FMT "d|n"
 
 /* set during initialization */
+extern struct tpm_chip *ima_tpm;
 extern int ima_initialized;
-extern int ima_used_chip;
 extern int ima_hash_algo;
 extern int ima_appraise;
 
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index d34e7dfc1118..c4631e5bac5a 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -556,10 +556,10 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data,
 
 static void __init ima_pcrread(int idx, u8 *pcr)
 {
-	if (!ima_used_chip)
+	if (!ima_tpm)
 		return;
 
-	if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
+	if (tpm_pcr_read(ima_tpm, idx, pcr) != 0)
 		pr_err("Error Communicating to TPM chip\n");
 }
 
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index e8f9d70a465d..bcad4da9e663 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -26,7 +26,7 @@
 
 /* name for boot aggregate entry */
 static const char *boot_aggregate_name = "boot_aggregate";
-int ima_used_chip;
+struct tpm_chip *ima_tpm;
 
 /* Add the boot aggregate to the IMA measurement list and extend
  * the PCR register.
@@ -62,7 +62,7 @@ static void __init ima_add_boot_aggregate(void)
 	iint->ima_hash->algo = HASH_ALGO_SHA1;
 	iint->ima_hash->length = SHA1_DIGEST_SIZE;
 
-	if (ima_used_chip) {
+	if (ima_tpm) {
 		result = ima_calc_boot_aggregate(&hash.hdr);
 		if (result < 0) {
 			audit_cause = "hashing_error";
@@ -90,12 +90,17 @@ int __init ima_init(void)
 	u8 pcr_i[TPM_DIGEST_SIZE];
 	int rc;
 
-	ima_used_chip = 0;
-	rc = tpm_pcr_read(TPM_ANY_NUM, 0, pcr_i);
-	if (rc == 0)
-		ima_used_chip = 1;
+	ima_tpm = tpm_chip_find_get(TPM_ANY_NUM);
 
-	if (!ima_used_chip)
+	if (ima_tpm) {
+		rc = tpm_pcr_read(ima_tpm, 0, pcr_i);
+		if (rc != 0) {
+			tpm_chip_put(ima_tpm);
+			ima_tpm = NULL;
+		}
+	}
+
+	if (!ima_tpm)
 		pr_info("No TPM chip found, activating TPM-bypass!\n");
 
 	rc = ima_init_crypto();
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 552705d5a78d..83629075375c 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -93,10 +93,10 @@ static int ima_pcr_extend(const u8 *hash)
 {
 	int result = 0;
 
-	if (!ima_used_chip)
+	if (!ima_tpm)
 		return result;
 
-	result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash);
+	result = tpm_pcr_extend(ima_tpm, CONFIG_IMA_MEASURE_PCR_IDX, hash);
 	if (result != 0)
 		pr_err("Error Communicating to TPM chip, result: %d\n", result);
 	return result;
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index c0594cb07ada..adb0caa5c38d 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -354,13 +354,13 @@ out:
  * 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(const u32 chip_num, unsigned char *cmd,
+static int trusted_tpm_send(struct tpm_chip *chip, unsigned char *cmd,
 			    size_t buflen)
 {
 	int rc;
 
 	dump_tpm_buf(cmd);
-	rc = tpm_send(chip_num, cmd, buflen);
+	rc = tpm_send(chip, cmd, buflen);
 	dump_tpm_buf(cmd);
 	if (rc > 0)
 		/* Can't return positive return codes values to keyctl */
@@ -374,30 +374,31 @@ static int trusted_tpm_send(const u32 chip_num, unsigned char *cmd,
  * Prevents a trusted key that is sealed to PCRs from being accessed.
  * This uses the tpm driver's extend function.
  */
-static int pcrlock(const int pcrnum)
+static int pcrlock(struct tpm_chip *chip, const int pcrnum)
 {
 	unsigned char hash[SHA1_DIGEST_SIZE];
 	int ret;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	ret = tpm_get_random(TPM_ANY_NUM, hash, SHA1_DIGEST_SIZE);
+	ret = tpm_get_random(chip, hash, SHA1_DIGEST_SIZE);
 	if (ret != SHA1_DIGEST_SIZE)
 		return ret;
-	return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0;
+	return tpm_pcr_extend(chip, pcrnum, hash) ? -EINVAL : 0;
 }
 
 /*
  * Create an object specific authorisation protocol (OSAP) session
  */
-static int osap(struct tpm_buf *tb, struct osapsess *s,
+static int osap(struct tpm_chip *chip,
+		struct tpm_buf *tb, struct osapsess *s,
 		const unsigned char *key, uint16_t type, uint32_t handle)
 {
 	unsigned char enonce[TPM_NONCE_SIZE];
 	unsigned char ononce[TPM_NONCE_SIZE];
 	int ret;
 
-	ret = tpm_get_random(TPM_ANY_NUM, ononce, TPM_NONCE_SIZE);
+	ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE);
 	if (ret != TPM_NONCE_SIZE)
 		return ret;
 
@@ -409,7 +410,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s,
 	store32(tb, handle);
 	storebytes(tb, ononce, TPM_NONCE_SIZE);
 
-	ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE);
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE);
 	if (ret < 0)
 		return ret;
 
@@ -425,7 +426,8 @@ static int osap(struct tpm_buf *tb, struct osapsess *s,
 /*
  * Create an object independent authorisation protocol (oiap) session
  */
-static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)
+static int oiap(struct tpm_chip *chip, struct tpm_buf *tb, uint32_t *handle,
+		unsigned char *nonce)
 {
 	int ret;
 
@@ -433,7 +435,7 @@ static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)
 	store16(tb, TPM_TAG_RQU_COMMAND);
 	store32(tb, TPM_OIAP_SIZE);
 	store32(tb, TPM_ORD_OIAP);
-	ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE);
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE);
 	if (ret < 0)
 		return ret;
 
@@ -455,7 +457,8 @@ struct tpm_digests {
  * Have the TPM seal(encrypt) the trusted key, possibly based on
  * Platform Configuration Registers (PCRs). AUTH1 for sealing key.
  */
-static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
+static int tpm_seal(struct tpm_chip *chip,
+		    struct tpm_buf *tb, uint16_t keytype,
 		    uint32_t keyhandle, const unsigned char *keyauth,
 		    const unsigned char *data, uint32_t datalen,
 		    unsigned char *blob, uint32_t *bloblen,
@@ -480,7 +483,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
 		return -ENOMEM;
 
 	/* get session for sealing key */
-	ret = osap(tb, &sess, keyauth, keytype, keyhandle);
+	ret = osap(chip, tb, &sess, keyauth, keytype, keyhandle);
 	if (ret < 0)
 		goto out;
 	dump_sess(&sess);
@@ -492,7 +495,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
 	if (ret < 0)
 		goto out;
 
-	ret = tpm_get_random(TPM_ANY_NUM, td->nonceodd, TPM_NONCE_SIZE);
+	ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE);
 	if (ret != TPM_NONCE_SIZE)
 		goto out;
 	ordinal = htonl(TPM_ORD_SEAL);
@@ -541,7 +544,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
 	store8(tb, cont);
 	storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE);
 
-	ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE);
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE);
 	if (ret < 0)
 		goto out;
 
@@ -570,7 +573,7 @@ out:
 /*
  * use the AUTH2_COMMAND form of unseal, to authorize both key and blob
  */
-static int tpm_unseal(struct tpm_buf *tb,
+static int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 		      uint32_t keyhandle, const unsigned char *keyauth,
 		      const unsigned char *blob, int bloblen,
 		      const unsigned char *blobauth,
@@ -589,12 +592,12 @@ static int tpm_unseal(struct tpm_buf *tb,
 	int ret;
 
 	/* sessions for unsealing key and data */
-	ret = oiap(tb, &authhandle1, enonce1);
+	ret = oiap(chip, tb, &authhandle1, enonce1);
 	if (ret < 0) {
 		pr_info("trusted_key: oiap failed (%d)\n", ret);
 		return ret;
 	}
-	ret = oiap(tb, &authhandle2, enonce2);
+	ret = oiap(chip, tb, &authhandle2, enonce2);
 	if (ret < 0) {
 		pr_info("trusted_key: oiap failed (%d)\n", ret);
 		return ret;
@@ -602,7 +605,7 @@ static int tpm_unseal(struct tpm_buf *tb,
 
 	ordinal = htonl(TPM_ORD_UNSEAL);
 	keyhndl = htonl(SRKHANDLE);
-	ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE);
+	ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE);
 	if (ret != TPM_NONCE_SIZE) {
 		pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
 		return ret;
@@ -634,7 +637,7 @@ static int tpm_unseal(struct tpm_buf *tb,
 	store8(tb, cont);
 	storebytes(tb, authdata2, SHA1_DIGEST_SIZE);
 
-	ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE);
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE);
 	if (ret < 0) {
 		pr_info("trusted_key: authhmac failed (%d)\n", ret);
 		return ret;
@@ -658,7 +661,8 @@ static int tpm_unseal(struct tpm_buf *tb,
 /*
  * Have the TPM seal(encrypt) the symmetric key
  */
-static int key_seal(struct trusted_key_payload *p,
+static int key_seal(struct tpm_chip *chip,
+		    struct trusted_key_payload *p,
 		    struct trusted_key_options *o)
 {
 	struct tpm_buf *tb;
@@ -671,7 +675,7 @@ static int key_seal(struct trusted_key_payload *p,
 	/* include migratable flag at end of sealed key */
 	p->key[p->key_len] = p->migratable;
 
-	ret = tpm_seal(tb, o->keytype, o->keyhandle, o->keyauth,
+	ret = tpm_seal(chip, 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)
@@ -684,7 +688,8 @@ static int key_seal(struct trusted_key_payload *p,
 /*
  * Have the TPM unseal(decrypt) the symmetric key
  */
-static int key_unseal(struct trusted_key_payload *p,
+static int key_unseal(struct tpm_chip *chip,
+		      struct trusted_key_payload *p,
 		      struct trusted_key_options *o)
 {
 	struct tpm_buf *tb;
@@ -694,7 +699,8 @@ static int key_unseal(struct trusted_key_payload *p,
 	if (!tb)
 		return -ENOMEM;
 
-	ret = tpm_unseal(tb, o->keyhandle, o->keyauth, p->blob, p->blob_len,
+	ret = tpm_unseal(chip, tb, o->keyhandle, o->keyauth,
+			 p->blob, p->blob_len,
 			 o->blobauth, p->key, &p->key_len);
 	if (ret < 0)
 		pr_info("trusted_key: srkunseal failed (%d)\n", ret);
@@ -900,6 +906,7 @@ static int trusted_instantiate(struct key *key,
 {
 	struct trusted_key_payload *payload = NULL;
 	struct trusted_key_options *options = NULL;
+	struct tpm_chip *chip = NULL;
 	size_t datalen = prep->datalen;
 	char *datablob;
 	int ret = 0;
@@ -935,9 +942,14 @@ static int trusted_instantiate(struct key *key,
 	dump_payload(payload);
 	dump_options(options);
 
+	ret = -ENODEV;
+	chip = tpm_chip_find_get(TPM_ANY_NUM);
+	if (!chip)
+		goto out;
+
 	switch (key_cmd) {
 	case Opt_load:
-		ret = key_unseal(payload, options);
+		ret = key_unseal(chip, payload, options);
 		dump_payload(payload);
 		dump_options(options);
 		if (ret < 0)
@@ -945,12 +957,12 @@ static int trusted_instantiate(struct key *key,
 		break;
 	case Opt_new:
 		key_len = payload->key_len;
-		ret = tpm_get_random(TPM_ANY_NUM, payload->key, key_len);
+		ret = tpm_get_random(chip, payload->key, key_len);
 		if (ret != key_len) {
 			pr_info("trusted_key: key_create failed (%d)\n", ret);
 			goto out;
 		}
-		ret = key_seal(payload, options);
+		ret = key_seal(chip, payload, options);
 		if (ret < 0)
 			pr_info("trusted_key: key_seal failed (%d)\n", ret);
 		break;
@@ -958,9 +970,11 @@ static int trusted_instantiate(struct key *key,
 		ret = -EINVAL;
 		goto out;
 	}
+
 	if (!ret && options->pcrlock)
-		ret = pcrlock(options->pcrlock);
+		ret = pcrlock(chip, options->pcrlock);
 out:
+	tpm_chip_put(chip);
 	kfree(datablob);
 	kfree(options);
 	if (!ret)
@@ -987,6 +1001,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
 	struct trusted_key_payload *p = key->payload.data;
 	struct trusted_key_payload *new_p;
 	struct trusted_key_options *new_o;
+	struct tpm_chip *chip = NULL;
 	size_t datalen = prep->datalen;
 	char *datablob;
 	int ret = 0;
@@ -1018,6 +1033,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
 		kfree(new_p);
 		goto out;
 	}
+
 	/* copy old key values, and reseal with new pcrs */
 	new_p->migratable = p->migratable;
 	new_p->key_len = p->key_len;
@@ -1025,14 +1041,19 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
 	dump_payload(p);
 	dump_payload(new_p);
 
-	ret = key_seal(new_p, new_o);
+	ret = -ENODEV;
+	chip = tpm_chip_find_get(TPM_ANY_NUM);
+	if (!chip)
+		goto out;
+
+	ret = key_seal(chip, new_p, new_o);
 	if (ret < 0) {
 		pr_info("trusted_key: key_seal failed (%d)\n", ret);
 		kfree(new_p);
 		goto out;
 	}
 	if (new_o->pcrlock) {
-		ret = pcrlock(new_o->pcrlock);
+		ret = pcrlock(chip, new_o->pcrlock);
 		if (ret < 0) {
 			pr_info("trusted_key: pcrlock failed (%d)\n", ret);
 			kfree(new_p);
@@ -1042,6 +1063,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
 	rcu_assign_keypointer(key, new_p);
 	call_rcu(&p->rcu, trusted_rcu_free);
 out:
+	tpm_chip_put(chip);
 	kfree(datablob);
 	kfree(new_o);
 	return ret;


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 06/23] TPM: Move ordinal values from interface file to header with other ordinals
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (4 preceding siblings ...)
  2018-08-21 15:57   ` [PATCH 05/23] TPM: Use struct tpm_chip rather than chip number as interface parameter David Howells
@ 2018-08-21 15:57   ` David Howells
  2018-08-21 15:57   ` [PATCH 07/23] TPM: Consolidate tpm_send(), transmit_cmd() and tpm_transmit() David Howells
                     ` (17 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:57 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Move the ordinal values (command IDs) from the tpm-interface.c file to the
tpm_command.h header where the other ordinal values are declared.  Use
cpu_to_be32() when the ordinal values are used, and not in their declarations.

The TPM_TAG_RQU_COMMAND definition in the internal tpm.h has to be removed
because it is a differently-defined duplicate label to avoid a clash.
cpu_to_be16() is then used in the places where it was used.

This allows the infineon TPM driver to use the constants directly in
tpm_inf_pnp_suspend().  The savestate buffer there can also be made static and
const.

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

 drivers/char/tpm/tpm-interface.c |   48 +++++++++++++++++---------------------
 drivers/char/tpm/tpm-sysfs.c     |    8 +++---
 drivers/char/tpm/tpm.h           |    2 --
 drivers/char/tpm/tpm_infineon.c  |    6 ++---
 include/linux/tpm_command.h      |   19 +++++++++++----
 5 files changed, 42 insertions(+), 41 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 29c2ce5cfc69..9add6034c252 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -28,6 +28,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/freezer.h>
+#include <linux/tpm_command.h>
 
 #include "tpm.h"
 #include "tpm_eventlog.h"
@@ -417,13 +418,11 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
 }
 
 #define TPM_INTERNAL_RESULT_SIZE 200
-#define TPM_ORD_GET_CAP cpu_to_be32(101)
-#define TPM_ORD_GET_RANDOM cpu_to_be32(70)
 
 static const struct tpm_input_header tpm_getcap_header = {
-	.tag = TPM_TAG_RQU_COMMAND,
-	.length = cpu_to_be32(22),
-	.ordinal = TPM_ORD_GET_CAP
+	.tag	 = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+	.length	 = cpu_to_be32(22),
+	.ordinal = cpu_to_be32(TPM_ORD_GET_CAP),
 };
 
 ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap,
@@ -469,14 +468,13 @@ void tpm_gen_interrupt(struct tpm_chip *chip)
 }
 EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
 
-#define TPM_ORD_STARTUP cpu_to_be32(153)
 #define TPM_ST_CLEAR cpu_to_be16(1)
 #define TPM_ST_STATE cpu_to_be16(2)
 #define TPM_ST_DEACTIVATED cpu_to_be16(3)
 static const struct tpm_input_header tpm_startup_header = {
-	.tag = TPM_TAG_RQU_COMMAND,
-	.length = cpu_to_be32(12),
-	.ordinal = TPM_ORD_STARTUP
+	.tag	 = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+	.length	 = cpu_to_be32(12),
+	.ordinal = cpu_to_be32(TPM_ORD_STARTUP),
 };
 
 static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
@@ -609,12 +607,11 @@ duration:
 }
 EXPORT_SYMBOL_GPL(tpm_get_timeouts);
 
-#define TPM_ORD_CONTINUE_SELFTEST 83
 #define CONTINUE_SELFTEST_RESULT_SIZE 10
 
 static struct tpm_input_header continue_selftest_header = {
-	.tag = TPM_TAG_RQU_COMMAND,
-	.length = cpu_to_be32(10),
+	.tag	 = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+	.length	 = cpu_to_be32(10),
 	.ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
 };
 
@@ -670,12 +667,11 @@ void tpm_chip_put(struct tpm_chip *chip)
 }
 EXPORT_SYMBOL_GPL(tpm_chip_put);
 
-#define TPM_ORDINAL_PCRREAD cpu_to_be32(21)
 #define READ_PCR_RESULT_SIZE 30
 static struct tpm_input_header pcrread_header = {
-	.tag = TPM_TAG_RQU_COMMAND,
-	.length = cpu_to_be32(14),
-	.ordinal = TPM_ORDINAL_PCRREAD
+	.tag	 = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+	.length	 = cpu_to_be32(14),
+	.ordinal = cpu_to_be32(TPM_ORD_PCR_READ),
 };
 
 /**
@@ -716,12 +712,11 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read);
  * isn't, protect against the chip disappearing, by incrementing
  * the module usage count.
  */
-#define TPM_ORD_PCR_EXTEND cpu_to_be32(20)
 #define EXTEND_PCR_RESULT_SIZE 34
 static struct tpm_input_header pcrextend_header = {
-	.tag = TPM_TAG_RQU_COMMAND,
-	.length = cpu_to_be32(34),
-	.ordinal = TPM_ORD_PCR_EXTEND
+	.tag	 = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+	.length	 = cpu_to_be32(34),
+	.ordinal = cpu_to_be32(TPM_ORD_PCR_EXTEND)
 };
 
 int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
@@ -889,13 +884,12 @@ void tpm_remove_hardware(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(tpm_remove_hardware);
 
-#define TPM_ORD_SAVESTATE cpu_to_be32(152)
 #define SAVESTATE_RESULT_SIZE 10
 
 static struct tpm_input_header savestate_header = {
-	.tag = TPM_TAG_RQU_COMMAND,
-	.length = cpu_to_be32(10),
-	.ordinal = TPM_ORD_SAVESTATE
+	.tag	 = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+	.length	 = cpu_to_be32(10),
+	.ordinal = cpu_to_be32(TPM_ORD_SAVESTATE),
 };
 
 /*
@@ -971,9 +965,9 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
 
 #define TPM_GETRANDOM_RESULT_SIZE	18
 static struct tpm_input_header tpm_getrandom_header = {
-	.tag = TPM_TAG_RQU_COMMAND,
-	.length = cpu_to_be32(14),
-	.ordinal = TPM_ORD_GET_RANDOM
+	.tag	 = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+	.length	 = cpu_to_be32(14),
+	.ordinal = cpu_to_be32(TPM_ORD_GET_RANDOM),
 };
 
 /**
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index 507d8ab37ef1..d8da83a1d11c 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -18,6 +18,7 @@
  *
  */
 #include <linux/device.h>
+#include <linux/tpm_command.h>
 #include "tpm.h"
 
 /* XXX for now this helper is duplicated in tpm-interface.c */
@@ -40,11 +41,10 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
 }
 
 #define READ_PUBEK_RESULT_SIZE 314
-#define TPM_ORD_READPUBEK cpu_to_be32(124)
 static struct tpm_input_header tpm_readpubek_header = {
-	.tag = TPM_TAG_RQU_COMMAND,
-	.length = cpu_to_be32(30),
-	.ordinal = TPM_ORD_READPUBEK
+	.tag	 = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+	.length	 = cpu_to_be32(30),
+	.ordinal = cpu_to_be32(TPM_ORD_READPUBEK),
 };
 static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
 			  char *buf)
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index df6ffceb3429..2a1be0ec2fbd 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -138,8 +138,6 @@ struct tpm_output_header {
 	__be32	return_code;
 } __packed;
 
-#define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
-
 struct	stclear_flags_t {
 	__be16	tag;
 	u8	deactivated;
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index dc0a2554034e..7daa3317e18d 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -591,10 +591,10 @@ static int tpm_inf_pnp_suspend(struct pnp_dev *dev, pm_message_t pm_state)
 	struct tpm_chip *chip = pnp_get_drvdata(dev);
 	int rc;
 	if (chip) {
-		u8 savestate[] = {
-			0, 193,	/* TPM_TAG_RQU_COMMAND */
+		static const u8 savestate[] = {
+			0, TPM_TAG_RQU_COMMAND,
 			0, 0, 0, 10,	/* blob length (in bytes) */
-			0, 0, 0, 152	/* TPM_ORD_SaveState */
+			0, 0, 0, TPM_ORD_SAVESTATE,
 		};
 		dev_info(&dev->dev, "saving TPM state\n");
 		rc = tpm_inf_send(chip, savestate, sizeof(savestate));
diff --git a/include/linux/tpm_command.h b/include/linux/tpm_command.h
index 727512e249b5..a3e0bb670e62 100644
--- a/include/linux/tpm_command.h
+++ b/include/linux/tpm_command.h
@@ -15,11 +15,20 @@
 #define TPM_TAG_RSP_AUTH2_COMMAND       198
 
 /* Command Ordinals */
-#define TPM_ORD_GETRANDOM               70
-#define TPM_ORD_OSAP                    11
-#define TPM_ORD_OIAP                    10
-#define TPM_ORD_SEAL                    23
-#define TPM_ORD_UNSEAL                  24
+enum tpm_ordinal {
+	TPM_ORD_OSAP			= 11,
+	TPM_ORD_OIAP			= 10,
+	TPM_ORD_PCR_EXTEND		= 20,
+	TPM_ORD_PCR_READ		= 21,
+	TPM_ORD_SEAL			= 23,
+	TPM_ORD_UNSEAL			= 24,
+	TPM_ORD_GET_RANDOM		= 70,
+	TPM_ORD_CONTINUE_SELFTEST	= 83,
+	TPM_ORD_GET_CAP			= 101,
+	TPM_ORD_READPUBEK		= 124,
+	TPM_ORD_SAVESTATE		= 152,
+	TPM_ORD_STARTUP			= 153,
+};
 
 /* Other constants */
 #define SRKHANDLE                       0x40000000


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 07/23] TPM: Consolidate tpm_send(), transmit_cmd() and tpm_transmit()
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (5 preceding siblings ...)
  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   ` David Howells
  2018-08-21 15:57   ` [PATCH 08/23] TPMLIB: Break TPM bits out of security/keys/trusted.c David Howells
                     ` (16 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:57 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA


---

 drivers/char/tpm/tpm-dev.c       |   17 ++--
 drivers/char/tpm/tpm-interface.c |  171 +++++++++++++++++++-------------------
 drivers/char/tpm/tpm-sysfs.c     |   23 -----
 drivers/char/tpm/tpm.h           |    8 +-
 include/linux/tpm.h              |    7 +-
 security/keys/trusted.c          |   16 ++--
 6 files changed, 117 insertions(+), 125 deletions(-)

diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
index d9b774e02a1f..6809c2791276 100644
--- a/drivers/char/tpm/tpm-dev.c
+++ b/drivers/char/tpm/tpm-dev.c
@@ -32,7 +32,10 @@ struct file_priv {
 	struct timer_list user_read_timer;      /* user needs to claim result */
 	struct work_struct work;
 
-	u8 data_buffer[TPM_BUFSIZE];
+	union {
+		u8 data_buffer[TPM_BUFSIZE];
+		struct tpm_output_header reply;
+	};
 };
 
 static void user_reader_timeout(unsigned long ptr)
@@ -119,7 +122,7 @@ static ssize_t tpm_write(struct file *file, const char __user *buf,
 {
 	struct file_priv *priv = file->private_data;
 	size_t in_size = size;
-	ssize_t out_size;
+	long rc;
 
 	/* cannot perform a write until the read has cleared
 	   either via tpm_read or a user_read_timer timeout.
@@ -140,14 +143,14 @@ static ssize_t tpm_write(struct file *file, const char __user *buf,
 	}
 
 	/* atomic tpm command send and result receive */
-	out_size = tpm_transmit(priv->chip, priv->data_buffer,
-				sizeof(priv->data_buffer));
-	if (out_size < 0) {
+	rc = tpm_send_command(priv->chip, priv->data_buffer,
+			      sizeof(priv->data_buffer), NULL);
+	if (rc < 0) {
 		mutex_unlock(&priv->buffer_mutex);
-		return out_size;
+		return rc;
 	}
 
-	atomic_set(&priv->data_pending, out_size);
+	atomic_set(&priv->data_pending, be32_to_cpu(priv->reply.length));
 	mutex_unlock(&priv->buffer_mutex);
 
 	/* Set a timeout by which the reader must come claim the result */
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 9add6034c252..e90f9d2dfaf2 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -329,13 +329,34 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
 }
 EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
 
-/*
- * Internal kernel interface to transmit TPM commands
+/**
+ * tpm_send_command - Send a command to the TPM and receive the reply
+ * @chip: The TPM to communicate with
+ * @buf: The command and reply buffer
+ * @bufsiz: The maximum amount of space in buffer for the reply
+ * @desc: Info about the command being performed for printing purposes (or NULL)
+ *
+ * This function sends a command to the TPM and then receives the reply.  The
+ * command must be in the buffer on entry, with the length of the command
+ * indicated by the command header in the buffer.
+ *
+ * The reply is read into the buffer, overwriting the command, up to a maximum
+ * length of bufsiz.
+ *
+ * If the TPM reports an error, desc is used to fabricate an error message.
+ *
+ * This function returns 0 on success, a negative kernel error code or a
+ * positive TPM error code on failure.
+ *
+ * In the case that success or a TPM error code is returned, the buffer is
+ * guaranteed to contain at least a valid reply header.  The length of the
+ * reply is contained in the reply header.
  */
-ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
-		     size_t bufsiz)
+long tpm_send_command(struct tpm_chip *chip, void *buf, size_t bufsiz,
+		      const char *desc)
 {
-	ssize_t rc;
+	struct tpm_output_header *reply;
+	long rc;
 	u32 count, ordinal;
 	unsigned long stop;
 
@@ -393,29 +414,30 @@ out_recv:
 			"tpm_transmit: tpm_recv: error %zd\n", rc);
 out:
 	mutex_unlock(&chip->tpm_mutex);
+	if (rc < 0)
+		return rc;
+
+	/* The transmission apparently worked.  Sanity check the reply and
+	 * extract the return code.
+	 */
+	if (rc < TPM_HEADER_SIZE)
+		return -EIO;
+	reply = buf;
+
+	rc = be32_to_cpu(reply->length);
+	if (rc < TPM_HEADER_SIZE || rc > bufsiz)
+		return -EIO;
+
+	rc = be32_to_cpu(reply->return_code);
+	if (rc < 0 || rc >= 0x1000)
+		return -EIO;
+	if (rc != 0 && desc)
+		dev_err(chip->dev,
+			"A TPM error (%ld) occurred %s\n", rc, desc);
 	return rc;
 }
 
 #define TPM_DIGEST_SIZE 20
-#define TPM_RET_CODE_IDX 6
-
-static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
-			    int len, const char *desc)
-{
-	int err;
-
-	len = tpm_transmit(chip, (u8 *) cmd, len);
-	if (len <  0)
-		return len;
-	else if (len < TPM_HEADER_SIZE)
-		return -EFAULT;
-
-	err = be32_to_cpu(cmd->header.out.return_code);
-	if (err != 0 && desc)
-		dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
-
-	return err;
-}
 
 #define TPM_INTERNAL_RESULT_SIZE 200
 
@@ -425,8 +447,8 @@ static const struct tpm_input_header tpm_getcap_header = {
 	.ordinal = cpu_to_be32(TPM_ORD_GET_CAP),
 };
 
-ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap,
-		   const char *desc)
+long tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap,
+		const char *desc)
 {
 	struct tpm_cmd_t tpm_cmd;
 	int rc;
@@ -447,7 +469,7 @@ ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap,
 		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 		tpm_cmd.params.getcap_in.subcap = subcap_id;
 	}
-	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc);
+	rc = tpm_send_command(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc);
 	if (!rc)
 		*cap = tpm_cmd.params.getcap_out.cap;
 	return rc;
@@ -456,15 +478,14 @@ ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap,
 void tpm_gen_interrupt(struct tpm_chip *chip)
 {
 	struct	tpm_cmd_t tpm_cmd;
-	ssize_t rc;
 
 	tpm_cmd.header.in = tpm_getcap_header;
 	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
 	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
 
-	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
-			"attempting to determine the timeouts");
+	tpm_send_command(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
+			 "attempting to determine the timeouts");
 }
 EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
 
@@ -477,16 +498,16 @@ static const struct tpm_input_header tpm_startup_header = {
 	.ordinal = cpu_to_be32(TPM_ORD_STARTUP),
 };
 
-static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
+static long tpm_startup(struct tpm_chip *chip, struct tpm_cmd_t *start_cmd,
+			__be16 startup_type)
 {
-	struct tpm_cmd_t start_cmd;
-	start_cmd.header.in = tpm_startup_header;
-	start_cmd.params.startup_in.startup_type = startup_type;
-	return transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE,
-			    "attempting to start the TPM");
+	start_cmd->header.in = tpm_startup_header;
+	start_cmd->params.startup_in.startup_type = startup_type;
+	return tpm_send_command(chip, start_cmd, TPM_INTERNAL_RESULT_SIZE,
+				"attempting to start the TPM");
 }
 
-int tpm_get_timeouts(struct tpm_chip *chip)
+long tpm_get_timeouts(struct tpm_chip *chip)
 {
 	struct tpm_cmd_t tpm_cmd;
 	unsigned long new_timeout[4];
@@ -498,32 +519,28 @@ int tpm_get_timeouts(struct tpm_chip *chip)
 	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
 	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
-	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, NULL);
+	rc = tpm_send_command(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
+			      "attempting to determine the timeouts");
 
 	if (rc == TPM_ERR_INVALID_POSTINIT) {
 		/* The TPM is not started, we are the first to talk to it.
 		   Execute a startup command. */
 		dev_info(chip->dev, "Issuing TPM_STARTUP");
-		if (tpm_startup(chip, TPM_ST_CLEAR))
+		if (tpm_startup(chip, &tpm_cmd, TPM_ST_CLEAR))
 			return rc;
 
 		tpm_cmd.header.in = tpm_getcap_header;
 		tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
 		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 		tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
-		rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
-				  NULL);
+		rc = tpm_send_command(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
+				      "attempting to determine the timeouts");
 	}
-	if (rc) {
-		dev_err(chip->dev,
-			"A TPM error (%zd) occurred attempting to determine the timeouts\n",
-			rc);
+	if (rc)
 		goto duration;
-	}
 
-	if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
-	    be32_to_cpu(tpm_cmd.header.out.length)
-	    != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
+	if (be32_to_cpu(tpm_cmd.header.out.length) !=
+	    sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
 		return -EINVAL;
 
 	old_timeout[0] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.a);
@@ -573,8 +590,8 @@ duration:
 	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION;
 
-	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
-			"attempting to determine the durations");
+	rc = tpm_send_command(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
+			      "attempting to determine the durations");
 	if (rc)
 		return rc;
 
@@ -622,15 +639,11 @@ static struct tpm_input_header continue_selftest_header = {
  * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
  * a TPM error code.
  */
-static int tpm_continue_selftest(struct tpm_chip *chip)
+static int tpm_continue_selftest(struct tpm_chip *chip, struct tpm_cmd_t *cmd)
 {
-	int rc;
-	struct tpm_cmd_t cmd;
-
-	cmd.header.in = continue_selftest_header;
-	rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
-			  "continue selftest");
-	return rc;
+	cmd->header.in = continue_selftest_header;
+	return tpm_send_command(chip, cmd, CONTINUE_SELFTEST_RESULT_SIZE,
+				"continue selftest");
 }
 
 /**
@@ -692,8 +705,8 @@ int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
 
 	cmd.header.in = pcrread_header;
 	cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
-	rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
-			  "attempting to read a pcr value");
+	rc = tpm_send_command(chip, &cmd, READ_PCR_RESULT_SIZE,
+			      "attempting to read a pcr value");
 
 	if (rc == 0)
 		memcpy(res_buf, cmd.params.pcrread_out.pcr_result,
@@ -726,8 +739,8 @@ int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
 	cmd.header.in = pcrextend_header;
 	cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
 	memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
-	return transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
-			    "attempting extend a PCR value");
+	return tpm_send_command(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
+				"attempting extend a PCR value");
 }
 EXPORT_SYMBOL_GPL(tpm_pcr_extend);
 
@@ -739,9 +752,9 @@ EXPORT_SYMBOL_GPL(tpm_pcr_extend);
  * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
  * a TPM error code.
  */
-int tpm_do_selftest(struct tpm_chip *chip)
+long tpm_do_selftest(struct tpm_chip *chip)
 {
-	int rc;
+	long rc;
 	unsigned int loops;
 	unsigned int delay_msec = 100;
 	unsigned long duration;
@@ -751,7 +764,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
 
 	loops = jiffies_to_msecs(duration) / delay_msec;
 
-	rc = tpm_continue_selftest(chip);
+	rc = tpm_continue_selftest(chip, &cmd);
 	/* This may fail if there was no TPM driver during a suspend/resume
 	 * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST)
 	 */
@@ -762,7 +775,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
 		/* Attempt to read a PCR value */
 		cmd.header.in = pcrread_header;
 		cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0);
-		rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE);
+		rc = tpm_send_command(chip, &cmd, READ_PCR_RESULT_SIZE, NULL);
 		/* Some buggy TPMs will not respond to tpm_tis_ready() for
 		 * around 300ms while the self test is ongoing, keep trying
 		 * until the self test duration expires. */
@@ -772,13 +785,9 @@ int tpm_do_selftest(struct tpm_chip *chip)
 			continue;
 		}
 
-		if (rc < TPM_HEADER_SIZE)
-			return -EFAULT;
-
-		rc = be32_to_cpu(cmd.header.out.return_code);
 		if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
 			dev_info(chip->dev,
-				 "TPM is disabled/deactivated (0x%X)\n", rc);
+				 "TPM is disabled/deactivated (0x%lX)\n", rc);
 			/* TPM is disabled and/or deactivated; driver can
 			 * proceed and TPM does handle commands for
 			 * suspend/resume correctly
@@ -794,12 +803,6 @@ int tpm_do_selftest(struct tpm_chip *chip)
 }
 EXPORT_SYMBOL_GPL(tpm_do_selftest);
 
-int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
-{
-	return transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd");
-}
-EXPORT_SYMBOL_GPL(tpm_send);
-
 static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
 					bool check_cancel, bool *canceled)
 {
@@ -913,14 +916,14 @@ int tpm_pm_suspend(struct device *dev)
 		cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr);
 		memcpy(cmd.params.pcrextend_in.hash, dummy_hash,
 		       TPM_DIGEST_SIZE);
-		rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
-				  "extending dummy pcr before suspend");
+		tpm_send_command(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
+				 "extending dummy pcr before suspend");
 	}
 
 	/* now do the actual savestate */
 	for (try = 0; try < TPM_RETRY; try++) {
 		cmd.header.in = savestate_header;
-		rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL);
+		rc = tpm_send_command(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL);
 
 		/*
 		 * If the TPM indicates that it is too busy to respond to
@@ -992,9 +995,9 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
 		tpm_cmd.header.in = tpm_getrandom_header;
 		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
 
-		err = transmit_cmd(chip, &tpm_cmd,
-				   TPM_GETRANDOM_RESULT_SIZE + num_bytes,
-				   "attempting get random");
+		err = tpm_send_command(chip, &tpm_cmd,
+				       TPM_GETRANDOM_RESULT_SIZE + num_bytes,
+				       "attempting get random");
 		if (err)
 			break;
 
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index d8da83a1d11c..ad3b01882b15 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -21,25 +21,6 @@
 #include <linux/tpm_command.h>
 #include "tpm.h"
 
-/* XXX for now this helper is duplicated in tpm-interface.c */
-static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
-			    int len, const char *desc)
-{
-	int err;
-
-	len = tpm_transmit(chip, (u8 *) cmd, len);
-	if (len <  0)
-		return len;
-	else if (len < TPM_HEADER_SIZE)
-		return -EFAULT;
-
-	err = be32_to_cpu(cmd->header.out.return_code);
-	if (err != 0 && desc)
-		dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
-
-	return err;
-}
-
 #define READ_PUBEK_RESULT_SIZE 314
 static struct tpm_input_header tpm_readpubek_header = {
 	.tag	 = cpu_to_be16(TPM_TAG_RQU_COMMAND),
@@ -58,8 +39,8 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
 	struct tpm_chip *chip = dev_get_drvdata(dev);
 
 	tpm_cmd.header.in = tpm_readpubek_header;
-	err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
-			   "attempting to read the PUBEK");
+	err = tpm_send_command(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
+			       "attempting to read the PUBEK");
 	if (err)
 		goto out;
 
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 2a1be0ec2fbd..912eba092e62 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -306,13 +306,11 @@ struct tpm_cmd_t {
 	tpm_cmd_params	params;
 } __packed;
 
-ssize_t	tpm_getcap(struct device *, __be32, cap_t *, const char *);
+extern long tpm_getcap(struct device *, __be32, cap_t *, const char *);
 
-ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
-		     size_t bufsiz);
-extern int tpm_get_timeouts(struct tpm_chip *);
+extern long tpm_get_timeouts(struct tpm_chip *);
 extern void tpm_gen_interrupt(struct tpm_chip *);
-extern int tpm_do_selftest(struct tpm_chip *);
+extern long tpm_do_selftest(struct tpm_chip *);
 extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
 extern struct tpm_chip* tpm_register_hardware(struct device *,
 					      const struct tpm_class_ops *ops);
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index c213e09b7d81..f4e14405f5cf 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -51,7 +51,8 @@ extern void tpm_chip_put(struct tpm_chip *chip);
 
 extern int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
 extern int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
-extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen);
+extern long tpm_send_command(struct tpm_chip *chip, void *buf, size_t buflen,
+			     const char *desc);
 extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max);
 #else
 static inline struct tpm_chip *tpm_chip_find_get(int chip_num)
@@ -67,7 +68,9 @@ static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
 static inline int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) {
 	return -ENODEV;
 }
-static inline int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen) {
+static inline long tpm_send_command(struct tpm_chip *chip, void *buf, size_t buflen,
+				    const char *desc)
+{
 	return -ENODEV;
 }
 static inline int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max) {
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index adb0caa5c38d..943c65b53201 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -355,12 +355,12 @@ out:
  * own TPM command packets using the drivers send function.
  */
 static int trusted_tpm_send(struct tpm_chip *chip, unsigned char *cmd,
-			    size_t buflen)
+			    size_t buflen, const char *desc)
 {
 	int rc;
 
 	dump_tpm_buf(cmd);
-	rc = tpm_send(chip, cmd, buflen);
+	rc = tpm_send_command(chip, cmd, buflen, desc);
 	dump_tpm_buf(cmd);
 	if (rc > 0)
 		/* Can't return positive return codes values to keyctl */
@@ -410,7 +410,8 @@ static int osap(struct tpm_chip *chip,
 	store32(tb, handle);
 	storebytes(tb, ononce, TPM_NONCE_SIZE);
 
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE);
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
+			       "creating OSAP session");
 	if (ret < 0)
 		return ret;
 
@@ -435,7 +436,8 @@ static int oiap(struct tpm_chip *chip, struct tpm_buf *tb, uint32_t *handle,
 	store16(tb, TPM_TAG_RQU_COMMAND);
 	store32(tb, TPM_OIAP_SIZE);
 	store32(tb, TPM_ORD_OIAP);
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE);
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
+			       "creating OIAP session");
 	if (ret < 0)
 		return ret;
 
@@ -544,7 +546,8 @@ static int tpm_seal(struct tpm_chip *chip,
 	store8(tb, cont);
 	storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE);
 
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE);
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
+			       "sealing data");
 	if (ret < 0)
 		goto out;
 
@@ -637,7 +640,8 @@ static int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	store8(tb, cont);
 	storebytes(tb, authdata2, SHA1_DIGEST_SIZE);
 
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE);
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
+			       "unsealing data");
 	if (ret < 0) {
 		pr_info("trusted_key: authhmac failed (%d)\n", ret);
 		return ret;


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 08/23] TPMLIB: Break TPM bits out of security/keys/trusted.c
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (6 preceding siblings ...)
  2018-08-21 15:57   ` [PATCH 07/23] TPM: Consolidate tpm_send(), transmit_cmd() and tpm_transmit() David Howells
@ 2018-08-21 15:57   ` David Howells
       [not found]     ` <153486706322.13066.3105842100625841410.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
  2018-08-21 15:57   ` [PATCH 09/23] TPMLIB: Do some source cleanups David Howells
                     ` (15 subsequent siblings)
  23 siblings, 1 reply; 42+ messages in thread
From: David Howells @ 2018-08-21 15:57 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Break the TPM bits out of security/keys/trusted.c into their own call wrapper
library.

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

 drivers/char/tpm/Makefile      |    2 
 drivers/char/tpm/tpm-library.c |  682 ++++++++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm-library.h |   83 +++++
 include/linux/tpm.h            |   38 ++
 security/keys/trusted.c        |  646 --------------------------------------
 security/keys/trusted.h        |   80 -----
 6 files changed, 804 insertions(+), 727 deletions(-)
 create mode 100644 drivers/char/tpm/tpm-library.c
 create mode 100644 drivers/char/tpm/tpm-library.h

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index b179052cd81b..cea6a4d05920 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the kernel tpm device drivers.
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
-tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o
+tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-library.o
 tpm-$(CONFIG_ACPI) += tpm_ppi.o
 
 ifdef CONFIG_ACPI
diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
new file mode 100644
index 000000000000..1be4f71cabcb
--- /dev/null
+++ b/drivers/char/tpm/tpm-library.c
@@ -0,0 +1,682 @@
+/* TPM call wrapper library.
+ *
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * David Safford <safford-r/Jw6+rmf7HQT0dZR+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 License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * See Documentation/security/keys-trusted-encrypted.txt
+ */
+
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/parser.h>
+#include <linux/string.h>
+#include <linux/err.h>
+#include <keys/user-type.h>
+#include <keys/trusted-type.h>
+#include <linux/key-type.h>
+#include <linux/rcupdate.h>
+#include <linux/crypto.h>
+#include <crypto/hash.h>
+#include <crypto/sha.h>
+#include <linux/capability.h>
+#include <linux/tpm.h>
+#include <linux/tpm_command.h>
+
+#include "tpm-library.h"
+
+static const char hmac_alg[] = "hmac(sha1)";
+static const char hash_alg[] = "sha1";
+
+struct sdesc {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+static struct crypto_shash *hashalg;
+static struct crypto_shash *hmacalg;
+
+static struct sdesc *init_sdesc(struct crypto_shash *alg)
+{
+	struct sdesc *sdesc;
+	int size;
+
+	size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
+	sdesc = kmalloc(size, GFP_KERNEL);
+	if (!sdesc)
+		return ERR_PTR(-ENOMEM);
+	sdesc->shash.tfm = alg;
+	sdesc->shash.flags = 0x0;
+	return sdesc;
+}
+
+static int TSS_sha1(const unsigned char *data, unsigned int datalen,
+		    unsigned char *digest)
+{
+	struct sdesc *sdesc;
+	int ret;
+
+	sdesc = init_sdesc(hashalg);
+	if (IS_ERR(sdesc)) {
+		pr_info("trusted_key: can't alloc %s\n", hash_alg);
+		return PTR_ERR(sdesc);
+	}
+
+	ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
+	kfree(sdesc);
+	return ret;
+}
+
+static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,
+		       unsigned int keylen, ...)
+{
+	struct sdesc *sdesc;
+	va_list argp;
+	unsigned int dlen;
+	unsigned char *data;
+	int ret;
+
+	sdesc = init_sdesc(hmacalg);
+	if (IS_ERR(sdesc)) {
+		pr_info("trusted_key: can't alloc %s\n", hmac_alg);
+		return PTR_ERR(sdesc);
+	}
+
+	ret = crypto_shash_setkey(hmacalg, key, keylen);
+	if (ret < 0)
+		goto out;
+	ret = crypto_shash_init(&sdesc->shash);
+	if (ret < 0)
+		goto out;
+
+	va_start(argp, keylen);
+	for (;;) {
+		dlen = va_arg(argp, unsigned int);
+		if (dlen == 0)
+			break;
+		data = va_arg(argp, unsigned char *);
+		if (data == NULL) {
+			ret = -EINVAL;
+			break;
+		}
+		ret = crypto_shash_update(&sdesc->shash, data, dlen);
+		if (ret < 0)
+			break;
+	}
+	va_end(argp);
+	if (!ret)
+		ret = crypto_shash_final(&sdesc->shash, digest);
+out:
+	kfree(sdesc);
+	return ret;
+}
+
+/*
+ * calculate authorization info fields to send to TPM
+ */
+static int TSS_authhmac(unsigned char *digest, const unsigned char *key,
+			unsigned int keylen, unsigned char *h1,
+			unsigned char *h2, unsigned char h3, ...)
+{
+	unsigned char paramdigest[SHA1_DIGEST_SIZE];
+	struct sdesc *sdesc;
+	unsigned int dlen;
+	unsigned char *data;
+	unsigned char c;
+	int ret;
+	va_list argp;
+
+	sdesc = init_sdesc(hashalg);
+	if (IS_ERR(sdesc)) {
+		pr_info("trusted_key: can't alloc %s\n", hash_alg);
+		return PTR_ERR(sdesc);
+	}
+
+	c = h3;
+	ret = crypto_shash_init(&sdesc->shash);
+	if (ret < 0)
+		goto out;
+	va_start(argp, h3);
+	for (;;) {
+		dlen = va_arg(argp, unsigned int);
+		if (dlen == 0)
+			break;
+		data = va_arg(argp, unsigned char *);
+		if (!data) {
+			ret = -EINVAL;
+			break;
+		}
+		ret = crypto_shash_update(&sdesc->shash, data, dlen);
+		if (ret < 0)
+			break;
+	}
+	va_end(argp);
+	if (!ret)
+		ret = crypto_shash_final(&sdesc->shash, paramdigest);
+	if (!ret)
+		ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE,
+				  paramdigest, TPM_NONCE_SIZE, h1,
+				  TPM_NONCE_SIZE, h2, 1, &c, 0, 0);
+out:
+	kfree(sdesc);
+	return ret;
+}
+
+/*
+ * verify the AUTH1_COMMAND (Seal) result from TPM
+ */
+static int TSS_checkhmac1(unsigned char *buffer,
+			  const uint32_t command,
+			  const unsigned char *ononce,
+			  const unsigned char *key,
+			  unsigned int keylen, ...)
+{
+	uint32_t bufsize;
+	uint16_t tag;
+	uint32_t ordinal;
+	uint32_t result;
+	unsigned char *enonce;
+	unsigned char *continueflag;
+	unsigned char *authdata;
+	unsigned char testhmac[SHA1_DIGEST_SIZE];
+	unsigned char paramdigest[SHA1_DIGEST_SIZE];
+	struct sdesc *sdesc;
+	unsigned int dlen;
+	unsigned int dpos;
+	va_list argp;
+	int ret;
+
+	bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
+	tag = LOAD16(buffer, 0);
+	ordinal = command;
+	result = LOAD32N(buffer, TPM_RETURN_OFFSET);
+	if (tag == TPM_TAG_RSP_COMMAND)
+		return 0;
+	if (tag != TPM_TAG_RSP_AUTH1_COMMAND)
+		return -EINVAL;
+	authdata = buffer + bufsize - SHA1_DIGEST_SIZE;
+	continueflag = authdata - 1;
+	enonce = continueflag - TPM_NONCE_SIZE;
+
+	sdesc = init_sdesc(hashalg);
+	if (IS_ERR(sdesc)) {
+		pr_info("trusted_key: can't alloc %s\n", hash_alg);
+		return PTR_ERR(sdesc);
+	}
+	ret = crypto_shash_init(&sdesc->shash);
+	if (ret < 0)
+		goto out;
+	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,
+				  sizeof result);
+	if (ret < 0)
+		goto out;
+	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
+				  sizeof ordinal);
+	if (ret < 0)
+		goto out;
+	va_start(argp, keylen);
+	for (;;) {
+		dlen = va_arg(argp, unsigned int);
+		if (dlen == 0)
+			break;
+		dpos = va_arg(argp, unsigned int);
+		ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
+		if (ret < 0)
+			break;
+	}
+	va_end(argp);
+	if (!ret)
+		ret = crypto_shash_final(&sdesc->shash, paramdigest);
+	if (ret < 0)
+		goto out;
+
+	ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest,
+			  TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce,
+			  1, continueflag, 0, 0);
+	if (ret < 0)
+		goto out;
+
+	if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE))
+		ret = -EINVAL;
+out:
+	kfree(sdesc);
+	return ret;
+}
+
+/*
+ * verify the AUTH2_COMMAND (unseal) result from TPM
+ */
+static int TSS_checkhmac2(unsigned char *buffer,
+			  const uint32_t command,
+			  const unsigned char *ononce,
+			  const unsigned char *key1,
+			  unsigned int keylen1,
+			  const unsigned char *key2,
+			  unsigned int keylen2, ...)
+{
+	uint32_t bufsize;
+	uint16_t tag;
+	uint32_t ordinal;
+	uint32_t result;
+	unsigned char *enonce1;
+	unsigned char *continueflag1;
+	unsigned char *authdata1;
+	unsigned char *enonce2;
+	unsigned char *continueflag2;
+	unsigned char *authdata2;
+	unsigned char testhmac1[SHA1_DIGEST_SIZE];
+	unsigned char testhmac2[SHA1_DIGEST_SIZE];
+	unsigned char paramdigest[SHA1_DIGEST_SIZE];
+	struct sdesc *sdesc;
+	unsigned int dlen;
+	unsigned int dpos;
+	va_list argp;
+	int ret;
+
+	bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
+	tag = LOAD16(buffer, 0);
+	ordinal = command;
+	result = LOAD32N(buffer, TPM_RETURN_OFFSET);
+
+	if (tag == TPM_TAG_RSP_COMMAND)
+		return 0;
+	if (tag != TPM_TAG_RSP_AUTH2_COMMAND)
+		return -EINVAL;
+	authdata1 = buffer + bufsize - (SHA1_DIGEST_SIZE + 1
+			+ SHA1_DIGEST_SIZE + SHA1_DIGEST_SIZE);
+	authdata2 = buffer + bufsize - (SHA1_DIGEST_SIZE);
+	continueflag1 = authdata1 - 1;
+	continueflag2 = authdata2 - 1;
+	enonce1 = continueflag1 - TPM_NONCE_SIZE;
+	enonce2 = continueflag2 - TPM_NONCE_SIZE;
+
+	sdesc = init_sdesc(hashalg);
+	if (IS_ERR(sdesc)) {
+		pr_info("trusted_key: can't alloc %s\n", hash_alg);
+		return PTR_ERR(sdesc);
+	}
+	ret = crypto_shash_init(&sdesc->shash);
+	if (ret < 0)
+		goto out;
+	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,
+				  sizeof result);
+	if (ret < 0)
+		goto out;
+	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
+				  sizeof ordinal);
+	if (ret < 0)
+		goto out;
+
+	va_start(argp, keylen2);
+	for (;;) {
+		dlen = va_arg(argp, unsigned int);
+		if (dlen == 0)
+			break;
+		dpos = va_arg(argp, unsigned int);
+		ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
+		if (ret < 0)
+			break;
+	}
+	va_end(argp);
+	if (!ret)
+		ret = crypto_shash_final(&sdesc->shash, paramdigest);
+	if (ret < 0)
+		goto out;
+
+	ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE,
+			  paramdigest, TPM_NONCE_SIZE, enonce1,
+			  TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0);
+	if (ret < 0)
+		goto out;
+	if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) {
+		ret = -EINVAL;
+		goto out;
+	}
+	ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE,
+			  paramdigest, TPM_NONCE_SIZE, enonce2,
+			  TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0);
+	if (ret < 0)
+		goto out;
+	if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE))
+		ret = -EINVAL;
+out:
+	kfree(sdesc);
+	return ret;
+}
+
+/*
+ * 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(struct tpm_chip *chip, unsigned char *cmd,
+			    size_t buflen, const char *desc)
+{
+	int rc;
+
+	dump_tpm_buf(cmd);
+	rc = tpm_send_command(chip, cmd, buflen, desc);
+	dump_tpm_buf(cmd);
+	if (rc > 0)
+		/* Can't return positive return codes values to keyctl */
+		rc = -EPERM;
+	return rc;
+}
+
+/*
+ * Create an object specific authorisation protocol (OSAP) session
+ */
+static int osap(struct tpm_chip *chip,
+		struct tpm_buf *tb, struct osapsess *s,
+		const unsigned char *key, uint16_t type, uint32_t handle)
+{
+	unsigned char enonce[TPM_NONCE_SIZE];
+	unsigned char ononce[TPM_NONCE_SIZE];
+	int ret;
+
+	ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE);
+	if (ret != TPM_NONCE_SIZE)
+		return ret;
+
+	INIT_BUF(tb);
+	store16(tb, TPM_TAG_RQU_COMMAND);
+	store32(tb, TPM_OSAP_SIZE);
+	store32(tb, TPM_ORD_OSAP);
+	store16(tb, type);
+	store32(tb, handle);
+	storebytes(tb, ononce, TPM_NONCE_SIZE);
+
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
+			       "creating OSAP session");
+	if (ret < 0)
+		return ret;
+
+	s->handle = LOAD32(tb->data, TPM_DATA_OFFSET);
+	memcpy(s->enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]),
+	       TPM_NONCE_SIZE);
+	memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +
+				  TPM_NONCE_SIZE]), TPM_NONCE_SIZE);
+	return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE,
+			   enonce, TPM_NONCE_SIZE, ononce, 0, 0);
+}
+
+/*
+ * Create an object independent authorisation protocol (oiap) session
+ */
+static int oiap(struct tpm_chip *chip, struct tpm_buf *tb, uint32_t *handle,
+		unsigned char *nonce)
+{
+	int ret;
+
+	INIT_BUF(tb);
+	store16(tb, TPM_TAG_RQU_COMMAND);
+	store32(tb, TPM_OIAP_SIZE);
+	store32(tb, TPM_ORD_OIAP);
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
+			       "creating OIAP session");
+	if (ret < 0)
+		return ret;
+
+	*handle = LOAD32(tb->data, TPM_DATA_OFFSET);
+	memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)],
+	       TPM_NONCE_SIZE);
+	return 0;
+}
+
+struct tpm_digests {
+	unsigned char encauth[SHA1_DIGEST_SIZE];
+	unsigned char pubauth[SHA1_DIGEST_SIZE];
+	unsigned char xorwork[SHA1_DIGEST_SIZE * 2];
+	unsigned char xorhash[SHA1_DIGEST_SIZE];
+	unsigned char nonceodd[TPM_NONCE_SIZE];
+};
+
+/*
+ * Have the TPM seal(encrypt) the trusted key, possibly based on
+ * Platform Configuration Registers (PCRs). AUTH1 for sealing key.
+ */
+int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
+	     uint32_t keyhandle, const unsigned char *keyauth,
+	     const unsigned char *data, uint32_t datalen,
+	     unsigned char *blob, uint32_t *bloblen,
+	     const unsigned char *blobauth,
+	     const unsigned char *pcrinfo, uint32_t pcrinfosize)
+{
+	struct osapsess sess;
+	struct tpm_digests *td;
+	unsigned char cont;
+	uint32_t ordinal;
+	uint32_t pcrsize;
+	uint32_t datsize;
+	int sealinfosize;
+	int encdatasize;
+	int storedsize;
+	int ret;
+	int i;
+
+	/* alloc some work space for all the hashes */
+	td = kmalloc(sizeof *td, GFP_KERNEL);
+	if (!td)
+		return -ENOMEM;
+
+	/* get session for sealing key */
+	ret = osap(chip, tb, &sess, keyauth, keytype, keyhandle);
+	if (ret < 0)
+		goto out;
+	dump_sess(&sess);
+
+	/* calculate encrypted authorization value */
+	memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE);
+	memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE);
+	ret = TSS_sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);
+	if (ret < 0)
+		goto out;
+
+	ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE);
+	if (ret != TPM_NONCE_SIZE)
+		goto out;
+	ordinal = htonl(TPM_ORD_SEAL);
+	datsize = htonl(datalen);
+	pcrsize = htonl(pcrinfosize);
+	cont = 0;
+
+	/* encrypt data authorization key */
+	for (i = 0; i < SHA1_DIGEST_SIZE; ++i)
+		td->encauth[i] = td->xorhash[i] ^ blobauth[i];
+
+	/* calculate authorization HMAC value */
+	if (pcrinfosize == 0) {
+		/* no pcr info specified */
+		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
+				   sess.enonce, td->nonceodd, cont,
+				   sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,
+				   td->encauth, sizeof(uint32_t), &pcrsize,
+				   sizeof(uint32_t), &datsize, datalen, data, 0,
+				   0);
+	} else {
+		/* pcr info specified */
+		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
+				   sess.enonce, td->nonceodd, cont,
+				   sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,
+				   td->encauth, sizeof(uint32_t), &pcrsize,
+				   pcrinfosize, pcrinfo, sizeof(uint32_t),
+				   &datsize, datalen, data, 0, 0);
+	}
+	if (ret < 0)
+		goto out;
+
+	/* build and send the TPM request packet */
+	INIT_BUF(tb);
+	store16(tb, TPM_TAG_RQU_AUTH1_COMMAND);
+	store32(tb, TPM_SEAL_SIZE + pcrinfosize + datalen);
+	store32(tb, TPM_ORD_SEAL);
+	store32(tb, keyhandle);
+	storebytes(tb, td->encauth, SHA1_DIGEST_SIZE);
+	store32(tb, pcrinfosize);
+	storebytes(tb, pcrinfo, pcrinfosize);
+	store32(tb, datalen);
+	storebytes(tb, data, datalen);
+	store32(tb, sess.handle);
+	storebytes(tb, td->nonceodd, TPM_NONCE_SIZE);
+	store8(tb, cont);
+	storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE);
+
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
+			       "sealing data");
+	if (ret < 0)
+		goto out;
+
+	/* calculate the size of the returned Blob */
+	sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t));
+	encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t) +
+			     sizeof(uint32_t) + sealinfosize);
+	storedsize = sizeof(uint32_t) + sizeof(uint32_t) + sealinfosize +
+	    sizeof(uint32_t) + encdatasize;
+
+	/* check the HMAC in the response */
+	ret = TSS_checkhmac1(tb->data, ordinal, td->nonceodd, sess.secret,
+			     SHA1_DIGEST_SIZE, storedsize, TPM_DATA_OFFSET, 0,
+			     0);
+
+	/* copy the returned blob to caller */
+	if (!ret) {
+		memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize);
+		*bloblen = storedsize;
+	}
+out:
+	kfree(td);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tpm_seal);
+
+/*
+ * use the AUTH2_COMMAND form of unseal, to authorize both key and blob
+ */
+int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
+	       uint32_t keyhandle, const unsigned char *keyauth,
+	       const unsigned char *blob, int bloblen,
+	       const unsigned char *blobauth,
+	       unsigned char *data, unsigned int *datalen)
+{
+	unsigned char nonceodd[TPM_NONCE_SIZE];
+	unsigned char enonce1[TPM_NONCE_SIZE];
+	unsigned char enonce2[TPM_NONCE_SIZE];
+	unsigned char authdata1[SHA1_DIGEST_SIZE];
+	unsigned char authdata2[SHA1_DIGEST_SIZE];
+	uint32_t authhandle1 = 0;
+	uint32_t authhandle2 = 0;
+	unsigned char cont = 0;
+	uint32_t ordinal;
+	uint32_t keyhndl;
+	int ret;
+
+	/* sessions for unsealing key and data */
+	ret = oiap(chip, tb, &authhandle1, enonce1);
+	if (ret < 0) {
+		pr_info("trusted_key: oiap failed (%d)\n", ret);
+		return ret;
+	}
+	ret = oiap(chip, tb, &authhandle2, enonce2);
+	if (ret < 0) {
+		pr_info("trusted_key: oiap failed (%d)\n", ret);
+		return ret;
+	}
+
+	ordinal = htonl(TPM_ORD_UNSEAL);
+	keyhndl = htonl(SRKHANDLE);
+	ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE);
+	if (ret != TPM_NONCE_SIZE) {
+		pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
+		return ret;
+	}
+	ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,
+			   enonce1, nonceodd, cont, sizeof(uint32_t),
+			   &ordinal, bloblen, blob, 0, 0);
+	if (ret < 0)
+		return ret;
+	ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE,
+			   enonce2, nonceodd, cont, sizeof(uint32_t),
+			   &ordinal, bloblen, blob, 0, 0);
+	if (ret < 0)
+		return ret;
+
+	/* build and send TPM request packet */
+	INIT_BUF(tb);
+	store16(tb, TPM_TAG_RQU_AUTH2_COMMAND);
+	store32(tb, TPM_UNSEAL_SIZE + bloblen);
+	store32(tb, TPM_ORD_UNSEAL);
+	store32(tb, keyhandle);
+	storebytes(tb, blob, bloblen);
+	store32(tb, authhandle1);
+	storebytes(tb, nonceodd, TPM_NONCE_SIZE);
+	store8(tb, cont);
+	storebytes(tb, authdata1, SHA1_DIGEST_SIZE);
+	store32(tb, authhandle2);
+	storebytes(tb, nonceodd, TPM_NONCE_SIZE);
+	store8(tb, cont);
+	storebytes(tb, authdata2, SHA1_DIGEST_SIZE);
+
+	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
+			       "unsealing data");
+	if (ret < 0) {
+		pr_info("trusted_key: authhmac failed (%d)\n", ret);
+		return ret;
+	}
+
+	*datalen = LOAD32(tb->data, TPM_DATA_OFFSET);
+	ret = TSS_checkhmac2(tb->data, ordinal, nonceodd,
+			     keyauth, SHA1_DIGEST_SIZE,
+			     blobauth, SHA1_DIGEST_SIZE,
+			     sizeof(uint32_t), TPM_DATA_OFFSET,
+			     *datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0,
+			     0);
+	if (ret < 0) {
+		pr_info("trusted_key: TSS_checkhmac2 failed (%d)\n", ret);
+		return ret;
+	}
+	memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(tpm_unseal);
+
+void trusted_shash_release(void)
+{
+	if (hashalg)
+		crypto_free_shash(hashalg);
+	if (hmacalg)
+		crypto_free_shash(hmacalg);
+}
+EXPORT_SYMBOL_GPL(trusted_shash_release);
+
+int trusted_shash_alloc(void)
+{
+	int ret;
+
+	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(hmacalg)) {
+		pr_info("trusted_key: could not allocate crypto %s\n",
+			hmac_alg);
+		return PTR_ERR(hmacalg);
+	}
+
+	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(hashalg)) {
+		pr_info("trusted_key: could not allocate crypto %s\n",
+			hash_alg);
+		ret = PTR_ERR(hashalg);
+		goto hashalg_fail;
+	}
+
+	return 0;
+
+hashalg_fail:
+	crypto_free_shash(hmacalg);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(trusted_shash_alloc);
diff --git a/drivers/char/tpm/tpm-library.h b/drivers/char/tpm/tpm-library.h
new file mode 100644
index 000000000000..eec1dfe26c2a
--- /dev/null
+++ b/drivers/char/tpm/tpm-library.h
@@ -0,0 +1,83 @@
+/* TPM call wrapper library internal definitions.
+ *
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * David Safford <safford-r/Jw6+rmf7HQT0dZR+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 License as published by
+ * the Free Software Foundation, version 2 of the License.
+ */
+
+
+#define LOAD32(buffer, offset)	(ntohl(*(uint32_t *)&buffer[offset]))
+#define LOAD32N(buffer, offset)	(*(uint32_t *)&buffer[offset])
+#define LOAD16(buffer, offset)	(ntohs(*(uint16_t *)&buffer[offset]))
+
+struct osapsess {
+	uint32_t handle;
+	unsigned char secret[SHA1_DIGEST_SIZE];
+	unsigned char enonce[TPM_NONCE_SIZE];
+};
+
+static inline void store8(struct tpm_buf *buf, const unsigned char value)
+{
+	buf->data[buf->len++] = value;
+}
+
+static inline void store16(struct tpm_buf *buf, const uint16_t value)
+{
+	*(uint16_t *) & buf->data[buf->len] = htons(value);
+	buf->len += sizeof value;
+}
+
+static inline void store32(struct tpm_buf *buf, const uint32_t value)
+{
+	*(uint32_t *) & buf->data[buf->len] = htonl(value);
+	buf->len += sizeof value;
+}
+
+static inline void storebytes(struct tpm_buf *buf, const unsigned char *in,
+			      const int len)
+{
+	memcpy(buf->data + buf->len, in, len);
+	buf->len += len;
+}
+
+/*
+ * Debugging
+ */
+#define TPM_DEBUG 0
+
+#ifdef TPM_DEBUG
+static inline void dump_sess(struct osapsess *s)
+{
+	print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE,
+		       16, 1, &s->handle, 4, 0);
+	pr_info("trusted-key: secret:\n");
+	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
+		       16, 1, &s->secret, SHA1_DIGEST_SIZE, 0);
+	pr_info("trusted-key: enonce:\n");
+	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
+		       16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);
+}
+
+static inline void dump_tpm_buf(unsigned char *buf)
+{
+	int len;
+
+	pr_info("\ntrusted-key: tpm buffer\n");
+	len = LOAD32(buf, TPM_SIZE_OFFSET);
+	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
+}
+
+#else
+static inline void dump_sess(struct osapsess *s)
+{
+}
+
+static inline void dump_tpm_buf(unsigned char *buf)
+{
+}
+#endif
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index f4e14405f5cf..5d8caf56c272 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -77,4 +77,42 @@ static inline int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max) {
 	return -ENODEV;
 }
 #endif
+
+/*
+ * TPM call library.
+ */
+/* implementation specific TPM constants */
+#define MAX_PCRINFO_SIZE		64
+#define MAX_BUF_SIZE			512
+#define TPM_GETRANDOM_SIZE		14
+#define TPM_OSAP_SIZE			36
+#define TPM_OIAP_SIZE			10
+#define TPM_SEAL_SIZE			87
+#define TPM_UNSEAL_SIZE			104
+#define TPM_SIZE_OFFSET			2
+#define TPM_RETURN_OFFSET		6
+#define TPM_DATA_OFFSET			10
+
+struct tpm_buf {
+	int len;
+	unsigned char data[MAX_BUF_SIZE];
+};
+
+#define INIT_BUF(tb) (tb->len = 0)
+
+extern void trusted_shash_release(void);
+extern int trusted_shash_alloc(void);
+
+extern int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
+		    uint32_t keyhandle, const unsigned char *keyauth,
+		    const unsigned char *data, uint32_t datalen,
+		    unsigned char *blob, uint32_t *bloblen,
+		    const unsigned char *blobauth,
+		    const unsigned char *pcrinfo, uint32_t pcrinfosize);
+extern int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
+		      uint32_t keyhandle, const unsigned char *keyauth,
+		      const unsigned char *blob, int bloblen,
+		      const unsigned char *blobauth,
+		      unsigned char *data, unsigned int *datalen);
+
 #endif
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index 943c65b53201..83c6a485e62a 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -31,343 +31,6 @@
 
 #include "trusted.h"
 
-static const char hmac_alg[] = "hmac(sha1)";
-static const char hash_alg[] = "sha1";
-
-struct sdesc {
-	struct shash_desc shash;
-	char ctx[];
-};
-
-static struct crypto_shash *hashalg;
-static struct crypto_shash *hmacalg;
-
-static struct sdesc *init_sdesc(struct crypto_shash *alg)
-{
-	struct sdesc *sdesc;
-	int size;
-
-	size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
-	sdesc = kmalloc(size, GFP_KERNEL);
-	if (!sdesc)
-		return ERR_PTR(-ENOMEM);
-	sdesc->shash.tfm = alg;
-	sdesc->shash.flags = 0x0;
-	return sdesc;
-}
-
-static int TSS_sha1(const unsigned char *data, unsigned int datalen,
-		    unsigned char *digest)
-{
-	struct sdesc *sdesc;
-	int ret;
-
-	sdesc = init_sdesc(hashalg);
-	if (IS_ERR(sdesc)) {
-		pr_info("trusted_key: can't alloc %s\n", hash_alg);
-		return PTR_ERR(sdesc);
-	}
-
-	ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
-	kfree(sdesc);
-	return ret;
-}
-
-static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,
-		       unsigned int keylen, ...)
-{
-	struct sdesc *sdesc;
-	va_list argp;
-	unsigned int dlen;
-	unsigned char *data;
-	int ret;
-
-	sdesc = init_sdesc(hmacalg);
-	if (IS_ERR(sdesc)) {
-		pr_info("trusted_key: can't alloc %s\n", hmac_alg);
-		return PTR_ERR(sdesc);
-	}
-
-	ret = crypto_shash_setkey(hmacalg, key, keylen);
-	if (ret < 0)
-		goto out;
-	ret = crypto_shash_init(&sdesc->shash);
-	if (ret < 0)
-		goto out;
-
-	va_start(argp, keylen);
-	for (;;) {
-		dlen = va_arg(argp, unsigned int);
-		if (dlen == 0)
-			break;
-		data = va_arg(argp, unsigned char *);
-		if (data == NULL) {
-			ret = -EINVAL;
-			break;
-		}
-		ret = crypto_shash_update(&sdesc->shash, data, dlen);
-		if (ret < 0)
-			break;
-	}
-	va_end(argp);
-	if (!ret)
-		ret = crypto_shash_final(&sdesc->shash, digest);
-out:
-	kfree(sdesc);
-	return ret;
-}
-
-/*
- * calculate authorization info fields to send to TPM
- */
-static int TSS_authhmac(unsigned char *digest, const unsigned char *key,
-			unsigned int keylen, unsigned char *h1,
-			unsigned char *h2, unsigned char h3, ...)
-{
-	unsigned char paramdigest[SHA1_DIGEST_SIZE];
-	struct sdesc *sdesc;
-	unsigned int dlen;
-	unsigned char *data;
-	unsigned char c;
-	int ret;
-	va_list argp;
-
-	sdesc = init_sdesc(hashalg);
-	if (IS_ERR(sdesc)) {
-		pr_info("trusted_key: can't alloc %s\n", hash_alg);
-		return PTR_ERR(sdesc);
-	}
-
-	c = h3;
-	ret = crypto_shash_init(&sdesc->shash);
-	if (ret < 0)
-		goto out;
-	va_start(argp, h3);
-	for (;;) {
-		dlen = va_arg(argp, unsigned int);
-		if (dlen == 0)
-			break;
-		data = va_arg(argp, unsigned char *);
-		if (!data) {
-			ret = -EINVAL;
-			break;
-		}
-		ret = crypto_shash_update(&sdesc->shash, data, dlen);
-		if (ret < 0)
-			break;
-	}
-	va_end(argp);
-	if (!ret)
-		ret = crypto_shash_final(&sdesc->shash, paramdigest);
-	if (!ret)
-		ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE,
-				  paramdigest, TPM_NONCE_SIZE, h1,
-				  TPM_NONCE_SIZE, h2, 1, &c, 0, 0);
-out:
-	kfree(sdesc);
-	return ret;
-}
-
-/*
- * verify the AUTH1_COMMAND (Seal) result from TPM
- */
-static int TSS_checkhmac1(unsigned char *buffer,
-			  const uint32_t command,
-			  const unsigned char *ononce,
-			  const unsigned char *key,
-			  unsigned int keylen, ...)
-{
-	uint32_t bufsize;
-	uint16_t tag;
-	uint32_t ordinal;
-	uint32_t result;
-	unsigned char *enonce;
-	unsigned char *continueflag;
-	unsigned char *authdata;
-	unsigned char testhmac[SHA1_DIGEST_SIZE];
-	unsigned char paramdigest[SHA1_DIGEST_SIZE];
-	struct sdesc *sdesc;
-	unsigned int dlen;
-	unsigned int dpos;
-	va_list argp;
-	int ret;
-
-	bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
-	tag = LOAD16(buffer, 0);
-	ordinal = command;
-	result = LOAD32N(buffer, TPM_RETURN_OFFSET);
-	if (tag == TPM_TAG_RSP_COMMAND)
-		return 0;
-	if (tag != TPM_TAG_RSP_AUTH1_COMMAND)
-		return -EINVAL;
-	authdata = buffer + bufsize - SHA1_DIGEST_SIZE;
-	continueflag = authdata - 1;
-	enonce = continueflag - TPM_NONCE_SIZE;
-
-	sdesc = init_sdesc(hashalg);
-	if (IS_ERR(sdesc)) {
-		pr_info("trusted_key: can't alloc %s\n", hash_alg);
-		return PTR_ERR(sdesc);
-	}
-	ret = crypto_shash_init(&sdesc->shash);
-	if (ret < 0)
-		goto out;
-	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,
-				  sizeof result);
-	if (ret < 0)
-		goto out;
-	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
-				  sizeof ordinal);
-	if (ret < 0)
-		goto out;
-	va_start(argp, keylen);
-	for (;;) {
-		dlen = va_arg(argp, unsigned int);
-		if (dlen == 0)
-			break;
-		dpos = va_arg(argp, unsigned int);
-		ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
-		if (ret < 0)
-			break;
-	}
-	va_end(argp);
-	if (!ret)
-		ret = crypto_shash_final(&sdesc->shash, paramdigest);
-	if (ret < 0)
-		goto out;
-
-	ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest,
-			  TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce,
-			  1, continueflag, 0, 0);
-	if (ret < 0)
-		goto out;
-
-	if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE))
-		ret = -EINVAL;
-out:
-	kfree(sdesc);
-	return ret;
-}
-
-/*
- * verify the AUTH2_COMMAND (unseal) result from TPM
- */
-static int TSS_checkhmac2(unsigned char *buffer,
-			  const uint32_t command,
-			  const unsigned char *ononce,
-			  const unsigned char *key1,
-			  unsigned int keylen1,
-			  const unsigned char *key2,
-			  unsigned int keylen2, ...)
-{
-	uint32_t bufsize;
-	uint16_t tag;
-	uint32_t ordinal;
-	uint32_t result;
-	unsigned char *enonce1;
-	unsigned char *continueflag1;
-	unsigned char *authdata1;
-	unsigned char *enonce2;
-	unsigned char *continueflag2;
-	unsigned char *authdata2;
-	unsigned char testhmac1[SHA1_DIGEST_SIZE];
-	unsigned char testhmac2[SHA1_DIGEST_SIZE];
-	unsigned char paramdigest[SHA1_DIGEST_SIZE];
-	struct sdesc *sdesc;
-	unsigned int dlen;
-	unsigned int dpos;
-	va_list argp;
-	int ret;
-
-	bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
-	tag = LOAD16(buffer, 0);
-	ordinal = command;
-	result = LOAD32N(buffer, TPM_RETURN_OFFSET);
-
-	if (tag == TPM_TAG_RSP_COMMAND)
-		return 0;
-	if (tag != TPM_TAG_RSP_AUTH2_COMMAND)
-		return -EINVAL;
-	authdata1 = buffer + bufsize - (SHA1_DIGEST_SIZE + 1
-			+ SHA1_DIGEST_SIZE + SHA1_DIGEST_SIZE);
-	authdata2 = buffer + bufsize - (SHA1_DIGEST_SIZE);
-	continueflag1 = authdata1 - 1;
-	continueflag2 = authdata2 - 1;
-	enonce1 = continueflag1 - TPM_NONCE_SIZE;
-	enonce2 = continueflag2 - TPM_NONCE_SIZE;
-
-	sdesc = init_sdesc(hashalg);
-	if (IS_ERR(sdesc)) {
-		pr_info("trusted_key: can't alloc %s\n", hash_alg);
-		return PTR_ERR(sdesc);
-	}
-	ret = crypto_shash_init(&sdesc->shash);
-	if (ret < 0)
-		goto out;
-	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,
-				  sizeof result);
-	if (ret < 0)
-		goto out;
-	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
-				  sizeof ordinal);
-	if (ret < 0)
-		goto out;
-
-	va_start(argp, keylen2);
-	for (;;) {
-		dlen = va_arg(argp, unsigned int);
-		if (dlen == 0)
-			break;
-		dpos = va_arg(argp, unsigned int);
-		ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
-		if (ret < 0)
-			break;
-	}
-	va_end(argp);
-	if (!ret)
-		ret = crypto_shash_final(&sdesc->shash, paramdigest);
-	if (ret < 0)
-		goto out;
-
-	ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE,
-			  paramdigest, TPM_NONCE_SIZE, enonce1,
-			  TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0);
-	if (ret < 0)
-		goto out;
-	if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) {
-		ret = -EINVAL;
-		goto out;
-	}
-	ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE,
-			  paramdigest, TPM_NONCE_SIZE, enonce2,
-			  TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0);
-	if (ret < 0)
-		goto out;
-	if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE))
-		ret = -EINVAL;
-out:
-	kfree(sdesc);
-	return ret;
-}
-
-/*
- * 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(struct tpm_chip *chip, unsigned char *cmd,
-			    size_t buflen, const char *desc)
-{
-	int rc;
-
-	dump_tpm_buf(cmd);
-	rc = tpm_send_command(chip, cmd, buflen, desc);
-	dump_tpm_buf(cmd);
-	if (rc > 0)
-		/* Can't return positive return codes values to keyctl */
-		rc = -EPERM;
-	return rc;
-}
-
 /*
  * Lock a trusted key, by extending a selected PCR.
  *
@@ -387,281 +50,6 @@ static int pcrlock(struct tpm_chip *chip, const int pcrnum)
 	return tpm_pcr_extend(chip, pcrnum, hash) ? -EINVAL : 0;
 }
 
-/*
- * Create an object specific authorisation protocol (OSAP) session
- */
-static int osap(struct tpm_chip *chip,
-		struct tpm_buf *tb, struct osapsess *s,
-		const unsigned char *key, uint16_t type, uint32_t handle)
-{
-	unsigned char enonce[TPM_NONCE_SIZE];
-	unsigned char ononce[TPM_NONCE_SIZE];
-	int ret;
-
-	ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE);
-	if (ret != TPM_NONCE_SIZE)
-		return ret;
-
-	INIT_BUF(tb);
-	store16(tb, TPM_TAG_RQU_COMMAND);
-	store32(tb, TPM_OSAP_SIZE);
-	store32(tb, TPM_ORD_OSAP);
-	store16(tb, type);
-	store32(tb, handle);
-	storebytes(tb, ononce, TPM_NONCE_SIZE);
-
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
-			       "creating OSAP session");
-	if (ret < 0)
-		return ret;
-
-	s->handle = LOAD32(tb->data, TPM_DATA_OFFSET);
-	memcpy(s->enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]),
-	       TPM_NONCE_SIZE);
-	memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +
-				  TPM_NONCE_SIZE]), TPM_NONCE_SIZE);
-	return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE,
-			   enonce, TPM_NONCE_SIZE, ononce, 0, 0);
-}
-
-/*
- * Create an object independent authorisation protocol (oiap) session
- */
-static int oiap(struct tpm_chip *chip, struct tpm_buf *tb, uint32_t *handle,
-		unsigned char *nonce)
-{
-	int ret;
-
-	INIT_BUF(tb);
-	store16(tb, TPM_TAG_RQU_COMMAND);
-	store32(tb, TPM_OIAP_SIZE);
-	store32(tb, TPM_ORD_OIAP);
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
-			       "creating OIAP session");
-	if (ret < 0)
-		return ret;
-
-	*handle = LOAD32(tb->data, TPM_DATA_OFFSET);
-	memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)],
-	       TPM_NONCE_SIZE);
-	return 0;
-}
-
-struct tpm_digests {
-	unsigned char encauth[SHA1_DIGEST_SIZE];
-	unsigned char pubauth[SHA1_DIGEST_SIZE];
-	unsigned char xorwork[SHA1_DIGEST_SIZE * 2];
-	unsigned char xorhash[SHA1_DIGEST_SIZE];
-	unsigned char nonceodd[TPM_NONCE_SIZE];
-};
-
-/*
- * Have the TPM seal(encrypt) the trusted key, possibly based on
- * Platform Configuration Registers (PCRs). AUTH1 for sealing key.
- */
-static int tpm_seal(struct tpm_chip *chip,
-		    struct tpm_buf *tb, uint16_t keytype,
-		    uint32_t keyhandle, const unsigned char *keyauth,
-		    const unsigned char *data, uint32_t datalen,
-		    unsigned char *blob, uint32_t *bloblen,
-		    const unsigned char *blobauth,
-		    const unsigned char *pcrinfo, uint32_t pcrinfosize)
-{
-	struct osapsess sess;
-	struct tpm_digests *td;
-	unsigned char cont;
-	uint32_t ordinal;
-	uint32_t pcrsize;
-	uint32_t datsize;
-	int sealinfosize;
-	int encdatasize;
-	int storedsize;
-	int ret;
-	int i;
-
-	/* alloc some work space for all the hashes */
-	td = kmalloc(sizeof *td, GFP_KERNEL);
-	if (!td)
-		return -ENOMEM;
-
-	/* get session for sealing key */
-	ret = osap(chip, tb, &sess, keyauth, keytype, keyhandle);
-	if (ret < 0)
-		goto out;
-	dump_sess(&sess);
-
-	/* calculate encrypted authorization value */
-	memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE);
-	memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE);
-	ret = TSS_sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);
-	if (ret < 0)
-		goto out;
-
-	ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE);
-	if (ret != TPM_NONCE_SIZE)
-		goto out;
-	ordinal = htonl(TPM_ORD_SEAL);
-	datsize = htonl(datalen);
-	pcrsize = htonl(pcrinfosize);
-	cont = 0;
-
-	/* encrypt data authorization key */
-	for (i = 0; i < SHA1_DIGEST_SIZE; ++i)
-		td->encauth[i] = td->xorhash[i] ^ blobauth[i];
-
-	/* calculate authorization HMAC value */
-	if (pcrinfosize == 0) {
-		/* no pcr info specified */
-		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
-				   sess.enonce, td->nonceodd, cont,
-				   sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,
-				   td->encauth, sizeof(uint32_t), &pcrsize,
-				   sizeof(uint32_t), &datsize, datalen, data, 0,
-				   0);
-	} else {
-		/* pcr info specified */
-		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
-				   sess.enonce, td->nonceodd, cont,
-				   sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,
-				   td->encauth, sizeof(uint32_t), &pcrsize,
-				   pcrinfosize, pcrinfo, sizeof(uint32_t),
-				   &datsize, datalen, data, 0, 0);
-	}
-	if (ret < 0)
-		goto out;
-
-	/* build and send the TPM request packet */
-	INIT_BUF(tb);
-	store16(tb, TPM_TAG_RQU_AUTH1_COMMAND);
-	store32(tb, TPM_SEAL_SIZE + pcrinfosize + datalen);
-	store32(tb, TPM_ORD_SEAL);
-	store32(tb, keyhandle);
-	storebytes(tb, td->encauth, SHA1_DIGEST_SIZE);
-	store32(tb, pcrinfosize);
-	storebytes(tb, pcrinfo, pcrinfosize);
-	store32(tb, datalen);
-	storebytes(tb, data, datalen);
-	store32(tb, sess.handle);
-	storebytes(tb, td->nonceodd, TPM_NONCE_SIZE);
-	store8(tb, cont);
-	storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE);
-
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
-			       "sealing data");
-	if (ret < 0)
-		goto out;
-
-	/* calculate the size of the returned Blob */
-	sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t));
-	encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t) +
-			     sizeof(uint32_t) + sealinfosize);
-	storedsize = sizeof(uint32_t) + sizeof(uint32_t) + sealinfosize +
-	    sizeof(uint32_t) + encdatasize;
-
-	/* check the HMAC in the response */
-	ret = TSS_checkhmac1(tb->data, ordinal, td->nonceodd, sess.secret,
-			     SHA1_DIGEST_SIZE, storedsize, TPM_DATA_OFFSET, 0,
-			     0);
-
-	/* copy the returned blob to caller */
-	if (!ret) {
-		memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize);
-		*bloblen = storedsize;
-	}
-out:
-	kfree(td);
-	return ret;
-}
-
-/*
- * use the AUTH2_COMMAND form of unseal, to authorize both key and blob
- */
-static int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
-		      uint32_t keyhandle, const unsigned char *keyauth,
-		      const unsigned char *blob, int bloblen,
-		      const unsigned char *blobauth,
-		      unsigned char *data, unsigned int *datalen)
-{
-	unsigned char nonceodd[TPM_NONCE_SIZE];
-	unsigned char enonce1[TPM_NONCE_SIZE];
-	unsigned char enonce2[TPM_NONCE_SIZE];
-	unsigned char authdata1[SHA1_DIGEST_SIZE];
-	unsigned char authdata2[SHA1_DIGEST_SIZE];
-	uint32_t authhandle1 = 0;
-	uint32_t authhandle2 = 0;
-	unsigned char cont = 0;
-	uint32_t ordinal;
-	uint32_t keyhndl;
-	int ret;
-
-	/* sessions for unsealing key and data */
-	ret = oiap(chip, tb, &authhandle1, enonce1);
-	if (ret < 0) {
-		pr_info("trusted_key: oiap failed (%d)\n", ret);
-		return ret;
-	}
-	ret = oiap(chip, tb, &authhandle2, enonce2);
-	if (ret < 0) {
-		pr_info("trusted_key: oiap failed (%d)\n", ret);
-		return ret;
-	}
-
-	ordinal = htonl(TPM_ORD_UNSEAL);
-	keyhndl = htonl(SRKHANDLE);
-	ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE);
-	if (ret != TPM_NONCE_SIZE) {
-		pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
-		return ret;
-	}
-	ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,
-			   enonce1, nonceodd, cont, sizeof(uint32_t),
-			   &ordinal, bloblen, blob, 0, 0);
-	if (ret < 0)
-		return ret;
-	ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE,
-			   enonce2, nonceodd, cont, sizeof(uint32_t),
-			   &ordinal, bloblen, blob, 0, 0);
-	if (ret < 0)
-		return ret;
-
-	/* build and send TPM request packet */
-	INIT_BUF(tb);
-	store16(tb, TPM_TAG_RQU_AUTH2_COMMAND);
-	store32(tb, TPM_UNSEAL_SIZE + bloblen);
-	store32(tb, TPM_ORD_UNSEAL);
-	store32(tb, keyhandle);
-	storebytes(tb, blob, bloblen);
-	store32(tb, authhandle1);
-	storebytes(tb, nonceodd, TPM_NONCE_SIZE);
-	store8(tb, cont);
-	storebytes(tb, authdata1, SHA1_DIGEST_SIZE);
-	store32(tb, authhandle2);
-	storebytes(tb, nonceodd, TPM_NONCE_SIZE);
-	store8(tb, cont);
-	storebytes(tb, authdata2, SHA1_DIGEST_SIZE);
-
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
-			       "unsealing data");
-	if (ret < 0) {
-		pr_info("trusted_key: authhmac failed (%d)\n", ret);
-		return ret;
-	}
-
-	*datalen = LOAD32(tb->data, TPM_DATA_OFFSET);
-	ret = TSS_checkhmac2(tb->data, ordinal, nonceodd,
-			     keyauth, SHA1_DIGEST_SIZE,
-			     blobauth, SHA1_DIGEST_SIZE,
-			     sizeof(uint32_t), TPM_DATA_OFFSET,
-			     *datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0,
-			     0);
-	if (ret < 0) {
-		pr_info("trusted_key: TSS_checkhmac2 failed (%d)\n", ret);
-		return ret;
-	}
-	memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen);
-	return 0;
-}
-
 /*
  * Have the TPM seal(encrypt) the symmetric key
  */
@@ -1129,40 +517,6 @@ struct key_type key_type_trusted = {
 
 EXPORT_SYMBOL_GPL(key_type_trusted);
 
-static void trusted_shash_release(void)
-{
-	if (hashalg)
-		crypto_free_shash(hashalg);
-	if (hmacalg)
-		crypto_free_shash(hmacalg);
-}
-
-static int __init trusted_shash_alloc(void)
-{
-	int ret;
-
-	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(hmacalg)) {
-		pr_info("trusted_key: could not allocate crypto %s\n",
-			hmac_alg);
-		return PTR_ERR(hmacalg);
-	}
-
-	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(hashalg)) {
-		pr_info("trusted_key: could not allocate crypto %s\n",
-			hash_alg);
-		ret = PTR_ERR(hashalg);
-		goto hashalg_fail;
-	}
-
-	return 0;
-
-hashalg_fail:
-	crypto_free_shash(hmacalg);
-	return ret;
-}
-
 static int __init init_trusted(void)
 {
 	int ret;
diff --git a/security/keys/trusted.h b/security/keys/trusted.h
index 3249fbd2b653..61fe24d5c6b3 100644
--- a/security/keys/trusted.h
+++ b/security/keys/trusted.h
@@ -1,35 +1,6 @@
 #ifndef __TRUSTED_KEY_H
 #define __TRUSTED_KEY_H
 
-/* implementation specific TPM constants */
-#define MAX_PCRINFO_SIZE		64
-#define MAX_BUF_SIZE			512
-#define TPM_GETRANDOM_SIZE		14
-#define TPM_OSAP_SIZE			36
-#define TPM_OIAP_SIZE			10
-#define TPM_SEAL_SIZE			87
-#define TPM_UNSEAL_SIZE			104
-#define TPM_SIZE_OFFSET			2
-#define TPM_RETURN_OFFSET		6
-#define TPM_DATA_OFFSET			10
-
-#define LOAD32(buffer, offset)	(ntohl(*(uint32_t *)&buffer[offset]))
-#define LOAD32N(buffer, offset)	(*(uint32_t *)&buffer[offset])
-#define LOAD16(buffer, offset)	(ntohs(*(uint16_t *)&buffer[offset]))
-
-struct tpm_buf {
-	int len;
-	unsigned char data[MAX_BUF_SIZE];
-};
-
-#define INIT_BUF(tb) (tb->len = 0)
-
-struct osapsess {
-	uint32_t handle;
-	unsigned char secret[SHA1_DIGEST_SIZE];
-	unsigned char enonce[TPM_NONCE_SIZE];
-};
-
 /* discrete values, but have to store in uint16_t for TPM use */
 enum {
 	SEAL_keytype = 1,
@@ -70,26 +41,6 @@ static inline void dump_payload(struct trusted_key_payload *p)
 	pr_info("trusted_key: migratable %d\n", p->migratable);
 }
 
-static inline void dump_sess(struct osapsess *s)
-{
-	print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE,
-		       16, 1, &s->handle, 4, 0);
-	pr_info("trusted-key: secret:\n");
-	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
-		       16, 1, &s->secret, SHA1_DIGEST_SIZE, 0);
-	pr_info("trusted-key: enonce:\n");
-	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
-		       16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);
-}
-
-static inline void dump_tpm_buf(unsigned char *buf)
-{
-	int len;
-
-	pr_info("\ntrusted-key: tpm buffer\n");
-	len = LOAD32(buf, TPM_SIZE_OFFSET);
-	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
-}
 #else
 static inline void dump_options(struct trusted_key_options *o)
 {
@@ -99,36 +50,5 @@ static inline void dump_payload(struct trusted_key_payload *p)
 {
 }
 
-static inline void dump_sess(struct osapsess *s)
-{
-}
-
-static inline void dump_tpm_buf(unsigned char *buf)
-{
-}
 #endif
-
-static inline void store8(struct tpm_buf *buf, const unsigned char value)
-{
-	buf->data[buf->len++] = value;
-}
-
-static inline void store16(struct tpm_buf *buf, const uint16_t value)
-{
-	*(uint16_t *) & buf->data[buf->len] = htons(value);
-	buf->len += sizeof value;
-}
-
-static inline void store32(struct tpm_buf *buf, const uint32_t value)
-{
-	*(uint32_t *) & buf->data[buf->len] = htonl(value);
-	buf->len += sizeof value;
-}
-
-static inline void storebytes(struct tpm_buf *buf, const unsigned char *in,
-			      const int len)
-{
-	memcpy(buf->data + buf->len, in, len);
-	buf->len += len;
-}
 #endif


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 09/23] TPMLIB: Do some source cleanups
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (7 preceding siblings ...)
  2018-08-21 15:57   ` [PATCH 08/23] TPMLIB: Break TPM bits out of security/keys/trusted.c David Howells
@ 2018-08-21 15:57   ` David Howells
  2018-08-21 15:57   ` [PATCH 10/23] TPMLIB: Better format calls to TSS_*hmac*() David Howells
                     ` (14 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:57 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Clean up the TPM library file that was split out of trusted keys.

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

 drivers/char/tpm/tpm-library.c |  187 +++++++++++++++++++++++-----------------
 drivers/char/tpm/tpm-library.h |   14 +--
 include/linux/tpm.h            |    4 -
 security/keys/trusted.c        |    6 +
 4 files changed, 121 insertions(+), 90 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index 1be4f71cabcb..e4cfc1f090e1 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -8,44 +8,36 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 2 of the License.
- *
- * See Documentation/security/keys-trusted-encrypted.txt
  */
 
-#include <linux/uaccess.h>
-#include <linux/module.h>
-#include <linux/init.h>
+#define pr_fmt(fmt) "TPMLIB: "fmt
 #include <linux/slab.h>
-#include <linux/parser.h>
-#include <linux/string.h>
 #include <linux/err.h>
-#include <keys/user-type.h>
-#include <keys/trusted-type.h>
-#include <linux/key-type.h>
-#include <linux/rcupdate.h>
+#include <linux/mutex.h>
 #include <linux/crypto.h>
 #include <crypto/hash.h>
 #include <crypto/sha.h>
-#include <linux/capability.h>
 #include <linux/tpm.h>
 #include <linux/tpm_command.h>
 
 #include "tpm-library.h"
 
-static const char hmac_alg[] = "hmac(sha1)";
-static const char hash_alg[] = "sha1";
+static const char tpm_hmac_alg[] = "hmac(sha1)";
+static const char tpm_hash_alg[] = "sha1";
 
-struct sdesc {
+struct tpm_sdesc {
 	struct shash_desc shash;
 	char ctx[];
 };
 
-static struct crypto_shash *hashalg;
-static struct crypto_shash *hmacalg;
+static DEFINE_MUTEX(tpm_library_init_mutex);
+static atomic_t tpm_library_usage;
+static struct crypto_shash *tpm_hashalg;
+static struct crypto_shash *tpm_hmacalg;
 
-static struct sdesc *init_sdesc(struct crypto_shash *alg)
+static struct tpm_sdesc *tpm_init_sdesc(struct crypto_shash *alg)
 {
-	struct sdesc *sdesc;
+	struct tpm_sdesc *sdesc;
 	int size;
 
 	size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
@@ -60,12 +52,12 @@ static struct sdesc *init_sdesc(struct crypto_shash *alg)
 static int TSS_sha1(const unsigned char *data, unsigned int datalen,
 		    unsigned char *digest)
 {
-	struct sdesc *sdesc;
+	struct tpm_sdesc *sdesc;
 	int ret;
 
-	sdesc = init_sdesc(hashalg);
+	sdesc = tpm_init_sdesc(tpm_hashalg);
 	if (IS_ERR(sdesc)) {
-		pr_info("trusted_key: can't alloc %s\n", hash_alg);
+		pr_info("Can't alloc %s\n", tpm_hash_alg);
 		return PTR_ERR(sdesc);
 	}
 
@@ -77,19 +69,19 @@ static int TSS_sha1(const unsigned char *data, unsigned int datalen,
 static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,
 		       unsigned int keylen, ...)
 {
-	struct sdesc *sdesc;
+	struct tpm_sdesc *sdesc;
 	va_list argp;
 	unsigned int dlen;
 	unsigned char *data;
 	int ret;
 
-	sdesc = init_sdesc(hmacalg);
+	sdesc = tpm_init_sdesc(tpm_hmacalg);
 	if (IS_ERR(sdesc)) {
-		pr_info("trusted_key: can't alloc %s\n", hmac_alg);
+		pr_info("Can't alloc %s\n", tpm_hmac_alg);
 		return PTR_ERR(sdesc);
 	}
 
-	ret = crypto_shash_setkey(hmacalg, key, keylen);
+	ret = crypto_shash_setkey(tpm_hmacalg, key, keylen);
 	if (ret < 0)
 		goto out;
 	ret = crypto_shash_init(&sdesc->shash);
@@ -126,16 +118,16 @@ static int TSS_authhmac(unsigned char *digest, const unsigned char *key,
 			unsigned char *h2, unsigned char h3, ...)
 {
 	unsigned char paramdigest[SHA1_DIGEST_SIZE];
-	struct sdesc *sdesc;
+	struct tpm_sdesc *sdesc;
 	unsigned int dlen;
 	unsigned char *data;
 	unsigned char c;
 	int ret;
 	va_list argp;
 
-	sdesc = init_sdesc(hashalg);
+	sdesc = tpm_init_sdesc(tpm_hashalg);
 	if (IS_ERR(sdesc)) {
-		pr_info("trusted_key: can't alloc %s\n", hash_alg);
+		pr_info("Can't alloc %s\n", tpm_hash_alg);
 		return PTR_ERR(sdesc);
 	}
 
@@ -187,7 +179,7 @@ static int TSS_checkhmac1(unsigned char *buffer,
 	unsigned char *authdata;
 	unsigned char testhmac[SHA1_DIGEST_SIZE];
 	unsigned char paramdigest[SHA1_DIGEST_SIZE];
-	struct sdesc *sdesc;
+	struct tpm_sdesc *sdesc;
 	unsigned int dlen;
 	unsigned int dpos;
 	va_list argp;
@@ -205,9 +197,9 @@ static int TSS_checkhmac1(unsigned char *buffer,
 	continueflag = authdata - 1;
 	enonce = continueflag - TPM_NONCE_SIZE;
 
-	sdesc = init_sdesc(hashalg);
+	sdesc = tpm_init_sdesc(tpm_hashalg);
 	if (IS_ERR(sdesc)) {
-		pr_info("trusted_key: can't alloc %s\n", hash_alg);
+		pr_info("Can't alloc %s\n", tpm_hash_alg);
 		return PTR_ERR(sdesc);
 	}
 	ret = crypto_shash_init(&sdesc->shash);
@@ -274,7 +266,7 @@ static int TSS_checkhmac2(unsigned char *buffer,
 	unsigned char testhmac1[SHA1_DIGEST_SIZE];
 	unsigned char testhmac2[SHA1_DIGEST_SIZE];
 	unsigned char paramdigest[SHA1_DIGEST_SIZE];
-	struct sdesc *sdesc;
+	struct tpm_sdesc *sdesc;
 	unsigned int dlen;
 	unsigned int dpos;
 	va_list argp;
@@ -297,9 +289,9 @@ static int TSS_checkhmac2(unsigned char *buffer,
 	enonce1 = continueflag1 - TPM_NONCE_SIZE;
 	enonce2 = continueflag2 - TPM_NONCE_SIZE;
 
-	sdesc = init_sdesc(hashalg);
+	sdesc = tpm_init_sdesc(tpm_hashalg);
 	if (IS_ERR(sdesc)) {
-		pr_info("trusted_key: can't alloc %s\n", hash_alg);
+		pr_info("Can't alloc %s\n", tpm_hash_alg);
 		return PTR_ERR(sdesc);
 	}
 	ret = crypto_shash_init(&sdesc->shash);
@@ -355,8 +347,8 @@ out:
  * 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(struct tpm_chip *chip, unsigned char *cmd,
-			    size_t buflen, const char *desc)
+static int tpm_send_dump(struct tpm_chip *chip,
+			 unsigned char *cmd, size_t buflen, const char *desc)
 {
 	int rc;
 
@@ -372,9 +364,10 @@ static int trusted_tpm_send(struct tpm_chip *chip, unsigned char *cmd,
 /*
  * Create an object specific authorisation protocol (OSAP) session
  */
-static int osap(struct tpm_chip *chip,
-		struct tpm_buf *tb, struct osapsess *s,
-		const unsigned char *key, uint16_t type, uint32_t handle)
+static int tpm_create_osap(struct tpm_chip *chip,
+			   struct tpm_buf *tb, struct tpm_osapsess *s,
+			   const unsigned char *key, uint16_t type,
+			   uint32_t handle)
 {
 	unsigned char enonce[TPM_NONCE_SIZE];
 	unsigned char ononce[TPM_NONCE_SIZE];
@@ -392,8 +385,8 @@ static int osap(struct tpm_chip *chip,
 	store32(tb, handle);
 	storebytes(tb, ononce, TPM_NONCE_SIZE);
 
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
-			       "creating OSAP session");
+	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
+			    "creating OSAP session");
 	if (ret < 0)
 		return ret;
 
@@ -409,8 +402,8 @@ static int osap(struct tpm_chip *chip,
 /*
  * Create an object independent authorisation protocol (oiap) session
  */
-static int oiap(struct tpm_chip *chip, struct tpm_buf *tb, uint32_t *handle,
-		unsigned char *nonce)
+static int tpm_create_oiap(struct tpm_chip *chip, struct tpm_buf *tb,
+			   uint32_t *handle, unsigned char *nonce)
 {
 	int ret;
 
@@ -418,8 +411,8 @@ static int oiap(struct tpm_chip *chip, struct tpm_buf *tb, uint32_t *handle,
 	store16(tb, TPM_TAG_RQU_COMMAND);
 	store32(tb, TPM_OIAP_SIZE);
 	store32(tb, TPM_ORD_OIAP);
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
-			       "creating OIAP session");
+	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
+			    "creating OIAP session");
 	if (ret < 0)
 		return ret;
 
@@ -448,7 +441,7 @@ int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 	     const unsigned char *blobauth,
 	     const unsigned char *pcrinfo, uint32_t pcrinfosize)
 {
-	struct osapsess sess;
+	struct tpm_osapsess sess;
 	struct tpm_digests *td;
 	unsigned char cont;
 	uint32_t ordinal;
@@ -466,7 +459,7 @@ int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 		return -ENOMEM;
 
 	/* get session for sealing key */
-	ret = osap(chip, tb, &sess, keyauth, keytype, keyhandle);
+	ret = tpm_create_osap(chip, tb, &sess, keyauth, keytype, keyhandle);
 	if (ret < 0)
 		goto out;
 	dump_sess(&sess);
@@ -527,8 +520,8 @@ int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 	store8(tb, cont);
 	storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE);
 
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
-			       "sealing data");
+	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
+			    "sealing data");
 	if (ret < 0)
 		goto out;
 
@@ -577,14 +570,14 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	int ret;
 
 	/* sessions for unsealing key and data */
-	ret = oiap(chip, tb, &authhandle1, enonce1);
+	ret = tpm_create_oiap(chip, tb, &authhandle1, enonce1);
 	if (ret < 0) {
-		pr_info("trusted_key: oiap failed (%d)\n", ret);
+		pr_info("Failed to create OIAP 1 (%d)\n", ret);
 		return ret;
 	}
-	ret = oiap(chip, tb, &authhandle2, enonce2);
+	ret = tpm_create_oiap(chip, tb, &authhandle2, enonce2);
 	if (ret < 0) {
-		pr_info("trusted_key: oiap failed (%d)\n", ret);
+		pr_info("Failed to create OIAP 2 (%d)\n", ret);
 		return ret;
 	}
 
@@ -592,7 +585,7 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	keyhndl = htonl(SRKHANDLE);
 	ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE);
 	if (ret != TPM_NONCE_SIZE) {
-		pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
+		pr_info("tpm_get_random failed (%d)\n", ret);
 		return ret;
 	}
 	ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,
@@ -622,10 +615,10 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	store8(tb, cont);
 	storebytes(tb, authdata2, SHA1_DIGEST_SIZE);
 
-	ret = trusted_tpm_send(chip, tb->data, MAX_BUF_SIZE,
-			       "unsealing data");
+	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
+			    "unsealing data");
 	if (ret < 0) {
-		pr_info("trusted_key: authhmac failed (%d)\n", ret);
+		pr_info("authhmac failed (%d)\n", ret);
 		return ret;
 	}
 
@@ -637,7 +630,7 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 			     *datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0,
 			     0);
 	if (ret < 0) {
-		pr_info("trusted_key: TSS_checkhmac2 failed (%d)\n", ret);
+		pr_info("TSS_checkhmac2 failed (%d)\n", ret);
 		return ret;
 	}
 	memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen);
@@ -645,38 +638,76 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 }
 EXPORT_SYMBOL_GPL(tpm_unseal);
 
-void trusted_shash_release(void)
-{
-	if (hashalg)
-		crypto_free_shash(hashalg);
-	if (hmacalg)
-		crypto_free_shash(hmacalg);
-}
-EXPORT_SYMBOL_GPL(trusted_shash_release);
-
-int trusted_shash_alloc(void)
+/**
+ * tpm_library_use - Tell the TPM library we want to make use of it
+ *
+ * Tell the TPM library that we want to make use of it, allowing it to
+ * allocate the resources it needs.
+ */
+int tpm_library_use(void)
 {
+	struct crypto_shash *hashalg = NULL;
+	struct crypto_shash *hmacalg = NULL;
 	int ret;
 
-	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
+	if (atomic_inc_not_zero(&tpm_library_usage))
+		return 0;
+
+	/* We don't want to hold a mutex whilst allocating a crypto
+	 * object as it may have to call up to userspace.
+	 */
+	hmacalg = crypto_alloc_shash(tpm_hmac_alg, 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(hmacalg)) {
-		pr_info("trusted_key: could not allocate crypto %s\n",
-			hmac_alg);
-		return PTR_ERR(hmacalg);
+		pr_info("Could not allocate crypto %s\n", tpm_hmac_alg);
+		ret = PTR_ERR(hmacalg);
+		goto hmacalg_fail;
 	}
 
-	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
+	hashalg = crypto_alloc_shash(tpm_hash_alg, 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(hashalg)) {
-		pr_info("trusted_key: could not allocate crypto %s\n",
-			hash_alg);
+		pr_info("Could not allocate crypto %s\n", tpm_hash_alg);
 		ret = PTR_ERR(hashalg);
 		goto hashalg_fail;
 	}
 
+	mutex_lock(&tpm_library_init_mutex);
+
+	if (atomic_inc_return(&tpm_library_usage) == 1) {
+		tpm_hmacalg = hmacalg;
+		tpm_hashalg = hashalg;
+	} else {
+		crypto_free_shash(hashalg);
+		crypto_free_shash(hmacalg);
+	}
+
+	mutex_unlock(&tpm_library_init_mutex);
 	return 0;
 
 hashalg_fail:
-	crypto_free_shash(hmacalg);
+	crypto_free_shash(tpm_hmacalg);
+hmacalg_fail:
 	return ret;
 }
-EXPORT_SYMBOL_GPL(trusted_shash_alloc);
+EXPORT_SYMBOL_GPL(tpm_library_use);
+
+/**
+ * tpm_library_unuse - Tell the TPM library we've finished with it
+ *
+ * Tell the TPM library we've finished with it, allowing it to free the
+ * resources it had allocated.
+ */
+void tpm_library_unuse(void)
+{
+	if (atomic_add_unless(&tpm_library_usage, -1, 1))
+		return;
+
+	mutex_lock(&tpm_library_init_mutex);
+
+	if (atomic_dec_and_test(&tpm_library_usage)) {
+		crypto_free_shash(tpm_hashalg);
+		crypto_free_shash(tpm_hmacalg);
+	}
+
+	mutex_unlock(&tpm_library_init_mutex);
+}
+EXPORT_SYMBOL_GPL(tpm_library_unuse);
diff --git a/drivers/char/tpm/tpm-library.h b/drivers/char/tpm/tpm-library.h
index eec1dfe26c2a..6f7571cc6d6c 100644
--- a/drivers/char/tpm/tpm-library.h
+++ b/drivers/char/tpm/tpm-library.h
@@ -15,7 +15,7 @@
 #define LOAD32N(buffer, offset)	(*(uint32_t *)&buffer[offset])
 #define LOAD16(buffer, offset)	(ntohs(*(uint16_t *)&buffer[offset]))
 
-struct osapsess {
+struct tpm_osapsess {
 	uint32_t handle;
 	unsigned char secret[SHA1_DIGEST_SIZE];
 	unsigned char enonce[TPM_NONCE_SIZE];
@@ -51,14 +51,14 @@ static inline void storebytes(struct tpm_buf *buf, const unsigned char *in,
 #define TPM_DEBUG 0
 
 #ifdef TPM_DEBUG
-static inline void dump_sess(struct osapsess *s)
+static inline void dump_sess(struct tpm_osapsess *s)
 {
-	print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE,
+	print_hex_dump(KERN_INFO, "handle ", DUMP_PREFIX_NONE,
 		       16, 1, &s->handle, 4, 0);
-	pr_info("trusted-key: secret:\n");
+	pr_info("secret:\n");
 	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
 		       16, 1, &s->secret, SHA1_DIGEST_SIZE, 0);
-	pr_info("trusted-key: enonce:\n");
+	pr_info("enonce:\n");
 	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
 		       16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);
 }
@@ -67,13 +67,13 @@ static inline void dump_tpm_buf(unsigned char *buf)
 {
 	int len;
 
-	pr_info("\ntrusted-key: tpm buffer\n");
+	pr_info("\ntpm buffer\n");
 	len = LOAD32(buf, TPM_SIZE_OFFSET);
 	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
 }
 
 #else
-static inline void dump_sess(struct osapsess *s)
+static inline void dump_sess(struct tpm_osapsess *s)
 {
 }
 
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 5d8caf56c272..b08539920f76 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -100,8 +100,8 @@ struct tpm_buf {
 
 #define INIT_BUF(tb) (tb->len = 0)
 
-extern void trusted_shash_release(void);
-extern int trusted_shash_alloc(void);
+extern int tpm_library_use(void);
+extern void tpm_library_unuse(void);
 
 extern int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 		    uint32_t keyhandle, const unsigned char *keyauth,
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index 83c6a485e62a..3afb152a6ae2 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -521,19 +521,19 @@ static int __init init_trusted(void)
 {
 	int ret;
 
-	ret = trusted_shash_alloc();
+	ret = tpm_library_use();
 	if (ret < 0)
 		return ret;
 	ret = register_key_type(&key_type_trusted);
 	if (ret < 0)
-		trusted_shash_release();
+		tpm_library_unuse();
 	return ret;
 }
 
 static void __exit cleanup_trusted(void)
 {
-	trusted_shash_release();
 	unregister_key_type(&key_type_trusted);
+	tpm_library_unuse();
 }
 
 late_initcall(init_trusted);


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 10/23] TPMLIB: Better format calls to TSS_*hmac*()
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (8 preceding siblings ...)
  2018-08-21 15:57   ` [PATCH 09/23] TPMLIB: Do some source cleanups David Howells
@ 2018-08-21 15:57   ` David Howells
  2018-08-21 15:58   ` [PATCH 11/23] TPMLIB: Put banner comments on public TPM library functions David Howells
                     ` (13 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:57 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Better format calls to TSS_rawhmac(), TSS_authhmac() and TSS_checkhmac*().
Each of these calls takes a varargs list of pairs of datasize and data values.
Put each pair on its own line so that things are more obvious.

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

 drivers/char/tpm/tpm-library.c |   86 ++++++++++++++++++++++++++--------------
 1 file changed, 55 insertions(+), 31 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index e4cfc1f090e1..41fe4247a4c8 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -153,9 +153,12 @@ static int TSS_authhmac(unsigned char *digest, const unsigned char *key,
 	if (!ret)
 		ret = crypto_shash_final(&sdesc->shash, paramdigest);
 	if (!ret)
-		ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE,
-				  paramdigest, TPM_NONCE_SIZE, h1,
-				  TPM_NONCE_SIZE, h2, 1, &c, 0, 0);
+		ret = TSS_rawhmac(digest, key, keylen,
+				  SHA1_DIGEST_SIZE, paramdigest,
+				  TPM_NONCE_SIZE, h1,
+				  TPM_NONCE_SIZE, h2,
+				  1, &c,
+				  0, 0);
 out:
 	kfree(sdesc);
 	return ret;
@@ -229,9 +232,12 @@ static int TSS_checkhmac1(unsigned char *buffer,
 	if (ret < 0)
 		goto out;
 
-	ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest,
-			  TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce,
-			  1, continueflag, 0, 0);
+	ret = TSS_rawhmac(testhmac, key, keylen,
+			  SHA1_DIGEST_SIZE, paramdigest,
+			  TPM_NONCE_SIZE, enonce,
+			  TPM_NONCE_SIZE, ononce,
+			  1, continueflag,
+			  0, 0);
 	if (ret < 0)
 		goto out;
 
@@ -322,18 +328,24 @@ static int TSS_checkhmac2(unsigned char *buffer,
 	if (ret < 0)
 		goto out;
 
-	ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE,
-			  paramdigest, TPM_NONCE_SIZE, enonce1,
-			  TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0);
+	ret = TSS_rawhmac(testhmac1, key1, keylen1,
+			  SHA1_DIGEST_SIZE, paramdigest,
+			  TPM_NONCE_SIZE, enonce1,
+			  TPM_NONCE_SIZE, ononce,
+			  1, continueflag1,
+			  0, 0);
 	if (ret < 0)
 		goto out;
 	if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) {
 		ret = -EINVAL;
 		goto out;
 	}
-	ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE,
-			  paramdigest, TPM_NONCE_SIZE, enonce2,
-			  TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0);
+	ret = TSS_rawhmac(testhmac2, key2, keylen2,
+			  SHA1_DIGEST_SIZE, paramdigest,
+			  TPM_NONCE_SIZE, enonce2,
+			  TPM_NONCE_SIZE, ononce,
+			  1, continueflag2,
+			  0, 0);
 	if (ret < 0)
 		goto out;
 	if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE))
@@ -395,8 +407,10 @@ static int tpm_create_osap(struct tpm_chip *chip,
 	       TPM_NONCE_SIZE);
 	memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +
 				  TPM_NONCE_SIZE]), TPM_NONCE_SIZE);
-	return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE,
-			   enonce, TPM_NONCE_SIZE, ononce, 0, 0);
+	return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE,
+			   TPM_NONCE_SIZE, enonce,
+			   TPM_NONCE_SIZE, ononce,
+			   0, 0);
 }
 
 /*
@@ -488,18 +502,23 @@ int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 		/* no pcr info specified */
 		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
 				   sess.enonce, td->nonceodd, cont,
-				   sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,
-				   td->encauth, sizeof(uint32_t), &pcrsize,
-				   sizeof(uint32_t), &datsize, datalen, data, 0,
-				   0);
+				   sizeof(uint32_t), &ordinal,
+				   SHA1_DIGEST_SIZE, td->encauth,
+				   sizeof(uint32_t), &pcrsize,
+				   sizeof(uint32_t), &datsize,
+				   datalen, data,
+				   0, 0);
 	} else {
 		/* pcr info specified */
 		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
 				   sess.enonce, td->nonceodd, cont,
-				   sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,
-				   td->encauth, sizeof(uint32_t), &pcrsize,
-				   pcrinfosize, pcrinfo, sizeof(uint32_t),
-				   &datsize, datalen, data, 0, 0);
+				   sizeof(uint32_t), &ordinal,
+				   SHA1_DIGEST_SIZE, td->encauth,
+				   sizeof(uint32_t), &pcrsize,
+				   pcrinfosize, pcrinfo,
+				   sizeof(uint32_t), &datsize,
+				   datalen, data,
+				   0, 0);
 	}
 	if (ret < 0)
 		goto out;
@@ -533,9 +552,10 @@ int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 	    sizeof(uint32_t) + encdatasize;
 
 	/* check the HMAC in the response */
-	ret = TSS_checkhmac1(tb->data, ordinal, td->nonceodd, sess.secret,
-			     SHA1_DIGEST_SIZE, storedsize, TPM_DATA_OFFSET, 0,
-			     0);
+	ret = TSS_checkhmac1(tb->data, ordinal, td->nonceodd,
+			     sess.secret, SHA1_DIGEST_SIZE,
+			     storedsize, TPM_DATA_OFFSET,
+			     0, 0);
 
 	/* copy the returned blob to caller */
 	if (!ret) {
@@ -589,13 +609,17 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 		return ret;
 	}
 	ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,
-			   enonce1, nonceodd, cont, sizeof(uint32_t),
-			   &ordinal, bloblen, blob, 0, 0);
+			   enonce1, nonceodd, cont,
+			   sizeof(uint32_t), &ordinal,
+			   bloblen, blob,
+			   0, 0);
 	if (ret < 0)
 		return ret;
 	ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE,
-			   enonce2, nonceodd, cont, sizeof(uint32_t),
-			   &ordinal, bloblen, blob, 0, 0);
+			   enonce2, nonceodd, cont,
+			   sizeof(uint32_t), &ordinal,
+			   bloblen, blob,
+			   0, 0);
 	if (ret < 0)
 		return ret;
 
@@ -627,8 +651,8 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 			     keyauth, SHA1_DIGEST_SIZE,
 			     blobauth, SHA1_DIGEST_SIZE,
 			     sizeof(uint32_t), TPM_DATA_OFFSET,
-			     *datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0,
-			     0);
+			     *datalen, TPM_DATA_OFFSET + sizeof(uint32_t),
+			     0, 0);
 	if (ret < 0) {
 		pr_info("TSS_checkhmac2 failed (%d)\n", ret);
 		return ret;


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 11/23] TPMLIB: Put banner comments on public TPM library functions
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (9 preceding siblings ...)
  2018-08-21 15:57   ` [PATCH 10/23] TPMLIB: Better format calls to TSS_*hmac*() David Howells
@ 2018-08-21 15:58   ` David Howells
  2018-08-21 15:58   ` [PATCH 12/23] TPMLIB: Create tpm_{even, odd}_nonce structs to represent nonces David Howells
                     ` (12 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:58 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Put banner comments on public TPM library functions and, if necessary, rename
the arguments to make them more obvious.

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

 drivers/char/tpm/tpm-library.c |  126 ++++++++++++++++++++++++++++------------
 include/linux/tpm.h            |   19 ++++++
 2 files changed, 105 insertions(+), 40 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index 41fe4247a4c8..7d1f55413f02 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -66,8 +66,17 @@ static int TSS_sha1(const unsigned char *data, unsigned int datalen,
 	return ret;
 }
 
-static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,
-		       unsigned int keylen, ...)
+/**
+ * TSS_rawhmac - Generate a HMAC(SHA1) from raw data
+ * @digest: Result buffer - must be SHA1_DIGEST_SIZE in size
+ * @key: The key to use in the HMAC generation
+ * @keylen: The size of @key
+ * @...: Pairs of size and pointer of data elements to load into hmac
+ * @0,0: Terminator
+ */
+static int TSS_rawhmac(unsigned char *digest,
+		       const unsigned char *key, unsigned keylen,
+		       ...)
 {
 	struct tpm_sdesc *sdesc;
 	va_list argp;
@@ -110,7 +119,17 @@ out:
 	return ret;
 }
 
-/*
+/**
+ * TSS_authhmac - Calculate authorisation info to send to TPM
+ * @digest: Result buffer - must be SHA1_DIGEST_SIZE in size
+ * @key: The key to use in the HMAC generation
+ * @keylen: The size of @key
+ * @h1: Even nonce
+ * @h2: Odd nonce
+ * @h3: Continuation flag
+ * @...: Pairs of size and pointer of data elements to load into hash
+ * @0,0: Terminator
+ *
  * calculate authorization info fields to send to TPM
  */
 static int TSS_authhmac(unsigned char *digest, const unsigned char *key,
@@ -378,8 +397,8 @@ static int tpm_send_dump(struct tpm_chip *chip,
  */
 static int tpm_create_osap(struct tpm_chip *chip,
 			   struct tpm_buf *tb, struct tpm_osapsess *s,
-			   const unsigned char *key, uint16_t type,
-			   uint32_t handle)
+			   const unsigned char *keyauth,
+			   enum tpm_entity_type keytype, uint32_t keyhandle)
 {
 	unsigned char enonce[TPM_NONCE_SIZE];
 	unsigned char ononce[TPM_NONCE_SIZE];
@@ -393,8 +412,8 @@ static int tpm_create_osap(struct tpm_chip *chip,
 	store16(tb, TPM_TAG_RQU_COMMAND);
 	store32(tb, TPM_OSAP_SIZE);
 	store32(tb, TPM_ORD_OSAP);
-	store16(tb, type);
-	store32(tb, handle);
+	store16(tb, keytype);
+	store32(tb, keyhandle);
 	storebytes(tb, ononce, TPM_NONCE_SIZE);
 
 	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
@@ -407,7 +426,7 @@ static int tpm_create_osap(struct tpm_chip *chip,
 	       TPM_NONCE_SIZE);
 	memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +
 				  TPM_NONCE_SIZE]), TPM_NONCE_SIZE);
-	return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE,
+	return TSS_rawhmac(s->secret, keyauth, SHA1_DIGEST_SIZE,
 			   TPM_NONCE_SIZE, enonce,
 			   TPM_NONCE_SIZE, ononce,
 			   0, 0);
@@ -444,15 +463,33 @@ struct tpm_digests {
 	unsigned char nonceodd[TPM_NONCE_SIZE];
 };
 
-/*
- * Have the TPM seal(encrypt) the trusted key, possibly based on
- * Platform Configuration Registers (PCRs). AUTH1 for sealing key.
+/**
+ * tpm_seal - Encrypt one key according to another plus PCR state
+ * @chip: The chip to use
+ * @tb: Large scratch buffer for I/O
+ * @keytype: Type of entity attached to @keyhandle
+ * @keyhandle: TPM-resident key used to encrypt
+ * @keyauth: 'Password' to use the key.
+ * @rawdata: Data to be encrypted
+ * @rawlen: Length of @rawdata
+ * @encbuffer: Buffer to hold the encrypted data (max SHA1_DIGEST_SIZE)
+ * @_enclen: Where to place the size of the encrypted data
+ * @encauth: 'Password' to use to encrypt authorisation key
+ * @pcrinfo: Information on PCR register values to seal to
+ * @pcrinfosize: size of @pcrinfo
+ *
+ * Have the TPM seal (encrypt) the data in the data buffer.  The encryption is
+ * based on a key already resident in the TPM and may also include the state of
+ * one or more Platform Configuration Registers (PCRs).
+ *
+ * AUTH1 is used for sealing key.
  */
-int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
+int tpm_seal(struct tpm_chip *chip,
+	     struct tpm_buf *tb, enum tpm_entity_type keytype,
 	     uint32_t keyhandle, const unsigned char *keyauth,
-	     const unsigned char *data, uint32_t datalen,
-	     unsigned char *blob, uint32_t *bloblen,
-	     const unsigned char *blobauth,
+	     const unsigned char *rawdata, uint32_t rawlen,
+	     unsigned char *encbuffer, uint32_t *_enclen,
+	     const unsigned char *encauth,
 	     const unsigned char *pcrinfo, uint32_t pcrinfosize)
 {
 	struct tpm_osapsess sess;
@@ -489,13 +526,13 @@ int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 	if (ret != TPM_NONCE_SIZE)
 		goto out;
 	ordinal = htonl(TPM_ORD_SEAL);
-	datsize = htonl(datalen);
+	datsize = htonl(rawlen);
 	pcrsize = htonl(pcrinfosize);
 	cont = 0;
 
 	/* encrypt data authorization key */
 	for (i = 0; i < SHA1_DIGEST_SIZE; ++i)
-		td->encauth[i] = td->xorhash[i] ^ blobauth[i];
+		td->encauth[i] = td->xorhash[i] ^ encauth[i];
 
 	/* calculate authorization HMAC value */
 	if (pcrinfosize == 0) {
@@ -506,7 +543,7 @@ int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 				   SHA1_DIGEST_SIZE, td->encauth,
 				   sizeof(uint32_t), &pcrsize,
 				   sizeof(uint32_t), &datsize,
-				   datalen, data,
+				   rawlen, rawdata,
 				   0, 0);
 	} else {
 		/* pcr info specified */
@@ -517,7 +554,7 @@ int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 				   sizeof(uint32_t), &pcrsize,
 				   pcrinfosize, pcrinfo,
 				   sizeof(uint32_t), &datsize,
-				   datalen, data,
+				   rawlen, rawdata,
 				   0, 0);
 	}
 	if (ret < 0)
@@ -526,14 +563,14 @@ int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 	/* build and send the TPM request packet */
 	INIT_BUF(tb);
 	store16(tb, TPM_TAG_RQU_AUTH1_COMMAND);
-	store32(tb, TPM_SEAL_SIZE + pcrinfosize + datalen);
+	store32(tb, TPM_SEAL_SIZE + pcrinfosize + rawlen);
 	store32(tb, TPM_ORD_SEAL);
 	store32(tb, keyhandle);
 	storebytes(tb, td->encauth, SHA1_DIGEST_SIZE);
 	store32(tb, pcrinfosize);
 	storebytes(tb, pcrinfo, pcrinfosize);
-	store32(tb, datalen);
-	storebytes(tb, data, datalen);
+	store32(tb, rawlen);
+	storebytes(tb, rawdata, rawlen);
 	store32(tb, sess.handle);
 	storebytes(tb, td->nonceodd, TPM_NONCE_SIZE);
 	store8(tb, cont);
@@ -544,7 +581,7 @@ int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 	if (ret < 0)
 		goto out;
 
-	/* calculate the size of the returned Blob */
+	/* calculate the size of the returned encrypted data */
 	sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t));
 	encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t) +
 			     sizeof(uint32_t) + sealinfosize);
@@ -557,10 +594,10 @@ int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
 			     storedsize, TPM_DATA_OFFSET,
 			     0, 0);
 
-	/* copy the returned blob to caller */
+	/* copy the encrypted data to caller's buffer */
 	if (!ret) {
-		memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize);
-		*bloblen = storedsize;
+		memcpy(encbuffer, tb->data + TPM_DATA_OFFSET, storedsize);
+		*_enclen = storedsize;
 	}
 out:
 	kfree(td);
@@ -568,14 +605,25 @@ out:
 }
 EXPORT_SYMBOL_GPL(tpm_seal);
 
-/*
+/**
+ * tpm_unseal - Encrypt one key according to another plus PCR state
+ * @chip: The chip to use
+ * @tb: Large scratch buffer for I/O
+ * @keyhandle: TPM-resident key used to decrypt
+ * @keyauth: HMAC key
+ * @encdata: Data to be decrypted
+ * @enclen: Length of @encdata
+ * @decauth: Data to use to decrypt the authorisation key
+ * @rawbuffer: Buffer to hold the decrypted data (max SHA1_DIGEST_SIZE)
+ * @_rawlen: Where to place the size of the decrypted data
+ *
  * use the AUTH2_COMMAND form of unseal, to authorize both key and blob
  */
 int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	       uint32_t keyhandle, const unsigned char *keyauth,
-	       const unsigned char *blob, int bloblen,
-	       const unsigned char *blobauth,
-	       unsigned char *data, unsigned int *datalen)
+	       const unsigned char *encdata, int enclen,
+	       const unsigned char *decauth,
+	       unsigned char *rawbuffer, unsigned int *_rawlen)
 {
 	unsigned char nonceodd[TPM_NONCE_SIZE];
 	unsigned char enonce1[TPM_NONCE_SIZE];
@@ -611,14 +659,14 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,
 			   enonce1, nonceodd, cont,
 			   sizeof(uint32_t), &ordinal,
-			   bloblen, blob,
+			   enclen, encdata,
 			   0, 0);
 	if (ret < 0)
 		return ret;
-	ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE,
+	ret = TSS_authhmac(authdata2, decauth, TPM_NONCE_SIZE,
 			   enonce2, nonceodd, cont,
 			   sizeof(uint32_t), &ordinal,
-			   bloblen, blob,
+			   enclen, encdata,
 			   0, 0);
 	if (ret < 0)
 		return ret;
@@ -626,10 +674,10 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	/* build and send TPM request packet */
 	INIT_BUF(tb);
 	store16(tb, TPM_TAG_RQU_AUTH2_COMMAND);
-	store32(tb, TPM_UNSEAL_SIZE + bloblen);
+	store32(tb, TPM_UNSEAL_SIZE + enclen);
 	store32(tb, TPM_ORD_UNSEAL);
 	store32(tb, keyhandle);
-	storebytes(tb, blob, bloblen);
+	storebytes(tb, encdata, enclen);
 	store32(tb, authhandle1);
 	storebytes(tb, nonceodd, TPM_NONCE_SIZE);
 	store8(tb, cont);
@@ -646,18 +694,18 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 		return ret;
 	}
 
-	*datalen = LOAD32(tb->data, TPM_DATA_OFFSET);
+	*_rawlen = LOAD32(tb->data, TPM_DATA_OFFSET);
 	ret = TSS_checkhmac2(tb->data, ordinal, nonceodd,
 			     keyauth, SHA1_DIGEST_SIZE,
-			     blobauth, SHA1_DIGEST_SIZE,
+			     decauth, SHA1_DIGEST_SIZE,
 			     sizeof(uint32_t), TPM_DATA_OFFSET,
-			     *datalen, TPM_DATA_OFFSET + sizeof(uint32_t),
+			     *_rawlen, TPM_DATA_OFFSET + sizeof(uint32_t),
 			     0, 0);
 	if (ret < 0) {
 		pr_info("TSS_checkhmac2 failed (%d)\n", ret);
 		return ret;
 	}
-	memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen);
+	memcpy(rawbuffer, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *_rawlen);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(tpm_unseal);
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index b08539920f76..cbd13e03a869 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -93,6 +93,22 @@ static inline int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max) {
 #define TPM_RETURN_OFFSET		6
 #define TPM_DATA_OFFSET			10
 
+enum tpm_entity_type {
+	TPM_ET_KEYHANDLE		= 0x01,
+	TPM_ET_OWNER			= 0x02,
+	TPM_ET_DATA			= 0x03,
+	TPM_ET_SRK			= 0x04,
+	TPM_ET_KEY			= 0x05,
+	TPM_ET_REVOKE			= 0x06,
+	TPM_ET_DEL_OWNER_BLOB		= 0x07,
+	TPM_ET_DEL_ROW			= 0x08,
+	TPM_ET_DEL_KEY_BLOB		= 0x09,
+	TPM_ET_COUNTER			= 0x0a,
+	TPM_ET_NV			= 0x0b,
+	TPM_ET_OPERATOR			= 0x0c,
+	TPM_ET_RESERVED_HANDLE		= 0x40,
+};
+
 struct tpm_buf {
 	int len;
 	unsigned char data[MAX_BUF_SIZE];
@@ -103,7 +119,8 @@ struct tpm_buf {
 extern int tpm_library_use(void);
 extern void tpm_library_unuse(void);
 
-extern int tpm_seal(struct tpm_chip *chip, struct tpm_buf *tb, uint16_t keytype,
+extern int tpm_seal(struct tpm_chip *chip,
+		    struct tpm_buf *tb, enum tpm_entity_type keytype,
 		    uint32_t keyhandle, const unsigned char *keyauth,
 		    const unsigned char *data, uint32_t datalen,
 		    unsigned char *blob, uint32_t *bloblen,


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 12/23] TPMLIB: Create tpm_{even, odd}_nonce structs to represent nonces
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (10 preceding siblings ...)
  2018-08-21 15:58   ` [PATCH 11/23] TPMLIB: Put banner comments on public TPM library functions David Howells
@ 2018-08-21 15:58   ` David Howells
  2018-08-21 15:58   ` [PATCH 13/23] TPMLIB: Rename store8() and storebytes() David Howells
                     ` (11 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:58 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Create a tpm_even_nonce struct and a tpm_odd_nonce struct to represent nonces
in internal routines rather than directly using char arrays.  Having two
separate structures helps keep track of which nonce is used where.

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

 drivers/char/tpm/tpm-library.c |  151 +++++++++++++++++++++-------------------
 drivers/char/tpm/tpm-library.h |   10 ++-
 2 files changed, 90 insertions(+), 71 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index 7d1f55413f02..1c64282d1d0d 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -35,6 +35,19 @@ static atomic_t tpm_library_usage;
 static struct crypto_shash *tpm_hashalg;
 static struct crypto_shash *tpm_hmacalg;
 
+static int tpm_gen_odd_nonce(struct tpm_chip *chip,
+			     struct tpm_odd_nonce *ononce)
+{
+	int ret;
+
+	ret = tpm_get_random(chip, ononce->data, TPM_NONCE_SIZE);
+	if (ret == TPM_NONCE_SIZE)
+		ret = 0;
+	else
+		pr_info("tpm_get_random failed (%d)\n", ret);
+	return ret;
+}
+
 static struct tpm_sdesc *tpm_init_sdesc(struct crypto_shash *alg)
 {
 	struct tpm_sdesc *sdesc;
@@ -124,23 +137,25 @@ out:
  * @digest: Result buffer - must be SHA1_DIGEST_SIZE in size
  * @key: The key to use in the HMAC generation
  * @keylen: The size of @key
- * @h1: Even nonce
- * @h2: Odd nonce
- * @h3: Continuation flag
+ * @enonce: Even nonce
+ * @ononce: Odd nonce
+ * @cont: Continuation flag
  * @...: Pairs of size and pointer of data elements to load into hash
  * @0,0: Terminator
  *
  * calculate authorization info fields to send to TPM
  */
-static int TSS_authhmac(unsigned char *digest, const unsigned char *key,
-			unsigned int keylen, unsigned char *h1,
-			unsigned char *h2, unsigned char h3, ...)
+static int TSS_authhmac(unsigned char *digest,
+			const unsigned char *key, unsigned keylen,
+			const struct tpm_even_nonce *enonce,
+			const struct tpm_odd_nonce *ononce,
+			unsigned char cont,
+			...)
 {
 	unsigned char paramdigest[SHA1_DIGEST_SIZE];
 	struct tpm_sdesc *sdesc;
 	unsigned int dlen;
 	unsigned char *data;
-	unsigned char c;
 	int ret;
 	va_list argp;
 
@@ -150,11 +165,10 @@ static int TSS_authhmac(unsigned char *digest, const unsigned char *key,
 		return PTR_ERR(sdesc);
 	}
 
-	c = h3;
 	ret = crypto_shash_init(&sdesc->shash);
 	if (ret < 0)
 		goto out;
-	va_start(argp, h3);
+	va_start(argp, cont);
 	for (;;) {
 		dlen = va_arg(argp, unsigned int);
 		if (dlen == 0)
@@ -174,9 +188,9 @@ static int TSS_authhmac(unsigned char *digest, const unsigned char *key,
 	if (!ret)
 		ret = TSS_rawhmac(digest, key, keylen,
 				  SHA1_DIGEST_SIZE, paramdigest,
-				  TPM_NONCE_SIZE, h1,
-				  TPM_NONCE_SIZE, h2,
-				  1, &c,
+				  TPM_NONCE_SIZE, enonce->data,
+				  TPM_NONCE_SIZE, ononce->data,
+				  1, &cont,
 				  0, 0);
 out:
 	kfree(sdesc);
@@ -188,15 +202,15 @@ out:
  */
 static int TSS_checkhmac1(unsigned char *buffer,
 			  const uint32_t command,
-			  const unsigned char *ononce,
-			  const unsigned char *key,
-			  unsigned int keylen, ...)
+			  const struct tpm_odd_nonce *ononce,
+			  const unsigned char *key, unsigned keylen,
+			  ...)
 {
 	uint32_t bufsize;
 	uint16_t tag;
 	uint32_t ordinal;
 	uint32_t result;
-	unsigned char *enonce;
+	struct tpm_even_nonce *enonce;
 	unsigned char *continueflag;
 	unsigned char *authdata;
 	unsigned char testhmac[SHA1_DIGEST_SIZE];
@@ -217,7 +231,7 @@ static int TSS_checkhmac1(unsigned char *buffer,
 		return -EINVAL;
 	authdata = buffer + bufsize - SHA1_DIGEST_SIZE;
 	continueflag = authdata - 1;
-	enonce = continueflag - TPM_NONCE_SIZE;
+	enonce = (void *)continueflag - TPM_NONCE_SIZE;
 
 	sdesc = tpm_init_sdesc(tpm_hashalg);
 	if (IS_ERR(sdesc)) {
@@ -253,8 +267,8 @@ static int TSS_checkhmac1(unsigned char *buffer,
 
 	ret = TSS_rawhmac(testhmac, key, keylen,
 			  SHA1_DIGEST_SIZE, paramdigest,
-			  TPM_NONCE_SIZE, enonce,
-			  TPM_NONCE_SIZE, ononce,
+			  TPM_NONCE_SIZE, enonce->data,
+			  TPM_NONCE_SIZE, ononce->data,
 			  1, continueflag,
 			  0, 0);
 	if (ret < 0)
@@ -270,24 +284,23 @@ out:
 /*
  * verify the AUTH2_COMMAND (unseal) result from TPM
  */
-static int TSS_checkhmac2(unsigned char *buffer,
+static int TSS_checkhmac2(const unsigned char *buffer,
 			  const uint32_t command,
-			  const unsigned char *ononce,
-			  const unsigned char *key1,
-			  unsigned int keylen1,
-			  const unsigned char *key2,
-			  unsigned int keylen2, ...)
+			  const struct tpm_odd_nonce *ononce,
+			  const unsigned char *key1, unsigned keylen1,
+			  const unsigned char *key2, unsigned keylen2,
+			  ...)
 {
 	uint32_t bufsize;
 	uint16_t tag;
 	uint32_t ordinal;
 	uint32_t result;
-	unsigned char *enonce1;
-	unsigned char *continueflag1;
-	unsigned char *authdata1;
-	unsigned char *enonce2;
-	unsigned char *continueflag2;
-	unsigned char *authdata2;
+	const struct tpm_even_nonce *enonce1;
+	const unsigned char *continueflag1;
+	const unsigned char *authdata1;
+	const struct tpm_even_nonce *enonce2;
+	const unsigned char *continueflag2;
+	const unsigned char *authdata2;
 	unsigned char testhmac1[SHA1_DIGEST_SIZE];
 	unsigned char testhmac2[SHA1_DIGEST_SIZE];
 	unsigned char paramdigest[SHA1_DIGEST_SIZE];
@@ -311,8 +324,8 @@ static int TSS_checkhmac2(unsigned char *buffer,
 	authdata2 = buffer + bufsize - (SHA1_DIGEST_SIZE);
 	continueflag1 = authdata1 - 1;
 	continueflag2 = authdata2 - 1;
-	enonce1 = continueflag1 - TPM_NONCE_SIZE;
-	enonce2 = continueflag2 - TPM_NONCE_SIZE;
+	enonce1 = (const void *)continueflag1 - TPM_NONCE_SIZE;
+	enonce2 = (const void *)continueflag2 - TPM_NONCE_SIZE;
 
 	sdesc = tpm_init_sdesc(tpm_hashalg);
 	if (IS_ERR(sdesc)) {
@@ -349,8 +362,8 @@ static int TSS_checkhmac2(unsigned char *buffer,
 
 	ret = TSS_rawhmac(testhmac1, key1, keylen1,
 			  SHA1_DIGEST_SIZE, paramdigest,
-			  TPM_NONCE_SIZE, enonce1,
-			  TPM_NONCE_SIZE, ononce,
+			  TPM_NONCE_SIZE, enonce1->data,
+			  TPM_NONCE_SIZE, ononce->data,
 			  1, continueflag1,
 			  0, 0);
 	if (ret < 0)
@@ -361,8 +374,8 @@ static int TSS_checkhmac2(unsigned char *buffer,
 	}
 	ret = TSS_rawhmac(testhmac2, key2, keylen2,
 			  SHA1_DIGEST_SIZE, paramdigest,
-			  TPM_NONCE_SIZE, enonce2,
-			  TPM_NONCE_SIZE, ononce,
+			  TPM_NONCE_SIZE, enonce2->data,
+			  TPM_NONCE_SIZE, ononce->data,
 			  1, continueflag2,
 			  0, 0);
 	if (ret < 0)
@@ -400,12 +413,12 @@ static int tpm_create_osap(struct tpm_chip *chip,
 			   const unsigned char *keyauth,
 			   enum tpm_entity_type keytype, uint32_t keyhandle)
 {
-	unsigned char enonce[TPM_NONCE_SIZE];
-	unsigned char ononce[TPM_NONCE_SIZE];
+	struct tpm_even_nonce enonce;
+	struct tpm_odd_nonce ononce;
 	int ret;
 
-	ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE);
-	if (ret != TPM_NONCE_SIZE)
+	ret = tpm_gen_odd_nonce(chip, &ononce);
+	if (ret < 0)
 		return ret;
 
 	INIT_BUF(tb);
@@ -414,7 +427,7 @@ static int tpm_create_osap(struct tpm_chip *chip,
 	store32(tb, TPM_ORD_OSAP);
 	store16(tb, keytype);
 	store32(tb, keyhandle);
-	storebytes(tb, ononce, TPM_NONCE_SIZE);
+	storebytes(tb, ononce.data, TPM_NONCE_SIZE);
 
 	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
 			    "creating OSAP session");
@@ -422,13 +435,13 @@ static int tpm_create_osap(struct tpm_chip *chip,
 		return ret;
 
 	s->handle = LOAD32(tb->data, TPM_DATA_OFFSET);
-	memcpy(s->enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]),
+	memcpy(s->enonce.data, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]),
 	       TPM_NONCE_SIZE);
-	memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +
+	memcpy(enonce.data, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +
 				  TPM_NONCE_SIZE]), TPM_NONCE_SIZE);
 	return TSS_rawhmac(s->secret, keyauth, SHA1_DIGEST_SIZE,
-			   TPM_NONCE_SIZE, enonce,
-			   TPM_NONCE_SIZE, ononce,
+			   TPM_NONCE_SIZE, enonce.data,
+			   TPM_NONCE_SIZE, ononce.data,
 			   0, 0);
 }
 
@@ -436,7 +449,7 @@ static int tpm_create_osap(struct tpm_chip *chip,
  * Create an object independent authorisation protocol (oiap) session
  */
 static int tpm_create_oiap(struct tpm_chip *chip, struct tpm_buf *tb,
-			   uint32_t *handle, unsigned char *nonce)
+			   uint32_t *handle, struct tpm_even_nonce *enonce)
 {
 	int ret;
 
@@ -450,7 +463,7 @@ static int tpm_create_oiap(struct tpm_chip *chip, struct tpm_buf *tb,
 		return ret;
 
 	*handle = LOAD32(tb->data, TPM_DATA_OFFSET);
-	memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)],
+	memcpy(enonce->data, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)],
 	       TPM_NONCE_SIZE);
 	return 0;
 }
@@ -460,7 +473,7 @@ struct tpm_digests {
 	unsigned char pubauth[SHA1_DIGEST_SIZE];
 	unsigned char xorwork[SHA1_DIGEST_SIZE * 2];
 	unsigned char xorhash[SHA1_DIGEST_SIZE];
-	unsigned char nonceodd[TPM_NONCE_SIZE];
+	struct tpm_odd_nonce ononce;
 };
 
 /**
@@ -517,13 +530,13 @@ int tpm_seal(struct tpm_chip *chip,
 
 	/* calculate encrypted authorization value */
 	memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE);
-	memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE);
+	memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce.data, SHA1_DIGEST_SIZE);
 	ret = TSS_sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);
 	if (ret < 0)
 		goto out;
 
-	ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE);
-	if (ret != TPM_NONCE_SIZE)
+	ret = tpm_gen_odd_nonce(chip, &td->ononce);
+	if (ret < 0)
 		goto out;
 	ordinal = htonl(TPM_ORD_SEAL);
 	datsize = htonl(rawlen);
@@ -538,7 +551,7 @@ int tpm_seal(struct tpm_chip *chip,
 	if (pcrinfosize == 0) {
 		/* no pcr info specified */
 		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
-				   sess.enonce, td->nonceodd, cont,
+				   &sess.enonce, &td->ononce, cont,
 				   sizeof(uint32_t), &ordinal,
 				   SHA1_DIGEST_SIZE, td->encauth,
 				   sizeof(uint32_t), &pcrsize,
@@ -548,7 +561,7 @@ int tpm_seal(struct tpm_chip *chip,
 	} else {
 		/* pcr info specified */
 		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
-				   sess.enonce, td->nonceodd, cont,
+				   &sess.enonce, &td->ononce, cont,
 				   sizeof(uint32_t), &ordinal,
 				   SHA1_DIGEST_SIZE, td->encauth,
 				   sizeof(uint32_t), &pcrsize,
@@ -572,7 +585,7 @@ int tpm_seal(struct tpm_chip *chip,
 	store32(tb, rawlen);
 	storebytes(tb, rawdata, rawlen);
 	store32(tb, sess.handle);
-	storebytes(tb, td->nonceodd, TPM_NONCE_SIZE);
+	storebytes(tb, td->ononce.data, TPM_NONCE_SIZE);
 	store8(tb, cont);
 	storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE);
 
@@ -589,7 +602,7 @@ int tpm_seal(struct tpm_chip *chip,
 	    sizeof(uint32_t) + encdatasize;
 
 	/* check the HMAC in the response */
-	ret = TSS_checkhmac1(tb->data, ordinal, td->nonceodd,
+	ret = TSS_checkhmac1(tb->data, ordinal, &td->ononce,
 			     sess.secret, SHA1_DIGEST_SIZE,
 			     storedsize, TPM_DATA_OFFSET,
 			     0, 0);
@@ -625,9 +638,9 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	       const unsigned char *decauth,
 	       unsigned char *rawbuffer, unsigned int *_rawlen)
 {
-	unsigned char nonceodd[TPM_NONCE_SIZE];
-	unsigned char enonce1[TPM_NONCE_SIZE];
-	unsigned char enonce2[TPM_NONCE_SIZE];
+	struct tpm_odd_nonce ononce;
+	struct tpm_even_nonce enonce1;
+	struct tpm_even_nonce enonce2;
 	unsigned char authdata1[SHA1_DIGEST_SIZE];
 	unsigned char authdata2[SHA1_DIGEST_SIZE];
 	uint32_t authhandle1 = 0;
@@ -638,12 +651,12 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	int ret;
 
 	/* sessions for unsealing key and data */
-	ret = tpm_create_oiap(chip, tb, &authhandle1, enonce1);
+	ret = tpm_create_oiap(chip, tb, &authhandle1, &enonce1);
 	if (ret < 0) {
 		pr_info("Failed to create OIAP 1 (%d)\n", ret);
 		return ret;
 	}
-	ret = tpm_create_oiap(chip, tb, &authhandle2, enonce2);
+	ret = tpm_create_oiap(chip, tb, &authhandle2, &enonce2);
 	if (ret < 0) {
 		pr_info("Failed to create OIAP 2 (%d)\n", ret);
 		return ret;
@@ -651,20 +664,18 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 
 	ordinal = htonl(TPM_ORD_UNSEAL);
 	keyhndl = htonl(SRKHANDLE);
-	ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE);
-	if (ret != TPM_NONCE_SIZE) {
-		pr_info("tpm_get_random failed (%d)\n", ret);
+	ret = tpm_gen_odd_nonce(chip, &ononce);
+	if (ret < 0)
 		return ret;
-	}
 	ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,
-			   enonce1, nonceodd, cont,
+			   &enonce1, &ononce, cont,
 			   sizeof(uint32_t), &ordinal,
 			   enclen, encdata,
 			   0, 0);
 	if (ret < 0)
 		return ret;
 	ret = TSS_authhmac(authdata2, decauth, TPM_NONCE_SIZE,
-			   enonce2, nonceodd, cont,
+			   &enonce2, &ononce, cont,
 			   sizeof(uint32_t), &ordinal,
 			   enclen, encdata,
 			   0, 0);
@@ -679,11 +690,11 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	store32(tb, keyhandle);
 	storebytes(tb, encdata, enclen);
 	store32(tb, authhandle1);
-	storebytes(tb, nonceodd, TPM_NONCE_SIZE);
+	storebytes(tb, ononce.data, TPM_NONCE_SIZE);
 	store8(tb, cont);
 	storebytes(tb, authdata1, SHA1_DIGEST_SIZE);
 	store32(tb, authhandle2);
-	storebytes(tb, nonceodd, TPM_NONCE_SIZE);
+	storebytes(tb, ononce.data, TPM_NONCE_SIZE);
 	store8(tb, cont);
 	storebytes(tb, authdata2, SHA1_DIGEST_SIZE);
 
@@ -695,7 +706,7 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	}
 
 	*_rawlen = LOAD32(tb->data, TPM_DATA_OFFSET);
-	ret = TSS_checkhmac2(tb->data, ordinal, nonceodd,
+	ret = TSS_checkhmac2(tb->data, ordinal, &ononce,
 			     keyauth, SHA1_DIGEST_SIZE,
 			     decauth, SHA1_DIGEST_SIZE,
 			     sizeof(uint32_t), TPM_DATA_OFFSET,
diff --git a/drivers/char/tpm/tpm-library.h b/drivers/char/tpm/tpm-library.h
index 6f7571cc6d6c..ceb0ea1cd2bb 100644
--- a/drivers/char/tpm/tpm-library.h
+++ b/drivers/char/tpm/tpm-library.h
@@ -15,10 +15,18 @@
 #define LOAD32N(buffer, offset)	(*(uint32_t *)&buffer[offset])
 #define LOAD16(buffer, offset)	(ntohs(*(uint16_t *)&buffer[offset]))
 
+struct tpm_even_nonce {
+	unsigned char data[TPM_NONCE_SIZE];
+};
+
+struct tpm_odd_nonce {
+	unsigned char data[TPM_NONCE_SIZE];
+};
+
 struct tpm_osapsess {
 	uint32_t handle;
 	unsigned char secret[SHA1_DIGEST_SIZE];
-	unsigned char enonce[TPM_NONCE_SIZE];
+	struct tpm_even_nonce enonce;
 };
 
 static inline void store8(struct tpm_buf *buf, const unsigned char value)


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 13/23] TPMLIB: Rename store8() and storebytes()
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (11 preceding siblings ...)
  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   ` David Howells
  2018-08-21 15:58   ` [PATCH 14/23] TPMLIB: Make store_s() take a void* data argument, not unsigned char* David Howells
                     ` (10 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:58 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Rename store8() and storebytes() so that the names are the same length as for
store16() and store32() and their parameters line up, making blocks of them
easier to read.

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

 drivers/char/tpm/tpm-library.c |   28 ++++++++++++++--------------
 drivers/char/tpm/tpm-library.h |   14 +++++++-------
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index 1c64282d1d0d..1eea483cf36b 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -427,7 +427,7 @@ static int tpm_create_osap(struct tpm_chip *chip,
 	store32(tb, TPM_ORD_OSAP);
 	store16(tb, keytype);
 	store32(tb, keyhandle);
-	storebytes(tb, ononce.data, TPM_NONCE_SIZE);
+	store_s(tb, ononce.data, TPM_NONCE_SIZE);
 
 	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
 			    "creating OSAP session");
@@ -579,15 +579,15 @@ int tpm_seal(struct tpm_chip *chip,
 	store32(tb, TPM_SEAL_SIZE + pcrinfosize + rawlen);
 	store32(tb, TPM_ORD_SEAL);
 	store32(tb, keyhandle);
-	storebytes(tb, td->encauth, SHA1_DIGEST_SIZE);
+	store_s(tb, td->encauth, SHA1_DIGEST_SIZE);
 	store32(tb, pcrinfosize);
-	storebytes(tb, pcrinfo, pcrinfosize);
+	store_s(tb, pcrinfo, pcrinfosize);
 	store32(tb, rawlen);
-	storebytes(tb, rawdata, rawlen);
+	store_s(tb, rawdata, rawlen);
 	store32(tb, sess.handle);
-	storebytes(tb, td->ononce.data, TPM_NONCE_SIZE);
-	store8(tb, cont);
-	storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE);
+	store_s(tb, td->ononce.data, TPM_NONCE_SIZE);
+	store_8(tb, cont);
+	store_s(tb, td->pubauth, SHA1_DIGEST_SIZE);
 
 	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
 			    "sealing data");
@@ -688,15 +688,15 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	store32(tb, TPM_UNSEAL_SIZE + enclen);
 	store32(tb, TPM_ORD_UNSEAL);
 	store32(tb, keyhandle);
-	storebytes(tb, encdata, enclen);
+	store_s(tb, encdata, enclen);
 	store32(tb, authhandle1);
-	storebytes(tb, ononce.data, TPM_NONCE_SIZE);
-	store8(tb, cont);
-	storebytes(tb, authdata1, SHA1_DIGEST_SIZE);
+	store_s(tb, ononce.data, TPM_NONCE_SIZE);
+	store_8(tb, cont);
+	store_s(tb, authdata1, SHA1_DIGEST_SIZE);
 	store32(tb, authhandle2);
-	storebytes(tb, ononce.data, TPM_NONCE_SIZE);
-	store8(tb, cont);
-	storebytes(tb, authdata2, SHA1_DIGEST_SIZE);
+	store_s(tb, ononce.data, TPM_NONCE_SIZE);
+	store_8(tb, cont);
+	store_s(tb, authdata2, SHA1_DIGEST_SIZE);
 
 	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
 			    "unsealing data");
diff --git a/drivers/char/tpm/tpm-library.h b/drivers/char/tpm/tpm-library.h
index ceb0ea1cd2bb..c1af99dba08d 100644
--- a/drivers/char/tpm/tpm-library.h
+++ b/drivers/char/tpm/tpm-library.h
@@ -29,25 +29,25 @@ struct tpm_osapsess {
 	struct tpm_even_nonce enonce;
 };
 
-static inline void store8(struct tpm_buf *buf, const unsigned char value)
+static inline void store_8(struct tpm_buf *buf, unsigned char value)
 {
 	buf->data[buf->len++] = value;
 }
 
-static inline void store16(struct tpm_buf *buf, const uint16_t value)
+static inline void store16(struct tpm_buf *buf, uint16_t value)
 {
-	*(uint16_t *) & buf->data[buf->len] = htons(value);
+	*(uint16_t *)&buf->data[buf->len] = htons(value);
 	buf->len += sizeof value;
 }
 
-static inline void store32(struct tpm_buf *buf, const uint32_t value)
+static inline void store32(struct tpm_buf *buf, uint32_t value)
 {
-	*(uint32_t *) & buf->data[buf->len] = htonl(value);
+	*(uint32_t *)&buf->data[buf->len] = htonl(value);
 	buf->len += sizeof value;
 }
 
-static inline void storebytes(struct tpm_buf *buf, const unsigned char *in,
-			      const int len)
+static inline void store_s(struct tpm_buf *buf, const unsigned char *in,
+			   int len)
 {
 	memcpy(buf->data + buf->len, in, len);
 	buf->len += len;


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 14/23] TPMLIB: Make store_s() take a void* data argument, not unsigned char*
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (12 preceding siblings ...)
  2018-08-21 15:58   ` [PATCH 13/23] TPMLIB: Rename store8() and storebytes() David Howells
@ 2018-08-21 15:58   ` 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
                     ` (9 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:58 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Make store_s() (store arbitrarily-sized data) take a void* data argument, not
unsigned char* so that it can be given a pointer to a structure to be included
without the need to cast.

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

 drivers/char/tpm/tpm-library.h |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.h b/drivers/char/tpm/tpm-library.h
index c1af99dba08d..861e67df27fc 100644
--- a/drivers/char/tpm/tpm-library.h
+++ b/drivers/char/tpm/tpm-library.h
@@ -46,8 +46,7 @@ static inline void store32(struct tpm_buf *buf, uint32_t value)
 	buf->len += sizeof value;
 }
 
-static inline void store_s(struct tpm_buf *buf, const unsigned char *in,
-			   int len)
+static inline void store_s(struct tpm_buf *buf, const void *in, int len)
 {
 	memcpy(buf->data + buf->len, in, len);
 	buf->len += len;


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 15/23] TPMLIB: Use __be32 rather than int32_t and use cpu_to_beX() and co.
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (13 preceding siblings ...)
  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   ` David Howells
  2018-08-21 15:58   ` [PATCH 16/23] TPMLIB: Put more comments into the HMAC generation functions David Howells
                     ` (8 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:58 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Use __be32 rather than int32_t and use cpu_to_beX() and co. rather than
htonl() and co.

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

 drivers/char/tpm/tpm-library.c |   58 ++++++++++++++++++----------------------
 drivers/char/tpm/tpm-library.h |   14 +++++-----
 2 files changed, 33 insertions(+), 39 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index 1eea483cf36b..f14980be5ebb 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -201,15 +201,14 @@ out:
  * verify the AUTH1_COMMAND (Seal) result from TPM
  */
 static int TSS_checkhmac1(unsigned char *buffer,
-			  const uint32_t command,
+			  __be32 ordinal,
 			  const struct tpm_odd_nonce *ononce,
 			  const unsigned char *key, unsigned keylen,
 			  ...)
 {
 	uint32_t bufsize;
 	uint16_t tag;
-	uint32_t ordinal;
-	uint32_t result;
+	__be32 result;
 	struct tpm_even_nonce *enonce;
 	unsigned char *continueflag;
 	unsigned char *authdata;
@@ -223,8 +222,7 @@ static int TSS_checkhmac1(unsigned char *buffer,
 
 	bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
 	tag = LOAD16(buffer, 0);
-	ordinal = command;
-	result = LOAD32N(buffer, TPM_RETURN_OFFSET);
+	result = LOAD32BE(buffer, TPM_RETURN_OFFSET);
 	if (tag == TPM_TAG_RSP_COMMAND)
 		return 0;
 	if (tag != TPM_TAG_RSP_AUTH1_COMMAND)
@@ -246,7 +244,7 @@ static int TSS_checkhmac1(unsigned char *buffer,
 	if (ret < 0)
 		goto out;
 	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
-				  sizeof ordinal);
+				  sizeof(ordinal));
 	if (ret < 0)
 		goto out;
 	va_start(argp, keylen);
@@ -285,7 +283,7 @@ out:
  * verify the AUTH2_COMMAND (unseal) result from TPM
  */
 static int TSS_checkhmac2(const unsigned char *buffer,
-			  const uint32_t command,
+			  __be32 ordinal,
 			  const struct tpm_odd_nonce *ononce,
 			  const unsigned char *key1, unsigned keylen1,
 			  const unsigned char *key2, unsigned keylen2,
@@ -293,8 +291,7 @@ static int TSS_checkhmac2(const unsigned char *buffer,
 {
 	uint32_t bufsize;
 	uint16_t tag;
-	uint32_t ordinal;
-	uint32_t result;
+	__be32 result;
 	const struct tpm_even_nonce *enonce1;
 	const unsigned char *continueflag1;
 	const unsigned char *authdata1;
@@ -312,8 +309,7 @@ static int TSS_checkhmac2(const unsigned char *buffer,
 
 	bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
 	tag = LOAD16(buffer, 0);
-	ordinal = command;
-	result = LOAD32N(buffer, TPM_RETURN_OFFSET);
+	result = LOAD32BE(buffer, TPM_RETURN_OFFSET);
 
 	if (tag == TPM_TAG_RSP_COMMAND)
 		return 0;
@@ -336,11 +332,11 @@ static int TSS_checkhmac2(const unsigned char *buffer,
 	if (ret < 0)
 		goto out;
 	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,
-				  sizeof result);
+				  sizeof(result));
 	if (ret < 0)
 		goto out;
 	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
-				  sizeof ordinal);
+				  sizeof(ordinal));
 	if (ret < 0)
 		goto out;
 
@@ -508,9 +504,9 @@ int tpm_seal(struct tpm_chip *chip,
 	struct tpm_osapsess sess;
 	struct tpm_digests *td;
 	unsigned char cont;
-	uint32_t ordinal;
-	uint32_t pcrsize;
-	uint32_t datsize;
+	__be32 ordinal_be;
+	__be32 rawlen_be;
+	__be32 pcrinfosize_be;
 	int sealinfosize;
 	int encdatasize;
 	int storedsize;
@@ -538,9 +534,9 @@ int tpm_seal(struct tpm_chip *chip,
 	ret = tpm_gen_odd_nonce(chip, &td->ononce);
 	if (ret < 0)
 		goto out;
-	ordinal = htonl(TPM_ORD_SEAL);
-	datsize = htonl(rawlen);
-	pcrsize = htonl(pcrinfosize);
+	ordinal_be	= cpu_to_be32(TPM_ORD_SEAL);
+	rawlen_be	= cpu_to_be32(rawlen);
+	pcrinfosize_be	= cpu_to_be32(pcrinfosize);
 	cont = 0;
 
 	/* encrypt data authorization key */
@@ -552,21 +548,21 @@ int tpm_seal(struct tpm_chip *chip,
 		/* no pcr info specified */
 		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
 				   &sess.enonce, &td->ononce, cont,
-				   sizeof(uint32_t), &ordinal,
+				   sizeof(__be32), &ordinal_be,
 				   SHA1_DIGEST_SIZE, td->encauth,
-				   sizeof(uint32_t), &pcrsize,
-				   sizeof(uint32_t), &datsize,
+				   sizeof(__be32), &pcrinfosize_be,
+				   sizeof(__be32), &rawlen_be,
 				   rawlen, rawdata,
 				   0, 0);
 	} else {
 		/* pcr info specified */
 		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
 				   &sess.enonce, &td->ononce, cont,
-				   sizeof(uint32_t), &ordinal,
+				   sizeof(__be32), &ordinal_be,
 				   SHA1_DIGEST_SIZE, td->encauth,
-				   sizeof(uint32_t), &pcrsize,
+				   sizeof(__be32), &pcrinfosize_be,
 				   pcrinfosize, pcrinfo,
-				   sizeof(uint32_t), &datsize,
+				   sizeof(__be32), &rawlen_be,
 				   rawlen, rawdata,
 				   0, 0);
 	}
@@ -602,7 +598,7 @@ int tpm_seal(struct tpm_chip *chip,
 	    sizeof(uint32_t) + encdatasize;
 
 	/* check the HMAC in the response */
-	ret = TSS_checkhmac1(tb->data, ordinal, &td->ononce,
+	ret = TSS_checkhmac1(tb->data, ordinal_be, &td->ononce,
 			     sess.secret, SHA1_DIGEST_SIZE,
 			     storedsize, TPM_DATA_OFFSET,
 			     0, 0);
@@ -646,8 +642,7 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	uint32_t authhandle1 = 0;
 	uint32_t authhandle2 = 0;
 	unsigned char cont = 0;
-	uint32_t ordinal;
-	uint32_t keyhndl;
+	__be32 ordinal;
 	int ret;
 
 	/* sessions for unsealing key and data */
@@ -662,21 +657,20 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 		return ret;
 	}
 
-	ordinal = htonl(TPM_ORD_UNSEAL);
-	keyhndl = htonl(SRKHANDLE);
+	ordinal = cpu_to_be32(TPM_ORD_UNSEAL);
 	ret = tpm_gen_odd_nonce(chip, &ononce);
 	if (ret < 0)
 		return ret;
 	ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,
 			   &enonce1, &ononce, cont,
-			   sizeof(uint32_t), &ordinal,
+			   sizeof(__be32), &ordinal,
 			   enclen, encdata,
 			   0, 0);
 	if (ret < 0)
 		return ret;
 	ret = TSS_authhmac(authdata2, decauth, TPM_NONCE_SIZE,
 			   &enonce2, &ononce, cont,
-			   sizeof(uint32_t), &ordinal,
+			   sizeof(__be32), &ordinal,
 			   enclen, encdata,
 			   0, 0);
 	if (ret < 0)
diff --git a/drivers/char/tpm/tpm-library.h b/drivers/char/tpm/tpm-library.h
index 861e67df27fc..c12d451704a2 100644
--- a/drivers/char/tpm/tpm-library.h
+++ b/drivers/char/tpm/tpm-library.h
@@ -11,9 +11,9 @@
  */
 
 
-#define LOAD32(buffer, offset)	(ntohl(*(uint32_t *)&buffer[offset]))
-#define LOAD32N(buffer, offset)	(*(uint32_t *)&buffer[offset])
-#define LOAD16(buffer, offset)	(ntohs(*(uint16_t *)&buffer[offset]))
+#define LOAD32BE(buffer, offset) (*(__be32 *)&buffer[(offset)])
+#define LOAD16(buffer, offset)	(be16_to_cpu(*(__be16 *)&buffer[(offset)]))
+#define LOAD32(buffer, offset)	(be32_to_cpu(LOAD32BE(buffer, (offset))))
 
 struct tpm_even_nonce {
 	unsigned char data[TPM_NONCE_SIZE];
@@ -36,14 +36,14 @@ static inline void store_8(struct tpm_buf *buf, unsigned char value)
 
 static inline void store16(struct tpm_buf *buf, uint16_t value)
 {
-	*(uint16_t *)&buf->data[buf->len] = htons(value);
-	buf->len += sizeof value;
+	*(__be16 *)&buf->data[buf->len] = cpu_to_be16(value);
+	buf->len += sizeof(value);
 }
 
 static inline void store32(struct tpm_buf *buf, uint32_t value)
 {
-	*(uint32_t *)&buf->data[buf->len] = htonl(value);
-	buf->len += sizeof value;
+	*(__be32 *)&buf->data[buf->len] = cpu_to_be32(value);
+	buf->len += sizeof(value);
 }
 
 static inline void store_s(struct tpm_buf *buf, const void *in, int len)


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 16/23] TPMLIB: Put more comments into the HMAC generation functions
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (14 preceding siblings ...)
  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   ` David Howells
  2018-08-21 15:58   ` [PATCH 17/23] TPMLIB: Provide a wrapper to load bytes out of the reply David Howells
                     ` (7 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:58 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Put more comments into the HMAC generation functions in the TPM call library
so that it's easier to see how it relates to the request and response tables
in the documents.

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

 drivers/char/tpm/tpm-library.c |  161 +++++++++++++++++++++-------------------
 1 file changed, 83 insertions(+), 78 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index f14980be5ebb..46cd12d30ec6 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -85,7 +85,7 @@ static int TSS_sha1(const unsigned char *data, unsigned int datalen,
  * @key: The key to use in the HMAC generation
  * @keylen: The size of @key
  * @...: Pairs of size and pointer of data elements to load into hmac
- * @0,0: Terminator
+ * @0,NULL: Terminator
  */
 static int TSS_rawhmac(unsigned char *digest,
 		       const unsigned char *key, unsigned keylen,
@@ -113,13 +113,9 @@ static int TSS_rawhmac(unsigned char *digest,
 	va_start(argp, keylen);
 	for (;;) {
 		dlen = va_arg(argp, unsigned int);
-		if (dlen == 0)
-			break;
 		data = va_arg(argp, unsigned char *);
-		if (data == NULL) {
-			ret = -EINVAL;
+		if (!data)
 			break;
-		}
 		ret = crypto_shash_update(&sdesc->shash, data, dlen);
 		if (ret < 0)
 			break;
@@ -141,9 +137,9 @@ out:
  * @ononce: Odd nonce
  * @cont: Continuation flag
  * @...: Pairs of size and pointer of data elements to load into hash
- * @0,0: Terminator
+ * @0,NULL: Terminator
  *
- * calculate authorization info fields to send to TPM
+ * Calculate authorization info fields to send to TPM
  */
 static int TSS_authhmac(unsigned char *digest,
 			const unsigned char *key, unsigned keylen,
@@ -171,13 +167,9 @@ static int TSS_authhmac(unsigned char *digest,
 	va_start(argp, cont);
 	for (;;) {
 		dlen = va_arg(argp, unsigned int);
-		if (dlen == 0)
-			break;
 		data = va_arg(argp, unsigned char *);
-		if (!data) {
-			ret = -EINVAL;
+		if (!data)
 			break;
-		}
 		ret = crypto_shash_update(&sdesc->shash, data, dlen);
 		if (ret < 0)
 			break;
@@ -187,18 +179,25 @@ static int TSS_authhmac(unsigned char *digest,
 		ret = crypto_shash_final(&sdesc->shash, paramdigest);
 	if (!ret)
 		ret = TSS_rawhmac(digest, key, keylen,
-				  SHA1_DIGEST_SIZE, paramdigest,
-				  TPM_NONCE_SIZE, enonce->data,
-				  TPM_NONCE_SIZE, ononce->data,
-				  1, &cont,
-				  0, 0);
+				  /* 1H1 */ SHA1_DIGEST_SIZE, paramdigest,
+				  /* 2H1 */ TPM_NONCE_SIZE, enonce->data,
+				  /* 3H1 */ TPM_NONCE_SIZE, ononce->data,
+				  /* 4H1 */ 1, &cont,
+				  0, NULL);
 out:
 	kfree(sdesc);
 	return ret;
 }
 
-/*
- * verify the AUTH1_COMMAND (Seal) result from TPM
+/**
+ * TSS_checkhmac1 - Verify the result of an AUTH1_COMMAND (eg. Seal)
+ * @digest: Reply buffer
+ * @ordinal: The command ID, BE form
+ * @ononce: Odd nonce
+ * @key: The key to use in the HMAC generation
+ * @keylen: The size of @key
+ * @...: Pairs of size and pointer of data elements to load into hash
+ * @0,NULL: Terminator
  */
 static int TSS_checkhmac1(unsigned char *buffer,
 			  __be32 ordinal,
@@ -231,6 +230,9 @@ static int TSS_checkhmac1(unsigned char *buffer,
 	continueflag = authdata - 1;
 	enonce = (void *)continueflag - TPM_NONCE_SIZE;
 
+	/* Load the 1S, 2S, 3S, ... marked fields into a hash.  The digest
+	 * value is then 1H1 loaded into the HMAC below.
+	 */
 	sdesc = tpm_init_sdesc(tpm_hashalg);
 	if (IS_ERR(sdesc)) {
 		pr_info("Can't alloc %s\n", tpm_hash_alg);
@@ -240,19 +242,19 @@ static int TSS_checkhmac1(unsigned char *buffer,
 	if (ret < 0)
 		goto out;
 	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,
-				  sizeof result);
+				  sizeof(result)); /* 1S */
 	if (ret < 0)
 		goto out;
 	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
-				  sizeof(ordinal));
+				  sizeof(ordinal)); /* 2S */
 	if (ret < 0)
 		goto out;
 	va_start(argp, keylen);
 	for (;;) {
 		dlen = va_arg(argp, unsigned int);
-		if (dlen == 0)
-			break;
 		dpos = va_arg(argp, unsigned int);
+		if (!dlen && !dpos)
+			break;
 		ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
 		if (ret < 0)
 			break;
@@ -263,12 +265,13 @@ static int TSS_checkhmac1(unsigned char *buffer,
 	if (ret < 0)
 		goto out;
 
+	/* Generate the HMAC digest */
 	ret = TSS_rawhmac(testhmac, key, keylen,
-			  SHA1_DIGEST_SIZE, paramdigest,
-			  TPM_NONCE_SIZE, enonce->data,
-			  TPM_NONCE_SIZE, ononce->data,
-			  1, continueflag,
-			  0, 0);
+			  /* 1H1 */ SHA1_DIGEST_SIZE, paramdigest,
+			  /* 2H1 */ TPM_NONCE_SIZE, enonce->data,
+			  /* 3H1 */ TPM_NONCE_SIZE, ononce->data,
+			  /* 4H1 */ 1, continueflag,
+			  0, NULL);
 	if (ret < 0)
 		goto out;
 
@@ -279,7 +282,18 @@ out:
 	return ret;
 }
 
-/*
+/**
+ * TSS_checkhmac2 - Verify the result of an AUTH2_COMMAND (eg. Unseal)
+ * @digest: Reply buffer
+ * @ordinal: The command ID, BE form
+ * @ononce: Odd nonce
+ * @key1: The key to use in the authorisation session HMAC generation (nH1)
+ * @keylen1: The size of @key1
+ * @key2: The key to use in the data session HMAC generation (nH2)
+ * @keylen2: The size of @key2
+ * @...: Pairs of size and pointer of data elements to load into hash
+ * @0,NULL: Terminator
+ *
  * verify the AUTH2_COMMAND (unseal) result from TPM
  */
 static int TSS_checkhmac2(const unsigned char *buffer,
@@ -323,6 +337,9 @@ static int TSS_checkhmac2(const unsigned char *buffer,
 	enonce1 = (const void *)continueflag1 - TPM_NONCE_SIZE;
 	enonce2 = (const void *)continueflag2 - TPM_NONCE_SIZE;
 
+	/* Load the 1S, 2S, 3S, ... marked fields into a hash.  The digest
+	 * value is then 1H1 loaded into the HMAC below.
+	 */
 	sdesc = tpm_init_sdesc(tpm_hashalg);
 	if (IS_ERR(sdesc)) {
 		pr_info("Can't alloc %s\n", tpm_hash_alg);
@@ -332,20 +349,20 @@ static int TSS_checkhmac2(const unsigned char *buffer,
 	if (ret < 0)
 		goto out;
 	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,
-				  sizeof(result));
+				  sizeof(result)); /* 1S */
 	if (ret < 0)
 		goto out;
 	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
-				  sizeof(ordinal));
+				  sizeof(ordinal)); /* 2S */
 	if (ret < 0)
 		goto out;
 
 	va_start(argp, keylen2);
 	for (;;) {
 		dlen = va_arg(argp, unsigned int);
-		if (dlen == 0)
-			break;
 		dpos = va_arg(argp, unsigned int);
+		if (!dlen && !dpos)
+			break;
 		ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
 		if (ret < 0)
 			break;
@@ -357,11 +374,11 @@ static int TSS_checkhmac2(const unsigned char *buffer,
 		goto out;
 
 	ret = TSS_rawhmac(testhmac1, key1, keylen1,
-			  SHA1_DIGEST_SIZE, paramdigest,
-			  TPM_NONCE_SIZE, enonce1->data,
-			  TPM_NONCE_SIZE, ononce->data,
-			  1, continueflag1,
-			  0, 0);
+			  /* 1H1 */ SHA1_DIGEST_SIZE, paramdigest,
+			  /* 2H1 */ TPM_NONCE_SIZE, enonce1->data,
+			  /* 3H1 */ TPM_NONCE_SIZE, ononce->data,
+			  /* 4H1 */ 1, continueflag1,
+			  0, NULL);
 	if (ret < 0)
 		goto out;
 	if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) {
@@ -369,11 +386,11 @@ static int TSS_checkhmac2(const unsigned char *buffer,
 		goto out;
 	}
 	ret = TSS_rawhmac(testhmac2, key2, keylen2,
-			  SHA1_DIGEST_SIZE, paramdigest,
-			  TPM_NONCE_SIZE, enonce2->data,
-			  TPM_NONCE_SIZE, ononce->data,
-			  1, continueflag2,
-			  0, 0);
+			  /* 1H2 */ SHA1_DIGEST_SIZE, paramdigest,
+			  /* 2H2 */ TPM_NONCE_SIZE, enonce2->data,
+			  /* 3H2 */ TPM_NONCE_SIZE, ononce->data,
+			  /* 4H2 */ 1, continueflag2,
+			  0, NULL);
 	if (ret < 0)
 		goto out;
 	if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE))
@@ -438,7 +455,7 @@ static int tpm_create_osap(struct tpm_chip *chip,
 	return TSS_rawhmac(s->secret, keyauth, SHA1_DIGEST_SIZE,
 			   TPM_NONCE_SIZE, enonce.data,
 			   TPM_NONCE_SIZE, ononce.data,
-			   0, 0);
+			   0, NULL);
 }
 
 /*
@@ -484,7 +501,7 @@ struct tpm_digests {
  * @encbuffer: Buffer to hold the encrypted data (max SHA1_DIGEST_SIZE)
  * @_enclen: Where to place the size of the encrypted data
  * @encauth: 'Password' to use to encrypt authorisation key
- * @pcrinfo: Information on PCR register values to seal to
+ * @pcrinfo: Information on PCR register values to seal to (must not be NULL)
  * @pcrinfosize: size of @pcrinfo
  *
  * Have the TPM seal (encrypt) the data in the data buffer.  The encryption is
@@ -544,28 +561,16 @@ int tpm_seal(struct tpm_chip *chip,
 		td->encauth[i] = td->xorhash[i] ^ encauth[i];
 
 	/* calculate authorization HMAC value */
-	if (pcrinfosize == 0) {
-		/* no pcr info specified */
-		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
-				   &sess.enonce, &td->ononce, cont,
-				   sizeof(__be32), &ordinal_be,
-				   SHA1_DIGEST_SIZE, td->encauth,
-				   sizeof(__be32), &pcrinfosize_be,
-				   sizeof(__be32), &rawlen_be,
-				   rawlen, rawdata,
-				   0, 0);
-	} else {
-		/* pcr info specified */
-		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
-				   &sess.enonce, &td->ononce, cont,
-				   sizeof(__be32), &ordinal_be,
-				   SHA1_DIGEST_SIZE, td->encauth,
-				   sizeof(__be32), &pcrinfosize_be,
-				   pcrinfosize, pcrinfo,
-				   sizeof(__be32), &rawlen_be,
-				   rawlen, rawdata,
-				   0, 0);
-	}
+	BUG_ON(!pcrinfo);
+	ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
+			   &sess.enonce, &td->ononce, cont,
+			   /* 1S */ sizeof(__be32), &ordinal_be,
+			   /* 2S */ SHA1_DIGEST_SIZE, td->encauth,
+			   /* 3S */ sizeof(__be32), &pcrinfosize_be,
+			   /* 4S */ pcrinfosize, pcrinfo,
+			   /* 5S */ sizeof(__be32), &rawlen_be,
+			   /* 6S */ rawlen, rawdata,
+			   0, NULL);
 	if (ret < 0)
 		goto out;
 
@@ -600,8 +605,8 @@ int tpm_seal(struct tpm_chip *chip,
 	/* check the HMAC in the response */
 	ret = TSS_checkhmac1(tb->data, ordinal_be, &td->ononce,
 			     sess.secret, SHA1_DIGEST_SIZE,
-			     storedsize, TPM_DATA_OFFSET,
-			     0, 0);
+			     /* 3S */ storedsize, TPM_DATA_OFFSET,
+			     0, NULL);
 
 	/* copy the encrypted data to caller's buffer */
 	if (!ret) {
@@ -663,16 +668,16 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 		return ret;
 	ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,
 			   &enonce1, &ononce, cont,
-			   sizeof(__be32), &ordinal,
-			   enclen, encdata,
-			   0, 0);
+			   /* 1S */ sizeof(__be32), &ordinal,
+			   /* 2S */ enclen, encdata,
+			   0, NULL);
 	if (ret < 0)
 		return ret;
 	ret = TSS_authhmac(authdata2, decauth, TPM_NONCE_SIZE,
 			   &enonce2, &ononce, cont,
-			   sizeof(__be32), &ordinal,
-			   enclen, encdata,
-			   0, 0);
+			   /* 1S */ sizeof(__be32), &ordinal,
+			   /* 2S */ enclen, encdata,
+			   0, NULL);
 	if (ret < 0)
 		return ret;
 
@@ -703,8 +708,8 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	ret = TSS_checkhmac2(tb->data, ordinal, &ononce,
 			     keyauth, SHA1_DIGEST_SIZE,
 			     decauth, SHA1_DIGEST_SIZE,
-			     sizeof(uint32_t), TPM_DATA_OFFSET,
-			     *_rawlen, TPM_DATA_OFFSET + sizeof(uint32_t),
+			     /* 3S */ sizeof(uint32_t), TPM_DATA_OFFSET,
+			     /* 4S */ *_rawlen, TPM_DATA_OFFSET + sizeof(uint32_t),
 			     0, 0);
 	if (ret < 0) {
 		pr_info("TSS_checkhmac2 failed (%d)\n", ret);


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 17/23] TPMLIB: Provide a wrapper to load bytes out of the reply
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (15 preceding siblings ...)
  2018-08-21 15:58   ` [PATCH 16/23] TPMLIB: Put more comments into the HMAC generation functions David Howells
@ 2018-08-21 15:58   ` David Howells
  2018-08-21 15:58   ` [PATCH 18/23] TPMLIB: Encapsulate XOR-based encryption with authkey derivative David Howells
                     ` (6 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:58 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Provide a wrapper for memcpy to load bytes out of the reply, similar to
LOAD32() and friends.

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

 drivers/char/tpm/tpm-library.c |   87 ++++++++++++++++++++--------------------
 drivers/char/tpm/tpm-library.h |   43 +++++++++++++++++---
 include/linux/tpm.h            |    3 +
 3 files changed, 82 insertions(+), 51 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index 46cd12d30ec6..329b5c3f23a2 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -199,7 +199,7 @@ out:
  * @...: Pairs of size and pointer of data elements to load into hash
  * @0,NULL: Terminator
  */
-static int TSS_checkhmac1(unsigned char *buffer,
+static int TSS_checkhmac1(struct tpm_buf *tb,
 			  __be32 ordinal,
 			  const struct tpm_odd_nonce *ononce,
 			  const unsigned char *key, unsigned keylen,
@@ -219,14 +219,16 @@ static int TSS_checkhmac1(unsigned char *buffer,
 	va_list argp;
 	int ret;
 
-	bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
-	tag = LOAD16(buffer, 0);
-	result = LOAD32BE(buffer, TPM_RETURN_OFFSET);
+	SET_BUF_OFFSET(tb, 0);
+	tag = LOAD16(tb);
+	bufsize = LOAD32(tb);
+	result = LOAD32BE(tb);
 	if (tag == TPM_TAG_RSP_COMMAND)
 		return 0;
 	if (tag != TPM_TAG_RSP_AUTH1_COMMAND)
 		return -EINVAL;
-	authdata = buffer + bufsize - SHA1_DIGEST_SIZE;
+
+	authdata = tb->data + bufsize - SHA1_DIGEST_SIZE;
 	continueflag = authdata - 1;
 	enonce = (void *)continueflag - TPM_NONCE_SIZE;
 
@@ -255,7 +257,7 @@ static int TSS_checkhmac1(unsigned char *buffer,
 		dpos = va_arg(argp, unsigned int);
 		if (!dlen && !dpos)
 			break;
-		ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
+		ret = crypto_shash_update(&sdesc->shash, tb->data + dpos, dlen);
 		if (ret < 0)
 			break;
 	}
@@ -296,7 +298,7 @@ out:
  *
  * verify the AUTH2_COMMAND (unseal) result from TPM
  */
-static int TSS_checkhmac2(const unsigned char *buffer,
+static int TSS_checkhmac2(struct tpm_buf *tb,
 			  __be32 ordinal,
 			  const struct tpm_odd_nonce *ononce,
 			  const unsigned char *key1, unsigned keylen1,
@@ -321,17 +323,17 @@ static int TSS_checkhmac2(const unsigned char *buffer,
 	va_list argp;
 	int ret;
 
-	bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
-	tag = LOAD16(buffer, 0);
-	result = LOAD32BE(buffer, TPM_RETURN_OFFSET);
+	bufsize = LOAD32(tb);
+	tag = LOAD16(tb);
+	result = LOAD32BE(tb);
 
 	if (tag == TPM_TAG_RSP_COMMAND)
 		return 0;
 	if (tag != TPM_TAG_RSP_AUTH2_COMMAND)
 		return -EINVAL;
-	authdata1 = buffer + bufsize - (SHA1_DIGEST_SIZE + 1
+	authdata1 = tb->data + bufsize - (SHA1_DIGEST_SIZE + 1
 			+ SHA1_DIGEST_SIZE + SHA1_DIGEST_SIZE);
-	authdata2 = buffer + bufsize - (SHA1_DIGEST_SIZE);
+	authdata2 = tb->data + bufsize - (SHA1_DIGEST_SIZE);
 	continueflag1 = authdata1 - 1;
 	continueflag2 = authdata2 - 1;
 	enonce1 = (const void *)continueflag1 - TPM_NONCE_SIZE;
@@ -363,7 +365,7 @@ static int TSS_checkhmac2(const unsigned char *buffer,
 		dpos = va_arg(argp, unsigned int);
 		if (!dlen && !dpos)
 			break;
-		ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
+		ret = crypto_shash_update(&sdesc->shash, tb->data + dpos, dlen);
 		if (ret < 0)
 			break;
 	}
@@ -404,17 +406,19 @@ out:
  * For key specific tpm requests, we will generate and send our
  * own TPM command packets using the drivers send function.
  */
-static int tpm_send_dump(struct tpm_chip *chip,
-			 unsigned char *cmd, size_t buflen, const char *desc)
+static int tpm_send_dump(struct tpm_chip *chip, struct tpm_buf *cmd,
+			 const char *desc)
 {
 	int rc;
 
 	dump_tpm_buf(cmd);
-	rc = tpm_send_command(chip, cmd, buflen, desc);
+	rc = tpm_send_command(chip, cmd->data, MAX_BUF_SIZE, desc);
 	dump_tpm_buf(cmd);
 	if (rc > 0)
 		/* Can't return positive return codes values to keyctl */
 		rc = -EPERM;
+	else
+		SET_BUF_OFFSET(cmd, TPM_DATA_OFFSET);
 	return rc;
 }
 
@@ -442,16 +446,14 @@ static int tpm_create_osap(struct tpm_chip *chip,
 	store32(tb, keyhandle);
 	store_s(tb, ononce.data, TPM_NONCE_SIZE);
 
-	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
-			    "creating OSAP session");
+	ret = tpm_send_dump(chip, tb, "creating OSAP session");
 	if (ret < 0)
 		return ret;
 
-	s->handle = LOAD32(tb->data, TPM_DATA_OFFSET);
-	memcpy(s->enonce.data, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]),
-	       TPM_NONCE_SIZE);
-	memcpy(enonce.data, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +
-				  TPM_NONCE_SIZE]), TPM_NONCE_SIZE);
+	s->handle = LOAD32(tb);
+	LOAD_S(tb, s->enonce.data, TPM_NONCE_SIZE);
+	LOAD_S(tb, enonce.data, TPM_NONCE_SIZE);
+
 	return TSS_rawhmac(s->secret, keyauth, SHA1_DIGEST_SIZE,
 			   TPM_NONCE_SIZE, enonce.data,
 			   TPM_NONCE_SIZE, ononce.data,
@@ -470,14 +472,12 @@ static int tpm_create_oiap(struct tpm_chip *chip, struct tpm_buf *tb,
 	store16(tb, TPM_TAG_RQU_COMMAND);
 	store32(tb, TPM_OIAP_SIZE);
 	store32(tb, TPM_ORD_OIAP);
-	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
-			    "creating OIAP session");
+	ret = tpm_send_dump(chip, tb, "creating OIAP session");
 	if (ret < 0)
 		return ret;
 
-	*handle = LOAD32(tb->data, TPM_DATA_OFFSET);
-	memcpy(enonce->data, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)],
-	       TPM_NONCE_SIZE);
+	*handle = LOAD32(tb);
+	LOAD_S(tb, enonce->data, TPM_NONCE_SIZE);
 	return 0;
 }
 
@@ -590,27 +590,29 @@ int tpm_seal(struct tpm_chip *chip,
 	store_8(tb, cont);
 	store_s(tb, td->pubauth, SHA1_DIGEST_SIZE);
 
-	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
-			    "sealing data");
+	ret = tpm_send_dump(chip, tb, "sealing data");
 	if (ret < 0)
 		goto out;
 
-	/* calculate the size of the returned encrypted data */
-	sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t));
-	encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t) +
-			     sizeof(uint32_t) + sealinfosize);
-	storedsize = sizeof(uint32_t) + sizeof(uint32_t) + sealinfosize +
-	    sizeof(uint32_t) + encdatasize;
+	/* Look inside the TPM_STORED_DATA object to calculate the size of the
+	 * returned encrypted data.
+	 */
+	SET_BUF_OFFSET(tb, TPM_DATA_OFFSET + sizeof(uint32_t));
+	sealinfosize = LOAD32(tb);
+	SET_BUF_OFFSET(tb, TPM_DATA_OFFSET + sizeof(uint32_t) * 2 + sealinfosize);
+	storedsize = sizeof(uint32_t) * 2 + sealinfosize +
+		sizeof(uint32_t) + encdatasize;
 
 	/* check the HMAC in the response */
-	ret = TSS_checkhmac1(tb->data, ordinal_be, &td->ononce,
+	ret = TSS_checkhmac1(tb, ordinal_be, &td->ononce,
 			     sess.secret, SHA1_DIGEST_SIZE,
 			     /* 3S */ storedsize, TPM_DATA_OFFSET,
 			     0, NULL);
 
 	/* copy the encrypted data to caller's buffer */
 	if (!ret) {
-		memcpy(encbuffer, tb->data + TPM_DATA_OFFSET, storedsize);
+		SET_BUF_OFFSET(tb, TPM_DATA_OFFSET);
+		LOAD_S(tb, encbuffer, storedsize);
 		*_enclen = storedsize;
 	}
 out:
@@ -697,15 +699,14 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	store_8(tb, cont);
 	store_s(tb, authdata2, SHA1_DIGEST_SIZE);
 
-	ret = tpm_send_dump(chip, tb->data, MAX_BUF_SIZE,
-			    "unsealing data");
+	ret = tpm_send_dump(chip, tb, "unsealing data");
 	if (ret < 0) {
 		pr_info("authhmac failed (%d)\n", ret);
 		return ret;
 	}
 
-	*_rawlen = LOAD32(tb->data, TPM_DATA_OFFSET);
-	ret = TSS_checkhmac2(tb->data, ordinal, &ononce,
+	*_rawlen = LOAD32(tb);
+	ret = TSS_checkhmac2(tb, ordinal, &ononce,
 			     keyauth, SHA1_DIGEST_SIZE,
 			     decauth, SHA1_DIGEST_SIZE,
 			     /* 3S */ sizeof(uint32_t), TPM_DATA_OFFSET,
@@ -715,7 +716,7 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 		pr_info("TSS_checkhmac2 failed (%d)\n", ret);
 		return ret;
 	}
-	memcpy(rawbuffer, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *_rawlen);
+	LOAD_S(tb, rawbuffer, *_rawlen);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(tpm_unseal);
diff --git a/drivers/char/tpm/tpm-library.h b/drivers/char/tpm/tpm-library.h
index c12d451704a2..3e288624b8e8 100644
--- a/drivers/char/tpm/tpm-library.h
+++ b/drivers/char/tpm/tpm-library.h
@@ -11,10 +11,6 @@
  */
 
 
-#define LOAD32BE(buffer, offset) (*(__be32 *)&buffer[(offset)])
-#define LOAD16(buffer, offset)	(be16_to_cpu(*(__be16 *)&buffer[(offset)]))
-#define LOAD32(buffer, offset)	(be32_to_cpu(LOAD32BE(buffer, (offset))))
-
 struct tpm_even_nonce {
 	unsigned char data[TPM_NONCE_SIZE];
 };
@@ -29,6 +25,38 @@ struct tpm_osapsess {
 	struct tpm_even_nonce enonce;
 };
 
+static inline void SET_BUF_OFFSET(struct tpm_buf *buffer, unsigned offset)
+{
+	buffer->offset = offset;
+}
+
+static inline uint16_t LOAD16(struct tpm_buf *buffer)
+{
+	__be16 *p = (__be16 *)(buffer->data + buffer->offset);
+	buffer->offset += 2;
+	return be16_to_cpup(p);
+}
+
+static inline __be32 LOAD32BE(struct tpm_buf *buffer)
+{
+	__be32 val = *(__be32 *)(buffer->data + buffer->offset);
+	buffer->offset += 4;
+	return val;
+}
+
+static inline uint32_t LOAD32(struct tpm_buf *buffer)
+{
+	__be32 *p = (__be32 *)(buffer->data + buffer->offset);
+	buffer->offset += 4;
+	return be32_to_cpup(p);
+}
+
+static inline void LOAD_S(struct tpm_buf *buffer, void *data_buffer, size_t amount)
+{
+	memcpy(data_buffer, buffer->data + buffer->offset, amount);
+	buffer->offset += amount;
+}
+
 static inline void store_8(struct tpm_buf *buf, unsigned char value)
 {
 	buf->data[buf->len++] = value;
@@ -70,13 +98,14 @@ static inline void dump_sess(struct tpm_osapsess *s)
 		       16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);
 }
 
-static inline void dump_tpm_buf(unsigned char *buf)
+static inline void dump_tpm_buf(struct tpm_buf *tb)
 {
 	int len;
 
 	pr_info("\ntpm buffer\n");
-	len = LOAD32(buf, TPM_SIZE_OFFSET);
-	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
+	SET_BUF_OFFSET(tb, TPM_SIZE_OFFSET);
+	len = LOAD32(tb);
+	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, tb->data, len, 0);
 }
 
 #else
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index cbd13e03a869..398bfaef2325 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -110,7 +110,8 @@ enum tpm_entity_type {
 };
 
 struct tpm_buf {
-	int len;
+	unsigned short len;
+	unsigned short offset;
 	unsigned char data[MAX_BUF_SIZE];
 };
 


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 18/23] TPMLIB: Encapsulate XOR-based encryption with authkey derivative
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (16 preceding siblings ...)
  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   ` David Howells
  2018-08-21 15:58   ` [PATCH 19/23] TPMLIB: Add some debugging code David Howells
                     ` (5 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:58 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Encapsulate XOR-based encryption with a symmetric key derived from the authkey
so that it can be used in multiple functions.

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

 drivers/char/tpm/tpm-library.c |   42 +++++++++++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 9 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index 329b5c3f23a2..9234a2e7608f 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -489,6 +489,30 @@ struct tpm_digests {
 	struct tpm_odd_nonce ononce;
 };
 
+/*
+ * Calculate an XOR-based symmetric key that can be used to encrypt protected
+ * data.  The key is left in td->xorhash.
+ */
+static int tpm_calc_symmetric_authkey(struct tpm_digests *td,
+				      const u8 *secret,
+				      const struct tpm_even_nonce *enonce)
+{
+	memcpy(td->xorwork, secret, SHA1_DIGEST_SIZE);
+	memcpy(td->xorwork + SHA1_DIGEST_SIZE, enonce->data, SHA1_DIGEST_SIZE);
+	return TSS_sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);
+}
+
+/*
+ * Encrypt/decrypt data with a previously calculated XOR-based symmetric key.
+ */
+static void tpm_crypt_with_authkey(const struct tpm_digests *td,
+				   const u8 *data, u8 *buffer)
+{
+	int i;
+	for (i = 0; i < SHA1_DIGEST_SIZE; ++i)
+		buffer[i] = td->xorhash[i] ^ data[i];
+}
+
 /**
  * tpm_seal - Encrypt one key according to another plus PCR state
  * @chip: The chip to use
@@ -528,7 +552,6 @@ int tpm_seal(struct tpm_chip *chip,
 	int encdatasize;
 	int storedsize;
 	int ret;
-	int i;
 
 	/* alloc some work space for all the hashes */
 	td = kmalloc(sizeof *td, GFP_KERNEL);
@@ -541,13 +564,18 @@ int tpm_seal(struct tpm_chip *chip,
 		goto out;
 	dump_sess(&sess);
 
-	/* calculate encrypted authorization value */
-	memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE);
-	memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce.data, SHA1_DIGEST_SIZE);
-	ret = TSS_sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);
+	/* We need to pass a 'password' to the TPM with which it will encrypt
+	 * the sealed data before returning it.  So that the password doesn't
+	 * travel to the TPM in the clear, we generate a symmetric key from the
+	 * negotiated and encrypted session data and encrypt the password with
+	 * that.
+	 */
+	ret = tpm_calc_symmetric_authkey(td, sess.secret, &sess.enonce);
 	if (ret < 0)
 		goto out;
+	tpm_crypt_with_authkey(td, encauth, td->encauth);
 
+	/* Set up the parameters we will be sending */
 	ret = tpm_gen_odd_nonce(chip, &td->ononce);
 	if (ret < 0)
 		goto out;
@@ -556,10 +584,6 @@ int tpm_seal(struct tpm_chip *chip,
 	pcrinfosize_be	= cpu_to_be32(pcrinfosize);
 	cont = 0;
 
-	/* encrypt data authorization key */
-	for (i = 0; i < SHA1_DIGEST_SIZE; ++i)
-		td->encauth[i] = td->xorhash[i] ^ encauth[i];
-
 	/* calculate authorization HMAC value */
 	BUG_ON(!pcrinfo);
 	ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 19/23] TPMLIB: Add some debugging code
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (17 preceding siblings ...)
  2018-08-21 15:58   ` [PATCH 18/23] TPMLIB: Encapsulate XOR-based encryption with authkey derivative David Howells
@ 2018-08-21 15:58   ` David Howells
  2018-08-21 15:59   ` [PATCH 20/23] TPMLIB: Implement call to TPM_CreateWrapKey David Howells
                     ` (4 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:58 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Add some pr_devel() statements to make debugging easier.  They only exist
within the kernel if DEBUG is defined.

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

 drivers/char/tpm/tpm-library.c |   58 ++++++++++++++++++++++++++++------------
 1 file changed, 41 insertions(+), 17 deletions(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index 9234a2e7608f..0676165322a3 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -21,6 +21,8 @@
 #include <linux/tpm_command.h>
 
 #include "tpm-library.h"
+#define kenter(fmt, ...) pr_devel("==>%s("fmt")\n", __func__, ## __VA_ARGS__)
+#define kleave(fmt, ...) pr_devel("<==%s()"fmt"\n", __func__, ## __VA_ARGS__)
 
 static const char tpm_hmac_alg[] = "hmac(sha1)";
 static const char tpm_hash_alg[] = "sha1";
@@ -95,7 +97,7 @@ static int TSS_rawhmac(unsigned char *digest,
 	va_list argp;
 	unsigned int dlen;
 	unsigned char *data;
-	int ret;
+	int ret, s;
 
 	sdesc = tpm_init_sdesc(tpm_hmacalg);
 	if (IS_ERR(sdesc)) {
@@ -111,11 +113,12 @@ static int TSS_rawhmac(unsigned char *digest,
 		goto out;
 
 	va_start(argp, keylen);
-	for (;;) {
+	for (s = 1;; s++) {
 		dlen = va_arg(argp, unsigned int);
 		data = va_arg(argp, unsigned char *);
 		if (!data)
 			break;
+		pr_devel("RAWHMAC %dH1: [%u] %*phN\n", s, dlen, dlen, data);
 		ret = crypto_shash_update(&sdesc->shash, data, dlen);
 		if (ret < 0)
 			break;
@@ -152,7 +155,7 @@ static int TSS_authhmac(unsigned char *digest,
 	struct tpm_sdesc *sdesc;
 	unsigned int dlen;
 	unsigned char *data;
-	int ret;
+	int ret, s;
 	va_list argp;
 
 	sdesc = tpm_init_sdesc(tpm_hashalg);
@@ -165,11 +168,12 @@ static int TSS_authhmac(unsigned char *digest,
 	if (ret < 0)
 		goto out;
 	va_start(argp, cont);
-	for (;;) {
+	for (s = 1;; s++) {
 		dlen = va_arg(argp, unsigned int);
 		data = va_arg(argp, unsigned char *);
 		if (!data)
 			break;
+		pr_devel("AUTHHASH S%d: [%u] %*phN\n", s, dlen, dlen, data);
 		ret = crypto_shash_update(&sdesc->shash, data, dlen);
 		if (ret < 0)
 			break;
@@ -411,6 +415,9 @@ static int tpm_send_dump(struct tpm_chip *chip, struct tpm_buf *cmd,
 {
 	int rc;
 
+	kenter(",{%u,%u},%s",
+	       cmd->len, be32_to_cpu(*(__be32 *)(cmd->data + TPM_SIZE_OFFSET)), desc);
+
 	dump_tpm_buf(cmd);
 	rc = tpm_send_command(chip, cmd->data, MAX_BUF_SIZE, desc);
 	dump_tpm_buf(cmd);
@@ -419,6 +426,7 @@ static int tpm_send_dump(struct tpm_chip *chip, struct tpm_buf *cmd,
 		rc = -EPERM;
 	else
 		SET_BUF_OFFSET(cmd, TPM_DATA_OFFSET);
+	kleave(" = %d [%u]", rc, be32_to_cpu(*(__be32 *)(cmd->data + TPM_SIZE_OFFSET)));
 	return rc;
 }
 
@@ -434,6 +442,8 @@ static int tpm_create_osap(struct tpm_chip *chip,
 	struct tpm_odd_nonce ononce;
 	int ret;
 
+	kenter("");
+
 	ret = tpm_gen_odd_nonce(chip, &ononce);
 	if (ret < 0)
 		return ret;
@@ -448,16 +458,20 @@ static int tpm_create_osap(struct tpm_chip *chip,
 
 	ret = tpm_send_dump(chip, tb, "creating OSAP session");
 	if (ret < 0)
-		return ret;
+		goto out;
 
 	s->handle = LOAD32(tb);
 	LOAD_S(tb, s->enonce.data, TPM_NONCE_SIZE);
 	LOAD_S(tb, enonce.data, TPM_NONCE_SIZE);
 
-	return TSS_rawhmac(s->secret, keyauth, SHA1_DIGEST_SIZE,
-			   TPM_NONCE_SIZE, enonce.data,
-			   TPM_NONCE_SIZE, ononce.data,
-			   0, NULL);
+	/* Calculate the encrypted shared secret */
+	ret = TSS_rawhmac(s->secret, keyauth, SHA1_DIGEST_SIZE,
+			  TPM_NONCE_SIZE, enonce.data,
+			  TPM_NONCE_SIZE, ononce.data,
+			  0, NULL);
+out:
+	kleave(" = %d [%08x]", ret, s->handle);
+	return ret;
 }
 
 /*
@@ -468,6 +482,8 @@ static int tpm_create_oiap(struct tpm_chip *chip, struct tpm_buf *tb,
 {
 	int ret;
 
+	kenter("");
+
 	INIT_BUF(tb);
 	store16(tb, TPM_TAG_RQU_COMMAND);
 	store32(tb, TPM_OIAP_SIZE);
@@ -478,6 +494,7 @@ static int tpm_create_oiap(struct tpm_chip *chip, struct tpm_buf *tb,
 
 	*handle = LOAD32(tb);
 	LOAD_S(tb, enonce->data, TPM_NONCE_SIZE);
+	kleave(" = 0 [%08x]", *handle);
 	return 0;
 }
 
@@ -553,6 +570,8 @@ int tpm_seal(struct tpm_chip *chip,
 	int storedsize;
 	int ret;
 
+	kenter("");
+
 	/* alloc some work space for all the hashes */
 	td = kmalloc(sizeof *td, GFP_KERNEL);
 	if (!td)
@@ -641,6 +660,7 @@ int tpm_seal(struct tpm_chip *chip,
 	}
 out:
 	kfree(td);
+	kleave(" = %d", ret);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(tpm_seal);
@@ -676,36 +696,38 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	__be32 ordinal;
 	int ret;
 
+	kenter("");
+
 	/* sessions for unsealing key and data */
 	ret = tpm_create_oiap(chip, tb, &authhandle1, &enonce1);
 	if (ret < 0) {
 		pr_info("Failed to create OIAP 1 (%d)\n", ret);
-		return ret;
+		goto out;
 	}
 	ret = tpm_create_oiap(chip, tb, &authhandle2, &enonce2);
 	if (ret < 0) {
 		pr_info("Failed to create OIAP 2 (%d)\n", ret);
-		return ret;
+		goto out;
 	}
 
 	ordinal = cpu_to_be32(TPM_ORD_UNSEAL);
 	ret = tpm_gen_odd_nonce(chip, &ononce);
 	if (ret < 0)
-		return ret;
+		goto out;
 	ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,
 			   &enonce1, &ononce, cont,
 			   /* 1S */ sizeof(__be32), &ordinal,
 			   /* 2S */ enclen, encdata,
 			   0, NULL);
 	if (ret < 0)
-		return ret;
+		goto out;
 	ret = TSS_authhmac(authdata2, decauth, TPM_NONCE_SIZE,
 			   &enonce2, &ononce, cont,
 			   /* 1S */ sizeof(__be32), &ordinal,
 			   /* 2S */ enclen, encdata,
 			   0, NULL);
 	if (ret < 0)
-		return ret;
+		goto out;
 
 	/* build and send TPM request packet */
 	INIT_BUF(tb);
@@ -726,7 +748,7 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 	ret = tpm_send_dump(chip, tb, "unsealing data");
 	if (ret < 0) {
 		pr_info("authhmac failed (%d)\n", ret);
-		return ret;
+		goto out;
 	}
 
 	*_rawlen = LOAD32(tb);
@@ -738,10 +760,12 @@ int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 			     0, 0);
 	if (ret < 0) {
 		pr_info("TSS_checkhmac2 failed (%d)\n", ret);
-		return ret;
+		goto out;
 	}
 	LOAD_S(tb, rawbuffer, *_rawlen);
-	return 0;
+out:
+	kleave(" = %d", ret);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(tpm_unseal);
 


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 20/23] TPMLIB: Implement call to TPM_CreateWrapKey
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (18 preceding siblings ...)
  2018-08-21 15:58   ` [PATCH 19/23] TPMLIB: Add some debugging code David Howells
@ 2018-08-21 15:59   ` David Howells
  2018-08-21 15:59   ` [PATCH 21/23] TPMLIB: Implement call to TPM_LoadKey2 David Howells
                     ` (3 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:59 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Implement a function to invoke TPM_CreateWrapKey.

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

 drivers/char/tpm/tpm-library.c |  248 ++++++++++++++++++++++++++++++++++++++++
 include/linux/tpm.h            |   16 ++-
 include/linux/tpm_command.h    |    1 
 3 files changed, 264 insertions(+), 1 deletion(-)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index 0676165322a3..3413abeb3635 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -500,6 +500,7 @@ static int tpm_create_oiap(struct tpm_chip *chip, struct tpm_buf *tb,
 
 struct tpm_digests {
 	unsigned char encauth[SHA1_DIGEST_SIZE];
+	unsigned char encauth2[SHA1_DIGEST_SIZE];
 	unsigned char pubauth[SHA1_DIGEST_SIZE];
 	unsigned char xorwork[SHA1_DIGEST_SIZE * 2];
 	unsigned char xorhash[SHA1_DIGEST_SIZE];
@@ -769,6 +770,253 @@ out:
 }
 EXPORT_SYMBOL_GPL(tpm_unseal);
 
+enum tpm_key_usage {
+	TPM_KEY_SIGNING			= 0x0010,
+	TPM_KEY_STORAGE			= 0x0011,
+	TPM_KEY_IDENTITY		= 0x0012,
+	TPM_KEY_AUTHCHANGE		= 0x0013,
+	TPM_KEY_BIND			= 0x0014,
+	TPM_KEY_LEGACY			= 0x0015,
+	TPM_KEY_MIGRATE			= 0x0016,
+};
+
+enum tpm_algorithm_id {
+	TPM_ALG_RSA			= 0x00000001,
+	TPM_ALG_SHA			= 0x00000004,
+	TPM_ALG_HMAC			= 0x00000005,
+	TPM_ALG_AES128			= 0x00000006,
+	TPM_ALG_MGF1			= 0x00000007,
+	TPM_ALG_AES192			= 0x00000008,
+	TPM_ALG_AES256			= 0x00000009,
+	TPM_ALG_XOR			= 0x0000000a,
+};
+
+enum tpm_enc_scheme {
+	TPM_ES_NONE			= 0x0001,
+	TPM_ES_RSAESPKCSv15		= 0x0002,
+	TPM_ES_RSAESOAEP_SHA1_MGF1	= 0x0003,
+	TPM_ES_SYM_CTR			= 0x0004,
+	TPM_ES_SYM_OFB			= 0x0005,
+};
+
+enum tpm_sig_scheme {
+	TPM_SS_NONE			= 0x0001,
+	TPM_SS_RSAESPKCSv15_SHA1	= 0x0002,
+	TPM_SS_RSAESPKCSv15_DER		= 0x0003,
+	TPM_SS_RSAESPKCSv15_INFO	= 0x0004,
+};
+
+enum tpm_auth_data_usage {
+	TPM_AUTH_NEVER			= 0x00,
+	TPM_AUTH_ALWAYS			= 0x01,
+	TPM_NO_READ_PUBKEY_AUTH		= 0x03,
+};
+
+#define TPM_KEY_REDIRECTION		0x00000001
+#define TPM_KEY_MIGRATABLE		0x00000002
+#define TPM_KEY_ISVOLATILE		0x00000004
+#define TPM_KEY_PCRIGNOREDONREAD	0x00000008
+#define TPM_KEY_MIGRATEAUTHORITY	0x00000010
+
+struct tpm_key {
+	struct tpm_struct_ver {
+		u8	major, minor, rev_major, rev_minor;
+	} ver;
+	__be16		key_usage;		/* enum tpm_key_usage */
+	__be32		key_flags;
+	u8		auth_data_usage;	/* enum tpm_auth_data_usage */
+	struct tpm_key_parms {
+		__be32		algorithm_id;	/* enum tpm_algorithm_id */
+		__be16		enc_scheme;	/* enum tpm_enc_scheme */
+		__be16		sig_scheme;	/* enum tpm_sig_scheme */
+		__be32		parm_size;
+		struct tpm_rsa_key_parms {
+			__be32		key_length;
+			__be32		num_primes;
+			__be32		exponent_size;
+		} __packed rsa;
+	} __packed parms;
+	__be32		pcr_info_size;
+	struct tpm_store_pubkey {
+		__be32		key_length;
+		u8		key_data[0];
+	} __packed pub;
+	__be32		enc_data_size;
+	u8		enc_data[0];
+} __packed;
+
+/**
+ * tpm_create_wrap_key - Generate a new key and return it encrypted
+ * @chip: The chip to use
+ * @tb: Large scratch buffer for I/O
+ * @parent_type: Type of entity attached to @parent_handle
+ * @parent_handle: TPM-resident key used to encrypt
+ * @parent_auth: Parent authorisation HMAC key
+ * @usage_auth: Encrypted usage authdata for the key
+ * @migration_auth: Encrypted migration authdata for the key (or NULL)
+ * @_wrapped_key: Pointer to where to return the wrapped key (kmalloc'd)
+ *
+ * Have the TPM generate a new key and return it encrypted.  The encryption is
+ * based on a key already resident in the TPM and may also include the state of
+ * one or more Platform Configuration Registers (PCRs).
+ *
+ * AUTH1 is used for sealing key.
+ */
+int tpm_create_wrap_key(struct tpm_chip *chip,
+			enum tpm_entity_type parent_type,
+			uint32_t parent_handle,
+			const unsigned char *parent_auth,
+			const unsigned char *usage_auth,
+			const unsigned char *migration_auth,
+			struct tpm_wrapped_key **_wrapped_key)
+{
+	struct tpm_wrapped_key *wrapped_key;
+	struct tpm_osapsess sess;
+	struct tpm_digests *td;
+	struct tpm_buf *tb;
+	struct tpm_key *result;
+	unsigned char cont;
+	__be32 ordinal_be;
+	int key_size;
+	int ret;
+
+	struct tpm_key tpm_key = {
+		.ver			= { 0x01, 0x01, 0x00, 0x00 },
+		.key_usage		= cpu_to_be16(TPM_KEY_SIGNING),
+		.key_flags		= cpu_to_be32(0),
+		.auth_data_usage	= TPM_AUTH_ALWAYS,
+		.parms.algorithm_id	= cpu_to_be32(TPM_ALG_RSA),
+		.parms.enc_scheme	= cpu_to_be16(TPM_ES_RSAESPKCSv15),
+		.parms.sig_scheme	= cpu_to_be16(TPM_SS_RSAESPKCSv15_SHA1),
+		.parms.parm_size	= cpu_to_be32(sizeof(struct tpm_rsa_key_parms)),
+		.parms.rsa.key_length	= cpu_to_be32(2048),
+		.parms.rsa.num_primes	= cpu_to_be32(2),
+		.parms.rsa.exponent_size = cpu_to_be32(0),
+		.pcr_info_size		= cpu_to_be32(0),
+		.pub.key_length		= cpu_to_be32(0),
+		.enc_data_size		= cpu_to_be32(0),
+	};
+
+	kenter("");
+
+	if (migration_auth)
+		tpm_key.key_flags |= cpu_to_be32(TPM_KEY_MIGRATABLE);
+
+	/* alloc some work space */
+	tb = kmalloc(sizeof(*tb) + sizeof(*td), GFP_KERNEL);
+	if (!tb)
+		return -ENOMEM;
+	td = (void *)tb + sizeof(*tb);
+
+	/* Get the encryption session */
+	ret = tpm_create_osap(chip, tb, &sess,
+			      parent_auth, parent_type, parent_handle);
+	if (ret < 0)
+		goto out;
+	dump_sess(&sess);
+
+	/* We need to pass 'passwords' to the TPM with which it will encrypt
+	 * the key before returning it.  So that the passwords don't travel to
+	 * the TPM in the clear, we generate a symmetric key from the
+	 * negotiated and encrypted session data and encrypt the passwords with
+	 * that.
+	 */
+	ret = tpm_calc_symmetric_authkey(td, sess.secret, &sess.enonce);
+	if (ret < 0)
+		goto out;
+	tpm_crypt_with_authkey(td, usage_auth, td->encauth);
+	if (migration_auth)
+		tpm_crypt_with_authkey(td, migration_auth, td->encauth2);
+	else
+		tpm_crypt_with_authkey(td, sess.enonce.data, td->encauth2);
+
+	/* Set up the parameters we will be sending */
+	ret = tpm_gen_odd_nonce(chip, &td->ononce);
+	if (ret < 0)
+		goto out;
+
+	/* calculate authorization HMAC value */
+	ordinal_be = cpu_to_be32(TPM_ORD_CREATEWRAPKEY);
+	cont = 0;
+	ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
+			   &sess.enonce, &td->ononce, cont,
+			   /* 1S */ sizeof(__be32), &ordinal_be,
+			   /* 2S */ SHA1_DIGEST_SIZE, td->encauth,
+			   /* 3S */ SHA1_DIGEST_SIZE, td->encauth2,
+			   /* 4S */ sizeof(tpm_key), &tpm_key,
+			   0, NULL);
+	if (ret < 0)
+		goto out;
+
+	/* build and send the TPM request packet */
+	INIT_BUF(tb);
+	store16(tb, TPM_TAG_RQU_AUTH1_COMMAND);
+	store32(tb, TPM_DATA_OFFSET + 44 + sizeof(tpm_key) + 45);
+	store32(tb, TPM_ORD_CREATEWRAPKEY);
+	store32(tb, parent_handle);
+	store_s(tb, td->encauth, SHA1_DIGEST_SIZE);
+	store_s(tb, td->encauth2, SHA1_DIGEST_SIZE);
+	store_s(tb, &tpm_key, sizeof(tpm_key));
+	store32(tb, sess.handle);
+	store_s(tb, td->ononce.data, TPM_NONCE_SIZE);
+	store_8(tb, cont);
+	store_s(tb, td->pubauth, SHA1_DIGEST_SIZE);
+
+	ret = tpm_send_dump(chip, tb, "creating key");
+	if (ret < 0)
+		goto out;
+
+	/* We need to work out how big the TPM_KEY or TPM_KEY12 struct we got
+	 * back is.  These structs have several variable-length fields inside
+	 * to make parsing more difficult.  However, they are only followed by
+	 * fixed-length structs...
+	 */
+	SET_BUF_OFFSET(tb, TPM_SIZE_OFFSET);
+	key_size = LOAD32(tb);
+	key_size -= TPM_DATA_OFFSET;
+	key_size -= 2 * TPM_NONCE_SIZE + 1;
+	if (key_size < sizeof(tpm_key)) {
+		ret = -EBADMSG;
+		goto out;
+	}
+
+	/* Check the HMAC in the response */
+	ret = TSS_checkhmac1(tb, ordinal_be, &td->ononce,
+			     sess.secret, SHA1_DIGEST_SIZE,
+			     /* 3S */ key_size, TPM_DATA_OFFSET,
+			     0, NULL);
+	if (ret < 0)
+		goto out;
+
+	/* Parse the key */
+	result = (void *)tb->data + TPM_DATA_OFFSET;
+	ret = -EBADMSG;
+	if (key_size < sizeof(tpm_key) + be32_to_cpu(tpm_key.parms.rsa.key_length) / 8)
+		goto out;
+	if (memcmp(result, &tpm_key, offsetof(struct tpm_key, pub.key_length)) != 0)
+		goto out;
+	if (be32_to_cpu(result->pub.key_length) >
+	    be32_to_cpu(tpm_key.parms.rsa.key_length) / 8)
+		goto out;
+
+	ret = -ENOMEM;
+	wrapped_key = kmalloc(sizeof(struct tpm_wrapped_key) + key_size, GFP_KERNEL);
+	if (!wrapped_key)
+		goto out;
+	wrapped_key->data_len = key_size;
+	wrapped_key->pubkey_offset = offsetof(struct tpm_key, pub.key_data);
+	wrapped_key->pubkey_len = be32_to_cpu(result->pub.key_length);
+	memcpy(wrapped_key->data, result, key_size);
+	*_wrapped_key = wrapped_key;
+	ret = 0;
+
+out:
+	kfree(tb);
+	kleave(" = %d", ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tpm_create_wrap_key);
+
 /**
  * tpm_library_use - Tell the TPM library we want to make use of it
  *
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 398bfaef2325..0bc954ac8266 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -83,7 +83,7 @@ static inline int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max) {
  */
 /* implementation specific TPM constants */
 #define MAX_PCRINFO_SIZE		64
-#define MAX_BUF_SIZE			512
+#define MAX_BUF_SIZE			(2048 - 4)
 #define TPM_GETRANDOM_SIZE		14
 #define TPM_OSAP_SIZE			36
 #define TPM_OIAP_SIZE			10
@@ -133,4 +133,18 @@ extern int tpm_unseal(struct tpm_chip *chip, struct tpm_buf *tb,
 		      const unsigned char *blobauth,
 		      unsigned char *data, unsigned int *datalen);
 
+struct tpm_wrapped_key {
+	unsigned short data_len;
+	unsigned short pubkey_offset;
+	unsigned short pubkey_len;
+	u8 data[];
+};
+
+extern int tpm_create_wrap_key(struct tpm_chip *chip,
+			       enum tpm_entity_type parent_type,
+			       uint32_t parent_handle,
+			       const unsigned char *parent_auth,
+			       const unsigned char *usage_auth,
+			       const unsigned char *migration_auth,
+			       struct tpm_wrapped_key **_wrapped_key);
 #endif
diff --git a/include/linux/tpm_command.h b/include/linux/tpm_command.h
index a3e0bb670e62..0417a3db7e8f 100644
--- a/include/linux/tpm_command.h
+++ b/include/linux/tpm_command.h
@@ -22,6 +22,7 @@ enum tpm_ordinal {
 	TPM_ORD_PCR_READ		= 21,
 	TPM_ORD_SEAL			= 23,
 	TPM_ORD_UNSEAL			= 24,
+	TPM_ORD_CREATEWRAPKEY		= 31,
 	TPM_ORD_GET_RANDOM		= 70,
 	TPM_ORD_CONTINUE_SELFTEST	= 83,
 	TPM_ORD_GET_CAP			= 101,


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 21/23] TPMLIB: Implement call to TPM_LoadKey2
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (19 preceding siblings ...)
  2018-08-21 15:59   ` [PATCH 20/23] TPMLIB: Implement call to TPM_CreateWrapKey David Howells
@ 2018-08-21 15:59   ` David Howells
  2018-08-21 15:59   ` [PATCH 22/23] TPMLIB: Provide call for TPM_FlushSpecific David Howells
                     ` (2 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:59 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

Implement a function to invoke TPM_LoadKey2

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

 drivers/char/tpm/tpm-library.c |   93 ++++++++++++++++++++++++++++++++++++++++
 include/linux/tpm.h            |    7 +++
 include/linux/tpm_command.h    |    1 
 3 files changed, 101 insertions(+)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index 3413abeb3635..d279243ccc00 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -1017,6 +1017,99 @@ out:
 }
 EXPORT_SYMBOL_GPL(tpm_create_wrap_key);
 
+/**
+ * tpm_load_key2 - Load a key and decrypt it
+ * @chip: The chip to use
+ * @tb: Large scratch buffer for I/O
+ * @parent_type: Type of entity attached to @parent_handle
+ * @parent_handle: TPM-resident key used to encrypt
+ * @parent_auth: Parent authorisation HMAC key
+ * @wrapped_key: The wrapped key
+ * @_key_handle: The TPM's handle on the key
+ *
+ * Have the TPM decrypt a key and load it into its memory.  The TPM then
+ * returns a handle to the key that we can use in other operations.
+ *
+ * AUTH1 is used for sealing key.
+ */
+int tpm_load_key2(struct tpm_chip *chip,
+		  enum tpm_entity_type parent_type,
+		  uint32_t parent_handle,
+		  const unsigned char *parent_auth,
+		  const struct tpm_wrapped_key *wrapped_key,
+		  uint32_t *_key_handle)
+{
+	struct tpm_osapsess sess;
+	struct tpm_digests *td;
+	struct tpm_buf *tb;
+	unsigned char cont;
+	__be32 ordinal_be;
+	int ret;
+
+	kenter("");
+
+	/* alloc some work space */
+	tb = kmalloc(sizeof(*tb) + sizeof(*td), GFP_KERNEL);
+	if (!tb)
+		return -ENOMEM;
+	td = (void *)tb + sizeof(*tb);
+
+	/* Get the encryption session */
+	ret = tpm_create_osap(chip, tb, &sess,
+			      parent_auth, parent_type, parent_handle);
+	if (ret < 0)
+		goto out;
+	dump_sess(&sess);
+
+	/* Set up the parameters we will be sending */
+	ret = tpm_gen_odd_nonce(chip, &td->ononce);
+	if (ret < 0)
+		goto out;
+
+	/* calculate authorization HMAC value */
+	ordinal_be = cpu_to_be32(TPM_ORD_LOADKEY2);
+	cont = 0;
+	ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
+			   &sess.enonce, &td->ononce, cont,
+			   /* 1S */ sizeof(__be32), &ordinal_be,
+			   /* 2S */ wrapped_key->data_len, wrapped_key->data,
+			   0, NULL);
+	if (ret < 0)
+		goto out;
+
+	/* build and send the TPM request packet */
+	INIT_BUF(tb);
+	store16(tb, TPM_TAG_RQU_AUTH1_COMMAND);
+	store32(tb, TPM_DATA_OFFSET + 4 + wrapped_key->data_len + 45);
+	store32(tb, TPM_ORD_LOADKEY2);
+	store32(tb, parent_handle);
+	store_s(tb, wrapped_key->data, wrapped_key->data_len);
+	store32(tb, sess.handle);
+	store_s(tb, td->ononce.data, TPM_NONCE_SIZE);
+	store_8(tb, cont);
+	store_s(tb, td->pubauth, SHA1_DIGEST_SIZE);
+
+	ret = tpm_send_dump(chip, tb, "loading key");
+	if (ret < 0)
+		goto out;
+
+	/* Check the HMAC in the response */
+	ret = TSS_checkhmac1(tb, ordinal_be, &td->ononce,
+			     sess.secret, SHA1_DIGEST_SIZE,
+			     0, NULL);
+	if (ret < 0)
+		goto out;
+
+	*_key_handle = LOAD32(tb);
+	ret = 0;
+
+out:
+	kfree(tb);
+	kleave(" = %d [%08x]", ret, *_key_handle);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tpm_load_key2);
+
 /**
  * tpm_library_use - Tell the TPM library we want to make use of it
  *
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 0bc954ac8266..2be0decff93b 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -147,4 +147,11 @@ extern int tpm_create_wrap_key(struct tpm_chip *chip,
 			       const unsigned char *usage_auth,
 			       const unsigned char *migration_auth,
 			       struct tpm_wrapped_key **_wrapped_key);
+extern int tpm_load_key2(struct tpm_chip *chip,
+			 enum tpm_entity_type parent_type,
+			 uint32_t parent_handle,
+			 const unsigned char *parent_auth,
+			 const struct tpm_wrapped_key *wrapped_key,
+			 uint32_t *_key_handle);
+
 #endif
diff --git a/include/linux/tpm_command.h b/include/linux/tpm_command.h
index 0417a3db7e8f..211d4ce75f67 100644
--- a/include/linux/tpm_command.h
+++ b/include/linux/tpm_command.h
@@ -23,6 +23,7 @@ enum tpm_ordinal {
 	TPM_ORD_SEAL			= 23,
 	TPM_ORD_UNSEAL			= 24,
 	TPM_ORD_CREATEWRAPKEY		= 31,
+	TPM_ORD_LOADKEY2		= 65,
 	TPM_ORD_GET_RANDOM		= 70,
 	TPM_ORD_CONTINUE_SELFTEST	= 83,
 	TPM_ORD_GET_CAP			= 101,


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 22/23] TPMLIB: Provide call for TPM_FlushSpecific
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (20 preceding siblings ...)
  2018-08-21 15:59   ` [PATCH 21/23] TPMLIB: Implement call to TPM_LoadKey2 David Howells
@ 2018-08-21 15:59   ` David Howells
  2018-08-21 15:59   ` [PATCH 23/23] TPM: Add an asymmetric key subtype for handling TPM-based keys David Howells
  2018-08-22 14:19   ` tpm: Provide a TPM access library Jarkko Sakkinen
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:59 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA


---

 drivers/char/tpm/tpm-library.c |   31 +++++++++++++++++++++++++++++++
 include/linux/tpm.h            |   17 +++++++++++++++++
 include/linux/tpm_command.h    |    1 +
 3 files changed, 49 insertions(+)

diff --git a/drivers/char/tpm/tpm-library.c b/drivers/char/tpm/tpm-library.c
index d279243ccc00..27e993f0b0b7 100644
--- a/drivers/char/tpm/tpm-library.c
+++ b/drivers/char/tpm/tpm-library.c
@@ -1110,6 +1110,37 @@ out:
 }
 EXPORT_SYMBOL_GPL(tpm_load_key2);
 
+/**
+ * tpm_flush_specific - Tell the TPM to discard a handle and associated resources
+ * @chip: The chip to use
+ * @handle: The handle to discard
+ * @handle_type: The type of handle
+ */
+int tpm_flush_specific(struct tpm_chip *chip,
+		       uint32_t handle, enum tpm_resource_type handle_type)
+{
+	struct tpm_buf *tb;
+	int ret;
+
+	/* alloc some work space */
+	tb = kmalloc(sizeof(*tb), GFP_KERNEL);
+	if (!tb)
+		return -ENOMEM;
+
+	/* build and send the TPM request packet */
+	INIT_BUF(tb);
+	store16(tb, TPM_TAG_RQU_COMMAND);
+	store32(tb, TPM_DATA_OFFSET + 8);
+	store32(tb, TPM_ORD_FLUSHSPECIFIC);
+	store32(tb, handle);
+	store32(tb, handle_type);
+
+	ret = tpm_send_dump(chip, tb, "flushing handle");
+	kfree(tb);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tpm_flush_specific);
+
 /**
  * tpm_library_use - Tell the TPM library we want to make use of it
  *
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 2be0decff93b..753ffd3799a1 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -109,6 +109,19 @@ enum tpm_entity_type {
 	TPM_ET_RESERVED_HANDLE		= 0x40,
 };
 
+enum tpm_resource_type {
+	TPM_RT_KEY			= 0x00000001,
+	TPM_RT_AUTH			= 0x00000002,
+	TPM_RT_HASH			= 0x00000003,
+	TPM_RT_TRANS			= 0x00000004,
+	TPM_RT_CONTEXT			= 0x00000005,
+	TPM_RT_COUNTER			= 0x00000006,
+	TPM_RT_DELEGATE			= 0x00000007,
+	TPM_RT_DAA_TPM			= 0x00000008,
+	TPM_RT_DAA_V0			= 0x00000009,
+	TPM_RT_DAA_V1			= 0x0000000a,
+};
+
 struct tpm_buf {
 	unsigned short len;
 	unsigned short offset;
@@ -154,4 +167,8 @@ extern int tpm_load_key2(struct tpm_chip *chip,
 			 const struct tpm_wrapped_key *wrapped_key,
 			 uint32_t *_key_handle);
 
+extern int tpm_flush_specific(struct tpm_chip *chip,
+			      uint32_t handle,
+			      enum tpm_resource_type handle_type);
+
 #endif
diff --git a/include/linux/tpm_command.h b/include/linux/tpm_command.h
index 211d4ce75f67..8b52447bbee3 100644
--- a/include/linux/tpm_command.h
+++ b/include/linux/tpm_command.h
@@ -30,6 +30,7 @@ enum tpm_ordinal {
 	TPM_ORD_READPUBEK		= 124,
 	TPM_ORD_SAVESTATE		= 152,
 	TPM_ORD_STARTUP			= 153,
+	TPM_ORD_FLUSHSPECIFIC		= 186,
 };
 
 /* Other constants */


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 23/23] TPM: Add an asymmetric key subtype for handling TPM-based keys
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (21 preceding siblings ...)
  2018-08-21 15:59   ` [PATCH 22/23] TPMLIB: Provide call for TPM_FlushSpecific David Howells
@ 2018-08-21 15:59   ` David Howells
  2018-08-22 14:19   ` tpm: Provide a TPM access library Jarkko Sakkinen
  23 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 15:59 UTC (permalink / raw)
  To: denkenz-Re5JQEeQqe8AvxtiuMwx3w,
	jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	jejb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
  Cc: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] TPM: Add new TPMs to the tail of the list to prevent inadvertent change of dev
       [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:19       ` Jarkko Sakkinen
  1 sibling, 1 reply; 42+ messages in thread
From: Jason Gunthorpe @ 2018-08-21 18:30 UTC (permalink / raw)
  To: David Howells
  Cc: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Tue, Aug 21, 2018 at 04:56:56PM +0100, David Howells wrote:
> Add newly registered TPMs to the tail of the list, not the beginning, so that
> things that are specifying TPM_ANY_NUM don't find that the device they're
> using has inadvertently changed.  Adding a second device would break IMA, for
> instance.
> 
> Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> Reviewed-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
> Signed-off-by: Peter Huewe <peterhuewe-Mmb7MZpHnFY@public.gmane.org>
> cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> ---

We really should apply this patch...

Jason

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 04/23] TPM: Expose struct tpm_chip and related find_get and put functions
       [not found]     ` <153486703636.13066.16209594327379341518.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
@ 2018-08-21 18:31       ` Jason Gunthorpe
  0 siblings, 0 replies; 42+ messages in thread
From: Jason Gunthorpe @ 2018-08-21 18:31 UTC (permalink / raw)
  To: David Howells
  Cc: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Tue, Aug 21, 2018 at 04:57:16PM +0100, David Howells wrote:
> Expose struct tpm_chip and related find_get and put functions so that
> TPM-using code can make sure it uses the same TPM for any related set of
> operations.
> 
> Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---

>  drivers/char/tpm/tpm-interface.c |   19 ++++++++++++++++---
>  drivers/char/tpm/tpm.h           |    5 -----
>  include/linux/tpm.h              |   10 ++++++++++
>  3 files changed, 26 insertions(+), 8 deletions(-)

I think this is already in the kernel .. Stephen did it.

Jason

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/23] TPM: Provide a facility for a userspace TPM emulator
       [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>
  0 siblings, 1 reply; 42+ messages in thread
From: Jason Gunthorpe @ 2018-08-21 18:31 UTC (permalink / raw)
  To: David Howells
  Cc: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Tue, Aug 21, 2018 at 04:57:03PM +0100, David Howells wrote:
> Provide a misc device file (/dev/tpm_emul) by which a userspace TPM emulator
> can set up a virtual TPM device under the control of the TPM frontend.  The
> way this works is:
> 
>  (1) The emulator opens /dev/tpm_emul which is provided by the tpm_user
>      driver.
> 
>  (2) tpm_user registers a TPM device and the tpm driver creates a /dev/tpmN
>      misc device for the trousers package and suchlike to access.
> 
>  (3) The emulator sits in read() on the emulator device waiting for a command
>      to come through.
> 
>  (4) tpm_user passes requests from /dev/tpmN to the emulator's read() call.
> 
>  (5) The emulator processes the request.
> 
>  (6) The emulator either write()'s the reply or calls ioctl(fd,0,0) to cancel
>      the command.
> 
>  (7) The emulator goes back to read() to wait for the next command.
> 
>  (8) tpm_user passes the reply back to the tpm driver which passes it back to
>      /dev/tpmN.
> 
> When the emulator closes /dev/tpm_emul, the TPM driver is unregistered and the
> /dev/tpmN misc device is then removed.  Any outstanding requests are aborted
> and -EIO will be returned from then on.  Multiple TPMs can be registered.
> 
> Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
> 
>  drivers/char/tpm/Kconfig         |   13 +
>  drivers/char/tpm/Makefile        |    1 
>  drivers/char/tpm/tpm_user_emul.c |  672 ++++++++++++++++++++++++++++++++++++++
>  include/linux/wait.h             |   11 +
>  4 files changed, 697 insertions(+)
>  create mode 100644 drivers/char/tpm/tpm_user_emul.c

This looks to duplicate the vtpm stuff...

Jason

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 04/23] TPM: Expose struct tpm_chip and related find_get and put functions
       [not found]     ` <20180821183108.GC25543-uk2M96/98Pc@public.gmane.org>
@ 2018-08-21 18:35       ` David Howells
  0 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2018-08-21 18:35 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
	dhowells-H+wXaHxf7aLQT0dZR+AlfA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

Jason Gunthorpe <jgg-uk2M96/98Pc@public.gmane.org> wrote:

> I think this is already in the kernel .. Stephen did it.

As I said in the cover: one or two of these patches may already be upstream.

It's the state of the branch I had four years ago.

David

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: tpm: Provide a TPM access library
       [not found] ` <153486700916.13066.12870860668352070081.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
                     ` (22 preceding siblings ...)
  2018-08-21 15:59   ` [PATCH 23/23] TPM: Add an asymmetric key subtype for handling TPM-based keys David Howells
@ 2018-08-22 14:19   ` Jarkko Sakkinen
  23 siblings, 0 replies; 42+ messages in thread
From: Jarkko Sakkinen @ 2018-08-22 14:19 UTC (permalink / raw)
  To: David Howells
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Tue, Aug 21, 2018 at 04:56:49PM +0100, David Howells wrote:
> 
> Hi Denis, Jarkko, James,
> 
> I managed to recover the TPM library patchset that I was working on about four
> years ago in the process of trying to write an asymmetric key subtype that
> could use the TPM.
> 
> Here it is in it's original glory for reference.  I ended up leaving it
> because Jarkko's tpm-2 stuff broke it and I had other things to work on.  If
> it's deemed worthwhile, I can try to forward port it to current Linus/mastet.
> 
> Note that one or two of the preliminary patches may be upstream.
> 
> The patches can also be found here:
> 
> 	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=tpm-lib

Just a minor overal complaint: lower case for tags (please do not send
a newer version just because of that  before I have time to review this).
Thank you.

/Jarkko

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: tpm: Provide a TPM access library
       [not found] ` <20180822141956.GA28110-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
@ 2018-08-22 14:45   ` David Howells
       [not found]     ` <13611.1534949106-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
  0 siblings, 1 reply; 42+ messages in thread
From: David Howells @ 2018-08-22 14:45 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> wrote:

> Just a minor overal complaint: lower case for tags

You mean like TPM_TAG_RQU_COMMAND?

> (please do not send a newer version just because of that before I have time
> to review this).

I'd want to pull it up to current linus/master before posting again.

David

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: tpm: Provide a TPM access library
       [not found]     ` <13611.1534949106-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
@ 2018-08-23 22:49       ` Jarkko Sakkinen
  0 siblings, 0 replies; 42+ messages in thread
From: Jarkko Sakkinen @ 2018-08-23 22:49 UTC (permalink / raw)
  To: David Howells
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Wed, Aug 22, 2018 at 03:45:06PM +0100, David Howells wrote:
> Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> wrote:
> 
> > Just a minor overal complaint: lower case for tags
> 
> You mean like TPM_TAG_RQU_COMMAND?

No, I meant just the the short summary...

/Jarkko

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] TPM: Add new TPMs to the tail of the list to prevent inadvertent change of dev
       [not found]     ` <153486701644.13066.13372706238885253812.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
  2018-08-21 18:30       ` Jason Gunthorpe
@ 2018-08-24  6:19       ` Jarkko Sakkinen
  1 sibling, 0 replies; 42+ messages in thread
From: Jarkko Sakkinen @ 2018-08-24  6:19 UTC (permalink / raw)
  To: David Howells
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

Use "tpm" instead of "TPM" in the short summary.

On Tue, Aug 21, 2018 at 04:56:56PM +0100, David Howells wrote:
> Add newly registered TPMs to the tail of the list, not the beginning, so that
> things that are specifying TPM_ANY_NUM don't find that the device they're
> using has inadvertently changed.  Adding a second device would break IMA, for
> instance.
> 
> Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> Reviewed-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
> Signed-off-by: Peter Huewe <peterhuewe-Mmb7MZpHnFY@public.gmane.org>
> cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org

Usually I add Cc-tag before signed-off-by's (and have the first c in
upper case).

Peter's singed-off-by should be accompanied with a co-developed-by tag
if he has participated to the development of this commit.

As far as I see signed-off-by without co-developed-by makes sense in two
occasions:

* You own the subsystem tree i.e. you have to sign the changes that you
  include part of your pull request.
* You are the initial authoer of the change.  

> ---
> 
>  drivers/char/tpm/tpm-interface.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> index 6af17002a115..cfb9089887bd 100644
> --- a/drivers/char/tpm/tpm-interface.c
> +++ b/drivers/char/tpm/tpm-interface.c
> @@ -1122,7 +1122,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
>  
>  	/* Make chip available */
>  	spin_lock(&driver_lock);
> -	list_add_rcu(&chip->list, &tpm_chip_list);

I would add here a comment just as a remainder.
> +	list_add_tail_rcu(&chip->list, &tpm_chip_list);
>  	spin_unlock(&driver_lock);
>  
>  	return chip;

/Jarkko

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] TPM: Add new TPMs to the tail of the list to prevent inadvertent change of dev
       [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>
  0 siblings, 1 reply; 42+ messages in thread
From: Jarkko Sakkinen @ 2018-08-24  6:24 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: David Howells, linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Tue, Aug 21, 2018 at 12:30:04PM -0600, Jason Gunthorpe wrote:
> On Tue, Aug 21, 2018 at 04:56:56PM +0100, David Howells wrote:
> > Add newly registered TPMs to the tail of the list, not the beginning, so that
> > things that are specifying TPM_ANY_NUM don't find that the device they're
> > using has inadvertently changed.  Adding a second device would break IMA, for
> > instance.
> > 
> > Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > Reviewed-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
> > Signed-off-by: Peter Huewe <peterhuewe-Mmb7MZpHnFY@public.gmane.org>
> > cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > ---
> 
> We really should apply this patch...
> 
> Jason

This is the first time I remember seeing it.

/Jarkko

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] TPM: Add new TPMs to the tail of the list to prevent inadvertent change of dev
       [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>
  0 siblings, 1 reply; 42+ messages in thread
From: Jarkko Sakkinen @ 2018-08-24  6:25 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: David Howells, linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Fri, Aug 24, 2018 at 09:24:34AM +0300, Jarkko Sakkinen wrote:
> On Tue, Aug 21, 2018 at 12:30:04PM -0600, Jason Gunthorpe wrote:
> > On Tue, Aug 21, 2018 at 04:56:56PM +0100, David Howells wrote:
> > > Add newly registered TPMs to the tail of the list, not the beginning, so that
> > > things that are specifying TPM_ANY_NUM don't find that the device they're
> > > using has inadvertently changed.  Adding a second device would break IMA, for
> > > instance.
> > > 
> > > Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > > Reviewed-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
> > > Signed-off-by: Peter Huewe <peterhuewe-Mmb7MZpHnFY@public.gmane.org>
> > > cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > > ---
> > 
> > We really should apply this patch...
> > 
> > Jason
> 
> This is the first time I remember seeing it.

At least in the sense that I should review it.

/Jarkkko

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/23] TPM: Provide a facility for a userspace TPM emulator
       [not found]         ` <20180821183140.GD25543-uk2M96/98Pc@public.gmane.org>
@ 2018-08-24  6:29           ` Jarkko Sakkinen
  0 siblings, 0 replies; 42+ messages in thread
From: Jarkko Sakkinen @ 2018-08-24  6:29 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: David Howells, linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Tue, Aug 21, 2018 at 12:31:40PM -0600, Jason Gunthorpe wrote:
> On Tue, Aug 21, 2018 at 04:57:03PM +0100, David Howells wrote:
> > Provide a misc device file (/dev/tpm_emul) by which a userspace TPM emulator
> > can set up a virtual TPM device under the control of the TPM frontend.  The
> > way this works is:
> > 
> >  (1) The emulator opens /dev/tpm_emul which is provided by the tpm_user
> >      driver.
> > 
> >  (2) tpm_user registers a TPM device and the tpm driver creates a /dev/tpmN
> >      misc device for the trousers package and suchlike to access.
> > 
> >  (3) The emulator sits in read() on the emulator device waiting for a command
> >      to come through.
> > 
> >  (4) tpm_user passes requests from /dev/tpmN to the emulator's read() call.
> > 
> >  (5) The emulator processes the request.
> > 
> >  (6) The emulator either write()'s the reply or calls ioctl(fd,0,0) to cancel
> >      the command.
> > 
> >  (7) The emulator goes back to read() to wait for the next command.
> > 
> >  (8) tpm_user passes the reply back to the tpm driver which passes it back to
> >      /dev/tpmN.
> > 
> > When the emulator closes /dev/tpm_emul, the TPM driver is unregistered and the
> > /dev/tpmN misc device is then removed.  Any outstanding requests are aborted
> > and -EIO will be returned from then on.  Multiple TPMs can be registered.
> > 
> > Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > ---
> > 
> >  drivers/char/tpm/Kconfig         |   13 +
> >  drivers/char/tpm/Makefile        |    1 
> >  drivers/char/tpm/tpm_user_emul.c |  672 ++++++++++++++++++++++++++++++++++++++
> >  include/linux/wait.h             |   11 +
> >  4 files changed, 697 insertions(+)
> >  create mode 100644 drivers/char/tpm/tpm_user_emul.c
> 
> This looks to duplicate the vtpm stuff...

Yeah, this is a duplicate to tpm_vtpm_proxy.

> 
> Jason

/Jarkko


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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 03/23] TPM: Provide a platform driver for the user emulator driver
       [not found]     ` <153486702979.13066.16900998092976336647.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
@ 2018-08-24  6:30       ` Jarkko Sakkinen
  0 siblings, 0 replies; 42+ messages in thread
From: Jarkko Sakkinen @ 2018-08-24  6:30 UTC (permalink / raw)
  To: David Howells
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Tue, Aug 21, 2018 at 04:57:09PM +0100, David Howells wrote:
> Provide a platform driver for the user emulator driver.  This seems to be
> necessary to stop tpm_chip_find_get() from blowing up because it assumes
> unconditionally that any device will have a driver attached:
> 
> 		if (try_module_get(pos->dev->driver->owner)) {
> 
> However, this doesn't then work right because if I remove the TPM device and
> re-add it, the tpm ID isn't recycled (ie, /dev/tpm0 becomes unavailable and
> the new TPM is /dev/tpm1).
> 
> Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

Again, a duplicate.

/Jarkko

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 05/23] TPM: Use struct tpm_chip rather than chip number as interface parameter
       [not found]     ` <153486704294.13066.8818198038331415342.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
@ 2018-08-24  7:42       ` Jarkko Sakkinen
  0 siblings, 0 replies; 42+ messages in thread
From: Jarkko Sakkinen @ 2018-08-24  7:42 UTC (permalink / raw)
  To: David Howells
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Tue, Aug 21, 2018 at 04:57:22PM +0100, David Howells wrote:
> Use struct tpm_chip rather than chip number as interface parameter for most
> interface functions.  This allows the client to be sure about the consistency
> of what device it uses.
> 
> Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
> 
>  drivers/char/tpm/tpm-interface.c    |   76 ++++++++-------------------------
>  drivers/char/tpm/tpm-sysfs.c        |    2 -
>  include/linux/tpm.h                 |   16 ++++---
>  security/integrity/ima/ima.h        |    2 -
>  security/integrity/ima/ima_crypto.c |    4 +-
>  security/integrity/ima/ima_init.c   |   19 +++++---
>  security/integrity/ima/ima_queue.c  |    4 +-
>  security/keys/trusted.c             |   80 ++++++++++++++++++++++-------------
>  8 files changed, 96 insertions(+), 107 deletions(-)

Should be split at least to three patches and TPM side is
already in the upstream.

/Jarkko

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 08/23] TPMLIB: Break TPM bits out of security/keys/trusted.c
       [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>
       [not found]         ` <20180824084930.GA10266-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
  0 siblings, 2 replies; 42+ messages in thread
From: Jarkko Sakkinen @ 2018-08-24  7:52 UTC (permalink / raw)
  To: David Howells
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Tue, Aug 21, 2018 at 04:57:43PM +0100, David Howells wrote:
> Break the TPM bits out of security/keys/trusted.c into their own call wrapper
> library.
> 
> Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

I think the very first steps that we should take would be to make TPM
subsystem to use struct tpm_buf internally for everything and convert
tpm_send() to take tpm_buf instead of a raw buffer.

For TPM 2.0 the subsystem already uses tpm_buf. I remember Tomas Winkler
working on to do the same for TPM 1.x.

After that it would make sense to convert TPM 1.x to use struct tpm_buf to
construct commands.

After all of this is done it is possible to evaluate these changes.

BTW right now there is call wrapper interface provided by the TPM
subsystem for TPM 2.0 trusted keys. Not sure if this has been the
right design choice. TPM 1.x and TPM 2.0 trusted keys implementations
live in different subsystems ATM, which at least somewhat wrong.

/Jarkko

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 08/23] TPMLIB: Break TPM bits out of security/keys/trusted.c
       [not found]         ` <20180824075227.GG3584-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
@ 2018-08-24  8:49           ` Jarkko Sakkinen
  0 siblings, 0 replies; 42+ messages in thread
From: Jarkko Sakkinen @ 2018-08-24  8:49 UTC (permalink / raw)
  To: David Howells
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Fri, Aug 24, 2018 at 10:52:27AM +0300, Jarkko Sakkinen wrote:
> On Tue, Aug 21, 2018 at 04:57:43PM +0100, David Howells wrote:
> > Break the TPM bits out of security/keys/trusted.c into their own call wrapper
> > library.
> > 
> > Signed-off-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> 
> I think the very first steps that we should take would be to make TPM
> subsystem to use struct tpm_buf internally for everything and convert
> tpm_send() to take tpm_buf instead of a raw buffer.
> 
> For TPM 2.0 the subsystem already uses tpm_buf. I remember Tomas Winkler
> working on to do the same for TPM 1.x.
> 
> After that it would make sense to convert TPM 1.x to use struct tpm_buf to
> construct commands.
> 
> After all of this is done it is possible to evaluate these changes.
> 
> BTW right now there is call wrapper interface provided by the TPM
> subsystem for TPM 2.0 trusted keys. Not sure if this has been the
> right design choice. TPM 1.x and TPM 2.0 trusted keys implementations
> live in different subsystems ATM, which at least somewhat wrong.

Tomas' patches are scattered here:

https://patchwork.kernel.org/patch/10261169/

I could rebase them and make a patch set out of them when I have time.

/Jarkko

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 08/23] TPMLIB: Break TPM bits out of security/keys/trusted.c
       [not found]         ` <20180824084930.GA10266-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
@ 2018-08-24  9:33           ` David Howells
       [not found]             ` <25340.1535103190-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
  0 siblings, 1 reply; 42+ messages in thread
From: David Howells @ 2018-08-24  9:33 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> wrote:

> I could rebase them and make a patch set out of them when I have time.

Thanks.  I'm not going to do anything further with this until after the merge
window anyway.

And thanks for taking the time to look through the patches.  I just dumped the
entire patchset on you rather than weeding out the duplicate/obsolete patches
as I don't have time just now to port them to linus/master.

David

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] TPM: Add new TPMs to the tail of the list to prevent inadvertent change of dev
       [not found]                 ` <20180824062557.GC3584-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
@ 2018-08-24 11:22                   ` Mimi Zohar
  0 siblings, 0 replies; 42+ messages in thread
From: Mimi Zohar @ 2018-08-24 11:22 UTC (permalink / raw)
  To: Jarkko Sakkinen, Jason Gunthorpe
  Cc: David Howells, linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Fri, 2018-08-24 at 09:25 +0300, Jarkko Sakkinen wrote:
> On Fri, Aug 24, 2018 at 09:24:34AM +0300, Jarkko Sakkinen wrote:
> > On Tue, Aug 21, 2018 at 12:30:04PM -0600, Jason Gunthorpe wrote:
> > > On Tue, Aug 21, 2018 at 04:56:56PM +0100, David Howells wrote:
> > > > Add newly registered TPMs to the tail of the list, not the beginning, so that
> > > > things that are specifying TPM_ANY_NUM don't find that the device they're
> > > > using has inadvertently changed.  Adding a second device would break IMA, for
> > > > instance.
> > > > 
> > > > Signed-off-by: David Howells <dhowells@redhat.com>
> > > > Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> > > > Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
> > > > cc: stable@vger.kernel.org
> > > > ---
> > > 
> > > We really should apply this patch...
> > > 
> > > Jason
> > 
> > This is the first time I remember seeing it.
> 
> At least in the sense that I should review it.

I remember this patch, because it affected IMA.  It has already been
upstreamed as 398a1e71dc82.

Mimi


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
tpmdd-devel mailing list
tpmdd-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 08/23] TPMLIB: Break TPM bits out of security/keys/trusted.c
       [not found]             ` <25340.1535103190-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
@ 2018-08-27  8:25               ` Jarkko Sakkinen
  0 siblings, 0 replies; 42+ messages in thread
From: Jarkko Sakkinen @ 2018-08-27  8:25 UTC (permalink / raw)
  To: David Howells
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-integrity-u79uwXL29TY76Z2rM5mHXA,
	denkenz-Re5JQEeQqe8AvxtiuMwx3w

On Fri, 2018-08-24 at 10:33 +0100, David Howells wrote:
> Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> wrote:
> 
> > I could rebase them and make a patch set out of them when I have time.
> 
> Thanks.  I'm not going to do anything further with this until after the merge
> window anyway.
> 
> And thanks for taking the time to look through the patches.  I just dumped the
> entire patchset on you rather than weeding out the duplicate/obsolete patches
> as I don't have time just now to port them to linus/master.

Are you coming to Edinburgh in late Oct? Could discuss there about TPM
and keyring "intersections" (not only this patch set but also trusted
keys etc.).

> David

/Jarkko

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, back to index

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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   ` [PATCH 23/23] TPM: Add an asymmetric key subtype for handling TPM-based keys David Howells
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

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