linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] Basic trusted keys support for TPM 2.0
@ 2015-10-13  8:11 Jarkko Sakkinen
  2015-10-13  8:11 ` [PATCH v2 1/4] tpm: introduce tpm_buf Jarkko Sakkinen
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Jarkko Sakkinen @ 2015-10-13  8:11 UTC (permalink / raw)
  To: tpmdd-devel, linux-kernel
  Cc: peterhuewe, gregkh, jgunthorpe, Jarkko Sakkinen,
	open list:KEYS-TRUSTED, open list:KEYS-TRUSTED

Basic trusted keys support: auth value and SHA256.

v2:

* Removed all the changes that modify the existing functions to use
  the new struct tpm_buf. These changes should be done separately from
  this patch set as they require separate QA + review.
* 'keyhandle=' is now required for TPM2. Makes sense to always state
  the sealing key because there's no any fixed keys on the chip (thanks
  to Andreas Fuchs for this comment).
* I updated tpm_buf to a be heap based structure. Now there's one full
  page of memory for variable sized messages. Also the stack is greatly
  reduced.

Jarkko Sakkinen (4):
  tpm: introduce tpm_buf
  keys, trusted: move struct trusted_key_options to trusted-type.h
  tpm: seal/unseal for TPM 2.0
  keys, trusted: seal/unseal with TPM 2.0 chips

 drivers/char/tpm/tpm-interface.c |  76 ++++++++++++
 drivers/char/tpm/tpm.h           | 110 +++++++++++++++++
 drivers/char/tpm/tpm2-cmd.c      | 250 ++++++++++++++++++++++++++++++++++++++-
 include/keys/trusted-type.h      |  14 ++-
 include/linux/tpm.h              |  26 ++++
 security/keys/trusted.c          |  36 +++++-
 security/keys/trusted.h          |  11 --
 7 files changed, 507 insertions(+), 16 deletions(-)

-- 
2.5.0


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

* [PATCH v2 1/4] tpm: introduce tpm_buf
  2015-10-13  8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
@ 2015-10-13  8:11 ` Jarkko Sakkinen
  2015-10-13  8:11 ` [PATCH v2 2/4] keys, trusted: move struct trusted_key_options to trusted-type.h Jarkko Sakkinen
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Jarkko Sakkinen @ 2015-10-13  8:11 UTC (permalink / raw)
  To: tpmdd-devel, linux-kernel
  Cc: peterhuewe, gregkh, jgunthorpe, Jarkko Sakkinen, Marcel Selhorst

This patch introduces struct tpm_buf that provides a string buffer for
constructing TPM commands. This allows to construct variable sized TPM
commands. For the buffer a page is allocated and mapped, which limits
maximum size to PAGE_SIZE.

Variable sized TPM commands are needed in order to add algorithmic
agility.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/char/tpm/tpm.h | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f8319a0..df43979 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2004 IBM Corporation
+ * Copyright (C) 2015 Intel Corporation
  *
  * Authors:
  * Leendert van Doorn <leendert@watson.ibm.com>
@@ -28,6 +29,7 @@
 #include <linux/tpm.h>
 #include <linux/acpi.h>
 #include <linux/cdev.h>
+#include <linux/highmem.h>
 
 enum tpm_const {
 	TPM_MINOR = 224,	/* officially assigned */
@@ -382,6 +384,101 @@ struct tpm_cmd_t {
 	tpm_cmd_params	params;
 } __packed;
 
+/* A string buffer type for constructing TPM commands. This is based on the
+ * ideas of string buffer code in security/keys/trusted.h but is heap based
+ * in order to keep the stack usage minimal.
+ */
+
+enum tpm_buf_flags {
+	TPM_BUF_OVERFLOW	= BIT(0),
+};
+
+struct tpm_buf {
+	struct page *data_page;
+	unsigned int flags;
+	u8 *data;
+};
+
+static inline void tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
+{
+	struct tpm_input_header *head;
+
+	buf->data_page = alloc_page(GFP_HIGHUSER);
+	if (!buf->data_page)
+		return -ENOMEM;
+
+	buf->flags = 0;
+	buf->data = kmap(buf->data_page);
+
+	head = (struct tpm_input_header *) buf->data;
+
+	head->tag = cpu_to_be16(tag);
+	head->length = cpu_to_be32(sizeof(*head));
+	head->ordinal = cpu_to_be32(ordinal);
+
+	return 0;
+}
+
+static inline void tpm_buf_destroy(struct tpm_buf *buf)
+{
+	kunmap(buf->data_page);
+	__free_page(buf->data_page);
+}
+
+static inline u32 tpm_buf_length(struct tpm_buf *buf)
+{
+	struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
+
+	return be32_to_cpu(head->length);
+}
+
+static inline u16 tpm_buf_tag(struct tpm_buf *buf)
+{
+	struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
+
+	return be16_to_cpu(head->tag);
+}
+
+static inline void tpm_buf_append(struct tpm_buf *buf,
+				  const unsigned char *new_data,
+				  unsigned int new_len)
+{
+	struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
+	u32 len = tpm_buf_length(buf);
+
+	/* Return silently if overflow has already happened. */
+	if (buf->flags & TPM_BUF_OVERFLOW)
+		return;
+
+	if ((len + new_len) > PAGE_SIZE) {
+		WARN(1, "tpm_buf: overflow\n");
+		buf->flags |= TPM_BUF_OVERFLOW;
+		return;
+	}
+
+	memcpy(&buf->data[len], new_data, new_len);
+	head->length = cpu_to_be32(len + new_len);
+}
+
+static inline void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value)
+{
+	tpm_buf_append(buf, &value, 1);
+}
+
+static inline void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value)
+{
+	__be16 value2 = cpu_to_be16(value);
+
+	tpm_buf_append(buf, (u8 *) &value2, 2);
+}
+
+static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
+{
+	__be32 value2 = cpu_to_be32(value);
+
+	tpm_buf_append(buf, (u8 *) &value2, 4);
+}
+
 extern struct class *tpm_class;
 extern dev_t tpm_devt;
 extern const struct file_operations tpm_fops;
-- 
2.5.0


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

* [PATCH v2 2/4] keys, trusted: move struct trusted_key_options to trusted-type.h
  2015-10-13  8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
  2015-10-13  8:11 ` [PATCH v2 1/4] tpm: introduce tpm_buf Jarkko Sakkinen
