Commit 8c657a05 authored by Jarkko Sakkinen's avatar Jarkko Sakkinen

KEYS: trusted: Reserve TPM for seal and unseal operations

When TPM 2.0 trusted keys code was moved to the trusted keys subsystem,
the operations were unwrapped from tpm_try_get_ops() and tpm_put_ops(),
which are used to take temporarily the ownership of the TPM chip. The
ownership is only taken inside tpm_send(), but this is not sufficient,
as in the key load TPM2_CC_LOAD, TPM2_CC_UNSEAL and TPM2_FLUSH_CONTEXT
need to be done as a one single atom.

Take the TPM chip ownership before sending anything with
tpm_try_get_ops() and tpm_put_ops(), and use tpm_transmit_cmd() to send
TPM commands instead of tpm_send(), reverting back to the old behaviour.

Fixes: 2e19e101 ("KEYS: trusted: Move TPM2 trusted keys code")
Reported-by: default avatar"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: stable@vger.kernel.org
Cc: David Howells <dhowells@redhat.com>
Cc: Mimi Zohar <zohar@linux.ibm.com>
Cc: Sumit Garg <sumit.garg@linaro.org>
Acked-by Sumit Garg <sumit.garg@linaro.org>
Tested-by: default avatarMimi Zohar <zohar@linux.ibm.com>
Signed-off-by: default avatarJarkko Sakkinen <jarkko@kernel.org>
parent 8da7520c
...@@ -164,8 +164,6 @@ extern const struct file_operations tpmrm_fops; ...@@ -164,8 +164,6 @@ extern const struct file_operations tpmrm_fops;
extern struct idr dev_nums_idr; extern struct idr dev_nums_idr;
ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz); ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz);
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf,
size_t min_rsp_body_length, const char *desc);
int tpm_get_timeouts(struct tpm_chip *); int tpm_get_timeouts(struct tpm_chip *);
int tpm_auto_startup(struct tpm_chip *chip); int tpm_auto_startup(struct tpm_chip *chip);
...@@ -194,8 +192,6 @@ static inline void tpm_msleep(unsigned int delay_msec) ...@@ -194,8 +192,6 @@ static inline void tpm_msleep(unsigned int delay_msec)
int tpm_chip_start(struct tpm_chip *chip); int tpm_chip_start(struct tpm_chip *chip);
void tpm_chip_stop(struct tpm_chip *chip); void tpm_chip_stop(struct tpm_chip *chip);
struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip); struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip);
__must_check int tpm_try_get_ops(struct tpm_chip *chip);
void tpm_put_ops(struct tpm_chip *chip);
struct tpm_chip *tpm_chip_alloc(struct device *dev, struct tpm_chip *tpm_chip_alloc(struct device *dev,
const struct tpm_class_ops *ops); const struct tpm_class_ops *ops);
......
...@@ -404,6 +404,10 @@ static inline u32 tpm2_rc_value(u32 rc) ...@@ -404,6 +404,10 @@ static inline u32 tpm2_rc_value(u32 rc)
#if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)
extern int tpm_is_tpm2(struct tpm_chip *chip); extern int tpm_is_tpm2(struct tpm_chip *chip);
extern __must_check int tpm_try_get_ops(struct tpm_chip *chip);
extern void tpm_put_ops(struct tpm_chip *chip);
extern ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf,
size_t min_rsp_body_length, const char *desc);
extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
struct tpm_digest *digest); struct tpm_digest *digest);
extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
...@@ -417,7 +421,6 @@ static inline int tpm_is_tpm2(struct tpm_chip *chip) ...@@ -417,7 +421,6 @@ static inline int tpm_is_tpm2(struct tpm_chip *chip)
{ {
return -ENODEV; return -ENODEV;
} }
static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx,
struct tpm_digest *digest) struct tpm_digest *digest)
{ {
......
...@@ -83,6 +83,12 @@ int tpm2_seal_trusted(struct tpm_chip *chip, ...@@ -83,6 +83,12 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
if (rc) if (rc)
return rc; return rc;
rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
if (rc) {
tpm_put_ops(chip);
return rc;
}
tpm_buf_append_u32(&buf, options->keyhandle); tpm_buf_append_u32(&buf, options->keyhandle);
tpm2_buf_append_auth(&buf, TPM2_RS_PW, tpm2_buf_append_auth(&buf, TPM2_RS_PW,
NULL /* nonce */, 0, NULL /* nonce */, 0,
...@@ -130,7 +136,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, ...@@ -130,7 +136,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
goto out; goto out;
} }
rc = tpm_send(chip, buf.data, tpm_buf_length(&buf)); rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
if (rc) if (rc)
goto out; goto out;
...@@ -157,6 +163,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, ...@@ -157,6 +163,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
rc = -EPERM; rc = -EPERM;
} }
tpm_put_ops(chip);
return rc; return rc;
} }
...@@ -211,7 +218,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip, ...@@ -211,7 +218,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
goto out; goto out;
} }
rc = tpm_send(chip, buf.data, tpm_buf_length(&buf)); rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob");
if (!rc) if (!rc)
*blob_handle = be32_to_cpup( *blob_handle = be32_to_cpup(
(__be32 *) &buf.data[TPM_HEADER_SIZE]); (__be32 *) &buf.data[TPM_HEADER_SIZE]);
...@@ -260,7 +267,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, ...@@ -260,7 +267,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
options->blobauth /* hmac */, options->blobauth /* hmac */,
TPM_DIGEST_SIZE); TPM_DIGEST_SIZE);
rc = tpm_send(chip, buf.data, tpm_buf_length(&buf)); rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing");
if (rc > 0) if (rc > 0)
rc = -EPERM; rc = -EPERM;
...@@ -304,12 +311,19 @@ int tpm2_unseal_trusted(struct tpm_chip *chip, ...@@ -304,12 +311,19 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
u32 blob_handle; u32 blob_handle;
int rc; int rc;
rc = tpm2_load_cmd(chip, payload, options, &blob_handle); rc = tpm_try_get_ops(chip);
if (rc) if (rc)
return rc; return rc;
rc = tpm2_load_cmd(chip, payload, options, &blob_handle);
if (rc)
goto out;
rc = tpm2_unseal_cmd(chip, payload, options, blob_handle); rc = tpm2_unseal_cmd(chip, payload, options, blob_handle);
tpm2_flush_context(chip, blob_handle); tpm2_flush_context(chip, blob_handle);
out:
tpm_put_ops(chip);
return rc; return rc;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment