Skip to content

Commit

Permalink
tpm: Lazily flush the auth session
Browse files Browse the repository at this point in the history
[ Upstream commit df745e2 ]

Move the allocation of chip->auth to tpm2_start_auth_session() so that this
field can be used as flag to tell whether auth session is active or not.

Instead of flushing and reloading the auth session for every transaction
separately, keep the session open unless /dev/tpm0 is used.

Reported-by: Pengyu Ma <mapengyu@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219229
Cc: stable@vger.kernel.org # v6.10+
Fixes: 7ca110f ("tpm: Address !chip->auth in tpm_buf_append_hmac_session*()")
Tested-by: Pengyu Ma <mapengyu@gmail.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
jarkkojs authored and gregkh committed Nov 8, 2024
1 parent ddb0615 commit e693eb0
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 20 deletions.
10 changes: 10 additions & 0 deletions drivers/char/tpm/tpm-chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,16 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
*/
void tpm_chip_unregister(struct tpm_chip *chip)
{
#ifdef CONFIG_TCG_TPM2_HMAC
int rc;

rc = tpm_try_get_ops(chip);
if (!rc) {
tpm2_end_auth_session(chip);
tpm_put_ops(chip);
}
#endif

tpm_del_legacy_sysfs(chip);
if (tpm_is_hwrng_enabled(chip))
hwrng_unregister(&chip->hwrng);
Expand Down
3 changes: 3 additions & 0 deletions drivers/char/tpm/tpm-dev-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space,
struct tpm_header *header = (void *)buf;
ssize_t ret, len;

if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_end_auth_session(chip);

ret = tpm2_prepare_space(chip, space, buf, bufsiz);
/* If the command is not implemented by the TPM, synthesize a
* response with a TPM2_RC_COMMAND_CODE return for user-space.
Expand Down
6 changes: 4 additions & 2 deletions drivers/char/tpm/tpm-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,10 +379,12 @@ int tpm_pm_suspend(struct device *dev)

rc = tpm_try_get_ops(chip);
if (!rc) {
if (chip->flags & TPM_CHIP_FLAG_TPM2)
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
tpm2_end_auth_session(chip);
tpm2_shutdown(chip, TPM2_SU_STATE);
else
} else {
rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
}

tpm_put_ops(chip);
}
Expand Down
45 changes: 27 additions & 18 deletions drivers/char/tpm/tpm2-sessions.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,9 @@ void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
}

#ifdef CONFIG_TCG_TPM2_HMAC
/* The first write to /dev/tpm{rm0} will flush the session. */
attributes |= TPM2_SA_CONTINUE_SESSION;

/*
* The Architecture Guide requires us to strip trailing zeros
* before computing the HMAC
Expand Down Expand Up @@ -484,7 +487,8 @@ static void tpm2_KDFe(u8 z[EC_PT_SZ], const char *str, u8 *pt_u, u8 *pt_v,
sha256_final(&sctx, out);
}

static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip)
static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
struct tpm2_auth *auth)
{
struct crypto_kpp *kpp;
struct kpp_request *req;
Expand Down Expand Up @@ -543,7 +547,7 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip)
sg_set_buf(&s[0], chip->null_ec_key_x, EC_PT_SZ);
sg_set_buf(&s[1], chip->null_ec_key_y, EC_PT_SZ);
kpp_request_set_input(req, s, EC_PT_SZ*2);
sg_init_one(d, chip->auth->salt, EC_PT_SZ);
sg_init_one(d, auth->salt, EC_PT_SZ);
kpp_request_set_output(req, d, EC_PT_SZ);
crypto_kpp_compute_shared_secret(req);
kpp_request_free(req);
Expand All @@ -554,8 +558,7 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip)
* This works because KDFe fully consumes the secret before it
* writes the salt
*/
tpm2_KDFe(chip->auth->salt, "SECRET", x, chip->null_ec_key_x,
chip->auth->salt);
tpm2_KDFe(auth->salt, "SECRET", x, chip->null_ec_key_x, auth->salt);

out:
crypto_free_kpp(kpp);
Expand Down Expand Up @@ -853,7 +856,9 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
if (rc)
/* manually close the session if it wasn't consumed */
tpm2_flush_context(chip, auth->handle);
memzero_explicit(auth, sizeof(*auth));

kfree_sensitive(auth);
chip->auth = NULL;
} else {
/* reset for next use */
auth->session = TPM_HEADER_SIZE;
Expand Down Expand Up @@ -881,7 +886,8 @@ void tpm2_end_auth_session(struct tpm_chip *chip)
return;

tpm2_flush_context(chip, auth->handle);
memzero_explicit(auth, sizeof(*auth));
kfree_sensitive(auth);
chip->auth = NULL;
}
EXPORT_SYMBOL(tpm2_end_auth_session);

Expand Down Expand Up @@ -962,16 +968,20 @@ static int tpm2_load_null(struct tpm_chip *chip, u32 *null_key)
*/
int tpm2_start_auth_session(struct tpm_chip *chip)
{
struct tpm2_auth *auth;
struct tpm_buf buf;
struct tpm2_auth *auth = chip->auth;
int rc;
u32 null_key;
int rc;

if (!auth) {
dev_warn_once(&chip->dev, "auth session is not active\n");
if (chip->auth) {
dev_warn_once(&chip->dev, "auth session is active\n");
return 0;
}

auth = kzalloc(sizeof(*auth), GFP_KERNEL);
if (!auth)
return -ENOMEM;

rc = tpm2_load_null(chip, &null_key);
if (rc)
goto out;
Expand All @@ -992,7 +1002,7 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
tpm_buf_append(&buf, auth->our_nonce, sizeof(auth->our_nonce));

/* append encrypted salt and squirrel away unencrypted in auth */
tpm_buf_append_salt(&buf, chip);
tpm_buf_append_salt(&buf, chip, auth);
/* session type (HMAC, audit or policy) */
tpm_buf_append_u8(&buf, TPM2_SE_HMAC);

Expand All @@ -1014,10 +1024,13 @@ int tpm2_start_auth_session(struct tpm_chip *chip)

tpm_buf_destroy(&buf);

if (rc)
goto out;
if (rc == TPM2_RC_SUCCESS) {
chip->auth = auth;
return 0;
}

out:
out:
kfree_sensitive(auth);
return rc;
}
EXPORT_SYMBOL(tpm2_start_auth_session);
Expand Down Expand Up @@ -1367,10 +1380,6 @@ int tpm2_sessions_init(struct tpm_chip *chip)
return rc;
}

chip->auth = kmalloc(sizeof(*chip->auth), GFP_KERNEL);
if (!chip->auth)
return -ENOMEM;

return rc;
}
EXPORT_SYMBOL(tpm2_sessions_init);
Expand Down

0 comments on commit e693eb0

Please sign in to comment.