Export tpm2_load_context() so that the null key can be loaded as the
parent of a asymmetric TPM2 key.

Signed-off-by: Jarkko Sakkinen <jar...@kernel.org>
---
 drivers/char/tpm/tpm.h        |  2 -
 drivers/char/tpm/tpm2-cmd.c   | 77 +++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm2-space.c | 61 ---------------------------
 include/linux/tpm.h           |  2 +
 4 files changed, 79 insertions(+), 63 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 6b8b9956ba69..c9c67fe84f33 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -314,8 +314,6 @@ int tpm_devs_add(struct tpm_chip *chip);
 void tpm_devs_remove(struct tpm_chip *chip);
 int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,
                      unsigned int buf_size, unsigned int *offset);
-int tpm2_load_context(struct tpm_chip *chip, u8 *buf,
-                     unsigned int *offset, u32 *handle);
 
 void tpm_bios_log_setup(struct tpm_chip *chip);
 void tpm_bios_log_teardown(struct tpm_chip *chip);
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 0cdf892ec2a7..eb07a109e2ba 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -370,6 +370,83 @@ void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
 }
 EXPORT_SYMBOL_GPL(tpm2_flush_context);
 
+struct tpm2_context {
+       __be64 sequence;
+       __be32 saved_handle;
+       __be32 hierarchy;
+       __be16 blob_size;
+} __packed;
+
+/**
+ * tpm2_load_context() - Load TPM2 object to the TPM memory
+ * @chip:      TPM chip to use
+ * @buf:       Blob containing TPM2 object.
+ * @offset:    Output variable for the offset in @buf reached.
+ * @handle:    Output variable for the handle of the object in TPM memory.
+ *
+ * Load a blob encrypted with TPM from the memory to the TPM chip.
+ *
+ * Return:
+ * - 0 when the blob is successfully loaded to the TPM.
+ * - -EFAULT if the TPM chip itself fails.
+ * - -ENOENT if the TPM object is replayed.
+ * - -EINVAL if the TPM object is corrupted.
+ */
+int tpm2_load_context(struct tpm_chip *chip, const u8 *buf,
+                     unsigned int *offset, u32 *handle)
+{
+       struct tpm_buf tbuf;
+       struct tpm2_context *ctx;
+       unsigned int body_size;
+       int rc;
+
+       rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD);
+       if (rc)
+               return rc;
+
+       ctx = (struct tpm2_context *)&buf[*offset];
+       body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size);
+       tpm_buf_append(&tbuf, &buf[*offset], body_size);
+
+       rc = tpm_transmit_cmd(chip, &tbuf, 4, NULL);
+       if (rc < 0) {
+               dev_warn(&chip->dev, "%s: failed with a system error %d\n",
+                        __func__, rc);
+               tpm_buf_destroy(&tbuf);
+               return -EFAULT;
+       } else if (tpm2_rc_value(rc) == TPM2_RC_HANDLE ||
+                  rc == TPM2_RC_REFERENCE_H0) {
+               /*
+                * TPM_RC_HANDLE means that the session context can't
+                * be loaded because of an internal counter mismatch
+                * that makes the TPM think there might have been a
+                * replay.  This might happen if the context was saved
+                * and loaded outside the space.
+                *
+                * TPM_RC_REFERENCE_H0 means the session has been
+                * flushed outside the space
+                */
+               *handle = 0;
+               tpm_buf_destroy(&tbuf);
+               return -ENOENT;
+       } else if (tpm2_rc_value(rc) == TPM2_RC_INTEGRITY) {
+               tpm_buf_destroy(&tbuf);
+               return -EINVAL;
+       } else if (rc > 0) {
+               dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n",
+                        __func__, rc);
+               tpm_buf_destroy(&tbuf);
+               return -EFAULT;
+       }
+
+       *handle = be32_to_cpup((__be32 *)&tbuf.data[TPM_HEADER_SIZE]);
+       *offset += body_size;
+
+       tpm_buf_destroy(&tbuf);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tpm2_load_context);
+
 struct tpm2_get_cap_out {
        u8 more_data;
        __be32 subcap_id;
diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
index 4892d491da8d..708c6e4d64cd 100644
--- a/drivers/char/tpm/tpm2-space.c
+++ b/drivers/char/tpm/tpm2-space.c
@@ -21,13 +21,6 @@ enum tpm2_handle_types {
        TPM2_HT_TRANSIENT       = 0x80000000,
 };
 
-struct tpm2_context {
-       __be64 sequence;
-       __be32 saved_handle;
-       __be32 hierarchy;
-       __be16 blob_size;
-} __packed;
-
 static void tpm2_flush_sessions(struct tpm_chip *chip, struct tpm_space *space)
 {
        int i;
@@ -68,60 +61,6 @@ void tpm2_del_space(struct tpm_chip *chip, struct tpm_space 
*space)
        kfree(space->session_buf);
 }
 
-int tpm2_load_context(struct tpm_chip *chip, u8 *buf,
-                     unsigned int *offset, u32 *handle)
-{
-       struct tpm_buf tbuf;
-       struct tpm2_context *ctx;
-       unsigned int body_size;
-       int rc;
-
-       rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD);
-       if (rc)
-               return rc;
-
-       ctx = (struct tpm2_context *)&buf[*offset];
-       body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size);
-       tpm_buf_append(&tbuf, &buf[*offset], body_size);
-
-       rc = tpm_transmit_cmd(chip, &tbuf, 4, NULL);
-       if (rc < 0) {
-               dev_warn(&chip->dev, "%s: failed with a system error %d\n",
-                        __func__, rc);
-               tpm_buf_destroy(&tbuf);
-               return -EFAULT;
-       } else if (tpm2_rc_value(rc) == TPM2_RC_HANDLE ||
-                  rc == TPM2_RC_REFERENCE_H0) {
-               /*
-                * TPM_RC_HANDLE means that the session context can't
-                * be loaded because of an internal counter mismatch
-                * that makes the TPM think there might have been a
-                * replay.  This might happen if the context was saved
-                * and loaded outside the space.
-                *
-                * TPM_RC_REFERENCE_H0 means the session has been
-                * flushed outside the space
-                */
-               *handle = 0;
-               tpm_buf_destroy(&tbuf);
-               return -ENOENT;
-       } else if (tpm2_rc_value(rc) == TPM2_RC_INTEGRITY) {
-               tpm_buf_destroy(&tbuf);
-               return -EINVAL;
-       } else if (rc > 0) {
-               dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n",
-                        __func__, rc);
-               tpm_buf_destroy(&tbuf);
-               return -EFAULT;
-       }
-
-       *handle = be32_to_cpup((__be32 *)&tbuf.data[TPM_HEADER_SIZE]);
-       *offset += body_size;
-
-       tpm_buf_destroy(&tbuf);
-       return 0;
-}
-
 int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,
                      unsigned int buf_size, unsigned int *offset)
 {
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index c17e4efbb2e5..2f25ca07127b 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -466,6 +466,8 @@ extern int tpm_pcr_extend(struct tpm_chip *chip, u32 
pcr_idx,
 extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max);
 extern struct tpm_chip *tpm_default_chip(void);
 void tpm2_flush_context(struct tpm_chip *chip, u32 handle);
+int tpm2_load_context(struct tpm_chip *chip, const u8 *buf,
+                     unsigned int *offset, u32 *handle);
 
 static inline void tpm_buf_append_empty_auth(struct tpm_buf *buf, u32 handle)
 {
-- 
2.45.1


Reply via email to