@ 2015-10-13  8:11 ` Jarkko Sakkinen
  2015-10-13  8:11 ` [PATCH v2 3/4] tpm: seal/unseal for TPM 2.0 Jarkko Sakkinen
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Jarkko Sakkinen @ 2015-10-13  8:11 UTC (permalink / raw)
  To: tpmdd-devel, linux-kernel
  Cc: peterhuewe, gregkh, jgunthorpe, Jarkko Sakkinen, David Safford,
	Mimi Zohar, David Howells, James Morris, Serge E. Hallyn,
	open list:KEYS-TRUSTED, open list:KEYS-TRUSTED

Moved struct trusted_key_options to trustes-type.h so that the fields
can be accessed from drivers/char/tpm.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 include/keys/trusted-type.h | 12 ++++++++++++
 security/keys/trusted.h     | 11 -----------
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
index 56f82e5..c91651f 100644
--- a/include/keys/trusted-type.h
+++ b/include/keys/trusted-type.h
@@ -12,10 +12,12 @@
 
 #include <linux/key.h>
 #include <linux/rcupdate.h>
+#include <linux/tpm.h>
 
 #define MIN_KEY_SIZE			32
 #define MAX_KEY_SIZE			128
 #define MAX_BLOB_SIZE			320
+#define MAX_PCRINFO_SIZE		64
 
 struct trusted_key_payload {
 	struct rcu_head rcu;
@@ -26,6 +28,16 @@ struct trusted_key_payload {
 	unsigned char blob[MAX_BLOB_SIZE];
 };
 
+struct trusted_key_options {
+	uint16_t keytype;
+	uint32_t keyhandle;
+	unsigned char keyauth[TPM_DIGEST_SIZE];
+	unsigned char blobauth[TPM_DIGEST_SIZE];
+	uint32_t pcrinfo_len;
+	unsigned char pcrinfo[MAX_PCRINFO_SIZE];
+	int pcrlock;
+};
+
 extern struct key_type key_type_trusted;
 
 #endif /* _KEYS_TRUSTED_TYPE_H */
diff --git a/security/keys/trusted.h b/security/keys/trusted.h
index 3249fbd..ff001a5 100644
--- a/security/keys/trusted.h
+++ b/security/keys/trusted.h
@@ -2,7 +2,6 @@
 #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
@@ -36,16 +35,6 @@ enum {
 	SRK_keytype = 4
 };
 
-struct trusted_key_options {
-	uint16_t keytype;
-	uint32_t keyhandle;
-	unsigned char keyauth[SHA1_DIGEST_SIZE];
-	unsigned char blobauth[SHA1_DIGEST_SIZE];
-	uint32_t pcrinfo_len;
-	unsigned char pcrinfo[MAX_PCRINFO_SIZE];
-	int pcrlock;
-};
-
 #define TPM_DEBUG 0
 
 #if TPM_DEBUG
-- 
2.5.0


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

* [PATCH v2 3/4] tpm: seal/unseal for TPM 2.0
  2015-10-13  8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
  2015-10-13  8:11 ` [PATCH v2 1/4] tpm: introduce tpm_buf Jarkko Sakkinen
  2015-10-13  8:11 ` [PATCH v2 2/4] keys, trusted: move struct trusted_key_options to trusted-type.h Jarkko Sakkinen
@ 2015-10-13  8:11 ` Jarkko Sakkinen
  2015-10-13  8:11 ` [PATCH v2 4/4] keys, trusted: seal/unseal with TPM 2.0 chips Jarkko Sakkinen
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Jarkko Sakkinen @ 2015-10-13  8:11 UTC (permalink / raw)
  To: tpmdd-devel, linux-kernel
  Cc: peterhuewe, gregkh, jgunthorpe, Jarkko Sakkinen, Marcel Selhorst,
	David Safford, Mimi Zohar, David Howells, open list:KEYS-TRUSTED,
	open list:KEYS-TRUSTED

Added tpm_trusted_seal() and tpm_trusted_unseal() API for sealing
trusted keys.

This patch implements basic sealing and unsealing functionality for
TPM 2.0:

* Seal with a parent key using a 20 byte auth value.
* Unseal with a parent key using a 20 byte auth value.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/char/tpm/tpm-interface.c |  76 ++++++++++++
 drivers/char/tpm/tpm.h           |  15 ++-
 drivers/char/tpm/tpm2-cmd.c      | 250 ++++++++++++++++++++++++++++++++++++++-
 include/keys/trusted-type.h      |   2 +-
 include/linux/tpm.h              |  26 ++++
 5 files changed, 366 insertions(+), 3 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index e85d341..c50637d 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -666,6 +666,30 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
 }
 
 /**
+ * tpm_is_tpm2 - is the chip a TPM2 chip?
+ * @chip_num:	tpm idx # or ANY
+ *
+ * Returns < 0 on error, and 1 or 0 on success depending whether the chip
+ * is a TPM2 chip.
+ */
+int tpm_is_tpm2(u32 chip_num)
+{
+	struct tpm_chip *chip;
+	int rc;
+
+	chip = tpm_chip_find_get(chip_num);
+	if (chip == NULL)
+		return -ENODEV;
+
+	rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0;
+
+	tpm_chip_put(chip);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_is_tpm2);
+
+/**
  * tpm_pcr_read - read a pcr value
  * @chip_num:	tpm idx # or ANY
  * @pcr_idx:	pcr idx to retrieve
@@ -1021,6 +1045,58 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
 }
 EXPORT_SYMBOL_GPL(tpm_get_random);
 
+/**
+ * tpm_seal_trusted() - seal a trusted key
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @options: authentication values and other options
+ * @payload: the key data in clear and encrypted form
+ *
+ * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips
+ * are supported.
+ */
+int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload,
+		     struct trusted_key_options *options)
+{
+	struct tpm_chip *chip;
+	int rc;
+
+	chip = tpm_chip_find_get(chip_num);
+	if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2))
+		return -ENODEV;
+
+	rc = tpm2_seal_trusted(chip, payload, options);
+
+	tpm_chip_put(chip);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_seal_trusted);
+
+/**
+ * tpm_unseal_trusted() - unseal a trusted key
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @options: authentication values and other options
+ * @payload: the key data in clear and encrypted form
+ *
+ * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips
+ * are supported.
+ */
+int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload,
+		       struct trusted_key_options *options)
+{
+	struct tpm_chip *chip;
+	int rc;
+
+	chip = tpm_chip_find_get(chip_num);
+	if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2))
+		return -ENODEV;
+
+	rc = tpm2_unseal_trusted(chip, payload, options);
+
+	tpm_chip_put(chip);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_unseal_trusted);
+
 static int __init tpm_init(void)
 {
 	int rc;
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index df43979..09aca509 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -90,6 +90,9 @@ enum tpm2_return_codes {
 
 enum tpm2_algorithms {
 	TPM2_ALG_SHA1		= 0x0004,
+	TPM2_ALG_KEYEDHASH	= 0x0008,
+	TPM2_ALG_SHA256		= 0x000B,
+	TPM2_ALG_NULL		= 0x0010
 };
 
 enum tpm2_command_codes {
@@ -97,6 +100,10 @@ enum tpm2_command_codes {
 	TPM2_CC_SELF_TEST	= 0x0143,
 	TPM2_CC_STARTUP		= 0x0144,
 	TPM2_CC_SHUTDOWN	= 0x0145,
+	TPM2_CC_CREATE		= 0x0153,
+	TPM2_CC_LOAD		= 0x0157,
+	TPM2_CC_UNSEAL		= 0x015E,
+	TPM2_CC_FLUSH_CONTEXT	= 0x0165,
 	TPM2_CC_GET_CAPABILITY	= 0x017A,
 	TPM2_CC_GET_RANDOM	= 0x017B,
 	TPM2_CC_PCR_READ	= 0x017E,
@@ -399,7 +406,7 @@ struct tpm_buf {
 	u8 *data;
 };
 
-static inline void tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
+static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
 {
 	struct tpm_input_header *head;
 
@@ -525,6 +532,12 @@ static inline void tpm_remove_ppi(struct tpm_chip *chip)
 int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
 int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
 int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max);
+int tpm2_seal_trusted(struct tpm_chip *chip,
+		      struct trusted_key_payload *payload,
+		      struct trusted_key_options *options);
+int tpm2_unseal_trusted(struct tpm_chip *chip,
+			struct trusted_key_payload *payload,
+			struct trusted_key_options *options);
 ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
 			u32 *value, const char *desc);
 
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 011909a..bd7039f 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Intel Corporation
+ * Copyright (C) 2014, 2015 Intel Corporation
  *
  * Authors:
  * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
@@ -16,6 +16,11 @@
  */
 
 #include "tpm.h"
+#include <keys/trusted-type.h>
+
+enum tpm2_object_attributes {
+	TPM2_ATTR_USER_WITH_AUTH	= BIT(6),
+};
 
 struct tpm2_startup_in {
 	__be16	startup_type;
@@ -381,6 +386,249 @@ static const struct tpm_input_header tpm2_get_tpm_pt_header = {
 };
 
 /**
+ * Append TPMS_AUTH_COMMAND to the buffer. The buffer must be allocated with
+ * tpm_buf_alloc().
+ *
+ * @param buf: an allocated tpm_buf instance
+ * @param nonce: the session nonce, may be NULL if not used
+ * @param nonce_len: the session nonce length, may be 0 if not used
+ * @param attributes: the session attributes
+ * @param hmac: the session HMAC or password, may be NULL if not used
+ * @param hmac_len: the session HMAC or password length, maybe 0 if not used
+ */
+static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle,
+				 const u8 *nonce, u16 nonce_len,
+				 u8 attributes,
+				 const u8 *hmac, u16 hmac_len)
+{
+	tpm_buf_append_u32(buf, 9 + nonce_len + hmac_len);
+	tpm_buf_append_u32(buf, session_handle);
+	tpm_buf_append_u16(buf, nonce_len);
+
+	if (nonce && nonce_len)
+		tpm_buf_append(buf, nonce, nonce_len);
+
+	tpm_buf_append_u8(buf, attributes);
+	tpm_buf_append_u16(buf, hmac_len);
+
+	if (hmac && hmac_len)
+		tpm_buf_append(buf, hmac, hmac_len);
+}
+
+/**
+ * tpm2_seal_trusted() - seal a trusted key
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @options: authentication values and other options
+ * @payload: the key data in clear and encrypted form
+ *
+ * Returns < 0 on error and 0 on success.
+ */
+int tpm2_seal_trusted(struct tpm_chip *chip,
+		      struct trusted_key_payload *payload,
+		      struct trusted_key_options *options)
+{
+	unsigned int blob_len;
+	struct tpm_buf buf;
+	int rc;
+
+	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
+	if (rc)
+		return rc;
+
+	tpm_buf_append_u32(&buf, options->keyhandle);
+	tpm2_buf_append_auth(&buf, TPM2_RS_PW,
+			     NULL /* nonce */, 0,
+			     0 /* session_attributes */,
+			     options->keyauth /* hmac */,
+			     TPM_DIGEST_SIZE);
+
+	/* sensitive */
+	tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len);
+
+	tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE);
+	tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE);
+	tpm_buf_append_u16(&buf, payload->key_len);
+	tpm_buf_append(&buf, payload->key, payload->key_len);
+
+	/* public */
+	tpm_buf_append_u16(&buf, 14);
+
+	tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
+	tpm_buf_append_u16(&buf, TPM2_ALG_SHA256);
+	tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
+	tpm_buf_append_u16(&buf, 0); /* policy digest size */
+	tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
+	tpm_buf_append_u16(&buf, 0);
+
+	/* outside info */
+	tpm_buf_append_u16(&buf, 0);
+
+	/* creation PCR */
+	tpm_buf_append_u32(&buf, 0);
+
+	if (buf.flags & TPM_BUF_OVERFLOW) {
+		rc = -E2BIG;
+		goto out;
+	}
+
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "sealing data");
+	if (rc)
+		goto out;
+
+	blob_len = be32_to_cpup((__be32 *) &buf.data[TPM_HEADER_SIZE]);
+	if (blob_len > MAX_BLOB_SIZE) {
+		rc = -E2BIG;
+		goto out;
+	}
+
+	memcpy(payload->blob, &buf.data[TPM_HEADER_SIZE + 4], blob_len);
+	payload->blob_len = blob_len;
+
+out:
+	tpm_buf_destroy(&buf);
+
+	if (rc > 0)
+		rc = -EPERM;
+
+	return rc;
+}
+
+static int tpm2_load(struct tpm_chip *chip,
+		     struct trusted_key_payload *payload,
+		     struct trusted_key_options *options,
+		     u32 *blob_handle)
+{
+	struct tpm_buf buf;
+	unsigned int private_len;
+	unsigned int public_len;
+	unsigned int blob_len;
+	int rc;
+
+	private_len = be16_to_cpup((__be16 *) &payload->blob[0]);
+	if (private_len > (payload->blob_len - 2))
+		return -E2BIG;
+
+	public_len = be16_to_cpup((__be16 *) &payload->blob[2 + private_len]);
+	blob_len = private_len + public_len + 4;
+	if (blob_len > payload->blob_len)
+		return -E2BIG;
+
+	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
+	if (rc)
+		return rc;
+
+	tpm_buf_append_u32(&buf, options->keyhandle);
+	tpm2_buf_append_auth(&buf, TPM2_RS_PW,
+			     NULL /* nonce */, 0,
+			     0 /* session_attributes */,
+			     options->keyauth /* hmac */,
+			     TPM_DIGEST_SIZE);
+
+	tpm_buf_append(&buf, payload->blob, blob_len);
+
+	if (buf.flags & TPM_BUF_OVERFLOW) {
+		rc = -E2BIG;
+		goto out;
+	}
+
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "loading blob");
+	if (!rc)
+		*blob_handle = be32_to_cpup(
+			(__be32 *) &buf.data[TPM_HEADER_SIZE]);
+
+out:
+	tpm_buf_destroy(&buf);
+
+	if (rc > 0)
+		rc = -EPERM;
+
+	return rc;
+}
+
+static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
+{
+	struct tpm_buf buf;
+	int rc;
+
+	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
+	if (rc) {
+		dev_warn(chip->pdev, "0x%08x was not flushed, out of memory\n",
+			 handle);
+		return;
+	}
+
+	tpm_buf_append_u32(&buf, handle);
+
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context");
+	if (rc)
+		dev_warn(chip->pdev, "0x%08x was not flushed, rc=%d\n", handle,
+			 rc);
+
+	tpm_buf_destroy(&buf);
+}
+
+static int tpm2_unseal(struct tpm_chip *chip,
+		       struct trusted_key_payload *payload,
+		       struct trusted_key_options *options,
+		       u32 blob_handle)
+{
+	struct tpm_buf buf;
+	int rc;
+
+	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
+	if (rc)
+		return rc;
+
+	tpm_buf_append_u32(&buf, blob_handle);
+	tpm2_buf_append_auth(&buf, TPM2_RS_PW,
+			     NULL /* nonce */, 0,
+			     0 /* session_attributes */,
+			     options->blobauth /* hmac */,
+			     TPM_DIGEST_SIZE);
+
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "unsealing");
+	if (rc > 0)
+		rc = -EPERM;
+
+	if (!rc) {
+		payload->key_len = be16_to_cpup(
+			(__be16 *) &buf.data[TPM_HEADER_SIZE + 4]);
+
+		memcpy(payload->key, &buf.data[TPM_HEADER_SIZE + 6],
+		       payload->key_len);
+	}
+
+	tpm_buf_destroy(&buf);
+	return rc;
+}
+
+/**
+ * tpm_unseal_trusted() - unseal a trusted key
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @options: authentication values and other options
+ * @payload: the key data in clear and encrypted form
+ *
+ * Returns < 0 on error and 0 on success.
+ */
+int tpm2_unseal_trusted(struct tpm_chip *chip,
+			struct trusted_key_payload *payload,
+			struct trusted_key_options *options)
+{
+	u32 blob_handle;
+	int rc;
+
+	rc = tpm2_load(chip, payload, options, &blob_handle);
+	if (rc)
+		return rc;
+
+	rc = tpm2_unseal(chip, payload, options, blob_handle);
+
+	tpm2_flush_context(chip, blob_handle);
+
+	return rc;
+}
+
+/**
  * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property
  * @chip:		TPM chip to use.
  * @property_id:	property ID.
diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
index c91651f..f91ecd9 100644
--- a/include/keys/trusted-type.h
+++ b/include/keys/trusted-type.h
@@ -16,7 +16,7 @@
 
 #define MIN_KEY_SIZE			32
 #define MAX_KEY_SIZE			128
-#define MAX_BLOB_SIZE			320
+#define MAX_BLOB_SIZE			512
 #define MAX_PCRINFO_SIZE		64
 
 struct trusted_key_payload {
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 8350c53..706e63e 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -30,6 +30,8 @@
 #define	TPM_ANY_NUM 0xFFFF
 
 struct tpm_chip;
+struct trusted_key_payload;
+struct trusted_key_options;
 
 struct tpm_class_ops {
 	const u8 req_complete_mask;
@@ -46,11 +48,22 @@ struct tpm_class_ops {
 
 #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)
 
+extern int tpm_is_tpm2(u32 chip_num);
 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_seal_trusted(u32 chip_num,
+			    struct trusted_key_payload *payload,
+			    struct trusted_key_options *options);
+extern int tpm_unseal_trusted(u32 chip_num,
+			      struct trusted_key_payload *payload,
+			      struct trusted_key_options *options);
 #else
+static inline int tpm_is_tpm2(u32 chip_num)
+{
+	return -ENODEV;
+}
 static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
 	return -ENODEV;
 }
@@ -63,5 +76,18 @@ static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) {
 static inline int tpm_get_random(u32 chip_num, u8 *data, size_t max) {
 	return -ENODEV;
 }
+
+static inline int tpm_seal_trusted(u32 chip_num,
+				   struct trusted_key_payload *payload,
+				   struct trusted_key_options *options)
+{
+	return -ENODEV;
+}
+static inline int tpm_unseal_trusted(u32 chip_num,
+				     struct trusted_key_payload *payload,
+				     struct trusted_key_options *options)
+{
+	return -ENODEV;
+}
 #endif
 #endif
-- 
2.5.0


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

* [PATCH v2 4/4] keys, trusted: seal/unseal with TPM 2.0 chips
  2015-10-13  8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
                   ` (2 preceding siblings ...)
  2015-10-13  8:11 ` [PATCH v2 3/4] tpm: seal/unseal for TPM 2.0 Jarkko Sakkinen
@ 2015-10-13  8:11 ` Jarkko Sakkinen
  2015-10-13  8:53 ` [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Jarkko Sakkinen @ 2015-10-13  8:11 UTC (permalink / raw)
  To: tpmdd-devel, linux-kernel
  Cc: peterhuewe, gregkh, jgunthorpe, Jarkko Sakkinen, David Safford,
	Mimi Zohar, David Howells, James Morris, Serge E. Hallyn,
	open list:KEYS-TRUSTED, open list:KEYS-TRUSTED

Call tpm_seal_trusted() and tpm_unseal_trusted() for TPM 2.0 chips.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Reviewed-by: Andreas Fuchs <andreas.fuchs@sit.fraunhofer.de>
---
 security/keys/trusted.c | 36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index c0594cb..d3633cf 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -862,12 +862,19 @@ static int datablob_parse(char *datablob, struct trusted_key_payload *p,
 static struct trusted_key_options *trusted_options_alloc(void)
 {
 	struct trusted_key_options *options;
+	int tpm2;
+
+	tpm2 = tpm_is_tpm2(TPM_ANY_NUM);
+	if (tpm2 < 0)
+		return NULL;
 
 	options = kzalloc(sizeof *options, GFP_KERNEL);
 	if (options) {
 		/* set any non-zero defaults */
 		options->keytype = SRK_keytype;
