u-boot.lists.denx.de archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] tpm: Various minor fixes and enhancements
@ 2022-03-01  0:11 Simon Glass
  2022-03-01  0:11 ` [PATCH 1/8] tpm: Export the TPM-version functions Simon Glass
                   ` (7 more replies)
  0 siblings, 8 replies; 19+ messages in thread
From: Simon Glass @ 2022-03-01  0:11 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Simon Glass

This series contains some minor enhancements for the TPM code to make it
work with Chromium OS verified boot.


Simon Glass (8):
  tpm: Export the TPM-version functions
  tpm: Require a digest source when extending the PCR
  tpm: Correct the permissions command in TPMv1
  tpm: Correct the define-space command in TPMv2
  tpm: sandbox: Allow init of TPM in a different phase
  tpm: Allow reporting the internal state
  tpm: Implement state command for Cr50
  tpm: Allow commiting non-volatile data

 cmd/tpm-common.c               |  20 ++++++
 cmd/tpm-user-utils.h           |   2 +
 cmd/tpm-v1.c                   |   3 +-
 cmd/tpm-v2.c                   |   3 +
 cmd/tpm_test.c                 |   5 +-
 drivers/tpm/cr50_i2c.c         | 117 +++++++++++++++++++++++++++++++++
 drivers/tpm/tpm-uclass.c       |  10 +++
 drivers/tpm/tpm2_tis_sandbox.c |  17 ++++-
 include/tpm-common.h           |  20 ++++++
 include/tpm-v2.h               |  68 +++++++++++++++++++
 include/tpm_api.h              |  18 ++++-
 lib/tpm-v1.c                   |   5 +-
 lib/tpm-v2.c                   |  64 ++++++++++++++++--
 lib/tpm_api.c                  | 102 ++++++++++++++--------------
 test/dm/Makefile               |   1 +
 test/dm/tpm.c                  |  34 ++++++++++
 16 files changed, 419 insertions(+), 70 deletions(-)
 create mode 100644 test/dm/tpm.c

-- 
2.35.1.574.g5d30c73bfb-goog


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/8] tpm: Export the TPM-version functions
  2022-03-01  0:11 [PATCH 0/8] tpm: Various minor fixes and enhancements Simon Glass
@ 2022-03-01  0:11 ` Simon Glass
  2022-06-07  8:28   ` Ilias Apalodimas
  2022-03-01  0:11 ` [PATCH 2/8] tpm: Require a digest source when extending the PCR Simon Glass
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Simon Glass @ 2022-03-01  0:11 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Simon Glass

These functions should really be available outside the TPM code, so that
other callers can find out which version the TPM is. Rename them to have
a tpm_ prefix() and add them to the header file.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/tpm_api.h | 10 ++++++
 lib/tpm_api.c     | 92 +++++++++++++++++++++--------------------------
 2 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/include/tpm_api.h b/include/tpm_api.h
index ef45b43a8f..11aa14eb79 100644
--- a/include/tpm_api.h
+++ b/include/tpm_api.h
@@ -319,4 +319,14 @@ u32 tpm_write_lock(struct udevice *dev, u32 index);
  */
 u32 tpm_resume(struct udevice *dev);
 
+static inline bool tpm_is_v1(struct udevice *dev)
+{
+	return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1;
+}
+
+static inline bool tpm_is_v2(struct udevice *dev)
+{
+	return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2;
+}
+
 #endif /* __TPM_API_H */
diff --git a/lib/tpm_api.c b/lib/tpm_api.c
index 4c662640a9..4ac4612c81 100644
--- a/lib/tpm_api.c
+++ b/lib/tpm_api.c
@@ -11,21 +11,11 @@
 #include <tpm-v2.h>
 #include <tpm_api.h>
 
-static bool is_tpm1(struct udevice *dev)
-{
-	return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1;
-}
-
-static bool is_tpm2(struct udevice *dev)
-{
-	return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2;
-}
-
 u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
 {
-	if (is_tpm1(dev)) {
+	if (tpm_is_v1(dev)) {
 		return tpm1_startup(dev, mode);
-	} else if (is_tpm2(dev)) {
+	} else if (tpm_is_v2(dev)) {
 		enum tpm2_startup_types type;
 
 		switch (mode) {
@@ -47,9 +37,9 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
 
 u32 tpm_resume(struct udevice *dev)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_startup(dev, TPM_ST_STATE);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return tpm2_startup(dev, TPM2_SU_STATE);
 	else
 		return -ENOSYS;
@@ -57,9 +47,9 @@ u32 tpm_resume(struct udevice *dev)
 
 u32 tpm_self_test_full(struct udevice *dev)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_self_test_full(dev);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return tpm2_self_test(dev, TPMI_YES);
 	else
 		return -ENOSYS;
@@ -67,9 +57,9 @@ u32 tpm_self_test_full(struct udevice *dev)
 
 u32 tpm_continue_self_test(struct udevice *dev)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_continue_self_test(dev);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return tpm2_self_test(dev, TPMI_NO);
 	else
 		return -ENOSYS;
@@ -86,7 +76,7 @@ u32 tpm_clear_and_reenable(struct udevice *dev)
 		return ret;
 	}
 
-	if (is_tpm1(dev)) {
+	if (tpm_is_v1(dev)) {
 		ret = tpm1_physical_enable(dev);
 		if (ret != TPM_SUCCESS) {
 			log_err("TPM: Can't set enabled state\n");
@@ -105,9 +95,9 @@ u32 tpm_clear_and_reenable(struct udevice *dev)
 
 u32 tpm_nv_enable_locking(struct udevice *dev)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return -ENOSYS;
 	else
 		return -ENOSYS;
@@ -115,9 +105,9 @@ u32 tpm_nv_enable_locking(struct udevice *dev)
 
 u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_nv_read_value(dev, index, data, count);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return tpm2_nv_read_value(dev, index, data, count);
 	else
 		return -ENOSYS;
@@ -126,9 +116,9 @@ u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
 u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
 		       u32 count)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_nv_write_value(dev, index, data, count);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return tpm2_nv_write_value(dev, index, data, count);
 	else
 		return -ENOSYS;
@@ -141,9 +131,9 @@ u32 tpm_set_global_lock(struct udevice *dev)
 
 u32 tpm_write_lock(struct udevice *dev, u32 index)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return -ENOSYS;
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return tpm2_write_lock(dev, index);
 	else
 		return -ENOSYS;
@@ -152,9 +142,9 @@ u32 tpm_write_lock(struct udevice *dev, u32 index)
 u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
 		   void *out_digest)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_extend(dev, index, in_digest, out_digest);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest,
 				       TPM2_DIGEST_LEN);
 	else
@@ -163,9 +153,9 @@ u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
 
 u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_pcr_read(dev, index, data, count);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return -ENOSYS;
 	else
 		return -ENOSYS;
@@ -173,14 +163,14 @@ u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
 
 u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_tsc_physical_presence(dev, presence);
 
 	/*
 	 * Nothing to do on TPM2 for this; use platform hierarchy availability
 	 * instead.
 	 */
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return 0;
 	else
 		return -ENOSYS;
@@ -188,11 +178,11 @@ u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
 
 u32 tpm_finalise_physical_presence(struct udevice *dev)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_finalise_physical_presence(dev);
 
 	/* Nothing needs to be done with tpm2 */
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return 0;
 	else
 		return -ENOSYS;
@@ -200,9 +190,9 @@ u32 tpm_finalise_physical_presence(struct udevice *dev)
 
 u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_read_pubek(dev, data, count);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return -ENOSYS; /* not implemented yet */
 	else
 		return -ENOSYS;
@@ -210,9 +200,9 @@ u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
 
 u32 tpm_force_clear(struct udevice *dev)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_force_clear(dev);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return tpm2_clear(dev, TPM2_RH_PLATFORM, NULL, 0);
 	else
 		return -ENOSYS;
@@ -220,11 +210,11 @@ u32 tpm_force_clear(struct udevice *dev)
 
 u32 tpm_physical_enable(struct udevice *dev)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_physical_enable(dev);
 
 	/* Nothing needs to be done with tpm2 */
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return 0;
 	else
 		return -ENOSYS;
@@ -232,11 +222,11 @@ u32 tpm_physical_enable(struct udevice *dev)
 
 u32 tpm_physical_disable(struct udevice *dev)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_physical_disable(dev);
 
 	/* Nothing needs to be done with tpm2 */
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return 0;
 	else
 		return -ENOSYS;
@@ -244,10 +234,10 @@ u32 tpm_physical_disable(struct udevice *dev)
 
 u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_physical_set_deactivated(dev, state);
 	/* Nothing needs to be done with tpm2 */
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return 0;
 	else
 		return -ENOSYS;
@@ -256,9 +246,9 @@ u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
 u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
 		       void *cap, size_t count)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_get_capability(dev, cap_area, sub_cap, cap, count);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return tpm2_get_capability(dev, cap_area, sub_cap, cap, count);
 	else
 		return -ENOSYS;
@@ -266,9 +256,9 @@ u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
 
 u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_get_permissions(dev, index, perm);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return -ENOSYS; /* not implemented yet */
 	else
 		return -ENOSYS;
@@ -276,9 +266,9 @@ u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
 
 u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
 {
-	if (is_tpm1(dev))
+	if (tpm_is_v1(dev))
 		return tpm1_get_random(dev, data, count);
-	else if (is_tpm2(dev))
+	else if (tpm_is_v2(dev))
 		return -ENOSYS; /* not implemented yet */
 	else
 		return -ENOSYS;
-- 
2.35.1.574.g5d30c73bfb-goog


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 2/8] tpm: Require a digest source when extending the PCR
  2022-03-01  0:11 [PATCH 0/8] tpm: Various minor fixes and enhancements Simon Glass
  2022-03-01  0:11 ` [PATCH 1/8] tpm: Export the TPM-version functions Simon Glass
@ 2022-03-01  0:11 ` Simon Glass
  2022-06-07  8:42   ` Ilias Apalodimas
  2022-03-01  0:11 ` [PATCH 3/8] tpm: Correct the permissions command in TPMv1 Simon Glass
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Simon Glass @ 2022-03-01  0:11 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Simon Glass

This feature is used for measured boot. It is not currently supported in
the TPM drivers, but add it to the API so that code which expects it can
signal its request.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 cmd/tpm-v1.c      |  3 ++-
 cmd/tpm_test.c    |  5 +++--
 include/tpm_api.h |  8 +++++---
 lib/tpm-v2.c      |  2 ++
 lib/tpm_api.c     | 14 ++++++++++----
 5 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/cmd/tpm-v1.c b/cmd/tpm-v1.c
index bf238a9f2e..0869b70775 100644
--- a/cmd/tpm-v1.c
+++ b/cmd/tpm-v1.c
@@ -131,7 +131,8 @@ static int do_tpm_extend(struct cmd_tbl *cmdtp, int flag, int argc,
 		return CMD_RET_FAILURE;
 	}
 
-	rc = tpm_pcr_extend(dev, index, in_digest, out_digest);
+	rc = tpm_pcr_extend(dev, index, in_digest, sizeof(in_digest),
+			    out_digest, "test");
 	if (!rc) {
 		puts("PCR value after execution of the command:\n");
 		print_byte_string(out_digest, sizeof(out_digest));
diff --git a/cmd/tpm_test.c b/cmd/tpm_test.c
index a3ccb12f53..b35eae81dc 100644
--- a/cmd/tpm_test.c
+++ b/cmd/tpm_test.c
@@ -91,7 +91,8 @@ static int test_early_extend(struct udevice *dev)
 	tpm_init(dev);
 	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
 	TPM_CHECK(tpm_continue_self_test(dev));
-	TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, value_out));
+	TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, sizeof(value_in), value_out,
+				 "test"));
 	printf("done\n");
 	return 0;
 }
@@ -438,7 +439,7 @@ static int test_timing(struct udevice *dev)
 		   100);
 	TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
 		   100);
-	TTPM_CHECK(tpm_pcr_extend(dev, 0, in, out), 200);
+	TTPM_CHECK(tpm_pcr_extend(dev, 0, in, sizeof(in), out, "test"), 200);
 	TTPM_CHECK(tpm_set_global_lock(dev), 50);
 	TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100);
 	printf("done\n");
diff --git a/include/tpm_api.h b/include/tpm_api.h
index 11aa14eb79..3c8e48bc25 100644
--- a/include/tpm_api.h
+++ b/include/tpm_api.h
@@ -81,14 +81,16 @@ u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
  *
  * @param dev		TPM device
  * @param index		index of the PCR
- * @param in_digest	160-bit value representing the event to be
+ * @param in_digest	160/256-bit value representing the event to be
  *			recorded
- * @param out_digest	160-bit PCR value after execution of the
+ * @param size		size of digest in bytes
+ * @param out_digest	160/256-bit PCR value after execution of the
  *			command
+ * @param name		additional info about where the digest comes from
  * Return: return code of the operation
  */
 u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
-		   void *out_digest);
+		   uint size, void *out_digest, const char *name);
 
 /**
  * Issue a TPM_PCRRead command.
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index 1bf627853a..6058f2e1e4 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -157,6 +157,8 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
 	};
 	int ret;
 
+	if (!digest)
+		return -EINVAL;
 	/*
 	 * Fill the command structure starting from the first buffer:
 	 *     - the digest
diff --git a/lib/tpm_api.c b/lib/tpm_api.c
index 4ac4612c81..a8d3731d3a 100644
--- a/lib/tpm_api.c
+++ b/lib/tpm_api.c
@@ -140,15 +140,21 @@ u32 tpm_write_lock(struct udevice *dev, u32 index)
 }
 
 u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
-		   void *out_digest)
+		   uint size, void *out_digest, const char *name)
 {
-	if (tpm_is_v1(dev))
+	if (tpm_is_v1(dev)) {
+		if (size != PCR_DIGEST_LENGTH || !out_digest)
+			return -EINVAL;
 		return tpm1_extend(dev, index, in_digest, out_digest);
-	else if (tpm_is_v2(dev))
+	} else if (tpm_is_v2(dev)) {
+		if (size != TPM2_SHA256_DIGEST_SIZE)
+			return -EINVAL;
 		return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest,
 				       TPM2_DIGEST_LEN);
-	else
+		/* @name is ignored as we do not support measured boot */
+	} else {
 		return -ENOSYS;
+	}
 }
 
 u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
-- 
2.35.1.574.g5d30c73bfb-goog


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 3/8] tpm: Correct the permissions command in TPMv1
  2022-03-01  0:11 [PATCH 0/8] tpm: Various minor fixes and enhancements Simon Glass
  2022-03-01  0:11 ` [PATCH 1/8] tpm: Export the TPM-version functions Simon Glass
  2022-03-01  0:11 ` [PATCH 2/8] tpm: Require a digest source when extending the PCR Simon Glass
@ 2022-03-01  0:11 ` Simon Glass
  2022-06-07  8:44   ` Ilias Apalodimas
  2022-03-01  0:11 ` [PATCH 4/8] tpm: Correct the define-space command in TPMv2 Simon Glass
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Simon Glass @ 2022-03-01  0:11 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Simon Glass

The offset here is incorrect. Fix it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 lib/tpm-v1.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c
index 22a769c587..d0e3ab1b21 100644
--- a/lib/tpm-v1.c
+++ b/lib/tpm-v1.c
@@ -456,12 +456,13 @@ u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm)
 		0x0, 0x0, 0x0, 0x4,
 	};
 	const size_t index_offset = 18;
-	const size_t perm_offset = 60;
+	const size_t perm_offset = 74;
 	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
 	size_t response_length = sizeof(response);
 	u32 err;
 
-	if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
+	if (pack_byte_string(buf, sizeof(buf), "sd",
+			     0, command, sizeof(command),
 			     index_offset, index))
 		return TPM_LIB_ERROR;
 	err = tpm_sendrecv_command(dev, buf, response, &response_length);
-- 
2.35.1.574.g5d30c73bfb-goog


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 4/8] tpm: Correct the define-space command in TPMv2
  2022-03-01  0:11 [PATCH 0/8] tpm: Various minor fixes and enhancements Simon Glass
                   ` (2 preceding siblings ...)
  2022-03-01  0:11 ` [PATCH 3/8] tpm: Correct the permissions command in TPMv1 Simon Glass
@ 2022-03-01  0:11 ` Simon Glass
  2022-06-07  8:46   ` Ilias Apalodimas
  2022-03-01  0:11 ` [PATCH 5/8] tpm: sandbox: Allow init of TPM in a different phase Simon Glass
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Simon Glass @ 2022-03-01  0:11 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Simon Glass

The message format is incorrect. Fix it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 lib/tpm-v2.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index 6058f2e1e4..fe99b9c863 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -89,14 +89,14 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
 	 * Calculate the offset of the nv_policy piece by adding each of the
 	 * chunks below.
 	 */
-	uint offset = 10 + 8 + 13 + 14;
+	uint offset = 10 + 4 + 13 + 14;
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
 		/* header 10 bytes */
 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
-		tpm_u32(offset + nv_policy_size),/* Length */
+		tpm_u32(offset + nv_policy_size + 2),/* Length */
 		tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
 
-		/* handles 8 bytes */
+		/* handles 4 bytes */
 		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
 
 		/* session header 13 bytes */
@@ -107,12 +107,15 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
 		tpm_u16(0),			/* auth_size */
 
 		/* message 14 bytes + policy */
-		tpm_u16(12 + nv_policy_size),	/* size */
+		tpm_u16(12 + nv_policy_size + 2),	/* size */
 		tpm_u32(space_index),
 		tpm_u16(TPM2_ALG_SHA256),
 		tpm_u32(nv_attributes),
 		tpm_u16(nv_policy_size),
-		/* nv_policy */
+		/*
+		 * nv_policy
+		 * space_size
+		 */
 	};
 	int ret;
 
@@ -120,8 +123,9 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
 	 * Fill the command structure starting from the first buffer:
 	 *     - the password (if any)
 	 */
-	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
-			       offset, nv_policy, nv_policy_size);
+	ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
+			       offset, nv_policy, nv_policy_size,
+			       offset + nv_policy_size, space_size);
 	if (ret)
 		return TPM_LIB_ERROR;
 
-- 
2.35.1.574.g5d30c73bfb-goog


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 5/8] tpm: sandbox: Allow init of TPM in a different phase
  2022-03-01  0:11 [PATCH 0/8] tpm: Various minor fixes and enhancements Simon Glass
                   ` (3 preceding siblings ...)
  2022-03-01  0:11 ` [PATCH 4/8] tpm: Correct the define-space command in TPMv2 Simon Glass
@ 2022-03-01  0:11 ` Simon Glass
  2022-06-07  8:48   ` Ilias Apalodimas
  2022-03-01  0:11 ` [PATCH 6/8] tpm: Allow reporting the internal state Simon Glass
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Simon Glass @ 2022-03-01  0:11 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Simon Glass

At present the emulator assumes that the TPM is inited in the same phase
where it is used. But in fact SPL may init the TPM, so we don't want to
complain when U-Boot proper later uses it. Remove this check.

It might be best to save this information into the device state for the
TPM, so that we can make sure the TPM was inited at some point. For now,
this seems good enough.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/tpm/tpm2_tis_sandbox.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index ac6eb14353..c26f5d35ab 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -366,8 +366,10 @@ static int sandbox_tpm2_check_readyness(struct udevice *dev, int command)
 
 		break;
 	default:
-		if (!tpm->tests_done)
-			return TPM2_RC_NEEDS_TEST;
+		/* Skip this, since the startup may have happened in SPL
+		 * if (!tpm->tests_done)
+		 *    return TPM2_RC_NEEDS_TEST;
+		 */
 
 		break;
 	}
-- 
2.35.1.574.g5d30c73bfb-goog


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 6/8] tpm: Allow reporting the internal state
  2022-03-01  0:11 [PATCH 0/8] tpm: Various minor fixes and enhancements Simon Glass
                   ` (4 preceding siblings ...)
  2022-03-01  0:11 ` [PATCH 5/8] tpm: sandbox: Allow init of TPM in a different phase Simon Glass
@ 2022-03-01  0:11 ` Simon Glass
  2022-03-01  0:11 ` [PATCH 7/8] tpm: Implement state command for Cr50 Simon Glass
  2022-03-01  0:11 ` [PATCH 8/8] tpm: Allow commiting non-volatile data Simon Glass
  7 siblings, 0 replies; 19+ messages in thread
From: Simon Glass @ 2022-03-01  0:11 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Simon Glass

It is useful to read information about the current TPM state, where
supported, e.g. for debugging purposes when verified boot fails.

Add support for this to the TPM interface as well as Cr50. Add a simple
sandbox test.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 cmd/tpm-common.c               | 20 ++++++++++++++++++++
 cmd/tpm-user-utils.h           |  2 ++
 cmd/tpm-v2.c                   |  3 +++
 drivers/tpm/tpm-uclass.c       | 10 ++++++++++
 drivers/tpm/tpm2_tis_sandbox.c | 11 +++++++++++
 include/tpm-common.h           | 20 ++++++++++++++++++++
 test/dm/Makefile               |  1 +
 test/dm/tpm.c                  | 34 ++++++++++++++++++++++++++++++++++
 8 files changed, 101 insertions(+)
 create mode 100644 test/dm/tpm.c

diff --git a/cmd/tpm-common.c b/cmd/tpm-common.c
index 47adaffd18..d0c63cadf4 100644
--- a/cmd/tpm-common.c
+++ b/cmd/tpm-common.c
@@ -333,6 +333,26 @@ int do_tpm_info(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	return 0;
 }
 
+int do_tpm_report_state(struct cmd_tbl *cmdtp, int flag, int argc,
+			char *const argv[])
+{
+	struct udevice *dev;
+	char buf[80];
+	int rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
+	rc = tpm_report_state(dev, buf, sizeof(buf));
+	if (rc < 0) {
+		printf("Couldn't get TPM state (%d)\n", rc);
+		return CMD_RET_FAILURE;
+	}
+	printf("%s\n", buf);
+
+	return 0;
+}
+
 int do_tpm_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
 	struct udevice *dev;
diff --git a/cmd/tpm-user-utils.h b/cmd/tpm-user-utils.h
index 358ddff576..de4a934aab 100644
--- a/cmd/tpm-user-utils.h
+++ b/cmd/tpm-user-utils.h
@@ -21,6 +21,8 @@ int do_tpm_device(struct cmd_tbl *cmdtp, int flag, int argc,
 		  char *const argv[]);
 int do_tpm_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tpm_info(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_tpm_report_state(struct cmd_tbl *cmdtp, int flag, int argc,
+			char *const argv[]);
 int do_tpm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
 #endif /* __TPM_USER_UTILS_H */
diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c
index 4ea5f9f094..d93b83ada9 100644
--- a/cmd/tpm-v2.c
+++ b/cmd/tpm-v2.c
@@ -359,6 +359,7 @@ static int do_tpm_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
 static struct cmd_tbl tpm2_commands[] = {
 	U_BOOT_CMD_MKENT(device, 0, 1, do_tpm_device, "", ""),
 	U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
+	U_BOOT_CMD_MKENT(state, 0, 1, do_tpm_report_state, "", ""),
 	U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""),
 	U_BOOT_CMD_MKENT(startup, 0, 1, do_tpm2_startup, "", ""),
 	U_BOOT_CMD_MKENT(self_test, 0, 1, do_tpm2_self_test, "", ""),
@@ -389,6 +390,8 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
 "    Show all devices or set the specified device\n"
 "info\n"
 "    Show information about the TPM.\n"
+"state\n"
+"    Show internal state from the TPM (if available)\n"
 "init\n"
 "    Initialize the software stack. Always the first command to issue.\n"
 "startup <mode>\n"
diff --git a/drivers/tpm/tpm-uclass.c b/drivers/tpm/tpm-uclass.c
index f67fe1019b..5db3676216 100644
--- a/drivers/tpm/tpm-uclass.c
+++ b/drivers/tpm/tpm-uclass.c
@@ -45,6 +45,16 @@ int tpm_get_desc(struct udevice *dev, char *buf, int size)
 	return ops->get_desc(dev, buf, size);
 }
 
+int tpm_report_state(struct udevice *dev, char *buf, int size)
+{
+	struct tpm_ops *ops = tpm_get_ops(dev);
+
+	if (!ops->report_state)
+		return -ENOSYS;
+
+	return ops->report_state(dev, buf, size);
+}
+
 /* Returns max number of milliseconds to wait */
 static ulong tpm_tis_i2c_calc_ordinal_duration(struct tpm_chip_priv *priv,
 					       u32 ordinal)
diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index c26f5d35ab..dd94bdc31f 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -795,6 +795,16 @@ static int sandbox_tpm2_get_desc(struct udevice *dev, char *buf, int size)
 	return snprintf(buf, size, "Sandbox TPM2.x");
 }
 
+static int sandbox_tpm2_report_state(struct udevice *dev, char *buf, int size)
+{
+	struct sandbox_tpm2 *priv = dev_get_priv(dev);
+
+	if (size < 40)
+		return -ENOSPC;
+
+	return snprintf(buf, size, "init_done=%d", priv->init_done);
+}
+
 static int sandbox_tpm2_open(struct udevice *dev)
 {
 	struct sandbox_tpm2 *tpm = dev_get_priv(dev);
@@ -834,6 +844,7 @@ static const struct tpm_ops sandbox_tpm2_ops = {
 	.open		= sandbox_tpm2_open,
 	.close		= sandbox_tpm2_close,
 	.get_desc	= sandbox_tpm2_get_desc,
+	.report_state	= sandbox_tpm2_report_state,
 	.xfer		= sandbox_tpm2_xfer,
 };
 
diff --git a/include/tpm-common.h b/include/tpm-common.h
index a28629e701..b2c5404430 100644
--- a/include/tpm-common.h
+++ b/include/tpm-common.h
@@ -119,6 +119,16 @@ struct tpm_ops {
 	 */
 	int (*get_desc)(struct udevice *dev, char *buf, int size);
 
+	/**
+	 * report_state() - Collect information about the current TPM state
+	 *
+	 * @dev:	Device to check
+	 * @buf:	Buffer to put the string
+	 * @size:	Maximum size of buffer
+	 * Return: return code of the operation (0 = success)
+	 */
+	int (*report_state)(struct udevice *dev, char *buf, int size);
+
 	/**
 	 * send() - send data to the TPM
 	 *
@@ -234,6 +244,16 @@ u32 tpm_clear_and_reenable(struct udevice *dev);
  */
 int tpm_get_desc(struct udevice *dev, char *buf, int size);
 
+/**
+ * tpm_report_state() - Collect information about the current TPM state
+ *
+ * @dev:	Device to check
+ * @buf:	Buffer to put the string
+ * @size:	Maximum size of buffer
+ * Return: return code of the operation (0 = success)
+ */
+int tpm_report_state(struct udevice *dev, char *buf, int size);
+
 /**
  * tpm_xfer() - send data to the TPM and get response
  *
diff --git a/test/dm/Makefile b/test/dm/Makefile
index d46552fbf3..47363bdb15 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -104,6 +104,7 @@ obj-$(CONFIG_SYSINFO) += sysinfo.o
 obj-$(CONFIG_SYSINFO_GPIO) += sysinfo-gpio.o
 obj-$(CONFIG_TEE) += tee.o
 obj-$(CONFIG_TIMER) += timer.o
+obj-$(CONFIG_TPM_V2) += tpm.o
 obj-$(CONFIG_DM_USB) += usb.o
 obj-$(CONFIG_DM_VIDEO) += video.o
 obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
diff --git a/test/dm/tpm.c b/test/dm/tpm.c
new file mode 100644
index 0000000000..0b46f79959
--- /dev/null
+++ b/test/dm/tpm.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <tpm_api.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of the TPM uclass */
+static int dm_test_tpm(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	char buf[50];
+
+	/* check probe success */
+	ut_assertok(uclass_first_device_err(UCLASS_TPM, &dev));
+	ut_assert(tpm_is_v2(dev));
+
+	ut_assert(tpm_report_state(dev, buf, sizeof(buf)));
+	ut_asserteq_str("init_done=0", buf);
+
+	ut_assertok(tpm_init(dev));
+
+	ut_assert(tpm_report_state(dev, buf, sizeof(buf)));
+	ut_asserteq_str("init_done=1", buf);
+
+	return 0;
+}
+DM_TEST(dm_test_tpm, UT_TESTF_SCAN_FDT);
-- 
2.35.1.574.g5d30c73bfb-goog


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 7/8] tpm: Implement state command for Cr50
  2022-03-01  0:11 [PATCH 0/8] tpm: Various minor fixes and enhancements Simon Glass
                   ` (5 preceding siblings ...)
  2022-03-01  0:11 ` [PATCH 6/8] tpm: Allow reporting the internal state Simon Glass
@ 2022-03-01  0:11 ` Simon Glass
  2022-06-07  8:54   ` Ilias Apalodimas
  2022-03-01  0:11 ` [PATCH 8/8] tpm: Allow commiting non-volatile data Simon Glass
  7 siblings, 1 reply; 19+ messages in thread
From: Simon Glass @ 2022-03-01  0:11 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Simon Glass

Add a vendor-specific TPM2 command for this and implement it for Cr50.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/tpm/cr50_i2c.c | 117 +++++++++++++++++++++++++++++++++++++++++
 include/tpm-v2.h       |  54 +++++++++++++++++++
 lib/tpm-v2.c           |  24 +++++++++
 3 files changed, 195 insertions(+)

diff --git a/drivers/tpm/cr50_i2c.c b/drivers/tpm/cr50_i2c.c
index f8c3087894..dabf617be0 100644
--- a/drivers/tpm/cr50_i2c.c
+++ b/drivers/tpm/cr50_i2c.c
@@ -13,11 +13,13 @@
 #include <irq.h>
 #include <log.h>
 #include <spl.h>
+#include <tpm-common.h>
 #include <tpm-v2.h>
 #include <acpi/acpigen.h>
 #include <acpi/acpi_device.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
+#include <asm/unaligned.h>
 #include <linux/delay.h>
 #include <dm/acpi.h>
 
@@ -54,6 +56,41 @@ struct cr50_priv {
 	bool use_irq;
 };
 
+/*
+ * The below structure represents the body of the response to the 'report tpm
+ * state' vendor command.
+ *
+ * It is transferred over the wire, so it needs to be serialized/deserialized,
+ * and it is likely to change, so its contents must be versioned.
+ */
+#define TPM_STATE_VERSION	1
+struct tpm_vendor_state {
+	u32 version;
+	/*
+	 * The following three fields are set by the TPM in case of an assert.
+	 * There is no other processing than setting the source code line
+	 * number, error code and the first 4 characters of the function name.
+	 *
+	 * We don't expect this happening, but it is included in the report
+	 * just in case.
+	 */
+	u32 fail_line;	/* s_failLIne */
+	u32 fail_code;	/* s_failCode */
+	char func_name[4];	/* s_failFunction, limited to 4 chars */
+
+	/*
+	 * The following two fields are the current time filtered value of the
+	 * 'failed tries' TPM counter, and the maximum allowed value of the
+	 * counter.
+	 *
+	 * failed_tries == max_tries is the definition of the TPM lockout
+	 * condition.
+	 */
+	u32 failed_tries;	/* gp.failedTries */
+	u32 max_tries;	/* gp.maxTries */
+	/* The below fields are present in version 2 and above */
+};
+
 /* Wait for interrupt to indicate TPM is ready */
 static int cr50_i2c_wait_tpm_ready(struct udevice *dev)
 {
@@ -573,6 +610,85 @@ static int cr50_i2c_get_desc(struct udevice *dev, char *buf, int size)
 	return len;
 }
 
+static int stringify_state(char *buf, int len, char *str, size_t max_size)
+{
+	struct tpm_vendor_state state;
+	size_t text_size = 0;
+
+	state.version = get_unaligned_be32(buf +
+		offsetof(struct tpm_vendor_state, version));
+	state.fail_line = get_unaligned_be32(buf +
+		offsetof(struct tpm_vendor_state, fail_line));
+	state.fail_code = get_unaligned_be32(buf +
+		offsetof(struct tpm_vendor_state, fail_code));
+	memcpy(state.func_name,
+	       buf + offsetof(struct tpm_vendor_state, func_name),
+	       sizeof(state.func_name));
+	state.failed_tries = get_unaligned_be32(buf +
+		offsetof(struct tpm_vendor_state, failed_tries));
+	state.max_tries = get_unaligned_be32(buf +
+		offsetof(struct tpm_vendor_state, max_tries));
+
+	text_size += snprintf(str + text_size, max_size - text_size,
+			      "v=%d", state.version);
+	if (text_size >= max_size)
+		return -ENOSPC;
+
+	if (state.version > TPM_STATE_VERSION)
+		text_size += snprintf(str + text_size,
+				      max_size - text_size,
+				      " not fully supported\n");
+	if (text_size >= max_size)
+		return -ENOSPC;
+
+	if (state.version == 0)
+		return -EINVAL;	/* This should never happen */
+
+	text_size += snprintf(str + text_size,
+			      max_size - text_size,
+			      " failed_tries=%d max_tries=%d\n",
+			      state.failed_tries, state.max_tries);
+	if (text_size >= max_size)
+		return -ENOSPC;
+
+	if (state.fail_line) {
+		/* make sure function name is zero terminated. */
+		char func_name[sizeof(state.func_name) + 1];
+
+		memcpy(func_name, state.func_name, sizeof(state.func_name));
+		func_name[sizeof(state.func_name)] = '\0';
+
+		text_size += snprintf(str + text_size,
+				      max_size - text_size,
+				      "tpm failed: f %s line %d code %d",
+				      func_name,
+				      state.fail_line,
+				      state.fail_code);
+		if (text_size >= max_size)
+			return -ENOSPC;
+	}
+
+	return 0;
+}
+
+static int cr50_i2c_report_state(struct udevice *dev, char *str, int str_max)
+{
+	char buf[50];
+	int buf_size = sizeof(buf);
+	int ret;
+
+	ret = tpm2_cr50_report_state(dev, buf, &buf_size);
+	if (ret)
+		return ret;
+
+	/* TPM responded as expected */
+	ret = stringify_state(buf, buf_size, str, str_max);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int cr50_i2c_open(struct udevice *dev)
 {
 	char buf[80];
@@ -730,6 +846,7 @@ struct acpi_ops cr50_acpi_ops = {
 static const struct tpm_ops cr50_i2c_ops = {
 	.open		= cr50_i2c_open,
 	.get_desc	= cr50_i2c_get_desc,
+	.report_state	= cr50_i2c_report_state,
 	.send		= cr50_i2c_send,
 	.recv		= cr50_i2c_recv,
 	.cleanup	= cr50_i2c_cleanup,
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index e79c90b939..8e90a61622 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -419,6 +419,50 @@ enum {
 	HR_NV_INDEX		= TPM_HT_NV_INDEX << HR_SHIFT,
 };
 
+/*
+ * Operations specific to the Cr50 TPM used on Chromium OS and Android devices
+ *
+ * FIXME: below is not enough to differentiate between vendors commands
+ * of numerous devices. However, the current tpm2 APIs aren't very amenable
+ * to extending generically because the marshaling code is assuming all
+ * knowledge of all commands.
+ */
+#define TPM2_CC_VENDOR_BIT_MASK			0x20000000
+
+#define TPM2_CR50_VENDOR_COMMAND		(TPM2_CC_VENDOR_BIT_MASK | 0)
+#define TPM2_CR50_SUB_CMD_IMMEDIATE_RESET	19
+#define TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS	21
+#define TPM2_CR50_SUB_CMD_REPORT_TPM_STATE	23
+#define TPM2_CR50_SUB_CMD_TURN_UPDATE_ON	24
+#define TPM2_CR50_SUB_CMD_GET_REC_BTN		29
+#define TPM2_CR50_SUB_CMD_TPM_MODE		40
+#define TPM2_CR50_SUB_CMD_GET_BOOT_MODE		52
+#define TPM2_CR50_SUB_CMD_RESET_EC		53
+
+/* Cr50 vendor-specific error codes. */
+#define VENDOR_RC_ERR              0x00000500
+enum cr50_vendor_rc {
+	VENDOR_RC_INTERNAL_ERROR	= (VENDOR_RC_ERR | 6),
+	VENDOR_RC_NO_SUCH_SUBCOMMAND	= (VENDOR_RC_ERR | 8),
+	VENDOR_RC_NO_SUCH_COMMAND	= (VENDOR_RC_ERR | 127),
+};
+
+enum cr50_tpm_mode {
+	/*
+	 * Default state: TPM is enabled, and may be set to either
+	 * TPM_MODE_ENABLED or TPM_MODE_DISABLED.
+	 */
+	TPM_MODE_ENABLED_TENTATIVE = 0,
+
+	/* TPM is enabled, and mode may not be changed. */
+	TPM_MODE_ENABLED = 1,
+
+	/* TPM is disabled, and mode may not be changed. */
+	TPM_MODE_DISABLED = 2,
+
+	TPM_MODE_INVALID,
+};
+
 /**
  * Issue a TPM2_Startup command.
  *
@@ -658,4 +702,14 @@ u32 tpm2_disable_platform_hierarchy(struct udevice *dev);
 u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
 			u8 *recvbuf, size_t *recv_size);
 
+/**
+ * tpm_cr50_report_state() - Report the Cr50 internal state
+ *
+ * @dev:	TPM device
+ * @recvbuf:	Buffer to save the response to
+ * @recv_size:	Pointer to the size of the response buffer
+ * Return: result of the operation
+ */
+u32 tpm2_cr50_report_state(struct udevice *dev, u8 *recvbuf, size_t *recv_size);
+
 #endif /* __TPM_V2_H */
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index fe99b9c863..bdf019b0f9 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -675,3 +675,27 @@ u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
 {
 	return tpm_sendrecv_command(dev, sendbuf, recvbuf, recv_size);
 }
+
+u32 tpm2_cr50_report_state(struct udevice *dev, u8 *recvbuf, size_t *recv_size)
+{
+	u8 command_v2[COMMAND_BUFFER_SIZE] = {
+		/* header 10 bytes */
+		tpm_u16(TPM2_ST_NO_SESSIONS),		/* TAG */
+		tpm_u32(10 + 2),			/* Length */
+		tpm_u32(TPM2_CR50_VENDOR_COMMAND),	/* Command code */
+
+		tpm_u16(TPM2_CR50_SUB_CMD_REPORT_TPM_STATE),
+	};
+	int ret;
+
+	ret = tpm_sendrecv_command(dev, command_v2, recvbuf, recv_size);
+	log_debug("ret=%s, %x\n", dev->name, ret);
+	if (ret)
+		return ret;
+	if (*recv_size < 12)
+		return -ENODATA;
+	*recv_size -= 12;
+	memcpy(recvbuf, recvbuf + 12, *recv_size);
+
+	return 0;
+}
-- 
2.35.1.574.g5d30c73bfb-goog


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 8/8] tpm: Allow commiting non-volatile data
  2022-03-01  0:11 [PATCH 0/8] tpm: Various minor fixes and enhancements Simon Glass
                   ` (6 preceding siblings ...)
  2022-03-01  0:11 ` [PATCH 7/8] tpm: Implement state command for Cr50 Simon Glass
@ 2022-03-01  0:11 ` Simon Glass
  7 siblings, 0 replies; 19+ messages in thread
From: Simon Glass @ 2022-03-01  0:11 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Simon Glass

Add an option to tell the TPM to commit non-volatile data immediately it
is changed, rather than waiting until later. This is needed in some
situations, since if the device reboots it may not write the data.

Add definitions for the rest of the Cr50 commands while we are here.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/tpm-v2.h | 14 ++++++++++++++
 lib/tpm-v2.c     | 20 ++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 8e90a61622..0a03994740 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -712,4 +712,18 @@ u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
  */
 u32 tpm2_cr50_report_state(struct udevice *dev, u8 *recvbuf, size_t *recv_size);
 
+/*
+ * tpm2_cr50_enable_nvcommits() - Tell Cr50 to commit NV data immediately
+ *
+ * For Chromium OS verified boot, we may reboot or reset at different times,
+ * possibly leaving non-volatile data unwritten by the TPM.
+ *
+ * This vendor command is used to indicate that non-volatile data should be
+ * written to its store immediately.
+ *
+ * @dev		TPM device
+ * Return: result of the operation
+ */
+u32 tpm2_cr50_enable_nvcommits(struct udevice *dev);
+
 #endif /* __TPM_V2_H */
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index bdf019b0f9..5fcd3649b7 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -699,3 +699,23 @@ u32 tpm2_cr50_report_state(struct udevice *dev, u8 *recvbuf, size_t *recv_size)
 
 	return 0;
 }
+
+u32 tpm2_cr50_enable_nvcommits(struct udevice *dev)
+{
+	u8 command_v2[COMMAND_BUFFER_SIZE] = {
+		/* header 10 bytes */
+		tpm_u16(TPM2_ST_NO_SESSIONS),		/* TAG */
+		tpm_u32(10 + 2),			/* Length */
+		tpm_u32(TPM2_CR50_VENDOR_COMMAND),	/* Command code */
+
+		tpm_u16(TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS),
+	};
+	int ret;
+
+	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+	log_debug("ret=%s, %x\n", dev->name, ret);
+	if (ret)
+		return ret;
+
+	return 0;
+}
-- 
2.35.1.574.g5d30c73bfb-goog


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/8] tpm: Export the TPM-version functions
  2022-03-01  0:11 ` [PATCH 1/8] tpm: Export the TPM-version functions Simon Glass
@ 2022-06-07  8:28   ` Ilias Apalodimas
  0 siblings, 0 replies; 19+ messages in thread
From: Ilias Apalodimas @ 2022-06-07  8:28 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List

Hi Simon, 

Apologies the late reply.  I wasn't cc'ed on those and missed them in my
mailbox.

On Mon, Feb 28, 2022 at 05:11:18PM -0700, Simon Glass wrote:
> These functions should really be available outside the TPM code, so that
> other callers can find out which version the TPM is. Rename them to have
> a tpm_ prefix() and add them to the header file.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  include/tpm_api.h | 10 ++++++
>  lib/tpm_api.c     | 92 +++++++++++++++++++++--------------------------
>  2 files changed, 51 insertions(+), 51 deletions(-)
> 
> diff --git a/include/tpm_api.h b/include/tpm_api.h
> index ef45b43a8f..11aa14eb79 100644
> --- a/include/tpm_api.h
> +++ b/include/tpm_api.h
> @@ -319,4 +319,14 @@ u32 tpm_write_lock(struct udevice *dev, u32 index);
>   */
>  u32 tpm_resume(struct udevice *dev);
>  
> +static inline bool tpm_is_v1(struct udevice *dev)
> +{
> +	return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1;
> +}
> +
> +static inline bool tpm_is_v2(struct udevice *dev)
> +{
> +	return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2;
> +}
> +
>  #endif /* __TPM_API_H */
> diff --git a/lib/tpm_api.c b/lib/tpm_api.c
> index 4c662640a9..4ac4612c81 100644
> --- a/lib/tpm_api.c
> +++ b/lib/tpm_api.c
> @@ -11,21 +11,11 @@
>  #include <tpm-v2.h>
>  #include <tpm_api.h>
>  
> -static bool is_tpm1(struct udevice *dev)
> -{
> -	return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1;
> -}
> -
> -static bool is_tpm2(struct udevice *dev)
> -{
> -	return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2;
> -}
> -
>  u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
>  {
> -	if (is_tpm1(dev)) {
> +	if (tpm_is_v1(dev)) {
>  		return tpm1_startup(dev, mode);
> -	} else if (is_tpm2(dev)) {
> +	} else if (tpm_is_v2(dev)) {
>  		enum tpm2_startup_types type;
>  
>  		switch (mode) {
> @@ -47,9 +37,9 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
>  
>  u32 tpm_resume(struct udevice *dev)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_startup(dev, TPM_ST_STATE);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return tpm2_startup(dev, TPM2_SU_STATE);
>  	else
>  		return -ENOSYS;
> @@ -57,9 +47,9 @@ u32 tpm_resume(struct udevice *dev)
>  
>  u32 tpm_self_test_full(struct udevice *dev)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_self_test_full(dev);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return tpm2_self_test(dev, TPMI_YES);
>  	else
>  		return -ENOSYS;
> @@ -67,9 +57,9 @@ u32 tpm_self_test_full(struct udevice *dev)
>  
>  u32 tpm_continue_self_test(struct udevice *dev)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_continue_self_test(dev);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return tpm2_self_test(dev, TPMI_NO);
>  	else
>  		return -ENOSYS;
> @@ -86,7 +76,7 @@ u32 tpm_clear_and_reenable(struct udevice *dev)
>  		return ret;
>  	}
>  
> -	if (is_tpm1(dev)) {
> +	if (tpm_is_v1(dev)) {
>  		ret = tpm1_physical_enable(dev);
>  		if (ret != TPM_SUCCESS) {
>  			log_err("TPM: Can't set enabled state\n");
> @@ -105,9 +95,9 @@ u32 tpm_clear_and_reenable(struct udevice *dev)
>  
>  u32 tpm_nv_enable_locking(struct udevice *dev)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return -ENOSYS;
>  	else
>  		return -ENOSYS;
> @@ -115,9 +105,9 @@ u32 tpm_nv_enable_locking(struct udevice *dev)
>  
>  u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_nv_read_value(dev, index, data, count);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return tpm2_nv_read_value(dev, index, data, count);
>  	else
>  		return -ENOSYS;
> @@ -126,9 +116,9 @@ u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
>  u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
>  		       u32 count)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_nv_write_value(dev, index, data, count);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return tpm2_nv_write_value(dev, index, data, count);
>  	else
>  		return -ENOSYS;
> @@ -141,9 +131,9 @@ u32 tpm_set_global_lock(struct udevice *dev)
>  
>  u32 tpm_write_lock(struct udevice *dev, u32 index)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return -ENOSYS;
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return tpm2_write_lock(dev, index);
>  	else
>  		return -ENOSYS;
> @@ -152,9 +142,9 @@ u32 tpm_write_lock(struct udevice *dev, u32 index)
>  u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
>  		   void *out_digest)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_extend(dev, index, in_digest, out_digest);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest,
>  				       TPM2_DIGEST_LEN);
>  	else
> @@ -163,9 +153,9 @@ u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
>  
>  u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_pcr_read(dev, index, data, count);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return -ENOSYS;
>  	else
>  		return -ENOSYS;
> @@ -173,14 +163,14 @@ u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
>  
>  u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_tsc_physical_presence(dev, presence);
>  
>  	/*
>  	 * Nothing to do on TPM2 for this; use platform hierarchy availability
>  	 * instead.
>  	 */
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return 0;
>  	else
>  		return -ENOSYS;
> @@ -188,11 +178,11 @@ u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
>  
>  u32 tpm_finalise_physical_presence(struct udevice *dev)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_finalise_physical_presence(dev);
>  
>  	/* Nothing needs to be done with tpm2 */
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return 0;
>  	else
>  		return -ENOSYS;
> @@ -200,9 +190,9 @@ u32 tpm_finalise_physical_presence(struct udevice *dev)
>  
>  u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_read_pubek(dev, data, count);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return -ENOSYS; /* not implemented yet */
>  	else
>  		return -ENOSYS;
> @@ -210,9 +200,9 @@ u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
>  
>  u32 tpm_force_clear(struct udevice *dev)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_force_clear(dev);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return tpm2_clear(dev, TPM2_RH_PLATFORM, NULL, 0);
>  	else
>  		return -ENOSYS;
> @@ -220,11 +210,11 @@ u32 tpm_force_clear(struct udevice *dev)
>  
>  u32 tpm_physical_enable(struct udevice *dev)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_physical_enable(dev);
>  
>  	/* Nothing needs to be done with tpm2 */
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return 0;
>  	else
>  		return -ENOSYS;
> @@ -232,11 +222,11 @@ u32 tpm_physical_enable(struct udevice *dev)
>  
>  u32 tpm_physical_disable(struct udevice *dev)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_physical_disable(dev);
>  
>  	/* Nothing needs to be done with tpm2 */
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return 0;
>  	else
>  		return -ENOSYS;
> @@ -244,10 +234,10 @@ u32 tpm_physical_disable(struct udevice *dev)
>  
>  u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_physical_set_deactivated(dev, state);
>  	/* Nothing needs to be done with tpm2 */
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return 0;
>  	else
>  		return -ENOSYS;
> @@ -256,9 +246,9 @@ u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
>  u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
>  		       void *cap, size_t count)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_get_capability(dev, cap_area, sub_cap, cap, count);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return tpm2_get_capability(dev, cap_area, sub_cap, cap, count);
>  	else
>  		return -ENOSYS;
> @@ -266,9 +256,9 @@ u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
>  
>  u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_get_permissions(dev, index, perm);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return -ENOSYS; /* not implemented yet */
>  	else
>  		return -ENOSYS;
> @@ -276,9 +266,9 @@ u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
>  
>  u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
>  {
> -	if (is_tpm1(dev))
> +	if (tpm_is_v1(dev))
>  		return tpm1_get_random(dev, data, count);
> -	else if (is_tpm2(dev))
> +	else if (tpm_is_v2(dev))
>  		return -ENOSYS; /* not implemented yet */
>  	else
>  		return -ENOSYS;
> -- 
> 2.35.1.574.g5d30c73bfb-goog
> 

Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/8] tpm: Require a digest source when extending the PCR
  2022-03-01  0:11 ` [PATCH 2/8] tpm: Require a digest source when extending the PCR Simon Glass
@ 2022-06-07  8:42   ` Ilias Apalodimas
  2022-08-14 23:29     ` Simon Glass
  0 siblings, 1 reply; 19+ messages in thread
From: Ilias Apalodimas @ 2022-06-07  8:42 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List

On Mon, Feb 28, 2022 at 05:11:19PM -0700, Simon Glass wrote:
> This feature is used for measured boot. It is not currently supported in
> the TPM drivers, but add it to the API so that code which expects it can
> signal its request.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  cmd/tpm-v1.c      |  3 ++-
>  cmd/tpm_test.c    |  5 +++--
>  include/tpm_api.h |  8 +++++---
>  lib/tpm-v2.c      |  2 ++
>  lib/tpm_api.c     | 14 ++++++++++----
>  5 files changed, 22 insertions(+), 10 deletions(-)
> 
> diff --git a/cmd/tpm-v1.c b/cmd/tpm-v1.c
> index bf238a9f2e..0869b70775 100644
> --- a/cmd/tpm-v1.c
> +++ b/cmd/tpm-v1.c
> @@ -131,7 +131,8 @@ static int do_tpm_extend(struct cmd_tbl *cmdtp, int flag, int argc,
>  		return CMD_RET_FAILURE;
>  	}
>  
> -	rc = tpm_pcr_extend(dev, index, in_digest, out_digest);
> +	rc = tpm_pcr_extend(dev, index, in_digest, sizeof(in_digest),
> +			    out_digest, "test");

Where is the output value of an extended PCR needed in measured boot?
IMHO this out_digest seems pointless.  I'd be happier if we just completely
removed it and make the v2 variant look like v1 more. 

>  	if (!rc) {
>  		puts("PCR value after execution of the command:\n");
>  		print_byte_string(out_digest, sizeof(out_digest));
> diff --git a/cmd/tpm_test.c b/cmd/tpm_test.c
> index a3ccb12f53..b35eae81dc 100644
> --- a/cmd/tpm_test.c
> +++ b/cmd/tpm_test.c
> @@ -91,7 +91,8 @@ static int test_early_extend(struct udevice *dev)
>  	tpm_init(dev);
>  	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
>  	TPM_CHECK(tpm_continue_self_test(dev));
> -	TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, value_out));
> +	TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, sizeof(value_in), value_out,
> +				 "test"));
>  	printf("done\n");
>  	return 0;
>  }
> @@ -438,7 +439,7 @@ static int test_timing(struct udevice *dev)
>  		   100);
>  	TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
>  		   100);
> -	TTPM_CHECK(tpm_pcr_extend(dev, 0, in, out), 200);
> +	TTPM_CHECK(tpm_pcr_extend(dev, 0, in, sizeof(in), out, "test"), 200);
>  	TTPM_CHECK(tpm_set_global_lock(dev), 50);
>  	TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100);
>  	printf("done\n");
> diff --git a/include/tpm_api.h b/include/tpm_api.h
> index 11aa14eb79..3c8e48bc25 100644
> --- a/include/tpm_api.h
> +++ b/include/tpm_api.h
> @@ -81,14 +81,16 @@ u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
>   *
>   * @param dev		TPM device
>   * @param index		index of the PCR
> - * @param in_digest	160-bit value representing the event to be
> + * @param in_digest	160/256-bit value representing the event to be
>   *			recorded
> - * @param out_digest	160-bit PCR value after execution of the
> + * @param size		size of digest in bytes
> + * @param out_digest	160/256-bit PCR value after execution of the
>   *			command
> + * @param name		additional info about where the digest comes from
>   * Return: return code of the operation
>   */
>  u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
> -		   void *out_digest);
> +		   uint size, void *out_digest, const char *name);
>  
>  /**
>   * Issue a TPM_PCRRead command.
> diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> index 1bf627853a..6058f2e1e4 100644
> --- a/lib/tpm-v2.c
> +++ b/lib/tpm-v2.c
> @@ -157,6 +157,8 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
>  	};
>  	int ret;
>  
> +	if (!digest)
> +		return -EINVAL;
>  	/*
>  	 * Fill the command structure starting from the first buffer:
>  	 *     - the digest
> diff --git a/lib/tpm_api.c b/lib/tpm_api.c
> index 4ac4612c81..a8d3731d3a 100644
> --- a/lib/tpm_api.c
> +++ b/lib/tpm_api.c
> @@ -140,15 +140,21 @@ u32 tpm_write_lock(struct udevice *dev, u32 index)
>  }
>  
>  u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
> -		   void *out_digest)
> +		   uint size, void *out_digest, const char *name)
>  {
> -	if (tpm_is_v1(dev))
> +	if (tpm_is_v1(dev)) {
> +		if (size != PCR_DIGEST_LENGTH || !out_digest)
> +			return -EINVAL;
>  		return tpm1_extend(dev, index, in_digest, out_digest);
> -	else if (tpm_is_v2(dev))
> +	} else if (tpm_is_v2(dev)) {
> +		if (size != TPM2_SHA256_DIGEST_SIZE)
> +			return -EINVAL;

Why are we limiting this?  This is supposed to be dictated by the PCR bank
configuration of each hardware 

>  		return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest,
>  				       TPM2_DIGEST_LEN);
> -	else
> +		/* @name is ignored as we do not support measured boot */
> +	} else {
>  		return -ENOSYS;
> +	}
>  }
>  
>  u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
> -- 
> 2.35.1.574.g5d30c73bfb-goog
> 

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/8] tpm: Correct the permissions command in TPMv1
  2022-03-01  0:11 ` [PATCH 3/8] tpm: Correct the permissions command in TPMv1 Simon Glass
@ 2022-06-07  8:44   ` Ilias Apalodimas
  2022-08-14 23:29     ` Simon Glass
  0 siblings, 1 reply; 19+ messages in thread
From: Ilias Apalodimas @ 2022-06-07  8:44 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List

Hi Simon, 

On Mon, Feb 28, 2022 at 05:11:20PM -0700, Simon Glass wrote:
> The offset here is incorrect. Fix it.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  lib/tpm-v1.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c
> index 22a769c587..d0e3ab1b21 100644
> --- a/lib/tpm-v1.c
> +++ b/lib/tpm-v1.c
> @@ -456,12 +456,13 @@ u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm)
>  		0x0, 0x0, 0x0, 0x4,
>  	};
>  	const size_t index_offset = 18;
> -	const size_t perm_offset = 60;
> +	const size_t perm_offset = 74;

This is fine, but I hate all these magic values sprinkled around the TPM
APIs.  Starting with this patch can we do the right thing and at lease have
those in a #define with a names that makes some sense?

>  	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
>  	size_t response_length = sizeof(response);
>  	u32 err;
>  
> -	if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
> +	if (pack_byte_string(buf, sizeof(buf), "sd",
> +			     0, command, sizeof(command),
>  			     index_offset, index))
>  		return TPM_LIB_ERROR;
>  	err = tpm_sendrecv_command(dev, buf, response, &response_length);
> -- 
> 2.35.1.574.g5d30c73bfb-goog
> 

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 4/8] tpm: Correct the define-space command in TPMv2
  2022-03-01  0:11 ` [PATCH 4/8] tpm: Correct the define-space command in TPMv2 Simon Glass
@ 2022-06-07  8:46   ` Ilias Apalodimas
  2022-08-14 23:29     ` Simon Glass
  0 siblings, 1 reply; 19+ messages in thread
From: Ilias Apalodimas @ 2022-06-07  8:46 UTC (permalink / raw)
  Cc: U-Boot Mailing List

Hi Simon, 

Thanks for fixing this. 
On Mon, Feb 28, 2022 at 05:11:21PM -0700, Simon Glass wrote:
> The message format is incorrect. Fix it.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  lib/tpm-v2.c | 18 +++++++++++-------
>  1 file changed, 11 insertions(+), 7 deletions(-)
> 
> diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> index 6058f2e1e4..fe99b9c863 100644
> --- a/lib/tpm-v2.c
> +++ b/lib/tpm-v2.c
> @@ -89,14 +89,14 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
>  	 * Calculate the offset of the nv_policy piece by adding each of the
>  	 * chunks below.
>  	 */
> -	uint offset = 10 + 8 + 13 + 14;
> +	uint offset = 10 + 4 + 13 + 14;
>  	u8 command_v2[COMMAND_BUFFER_SIZE] = {
>  		/* header 10 bytes */
>  		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
> -		tpm_u32(offset + nv_policy_size),/* Length */
> +		tpm_u32(offset + nv_policy_size + 2),/* Length */
>  		tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
>  
> -		/* handles 8 bytes */
> +		/* handles 4 bytes */
>  		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */

Similar to my comment on the previous patches,  please send a version with
defines that gets rid of the magic numbers (offset, +2 on nv_policy_size etc)

>  
>  		/* session header 13 bytes */
> @@ -107,12 +107,15 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
>  		tpm_u16(0),			/* auth_size */
>  
>  		/* message 14 bytes + policy */
> -		tpm_u16(12 + nv_policy_size),	/* size */
> +		tpm_u16(12 + nv_policy_size + 2),	/* size */
>  		tpm_u32(space_index),
>  		tpm_u16(TPM2_ALG_SHA256),
>  		tpm_u32(nv_attributes),
>  		tpm_u16(nv_policy_size),
> -		/* nv_policy */
> +		/*
> +		 * nv_policy
> +		 * space_size
> +		 */
>  	};
>  	int ret;
>  
> @@ -120,8 +123,9 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
>  	 * Fill the command structure starting from the first buffer:
>  	 *     - the password (if any)
>  	 */
> -	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
> -			       offset, nv_policy, nv_policy_size);
> +	ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
> +			       offset, nv_policy, nv_policy_size,
> +			       offset + nv_policy_size, space_size);
>  	if (ret)
>  		return TPM_LIB_ERROR;
>  
> -- 
> 2.35.1.574.g5d30c73bfb-goog
> 


