From: Aidan Garske <aidan@wolfssl.com>
To: u-boot@lists.denx.de
Cc: Peter Robinson <pbrobinson@gmail.com>,
Ilias Apalodimas <ilias.apalodimas@linaro.org>,
Tom Rini <trini@konsulko.com>, David Garske <david@wolfssl.com>,
Aidan <aidan@wolfssl.com>,
"Kory Maincent (TI.com)" <kory.maincent@bootlin.com>,
Michael Trimarchi <michael@amarulasolutions.com>,
Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>,
Jerome Forissier <jerome@forissier.org>,
Sean Edmond <seanedmond@microsoft.com>,
Heinrich Schuchardt <xypron.glpk@gmx.de>,
Heiko Schocher <hs@nabladev.com>,
Dinesh Maniyam <dinesh.maniyam@altera.com>,
Mattijs Korpershoek <mkorpershoek@kernel.org>,
Michal Simek <michal.simek@amd.com>,
Brian Sune <briansune@gmail.com>, Simon Glass <sjg@chromium.org>,
Andrew Goodbody <andrew.goodbody@linaro.org>
Subject: [PATCH v4 10/14] cmd: refactor tpm2 command into frontend/backend architecture
Date: Tue, 12 May 2026 17:26:14 -0700 [thread overview]
Message-ID: <20260513002625.76915-10-aidan@wolfssl.com> (raw)
In-Reply-To: <cover.1778619453.git.aidan@wolfssl.com>
From: Aidan <aidan@wolfssl.com>
Split the tpm2 command implementation into a shared frontend and
two selectable backends. This allows wolfTPM to provide its own
TPM2 command implementations while keeping the command table,
dispatcher, and help text shared.
Architecture:
cmd/tpm-v2.c (frontend - always compiled):
Contains the tpm2_commands[] table, get_tpm2_commands(), the
do_tpm2() dispatcher, and the U_BOOT_CMD help text. References
backend functions via cmd/tpm2-backend.h. When CONFIG_TPM_WOLF
is enabled, additional wolfTPM-only commands (caps, pcr_print,
firmware_update, firmware_cancel) are added to the table.
cmd/tpm2-backend.h (new):
Declares all backend function prototypes that both backends must
implement: do_tpm2_device, do_tpm2_info, do_tpm2_init,
do_tpm2_startup, do_tpm2_selftest, do_tpm2_clear,
do_tpm2_pcr_extend, do_tpm2_pcr_read, do_tpm2_get_capability,
do_tpm2_dam_reset, do_tpm2_dam_parameters, do_tpm2_change_auth,
do_tpm2_pcr_setauthpolicy, do_tpm2_pcr_setauthvalue,
do_tpm2_pcr_allocate, plus wolfTPM-only functions.
cmd/native_tpm2.c (new - native backend):
Contains the original tpm2 command implementations that use
U-Boot's TPM driver model (tpm_api.h, tpm-v2.h). Compiled when
CONFIG_TPM_WOLF is not set. Common commands delegate to
tpm-common.c helpers (do_tpm_device, do_tpm_info, etc.).
cmd/wolftpm.c (new - wolfTPM backend):
Implements all tpm2 commands using wolfTPM library APIs directly
(wolfTPM2_Init, wolfTPM2_GetCapabilities, wolfTPM2_ExtendPCR,
etc.). Includes Infineon-specific firmware update and cancel
commands. Each command initializes its own WOLFTPM2_DEV instance
rather than going through U-Boot's driver model.
cmd/Kconfig:
Adds CMD_WOLFTPM option that selects TPM_WOLF and CMD_TPM_V2,
providing a single menuconfig toggle for wolfTPM support.
cmd/Makefile:
Conditionally compiles wolftpm.o (when CONFIG_TPM_WOLF=y) or
native_tpm2.o (otherwise) alongside the shared tpm-v2.o frontend.
Sets wolfTPM include paths and -DWOLFTPM_USER_SETTINGS.
The reason for separate backend files rather than a callback-based
approach is that wolfTPM uses fundamentally different types and
initialization patterns (WOLFTPM2_DEV vs struct udevice, direct
library calls vs driver model ops), making runtime dispatch
impractical without heavy abstraction.
Signed-off-by: Aidan Garske <aidan@wolfssl.com>
---
cmd/Kconfig | 11 +
cmd/Makefile | 10 +-
cmd/native_tpm2.c | 516 +++++++++++++++++++
cmd/tpm-v2.c | 559 +++------------------
cmd/tpm2-backend.h | 66 +++
cmd/wolftpm.c | 1170 ++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 1840 insertions(+), 492 deletions(-)
create mode 100644 cmd/native_tpm2.c
create mode 100644 cmd/tpm2-backend.h
create mode 100644 cmd/wolftpm.c
diff --git a/cmd/Kconfig b/cmd/Kconfig
index b71ac554c0b..fe9b3819eaa 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -3194,4 +3194,15 @@ config CMD_SPAWN_NUM_JOBS
When a jobs exits, its identifier is available to be re-used by the next
spawn command.
+config CMD_WOLFTPM
+ bool "Use wolfTPM as TPM2 backend"
+ depends on TPM_V2
+ select TPM_WOLF
+ select CMD_TPM_V2
+ help
+ Use the wolfTPM library as the backend for TPM2 commands instead
+ of the standard U-Boot TPM2 implementation. wolfTPM offers additional
+ features including firmware update support for Infineon TPMs and
+ enhanced capabilities reporting.
+
endif
diff --git a/cmd/Makefile b/cmd/Makefile
index 4cd13d4fa6e..2b12b26e61f 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -191,9 +191,17 @@ obj-$(CONFIG_CMD_TIMER) += timer.o
obj-$(CONFIG_CMD_TRACE) += trace.o
obj-$(CONFIG_HUSH_PARSER) += test.o
obj-$(CONFIG_CMD_TPM) += tpm-common.o
-obj-$(CONFIG_CMD_TPM_V1) += tpm-v1.o
obj-$(CONFIG_CMD_TPM_TEST) += tpm_test.o
+obj-$(CONFIG_CMD_TPM_V1) += tpm-v1.o
obj-$(CONFIG_CMD_TPM_V2) += tpm-v2.o
+ifeq ($(CONFIG_TPM_WOLF),y)
+ccflags-y += -I$(srctree)/lib/wolftpm \
+ -I$(srctree)/include/configs \
+ -DWOLFTPM_USER_SETTINGS
+obj-$(CONFIG_CMD_TPM_V2) += wolftpm.o
+else
+obj-$(CONFIG_CMD_TPM_V2) += native_tpm2.o
+endif
obj-$(CONFIG_CMD_CROS_EC) += cros_ec.o
obj-$(CONFIG_CMD_UBI) += ubi.o
obj-$(CONFIG_CMD_UBIFS) += ubifs.o
diff --git a/cmd/native_tpm2.c b/cmd/native_tpm2.c
new file mode 100644
index 00000000000..d8dea956156
--- /dev/null
+++ b/cmd/native_tpm2.c
@@ -0,0 +1,516 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Native TPM2 backend implementation
+ *
+ * Copyright (c) 2018 Bootlin
+ * Author: Miquel Raynal <miquel.raynal@bootlin.com>
+ */
+
+#include <command.h>
+#include <dm.h>
+#include <log.h>
+#include <mapmem.h>
+#include <tpm-common.h>
+#include <tpm-v2.h>
+#include "tpm-user-utils.h"
+
+/* Wrappers for common commands - delegate to tpm-common.c */
+int do_tpm2_device(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_tpm_device(cmdtp, flag, argc, argv);
+}
+
+int do_tpm2_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_tpm_info(cmdtp, flag, argc, argv);
+}
+
+int do_tpm2_state(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_tpm_report_state(cmdtp, flag, argc, argv);
+}
+
+int do_tpm2_init(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_tpm_init(cmdtp, flag, argc, argv);
+}
+
+int do_tpm2_autostart(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_tpm_autostart(cmdtp, flag, argc, argv);
+}
+
+int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ enum tpm2_startup_types mode;
+ struct udevice *dev;
+ int ret;
+ bool bon = true;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ /* argv[2] is optional to perform a TPM2_CC_SHUTDOWN */
+ if (argc > 3 || (argc == 3 && strcasecmp("off", argv[2])))
+ return CMD_RET_USAGE;
+
+ if (!strcasecmp("TPM2_SU_CLEAR", argv[1])) {
+ mode = TPM2_SU_CLEAR;
+ } else if (!strcasecmp("TPM2_SU_STATE", argv[1])) {
+ mode = TPM2_SU_STATE;
+ } else {
+ printf("Couldn't recognize mode string: %s\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ if (argv[2])
+ bon = false;
+
+ return report_return_code(tpm2_startup(dev, bon, mode));
+}
+
+int do_tpm2_selftest(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ enum tpm2_yes_no full_test;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ if (!strcasecmp("full", argv[1])) {
+ full_test = TPMI_YES;
+ } else if (!strcasecmp("continue", argv[1])) {
+ full_test = TPMI_NO;
+ } else {
+ printf("Couldn't recognize test mode: %s\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ return report_return_code(tpm2_self_test(dev, full_test));
+}
+
+int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 handle = 0;
+ const char *pw = (argc < 3) ? NULL : argv[2];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (argc < 2 || argc > 3)
+ return CMD_RET_USAGE;
+
+ if (pw_sz > TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
+ handle = TPM2_RH_LOCKOUT;
+ else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
+ handle = TPM2_RH_PLATFORM;
+ else
+ return CMD_RET_USAGE;
+
+ return report_return_code(tpm2_clear(dev, handle, pw, pw_sz));
+}
+
+int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ struct tpm_chip_priv *priv;
+ u32 index = simple_strtoul(argv[1], NULL, 0);
+ void *digest = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
+ int algo = TPM2_ALG_SHA256;
+ int algo_len;
+ int ret;
+ u32 rc;
+
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+ if (argc == 4) {
+ algo = tpm2_name_to_algorithm(argv[3]);
+ if (algo == TPM2_ALG_INVAL)
+ return CMD_RET_FAILURE;
+ }
+ algo_len = tpm2_algorithm_to_len(algo);
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ priv = dev_get_uclass_priv(dev);
+ if (!priv)
+ return -EINVAL;
+
+ if (index >= priv->pcr_count)
+ return -EINVAL;
+
+ rc = tpm2_pcr_extend(dev, index, algo, digest, algo_len);
+ if (!rc) {
+ printf("PCR #%u extended with %d byte %s digest\n", index,
+ algo_len, tpm2_algorithm_name(algo));
+ print_byte_string(digest, algo_len);
+ }
+
+ unmap_sysmem(digest);
+
+ return report_return_code(rc);
+}
+
+int do_tpm2_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ enum tpm2_algorithms algo = TPM2_ALG_SHA256;
+ struct udevice *dev;
+ struct tpm_chip_priv *priv;
+ u32 index, rc;
+ int algo_len;
+ unsigned int updates;
+ void *data;
+ int ret;
+
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+ if (argc == 4) {
+ algo = tpm2_name_to_algorithm(argv[3]);
+ if (algo == TPM2_ALG_INVAL)
+ return CMD_RET_FAILURE;
+ }
+ algo_len = tpm2_algorithm_to_len(algo);
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ priv = dev_get_uclass_priv(dev);
+ if (!priv)
+ return -EINVAL;
+
+ index = simple_strtoul(argv[1], NULL, 0);
+ if (index >= priv->pcr_count)
+ return -EINVAL;
+
+ data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
+
+ rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, algo,
+ data, algo_len, &updates);
+ if (!rc) {
+ printf("PCR #%u %s %d byte content (%u known updates):\n", index,
+ tpm2_algorithm_name(algo), algo_len, updates);
+ print_byte_string(data, algo_len);
+ }
+
+ unmap_sysmem(data);
+
+ return report_return_code(rc);
+}
+
+int do_tpm2_get_capability(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 capability, property, rc;
+ u8 *data;
+ size_t count;
+ int i, j;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (argc != 5)
+ return CMD_RET_USAGE;
+
+ capability = simple_strtoul(argv[1], NULL, 0);
+ property = simple_strtoul(argv[2], NULL, 0);
+ data = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
+ count = simple_strtoul(argv[4], NULL, 0);
+
+ rc = tpm2_get_capability(dev, capability, property, data, count);
+ if (rc)
+ goto unmap_data;
+
+ printf("Capabilities read from TPM:\n");
+ for (i = 0; i < count; i++) {
+ printf("Property 0x");
+ for (j = 0; j < 4; j++)
+ printf("%02x", data[(i * 8) + j + sizeof(u32)]);
+ printf(": 0x");
+ for (j = 4; j < 8; j++)
+ printf("%02x", data[(i * 8) + j + sizeof(u32)]);
+ printf("\n");
+ }
+
+unmap_data:
+ unmap_sysmem(data);
+
+ return report_return_code(rc);
+}
+
+static u32 select_mask(u32 mask, enum tpm2_algorithms algo, bool select)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
+ if (hash_algo_list[i].hash_alg != algo)
+ continue;
+
+ if (select)
+ mask |= hash_algo_list[i].hash_mask;
+ else
+ mask &= ~hash_algo_list[i].hash_mask;
+
+ break;
+ }
+
+ return mask;
+}
+
+static bool
+is_algo_in_pcrs(enum tpm2_algorithms algo, struct tpml_pcr_selection *pcrs)
+{
+ size_t i;
+
+ for (i = 0; i < pcrs->count; i++) {
+ if (algo == pcrs->selection[i].hash)
+ return true;
+ }
+
+ return false;
+}
+
+int do_tpm2_pcr_allocate(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ int ret;
+ enum tpm2_algorithms algo;
+ const char *pw = (argc < 4) ? NULL : argv[3];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ static struct tpml_pcr_selection pcr = { 0 };
+ u32 pcr_len = 0;
+ bool bon = false;
+ static u32 mask;
+ int i;
+
+ /* argv[1]: algorithm (bank), argv[2]: on/off */
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ if (!strcasecmp("on", argv[2]))
+ bon = true;
+ else if (strcasecmp("off", argv[2]))
+ return CMD_RET_USAGE;
+
+ algo = tpm2_name_to_algorithm(argv[1]);
+ if (algo == TPM2_ALG_INVAL)
+ return CMD_RET_USAGE;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (!pcr.count) {
+ /*
+ * Get current active algorithms (banks), PCRs and mask via the
+ * first call
+ */
+ ret = tpm2_get_pcr_info(dev, &pcr);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < pcr.count; i++) {
+ struct tpms_pcr_selection *sel = &pcr.selection[i];
+ const char *name;
+
+ if (!tpm2_is_active_bank(sel))
+ continue;
+
+ mask = select_mask(mask, sel->hash, true);
+ name = tpm2_algorithm_name(sel->hash);
+ if (name)
+ printf("Active bank[%d]: %s\n", i, name);
+ }
+ }
+
+ if (!is_algo_in_pcrs(algo, &pcr)) {
+ printf("%s is not supported by the tpm device\n", argv[1]);
+ return CMD_RET_USAGE;
+ }
+
+ mask = select_mask(mask, algo, bon);
+ ret = tpm2_pcr_config_algo(dev, mask, &pcr, &pcr_len);
+ if (ret)
+ return ret;
+
+ return report_return_code(tpm2_send_pcr_allocate(dev, pw, pw_sz, &pcr,
+ pcr_len));
+}
+
+int do_tpm2_dam_reset(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *pw = (argc < 2) ? NULL : argv[1];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (argc > 2)
+ return CMD_RET_USAGE;
+
+ if (pw_sz > TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ return report_return_code(tpm2_dam_reset(dev, pw, pw_sz));
+}
+
+int do_tpm2_dam_parameters(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *pw = (argc < 5) ? NULL : argv[4];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ /*
+ * No Dictionary Attack Mitigation (DAM) means:
+ * maxtries = 0xFFFFFFFF, recovery_time = 1, lockout_recovery = 0
+ */
+ unsigned long int max_tries;
+ unsigned long int recovery_time;
+ unsigned long int lockout_recovery;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (argc < 4 || argc > 5)
+ return CMD_RET_USAGE;
+
+ if (pw_sz > TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ if (strict_strtoul(argv[1], 0, &max_tries))
+ return CMD_RET_USAGE;
+
+ if (strict_strtoul(argv[2], 0, &recovery_time))
+ return CMD_RET_USAGE;
+
+ if (strict_strtoul(argv[3], 0, &lockout_recovery))
+ return CMD_RET_USAGE;
+
+ log(LOGC_NONE, LOGL_INFO, "Changing dictionary attack parameters:\n");
+ log(LOGC_NONE, LOGL_INFO, "- maxTries: %lu", max_tries);
+ log(LOGC_NONE, LOGL_INFO, "- recoveryTime: %lu\n", recovery_time);
+ log(LOGC_NONE, LOGL_INFO, "- lockoutRecovery: %lu\n", lockout_recovery);
+
+ return report_return_code(tpm2_dam_parameters(dev, pw, pw_sz, max_tries,
+ recovery_time,
+ lockout_recovery));
+}
+
+int do_tpm2_change_auth(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 handle;
+ const char *newpw = argv[2];
+ const char *oldpw = (argc == 3) ? NULL : argv[3];
+ const ssize_t newpw_sz = strlen(newpw);
+ const ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ if (newpw_sz > TPM2_DIGEST_LEN || oldpw_sz > TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
+ handle = TPM2_RH_LOCKOUT;
+ else if (!strcasecmp("TPM2_RH_ENDORSEMENT", argv[1]))
+ handle = TPM2_RH_ENDORSEMENT;
+ else if (!strcasecmp("TPM2_RH_OWNER", argv[1]))
+ handle = TPM2_RH_OWNER;
+ else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
+ handle = TPM2_RH_PLATFORM;
+ else
+ return CMD_RET_USAGE;
+
+ return report_return_code(tpm2_change_auth(dev, handle, newpw, newpw_sz,
+ oldpw, oldpw_sz));
+}
+
+int do_tpm2_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 index = simple_strtoul(argv[1], NULL, 0);
+ char *key = argv[2];
+ const char *pw = (argc < 4) ? NULL : argv[3];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (strlen(key) != TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ return report_return_code(tpm2_pcr_setauthpolicy(dev, pw, pw_sz, index,
+ key));
+}
+
+int do_tpm2_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ u32 index = simple_strtoul(argv[1], NULL, 0);
+ char *key = argv[2];
+ const ssize_t key_sz = strlen(key);
+ const char *pw = (argc < 4) ? NULL : argv[3];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (strlen(key) != TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ return report_return_code(tpm2_pcr_setauthvalue(dev, pw, pw_sz, index,
+ key, key_sz));
+}
diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c
index 847b2691581..a131a81d1a4 100644
--- a/cmd/tpm-v2.c
+++ b/cmd/tpm-v2.c
@@ -1,507 +1,51 @@
// SPDX-License-Identifier: GPL-2.0+
/*
+ * TPM2 command frontend - command table, dispatcher, and help text
+ *
+ * The actual command implementations are provided by the backend:
+ * - native_tpm2.c: U-Boot native TPM2 APIs (driver model)
+ * - wolftpm.c: wolfTPM library APIs
+ *
* Copyright (c) 2018 Bootlin
* Author: Miquel Raynal <miquel.raynal@bootlin.com>
*/
#include <command.h>
-#include <dm.h>
-#include <log.h>
-#include <mapmem.h>
#include <tpm-common.h>
-#include <tpm-v2.h>
-#include "tpm-user-utils.h"
-
-static int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- enum tpm2_startup_types mode;
- struct udevice *dev;
- int ret;
- bool bon = true;
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
-
- /* argv[2] is optional to perform a TPM2_CC_SHUTDOWN */
- if (argc > 3 || (argc == 3 && strcasecmp("off", argv[2])))
- return CMD_RET_USAGE;
-
- if (!strcasecmp("TPM2_SU_CLEAR", argv[1])) {
- mode = TPM2_SU_CLEAR;
- } else if (!strcasecmp("TPM2_SU_STATE", argv[1])) {
- mode = TPM2_SU_STATE;
- } else {
- printf("Couldn't recognize mode string: %s\n", argv[1]);
- return CMD_RET_FAILURE;
- }
-
- if (argv[2])
- bon = false;
-
- return report_return_code(tpm2_startup(dev, bon, mode));
-}
-
-static int do_tpm2_self_test(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- enum tpm2_yes_no full_test;
- struct udevice *dev;
- int ret;
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
- if (argc != 2)
- return CMD_RET_USAGE;
-
- if (!strcasecmp("full", argv[1])) {
- full_test = TPMI_YES;
- } else if (!strcasecmp("continue", argv[1])) {
- full_test = TPMI_NO;
- } else {
- printf("Couldn't recognize test mode: %s\n", argv[1]);
- return CMD_RET_FAILURE;
- }
-
- return report_return_code(tpm2_self_test(dev, full_test));
-}
-
-static int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- u32 handle = 0;
- const char *pw = (argc < 3) ? NULL : argv[2];
- const ssize_t pw_sz = pw ? strlen(pw) : 0;
- struct udevice *dev;
- int ret;
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
-
- if (argc < 2 || argc > 3)
- return CMD_RET_USAGE;
-
- if (pw_sz > TPM2_DIGEST_LEN)
- return -EINVAL;
-
- if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
- handle = TPM2_RH_LOCKOUT;
- else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
- handle = TPM2_RH_PLATFORM;
- else
- return CMD_RET_USAGE;
-
- return report_return_code(tpm2_clear(dev, handle, pw, pw_sz));
-}
-
-static int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- struct udevice *dev;
- struct tpm_chip_priv *priv;
- u32 index = simple_strtoul(argv[1], NULL, 0);
- void *digest = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
- int algo = TPM2_ALG_SHA256;
- int algo_len;
- int ret;
- u32 rc;
-
- if (argc < 3 || argc > 4)
- return CMD_RET_USAGE;
- if (argc == 4) {
- algo = tpm2_name_to_algorithm(argv[3]);
- if (algo == TPM2_ALG_INVAL)
- return CMD_RET_FAILURE;
- }
- algo_len = tpm2_algorithm_to_len(algo);
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
-
- priv = dev_get_uclass_priv(dev);
- if (!priv)
- return -EINVAL;
-
- if (index >= priv->pcr_count)
- return -EINVAL;
-
- rc = tpm2_pcr_extend(dev, index, algo, digest, algo_len);
- if (!rc) {
- printf("PCR #%u extended with %d byte %s digest\n", index,
- algo_len, tpm2_algorithm_name(algo));
- print_byte_string(digest, algo_len);
- }
-
- unmap_sysmem(digest);
-
- return report_return_code(rc);
-}
-
-static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- enum tpm2_algorithms algo = TPM2_ALG_SHA256;
- struct udevice *dev;
- struct tpm_chip_priv *priv;
- u32 index, rc;
- int algo_len;
- unsigned int updates;
- void *data;
- int ret;
-
- if (argc < 3 || argc > 4)
- return CMD_RET_USAGE;
- if (argc == 4) {
- algo = tpm2_name_to_algorithm(argv[3]);
- if (algo == TPM2_ALG_INVAL)
- return CMD_RET_FAILURE;
- }
- algo_len = tpm2_algorithm_to_len(algo);
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
-
- priv = dev_get_uclass_priv(dev);
- if (!priv)
- return -EINVAL;
-
- index = simple_strtoul(argv[1], NULL, 0);
- if (index >= priv->pcr_count)
- return -EINVAL;
-
- data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
-
- rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, algo,
- data, algo_len, &updates);
- if (!rc) {
- printf("PCR #%u %s %d byte content (%u known updates):\n", index,
- tpm2_algorithm_name(algo), algo_len, updates);
- print_byte_string(data, algo_len);
- }
-
- unmap_sysmem(data);
-
- return report_return_code(rc);
-}
-
-static int do_tpm_get_capability(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- u32 capability, property, rc;
- u8 *data;
- size_t count;
- int i, j;
- struct udevice *dev;
- int ret;
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
-
- if (argc != 5)
- return CMD_RET_USAGE;
-
- capability = simple_strtoul(argv[1], NULL, 0);
- property = simple_strtoul(argv[2], NULL, 0);
- data = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
- count = simple_strtoul(argv[4], NULL, 0);
-
- rc = tpm2_get_capability(dev, capability, property, data, count);
- if (rc)
- goto unmap_data;
-
- printf("Capabilities read from TPM:\n");
- for (i = 0; i < count; i++) {
- printf("Property 0x");
- for (j = 0; j < 4; j++)
- printf("%02x", data[(i * 8) + j + sizeof(u32)]);
- printf(": 0x");
- for (j = 4; j < 8; j++)
- printf("%02x", data[(i * 8) + j + sizeof(u32)]);
- printf("\n");
- }
-
-unmap_data:
- unmap_sysmem(data);
-
- return report_return_code(rc);
-}
-
-static u32 select_mask(u32 mask, enum tpm2_algorithms algo, bool select)
-{
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
- if (hash_algo_list[i].hash_alg != algo)
- continue;
-
- if (select)
- mask |= hash_algo_list[i].hash_mask;
- else
- mask &= ~hash_algo_list[i].hash_mask;
-
- break;
- }
-
- return mask;
-}
-
-static bool
-is_algo_in_pcrs(enum tpm2_algorithms algo, struct tpml_pcr_selection *pcrs)
-{
- size_t i;
-
- for (i = 0; i < pcrs->count; i++) {
- if (algo == pcrs->selection[i].hash)
- return true;
- }
-
- return false;
-}
-
-static int do_tpm2_pcrallocate(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- struct udevice *dev;
- int ret;
- enum tpm2_algorithms algo;
- const char *pw = (argc < 4) ? NULL : argv[3];
- const ssize_t pw_sz = pw ? strlen(pw) : 0;
- static struct tpml_pcr_selection pcr = { 0 };
- u32 pcr_len = 0;
- bool bon = false;
- static u32 mask;
- int i;
-
- /* argv[1]: algorithm (bank), argv[2]: on/off */
- if (argc < 3 || argc > 4)
- return CMD_RET_USAGE;
-
- if (!strcasecmp("on", argv[2]))
- bon = true;
- else if (strcasecmp("off", argv[2]))
- return CMD_RET_USAGE;
-
- algo = tpm2_name_to_algorithm(argv[1]);
- if (algo == TPM2_ALG_INVAL)
- return CMD_RET_USAGE;
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
-
- if (!pcr.count) {
- /*
- * Get current active algorithms (banks), PCRs and mask via the
- * first call
- */
- ret = tpm2_get_pcr_info(dev, &pcr);
- if (ret)
- return ret;
-
- for (i = 0; i < pcr.count; i++) {
- struct tpms_pcr_selection *sel = &pcr.selection[i];
- const char *name;
-
- if (!tpm2_is_active_bank(sel))
- continue;
-
- mask = select_mask(mask, sel->hash, true);
- name = tpm2_algorithm_name(sel->hash);
- if (name)
- printf("Active bank[%d]: %s\n", i, name);
- }
- }
-
- if (!is_algo_in_pcrs(algo, &pcr)) {
- printf("%s is not supported by the tpm device\n", argv[1]);
- return CMD_RET_USAGE;
- }
-
- mask = select_mask(mask, algo, bon);
- ret = tpm2_pcr_config_algo(dev, mask, &pcr, &pcr_len);
- if (ret)
- return ret;
-
- return report_return_code(tpm2_send_pcr_allocate(dev, pw, pw_sz, &pcr,
- pcr_len));
-}
-
-static int do_tpm_dam_reset(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- const char *pw = (argc < 2) ? NULL : argv[1];
- const ssize_t pw_sz = pw ? strlen(pw) : 0;
- struct udevice *dev;
- int ret;
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
-
- if (argc > 2)
- return CMD_RET_USAGE;
-
- if (pw_sz > TPM2_DIGEST_LEN)
- return -EINVAL;
-
- return report_return_code(tpm2_dam_reset(dev, pw, pw_sz));
-}
-
-static int do_tpm_dam_parameters(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- const char *pw = (argc < 5) ? NULL : argv[4];
- const ssize_t pw_sz = pw ? strlen(pw) : 0;
- /*
- * No Dictionary Attack Mitigation (DAM) means:
- * maxtries = 0xFFFFFFFF, recovery_time = 1, lockout_recovery = 0
- */
- unsigned long int max_tries;
- unsigned long int recovery_time;
- unsigned long int lockout_recovery;
- struct udevice *dev;
- int ret;
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
-
- if (argc < 4 || argc > 5)
- return CMD_RET_USAGE;
-
- if (pw_sz > TPM2_DIGEST_LEN)
- return -EINVAL;
-
- if (strict_strtoul(argv[1], 0, &max_tries))
- return CMD_RET_USAGE;
-
- if (strict_strtoul(argv[2], 0, &recovery_time))
- return CMD_RET_USAGE;
-
- if (strict_strtoul(argv[3], 0, &lockout_recovery))
- return CMD_RET_USAGE;
-
- log(LOGC_NONE, LOGL_INFO, "Changing dictionary attack parameters:\n");
- log(LOGC_NONE, LOGL_INFO, "- maxTries: %lu", max_tries);
- log(LOGC_NONE, LOGL_INFO, "- recoveryTime: %lu\n", recovery_time);
- log(LOGC_NONE, LOGL_INFO, "- lockoutRecovery: %lu\n", lockout_recovery);
-
- return report_return_code(tpm2_dam_parameters(dev, pw, pw_sz, max_tries,
- recovery_time,
- lockout_recovery));
-}
-
-static int do_tpm_change_auth(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- u32 handle;
- const char *newpw = argv[2];
- const char *oldpw = (argc == 3) ? NULL : argv[3];
- const ssize_t newpw_sz = strlen(newpw);
- const ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;
- struct udevice *dev;
- int ret;
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
-
- if (argc < 3 || argc > 4)
- return CMD_RET_USAGE;
-
- if (newpw_sz > TPM2_DIGEST_LEN || oldpw_sz > TPM2_DIGEST_LEN)
- return -EINVAL;
-
- if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
- handle = TPM2_RH_LOCKOUT;
- else if (!strcasecmp("TPM2_RH_ENDORSEMENT", argv[1]))
- handle = TPM2_RH_ENDORSEMENT;
- else if (!strcasecmp("TPM2_RH_OWNER", argv[1]))
- handle = TPM2_RH_OWNER;
- else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
- handle = TPM2_RH_PLATFORM;
- else
- return CMD_RET_USAGE;
-
- return report_return_code(tpm2_change_auth(dev, handle, newpw, newpw_sz,
- oldpw, oldpw_sz));
-}
-
-static int do_tpm_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- u32 index = simple_strtoul(argv[1], NULL, 0);
- char *key = argv[2];
- const char *pw = (argc < 4) ? NULL : argv[3];
- const ssize_t pw_sz = pw ? strlen(pw) : 0;
- struct udevice *dev;
- int ret;
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
-
- if (strlen(key) != TPM2_DIGEST_LEN)
- return -EINVAL;
-
- if (argc < 3 || argc > 4)
- return CMD_RET_USAGE;
-
- return report_return_code(tpm2_pcr_setauthpolicy(dev, pw, pw_sz, index,
- key));
-}
-
-static int do_tpm_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
- int argc, char *const argv[])
-{
- u32 index = simple_strtoul(argv[1], NULL, 0);
- char *key = argv[2];
- const ssize_t key_sz = strlen(key);
- const char *pw = (argc < 4) ? NULL : argv[3];
- const ssize_t pw_sz = pw ? strlen(pw) : 0;
- struct udevice *dev;
- int ret;
-
- ret = get_tpm(&dev);
- if (ret)
- return ret;
-
- if (strlen(key) != TPM2_DIGEST_LEN)
- return -EINVAL;
-
- if (argc < 3 || argc > 4)
- return CMD_RET_USAGE;
-
- return report_return_code(tpm2_pcr_setauthvalue(dev, pw, pw_sz, index,
- key, key_sz));
-}
+#include "tpm2-backend.h"
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(device, 0, 1, do_tpm2_device, "", ""),
+ U_BOOT_CMD_MKENT(info, 0, 1, do_tpm2_info, "", ""),
+ U_BOOT_CMD_MKENT(state, 0, 1, do_tpm2_state, "", ""),
+ U_BOOT_CMD_MKENT(init, 0, 1, do_tpm2_init, "", ""),
+ U_BOOT_CMD_MKENT(autostart, 0, 1, do_tpm2_autostart, "", ""),
U_BOOT_CMD_MKENT(startup, 0, 1, do_tpm2_startup, "", ""),
- U_BOOT_CMD_MKENT(self_test, 0, 1, do_tpm2_self_test, "", ""),
+ U_BOOT_CMD_MKENT(self_test, 0, 1, do_tpm2_selftest, "", ""),
U_BOOT_CMD_MKENT(clear, 0, 1, do_tpm2_clear, "", ""),
U_BOOT_CMD_MKENT(pcr_extend, 0, 1, do_tpm2_pcr_extend, "", ""),
- U_BOOT_CMD_MKENT(pcr_read, 0, 1, do_tpm_pcr_read, "", ""),
- U_BOOT_CMD_MKENT(get_capability, 0, 1, do_tpm_get_capability, "", ""),
- U_BOOT_CMD_MKENT(dam_reset, 0, 1, do_tpm_dam_reset, "", ""),
- U_BOOT_CMD_MKENT(dam_parameters, 0, 1, do_tpm_dam_parameters, "", ""),
- U_BOOT_CMD_MKENT(change_auth, 0, 1, do_tpm_change_auth, "", ""),
- U_BOOT_CMD_MKENT(autostart, 0, 1, do_tpm_autostart, "", ""),
+ U_BOOT_CMD_MKENT(pcr_read, 0, 1, do_tpm2_pcr_read, "", ""),
+ U_BOOT_CMD_MKENT(get_capability, 0, 1, do_tpm2_get_capability, "", ""),
+ U_BOOT_CMD_MKENT(dam_reset, 0, 1, do_tpm2_dam_reset, "", ""),
+ U_BOOT_CMD_MKENT(dam_parameters, 0, 1, do_tpm2_dam_parameters, "", ""),
+ U_BOOT_CMD_MKENT(change_auth, 0, 1, do_tpm2_change_auth, "", ""),
U_BOOT_CMD_MKENT(pcr_setauthpolicy, 0, 1,
- do_tpm_pcr_setauthpolicy, "", ""),
+ do_tpm2_pcr_setauthpolicy, "", ""),
U_BOOT_CMD_MKENT(pcr_setauthvalue, 0, 1,
- do_tpm_pcr_setauthvalue, "", ""),
- U_BOOT_CMD_MKENT(pcr_allocate, 0, 1, do_tpm2_pcrallocate, "", ""),
+ do_tpm2_pcr_setauthvalue, "", ""),
+ U_BOOT_CMD_MKENT(pcr_allocate, 0, 1, do_tpm2_pcr_allocate, "", ""),
+#ifdef CONFIG_TPM_WOLF
+ U_BOOT_CMD_MKENT(caps, 0, 1, do_tpm2_caps, "", ""),
+ U_BOOT_CMD_MKENT(pcr_print, 0, 1, do_tpm2_pcr_print, "", ""),
+#ifdef WOLFTPM_FIRMWARE_UPGRADE
+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)
+ U_BOOT_CMD_MKENT(firmware_update, 0, 1,
+ do_tpm2_firmware_update, "", ""),
+ U_BOOT_CMD_MKENT(firmware_cancel, 0, 1,
+ do_tpm2_firmware_cancel, "", ""),
+#endif /* WOLFTPM_SLB9672 || WOLFTPM_SLB9673 */
+#endif /* WOLFTPM_FIRMWARE_UPGRADE */
+#endif /* CONFIG_TPM_WOLF */
};
struct cmd_tbl *get_tpm2_commands(unsigned int *size)
@@ -511,7 +55,22 @@ struct cmd_tbl *get_tpm2_commands(unsigned int *size)
return tpm2_commands;
}
-U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
+static int do_tpm2(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *cmd;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ cmd = find_cmd_tbl(argv[1], tpm2_commands, ARRAY_SIZE(tpm2_commands));
+ if (!cmd)
+ return CMD_RET_USAGE;
+
+ return cmd->cmd(cmdtp, flag, argc - 1, argv + 1);
+}
+
+U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm2, "Issue a TPMv2.x command",
"<command> [<arguments>]\n"
"\n"
"device [num device]\n"
@@ -521,7 +80,7 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
"state\n"
" Show internal state from the TPM (if available)\n"
"autostart\n"
-" Initalize the tpm, perform a Startup(clear) and run a full selftest\n"
+" Initialize the tpm, perform a Startup(clear) and run a full selftest\n"
" sequence\n"
"init\n"
" Initialize the software stack. Always the first command to issue.\n"
@@ -573,6 +132,10 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
" <password>: optional password of the LOCKOUT hierarchy\n"
"change_auth <hierarchy> <new_pw> [<old_pw>]\n"
" <hierarchy>: the hierarchy\n"
+" * TPM2_RH_LOCKOUT\n"
+" * TPM2_RH_ENDORSEMENT\n"
+" * TPM2_RH_OWNER\n"
+" * TPM2_RH_PLATFORM\n"
" <new_pw>: new password for <hierarchy>\n"
" <old_pw>: optional previous password of <hierarchy>\n"
"pcr_setauthpolicy|pcr_setauthvalue <pcr> <key> [<password>]\n"
@@ -596,4 +159,18 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
" * off - Clear all available PCRs associated with the specified\n"
" algorithm (bank)\n"
" <password>: optional password\n"
+#ifdef CONFIG_TPM_WOLF
+"caps\n"
+" Show TPM capabilities and info\n"
+"pcr_print\n"
+" Prints the current PCR state\n"
+#ifdef WOLFTPM_FIRMWARE_UPGRADE
+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)
+"firmware_update <manifest_addr> <manifest_sz> <firmware_addr> <firmware_sz>\n"
+" Update TPM firmware\n"
+"firmware_cancel\n"
+" Cancel TPM firmware update\n"
+#endif /* WOLFTPM_SLB9672 || WOLFTPM_SLB9673 */
+#endif /* WOLFTPM_FIRMWARE_UPGRADE */
+#endif /* CONFIG_TPM_WOLF */
);
diff --git a/cmd/tpm2-backend.h b/cmd/tpm2-backend.h
new file mode 100644
index 00000000000..39e9a3a6b7b
--- /dev/null
+++ b/cmd/tpm2-backend.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * TPM2 backend function declarations
+ *
+ * Each backend (native_tpm2.c or wolftpm.c) implements these functions.
+ * The frontend (tpm-v2.c) references them in the command table.
+ */
+
+#ifndef __TPM2_BACKEND_H
+#define __TPM2_BACKEND_H
+
+#include <command.h>
+
+/* Common TPM2 command handlers - both backends must implement these */
+int do_tpm2_device(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_state(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_init(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_autostart(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_selftest(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_get_capability(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_dam_reset(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_dam_parameters(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_change_auth(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_pcr_allocate(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+
+/* wolfTPM-only command handlers */
+#ifdef CONFIG_TPM_WOLF
+int do_tpm2_caps(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_pcr_print(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+#ifdef WOLFTPM_FIRMWARE_UPGRADE
+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)
+int do_tpm2_firmware_update(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm2_firmware_cancel(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+#endif /* WOLFTPM_SLB9672 || WOLFTPM_SLB9673 */
+#endif /* WOLFTPM_FIRMWARE_UPGRADE */
+#endif /* CONFIG_TPM_WOLF */
+
+#endif /* __TPM2_BACKEND_H */
diff --git a/cmd/wolftpm.c b/cmd/wolftpm.c
new file mode 100644
index 00000000000..06ea8d47c8a
--- /dev/null
+++ b/cmd/wolftpm.c
@@ -0,0 +1,1170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * TPM2 command implementation using wolfTPM library
+ *
+ * Copyright (C) 2025 wolfSSL Inc.
+ * Author: Aidan Garske <aidan@wolfssl.com>
+ */
+
+#define LOG_CATEGORY UCLASS_BOOTSTD
+
+#include <wolftpm/tpm2.h>
+#include <wolftpm/tpm2_wrap.h>
+#include <wolftpm/tpm2_packet.h>
+#include <wolftpm.h>
+
+#include <stdio.h>
+#include <hash.h>
+#ifndef WOLFTPM2_NO_WRAPPER
+
+#include <hal/tpm_io.h>
+#include <examples/wrap/wrap_test.h>
+
+/* U-boot specific includes */
+#include <command.h>
+#include <tpm-common.h>
+#include <vsprintf.h>
+#include <mapmem.h>
+#include <errno.h>
+#include <log.h>
+#include <string.h>
+
+/* Firmware update info structure for Infineon TPM */
+#ifdef WOLFTPM_FIRMWARE_UPGRADE
+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)
+struct fw_info {
+ byte *manifest_buf;
+ byte *firmware_buf;
+ size_t manifest_bufSz;
+ size_t firmware_bufSz;
+};
+#endif
+#endif
+
+/******************************************************************************/
+/* --- BEGIN Common Commands -- */
+/******************************************************************************/
+
+int do_tpm2_device(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ WOLFTPM2_DEV dev;
+ WOLFTPM2_CAPS caps;
+ int rc;
+
+ /* Expected 1 arg only in native SPI mode (no device switching) */
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ /* Try to initialize and get device info */
+ rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
+ if (!rc) {
+ rc = wolfTPM2_GetCapabilities(&dev, &caps);
+ if (!rc) {
+ printf("TPM Device 0: %s (%s) FW=%d.%d\n",
+ caps.mfgStr, caps.vendorStr,
+ caps.fwVerMajor, caps.fwVerMinor);
+ }
+ wolfTPM2_Cleanup(&dev);
+ }
+
+ if (rc != 0) {
+ printf("No TPM device found (rc=%d: %s)\n", rc, TPM2_GetRCString(rc));
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+}
+
+int do_tpm2_info(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ WOLFTPM2_DEV dev;
+ WOLFTPM2_CAPS caps;
+ int rc;
+
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device */
+ rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
+ if (!rc) {
+ rc = wolfTPM2_GetCapabilities(&dev, &caps);
+ if (!rc) {
+ printf("TPM 2.0: %s (%s)\n", caps.mfgStr, caps.vendorStr);
+ printf(" Firmware: %d.%d (0x%08X)\n",
+ caps.fwVerMajor, caps.fwVerMinor, caps.fwVerVendor);
+ printf(" Type: 0x%08X\n", caps.tpmType);
+ }
+ wolfTPM2_Cleanup(&dev);
+ }
+
+ if (rc != 0) {
+ printf("Couldn't get TPM info (rc=%d: %s)\n", rc, TPM2_GetRCString(rc));
+ return CMD_RET_FAILURE;
+ }
+
+ log_debug("tpm2 info: rc = %d (%s)\n", rc, TPM2_GetRCString(rc));
+ return 0;
+}
+
+int do_tpm2_state(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ WOLFTPM2_DEV dev;
+ WOLFTPM2_CAPS caps;
+ int rc;
+
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device */
+ rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
+ if (!rc) {
+ rc = wolfTPM2_GetCapabilities(&dev, &caps);
+ if (!rc) {
+ printf("TPM State:\n");
+ printf(" Manufacturer: %s\n", caps.mfgStr);
+ printf(" Vendor: %s\n", caps.vendorStr);
+ printf(" Firmware: %d.%d\n", caps.fwVerMajor, caps.fwVerMinor);
+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)
+ printf(" Mode: Infineon SLB967x (Native SPI)\n");
+ printf(" OpMode: %d\n", caps.opMode);
+#else
+ printf(" Mode: Native wolfTPM SPI\n");
+#endif
+ }
+ wolfTPM2_Cleanup(&dev);
+ }
+
+ if (rc != 0) {
+ printf("Couldn't get TPM state (rc=%d: %s)\n", rc, TPM2_GetRCString(rc));
+ return CMD_RET_FAILURE;
+ }
+
+ log_debug("tpm2 state: rc = %d (%s)\n", rc, TPM2_GetRCString(rc));
+ return 0;
+}
+
+int do_tpm2_init(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ WOLFTPM2_DEV dev;
+
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device */
+ return TPM2_Init_Device(&dev, NULL);
+}
+
+int do_tpm2_autostart(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+
+ /* Perform a startup clear - doStartup=1: Just starts up the TPM */
+ rc = wolfTPM2_Reset(&dev, 0, 1);
+ /* TPM_RC_INITIALIZE means already started - treat as success */
+ if (rc == TPM_RC_INITIALIZE)
+ rc = TPM_RC_SUCCESS;
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("wolfTPM2_Reset failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+ return rc;
+ }
+
+ /* Perform a full self test */
+ rc = wolfTPM2_SelfTest(&dev);
+ if (rc != TPM_RC_SUCCESS)
+ log_debug("wolfTPM2_SelfTest failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+
+ log_debug("tpm2 autostart: rc = %d (%s)\n", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+/******************************************************************************/
+/* --- END Common Commands -- */
+/******************************************************************************/
+
+/******************************************************************************/
+/* --- START TPM 2.0 Commands -- */
+/******************************************************************************/
+
+int do_tpm2_get_capability(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ GetCapability_In in;
+ GetCapability_Out out;
+ u32 capability, property, rc;
+ u8 *data;
+ size_t count;
+ int i, j;
+
+ if (argc != 5)
+ return CMD_RET_USAGE;
+
+ capability = simple_strtoul(argv[1], NULL, 0);
+ property = simple_strtoul(argv[2], NULL, 0);
+ data = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
+ count = simple_strtoul(argv[4], NULL, 0);
+
+ memset(&in, 0, sizeof(in));
+ memset(&out, 0, sizeof(out));
+ in.capability = capability;
+ in.property = property;
+ in.propertyCount = count;
+ rc = TPM2_GetCapability(&in, &out);
+ if (!rc) {
+ memcpy(data, &out.capabilityData.data, sizeof(out.capabilityData.data));
+
+ printf("Capabilities read from TPM:\n");
+ for (i = 0; i < count; i++) {
+ printf("Property 0x");
+ for (j = 0; j < 4; j++)
+ printf("%02x", data[(i * 8) + j + sizeof(u32)]);
+ printf(": 0x");
+ for (j = 4; j < 8; j++)
+ printf("%02x", data[(i * 8) + j + sizeof(u32)]);
+ printf("\n");
+ }
+ }
+
+ unmap_sysmem(data);
+
+ log_debug("tpm2 get_capability: rc = %d (%s)\n", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+int do_tpm2_caps(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ WOLFTPM2_CAPS caps;
+
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+
+ rc = wolfTPM2_GetCapabilities(&dev, &caps);
+ if (rc != TPM_RC_SUCCESS)
+ goto cleanup;
+
+ log_debug("Mfg %s (%d), Vendor %s, Fw %u.%u (0x%x), "
+ "FIPS 140-2 %d, CC-EAL4 %d\n",
+ caps.mfgStr, caps.mfg, caps.vendorStr, caps.fwVerMajor,
+ caps.fwVerMinor, caps.fwVerVendor, caps.fips140_2, caps.cc_eal4);
+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)
+ log_debug("Operational mode: %s (0x%x)\n",
+ TPM2_IFX_GetOpModeStr(caps.opMode), caps.opMode);
+ log_debug("KeyGroupId 0x%x, FwCounter %d (%d same)\n",
+ caps.keyGroupId, caps.fwCounter, caps.fwCounterSame);
+#endif
+
+ /* List the active persistent handles */
+ rc = wolfTPM2_GetHandles(PERSISTENT_FIRST, NULL);
+ if (rc >= TPM_RC_SUCCESS)
+ log_debug("Found %d persistent handles\n", rc);
+
+ /* Print the available PCR's */
+ rc = TPM2_PCRs_Print();
+
+cleanup:
+ /* Only doShutdown=1: Just shut down the TPM */
+ wolfTPM2_Reset(&dev, 1, 0);
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 caps: rc = %d (%s)\n", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+#ifdef WOLFTPM_FIRMWARE_UPGRADE
+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)
+int do_tpm2_firmware_update(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ WOLFTPM2_CAPS caps;
+ struct fw_info fwinfo;
+ ulong manifest_addr, firmware_addr;
+ size_t manifest_sz, firmware_sz;
+ uint8_t manifest_hash[TPM_SHA384_DIGEST_SIZE];
+ int recovery = 0;
+
+ memset(&fwinfo, 0, sizeof(fwinfo));
+
+ /* Need 5 args: command + 4 arguments */
+ if (argc != 5) {
+ log_debug("Error: Expected 5 arguments but got %d\n", argc);
+ return CMD_RET_USAGE;
+ }
+ printf("TPM2 Firmware Update\n");
+
+ /* Convert all arguments from strings to numbers */
+ manifest_addr = simple_strtoul(argv[1], NULL, 0);
+ manifest_sz = simple_strtoul(argv[2], NULL, 0);
+ firmware_addr = simple_strtoul(argv[3], NULL, 0);
+ firmware_sz = simple_strtoul(argv[4], NULL, 0);
+
+ /* Map the memory addresses */
+ fwinfo.manifest_buf = map_sysmem(manifest_addr, manifest_sz);
+ fwinfo.firmware_buf = map_sysmem(firmware_addr, firmware_sz);
+ fwinfo.manifest_bufSz = manifest_sz;
+ fwinfo.firmware_bufSz = firmware_sz;
+
+ if (fwinfo.manifest_buf == NULL || fwinfo.firmware_buf == NULL) {
+ log_debug("Error: Invalid memory addresses\n");
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Infineon Firmware Update Tool\n");
+ printf("\tManifest Address: 0x%lx (size: %zu)\n",
+ manifest_addr, manifest_sz);
+ printf("\tFirmware Address: 0x%lx (size: %zu)\n",
+ firmware_addr, firmware_sz);
+
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ goto fw_cleanup;
+
+ rc = wolfTPM2_GetCapabilities(&dev, &caps);
+ if (rc != TPM_RC_SUCCESS)
+ goto fw_cleanup;
+
+ TPM2_IFX_PrintInfo(&caps);
+ if (caps.keyGroupId == 0)
+ log_debug("Error getting key group id from TPM!\n");
+ if (caps.opMode == 0x02 || (caps.opMode & 0x80))
+ recovery = 1;
+
+ if (recovery) {
+ printf("Firmware Update (recovery mode):\n");
+ rc = wolfTPM2_FirmwareUpgradeRecover(&dev,
+ fwinfo.manifest_buf, (uint32_t)fwinfo.manifest_bufSz,
+ TPM2_IFX_FwData_Cb, &fwinfo);
+ } else {
+ /* Normal mode - hash with wc_Sha384Hash */
+ printf("Firmware Update (normal mode):\n");
+ rc = wc_Sha384Hash(fwinfo.manifest_buf,
+ (uint32_t)fwinfo.manifest_bufSz, manifest_hash);
+ if (rc != TPM_RC_SUCCESS)
+ goto fw_cleanup;
+ rc = wolfTPM2_FirmwareUpgradeHash(&dev, TPM_ALG_SHA384,
+ manifest_hash, (uint32_t)sizeof(manifest_hash),
+ fwinfo.manifest_buf, (uint32_t)fwinfo.manifest_bufSz,
+ TPM2_IFX_FwData_Cb, &fwinfo);
+ }
+
+ if (!rc)
+ TPM2_IFX_PrintInfo(&caps);
+
+fw_cleanup:
+ if (fwinfo.manifest_buf)
+ unmap_sysmem(fwinfo.manifest_buf);
+ if (fwinfo.firmware_buf)
+ unmap_sysmem(fwinfo.firmware_buf);
+
+ if (rc != TPM_RC_SUCCESS)
+ log_debug("Infineon firmware update failed 0x%x: %s\n",
+ rc, TPM2_GetRCString(rc));
+
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 firmware_update: rc=%d (%s)\n", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+int do_tpm2_firmware_cancel(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ uint8_t cmd[TPM2_HEADER_SIZE + 2];
+ uint16_t val16;
+
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc == TPM_RC_SUCCESS) {
+ /* Setup command size in header */
+ val16 = TPM2_HEADER_SIZE + 2;
+ memcpy(cmd, &val16, sizeof(val16));
+ val16 = 0;
+ memcpy(&cmd[TPM2_HEADER_SIZE], &val16, sizeof(val16));
+
+ rc = TPM2_IFX_FieldUpgradeCommand(TPM_CC_FieldUpgradeAbandonVendor,
+ cmd, sizeof(cmd));
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("Firmware abandon failed 0x%x: %s\n",
+ rc, TPM2_GetRCString(rc));
+ }
+ }
+
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 firmware_cancel: rc=%d (%s)\n", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+#endif /* WOLFTPM_SLB9672 || WOLFTPM_SLB9673 */
+#endif /* WOLFTPM_FIRMWARE_UPGRADE */
+
+int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ Startup_In startupIn;
+ Shutdown_In shutdownIn;
+ int doStartup = YES;
+
+ /* startup TPM2_SU_CLEAR|TPM2_SU_STATE [off] */
+ if (argc < 2 || argc > 3)
+ return CMD_RET_USAGE;
+ /* Check if shutdown requested */
+ if (argc == 3) {
+ if (strcmp(argv[2], "off") != 0)
+ return CMD_RET_USAGE;
+ doStartup = NO; /* shutdown */
+ }
+ printf("TPM2 Startup\n");
+
+ memset(&startupIn, 0, sizeof(startupIn));
+ memset(&shutdownIn, 0, sizeof(shutdownIn));
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+
+ if (!strcmp(argv[1], "TPM2_SU_CLEAR")) {
+ if (doStartup == YES)
+ startupIn.startupType = TPM_SU_CLEAR;
+ else
+ shutdownIn.shutdownType = TPM_SU_CLEAR;
+ } else if (!strcmp(argv[1], "TPM2_SU_STATE")) {
+ if (doStartup == YES)
+ startupIn.startupType = TPM_SU_STATE;
+ else
+ shutdownIn.shutdownType = TPM_SU_STATE;
+ } else {
+ log_debug("Couldn't recognize mode string: %s\n", argv[1]);
+ wolfTPM2_Cleanup(&dev);
+ return CMD_RET_FAILURE;
+ }
+
+ /* startup */
+ if (doStartup == YES) {
+ rc = TPM2_Startup(&startupIn);
+ /* TPM_RC_INITIALIZE = Already started */
+ if (rc != TPM_RC_SUCCESS && rc != TPM_RC_INITIALIZE) {
+ log_debug("TPM2 Startup: Result = 0x%x (%s)\n", rc,
+ TPM2_GetRCString(rc));
+ }
+ /* shutdown */
+ } else {
+ rc = TPM2_Shutdown(&shutdownIn);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("TPM2 Shutdown: Result = 0x%x (%s)\n", rc,
+ TPM2_GetRCString(rc));
+ }
+ }
+
+ wolfTPM2_Cleanup(&dev);
+
+ if (rc >= 0)
+ rc = 0;
+
+ log_debug("tpm2 startup (%s): rc = %d (%s)\n",
+ doStartup ? "startup" : "shutdown", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+int do_tpm2_selftest(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ TPMI_YES_NO fullTest = YES;
+
+ /* Need 2 arg: command + type */
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc == TPM_RC_SUCCESS) {
+ if (!strcmp(argv[1], "full")) {
+ fullTest = YES;
+ } else if (!strcmp(argv[1], "continue")) {
+ fullTest = NO;
+ } else {
+ log_debug("Couldn't recognize test mode: %s\n", argv[1]);
+ wolfTPM2_Cleanup(&dev);
+ return CMD_RET_FAILURE;
+ }
+
+ /* full test */
+ if (fullTest == YES) {
+ rc = wolfTPM2_SelfTest(&dev);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("TPM2 Self Test: Result = 0x%x (%s)\n", rc,
+ TPM2_GetRCString(rc));
+ }
+ /* continue test */
+ } else {
+ rc = wolfTPM2_SelfTest(&dev);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("TPM2 Self Test: Result = 0x%x (%s)\n", rc,
+ TPM2_GetRCString(rc));
+ }
+ }
+ }
+
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 selftest (%s): rc = %d (%s)\n",
+ fullTest ? "full" : "continue", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ Clear_In clearIn;
+ TPMI_RH_CLEAR handle;
+
+ /* Need 2 arg: command + type */
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
+ handle = TPM_RH_LOCKOUT;
+ else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
+ handle = TPM_RH_PLATFORM;
+ else
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc == TPM_RC_SUCCESS) {
+ /* Set up clear */
+ memset(&clearIn, 0, sizeof(clearIn));
+ clearIn.authHandle = handle;
+
+ rc = TPM2_Clear(&clearIn);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("TPM2 Clear: Result = 0x%x (%s)\n", rc,
+ TPM2_GetRCString(rc));
+ }
+ }
+
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 clear (%s): rc = %d (%s)\n",
+ handle == TPM_RH_LOCKOUT ? "TPM2_RH_LOCKOUT" : "TPM2_RH_PLATFORM",
+ rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ uint32_t pcrIndex;
+ int algo = TPM_ALG_SHA256;
+ int digestLen;
+ void *digest;
+ ulong digest_addr;
+
+ /* Need 3-4 args: command + pcr + digest_addr + [algo] */
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+ printf("TPM2 PCR Extend\n");
+
+ pcrIndex = simple_strtoul(argv[1], NULL, 0);
+ digest_addr = simple_strtoul(argv[2], NULL, 0);
+
+ /* Optional algorithm */
+ if (argc == 4) {
+ algo = TPM2_GetAlgId(argv[3]);
+ if (algo < 0) {
+ log_debug("Couldn't recognize algorithm: %s\n", argv[3]);
+ return CMD_RET_FAILURE;
+ }
+ log_debug("Using algorithm: %s\n", TPM2_GetAlgName(algo));
+ }
+
+ /* Get digest length based on algorithm */
+ digestLen = TPM2_GetHashDigestSize(algo);
+ if (digestLen <= 0) {
+ log_debug("Invalid algorithm digest length\n");
+ return CMD_RET_FAILURE;
+ }
+
+ /* Map digest from memory address */
+ digest = map_sysmem(digest_addr, digestLen);
+ if (digest == NULL) {
+ log_debug("Error: Invalid digest memory address\n");
+ return CMD_RET_FAILURE;
+ }
+
+ log_debug("TPM2 PCR Extend: PCR %u with %s digest\n",
+ (unsigned int)pcrIndex, TPM2_GetAlgName(algo));
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc != TPM_RC_SUCCESS) {
+ unmap_sysmem(digest);
+ return rc;
+ }
+
+ /* Extend the PCR */
+ rc = wolfTPM2_ExtendPCR(&dev, pcrIndex, algo, digest, digestLen);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("TPM2_PCR_Extend failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+ }
+
+ unmap_sysmem(digest);
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 pcr_extend: rc = %d (%s)\n", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+int do_tpm2_pcr_read(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ uint32_t pcrIndex;
+ int algo = TPM_ALG_SHA256;
+ void *digest;
+ ulong digest_addr;
+ int digestLen;
+
+ /* Need 3-4 args: command + pcr + digest_addr + [algo] */
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ pcrIndex = simple_strtoul(argv[1], NULL, 0);
+ digest_addr = simple_strtoul(argv[2], NULL, 0);
+
+ /* Optional algorithm */
+ if (argc == 4) {
+ algo = TPM2_GetAlgId(argv[3]);
+ if (algo < 0) {
+ log_debug("Couldn't recognize algorithm: %s\n", argv[3]);
+ return CMD_RET_FAILURE;
+ }
+ log_debug("Using algorithm: %s\n", TPM2_GetAlgName(algo));
+ }
+
+ /* Get digest length based on algorithm */
+ digestLen = TPM2_GetHashDigestSize(algo);
+ if (digestLen <= 0) {
+ log_debug("Invalid algorithm digest length\n");
+ return CMD_RET_FAILURE;
+ }
+
+ /* Map digest from memory address */
+ digest = map_sysmem(digest_addr, digestLen);
+ if (digest == NULL) {
+ log_debug("Error: Invalid digest memory address\n");
+ return CMD_RET_FAILURE;
+ }
+
+ log_debug("TPM2 PCR Read: PCR %u to %s digest\n",
+ (unsigned int)pcrIndex, TPM2_GetAlgName(algo));
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc != TPM_RC_SUCCESS) {
+ unmap_sysmem(digest);
+ return rc;
+ }
+
+ /* Read the PCR */
+ rc = wolfTPM2_ReadPCR(&dev, pcrIndex, algo, digest, &digestLen);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("TPM2_PCR_Read failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+ }
+
+ unmap_sysmem(digest);
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 pcr_read: rc = %d (%s)\n", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+int do_tpm2_pcr_allocate(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ PCR_Allocate_In in;
+ PCR_Allocate_Out out;
+ TPM2B_AUTH auth;
+
+ /* Need 3-4 args: command + algorithm + on/off + [password] */
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+
+ /* Setup PCR Allocation command */
+ memset(&in, 0, sizeof(in));
+ in.authHandle = TPM_RH_PLATFORM;
+
+ /* Single PCR bank allocation */
+ in.pcrAllocation.count = 1; /* Change only one bank */
+ in.pcrAllocation.pcrSelections[0].hash = TPM2_GetAlgId(argv[1]);
+ in.pcrAllocation.pcrSelections[0].sizeofSelect = PCR_SELECT_MAX;
+
+ /* Set all PCRs for this algorithm */
+ if (!strcmp(argv[2], "on")) {
+ memset(in.pcrAllocation.pcrSelections[0].pcrSelect, 0xFF,
+ PCR_SELECT_MAX);
+ } else if (!strcmp(argv[2], "off")) {
+ /* Clear all PCRs for this algorithm */
+ memset(in.pcrAllocation.pcrSelections[0].pcrSelect, 0x00,
+ PCR_SELECT_MAX);
+ } else {
+ log_debug("Couldn't recognize allocate mode: %s\n", argv[2]);
+ wolfTPM2_Cleanup(&dev);
+ return CMD_RET_USAGE;
+ }
+ log_debug("Attempting to set %s bank to %s\n",
+ TPM2_GetAlgName(in.pcrAllocation.pcrSelections[0].hash),
+ argv[2]);
+
+ /* Set auth password if provided */
+ if (argc == 4) {
+ memset(&auth, 0, sizeof(auth));
+ auth.size = strlen(argv[3]);
+ memcpy(auth.buffer, argv[3], auth.size);
+ rc = wolfTPM2_SetAuth(&dev, 0, TPM_RH_PLATFORM, &auth, 0, NULL);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("wolfTPM2_SetAuth failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+ wolfTPM2_Cleanup(&dev);
+ return rc;
+ }
+ }
+
+ /* Allocate the PCR */
+ rc = TPM2_PCR_Allocate(&in, &out);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("TPM2_PCR_Allocate failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+ }
+
+ /* Print current PCR state */
+ printf("\n\tNOTE: A TPM restart is required for changes to take effect\n");
+ printf("\nCurrent PCR state:\n");
+ TPM2_PCRs_Print();
+
+ wolfTPM2_Cleanup(&dev);
+
+ printf("Allocation Success: %s\n",
+ out.allocationSuccess ? "YES" : "NO");
+ log_debug("tpm2 pcr_allocate %s (%s): rc = %d (%s)\n",
+ TPM2_GetAlgName(in.pcrAllocation.pcrSelections[0].hash),
+ argv[2], rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+/*
+ * Without wolfCrypt, parameter encryption is not available.
+ * A session is required to protect the new platform auth.
+ */
+#ifndef WOLFTPM2_NO_WOLFCRYPT
+static int TPM2_PCR_SetAuth(int argc, char *const argv[],
+ int isPolicy)
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ WOLFTPM2_SESSION session;
+ TPM2B_AUTH auth;
+ const char *pw = (argc < 4) ? NULL : argv[3];
+ const char *key = argv[2];
+ const ssize_t key_sz = strlen(key);
+ u32 pcrIndex = simple_strtoul(argv[1], NULL, 0);
+
+ /* Need 3-4 args: command + pcr + auth + [platform_auth] */
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device for value/policy */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+
+ /* Start the session */
+ rc = wolfTPM2_StartSession(&dev, &session, NULL, NULL,
+ isPolicy ? TPM_SE_POLICY : TPM_SE_HMAC, TPM_ALG_NULL);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("wolfTPM2_StartSession failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+ wolfTPM2_Cleanup(&dev);
+ return rc;
+ }
+
+ /* Set the platform auth if provided */
+ if (pw) {
+ TPM2B_AUTH platformAuth;
+
+ memset(&platformAuth, 0, sizeof(platformAuth));
+ platformAuth.size = strlen(pw);
+ memcpy(platformAuth.buffer, pw, platformAuth.size);
+ rc = wolfTPM2_SetAuth(&dev, 0, TPM_RH_PLATFORM,
+ &platformAuth, 0, NULL);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("wolfTPM2_SetAuth failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+ wolfTPM2_UnloadHandle(&dev, &session.handle);
+ wolfTPM2_Cleanup(&dev);
+ return rc;
+ }
+ }
+
+ printf("Setting %s auth for PCR %u\n",
+ isPolicy ? "policy" : "value", pcrIndex);
+
+ /* Set up the auth value/policy */
+ memset(&auth, 0, sizeof(auth));
+ auth.size = key_sz;
+ memcpy(auth.buffer, key, key_sz);
+
+ if (isPolicy) {
+ /* Use TPM2_PCR_SetAuthPolicy command */
+ PCR_SetAuthPolicy_In in;
+
+ memset(&in, 0, sizeof(in));
+ in.authHandle = TPM_RH_PLATFORM;
+ in.authPolicy = auth;
+ in.hashAlg = TPM_ALG_SHA256; /* Default to SHA256 */
+ in.pcrNum = pcrIndex;
+ rc = TPM2_PCR_SetAuthPolicy(&in);
+ } else {
+ /* Use TPM2_PCR_SetAuthValue command */
+ PCR_SetAuthValue_In in;
+
+ memset(&in, 0, sizeof(in));
+ in.pcrHandle = pcrIndex;
+ in.auth = auth;
+ rc = TPM2_PCR_SetAuthValue(&in);
+ }
+
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("TPM2_PCR_SetAuth%s failed 0x%x: %s\n",
+ isPolicy ? "Policy" : "Value",
+ rc, TPM2_GetRCString(rc));
+ }
+
+ wolfTPM2_UnloadHandle(&dev, &session.handle);
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 set_auth %s: rc = %d (%s)\n",
+ isPolicy ? "Policy" : "Value", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+int do_tpm2_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ return TPM2_PCR_SetAuth(argc, argv, YES);
+}
+
+int do_tpm2_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ return TPM2_PCR_SetAuth(argc, argv, NO);
+}
+
+int do_tpm2_change_auth(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ WOLFTPM2_SESSION session;
+ const char *newpw = argv[2];
+ const char *oldpw = (argc == 4) ? argv[3] : NULL;
+ const ssize_t newpw_sz = strlen(newpw);
+ const ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;
+ HierarchyChangeAuth_In in;
+ TPM2B_AUTH newAuth;
+
+ /* Need 3-4 args: command + hierarchy + new_pw + [old_pw] */
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+
+ memset(&in, 0, sizeof(in));
+
+ /* Set the handle */
+ if (!strcmp(argv[1], "TPM2_RH_LOCKOUT"))
+ in.authHandle = TPM_RH_LOCKOUT;
+ else if (!strcmp(argv[1], "TPM2_RH_ENDORSEMENT"))
+ in.authHandle = TPM_RH_ENDORSEMENT;
+ else if (!strcmp(argv[1], "TPM2_RH_OWNER"))
+ in.authHandle = TPM_RH_OWNER;
+ else if (!strcmp(argv[1], "TPM2_RH_PLATFORM"))
+ in.authHandle = TPM_RH_PLATFORM;
+ else {
+ wolfTPM2_Cleanup(&dev);
+ return CMD_RET_USAGE;
+ }
+
+ /* Validate password length if provided */
+ if (newpw_sz > TPM_SHA256_DIGEST_SIZE ||
+ oldpw_sz > TPM_SHA256_DIGEST_SIZE) {
+ wolfTPM2_Cleanup(&dev);
+ return -EINVAL;
+ }
+
+ /* Start auth session */
+ rc = wolfTPM2_StartSession(&dev, &session, NULL, NULL,
+ TPM_SE_HMAC, TPM_ALG_CFB);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("wolfTPM2_StartSession failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+ wolfTPM2_Cleanup(&dev);
+ return rc;
+ }
+
+ /* If old password exists then set it as the current auth */
+ if (oldpw) {
+ TPM2B_AUTH oldAuth;
+
+ memset(&oldAuth, 0, sizeof(oldAuth));
+ oldAuth.size = oldpw_sz;
+ memcpy(oldAuth.buffer, oldpw, oldpw_sz);
+ rc = wolfTPM2_SetAuthPassword(&dev, 0, &oldAuth);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("wolfTPM2_SetAuthPassword failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+ wolfTPM2_UnloadHandle(&dev, &session.handle);
+ wolfTPM2_Cleanup(&dev);
+ return rc;
+ }
+ }
+
+ memset(&newAuth, 0, sizeof(newAuth));
+ newAuth.size = newpw_sz;
+ memcpy(newAuth.buffer, newpw, newpw_sz);
+ in.newAuth = newAuth;
+
+ /* Change the auth based on the hierarchy */
+ rc = wolfTPM2_ChangeHierarchyAuth(&dev, &session, in.authHandle);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("wolfTPM2_ChangeHierarchyAuth failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+ } else {
+ log_debug("Successfully changed auth for %s\n", argv[1]);
+ }
+
+ wolfTPM2_UnloadHandle(&dev, &session.handle);
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 change_auth: rc = %d (%s)\n", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+#else /* WOLFTPM2_NO_WOLFCRYPT */
+int do_tpm2_change_auth(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ printf("wolfCrypt support required for change_auth\n");
+ return CMD_RET_FAILURE;
+}
+
+int do_tpm2_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ printf("wolfCrypt support required for pcr_setauthpolicy\n");
+ return CMD_RET_FAILURE;
+}
+
+int do_tpm2_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ printf("wolfCrypt support required for pcr_setauthvalue\n");
+ return CMD_RET_FAILURE;
+}
+#endif /* !WOLFTPM2_NO_WOLFCRYPT */
+
+int do_tpm2_pcr_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+
+ /* Need 1 arg: command */
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc == TPM_RC_SUCCESS) {
+ /* Print the current PCR state */
+ TPM2_PCRs_Print();
+ }
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 pcr_print: rc = %d (%s)\n", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+int do_tpm2_dam_reset(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ const char *pw = (argc < 2) ? NULL : argv[1];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ DictionaryAttackLockReset_In in;
+ TPM2_AUTH_SESSION session[MAX_SESSION_NUM];
+
+ /* Need 1-2 args: command + [password] */
+ if (argc > 2)
+ return CMD_RET_USAGE;
+
+ /* Validate password length if provided */
+ if (pw && pw_sz > TPM_SHA256_DIGEST_SIZE) {
+ log_debug("Error: Password too long\n");
+ return -EINVAL;
+ }
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc == TPM_RC_SUCCESS) {
+ /* set lock handle */
+ memset(&in, 0, sizeof(in));
+ in.lockHandle = TPM_RH_LOCKOUT;
+
+ /* Setup auth session only if password provided */
+ memset(session, 0, sizeof(session));
+ session[0].sessionHandle = TPM_RS_PW;
+ if (pw) {
+ session[0].auth.size = pw_sz;
+ memcpy(session[0].auth.buffer, pw, pw_sz);
+ }
+ TPM2_SetSessionAuth(session);
+
+ rc = TPM2_DictionaryAttackLockReset(&in);
+ log_debug("TPM2_Dam_Reset: Result = 0x%x (%s)\n", rc,
+ TPM2_GetRCString(rc));
+ }
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 dam_reset: rc = %d (%s)\n", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+int do_tpm2_dam_parameters(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int rc;
+ WOLFTPM2_DEV dev;
+ const char *pw = (argc < 5) ? NULL : argv[4];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ DictionaryAttackParameters_In in;
+ TPM2_AUTH_SESSION session[MAX_SESSION_NUM];
+
+ /*
+ * Need 4-5 args: command + max_tries + recovery_time +
+ * lockout_recovery + [password]
+ */
+ if (argc < 4 || argc > 5)
+ return CMD_RET_USAGE;
+
+ /* Validate password length if provided */
+ if (pw && pw_sz > TPM_SHA256_DIGEST_SIZE) {
+ log_debug("Error: Password too long\n");
+ return -EINVAL;
+ }
+
+ /* Init the TPM2 device */
+ rc = TPM2_Init_Device(&dev, NULL);
+ if (rc == TPM_RC_SUCCESS) {
+ /* Set parameters */
+ memset(&in, 0, sizeof(in));
+ in.newMaxTries = simple_strtoul(argv[1], NULL, 0);
+ in.newRecoveryTime = simple_strtoul(argv[2], NULL, 0);
+ in.lockoutRecovery = simple_strtoul(argv[3], NULL, 0);
+
+ /* set lock handle */
+ in.lockHandle = TPM_RH_LOCKOUT;
+
+ /* Setup auth session only if password provided */
+ memset(session, 0, sizeof(session));
+ session[0].sessionHandle = TPM_RS_PW;
+ if (pw) {
+ session[0].auth.size = pw_sz;
+ memcpy(session[0].auth.buffer, pw, pw_sz);
+ }
+ TPM2_SetSessionAuth(session);
+
+ /* Set DAM parameters */
+ rc = TPM2_DictionaryAttackParameters(&in);
+ if (rc != TPM_RC_SUCCESS) {
+ log_debug("TPM2_DictionaryAttackParameters failed 0x%x: %s\n", rc,
+ TPM2_GetRCString(rc));
+ }
+
+ printf("Changing dictionary attack parameters:\n");
+ printf(" maxTries: %u\n", in.newMaxTries);
+ printf(" recoveryTime: %u\n", in.newRecoveryTime);
+ printf(" lockoutRecovery: %u\n", in.lockoutRecovery);
+ }
+ wolfTPM2_Cleanup(&dev);
+
+ log_debug("tpm2 dam_parameters: rc = %d (%s)\n", rc, TPM2_GetRCString(rc));
+
+ return rc;
+}
+
+#endif /* !WOLFTPM2_NO_WRAPPER */
--
2.49.0
next prev parent reply other threads:[~2026-05-13 0:28 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-13 0:26 [PATCH v4 00/14] tpm: Add wolfTPM library support for TPM 2.0 Aidan Garske
2026-05-13 0:26 ` [PATCH v4 01/14] tpm: export tpm_show_device, tpm_set_device, and get_tpm Aidan Garske
2026-05-15 13:06 ` Simon Glass
2026-05-13 0:26 ` [PATCH v4 02/14] include/hash: add SHA384 hash wrapper declaration for wolfTPM Aidan Garske
2026-05-13 0:26 ` [PATCH v4 03/14] spi: add BCM2835/BCM2711 hardware SPI controller driver Aidan Garske
2026-05-15 13:07 ` Simon Glass
2026-05-15 15:13 ` Peter Robinson
2026-05-13 0:26 ` [PATCH v4 04/14] arm: dts: bcm2711-rpi-4-b: add Infineon SLB9670/9672 TPM in U-Boot dtsi Aidan Garske
2026-05-15 13:08 ` Simon Glass
2026-05-13 0:26 ` [PATCH v4 05/14] arm: dts: qemu-arm64: add TPM TIS MMIO node Aidan Garske
2026-05-15 13:09 ` Simon Glass
2026-05-13 0:26 ` [PATCH v4 06/14] sandbox: dts: add TPM SPI emulator node Aidan Garske
2026-05-15 13:11 ` Simon Glass
2026-05-13 0:26 ` [PATCH v4 07/14] tpm: add wolfTPM build rules and Kconfig Aidan Garske
2026-05-13 0:26 ` [PATCH v4 08/14] tpm: add wolfTPM headers and SHA384 glue code Aidan Garske
2026-05-13 0:26 ` [PATCH v4 09/14] tpm: add wolfTPM driver helpers and Kconfig options Aidan Garske
2026-05-13 0:26 ` Aidan Garske [this message]
2026-05-15 14:11 ` [PATCH v4 10/14] cmd: refactor tpm2 command into frontend/backend architecture Simon Glass
2026-05-15 14:15 ` Simon Glass
2026-05-13 0:26 ` [PATCH v4 11/14] tpm: add sandbox TPM SPI emulator Aidan Garske
2026-05-15 13:24 ` Simon Glass
2026-05-13 0:26 ` [PATCH v4 12/14] test: add wolfTPM C unit tests and Python integration tests Aidan Garske
2026-05-15 14:15 ` Simon Glass
2026-05-13 0:26 ` [PATCH v4 13/14] doc: add wolfTPM documentation Aidan Garske
2026-05-13 0:26 ` [PATCH v4 14/14] configs: add rpi_4_wolftpm_defconfig Aidan Garske
2026-05-15 11:31 ` Matthias Brugger
2026-05-13 6:35 ` [PATCH v4 00/14] tpm: Add wolfTPM library support for TPM 2.0 Ilias Apalodimas
2026-05-13 14:34 ` Tom Rini
2026-05-13 16:04 ` Aidan Garske
2026-05-13 16:36 ` Peter Robinson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260513002625.76915-10-aidan@wolfssl.com \
--to=aidan@wolfssl.com \
--cc=andrew.goodbody@linaro.org \
--cc=briansune@gmail.com \
--cc=david@wolfssl.com \
--cc=dinesh.maniyam@altera.com \
--cc=hs@nabladev.com \
--cc=ilias.apalodimas@linaro.org \
--cc=jerome@forissier.org \
--cc=kory.maincent@bootlin.com \
--cc=michael@amarulasolutions.com \
--cc=michal.simek@amd.com \
--cc=mikhail.kshevetskiy@iopsys.eu \
--cc=mkorpershoek@kernel.org \
--cc=pbrobinson@gmail.com \
--cc=seanedmond@microsoft.com \
--cc=sjg@chromium.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
--cc=xypron.glpk@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.