Implement a function to invoke TPM_LoadKey2

Signed-off-by: David Howells <dhowe...@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 --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
_______________________________________________
tpmdd-devel mailing list
tpmdd-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

Reply via email to