linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] Basic trusted keys support for TPM 2.0
@ 2015-07-03 15:36 Jarkko Sakkinen
  2015-07-03 15:36 ` [PATCH 1/4] tpm: introduce struct tpm_buf Jarkko Sakkinen
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Jarkko Sakkinen @ 2015-07-03 15:36 UTC (permalink / raw)
  To: peterhuewe, tpmdd-devel, linux-kernel, safford
  Cc: Jarkko Sakkinen, Berg, Christopher, Jason Gunthorpe,
	open list:KEYS-TRUSTED, open list:KEYS-TRUSTED

Jarkko Sakkinen (4):
  tpm: introduce struct tpm_buf
  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 |  75 ++++++
 drivers/char/tpm/tpm.h           |  77 ++++++
 drivers/char/tpm/tpm2-cmd.c      | 489 +++++++++++++++++++++++----------------
 include/keys/trusted-type.h      |  13 ++
 include/linux/tpm.h              |  26 +++
 include/linux/tpm_command.h      |   1 -
 security/keys/trusted.c          |  18 +-
 security/keys/trusted.h          |  18 +-
 8 files changed, 496 insertions(+), 221 deletions(-)

-- 
2.1.4


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

* [PATCH 1/4] tpm: introduce struct tpm_buf
  2015-07-03 15:36 [PATCH 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
@ 2015-07-03 15:36 ` Jarkko Sakkinen
  2015-07-03 15:36 ` [PATCH 2/4] trusted: move struct trusted_key_options to trusted-type.h Jarkko Sakkinen
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Jarkko Sakkinen @ 2015-07-03 15:36 UTC (permalink / raw)
  To: peterhuewe, tpmdd-devel, linux-kernel, safford
  Cc: Jarkko Sakkinen, Marcel Selhorst, Jason Gunthorpe

This patch introduces struct tpm_buf that provides a string buffer for
constructing TPM commands. This allows to construct variable sized TPM
commands. This feature is needed for sealing and unsealing trusted keys
because the input data is of variable size.

The commands in tpm2-cmd.c have been updated to use struct tpm_buf.

The code is based in the string buffer code in security/trusted/trusted.h.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/char/tpm/tpm.h      |  64 +++++++++
 drivers/char/tpm/tpm2-cmd.c | 317 +++++++++++++++-----------------------------
 2 files changed, 173 insertions(+), 208 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f8319a0..f04afb7 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -382,6 +382,70 @@ struct tpm_cmd_t {
 	tpm_cmd_params	params;
 } __packed;
 
+/* A string buffer type for constructing TPM commands. This is based on the
+ * string buffer code in security/keys/trusted.h.
+ */
+
+#define TPM_BUF_SIZE 512
+
+struct tpm_buf {
+	u8 data[TPM_BUF_SIZE];
+} __aligned(8);
+
+static inline void tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
+{
+	struct tpm_input_header *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);
+}
+
+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 *data,
+				  unsigned int len)
+{
+	struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
+
+	BUG_ON((len + tpm_buf_length(buf)) > TPM_BUF_SIZE);
+
+	memcpy(&buf->data[tpm_buf_length(buf)], data, len);
+	head->length = cpu_to_be32(tpm_buf_length(buf) + 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;
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 011909a..edf474f 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -17,14 +17,6 @@
 
 #include "tpm.h"
 
-struct tpm2_startup_in {
-	__be16	startup_type;
-} __packed;
-
-struct tpm2_self_test_in {
-	u8	full_test;
-} __packed;
-
 struct tpm2_pcr_read_in {
 	__be32	pcr_selects_cnt;
 	__be16	hash_alg;
@@ -43,17 +35,7 @@ struct tpm2_pcr_read_out {
 	u8	digest[TPM_DIGEST_SIZE];
 } __packed;
 
-struct tpm2_null_auth_area {
-	__be32			handle;
-	__be16			nonce_size;
-	u8			attributes;
-	__be16			auth_size;
-} __packed;
-
 struct tpm2_pcr_extend_in {
-	__be32				pcr_idx;
-	__be32				auth_area_size;
-	struct tpm2_null_auth_area	auth_area;
 	__be32				digest_cnt;
 	__be16				hash_alg;
 	u8				digest[TPM_DIGEST_SIZE];
@@ -73,32 +55,11 @@ struct tpm2_get_tpm_pt_out {
 	__be32	value;
 } __packed;
 
-struct tpm2_get_random_in {
-	__be16	size;
-} __packed;
-
 struct tpm2_get_random_out {
 	__be16	size;
 	u8	buffer[TPM_MAX_RNG_DATA];
 } __packed;
 
-union tpm2_cmd_params {
-	struct	tpm2_startup_in		startup_in;
-	struct	tpm2_self_test_in	selftest_in;
-	struct	tpm2_pcr_read_in	pcrread_in;
-	struct	tpm2_pcr_read_out	pcrread_out;
-	struct	tpm2_pcr_extend_in	pcrextend_in;
-	struct	tpm2_get_tpm_pt_in	get_tpm_pt_in;
-	struct	tpm2_get_tpm_pt_out	get_tpm_pt_out;
-	struct	tpm2_get_random_in	getrandom_in;
-	struct	tpm2_get_random_out	getrandom_out;
-};
-
-struct tpm2_cmd {
-	tpm_cmd_header		header;
-	union tpm2_cmd_params	params;
-} __packed;
-
 /*
  * Array with one entry per ordinal defining the maximum amount
  * of time the chip could take to return the result. The values
@@ -221,15 +182,24 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = {
 	TPM_UNDEFINED		/* 18f */
 };
 
-#define TPM2_PCR_READ_IN_SIZE \
-	(sizeof(struct tpm_input_header) + \
-	 sizeof(struct tpm2_pcr_read_in))
+static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle,
+				 const u8 *nonce, u16 nonce_len,
+				 u8 session_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);
 
-static const struct tpm_input_header tpm2_pcrread_header = {
-	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-	.length = cpu_to_be32(TPM2_PCR_READ_IN_SIZE),
-	.ordinal = cpu_to_be32(TPM2_CC_PCR_READ)
-};
+	if (nonce)
+		tpm_buf_append(buf, nonce, nonce_len);
+
+	tpm_buf_append_u8(buf, session_attributes);
+	tpm_buf_append_u16(buf, hmac_len);
+
+	if (hmac)
+		tpm_buf_append(buf, hmac, hmac_len);
+}
 
 /**
  * tpm2_pcr_read() - read a PCR value
@@ -243,42 +213,36 @@ static const struct tpm_input_header tpm2_pcrread_header = {
  */
 int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
 {
+	struct tpm_buf buf;
+	struct tpm2_pcr_read_in in;
+	struct tpm2_pcr_read_out *out;
 	int rc;
-	struct tpm2_cmd cmd;
-	u8 *buf;
 
 	if (pcr_idx >= TPM2_PLATFORM_PCR)
 		return -EINVAL;
 
-	cmd.header.in = tpm2_pcrread_header;
-	cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1);
-	cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
-	cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN;
+	tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ);
+
+	in.pcr_selects_cnt = cpu_to_be32(1);
+	in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
+	in.pcr_select_size = TPM2_PCR_SELECT_MIN;
+	in.pcr_select[0] = 0x00;
+	in.pcr_select[1] = 0x00;
+	in.pcr_select[2] = 0x00;
+	in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
 
-	memset(cmd.params.pcrread_in.pcr_select, 0,
-	       sizeof(cmd.params.pcrread_in.pcr_select));
-	cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
+	tpm_buf_append(&buf, (u8 *) &in, sizeof(in));
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+	rc = tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE,
 			      "attempting to read a pcr value");
-	if (rc == 0) {
-		buf = cmd.params.pcrread_out.digest;
-		memcpy(res_buf, buf, TPM_DIGEST_SIZE);
-	}
+	if (rc)
+		return rc;
 
-	return rc;
+	out = (struct tpm2_pcr_read_out *) &buf.data[TPM_HEADER_SIZE];
+	memcpy(res_buf, out->digest, TPM_DIGEST_SIZE);
+	return 0;
 }
 
-#define TPM2_GET_PCREXTEND_IN_SIZE \
-	(sizeof(struct tpm_input_header) + \
-	 sizeof(struct tpm2_pcr_extend_in))
-
-static const struct tpm_input_header tpm2_pcrextend_header = {
-	.tag = cpu_to_be16(TPM2_ST_SESSIONS),
-	.length = cpu_to_be32(TPM2_GET_PCREXTEND_IN_SIZE),
-	.ordinal = cpu_to_be32(TPM2_CC_PCR_EXTEND)
-};
-
 /**
  * tpm2_pcr_extend() - extend a PCR value
  * @chip:	TPM chip to use.
@@ -291,76 +255,63 @@ static const struct tpm_input_header tpm2_pcrextend_header = {
  */
 int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
 {
-	struct tpm2_cmd cmd;
-	int rc;
-
-	cmd.header.in = tpm2_pcrextend_header;
-	cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
-	cmd.params.pcrextend_in.auth_area_size =
-		cpu_to_be32(sizeof(struct tpm2_null_auth_area));
-	cmd.params.pcrextend_in.auth_area.handle =
-		cpu_to_be32(TPM2_RS_PW);
-	cmd.params.pcrextend_in.auth_area.nonce_size = 0;
-	cmd.params.pcrextend_in.auth_area.attributes = 0;
-	cmd.params.pcrextend_in.auth_area.auth_size = 0;
-	cmd.params.pcrextend_in.digest_cnt = cpu_to_be32(1);
-	cmd.params.pcrextend_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
-	memcpy(cmd.params.pcrextend_in.digest, hash, TPM_DIGEST_SIZE);
-
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
-			      "attempting extend a PCR value");
+	struct tpm_buf buf;
+	struct tpm2_pcr_extend_in in;
 
-	return rc;
-}
+	tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND);
+	tpm_buf_append_u32(&buf, pcr_idx);
+	tpm2_buf_append_auth(&buf, TPM2_RS_PW, NULL /* nonce */, 0,
+			     0 /* session_attributes */, NULL /* hmac */, 0);
 
-#define TPM2_GETRANDOM_IN_SIZE \
-	(sizeof(struct tpm_input_header) + \
-	 sizeof(struct tpm2_get_random_in))
+	in.digest_cnt = cpu_to_be32(1);
+	in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
+	memcpy(in.digest, hash, TPM_DIGEST_SIZE);
+	tpm_buf_append(&buf, (u8 *) &in, sizeof(in));
 
-static const struct tpm_input_header tpm2_getrandom_header = {
-	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-	.length = cpu_to_be32(TPM2_GETRANDOM_IN_SIZE),
-	.ordinal = cpu_to_be32(TPM2_CC_GET_RANDOM)
-};
+	return tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE,
+				"attempting extend a PCR value");
+}
 
 /**
  * tpm2_get_random() - get random bytes from the TPM RNG
  * @chip: TPM chip to use
- * @out: destination buffer for the random bytes
+ * @res_buf: destination buffer for the random bytes
  * @max: the max number of bytes to write to @out
  *
  * 0 is returned when the operation is successful. If a negative number is
  * returned it remarks a POSIX error code. If a positive number is returned
  * it remarks a TPM error.
  */
-int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max)
+int tpm2_get_random(struct tpm_chip *chip, u8 *res_buf, size_t max)
 {
-	struct tpm2_cmd cmd;
+	struct tpm_buf buf;
+	struct tpm2_get_random_out *out;
 	u32 recd;
 	u32 num_bytes;
 	int err;
 	int total = 0;
 	int retries = 5;
-	u8 *dest = out;
+	u8 *dest = res_buf;
 
-	num_bytes = min_t(u32, max, sizeof(cmd.params.getrandom_out.buffer));
+	num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
 
-	if (!out || !num_bytes ||
-	    max > sizeof(cmd.params.getrandom_out.buffer))
+	if (!res_buf || !num_bytes || max > TPM_MAX_RNG_DATA)
 		return -EINVAL;
 
 	do {
-		cmd.header.in = tpm2_getrandom_header;
-		cmd.params.getrandom_in.size = cpu_to_be16(num_bytes);
 
-		err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+		tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_RANDOM);
+		tpm_buf_append_u16(&buf, num_bytes);
+
+		err = tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE,
 				       "attempting get random");
 		if (err)
 			break;
 
-		recd = min_t(u32, be16_to_cpu(cmd.params.getrandom_out.size),
-			     num_bytes);
-		memcpy(dest, cmd.params.getrandom_out.buffer, recd);
+		out = (struct tpm2_get_random_out *) &buf.data[TPM_HEADER_SIZE];
+
+		recd = min_t(u32, be16_to_cpu(out->size), num_bytes);
+		memcpy(dest, out->buffer, recd);
 
 		dest += recd;
 		total += recd;
@@ -370,16 +321,6 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max)
 	return total ? total : -EIO;
 }
 
-#define TPM2_GET_TPM_PT_IN_SIZE \
-	(sizeof(struct tpm_input_header) + \
-	 sizeof(struct tpm2_get_tpm_pt_in))
-
-static const struct tpm_input_header tpm2_get_tpm_pt_header = {
-	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-	.length = cpu_to_be32(TPM2_GET_TPM_PT_IN_SIZE),
-	.ordinal = cpu_to_be32(TPM2_CC_GET_CAPABILITY)
-};
-
 /**
  * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property
  * @chip:		TPM chip to use.
@@ -391,33 +332,31 @@ static const struct tpm_input_header tpm2_get_tpm_pt_header = {
  * returned it remarks a POSIX error code. If a positive number is returned
  * it remarks a TPM error.
  */
-ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,  u32 *value,
+ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value,
 			const char *desc)
 {
-	struct tpm2_cmd cmd;
+	struct tpm_buf buf;
+	struct tpm2_get_tpm_pt_in in;
+	struct tpm2_get_tpm_pt_out *out;
 	int rc;
 
-	cmd.header.in = tpm2_get_tpm_pt_header;
-	cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
-	cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id);
-	cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
+	tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), desc);
-	if (!rc)
-		*value = cmd.params.get_tpm_pt_out.value;
+	in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
+	in.property_id = cpu_to_be32(property_id);
+	in.property_cnt = cpu_to_be32(1);
 
-	return rc;
-}
+	tpm_buf_append(&buf, (u8 *) &in, sizeof(in));
 
-#define TPM2_STARTUP_IN_SIZE \
-	(sizeof(struct tpm_input_header) + \
-	 sizeof(struct tpm2_startup_in))
+	rc = tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE, desc);
+	if (!rc) {
+		out = (struct tpm2_get_tpm_pt_out *)
+			&buf.data[TPM_HEADER_SIZE];
+		*value = be32_to_cpu(out->value);
+	}
 
-static const struct tpm_input_header tpm2_startup_header = {
-	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-	.length = cpu_to_be32(TPM2_STARTUP_IN_SIZE),
-	.ordinal = cpu_to_be32(TPM2_CC_STARTUP)
-};
+	return rc;
+}
 
 /**
  * tpm2_startup() - send startup command to the TPM chip
@@ -431,26 +370,18 @@ static const struct tpm_input_header tpm2_startup_header = {
  */
 int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
 {
-	struct tpm2_cmd cmd;
+	struct tpm_buf buf;
+	int rc;
 
-	cmd.header.in = tpm2_startup_header;
+	tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
+	tpm_buf_append_u16(&buf, startup_type);
+	rc = tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE,
+			      "attempting to start the TPM");
 
-	cmd.params.startup_in.startup_type = cpu_to_be16(startup_type);
-	return tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
-				"attempting to start the TPM");
+	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm2_startup);
 
-#define TPM2_SHUTDOWN_IN_SIZE \
-	(sizeof(struct tpm_input_header) + \
-	 sizeof(struct tpm2_startup_in))
-
-static const struct tpm_input_header tpm2_shutdown_header = {
-	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-	.length = cpu_to_be32(TPM2_SHUTDOWN_IN_SIZE),
-	.ordinal = cpu_to_be32(TPM2_CC_SHUTDOWN)
-};
-
 /**
  * tpm2_shutdown() - send shutdown command to the TPM chip
  * @chip:		TPM chip to use.
@@ -459,20 +390,11 @@ static const struct tpm_input_header tpm2_shutdown_header = {
  */
 void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
 {
-	struct tpm2_cmd cmd;
-	int rc;
-
-	cmd.header.in = tpm2_shutdown_header;
-	cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
+	struct tpm_buf buf;
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), "stopping the TPM");
-
-	/* In places where shutdown command is sent there's no much we can do
-	 * except print the error code on a system failure.
-	 */
-	if (rc < 0)
-		dev_warn(chip->pdev, "transmit returned %d while stopping the TPM",
-			 rc);
+	tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN);
+	tpm_buf_append_u16(&buf, shutdown_type);
+	tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE, "stopping the TPM");
 }
 EXPORT_SYMBOL_GPL(tpm2_shutdown);
 
@@ -503,16 +425,6 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
 }
 EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration);
 
-#define TPM2_SELF_TEST_IN_SIZE \
-	(sizeof(struct tpm_input_header) + \
-	 sizeof(struct tpm2_self_test_in))
-
-static const struct tpm_input_header tpm2_selftest_header = {
-	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-	.length = cpu_to_be32(TPM2_SELF_TEST_IN_SIZE),
-	.ordinal = cpu_to_be32(TPM2_CC_SELF_TEST)
-};
-
 /**
  * tpm2_continue_selftest() - start a self test
  * @chip: TPM chip to use
@@ -525,13 +437,13 @@ static const struct tpm_input_header tpm2_selftest_header = {
  */
 static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
 {
+	struct tpm_buf buf;
 	int rc;
-	struct tpm2_cmd cmd;
 
-	cmd.header.in = tpm2_selftest_header;
-	cmd.params.selftest_in.full_test = full;
+	tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST);
+	tpm_buf_append_u8(&buf, full);
 
-	rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE,
+	rc = tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE,
 			      "continue selftest");
 
 	/* At least some prototype chips seem to give RC_TESTING error
@@ -562,11 +474,10 @@ int tpm2_do_selftest(struct tpm_chip *chip)
 	unsigned int loops;
 	unsigned int delay_msec = 100;
 	unsigned long duration;
-	struct tpm2_cmd cmd;
+	u8 dig[TPM_DIGEST_SIZE];
 	int i;
 
 	duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST);
-
 	loops = jiffies_to_msecs(duration) / delay_msec;
 
 	rc = tpm2_start_selftest(chip, true);
@@ -574,21 +485,8 @@ int tpm2_do_selftest(struct tpm_chip *chip)
 		return rc;
 
 	for (i = 0; i < loops; i++) {
-		/* Attempt to read a PCR value */
-		cmd.header.in = tpm2_pcrread_header;
-		cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1);
-		cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
-		cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN;
-		cmd.params.pcrread_in.pcr_select[0] = 0x01;
-		cmd.params.pcrread_in.pcr_select[1] = 0x00;
-		cmd.params.pcrread_in.pcr_select[2] = 0x00;
-
-		rc = tpm_transmit_cmd(chip, (u8 *) &cmd, sizeof(cmd), NULL);
-		if (rc < 0)
-			break;
-
-		rc = be32_to_cpu(cmd.header.out.return_code);
-		if (rc != TPM2_RC_TESTING)
+		rc = tpm2_pcr_read(chip, 1, dig);
+		if (rc < 0 || rc != TPM2_RC_TESTING)
 			break;
 
 		msleep(delay_msec);
@@ -624,21 +522,24 @@ EXPORT_SYMBOL_GPL(tpm2_gen_interrupt);
  */
 int tpm2_probe(struct tpm_chip *chip)
 {
-	struct tpm2_cmd cmd;
+	struct tpm_buf buf;
+	struct tpm2_get_tpm_pt_in in;
 	int rc;
 
-	cmd.header.in = tpm2_get_tpm_pt_header;
-	cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
-	cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
-	cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
+	in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
+	in.property_id = cpu_to_be32(0x100);
+	in.property_cnt = cpu_to_be32(1);
+
+	tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_CAPABILITY);
+	tpm_buf_append(&buf, (u8 *) &in, sizeof(in));
 
-	rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd));
+	rc = tpm_transmit(chip, buf.data, TPM_BUF_SIZE);
 	if (rc <  0)
 		return rc;
 	else if (rc < TPM_HEADER_SIZE)
 		return -EFAULT;
 
-	if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS)
+	if (tpm_buf_tag(&buf) == TPM2_ST_NO_SESSIONS)
 		chip->flags |= TPM_CHIP_FLAG_TPM2;
 
 	return 0;
-- 
2.1.4


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

* [PATCH 2/4] trusted: move struct trusted_key_options to trusted-type.h
  2015-07-03 15:36 [PATCH 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
  2015-07-03 15:36 ` [PATCH 1/4] tpm: introduce struct tpm_buf Jarkko Sakkinen
