@@ -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);
@@ -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;
@@ -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)
{
@@ -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)
{
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 <jarkko@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(-)