From: Borys Movchan <borysmn@axis.com>
To: Peter Huewe <peterhuewe@gmx.de>,
Jarkko Sakkinen <jarkko@kernel.org>,
Jason Gunthorpe <jgg@ziepe.ca>
Cc: <kernel@axis.com>, Borys Movchan <borysmn@axis.com>,
<linux-integrity@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Subject: [PATCH v2] tpm: Add Upgrade/Reduced mode support for TPM2 modules
Date: Wed, 28 Jul 2021 12:57:30 +0200 [thread overview]
Message-ID: <20210728105730.10170-1-borysmn@axis.com> (raw)
If something went wrong during the TPM firmware upgrade,
like power failure or the firmware image file get corrupted,
the TPM might end up in Upgrade or Failure mode upon the
next start. The state is persistent between the TPM power
cycle/restart.
According to TPM specification:
* If the TPM is in Upgrade mode, it will answer with
TPM2_RC_UPGRADE to all commands except Field Upgrade
related ones.
* If the TPM is in Failure mode, it will allow performing
TPM initialization but will not provide any crypto
operations. Will happily respond to Field Upgrade calls.
The fix adds the possibility to detect an active state of
the TPM and gives the user-space a chance to finish the
firmware upgrade/recover the TPM.
Signed-off-by: Borys Movchan <borysmn@axis.com>
---
Notes:
v2: The terms are changed to match the ones used in the TPM specification.
Rework the commit message to provide more details regarding TPM
behavior in Failure/Upgrade mode.
The TPM specification describes TPM behavior in Upgrade mode very clearly.
Things are a bit more complex if we are talking about Failure mode.
The TPM behavior in this mode is highly vendor-specific. Although, there
is one thing clearly described in the TPM specification and can be relied
on to detect the Failure state: in Failure mode, the TPM doesn't provide
any crypto operations. Including access to attributes and configuration
registers.
It seems persistent between different TPM manufacturers, at least to the
degree I was able to verify.
drivers/char/tpm/tpm-chip.c | 23 +++++++++++++++--------
drivers/char/tpm/tpm2-cmd.c | 12 ++++++++++--
include/linux/tpm.h | 1 +
3 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index ddaeceb7e109..ff2367c447fb 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -574,20 +574,25 @@ static int tpm_get_pcr_allocation(struct tpm_chip *chip)
int tpm_chip_register(struct tpm_chip *chip)
{
int rc;
+ bool limited_mode = false;
rc = tpm_chip_start(chip);
if (rc)
return rc;
rc = tpm_auto_startup(chip);
- if (rc) {
+ if (rc == -EIO) {
+ limited_mode = true;
+ } else if (rc) {
tpm_chip_stop(chip);
return rc;
}
- rc = tpm_get_pcr_allocation(chip);
- tpm_chip_stop(chip);
- if (rc)
- return rc;
+ if (!limited_mode) {
+ rc = tpm_get_pcr_allocation(chip);
+ tpm_chip_stop(chip);
+ if (rc)
+ return rc;
+ }
tpm_sysfs_add_device(chip);
@@ -595,9 +600,11 @@ int tpm_chip_register(struct tpm_chip *chip)
tpm_add_ppi(chip);
- rc = tpm_add_hwrng(chip);
- if (rc)
- goto out_ppi;
+ if (!limited_mode) {
+ rc = tpm_add_hwrng(chip);
+ if (rc)
+ goto out_ppi;
+ }
rc = tpm_add_char_device(chip);
if (rc)
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index a25815a6f625..7468353ed67d 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -718,7 +718,8 @@ static int tpm2_startup(struct tpm_chip *chip)
* sequence
* @chip: TPM chip to use
*
- * Returns 0 on success, < 0 in case of fatal error.
+ * Returns 0 on success, -ENODEV in case of fatal error,
+ * -EIO in case of Reduced/Upgrade mode
*/
int tpm2_auto_startup(struct tpm_chip *chip)
{
@@ -729,7 +730,10 @@ int tpm2_auto_startup(struct tpm_chip *chip)
goto out;
rc = tpm2_do_selftest(chip);
- if (rc && rc != TPM2_RC_INITIALIZE)
+ if (rc == TPM2_RC_UPGRADE) {
+ rc = -EIO;
+ goto out;
+ } else if (rc && rc != TPM2_RC_INITIALIZE)
goto out;
if (rc == TPM2_RC_INITIALIZE) {
@@ -743,6 +747,10 @@ int tpm2_auto_startup(struct tpm_chip *chip)
}
rc = tpm2_get_cc_attrs_tbl(chip);
+ if (rc) { /* Succeeded until here, but failed -> reduced mode */
+ rc = -EIO;
+ goto out;
+ }
out:
if (rc > 0)
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index aa11fe323c56..e873c42907f0 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -207,6 +207,7 @@ enum tpm2_return_codes {
TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */
TPM2_RC_FAILURE = 0x0101,
TPM2_RC_DISABLED = 0x0120,
+ TPM2_RC_UPGRADE = 0x012D,
TPM2_RC_COMMAND_CODE = 0x0143,
TPM2_RC_TESTING = 0x090A, /* RC_WARN */
TPM2_RC_REFERENCE_H0 = 0x0910,
--
2.20.1
next reply other threads:[~2021-07-28 10:55 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-28 10:57 Borys Movchan [this message]
2021-07-28 21:58 ` [PATCH v2] tpm: Add Upgrade/Reduced mode support for TPM2 modules Jarkko Sakkinen
2021-07-30 14:24 ` Borys Movchan
2021-08-02 8:35 ` Jarkko Sakkinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210728105730.10170-1-borysmn@axis.com \
--to=borysmn@axis.com \
--cc=jarkko@kernel.org \
--cc=jgg@ziepe.ca \
--cc=kernel@axis.com \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=peterhuewe@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox