Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tpm: Lazily flush the auth session

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: 7ca110f2679b ("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>

+44 -20
+10
drivers/char/tpm/tpm-chip.c
··· 674 674 */ 675 675 void tpm_chip_unregister(struct tpm_chip *chip) 676 676 { 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 + 677 687 tpm_del_legacy_sysfs(chip); 678 688 if (tpm_is_hwrng_enabled(chip)) 679 689 hwrng_unregister(&chip->hwrng);
+3
drivers/char/tpm/tpm-dev-common.c
··· 27 27 struct tpm_header *header = (void *)buf; 28 28 ssize_t ret, len; 29 29 30 + if (chip->flags & TPM_CHIP_FLAG_TPM2) 31 + tpm2_end_auth_session(chip); 32 + 30 33 ret = tpm2_prepare_space(chip, space, buf, bufsiz); 31 34 /* If the command is not implemented by the TPM, synthesize a 32 35 * response with a TPM2_RC_COMMAND_CODE return for user-space.
+4 -2
drivers/char/tpm/tpm-interface.c
··· 379 379 380 380 rc = tpm_try_get_ops(chip); 381 381 if (!rc) { 382 - if (chip->flags & TPM_CHIP_FLAG_TPM2) 382 + if (chip->flags & TPM_CHIP_FLAG_TPM2) { 383 + tpm2_end_auth_session(chip); 383 384 tpm2_shutdown(chip, TPM2_SU_STATE); 384 - else 385 + } else { 385 386 rc = tpm1_pm_suspend(chip, tpm_suspend_pcr); 387 + } 386 388 387 389 tpm_put_ops(chip); 388 390 }
+27 -18
drivers/char/tpm/tpm2-sessions.c
··· 333 333 } 334 334 335 335 #ifdef CONFIG_TCG_TPM2_HMAC 336 + /* The first write to /dev/tpm{rm0} will flush the session. */ 337 + attributes |= TPM2_SA_CONTINUE_SESSION; 338 + 336 339 /* 337 340 * The Architecture Guide requires us to strip trailing zeros 338 341 * before computing the HMAC ··· 487 484 sha256_final(&sctx, out); 488 485 } 489 486 490 - static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip) 487 + static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip, 488 + struct tpm2_auth *auth) 491 489 { 492 490 struct crypto_kpp *kpp; 493 491 struct kpp_request *req; ··· 547 543 sg_set_buf(&s[0], chip->null_ec_key_x, EC_PT_SZ); 548 544 sg_set_buf(&s[1], chip->null_ec_key_y, EC_PT_SZ); 549 545 kpp_request_set_input(req, s, EC_PT_SZ*2); 550 - sg_init_one(d, chip->auth->salt, EC_PT_SZ); 546 + sg_init_one(d, auth->salt, EC_PT_SZ); 551 547 kpp_request_set_output(req, d, EC_PT_SZ); 552 548 crypto_kpp_compute_shared_secret(req); 553 549 kpp_request_free(req); ··· 558 554 * This works because KDFe fully consumes the secret before it 559 555 * writes the salt 560 556 */ 561 - tpm2_KDFe(chip->auth->salt, "SECRET", x, chip->null_ec_key_x, 562 - chip->auth->salt); 557 + tpm2_KDFe(auth->salt, "SECRET", x, chip->null_ec_key_x, auth->salt); 563 558 564 559 out: 565 560 crypto_free_kpp(kpp); ··· 856 853 if (rc) 857 854 /* manually close the session if it wasn't consumed */ 858 855 tpm2_flush_context(chip, auth->handle); 859 - memzero_explicit(auth, sizeof(*auth)); 856 + 857 + kfree_sensitive(auth); 858 + chip->auth = NULL; 860 859 } else { 861 860 /* reset for next use */ 862 861 auth->session = TPM_HEADER_SIZE; ··· 886 881 return; 887 882 888 883 tpm2_flush_context(chip, auth->handle); 889 - memzero_explicit(auth, sizeof(*auth)); 884 + kfree_sensitive(auth); 885 + chip->auth = NULL; 890 886 } 891 887 EXPORT_SYMBOL(tpm2_end_auth_session); 892 888 ··· 968 962 */ 969 963 int tpm2_start_auth_session(struct tpm_chip *chip) 970 964 { 965 + struct tpm2_auth *auth; 971 966 struct tpm_buf buf; 972 - struct tpm2_auth *auth = chip->auth; 973 - int rc; 974 967 u32 null_key; 968 + int rc; 975 969 976 - if (!auth) { 977 - dev_warn_once(&chip->dev, "auth session is not active\n"); 970 + if (chip->auth) { 971 + dev_warn_once(&chip->dev, "auth session is active\n"); 978 972 return 0; 979 973 } 974 + 975 + auth = kzalloc(sizeof(*auth), GFP_KERNEL); 976 + if (!auth) 977 + return -ENOMEM; 980 978 981 979 rc = tpm2_load_null(chip, &null_key); 982 980 if (rc) ··· 1002 992 tpm_buf_append(&buf, auth->our_nonce, sizeof(auth->our_nonce)); 1003 993 1004 994 /* append encrypted salt and squirrel away unencrypted in auth */ 1005 - tpm_buf_append_salt(&buf, chip); 995 + tpm_buf_append_salt(&buf, chip, auth); 1006 996 /* session type (HMAC, audit or policy) */ 1007 997 tpm_buf_append_u8(&buf, TPM2_SE_HMAC); 1008 998 ··· 1024 1014 1025 1015 tpm_buf_destroy(&buf); 1026 1016 1027 - if (rc) 1028 - goto out; 1017 + if (rc == TPM2_RC_SUCCESS) { 1018 + chip->auth = auth; 1019 + return 0; 1020 + } 1029 1021 1030 - out: 1022 + out: 1023 + kfree_sensitive(auth); 1031 1024 return rc; 1032 1025 } 1033 1026 EXPORT_SYMBOL(tpm2_start_auth_session); ··· 1379 1366 dev_err(&chip->dev, "null key creation failed with %d\n", rc); 1380 1367 return rc; 1381 1368 } 1382 - 1383 - chip->auth = kmalloc(sizeof(*chip->auth), GFP_KERNEL); 1384 - if (!chip->auth) 1385 - return -ENOMEM; 1386 1369 1387 1370 return rc; 1388 1371 }