@ 2015-07-03 15:36 ` Jarkko Sakkinen
  2015-07-03 15:36 ` [PATCH 3/4] tpm: seal/unseal for TPM 2.0 Jarkko Sakkinen
  2015-07-03 15:36 ` [PATCH 4/4] keys, trusted: seal/unseal with TPM 2.0 chips Jarkko Sakkinen
  3 siblings, 0 replies; 6+ messages in thread
From: Jarkko Sakkinen @ 2015-07-03 15:36 UTC (permalink / raw)
  To: peterhuewe, tpmdd-devel, linux-kernel, safford
  Cc: Jarkko Sakkinen, 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 | 13 +++++++++++++
 security/keys/trusted.h     | 11 -----------
 2 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
index 56f82e5..9a2c626 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,17 @@ 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.1.4


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

* [PATCH 3/4] tpm: seal/unseal for TPM 2.0
  2015-07-03 15:36 [PATCH 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
  2015-07-03 15:36 ` [PATCH 1/4] tpm: introduce struct tpm_buf Jarkko Sakkinen
  2015-07-03 15:36 ` [PATCH 2/4] trusted: move struct trusted_key_options to trusted-type.h Jarkko Sakkinen
@ 2015-07-03 15:36 ` Jarkko Sakkinen
  2015-07-03 15:36 ` [PATCH 4/4] keys, trusted: seal/unseal with TPM 2.0 chips Jarkko Sakkinen
  3 siblings, 0 replies; 6+ messages in thread
From: Jarkko Sakkinen @ 2015-07-03 15:36 UTC (permalink / raw)
  To: peterhuewe, tpmdd-devel, linux-kernel, safford
  Cc: Jarkko Sakkinen, Marcel Selhorst, Jason Gunthorpe, Berg, Christopher

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 |  75 ++++++++++++++++
 drivers/char/tpm/tpm.h           |  13 +++
 drivers/char/tpm/tpm2-cmd.c      | 182 +++++++++++++++++++++++++++++++++++++++
 include/linux/tpm.h              |  26 ++++++
 4 files changed, 296 insertions(+)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index e85d341..6dd4c74 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -666,6 +666,29 @@ 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 1 if 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 +1044,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 f04afb7..0fa179a 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -88,6 +88,8 @@ enum tpm2_return_codes {
 
 enum tpm2_algorithms {
 	TPM2_ALG_SHA1		= 0x0004,
+	TPM2_ALG_KEYEDHASH	= 0x0008,
+	TPM2_ALG_NULL		= 0x0010
 };
 
 enum tpm2_command_codes {
@@ -95,6 +97,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,
@@ -492,6 +498,13 @@ 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 edf474f..d404e5f 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -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_pcr_read_in {
 	__be32	pcr_selects_cnt;
@@ -322,6 +327,183 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *res_buf, size_t max)
 }
 
 /**
+ * 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;
+
+	tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
+	tpm_buf_append_u32(&buf, options->keyhandle);
+	tpm2_buf_append_auth(&buf, TPM2_RS_PW, NULL /* nonce */, 0,
+			     0 /* session_attributes */, NULL /* hmac */, 0);
+
+	/* 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_SHA1);
+	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);
+
+	rc = tpm_transmit_cmd(chip, buf.data, TPM_BUF_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:
+	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;
+
+	pr_info("private_len=%u\n", private_len);
+
+	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;
+
+	pr_info("public_len=%u\n", public_len);
+
+	tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
+	tpm_buf_append_u32(&buf, options->keyhandle);
+	tpm2_buf_append_auth(&buf, TPM2_RS_PW, NULL /* nonce */, 0,
+			     0 /* session_attributes */, NULL /* hmac */, 0);
+
+	tpm_buf_append(&buf, payload->blob, payload->blob_len);
+
+	rc = tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE, "loading blob");
+	if (!rc)
+		*blob_handle = be32_to_cpup(
+			(__be32 *) &buf.data[TPM_HEADER_SIZE]);
+
+	if (rc > 0)
+		rc = -EPERM;
+
+	return rc;
+}
+
+static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
+{
+	struct tpm_buf buf;
+	int rc;
+
+	tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
+	tpm_buf_append_u32(&buf, handle);
+
+	rc = tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE, "flushing context");
+	if (rc)
+		dev_warn(chip->pdev, "0x%08x was not flushed\n", handle);
+}
+
+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;
+
+	tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
+	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, TPM_BUF_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);
+	}
+
+	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/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.1.4


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

* [PATCH 4/4] keys, trusted: seal/unseal with TPM 2.0 chips
  2015-07-03 15:36 [PATCH 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
                   ` (2 preceding siblings ...)
  2015-07-03 15:36 ` [PATCH 3/4] tpm: seal/unseal for TPM 2.0 Jarkko Sakkinen
@ 2015-07-03 15:36 ` Jarkko Sakkinen
  3 siblings, 0 replies; 6+ messages in thread