-		options->keyhandle = SRKHANDLE;
+
+		if (!tpm2)
+			options->keyhandle = SRKHANDLE;
 	}
 	return options;
 }
@@ -905,6 +912,11 @@ static int trusted_instantiate(struct key *key,
 	int ret = 0;
 	int key_cmd;
 	size_t key_len;
+	int tpm2;
+
+	tpm2 = tpm_is_tpm2(TPM_ANY_NUM);
+	if (tpm2 < 0)
+		return tpm2;
 
 	if (datalen <= 0 || datalen > 32767 || !prep->data)
 		return -EINVAL;
@@ -932,12 +944,20 @@ static int trusted_instantiate(struct key *key,
 		goto out;
 	}
 
+	if (!options->keyhandle) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	dump_payload(payload);
 	dump_options(options);
 
 	switch (key_cmd) {
 	case Opt_load:
-		ret = key_unseal(payload, options);
+		if (tpm2)
+			ret = tpm_unseal_trusted(TPM_ANY_NUM, payload, options);
+		else
+			ret = key_unseal(payload, options);
 		dump_payload(payload);
 		dump_options(options);
 		if (ret < 0)
@@ -950,7 +970,10 @@ static int trusted_instantiate(struct key *key,
 			pr_info("trusted_key: key_create failed (%d)\n", ret);
 			goto out;
 		}
-		ret = key_seal(payload, options);
+		if (tpm2)
+			ret = tpm_seal_trusted(TPM_ANY_NUM, payload, options);
+		else
+			ret = key_seal(payload, options);
 		if (ret < 0)
 			pr_info("trusted_key: key_seal failed (%d)\n", ret);
 		break;
@@ -1018,6 +1041,13 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
 		kfree(new_p);
 		goto out;
 	}
+
+	if (!new_o->keyhandle) {
+		ret = -EINVAL;
+		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;
-- 
2.5.0


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

* Re: [PATCH v2 0/4] Basic trusted keys support for TPM 2.0
  2015-10-13  8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
                   ` (3 preceding siblings ...)
  2015-10-13  8:11 ` [PATCH v2 4/4] keys, trusted: seal/unseal with TPM 2.0 chips Jarkko Sakkinen
@ 2015-10-13  8:53 ` Jarkko Sakkinen
  2015-10-13 17:41 ` Jason Gunthorpe
  2015-10-16 16:21 ` David Howells
  6 siblings, 0 replies; 10+ messages in thread
From: Jarkko Sakkinen @ 2015-10-13  8:53 UTC (permalink / raw)
  To: tpmdd-devel, linux-kernel
  Cc: peterhuewe, gregkh, jgunthorpe, open list:KEYS-TRUSTED,
	open list:KEYS-TRUSTED, kevin.strasser

On Tue, Oct 13, 2015 at 11:11:21AM +0300, Jarkko Sakkinen wrote:
> Basic trusted keys support: auth value and SHA256.
> 
> v2:
> 
> * Removed all the changes that modify the existing functions to use
>   the new struct tpm_buf. These changes should be done separately from
>   this patch set as they require separate QA + review.
> * 'keyhandle=' is now required for TPM2. Makes sense to always state
>   the sealing key because there's no any fixed keys on the chip (thanks
>   to Andreas Fuchs for this comment).
> * I updated tpm_buf to a be heap based structure. Now there's one full
>   page of memory for variable sized messages. Also the stack is greatly
>   reduced.

The basic test that I did was:

ID=$(keyctl add trusted kmk "new 32 keyhandle=0x80000000" @u)
keyctl pipe $ID  > blob.hex
keyctl clear @u
keyctl add trusted kmk "load `cat blob.hex` keyhandle=0x80000000" @u
keyctl clear @u

I also checked that the code fails with -EINVAL when keyhandle is not
given.

For generating a sealing key I used tpm2-root-key script from

https://github.com/jsakkine/linux-tpm2

I think the code is in the shape that it is ready to be pulled but some
tested-by's are needed.

> Jarkko Sakkinen (4):
>   tpm: introduce tpm_buf
>   keys, trusted: move struct trusted_key_options to trusted-type.h
>   tpm: seal/unseal for TPM 2.0
>   keys, trusted: seal/unseal with TPM 2.0 chips
> 
>  drivers/char/tpm/tpm-interface.c |  76 ++++++++++++
>  drivers/char/tpm/tpm.h           | 110 +++++++++++++++++
>  drivers/char/tpm/tpm2-cmd.c      | 250 ++++++++++++++++++++++++++++++++++++++-
>  include/keys/trusted-type.h      |  14 ++-
>  include/linux/tpm.h              |  26 ++++
>  security/keys/trusted.c          |  36 +++++-
>  security/keys/trusted.h          |  11 --
>  7 files changed, 507 insertions(+), 16 deletions(-)
> 
> -- 
> 2.5.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 0/4] Basic trusted keys support for TPM 2.0
  2015-10-13  8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
                   ` (4 preceding siblings ...)
  2015-10-13  8:53 ` [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
@ 2015-10-13 17:41 ` Jason Gunthorpe
  2015-10-13 19:25   ` Jarkko Sakkinen
  2015-10-16 16:21 ` David Howells
  6 siblings, 1 reply; 10+ messages in thread
From: Jason Gunthorpe @ 2015-10-13 17:41 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: tpmdd-devel, linux-kernel, peterhuewe, gregkh,
	open list:KEYS-TRUSTED, open list:KEYS-TRUSTED

On Tue, Oct 13, 2015 at 11:11:21AM +0300, Jarkko Sakkinen wrote:

> * I updated tpm_buf to a be heap based structure. Now there's one full
>   page of memory for variable sized messages. Also the stack is greatly
>   reduced.

You may as well just use a skb then.

Jason

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

* Re: [PATCH v2 0/4] Basic trusted keys support for TPM 2.0
  2015-10-13 17:41 ` Jason Gunthorpe
@ 2015-10-13 19:25   ` Jarkko Sakkinen
  0 siblings, 0 replies; 10+ messages in thread
From: Jarkko Sakkinen @ 2015-10-13 19:25 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: tpmdd-devel, linux-kernel, peterhuewe, gregkh,
	open list:KEYS-TRUSTED, open list:KEYS-TRUSTED

On Tue, Oct 13, 2015 at 11:41:20AM -0600, Jason Gunthorpe wrote:
> On Tue, Oct 13, 2015 at 11:11:21AM +0300, Jarkko Sakkinen wrote:
> 
> > * I updated tpm_buf to a be heap based structure. Now there's one full
> >   page of memory for variable sized messages. Also the stack is greatly
> >   reduced.
> 
> You may as well just use a skb then.

struct sk_buff??

I think the structure that I've implemented is a good fit. It's simple
to use and does exactly what we need. Can you elaborate what's the
problem with tpm_buf?

> Jason

/Jarkko

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

* Re: [PATCH v2 0/4] Basic trusted keys support for TPM 2.0
  2015-10-13  8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
                   ` (5 preceding siblings ...)
  2015-10-13 17:41 ` Jason Gunthorpe
@ 2015-10-16 16:21 ` David Howells
  2015-10-16 18:30   ` Jarkko Sakkinen
  6 siblings, 1 reply; 10+ messages in thread
From: David Howells @ 2015-10-16 16:21 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: dhowells, tpmdd-devel, linux-kernel, peterhuewe, gregkh,
	jgunthorpe, open list:KEYS-TRUSTED, open list:KEYS-TRUSTED

Hi Jarkko,

For some reason I don't see patch 1.

David

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

* Re: [PATCH v2 0/4] Basic trusted keys support for TPM 2.0
  2015-10-16 16:21 ` David Howells
@ 2015-10-16 18:30   ` Jarkko Sakkinen
  0 siblings, 0 replies; 10+ messages in thread
From: Jarkko Sakkinen @ 2015-10-16 18:30 UTC (permalink / raw)
  To: David Howells
  Cc: tpmdd-devel, linux-kernel, peterhuewe, gregkh, jgunthorpe,
	open list:KEYS-TRUSTED, open list:KEYS-TRUSTED

Hi

On Fri, Oct 16, 2015 at 05:21:02PM +0100, David Howells wrote:
> Hi Jarkko,
> 
> For some reason I don't see patch 1.

Weird. Well, maybe the best way to proceed is that I'll send the
contents of for-peter-v44 branch for review. It's 9 patches in total,
PPI, trusted keys and couple of bug fixes.

> David

/Jarkko

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

end of thread, other threads:[~2015-10-16 18:30 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-13  8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
2015-10-13  8:11 ` [PATCH v2 1/4] tpm: introduce tpm_buf Jarkko Sakkinen
2015-10-13  8:11 ` [PATCH v2 2/4] keys, trusted: move struct trusted_key_options to trusted-type.h Jarkko Sakkinen
2015-10-13  8:11 ` [PATCH v2 3/4] tpm: seal/unseal for TPM 2.0 Jarkko Sakkinen
2015-10-13  8:11 ` [PATCH v2 4/4] keys, trusted: seal/unseal with TPM 2.0 chips Jarkko Sakkinen
2015-10-13  8:53 ` [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
2015-10-13 17:41 ` Jason Gunthorpe
2015-10-13 19:25   ` Jarkko Sakkinen
2015-10-16 16:21 ` David Howells
2015-10-16 18:30   ` Jarkko Sakkinen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).