Skip to content

Commit d5b2ee0

Browse files
committed
Merge tag 'tpmdd-next-6.12-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd
Pull tpm fix from Jarkko Sakkinen: "Address a significant boot-time delay issue" Link: https://bugzilla.kernel.org/show_bug.cgi?id=219229 * tag 'tpmdd-next-6.12-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd: tpm: Lazily flush the auth session tpm: Rollback tpm2_load_null() tpm: Return tpm2_sessions_init() when null key creation fails
2 parents e42b1a9 + df745e2 commit d5b2ee0

File tree

4 files changed

+77
-42
lines changed

4 files changed

+77
-42
lines changed

drivers/char/tpm/tpm-chip.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,16 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
674674
*/
675675
void tpm_chip_unregister(struct tpm_chip *chip)
676676
{
677+
#ifdef CONFIG_TCG_TPM2_HMAC
678+
int rc;
679+
680+
rc = tpm_try_get_ops(chip);
681+
if (!rc) {
682+
tpm2_end_auth_session(chip);
683+
tpm_put_ops(chip);
684+
}
685+
#endif
686+
677687
tpm_del_legacy_sysfs(chip);
678688
if (tpm_is_hwrng_enabled(chip))
679689
hwrng_unregister(&chip->hwrng);

drivers/char/tpm/tpm-dev-common.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space,
2727
struct tpm_header *header = (void *)buf;
2828
ssize_t ret, len;
2929

30+
if (chip->flags & TPM_CHIP_FLAG_TPM2)
31+
tpm2_end_auth_session(chip);
32+
3033
ret = tpm2_prepare_space(chip, space, buf, bufsiz);
3134
/* If the command is not implemented by the TPM, synthesize a
3235
* response with a TPM2_RC_COMMAND_CODE return for user-space.

drivers/char/tpm/tpm-interface.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,10 +379,12 @@ int tpm_pm_suspend(struct device *dev)
379379

380380
rc = tpm_try_get_ops(chip);
381381
if (!rc) {
382-
if (chip->flags & TPM_CHIP_FLAG_TPM2)
382+
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
383+
tpm2_end_auth_session(chip);
383384
tpm2_shutdown(chip, TPM2_SU_STATE);
384-
else
385+
} else {
385386
rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
387+
}
386388

387389
tpm_put_ops(chip);
388390
}

drivers/char/tpm/tpm2-sessions.c

Lines changed: 60 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
333333
}
334334

335335
#ifdef CONFIG_TCG_TPM2_HMAC
336+
/* The first write to /dev/tpm{rm0} will flush the session. */
337+
attributes |= TPM2_SA_CONTINUE_SESSION;
338+
336339
/*
337340
* The Architecture Guide requires us to strip trailing zeros
338341
* before computing the HMAC
@@ -484,7 +487,8 @@ static void tpm2_KDFe(u8 z[EC_PT_SZ], const char *str, u8 *pt_u, u8 *pt_v,
484487
sha256_final(&sctx, out);
485488
}
486489

487-
static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip)
490+
static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
491+
struct tpm2_auth *auth)
488492
{
489493
struct crypto_kpp *kpp;
490494
struct kpp_request *req;
@@ -543,7 +547,7 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip)
543547
sg_set_buf(&s[0], chip->null_ec_key_x, EC_PT_SZ);
544548
sg_set_buf(&s[1], chip->null_ec_key_y, EC_PT_SZ);
545549
kpp_request_set_input(req, s, EC_PT_SZ*2);
546-
sg_init_one(d, chip->auth->salt, EC_PT_SZ);
550+
sg_init_one(d, auth->salt, EC_PT_SZ);
547551
kpp_request_set_output(req, d, EC_PT_SZ);
548552
crypto_kpp_compute_shared_secret(req);
549553
kpp_request_free(req);
@@ -554,8 +558,7 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip)
554558
* This works because KDFe fully consumes the secret before it
555559
* writes the salt
556560
*/
557-
tpm2_KDFe(chip->auth->salt, "SECRET", x, chip->null_ec_key_x,
558-
chip->auth->salt);
561+
tpm2_KDFe(auth->salt, "SECRET", x, chip->null_ec_key_x, auth->salt);
559562

560563
out:
561564
crypto_free_kpp(kpp);
@@ -853,7 +856,9 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
853856
if (rc)
854857
/* manually close the session if it wasn't consumed */
855858
tpm2_flush_context(chip, auth->handle);
856-
memzero_explicit(auth, sizeof(*auth));
859+
860+
kfree_sensitive(auth);
861+
chip->auth = NULL;
857862
} else {
858863
/* reset for next use */
859864
auth->session = TPM_HEADER_SIZE;
@@ -881,7 +886,8 @@ void tpm2_end_auth_session(struct tpm_chip *chip)
881886
return;
882887

883888
tpm2_flush_context(chip, auth->handle);
884-
memzero_explicit(auth, sizeof(*auth));
889+
kfree_sensitive(auth);
890+
chip->auth = NULL;
885891
}
886892
EXPORT_SYMBOL(tpm2_end_auth_session);
887893

