diff mbox series

[21/23] TPMLIB: Implement call to TPM_LoadKey2

Message ID 153486715192.13066.16960521772592007978.stgit@warthog.procyon.org.uk (mailing list archive)
State New, archived
Headers show
Series [01/23] TPM: Add new TPMs to the tail of the list to prevent inadvertent change of dev | expand

Commit Message

David Howells Aug. 21, 2018, 3:59 p.m. UTC
Implement a function to invoke TPM_LoadKey2

Signed-off-by: David Howells <dhowells@redhat.com>
---

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

Patch

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,