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

tpm: Add upgrade/reduced mode support for TPM1.2 modules

In case a TPM in failure mode is detected, the TPM should be accessible
through a transparent communication channel for analysing purposes (e.g.
TPM_GetTestResult) or a field upgrade. Since a TPM in failure mode has
similar reduced functionality as in field upgrade mode, the flag
TPM_CHIP_FLAG_FIRMWARE_UPGRADE is also valid.

As described in TCG TPM Main Part1 Design Principles, Revision 116,
chapter 9.2.1. the TPM also allows an update function in case a TPM is
in failure mode.

If the TPM in failure mode is detected, the function tpm1_auto_startup()
sets TPM_CHIP_FLAG_FIRMWARE_UPGRADE flag, which is used later during
driver initialization/deinitialization to disable functionality which
makes no sense or will fail in the current TPM state. The following
functionality is affected:
* Do not register TPM as a hwrng
* Do not get pcr allocation
* Do not register sysfs entries which provide information impossible to
obtain in limited mode

Signed-off-by: Stefan Mahnke-Hartmann <stefan.mahnke-hartmann@infineon.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>

authored by

Stefan Mahnke-Hartmann and committed by
Jarkko Sakkinen
5e3a3f27 200e340f

+7 -1
+1
drivers/char/tpm/tpm.h
··· 55 55 #define TPM_WARN_DOING_SELFTEST 0x802 56 56 #define TPM_ERR_DEACTIVATED 0x6 57 57 #define TPM_ERR_DISABLED 0x7 58 + #define TPM_ERR_FAILEDSELFTEST 0x1C 58 59 #define TPM_ERR_INVALID_POSTINIT 38 59 60 60 61 #define TPM_TAG_RQU_COMMAND 193
+6 -1
drivers/char/tpm/tpm1-cmd.c
··· 709 709 if (rc) 710 710 goto out; 711 711 rc = tpm1_do_selftest(chip); 712 - if (rc) { 712 + if (rc == TPM_ERR_FAILEDSELFTEST) { 713 + dev_warn(&chip->dev, "TPM self test failed, switching to the firmware upgrade mode\n"); 714 + /* A TPM in this state possibly allows or needs a firmware upgrade */ 715 + chip->flags |= TPM_CHIP_FLAG_FIRMWARE_UPGRADE; 716 + return 0; 717 + } else if (rc) { 713 718 dev_err(&chip->dev, "TPM self test failed\n"); 714 719 goto out; 715 720 }