@@ -915,33 +921,37 @@ static int tpm2_parse_start_auth_session(struct tpm2_auth *auth,
915921

916922
static int tpm2_load_null(struct tpm_chip *chip, u32 *null_key)
917923
{
918-
int rc;
919924
unsigned int offset = 0; /* dummy offset for null seed context */
920925
u8 name[SHA256_DIGEST_SIZE + 2];
926+
u32 tmp_null_key;
927+
int rc;
921928

922929
rc = tpm2_load_context(chip, chip->null_key_context, &offset,
923-
null_key);
924-
if (rc != -EINVAL)
925-
return rc;
930+
&tmp_null_key);
931+
if (rc != -EINVAL) {
932+
if (!rc)
933+
*null_key = tmp_null_key;
934+
goto err;
935+
}
926936

927-
/* an integrity failure may mean the TPM has been reset */
928-
dev_err(&chip->dev, "NULL key integrity failure!\n");
929-
/* check the null name against what we know */
930-
tpm2_create_primary(chip, TPM2_RH_NULL, NULL, name);
931-
if (memcmp(name, chip->null_key_name, sizeof(name)) == 0)
932-
/* name unchanged, assume transient integrity failure */
933-
return rc;
934-
/*
935-
* Fatal TPM failure: the NULL seed has actually changed, so
936-
* the TPM must have been illegally reset. All in-kernel TPM
937-
* operations will fail because the NULL primary can't be
938-
* loaded to salt the sessions, but disable the TPM anyway so
939-
* userspace programmes can't be compromised by it.
940-
*/
941-
dev_err(&chip->dev, "NULL name has changed, disabling TPM due to interference\n");
937+
/* Try to re-create null key, given the integrity failure: */
938+
rc = tpm2_create_primary(chip, TPM2_RH_NULL, &tmp_null_key, name);
939+
if (rc)
940+
goto err;
941+
942+
/* Return null key if the name has not been changed: */
943+
if (!memcmp(name, chip->null_key_name, sizeof(name))) {
944+
*null_key = tmp_null_key;
945+
return 0;
946+
}
947+
948+
/* Deduce from the name change TPM interference: */
949+
dev_err(&chip->dev, "null key integrity check failed\n");
950+
tpm2_flush_context(chip, tmp_null_key);
942951
chip->flags |= TPM_CHIP_FLAG_DISABLE;
943952

944-
return rc;
953+
err:
954+
return rc ? -ENODEV : 0;
945955
}
946956

947957
/**
@@ -958,16 +968,20 @@ static int tpm2_load_null(struct tpm_chip *chip, u32 *null_key)
958968
*/
959969
int tpm2_start_auth_session(struct tpm_chip *chip)
960970
{
971+
struct tpm2_auth *auth;
961972
struct tpm_buf buf;
962-
struct tpm2_auth *auth = chip->auth;
963-
int rc;
964973
u32 null_key;
974+
int rc;
965975

966-
if (!auth) {
967-
dev_warn_once(&chip->dev, "auth session is not active\n");
976+
if (chip->auth) {
977+
dev_warn_once(&chip->dev, "auth session is active\n");
968978
return 0;
969979
}
970980

981+
auth = kzalloc(sizeof(*auth), GFP_KERNEL);
982+
if (!auth)
983+
return -ENOMEM;
984+
971985
rc = tpm2_load_null(chip, &null_key);
972986
if (rc)
973987
goto out;
@@ -988,7 +1002,7 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
9881002
tpm_buf_append(&buf, auth->our_nonce, sizeof(auth->our_nonce));
9891003

9901004
/* append encrypted salt and squirrel away unencrypted in auth */
991-
tpm_buf_append_salt(&buf, chip);
1005+
tpm_buf_append_salt(&buf, chip, auth);
9921006
/* session type (HMAC, audit or policy) */
9931007
tpm_buf_append_u8(&buf, TPM2_SE_HMAC);
9941008

@@ -1010,10 +1024,13 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
10101024

10111025
tpm_buf_destroy(&buf);
10121026

1013-
if (rc)
1014-
goto out;
1027+
if (rc == TPM2_RC_SUCCESS) {
1028+
chip->auth = auth;
1029+
return 0;
1030+
}
10151031

1016-
out:
1032+
out:
1033+
kfree_sensitive(auth);
10171034
return rc;
10181035
}
10191036
EXPORT_SYMBOL(tpm2_start_auth_session);
@@ -1347,18 +1364,21 @@ static int tpm2_create_null_primary(struct tpm_chip *chip)
13471364
*
13481365
* Derive and context save the null primary and allocate memory in the
13491366
* struct tpm_chip for the authorizations.
1367+
*
1368+
* Return:
1369+
* * 0 - OK
1370+
* * -errno - A system error
1371+
* * TPM_RC - A TPM error
13501372
*/
13511373
int tpm2_sessions_init(struct tpm_chip *chip)
13521374
{
13531375
int rc;
13541376

13551377
rc = tpm2_create_null_primary(chip);
1356-
if (rc)
1357-
dev_err(&chip->dev, "TPM: security failed (NULL seed derivation): %d\n", rc);
1358-
1359-
chip->auth = kmalloc(sizeof(*chip->auth), GFP_KERNEL);
1360-
if (!chip->auth)
1361-
return -ENOMEM;
1378+
if (rc) {
1379+
dev_err(&chip->dev, "null key creation failed with %d\n", rc);
1380+
return rc;
1381+
}
13621382

13631383
return rc;
13641384
}

0 commit comments

Comments
 (0)