From: Jarkko Sakkinen @ 2015-07-03 15:36 UTC (permalink / raw)
  To: peterhuewe, tpmdd-devel, linux-kernel, safford
  Cc: Jarkko Sakkinen, Marcel Selhorst, Jason Gunthorpe, 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>
---
 drivers/char/tpm/tpm2-cmd.c |  6 +-----
 include/linux/tpm_command.h |  1 -
 security/keys/trusted.c     | 18 ++++++++++++++----
 security/keys/trusted.h     |  7 +++++++
 4 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index d404e5f..d2bcf79 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -406,21 +406,17 @@ static int tpm2_load(struct tpm_chip *chip,
 	if (private_len > (payload->blob_len - 2))
 		return -E2BIG;
 
-	pr_info("private_len=%u\n", private_len);
-
 	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;
 
-	pr_info("public_len=%u\n", public_len);
-
 	tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
 	tpm_buf_append_u32(&buf, options->keyhandle);
 	tpm2_buf_append_auth(&buf, TPM2_RS_PW, NULL /* nonce */, 0,
 			     0 /* session_attributes */, NULL /* hmac */, 0);
 
-	tpm_buf_append(&buf, payload->blob, payload->blob_len);
+	tpm_buf_append(&buf, payload->blob, blob_len);
 
 	rc = tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE, "loading blob");
 	if (!rc)