Cheers
/Ilias

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 5/8] tpm: sandbox: Allow init of TPM in a different phase
  2022-03-01  0:11 ` [PATCH 5/8] tpm: sandbox: Allow init of TPM in a different phase Simon Glass
@ 2022-06-07  8:48   ` Ilias Apalodimas
  0 siblings, 0 replies; 19+ messages in thread
From: Ilias Apalodimas @ 2022-06-07  8:48 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List

Hi Simon, 

On Mon, Feb 28, 2022 at 05:11:22PM -0700, Simon Glass wrote:
> At present the emulator assumes that the TPM is inited in the same phase
> where it is used. But in fact SPL may init the TPM, so we don't want to
> complain when U-Boot proper later uses it. Remove this check.
> 
> It might be best to save this information into the device state for the
> TPM, so that we can make sure the TPM was inited at some point. For now,
> this seems good enough.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  drivers/tpm/tpm2_tis_sandbox.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
> index ac6eb14353..c26f5d35ab 100644
> --- a/drivers/tpm/tpm2_tis_sandbox.c
> +++ b/drivers/tpm/tpm2_tis_sandbox.c
> @@ -366,8 +366,10 @@ static int sandbox_tpm2_check_readyness(struct udevice *dev, int command)
>  
>  		break;
>  	default:
> -		if (!tpm->tests_done)
> -			return TPM2_RC_NEEDS_TEST;
> +		/* Skip this, since the startup may have happened in SPL
> +		 * if (!tpm->tests_done)
> +		 *    return TPM2_RC_NEEDS_TEST;
> +		 */


This looks reasonable.  On top of that the TPM will return 'already
initialized' if someone tries to do that after SPL, so we should be safe.

>  
>  		break;
>  	}
> -- 
> 2.35.1.574.g5d30c73bfb-goog
> 

Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 7/8] tpm: Implement state command for Cr50
  2022-03-01  0:11 ` [PATCH 7/8] tpm: Implement state command for Cr50 Simon Glass
@ 2022-06-07  8:54   ` Ilias Apalodimas
  2022-08-14 23:29     ` Simon Glass
  0 siblings, 1 reply; 19+ messages in thread
From: Ilias Apalodimas @ 2022-06-07  8:54 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List

On Mon, Feb 28, 2022 at 05:11:24PM -0700, Simon Glass wrote:
> Add a vendor-specific TPM2 command for this and implement it for Cr50.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  drivers/tpm/cr50_i2c.c | 117 +++++++++++++++++++++++++++++++++++++++++
>  include/tpm-v2.h       |  54 +++++++++++++++++++
>  lib/tpm-v2.c           |  24 +++++++++
>  3 files changed, 195 insertions(+)
> 
> diff --git a/drivers/tpm/cr50_i2c.c b/drivers/tpm/cr50_i2c.c
> index f8c3087894..dabf617be0 100644
> --- a/drivers/tpm/cr50_i2c.c
> +++ b/drivers/tpm/cr50_i2c.c
> @@ -13,11 +13,13 @@
>  #include <irq.h>
>  #include <log.h>
>  #include <spl.h>
> +#include <tpm-common.h>
>  #include <tpm-v2.h>
>  #include <acpi/acpigen.h>
>  #include <acpi/acpi_device.h>
>  #include <asm/gpio.h>
>  #include <asm/io.h>
> +#include <asm/unaligned.h>
>  #include <linux/delay.h>
>  #include <dm/acpi.h>
>  
> @@ -54,6 +56,41 @@ struct cr50_priv {
>  	bool use_irq;
>  };
>  
> +/*
> + * The below structure represents the body of the response to the 'report tpm
> + * state' vendor command.
> + *
> + * It is transferred over the wire, so it needs to be serialized/deserialized,
> + * and it is likely to change, so its contents must be versioned.
> + */
> +#define TPM_STATE_VERSION	1
> +struct tpm_vendor_state {
> +	u32 version;
> +	/*
> +	 * The following three fields are set by the TPM in case of an assert.
> +	 * There is no other processing than setting the source code line
> +	 * number, error code and the first 4 characters of the function name.
> +	 *
> +	 * We don't expect this happening, but it is included in the report
> +	 * just in case.
> +	 */
> +	u32 fail_line;	/* s_failLIne */
> +	u32 fail_code;	/* s_failCode */
> +	char func_name[4];	/* s_failFunction, limited to 4 chars */
> +
> +	/*
> +	 * The following two fields are the current time filtered value of the
> +	 * 'failed tries' TPM counter, and the maximum allowed value of the
> +	 * counter.
> +	 *
> +	 * failed_tries == max_tries is the definition of the TPM lockout
> +	 * condition.
> +	 */
> +	u32 failed_tries;	/* gp.failedTries */
> +	u32 max_tries;	/* gp.maxTries */
> +	/* The below fields are present in version 2 and above */
> +};
> +
>  /* Wait for interrupt to indicate TPM is ready */
>  static int cr50_i2c_wait_tpm_ready(struct udevice *dev)
>  {
> @@ -573,6 +610,85 @@ static int cr50_i2c_get_desc(struct udevice *dev, char *buf, int size)
>  	return len;
>  }
>  
> +static int stringify_state(char *buf, int len, char *str, size_t max_size)
> +{
> +	struct tpm_vendor_state state;
> +	size_t text_size = 0;
> +
> +	state.version = get_unaligned_be32(buf +
> +		offsetof(struct tpm_vendor_state, version));
> +	state.fail_line = get_unaligned_be32(buf +
> +		offsetof(struct tpm_vendor_state, fail_line));
> +	state.fail_code = get_unaligned_be32(buf +
> +		offsetof(struct tpm_vendor_state, fail_code));
> +	memcpy(state.func_name,
> +	       buf + offsetof(struct tpm_vendor_state, func_name),
> +	       sizeof(state.func_name));
> +	state.failed_tries = get_unaligned_be32(buf +
> +		offsetof(struct tpm_vendor_state, failed_tries));
> +	state.max_tries = get_unaligned_be32(buf +
> +		offsetof(struct tpm_vendor_state, max_tries));
> +
> +	text_size += snprintf(str + text_size, max_size - text_size,
> +			      "v=%d", state.version);
> +	if (text_size >= max_size)
> +		return -ENOSPC;
> +
> +	if (state.version > TPM_STATE_VERSION)
> +		text_size += snprintf(str + text_size,
> +				      max_size - text_size,
> +				      " not fully supported\n");
> +	if (text_size >= max_size)
> +		return -ENOSPC;
> +
> +	if (state.version == 0)
> +		return -EINVAL;	/* This should never happen */
> +
> +	text_size += snprintf(str + text_size,
> +			      max_size - text_size,
> +			      " failed_tries=%d max_tries=%d\n",
> +			      state.failed_tries, state.max_tries);
> +	if (text_size >= max_size)
> +		return -ENOSPC;
> +
> +	if (state.fail_line) {
> +		/* make sure function name is zero terminated. */
> +		char func_name[sizeof(state.func_name) + 1];
> +
> +		memcpy(func_name, state.func_name, sizeof(state.func_name));
> +		func_name[sizeof(state.func_name)] = '\0';
> +
> +		text_size += snprintf(str + text_size,
> +				      max_size - text_size,
> +				      "tpm failed: f %s line %d code %d",
> +				      func_name,
> +				      state.fail_line,
> +				      state.fail_code);
> +		if (text_size >= max_size)
> +			return -ENOSPC;
> +	}
> +
> +	return 0;
> +}

Is this error state described in the TCG TIS specs ?  If so we should plug
this into the generic TPM API and the driver should only define
cr50_i2c_report_state() etc

> +
> +static int cr50_i2c_report_state(struct udevice *dev, char *str, int str_max)
> +{
> +	char buf[50];
> +	int buf_size = sizeof(buf);
> +	int ret;
> +
> +	ret = tpm2_cr50_report_state(dev, buf, &buf_size);
> +	if (ret)
> +		return ret;
> +
> +	/* TPM responded as expected */
> +	ret = stringify_state(buf, buf_size, str, str_max);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +

[...]

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/8] tpm: Require a digest source when extending the PCR
  2022-06-07  8:42   ` Ilias Apalodimas
