diff mbox series

[1/2] tpm: add a function that performs selftest + startup

Message ID 20230125113904.517057-1-ilias.apalodimas@linaro.org
State New
Headers show
Series [1/2] tpm: add a function that performs selftest + startup | expand

Commit Message

Ilias Apalodimas Jan. 25, 2023, 11:39 a.m. UTC
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

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
 include/tpm-v2.h  |  8 ++++++++
 include/tpm_api.h |  8 ++++++++
 lib/tpm-v2.c      | 29 +++++++++++++++++++++++++++++
 lib/tpm_api.c     |  8 ++++++++
 4 files changed, 53 insertions(+)

Comments

Heinrich Schuchardt Jan. 25, 2023, 11:56 a.m. UTC | #1
On 1/25/23 12:39, Ilias Apalodimas wrote:
> 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
>
> Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> ---
>   include/tpm-v2.h  |  8 ++++++++
>   include/tpm_api.h |  8 ++++++++
>   lib/tpm-v2.c      | 29 +++++++++++++++++++++++++++++
>   lib/tpm_api.c     |  8 ++++++++
>   4 files changed, 53 insertions(+)
>
> diff --git a/include/tpm-v2.h b/include/tpm-v2.h
> index 737e57551d73..3013f69a90ed 100644
> --- a/include/tpm-v2.h
> +++ b/include/tpm-v2.h
> @@ -688,4 +688,12 @@ 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
> + *
> + * @param dev		TPM device
> + * Return: return code of the operation (0 = success)
> + */
> +u32 tpm2_auto_start(struct udevice *dev);
> +
>   #endif /* __TPM_V2_H */
> diff --git a/include/tpm_api.h b/include/tpm_api.h
> index 8979d9d6df7e..022a8bbaeca6 100644
> --- a/include/tpm_api.h
> +++ b/include/tpm_api.h
> @@ -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 */
> diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> index 697b982e079f..c34e158e2bb4 100644
> --- a/lib/tpm-v2.c
> +++ b/lib/tpm-v2.c
> @@ -44,6 +44,35 @@ u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
>   	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
>   }
>
> +/*
> + * - If a testable function has not been tested and is requested the TPM2  will return
> + *   TPM_RC_NEEDS_TEST.
> + * - If TPM2 self-test has been received and the tests are not complete the
> + *   result will be TPM_RC_TESTING.
> + * - If testing of all functions is complete without functional failures the result
> + *   will be TPM_RC_SUCCESS.
> + * - If any test failed, the result will be TPM2_RC_FAILURE.
> + * - if the TPM hasn't started it will return TPM2_RC_INITIALIZE.
> + */

This comment block should be moved to include/tpm-v2.h to show up in the
HTML documentation.

> +u32 tpm2_auto_start(struct udevice *dev)
> +{
> +	u32 rc;
> +
> +	rc = tpm2_self_test(dev, TPMI_YES);
> +	if (rc && rc != TPM2_RC_INITIALIZE)
> +		return rc;

This if and return are superfluous. We anyway return rc.

Best regards

Heinrich

> +
> +	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)
>   {
> diff --git a/lib/tpm_api.c b/lib/tpm_api.c
> index 7e8df8795ef3..5b2c11a277cc 100644
> --- a/lib/tpm_api.c
> +++ b/lib/tpm_api.c
> @@ -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))
diff mbox series

Patch

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 737e57551d73..3013f69a90ed 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -688,4 +688,12 @@  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
+ *
+ * @param dev		TPM device
+ * Return: return code of the operation (0 = success)
+ */
+u32 tpm2_auto_start(struct udevice *dev);
+
 #endif /* __TPM_V2_H */
diff --git a/include/tpm_api.h b/include/tpm_api.h
index 8979d9d6df7e..022a8bbaeca6 100644
--- a/include/tpm_api.h
+++ b/include/tpm_api.h
@@ -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 */
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index 697b982e079f..c34e158e2bb4 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -44,6 +44,35 @@  u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
+/*
+ * - If a testable function has not been tested and is requested the TPM2  will return
+ *   TPM_RC_NEEDS_TEST.
+ * - If TPM2 self-test has been received and the tests are not complete the
+ *   result will be TPM_RC_TESTING.
+ * - If testing of all functions is complete without functional failures the result
+ *   will be TPM_RC_SUCCESS.
+ * - If any test failed, the result will be TPM2_RC_FAILURE.
+ * - if the TPM hasn't started it will return TPM2_RC_INITIALIZE.
+ */
+u32 tpm2_auto_start(struct udevice *dev)
+{
+	u32 rc;
+
+	rc = tpm2_self_test(dev, TPMI_YES);
+	if (rc && rc != TPM2_RC_INITIALIZE)
+		return rc;
+
+	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)
 {
diff --git a/lib/tpm_api.c b/lib/tpm_api.c
index 7e8df8795ef3..5b2c11a277cc 100644
--- a/lib/tpm_api.c
+++ b/lib/tpm_api.c
@@ -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))