History

tpm: disable hwrng for fTPM on some AMD designs

AMD has issued an advisory indicating that having fTPM enabled in BIOS can cause "stuttering" in the OS. This issue has been fixed in newer versions of the fTPM firmware, but it's up to system designers to decide whether to distribute it. This issue has existed for a while, but is more prevalent starting with kernel 6.1 because commit b006c439d58db ("hwrng: core - start hwrng kthread also for untrusted sources") started to use the fTPM for hwrng by default. However, all uses of /dev/hwrng result in unacceptable stuttering. So, simply disable registration of the defective hwrng when detecting these faulty fTPM versions. As this is caused by faulty firmware, it is plausible that such a problem could also be reproduced by other TPM interactions, but this hasn't been shown by any user's testing or reports. It is hypothesized to be triggered more frequently by the use of the RNG because userspace software will fetch random numbers regularly. Intentionally continue to register other TPM functionality so that users that rely upon PCR measurements or any storage of data will still have access to it. If it's found later that another TPM functionality is exacerbating this problem a module parameter it can be turned off entirely and a module parameter can be introduced to allow users who rely upon fTPM functionality to turn it on even though this problem is present.

Mario Limonciello committed 3 years ago

Commit f1324bb1 parent 80a6c212 files · +132 −1Browse files

Unified · Split

2 files
  1. drivers/char/tpm/tpm-chip.c +59 −1
  2. drivers/char/tpm/tpm.h +73 −0
