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

tpm: Disable RNG for all AMD fTPMs

The TPM RNG functionality is not necessary for entropy when the CPU
already supports the RDRAND instruction. The TPM RNG functionality
was previously disabled on a subset of AMD fTPM series, but reports
continue to show problems on some systems causing stutter root caused
to TPM RNG functionality.

Expand disabling TPM RNG use for all AMD fTPMs whether they have versions
that claim to have fixed or not. To accomplish this, move the detection
into part of the TPM CRB registration and add a flag indicating that
the TPM should opt-out of registration to hwrng.

Cc: stable@vger.kernel.org # 6.1.y+
Fixes: b006c439d58d ("hwrng: core - start hwrng kthread also for untrusted sources")
Fixes: f1324bbc4011 ("tpm: disable hwrng for fTPM on some AMD designs")
Reported-by: daniil.stas@posteo.net
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217719
Reported-by: bitlord0xff@gmail.com
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217212
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>

authored by

Mario Limonciello and committed by
Jarkko Sakkinen
554b841d 0de030b3

+33 -66
+2 -66
drivers/char/tpm/tpm-chip.c
··· 510 510 return 0; 511 511 } 512 512 513 - /* 514 - * Some AMD fTPM versions may cause stutter 515 - * https://www.amd.com/en/support/kb/faq/pa-410 516 - * 517 - * Fixes are available in two series of fTPM firmware: 518 - * 6.x.y.z series: 6.0.18.6 + 519 - * 3.x.y.z series: 3.57.y.5 + 520 - */ 521 - #ifdef CONFIG_X86 522 - static bool tpm_amd_is_rng_defective(struct tpm_chip *chip) 523 - { 524 - u32 val1, val2; 525 - u64 version; 526 - int ret; 527 - 528 - if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) 529 - return false; 530 - 531 - ret = tpm_request_locality(chip); 532 - if (ret) 533 - return false; 534 - 535 - ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val1, NULL); 536 - if (ret) 537 - goto release; 538 - if (val1 != 0x414D4400U /* AMD */) { 539 - ret = -ENODEV; 540 - goto release; 541 - } 542 - ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_1, &val1, NULL); 543 - if (ret) 544 - goto release; 545 - ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_2, &val2, NULL); 546 - 547 - release: 548 - tpm_relinquish_locality(chip); 549 - 550 - if (ret) 551 - return false; 552 - 553 - version = ((u64)val1 << 32) | val2; 554 - if ((version >> 48) == 6) { 555 - if (version >= 0x0006000000180006ULL) 556 - return false; 557 - } else if ((version >> 48) == 3) { 558 - if (version >= 0x0003005700000005ULL) 559 - return false; 560 - } else { 561 - return false; 562 - } 563 - 564 - dev_warn(&chip->dev, 565 - "AMD fTPM version 0x%llx causes system stutter; hwrng disabled\n", 566 - version); 567 - 568 - return true; 569 - } 570 - #else 571 - static inline bool tpm_amd_is_rng_defective(struct tpm_chip *chip) 572 - { 573 - return false; 574 - } 575 - #endif /* CONFIG_X86 */ 576 - 577 513 static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) 578 514 { 579 515 struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng); ··· 524 588 static int tpm_add_hwrng(struct tpm_chip *chip) 525 589 { 526 590 if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM) || tpm_is_firmware_upgrade(chip) || 527 - tpm_amd_is_rng_defective(chip)) 591 + chip->flags & TPM_CHIP_FLAG_HWRNG_DISABLED) 528 592 return 0; 529 593 530 594 snprintf(chip->hwrng_name, sizeof(chip->hwrng_name), ··· 655 719 { 656 720 tpm_del_legacy_sysfs(chip); 657 721 if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip) && 658 - !tpm_amd_is_rng_defective(chip)) 722 + !(chip->flags & TPM_CHIP_FLAG_HWRNG_DISABLED)) 659 723 hwrng_unregister(&chip->hwrng); 660 724 tpm_bios_log_teardown(chip); 661 725 if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip))
+30
drivers/char/tpm/tpm_crb.c
··· 463 463 return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; 464 464 } 465 465 466 + static int crb_check_flags(struct tpm_chip *chip) 467 + { 468 + u32 val; 469 + int ret; 470 + 471 + ret = crb_request_locality(chip, 0); 472 + if (ret) 473 + return ret; 474 + 475 + ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val, NULL); 476 + if (ret) 477 + goto release; 478 + 479 + if (val == 0x414D4400U /* AMD */) 480 + chip->flags |= TPM_CHIP_FLAG_HWRNG_DISABLED; 481 + 482 + release: 483 + crb_relinquish_locality(chip, 0); 484 + 485 + return ret; 486 + } 487 + 466 488 static const struct tpm_class_ops tpm_crb = { 467 489 .flags = TPM_OPS_AUTO_STARTUP, 468 490 .status = crb_status, ··· 821 799 dev_set_drvdata(&chip->dev, priv); 822 800 chip->acpi_dev_handle = device->handle; 823 801 chip->flags = TPM_CHIP_FLAG_TPM2; 802 + 803 + rc = tpm_chip_bootstrap(chip); 804 + if (rc) 805 + goto out; 806 + 807 + rc = crb_check_flags(chip); 808 + if (rc) 809 + goto out; 824 810 825 811 rc = tpm_chip_register(chip); 826 812
+1
include/linux/tpm.h
··· 283 283 TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED = BIT(6), 284 284 TPM_CHIP_FLAG_FIRMWARE_UPGRADE = BIT(7), 285 285 TPM_CHIP_FLAG_SUSPENDED = BIT(8), 286 + TPM_CHIP_FLAG_HWRNG_DISABLED = BIT(9), 286 287 }; 287 288 288 289 #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)