diff --git a/include/linux/tpm_command.h b/include/linux/tpm_command.h
index 727512e..d7b0f82 100644
--- a/include/linux/tpm_command.h
+++ b/include/linux/tpm_command.h
@@ -22,7 +22,6 @@
 #define TPM_ORD_UNSEAL                  24
 
 /* Other constants */
-#define SRKHANDLE                       0x40000000
 #define TPM_NONCE_SIZE                  20
 
 #endif
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index c0594cb..f6557b1 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -601,7 +601,7 @@ static int tpm_unseal(struct tpm_buf *tb,
 	}
 
 	ordinal = htonl(TPM_ORD_UNSEAL);
-	keyhndl = htonl(SRKHANDLE);
+	keyhndl = htonl(TPM1_SRKHANDLE);
 	ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE);
 	if (ret != TPM_NONCE_SIZE) {
 		pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
@@ -867,7 +867,11 @@ static struct trusted_key_options *trusted_options_alloc(void)
 	if (options) {
 		/* set any non-zero defaults */
 		options->keytype = SRK_keytype;
-		options->keyhandle = SRKHANDLE;
+
+		if (tpm_is_tpm2(TPM_ANY_NUM))
+			options->keyhandle = TPM2_SRKHANDLE;
+		else
+			options->keyhandle = TPM1_SRKHANDLE;
 	}
 	return options;
 }