drivers/char/tpm/tpm-chip.c+59−1
@@ -511,6 +511,63 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip) · 510 unmodified lines
511 return 0;511 return 0;
512}512}
513 513
514/*
515 * Some AMD fTPM versions may cause stutter
516 * https://www.amd.com/en/support/kb/faq/pa-410
517 *
518 * Fixes are available in two series of fTPM firmware:
519 * 6.x.y.z series: 6.0.18.6 +
520 * 3.x.y.z series: 3.57.y.5 +
521 */
522static 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
547release:
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
514static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)571static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
515{572{
516 struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);573 struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
@@ -520,7 +577,8 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) · 3 unmodified lines
520 577
521static int tpm_add_hwrng(struct tpm_chip *chip)578static int tpm_add_hwrng(struct tpm_chip *chip)
522{579{
523 if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM) || tpm_is_firmware_upgrade(chip))580 if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM) || tpm_is_firmware_upgrade(chip) ||
581 tpm_amd_is_rng_defective(chip))
524 return 0;582 return 0;
525 583
526 snprintf(chip->hwrng_name, sizeof(chip->hwrng_name),584 snprintf(chip->hwrng_name, sizeof(chip->hwrng_name),
drivers/char/tpm/tpm.h+73−0
@@ -150,6 +150,79 @@ enum tpm_sub_capabilities { · 149 unmodified lines
150 TPM_CAP_PROP_TIS_DURATION = 0x120,150 TPM_CAP_PROP_TIS_DURATION = 0x120,
151};151};
152 152
153enum tpm2_pt_props {
154 TPM2_PT_NONE = 0x00000000,
155 TPM2_PT_GROUP = 0x00000100,
156 TPM2_PT_FIXED = TPM2_PT_GROUP * 1,
157 TPM2_PT_FAMILY_INDICATOR = TPM2_PT_FIXED + 0,
158 TPM2_PT_LEVEL = TPM2_PT_FIXED + 1,
159 TPM2_PT_REVISION = TPM2_PT_FIXED + 2,
160 TPM2_PT_DAY_OF_YEAR = TPM2_PT_FIXED + 3,
161 TPM2_PT_YEAR = TPM2_PT_FIXED + 4,
162 TPM2_PT_MANUFACTURER = TPM2_PT_FIXED + 5,
163 TPM2_PT_VENDOR_STRING_1 = TPM2_PT_FIXED + 6,
164 TPM2_PT_VENDOR_STRING_2 = TPM2_PT_FIXED + 7,
165 TPM2_PT_VENDOR_STRING_3 = TPM2_PT_FIXED + 8,
166 TPM2_PT_VENDOR_STRING_4 = TPM2_PT_FIXED + 9,
167 TPM2_PT_VENDOR_TPM_TYPE = TPM2_PT_FIXED + 10,
168 TPM2_PT_FIRMWARE_VERSION_1 = TPM2_PT_FIXED + 11,
169 TPM2_PT_FIRMWARE_VERSION_2 = TPM2_PT_FIXED + 12,
170 TPM2_PT_INPUT_BUFFER = TPM2_PT_FIXED + 13,
171 TPM2_PT_HR_TRANSIENT_MIN = TPM2_PT_FIXED + 14,
172 TPM2_PT_HR_PERSISTENT_MIN = TPM2_PT_FIXED + 15,
173 TPM2_PT_HR_LOADED_MIN = TPM2_PT_FIXED + 16,
174 TPM2_PT_ACTIVE_SESSIONS_MAX = TPM2_PT_FIXED + 17,
175 TPM2_PT_PCR_COUNT = TPM2_PT_FIXED + 18,
176 TPM2_PT_PCR_SELECT_MIN = TPM2_PT_FIXED + 19,
177 TPM2_PT_CONTEXT_GAP_MAX = TPM2_PT_FIXED + 20,
178 TPM2_PT_NV_COUNTERS_MAX = TPM2_PT_FIXED + 22,
179 TPM2_PT_NV_INDEX_MAX = TPM2_PT_FIXED + 23,
180 TPM2_PT_MEMORY = TPM2_PT_FIXED + 24,
181 TPM2_PT_CLOCK_UPDATE = TPM2_PT_FIXED + 25,
182 TPM2_PT_CONTEXT_HASH = TPM2_PT_FIXED + 26,
183 TPM2_PT_CONTEXT_SYM = TPM2_PT_FIXED + 27,
184 TPM2_PT_CONTEXT_SYM_SIZE = TPM2_PT_FIXED + 28,
185 TPM2_PT_ORDERLY_COUNT = TPM2_PT_FIXED + 29,
186 TPM2_PT_MAX_COMMAND_SIZE = TPM2_PT_FIXED + 30,
187 TPM2_PT_MAX_RESPONSE_SIZE = TPM2_PT_FIXED + 31,
188 TPM2_PT_MAX_DIGEST = TPM2_PT_FIXED + 32,
189 TPM2_PT_MAX_OBJECT_CONTEXT = TPM2_PT_FIXED + 33,
190 TPM2_PT_MAX_SESSION_CONTEXT = TPM2_PT_FIXED + 34,
191 TPM2_PT_PS_FAMILY_INDICATOR = TPM2_PT_FIXED + 35,
192 TPM2_PT_PS_LEVEL = TPM2_PT_FIXED + 36,
193 TPM2_PT_PS_REVISION = TPM2_PT_FIXED + 37,
194 TPM2_PT_PS_DAY_OF_YEAR = TPM2_PT_FIXED + 38,
195 TPM2_PT_PS_YEAR = TPM2_PT_FIXED + 39,
196 TPM2_PT_SPLIT_MAX = TPM2_PT_FIXED + 40,
197 TPM2_PT_TOTAL_COMMANDS = TPM2_PT_FIXED + 41,
198 TPM2_PT_LIBRARY_COMMANDS = TPM2_PT_FIXED + 42,
199 TPM2_PT_VENDOR_COMMANDS = TPM2_PT_FIXED + 43,
200 TPM2_PT_NV_BUFFER_MAX = TPM2_PT_FIXED + 44,
201 TPM2_PT_MODES = TPM2_PT_FIXED + 45,
202 TPM2_PT_MAX_CAP_BUFFER = TPM2_PT_FIXED + 46,
203 TPM2_PT_VAR = TPM2_PT_GROUP * 2,
204 TPM2_PT_PERMANENT = TPM2_PT_VAR + 0,
205 TPM2_PT_STARTUP_CLEAR = TPM2_PT_VAR + 1,
206 TPM2_PT_HR_NV_INDEX = TPM2_PT_VAR + 2,
207 TPM2_PT_HR_LOADED = TPM2_PT_VAR + 3,
208 TPM2_PT_HR_LOADED_AVAIL = TPM2_PT_VAR + 4,
209 TPM2_PT_HR_ACTIVE = TPM2_PT_VAR + 5,
210 TPM2_PT_HR_ACTIVE_AVAIL = TPM2_PT_VAR + 6,
211 TPM2_PT_HR_TRANSIENT_AVAIL = TPM2_PT_VAR + 7,
212 TPM2_PT_HR_PERSISTENT = TPM2_PT_VAR + 8,
213 TPM2_PT_HR_PERSISTENT_AVAIL = TPM2_PT_VAR + 9,
214 TPM2_PT_NV_COUNTERS = TPM2_PT_VAR + 10,
215 TPM2_PT_NV_COUNTERS_AVAIL = TPM2_PT_VAR + 11,
216 TPM2_PT_ALGORITHM_SET = TPM2_PT_VAR + 12,
217 TPM2_PT_LOADED_CURVES = TPM2_PT_VAR + 13,
218 TPM2_PT_LOCKOUT_COUNTER = TPM2_PT_VAR + 14,
219 TPM2_PT_MAX_AUTH_FAIL = TPM2_PT_VAR + 15,
220 TPM2_PT_LOCKOUT_INTERVAL = TPM2_PT_VAR + 16,
221 TPM2_PT_LOCKOUT_RECOVERY = TPM2_PT_VAR + 17,
222 TPM2_PT_NV_WRITE_RECOVERY = TPM2_PT_VAR + 18,
223 TPM2_PT_AUDIT_COUNTER_0 = TPM2_PT_VAR + 19,
224 TPM2_PT_AUDIT_COUNTER_1 = TPM2_PT_VAR + 20,
225};
153 226
154/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18227/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
155 * bytes, but 128 is still a relatively large number of random bytes and228 * bytes, but 128 is still a relatively large number of random bytes and