tpmdd-devel.lists.sourceforge.net archive mirror
 help / color / mirror / Atom feed
From: Alexander Steffen <Alexander.Steffen-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>
To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
Subject: [PATCH 3/3] tpm2-cmd: React correctly to RC_TESTING from self tests
Date: Fri, 18 Aug 2017 14:15:32 +0200	[thread overview]
Message-ID: <20170818121532.5764-3-Alexander.Steffen@infineon.com> (raw)
In-Reply-To: <20170818121532.5764-1-Alexander.Steffen-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>

The TPM can choose one of two ways to react to the TPM2_SelfTest command.
It can either run all self tests synchronously and then return RC_SUCCESS
once all tests were successful. Or it can choose to run the tests
asynchronously and return RC_TESTING immediately while the self tests still
execute in the background.

The previous implementation apparently was not aware of those possibilities
and attributed RC_TESTING to some prototype chips instead. With this change
the return code of TPM2_SelfTest is interpreted correctly, i.e. the self
test result is polled if and only if RC_TESTING is received. Unfortunately,
the polling cannot be done in the most straightforward way, so the solution
is explained with a comment in the code.

Signed-off-by: Alexander Steffen <Alexander.Steffen-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>
---
 drivers/char/tpm/tpm2-cmd.c | 68 ++++++++++++++++++---------------------------
 1 file changed, 27 insertions(+), 41 deletions(-)

diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index e3d4cc3..d09032f 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -834,68 +834,54 @@ static const struct tpm_input_header tpm2_selftest_header = {
 };
 
 /**
- * tpm2_continue_selftest() - start a self test
- *
- * @chip: TPM chip to use
- * @full: test all commands instead of testing only those that were not
- *        previously tested.
- *
- * Return: Same as with tpm_transmit_cmd with exception of RC_TESTING.
- */
-static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
-{
-	int rc;
-	struct tpm2_cmd cmd;
-
-	cmd.header.in = tpm2_selftest_header;
-	cmd.params.selftest_in.full_test = full;
-
-	rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0,
-			      "continue selftest");
-
-	/* At least some prototype chips seem to give RC_TESTING error
-	 * immediately. This is a workaround for that.
-	 */
-	if (rc == TPM2_RC_TESTING) {
-		dev_warn(&chip->dev, "Got RC_TESTING, ignoring\n");
-		rc = 0;
-	}
-
-	return rc;
-}
-
-/**
  * tpm2_do_selftest() - ensure that all self tests have passed
  *
  * @chip: TPM chip to use
  *
  * Return: Same as with tpm_transmit_cmd.
  *
- * During the self test TPM2 commands return with the error code RC_TESTING.
- * Waiting is done by issuing PCR read until it executes successfully.
+ * The TPM can either run all self tests synchronously and then return
+ * RC_SUCCESS once all tests were successful. Or it can choose to run the tests
+ * asynchronously and return RC_TESTING immediately while the self tests still
+ * execute in the background. This function handles both cases and waits until
+ * all tests have completed.
  */
 static int tpm2_do_selftest(struct tpm_chip *chip)
 {
 	int rc;
 	unsigned int delay_msec = 20;
 	long duration;
+	struct tpm2_cmd cmd;
 
 	duration = jiffies_to_msecs(
 		tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST));
 
-	rc = tpm2_start_selftest(chip, false);
-	if (rc)
-		return rc;
-
 	while (duration > 0) {
-		/* Attempt to read a PCR value */
-		rc = tpm2_pcr_read(chip, 0, NULL);
-		if (rc < 0)
-			break;
+		cmd.header.in = tpm2_selftest_header;
+		cmd.params.selftest_in.full_test = 0;
+
+		rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE,
+				      0, 0, "continue selftest");
 
 		if (rc != TPM2_RC_TESTING)
 			break;
 
+		/* If RC_TESTING is received, ideally the code should now poll
+		 * the selfTestDone bit in the STS register, as this avoids
+		 * sending more commands, that might interrupt self tests
+		 * executing in the background and thus prevent them from ever
+		 * completing.
+		 * Unfortunately, it cannot be guaranteed that this bit is
+		 * correctly implemented for all devices, so the next best thing
+		 * would be to use TPM2_GetTestResult to query the test result.
+		 * But the response to that command can be very long, and the
+		 * code currently lacks the capabilities for efficient
+		 * unmarshalling, so it is difficult to execute this command.
+		 * Therefore, we simply run the TPM2_SelfTest command in a loop,
+		 * which should complete eventually, since we only request the
+		 * execution of self tests that have not yet been done.
+		 */
+
 		msleep(delay_msec);
 		duration -= delay_msec;
 
-- 
2.7.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

  parent reply	other threads:[~2017-08-18 12:15 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-18 12:15 [PATCH 1/3] tpm2-cmd: Trigger only missing self tests Alexander Steffen
     [not found] ` <20170818121532.5764-1-Alexander.Steffen-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>
2017-08-18 12:15   ` [PATCH 2/3] tpm2-cmd: Use dynamic delay to wait for self test result Alexander Steffen
     [not found]     ` <20170818121532.5764-2-Alexander.Steffen-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>
2017-08-20 18:26       ` Jarkko Sakkinen
     [not found]         ` <20170820182632.ik4d5nfm2ggashiy-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2017-08-22 17:44           ` Jarkko Sakkinen
2017-08-18 12:15   ` Alexander Steffen [this message]
     [not found]     ` <20170818121532.5764-3-Alexander.Steffen-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>
2017-08-20 18:31       ` [PATCH 3/3] tpm2-cmd: React correctly to RC_TESTING from self tests Jarkko Sakkinen
2017-08-19 17:16   ` [PATCH 1/3] tpm2-cmd: Trigger only missing " Jarkko Sakkinen
2017-08-20 18:25   ` 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=20170818121532.5764-3-Alexander.Steffen@infineon.com \
    --to=alexander.steffen-d0qzbvysippwk0htik3j/w@public.gmane.org \
    --cc=jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org \
    --cc=tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    /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;
as well as URLs for NNTP newsgroup(s).