@@ -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
*
@@ -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
@@ -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,
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(+)