@@ -937,7 +941,10 @@ static int trusted_instantiate(struct key *key,
 
 	switch (key_cmd) {
 	case Opt_load:
-		ret = key_unseal(payload, options);
+		if (tpm_is_tpm2(TPM_ANY_NUM))
+			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 +957,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 (tpm_is_tpm2(TPM_ANY_NUM))
+			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;
diff --git a/security/keys/trusted.h b/security/keys/trusted.h
index ff001a5..fc32c47 100644
--- a/security/keys/trusted.h
+++ b/security/keys/trusted.h
@@ -12,6 +12,13 @@
 #define TPM_RETURN_OFFSET		6
 #define TPM_DATA_OFFSET			10
 
+/* Transient object handles start from 0x80000000 in TPM 2.0, which makes it
+ * a sane default.
+ */
+
+#define TPM1_SRKHANDLE	0x40000000
+#define TPM2_SRKHANDLE	0x80000000
+
 #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]))
-- 
2.1.4


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

* [PATCH 2/4] trusted: move struct trusted_key_options to trusted-type.h
  2015-10-02  8:38 [PATCH 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
@ 2015-10-02  8:38 ` Jarkko Sakkinen
  0 siblings, 0 replies; 6+ messages in thread
From: Jarkko Sakkinen @ 2015-10-02  8:38 UTC (permalink / raw)
  To: tpmdd-devel, linux-kernel
  Cc: peterhuewe, gregkh, jgunthorpe, akpm, mjg59, 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 | 13 +++++++++++++
 security/keys/trusted.h     | 11 -----------
 2 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
index 56f82e5..9a2c626 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,17 @@ 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] 6+ messages in thread

end of thread, other threads:[~2015-10-02  8:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-03 15:36 [PATCH 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
2015-07-03 15:36 ` [PATCH 1/4] tpm: introduce struct tpm_buf Jarkko Sakkinen
2015-07-03 15:36 ` [PATCH 2/4] trusted: move struct trusted_key_options to trusted-type.h Jarkko Sakkinen
2015-07-03 15:36 ` [PATCH 3/4] tpm: seal/unseal for TPM 2.0 Jarkko Sakkinen
2015-07-03 15:36 ` [PATCH 4/4] keys, trusted: seal/unseal with TPM 2.0 chips Jarkko Sakkinen
2015-10-02  8:38 [PATCH 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
2015-10-02  8:38 ` [PATCH 2/4] trusted: move struct trusted_key_options to trusted-type.h 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).