Skip to content

Commit

Permalink
KEYS: trusted: Reserve TPM for seal and unseal operations
Browse files Browse the repository at this point in the history
commit 8c657a0 upstream.

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: 2e19e10 ("KEYS: trusted: Move TPM2 trusted keys code")
Reported-by: "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: Mimi Zohar <zohar@linux.ibm.com>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
jarkkojs authored and gregkh committed Mar 4, 2021
1 parent f5166d9 commit 498b8fc
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 9 deletions.
4 changes: 0 additions & 4 deletions drivers/char/tpm/tpm.h
Expand Up @@ -164,8 +164,6 @@ extern const struct file_operations tpmrm_fops;
extern struct idr dev_nums_idr;

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_auto_startup(struct tpm_chip *chip);

Expand Down Expand Up @@ -194,8 +192,6 @@ static inline void tpm_msleep(unsigned int delay_msec)
int tpm_chip_start(struct tpm_chip *chip);
void tpm_chip_stop(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,
const struct tpm_class_ops *ops);
Expand Down
5 changes: 4 additions & 1 deletion include/linux/tpm.h
Expand Up @@ -397,6 +397,10 @@ static inline u32 tpm2_rc_value(u32 rc)
#if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)

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,
struct tpm_digest *digest);
extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
Expand All @@ -410,7 +414,6 @@ static inline int tpm_is_tpm2(struct tpm_chip *chip)
{
return -ENODEV;
}

static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx,
struct tpm_digest *digest)
{
Expand Down
22 changes: 18 additions & 4 deletions security/keys/trusted-keys/trusted_tpm2.c
Expand Up @@ -83,6 +83,12 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
if (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);
tpm2_buf_append_auth(&buf, TPM2_RS_PW,
NULL /* nonce */, 0,
Expand Down Expand Up @@ -130,7 +136,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
goto out;
}

rc = tpm_send(chip, buf.data, tpm_buf_length(&buf));
rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
if (rc)
goto out;

Expand All @@ -157,6 +163,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
rc = -EPERM;
}

tpm_put_ops(chip);
return rc;
}

Expand Down Expand Up @@ -211,7 +218,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
goto out;
}

rc = tpm_send(chip, buf.data, tpm_buf_length(&buf));
rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob");
if (!rc)
*blob_handle = be32_to_cpup(
(__be32 *) &buf.data[TPM_HEADER_SIZE]);
Expand Down Expand Up @@ -260,7 +267,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
options->blobauth /* hmac */,
TPM_DIGEST_SIZE);

rc = tpm_send(chip, buf.data, tpm_buf_length(&buf));
rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing");
if (rc > 0)
rc = -EPERM;

Expand Down Expand Up @@ -304,12 +311,19 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
u32 blob_handle;
int rc;

rc = tpm2_load_cmd(chip, payload, options, &blob_handle);
rc = tpm_try_get_ops(chip);
if (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);
tpm2_flush_context(chip, blob_handle);

out:
tpm_put_ops(chip);

return rc;
}

0 comments on commit 498b8fc

Please sign in to comment.