@ 2022-08-14 23:29     ` Simon Glass
  0 siblings, 0 replies; 19+ messages in thread
From: Simon Glass @ 2022-08-14 23:29 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: U-Boot Mailing List

Hi Ilias,

On Tue, 7 Jun 2022 at 02:42, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> On Mon, Feb 28, 2022 at 05:11:19PM -0700, Simon Glass wrote:
> > This feature is used for measured boot. It is not currently supported in
> > the TPM drivers, but add it to the API so that code which expects it can
> > signal its request.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> >  cmd/tpm-v1.c      |  3 ++-
> >  cmd/tpm_test.c    |  5 +++--
> >  include/tpm_api.h |  8 +++++---
> >  lib/tpm-v2.c      |  2 ++
> >  lib/tpm_api.c     | 14 ++++++++++----
> >  5 files changed, 22 insertions(+), 10 deletions(-)

(long pause as I forgot about this and only just discovered it was not applied)

> >
> > diff --git a/cmd/tpm-v1.c b/cmd/tpm-v1.c
> > index bf238a9f2e..0869b70775 100644
> > --- a/cmd/tpm-v1.c
> > +++ b/cmd/tpm-v1.c
> > @@ -131,7 +131,8 @@ static int do_tpm_extend(struct cmd_tbl *cmdtp, int flag, int argc,
> >               return CMD_RET_FAILURE;
> >       }
> >
> > -     rc = tpm_pcr_extend(dev, index, in_digest, out_digest);
> > +     rc = tpm_pcr_extend(dev, index, in_digest, sizeof(in_digest),
> > +                         out_digest, "test");
>
> Where is the output value of an extended PCR needed in measured boot?
> IMHO this out_digest seems pointless.  I'd be happier if we just completely
> removed it and make the v2 variant look like v1 more.

It is used by the tpm command to display the digest value.

>
> >       if (!rc) {
> >               puts("PCR value after execution of the command:\n");
> >               print_byte_string(out_digest, sizeof(out_digest));
> > diff --git a/cmd/tpm_test.c b/cmd/tpm_test.c
> > index a3ccb12f53..b35eae81dc 100644
> > --- a/cmd/tpm_test.c
> > +++ b/cmd/tpm_test.c
> > @@ -91,7 +91,8 @@ static int test_early_extend(struct udevice *dev)
> >       tpm_init(dev);
> >       TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
> >       TPM_CHECK(tpm_continue_self_test(dev));
> > -     TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, value_out));
> > +     TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, sizeof(value_in), value_out,
> > +                              "test"));
> >       printf("done\n");
> >       return 0;
> >  }
> > @@ -438,7 +439,7 @@ static int test_timing(struct udevice *dev)
> >                  100);
> >       TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
> >                  100);
> > -     TTPM_CHECK(tpm_pcr_extend(dev, 0, in, out), 200);
> > +     TTPM_CHECK(tpm_pcr_extend(dev, 0, in, sizeof(in), out, "test"), 200);
> >       TTPM_CHECK(tpm_set_global_lock(dev), 50);
> >       TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100);
> >       printf("done\n");
> > diff --git a/include/tpm_api.h b/include/tpm_api.h
> > index 11aa14eb79..3c8e48bc25 100644
> > --- a/include/tpm_api.h
> > +++ b/include/tpm_api.h
> > @@ -81,14 +81,16 @@ u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
> >   *
> >   * @param dev                TPM device
> >   * @param index              index of the PCR
> > - * @param in_digest  160-bit value representing the event to be
> > + * @param in_digest  160/256-bit value representing the event to be
> >   *                   recorded
> > - * @param out_digest 160-bit PCR value after execution of the
> > + * @param size               size of digest in bytes
> > + * @param out_digest 160/256-bit PCR value after execution of the
> >   *                   command
> > + * @param name               additional info about where the digest comes from
> >   * Return: return code of the operation
> >   */
> >  u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
> > -                void *out_digest);
> > +                uint size, void *out_digest, const char *name);
> >
> >  /**
> >   * Issue a TPM_PCRRead command.
> > diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> > index 1bf627853a..6058f2e1e4 100644
> > --- a/lib/tpm-v2.c
> > +++ b/lib/tpm-v2.c
> > @@ -157,6 +157,8 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
> >       };
> >       int ret;
> >
> > +     if (!digest)
> > +             return -EINVAL;
> >       /*
> >        * Fill the command structure starting from the first buffer:
> >        *     - the digest
> > diff --git a/lib/tpm_api.c b/lib/tpm_api.c
> > index 4ac4612c81..a8d3731d3a 100644
> > --- a/lib/tpm_api.c
> > +++ b/lib/tpm_api.c
> > @@ -140,15 +140,21 @@ u32 tpm_write_lock(struct udevice *dev, u32 index)
> >  }
> >
> >  u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
> > -                void *out_digest)
> > +                uint size, void *out_digest, const char *name)
> >  {
> > -     if (tpm_is_v1(dev))
> > +     if (tpm_is_v1(dev)) {
> > +             if (size != PCR_DIGEST_LENGTH || !out_digest)
> > +                     return -EINVAL;
> >               return tpm1_extend(dev, index, in_digest, out_digest);
> > -     else if (tpm_is_v2(dev))
> > +     } else if (tpm_is_v2(dev)) {
> > +             if (size != TPM2_SHA256_DIGEST_SIZE)
> > +                     return -EINVAL;
>
> Why are we limiting this?  This is supposed to be dictated by the PCR bank
> configuration of each hardware

OK I can drop this. Normally we use SHA256 for TPMv2 and I'm not sure
we suppose anything else. But we don't have to....

>
> >               return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest,
> >                                      TPM2_DIGEST_LEN);
> > -     else
> > +             /* @name is ignored as we do not support measured boot */
> > +     } else {
> >               return -ENOSYS;
> > +     }
> >  }
> >
> >  u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
> > --
> > 2.35.1.574.g5d30c73bfb-goog

Regards,
Simon

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/8] tpm: Correct the permissions command in TPMv1
  2022-06-07  8:44   ` Ilias Apalodimas
@ 2022-08-14 23:29     ` Simon Glass
  0 siblings, 0 replies; 19+ messages in thread
From: Simon Glass @ 2022-08-14 23:29 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: U-Boot Mailing List

Hi Ilias,

On Tue, 7 Jun 2022 at 02:44, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Simon,
>
> On Mon, Feb 28, 2022 at 05:11:20PM -0700, Simon Glass wrote:
> > The offset here is incorrect. Fix it.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> >  lib/tpm-v1.c | 5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c
> > index 22a769c587..d0e3ab1b21 100644
> > --- a/lib/tpm-v1.c
> > +++ b/lib/tpm-v1.c
> > @@ -456,12 +456,13 @@ u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm)
> >               0x0, 0x0, 0x0, 0x4,
> >       };
> >       const size_t index_offset = 18;
> > -     const size_t perm_offset = 60;
> > +     const size_t perm_offset = 74;
>
> This is fine, but I hate all these magic values sprinkled around the TPM
> APIs.  Starting with this patch can we do the right thing and at lease have
> those in a #define with a names that makes some sense?

Er, isn't this what I am doing? See the const values which have
sensible names. It really doesn't make sense to put them in a #define
in a distant header file since we don't use these in most commands.
There are just local to the function and determined by the format used
with pack_byte_string(), etc. (see below).

>
> >       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
> >       size_t response_length = sizeof(response);
> >       u32 err;
> >
> > -     if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
> > +     if (pack_byte_string(buf, sizeof(buf), "sd",
> > +                          0, command, sizeof(command),
> >                            index_offset, index))
> >               return TPM_LIB_ERROR;
> >       err = tpm_sendrecv_command(dev, buf, response, &response_length);
> > --
> > 2.35.1.574.g5d30c73bfb-goog
> >
>
> Thanks
> /Ilias

Regards,
SImon

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 4/8] tpm: Correct the define-space command in TPMv2
  2022-06-07  8:46   ` Ilias Apalodimas
