]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
tpm: add a function that performs selftest + startup
authorIlias Apalodimas <ilias.apalodimas@linaro.org>
Wed, 25 Jan 2023 10:18:36 +0000 (12:18 +0200)
committerIlias Apalodimas <ilias.apalodimas@linaro.org>
Tue, 28 Feb 2023 07:44:19 +0000 (09:44 +0200)
As described in [0] if a command requires use of an untested algorithm
or functional module, the TPM performs the test and then completes the
command actions.

Since we don't check for TPM_RC_NEEDS_TEST (which is the return code of
the TPM in that case) and even if we would, it would complicate our TPM
code for no apparent reason,  add a wrapper function that performs both
the selftest and the startup sequence of the TPM.

It's worth noting that this is implemented on TPMv2.0.  The code for
1.2 would look similar,  but I don't have a device available to test.

[0]
https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-1-Architecture-01.07-2014-03-13.pdf
ยง12.3 Self-test modes

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
include/tpm-v2.h
include/tpm_api.h
lib/tpm-v2.c
lib/tpm_api.c

index 2df3dad553245a9e0698e470b8e9404817fbd480..2b6980e441d62292aab51e1650a079c9c1f0821b 100644 (file)
@@ -690,4 +690,20 @@ u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
 u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
                          uint vendor_subcmd);
 
+/**
+ * tpm2_auto_start() - start up the TPM and perform selftests.
+ *                     If a testable function has not been tested and is
+ *                     requested the TPM2  will return TPM_RC_NEEDS_TEST.
+ *
+ * @param dev          TPM device
+ * Return: TPM2_RC_TESTING, if TPM2 self-test is in progress.
+ *         TPM2_RC_SUCCESS, if testing of all functions is complete without
+ *         functional failures.
+ *         TPM2_RC_FAILURE, if any test failed.
+ *         TPM2_RC_INITIALIZE, if the TPM has not gone through the Startup
+ *         sequence
+
+ */
+u32 tpm2_auto_start(struct udevice *dev);
+
 #endif /* __TPM_V2_H */
index 8979d9d6df7ef8caec8b9dd6287c7b23c1d805f7..022a8bbaeca606cc88715401dcfd05f5067e628f 100644 (file)
@@ -331,4 +331,12 @@ static inline bool tpm_is_v2(struct udevice *dev)
        return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2;
 }
 
+/**
+ * tpm_auto_start() - start up the TPM and perform selftests
+ *
+ * @param dev          TPM device
+ * Return: return code of the operation (0 = success)
+ */
+u32 tpm_auto_start(struct udevice *dev);
+
 #endif /* __TPM_API_H */
index 697b982e079fbdc4f4ebf1ed8daa953ef9647f5f..895b093bcb1a5df38fea36792dd673f090335042 100644 (file)
@@ -44,6 +44,31 @@ u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
        return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
+u32 tpm2_auto_start(struct udevice *dev)
+{
+       u32 rc;
+
+       /*
+        * the tpm_init() will return -EBUSY if the init has already happened
+        * The selftest and startup code can run multiple times with no side
+        * effects
+        */
+       rc = tpm_init(dev);
+       if (rc && rc != -EBUSY)
+               return rc;
+       rc = tpm2_self_test(dev, TPMI_YES);
+
+       if (rc == TPM2_RC_INITIALIZE) {
+               rc = tpm2_startup(dev, TPM2_SU_CLEAR);
+               if (rc)
+                       return rc;
+
+               rc = tpm2_self_test(dev, TPMI_YES);
+       }
+
+       return rc;
+}
+
 u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
               const ssize_t pw_sz)
 {
index 7e8df8795ef3e74973e30e940d3db19f3035e723..5b2c11a277cc9c4610d1f546f34d56b10dbd2128 100644 (file)
@@ -35,6 +35,14 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
        }
 }
 
+u32 tpm_auto_start(struct udevice *dev)
+{
+       if (tpm_is_v2(dev))
+               return tpm2_auto_start(dev);
+
+       return -ENOSYS;
+}
+
 u32 tpm_resume(struct udevice *dev)
 {
        if (tpm_is_v1(dev))