@ 2022-08-14 23:29     ` Simon Glass
  0 siblings, 0 replies; 19+ messages in thread
From: Simon Glass @ 2022-08-14 23:29 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: U-Boot Mailing List

Hi Ilias,

On Tue, 7 Jun 2022 at 02:46, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Simon,
>
> Thanks for fixing this.
> On Mon, Feb 28, 2022 at 05:11:21PM -0700, Simon Glass wrote:
> > The message format is incorrect. Fix it.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> >  lib/tpm-v2.c | 18 +++++++++++-------
> >  1 file changed, 11 insertions(+), 7 deletions(-)
> >
> > diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> > index 6058f2e1e4..fe99b9c863 100644
> > --- a/lib/tpm-v2.c
> > +++ b/lib/tpm-v2.c
> > @@ -89,14 +89,14 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
> >        * Calculate the offset of the nv_policy piece by adding each of the
> >        * chunks below.
> >        */
> > -     uint offset = 10 + 8 + 13 + 14;
> > +     uint offset = 10 + 4 + 13 + 14;
> >       u8 command_v2[COMMAND_BUFFER_SIZE] = {
> >               /* header 10 bytes */
> >               tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
> > -             tpm_u32(offset + nv_policy_size),/* Length */
> > +             tpm_u32(offset + nv_policy_size + 2),/* Length */
> >               tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
> >
> > -             /* handles 8 bytes */
> > +             /* handles 4 bytes */
> >               tpm_u32(TPM2_RH_PLATFORM),      /* Primary platform seed */
>
> Similar to my comment on the previous patches,  please send a version with
> defines that gets rid of the magic numbers (offset, +2 on nv_policy_size etc)

OK I have fixed these, with const int.

>
> >
> >               /* session header 13 bytes */
> > @@ -107,12 +107,15 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
> >               tpm_u16(0),                     /* auth_size */
> >
> >               /* message 14 bytes + policy */
> > -             tpm_u16(12 + nv_policy_size),   /* size */
> > +             tpm_u16(12 + nv_policy_size + 2),       /* size */
> >               tpm_u32(space_index),
> >               tpm_u16(TPM2_ALG_SHA256),
> >               tpm_u32(nv_attributes),
> >               tpm_u16(nv_policy_size),
> > -             /* nv_policy */
> > +             /*
> > +              * nv_policy
> > +              * space_size
> > +              */
> >       };
> >       int ret;
> >
> > @@ -120,8 +123,9 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
> >        * Fill the command structure starting from the first buffer:
> >        *     - the password (if any)
> >        */
> > -     ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
> > -                            offset, nv_policy, nv_policy_size);
> > +     ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
> > +                            offset, nv_policy, nv_policy_size,
> > +                            offset + nv_policy_size, space_size);
> >       if (ret)
> >               return TPM_LIB_ERROR;
> >
> > --
> > 2.35.1.574.g5d30c73bfb-goog
> >
>
>
> Cheers
> /Ilias

Regards,
Simon

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 7/8] tpm: Implement state command for Cr50
  2022-06-07  8:54   ` Ilias Apalodimas
@ 2022-08-14 23:29     ` Simon Glass
  0 siblings, 0 replies; 19+ messages in thread
From: Simon Glass @ 2022-08-14 23:29 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: U-Boot Mailing List

Hi Ilias,

On Tue, 7 Jun 2022 at 02:54, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> On Mon, Feb 28, 2022 at 05:11:24PM -0700, Simon Glass wrote:
> > Add a vendor-specific TPM2 command for this and implement it for Cr50.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> >  drivers/tpm/cr50_i2c.c | 117 +++++++++++++++++++++++++++++++++++++++++
> >  include/tpm-v2.h       |  54 +++++++++++++++++++
> >  lib/tpm-v2.c           |  24 +++++++++
> >  3 files changed, 195 insertions(+)
> >
> > diff --git a/drivers/tpm/cr50_i2c.c b/drivers/tpm/cr50_i2c.c
> > index f8c3087894..dabf617be0 100644
> > --- a/drivers/tpm/cr50_i2c.c
> > +++ b/drivers/tpm/cr50_i2c.c
> > @@ -13,11 +13,13 @@
> >  #include <irq.h>
> >  #include <log.h>
> >  #include <spl.h>
> > +#include <tpm-common.h>
> >  #include <tpm-v2.h>
> >  #include <acpi/acpigen.h>
> >  #include <acpi/acpi_device.h>
> >  #include <asm/gpio.h>
> >  #include <asm/io.h>
> > +#include <asm/unaligned.h>
> >  #include <linux/delay.h>
> >  #include <dm/acpi.h>
> >
> > @@ -54,6 +56,41 @@ struct cr50_priv {
> >       bool use_irq;
> >  };
> >
> > +/*
> > + * The below structure represents the body of the response to the 'report tpm
> > + * state' vendor command.
> > + *
> > + * It is transferred over the wire, so it needs to be serialized/deserialized,
> > + * and it is likely to change, so its contents must be versioned.
> > + */
> > +#define TPM_STATE_VERSION    1
> > +struct tpm_vendor_state {
> > +     u32 version;
> > +     /*
> > +      * The following three fields are set by the TPM in case of an assert.
> > +      * There is no other processing than setting the source code line
> > +      * number, error code and the first 4 characters of the function name.
> > +      *
> > +      * We don't expect this happening, but it is included in the report
> > +      * just in case.
> > +      */
> > +     u32 fail_line;  /* s_failLIne */
> > +     u32 fail_code;  /* s_failCode */
> > +     char func_name[4];      /* s_failFunction, limited to 4 chars */
> > +
> > +     /*
> > +      * The following two fields are the current time filtered value of the
> > +      * 'failed tries' TPM counter, and the maximum allowed value of the
> > +      * counter.
> > +      *
> > +      * failed_tries == max_tries is the definition of the TPM lockout
> > +      * condition.
> > +      */
> > +     u32 failed_tries;       /* gp.failedTries */
> > +     u32 max_tries;  /* gp.maxTries */
> > +     /* The below fields are present in version 2 and above */
> > +};
> > +
> >  /* Wait for interrupt to indicate TPM is ready */
> >  static int cr50_i2c_wait_tpm_ready(struct udevice *dev)
> >  {
> > @@ -573,6 +610,85 @@ static int cr50_i2c_get_desc(struct udevice *dev, char *buf, int size)
> >       return len;
> >  }
> >
> > +static int stringify_state(char *buf, int len, char *str, size_t max_size)
> > +{
> > +     struct tpm_vendor_state state;
> > +     size_t text_size = 0;
> > +
> > +     state.version = get_unaligned_be32(buf +
> > +             offsetof(struct tpm_vendor_state, version));
> > +     state.fail_line = get_unaligned_be32(buf +
> > +             offsetof(struct tpm_vendor_state, fail_line));
> > +     state.fail_code = get_unaligned_be32(buf +
> > +             offsetof(struct tpm_vendor_state, fail_code));
> > +     memcpy(state.func_name,
> > +            buf + offsetof(struct tpm_vendor_state, func_name),
> > +            sizeof(state.func_name));
> > +     state.failed_tries = get_unaligned_be32(buf +
> > +             offsetof(struct tpm_vendor_state, failed_tries));
> > +     state.max_tries = get_unaligned_be32(buf +
> > +             offsetof(struct tpm_vendor_state, max_tries));
> > +
> > +     text_size += snprintf(str + text_size, max_size - text_size,
> > +                           "v=%d", state.version);
> > +     if (text_size >= max_size)
> > +             return -ENOSPC;
> > +
> > +     if (state.version > TPM_STATE_VERSION)
> > +             text_size += snprintf(str + text_size,
> > +                                   max_size - text_size,
> > +                                   " not fully supported\n");
> > +     if (text_size >= max_size)
> > +             return -ENOSPC;
> > +
> > +     if (state.version == 0)
> > +             return -EINVAL; /* This should never happen */
> > +
> > +     text_size += snprintf(str + text_size,
> > +                           max_size - text_size,
> > +                           " failed_tries=%d max_tries=%d\n",
> > +                           state.failed_tries, state.max_tries);
> > +     if (text_size >= max_size)
> > +             return -ENOSPC;
> > +
> > +     if (state.fail_line) {
> > +             /* make sure function name is zero terminated. */
> > +             char func_name[sizeof(state.func_name) + 1];
> > +
> > +             memcpy(func_name, state.func_name, sizeof(state.func_name));
> > +             func_name[sizeof(state.func_name)] = '\0';
> > +
> > +             text_size += snprintf(str + text_size,
> > +                                   max_size - text_size,
> > +                                   "tpm failed: f %s line %d code %d",
> > +                                   func_name,
> > +                                   state.fail_line,
> > +                                   state.fail_code);
> > +             if (text_size >= max_size)
> > +                     return -ENOSPC;
> > +     }
> > +
> > +     return 0;
> > +}
>
> Is this error state described in the TCG TIS specs ?  If so we should plug
> this into the generic TPM API and the driver should only define
> cr50_i2c_report_state() etc

No, this is not in the spec. It is one of the many extensions supported by Cr50.

>
> > +
> > +static int cr50_i2c_report_state(struct udevice *dev, char *str, int str_max)
> > +{
> > +     char buf[50];
> > +     int buf_size = sizeof(buf);
> > +     int ret;
> > +
> > +     ret = tpm2_cr50_report_state(dev, buf, &buf_size);
> > +     if (ret)
> > +             return ret;
> > +
> > +     /* TPM responded as expected */
> > +     ret = stringify_state(buf, buf_size, str, str_max);
> > +     if (ret)
> > +             return ret;
> > +
> > +     return 0;
> > +}
> > +
>
> [...]
>
> Thanks
> /Ilias

Regards,
Simon

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2022-08-14 23:30 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-01  0:11 [PATCH 0/8] tpm: Various minor fixes and enhancements Simon Glass
2022-03-01  0:11 ` [PATCH 1/8] tpm: Export the TPM-version functions Simon Glass
2022-06-07  8:28   ` Ilias Apalodimas
2022-03-01  0:11 ` [PATCH 2/8] tpm: Require a digest source when extending the PCR Simon Glass
2022-06-07  8:42   ` Ilias Apalodimas
2022-08-14 23:29     ` Simon Glass
2022-03-01  0:11 ` [PATCH 3/8] tpm: Correct the permissions command in TPMv1 Simon Glass
2022-06-07  8:44   ` Ilias Apalodimas
2022-08-14 23:29     ` Simon Glass
2022-03-01  0:11 ` [PATCH 4/8] tpm: Correct the define-space command in TPMv2 Simon Glass
2022-06-07  8:46   ` Ilias Apalodimas
2022-08-14 23:29     ` Simon Glass
2022-03-01  0:11 ` [PATCH 5/8] tpm: sandbox: Allow init of TPM in a different phase Simon Glass
2022-06-07  8:48   ` Ilias Apalodimas
2022-03-01  0:11 ` [PATCH 6/8] tpm: Allow reporting the internal state Simon Glass
2022-03-01  0:11 ` [PATCH 7/8] tpm: Implement state command for Cr50 Simon Glass
2022-06-07  8:54   ` Ilias Apalodimas
2022-08-14 23:29     ` Simon Glass
2022-03-01  0:11 ` [PATCH 8/8] tpm: Allow commiting non-volatile data Simon Glass

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).