Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.2/patches/2235250/?format=api
{ "id": 2235250, "url": "http://patchwork.ozlabs.org/api/1.2/patches/2235250/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/94b785256db46e90c2c7f4b862c4686de37ea6e4.1778277334.git.aidan@wolfssl.com/", "project": { "id": 18, "url": "http://patchwork.ozlabs.org/api/1.2/projects/18/?format=api", "name": "U-Boot", "link_name": "uboot", "list_id": "u-boot.lists.denx.de", "list_email": "u-boot@lists.denx.de", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<94b785256db46e90c2c7f4b862c4686de37ea6e4.1778277334.git.aidan@wolfssl.com>", "list_archive_url": null, "date": "2026-05-09T00:04:15", "name": "[v3,08/12] cmd: refactor tpm2 command into frontend/backend architecture", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "de80c076f1c6b14b12d6b9d2acf439cec84197a9", "submitter": { "id": 92785, "url": "http://patchwork.ozlabs.org/api/1.2/people/92785/?format=api", "name": "Aidan Garske", "email": "aidan@wolfssl.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/94b785256db46e90c2c7f4b862c4686de37ea6e4.1778277334.git.aidan@wolfssl.com/mbox/", "series": [ { "id": 503464, "url": "http://patchwork.ozlabs.org/api/1.2/series/503464/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=503464", "date": "2026-05-09T00:04:07", "name": "tpm: Add wolfTPM library support for TPM 2.0", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/503464/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2235250/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2235250/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<u-boot-bounces@lists.denx.de>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=wolfssl-com.20251104.gappssmtp.com\n header.i=@wolfssl-com.20251104.gappssmtp.com header.a=rsa-sha256\n header.s=20251104 header.b=IP0i3JY0;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)", "phobos.denx.de;\n dmarc=fail (p=none dis=none) header.from=wolfssl.com", "phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de", "phobos.denx.de;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=wolfssl-com.20251104.gappssmtp.com\n header.i=@wolfssl-com.20251104.gappssmtp.com header.b=\"IP0i3JY0\";\n\tdkim-atps=neutral", "phobos.denx.de;\n dmarc=fail (p=none dis=none) header.from=wolfssl.com", "phobos.denx.de;\n spf=pass smtp.mailfrom=aidan@wolfssl.com" ], "Received": [ "from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4gC6cm1zMmz1yCg\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 09 May 2026 10:41:44 +1000 (AEST)", "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 7686484E38;\n\tSat, 9 May 2026 02:40:16 +0200 (CEST)", "by phobos.denx.de (Postfix, from userid 109)\n id DE58284E10; Sat, 9 May 2026 02:04:55 +0200 (CEST)", "from mail-dl1-x122e.google.com (mail-dl1-x122e.google.com\n [IPv6:2607:f8b0:4864:20::122e])\n (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id 91BF584E02\n for <u-boot@lists.denx.de>; Sat, 9 May 2026 02:04:51 +0200 (CEST)", "by mail-dl1-x122e.google.com with SMTP id\n a92af1059eb24-13246950f3cso2617295c88.1\n for <u-boot@lists.denx.de>; Fri, 08 May 2026 17:04:51 -0700 (PDT)", "from localhost.localdomain ([207.231.76.218])\n by smtp.gmail.com with ESMTPSA id\n a92af1059eb24-132787673ffsm5505030c88.15.2026.05.08.17.04.47\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Fri, 08 May 2026 17:04:47 -0700 (PDT)" ], "X-Spam-Checker-Version": "SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de", "X-Spam-Level": "*", "X-Spam-Status": "No, score=1.4 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,RCVD_IN_DNSWL_BLOCKED,RCVD_IN_SBL_CSS,SPF_HELO_NONE,\n SPF_PASS autolearn=no autolearn_force=no version=3.4.2", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=wolfssl-com.20251104.gappssmtp.com; s=20251104; t=1778285089; x=1778889889;\n darn=lists.denx.de;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=sx9NICbsiHn/bnRMoIEsoWLvd8d/hf90nuL0/ybK97M=;\n b=IP0i3JY05s0VzurkCErvp0AeNvHqOEluHle93mleAJPnoGVkXLKtGSnGST9sDjDLNa\n Vkyn9mzIkEIUhjAflOXjXa6eVkAQrtAwYP+w+PpywdYNrpmHp6T8toNI6z5M9X5S2tMr\n NqiD5xJUQcjyBecWLm0yMzGPzv2o2ezAJ5jXW9WWgfKglE3y8IeHVWnxA44oocEf+8Zw\n xScWp7QWDqzE8KgAL4tITLlJU5TddlbUogvHR6SPM6Fa91sf0zWP98zFh/CKLQVcKWQX\n EPV/lTSJsq+W9/eO6RVYq3hcME+yvJn98mh0e2oPEIfKuX2TSoU6FSHn5N46viNnDwIn\n Sh9Q==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1778285089; x=1778889889;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=sx9NICbsiHn/bnRMoIEsoWLvd8d/hf90nuL0/ybK97M=;\n b=GddMNq/g4bj/sn1j+Joi2JzzPrr1/2y0BvDi7bosItex7mEaHo2pOt0kSaEIKzQocs\n mZu1T80nhoVLDDW6CCwB+DPIrqLY8ZT9+WEZIMk0OplekTqpXNPmEZ2yRmUbJZaS5wq/\n 70HNppNU5dNHAUee1BF7C86Q1/I5Rf/sy18EZIR6/MgpAr0js8GLAUVjpQ+MT9irftAt\n o6Y5LW3HCQD7jHtQ79ZB14rPViTXWLLsVIBf54rvSxCzhdkiM0gQJYXtkEvSesnaBsmn\n YnZNhv62zNHwM+cXXiyfuiDtDL0e/TO7M0D4XU5e/qxCCmDkMvU2WACrgBbEh7m/IhBe\n eugg==", "X-Gm-Message-State": "AOJu0YyEMxQ4nA9XeYDxXvbk+HVdLWSLgqMwfqB+MzYavXWwe5MsNGtT\n ZHdFKCORTjPMRbaOFAFEt3+I6cDt4nKsBURCuNCv8KOUKbNr3FaUgkBr7wEM2qbw4CxeDaJzY2R\n GT8qa", "X-Gm-Gg": "AeBDiev5/IsG+HYJ9IfjM4M6Tmvp0sBbA+ZwQESRmwRikWZsrT2In+4gt1W8ChZWDjJ\n lDZq10y6RVaOuhvctGAR6vJ06owIkXHdnoI0uGipRLif/rgpV3CMzZyXRqhcu/BbJ2R5kirYODO\n t64r6CIuMiZBtVfE+tvNYPOvr/37ybCFiI9ObQJIHAp2V0MmxI8bvHaKPrk+7V+xztkeah1uHQH\n xSnPF30LXDsUcyQpvWIJvOqpg8yDBsqQzRCUuIxacPjRbJpcEUrj6VwTUnHKBxdWf0Ncl4CV9aE\n QpqTZ9Xq8f6ztXn9o1Bo5eDfDsCssYWDqY6WQW3D46e6Ikn+X8Bld7cZxXeEq6IHKzADi65u2cm\n IgSYbm31KEdM0/2RmbLztMoFUGoAWlSvTS0oJhBsGeOpQY46VMEnu1KJkbIEdKXW12rbl7iwKd/\n sDu95l9qx/EXE6WHdU8u5cn1dfO65TXqJT+ZT/wZDxrofI8ATmQKGzVQd27PpgkSbh2T1PBc+Hv\n GtXGxadK4Ljj3SSrYtzOA==", "X-Received": "by 2002:a05:7022:222a:b0:12d:c039:6599 with SMTP id\n a92af1059eb24-132a81d8c9bmr275717c88.22.1778285088097;\n Fri, 08 May 2026 17:04:48 -0700 (PDT)", "From": "Aidan Garske <aidan@wolfssl.com>", "To": "u-boot@lists.denx.de", "Cc": "David Garske <david@wolfssl.com>,\n Ilias Apalodimas <ilias.apalodimas@linaro.org>", "Subject": "[PATCH v3 08/12] cmd: refactor tpm2 command into frontend/backend\n architecture", "Date": "Fri, 8 May 2026 17:04:15 -0700", "Message-ID": "\n <94b785256db46e90c2c7f4b862c4686de37ea6e4.1778277334.git.aidan@wolfssl.com>", "X-Mailer": "git-send-email 2.47.3", "In-Reply-To": "<cover.1778277334.git.aidan@wolfssl.com>", "References": "<cover.1778277334.git.aidan@wolfssl.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-Mailman-Approved-At": "Sat, 09 May 2026 02:40:11 +0200", "X-BeenThere": "u-boot@lists.denx.de", "X-Mailman-Version": "2.1.39", "Precedence": "list", "List-Id": "U-Boot discussion <u-boot.lists.denx.de>", "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>", "List-Archive": "<https://lists.denx.de/pipermail/u-boot/>", "List-Post": "<mailto:u-boot@lists.denx.de>", "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>", "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>", "Errors-To": "u-boot-bounces@lists.denx.de", "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>", "X-Virus-Scanned": "clamav-milter 0.103.8 at phobos.denx.de", "X-Virus-Status": "Clean" }, "content": "From: Aidan <aidan@wolfssl.com>\n\nSplit the tpm2 command implementation into a shared frontend and\ntwo selectable backends. This allows wolfTPM to provide its own\nTPM2 command implementations while keeping the command table,\ndispatcher, and help text shared.\n\nArchitecture:\n\ncmd/tpm-v2.c (frontend - always compiled):\n Contains the tpm2_commands[] table, get_tpm2_commands(), the\n do_tpm2() dispatcher, and the U_BOOT_CMD help text. References\n backend functions via cmd/tpm2-backend.h. When CONFIG_TPM_WOLF\n is enabled, additional wolfTPM-only commands (caps, pcr_print,\n firmware_update, firmware_cancel) are added to the table.\n\ncmd/tpm2-backend.h (new):\n Declares all backend function prototypes that both backends must\n implement: do_tpm2_device, do_tpm2_info, do_tpm2_init,\n do_tpm2_startup, do_tpm2_selftest, do_tpm2_clear,\n do_tpm2_pcr_extend, do_tpm2_pcr_read, do_tpm2_get_capability,\n do_tpm2_dam_reset, do_tpm2_dam_parameters, do_tpm2_change_auth,\n do_tpm2_pcr_setauthpolicy, do_tpm2_pcr_setauthvalue,\n do_tpm2_pcr_allocate, plus wolfTPM-only functions.\n\ncmd/native_tpm2.c (new - native backend):\n Contains the original tpm2 command implementations that use\n U-Boot's TPM driver model (tpm_api.h, tpm-v2.h). Compiled when\n CONFIG_TPM_WOLF is not set. Common commands delegate to\n tpm-common.c helpers (do_tpm_device, do_tpm_info, etc.).\n\ncmd/wolftpm.c (new - wolfTPM backend):\n Implements all tpm2 commands using wolfTPM library APIs directly\n (wolfTPM2_Init, wolfTPM2_GetCapabilities, wolfTPM2_ExtendPCR,\n etc.). Includes Infineon-specific firmware update and cancel\n commands. Each command initializes its own WOLFTPM2_DEV instance\n rather than going through U-Boot's driver model.\n\ncmd/Kconfig:\n Adds CMD_WOLFTPM option that selects TPM_WOLF and CMD_TPM_V2,\n providing a single menuconfig toggle for wolfTPM support.\n\ncmd/Makefile:\n Conditionally compiles wolftpm.o (when CONFIG_TPM_WOLF=y) or\n native_tpm2.o (otherwise) alongside the shared tpm-v2.o frontend.\n Sets wolfTPM include paths and -DWOLFTPM_USER_SETTINGS.\n\nThe reason for separate backend files rather than a callback-based\napproach is that wolfTPM uses fundamentally different types and\ninitialization patterns (WOLFTPM2_DEV vs struct udevice, direct\nlibrary calls vs driver model ops), making runtime dispatch\nimpractical without heavy abstraction.\n\nSigned-off-by: Aidan Garske <aidan@wolfssl.com>\n---\n cmd/Kconfig | 11 +\n cmd/Makefile | 10 +-\n cmd/native_tpm2.c | 516 +++++++++++++++++++\n cmd/tpm-v2.c | 559 +++------------------\n cmd/tpm2-backend.h | 66 +++\n cmd/wolftpm.c | 1170 ++++++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 1840 insertions(+), 492 deletions(-)\n create mode 100644 cmd/native_tpm2.c\n create mode 100644 cmd/tpm2-backend.h\n create mode 100644 cmd/wolftpm.c", "diff": "diff --git a/cmd/Kconfig b/cmd/Kconfig\nindex b71ac554c0b..fe9b3819eaa 100644\n--- a/cmd/Kconfig\n+++ b/cmd/Kconfig\n@@ -3194,4 +3194,15 @@ config CMD_SPAWN_NUM_JOBS\n \t When a jobs exits, its identifier is available to be re-used by the next\n \t spawn command.\n \n+config CMD_WOLFTPM\n+\tbool \"Use wolfTPM as TPM2 backend\"\n+\tdepends on TPM_V2\n+\tselect TPM_WOLF\n+\tselect CMD_TPM_V2\n+\thelp\n+\t Use the wolfTPM library as the backend for TPM2 commands instead\n+\t of the standard U-Boot TPM2 implementation. wolfTPM offers additional\n+\t features including firmware update support for Infineon TPMs and\n+\t enhanced capabilities reporting.\n+\n endif\ndiff --git a/cmd/Makefile b/cmd/Makefile\nindex 4cd13d4fa6e..2b12b26e61f 100644\n--- a/cmd/Makefile\n+++ b/cmd/Makefile\n@@ -191,9 +191,17 @@ obj-$(CONFIG_CMD_TIMER) += timer.o\n obj-$(CONFIG_CMD_TRACE) += trace.o\n obj-$(CONFIG_HUSH_PARSER) += test.o\n obj-$(CONFIG_CMD_TPM) += tpm-common.o\n-obj-$(CONFIG_CMD_TPM_V1) += tpm-v1.o\n obj-$(CONFIG_CMD_TPM_TEST) += tpm_test.o\n+obj-$(CONFIG_CMD_TPM_V1) += tpm-v1.o\n obj-$(CONFIG_CMD_TPM_V2) += tpm-v2.o\n+ifeq ($(CONFIG_TPM_WOLF),y)\n+ccflags-y += -I$(srctree)/lib/wolftpm \\\n+ -I$(srctree)/include/configs \\\n+ -DWOLFTPM_USER_SETTINGS\n+obj-$(CONFIG_CMD_TPM_V2) += wolftpm.o\n+else\n+obj-$(CONFIG_CMD_TPM_V2) += native_tpm2.o\n+endif\n obj-$(CONFIG_CMD_CROS_EC) += cros_ec.o\n obj-$(CONFIG_CMD_UBI) += ubi.o\n obj-$(CONFIG_CMD_UBIFS) += ubifs.o\ndiff --git a/cmd/native_tpm2.c b/cmd/native_tpm2.c\nnew file mode 100644\nindex 00000000000..d8dea956156\n--- /dev/null\n+++ b/cmd/native_tpm2.c\n@@ -0,0 +1,516 @@\n+// SPDX-License-Identifier: GPL-2.0+\n+/*\n+ * Native TPM2 backend implementation\n+ *\n+ * Copyright (c) 2018 Bootlin\n+ * Author: Miquel Raynal <miquel.raynal@bootlin.com>\n+ */\n+\n+#include <command.h>\n+#include <dm.h>\n+#include <log.h>\n+#include <mapmem.h>\n+#include <tpm-common.h>\n+#include <tpm-v2.h>\n+#include \"tpm-user-utils.h\"\n+\n+/* Wrappers for common commands - delegate to tpm-common.c */\n+int do_tpm2_device(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\treturn do_tpm_device(cmdtp, flag, argc, argv);\n+}\n+\n+int do_tpm2_info(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\treturn do_tpm_info(cmdtp, flag, argc, argv);\n+}\n+\n+int do_tpm2_state(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\treturn do_tpm_report_state(cmdtp, flag, argc, argv);\n+}\n+\n+int do_tpm2_init(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\treturn do_tpm_init(cmdtp, flag, argc, argv);\n+}\n+\n+int do_tpm2_autostart(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\treturn do_tpm_autostart(cmdtp, flag, argc, argv);\n+}\n+\n+int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\tenum tpm2_startup_types mode;\n+\tstruct udevice *dev;\n+\tint ret;\n+\tbool bon = true;\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* argv[2] is optional to perform a TPM2_CC_SHUTDOWN */\n+\tif (argc > 3 || (argc == 3 && strcasecmp(\"off\", argv[2])))\n+\t\treturn CMD_RET_USAGE;\n+\n+\tif (!strcasecmp(\"TPM2_SU_CLEAR\", argv[1])) {\n+\t\tmode = TPM2_SU_CLEAR;\n+\t} else if (!strcasecmp(\"TPM2_SU_STATE\", argv[1])) {\n+\t\tmode = TPM2_SU_STATE;\n+\t} else {\n+\t\tprintf(\"Couldn't recognize mode string: %s\\n\", argv[1]);\n+\t\treturn CMD_RET_FAILURE;\n+\t}\n+\n+\tif (argv[2])\n+\t\tbon = false;\n+\n+\treturn report_return_code(tpm2_startup(dev, bon, mode));\n+}\n+\n+int do_tpm2_selftest(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\tenum tpm2_yes_no full_test;\n+\tstruct udevice *dev;\n+\tint ret;\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\tif (argc != 2)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tif (!strcasecmp(\"full\", argv[1])) {\n+\t\tfull_test = TPMI_YES;\n+\t} else if (!strcasecmp(\"continue\", argv[1])) {\n+\t\tfull_test = TPMI_NO;\n+\t} else {\n+\t\tprintf(\"Couldn't recognize test mode: %s\\n\", argv[1]);\n+\t\treturn CMD_RET_FAILURE;\n+\t}\n+\n+\treturn report_return_code(tpm2_self_test(dev, full_test));\n+}\n+\n+int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\tu32 handle = 0;\n+\tconst char *pw = (argc < 3) ? NULL : argv[2];\n+\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n+\tstruct udevice *dev;\n+\tint ret;\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (argc < 2 || argc > 3)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tif (pw_sz > TPM2_DIGEST_LEN)\n+\t\treturn -EINVAL;\n+\n+\tif (!strcasecmp(\"TPM2_RH_LOCKOUT\", argv[1]))\n+\t\thandle = TPM2_RH_LOCKOUT;\n+\telse if (!strcasecmp(\"TPM2_RH_PLATFORM\", argv[1]))\n+\t\thandle = TPM2_RH_PLATFORM;\n+\telse\n+\t\treturn CMD_RET_USAGE;\n+\n+\treturn report_return_code(tpm2_clear(dev, handle, pw, pw_sz));\n+}\n+\n+int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\tstruct udevice *dev;\n+\tstruct tpm_chip_priv *priv;\n+\tu32 index = simple_strtoul(argv[1], NULL, 0);\n+\tvoid *digest = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);\n+\tint algo = TPM2_ALG_SHA256;\n+\tint algo_len;\n+\tint ret;\n+\tu32 rc;\n+\n+\tif (argc < 3 || argc > 4)\n+\t\treturn CMD_RET_USAGE;\n+\tif (argc == 4) {\n+\t\talgo = tpm2_name_to_algorithm(argv[3]);\n+\t\tif (algo == TPM2_ALG_INVAL)\n+\t\t\treturn CMD_RET_FAILURE;\n+\t}\n+\talgo_len = tpm2_algorithm_to_len(algo);\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tpriv = dev_get_uclass_priv(dev);\n+\tif (!priv)\n+\t\treturn -EINVAL;\n+\n+\tif (index >= priv->pcr_count)\n+\t\treturn -EINVAL;\n+\n+\trc = tpm2_pcr_extend(dev, index, algo, digest, algo_len);\n+\tif (!rc) {\n+\t\tprintf(\"PCR #%u extended with %d byte %s digest\\n\", index,\n+\t\t algo_len, tpm2_algorithm_name(algo));\n+\t\tprint_byte_string(digest, algo_len);\n+\t}\n+\n+\tunmap_sysmem(digest);\n+\n+\treturn report_return_code(rc);\n+}\n+\n+int do_tpm2_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\tenum tpm2_algorithms algo = TPM2_ALG_SHA256;\n+\tstruct udevice *dev;\n+\tstruct tpm_chip_priv *priv;\n+\tu32 index, rc;\n+\tint algo_len;\n+\tunsigned int updates;\n+\tvoid *data;\n+\tint ret;\n+\n+\tif (argc < 3 || argc > 4)\n+\t\treturn CMD_RET_USAGE;\n+\tif (argc == 4) {\n+\t\talgo = tpm2_name_to_algorithm(argv[3]);\n+\t\tif (algo == TPM2_ALG_INVAL)\n+\t\t\treturn CMD_RET_FAILURE;\n+\t}\n+\talgo_len = tpm2_algorithm_to_len(algo);\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tpriv = dev_get_uclass_priv(dev);\n+\tif (!priv)\n+\t\treturn -EINVAL;\n+\n+\tindex = simple_strtoul(argv[1], NULL, 0);\n+\tif (index >= priv->pcr_count)\n+\t\treturn -EINVAL;\n+\n+\tdata = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);\n+\n+\trc = tpm2_pcr_read(dev, index, priv->pcr_select_min, algo,\n+\t\t\t data, algo_len, &updates);\n+\tif (!rc) {\n+\t\tprintf(\"PCR #%u %s %d byte content (%u known updates):\\n\", index,\n+\t\t tpm2_algorithm_name(algo), algo_len, updates);\n+\t\tprint_byte_string(data, algo_len);\n+\t}\n+\n+\tunmap_sysmem(data);\n+\n+\treturn report_return_code(rc);\n+}\n+\n+int do_tpm2_get_capability(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\t char *const argv[])\n+{\n+\tu32 capability, property, rc;\n+\tu8 *data;\n+\tsize_t count;\n+\tint i, j;\n+\tstruct udevice *dev;\n+\tint ret;\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (argc != 5)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tcapability = simple_strtoul(argv[1], NULL, 0);\n+\tproperty = simple_strtoul(argv[2], NULL, 0);\n+\tdata = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);\n+\tcount = simple_strtoul(argv[4], NULL, 0);\n+\n+\trc = tpm2_get_capability(dev, capability, property, data, count);\n+\tif (rc)\n+\t\tgoto unmap_data;\n+\n+\tprintf(\"Capabilities read from TPM:\\n\");\n+\tfor (i = 0; i < count; i++) {\n+\t\tprintf(\"Property 0x\");\n+\t\tfor (j = 0; j < 4; j++)\n+\t\t\tprintf(\"%02x\", data[(i * 8) + j + sizeof(u32)]);\n+\t\tprintf(\": 0x\");\n+\t\tfor (j = 4; j < 8; j++)\n+\t\t\tprintf(\"%02x\", data[(i * 8) + j + sizeof(u32)]);\n+\t\tprintf(\"\\n\");\n+\t}\n+\n+unmap_data:\n+\tunmap_sysmem(data);\n+\n+\treturn report_return_code(rc);\n+}\n+\n+static u32 select_mask(u32 mask, enum tpm2_algorithms algo, bool select)\n+{\n+\tsize_t i;\n+\n+\tfor (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {\n+\t\tif (hash_algo_list[i].hash_alg != algo)\n+\t\t\tcontinue;\n+\n+\t\tif (select)\n+\t\t\tmask |= hash_algo_list[i].hash_mask;\n+\t\telse\n+\t\t\tmask &= ~hash_algo_list[i].hash_mask;\n+\n+\t\tbreak;\n+\t}\n+\n+\treturn mask;\n+}\n+\n+static bool\n+is_algo_in_pcrs(enum tpm2_algorithms algo, struct tpml_pcr_selection *pcrs)\n+{\n+\tsize_t i;\n+\n+\tfor (i = 0; i < pcrs->count; i++) {\n+\t\tif (algo == pcrs->selection[i].hash)\n+\t\t\treturn true;\n+\t}\n+\n+\treturn false;\n+}\n+\n+int do_tpm2_pcr_allocate(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\t char *const argv[])\n+{\n+\tstruct udevice *dev;\n+\tint ret;\n+\tenum tpm2_algorithms algo;\n+\tconst char *pw = (argc < 4) ? NULL : argv[3];\n+\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n+\tstatic struct tpml_pcr_selection pcr = { 0 };\n+\tu32 pcr_len = 0;\n+\tbool bon = false;\n+\tstatic u32 mask;\n+\tint i;\n+\n+\t/* argv[1]: algorithm (bank), argv[2]: on/off */\n+\tif (argc < 3 || argc > 4)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tif (!strcasecmp(\"on\", argv[2]))\n+\t\tbon = true;\n+\telse if (strcasecmp(\"off\", argv[2]))\n+\t\treturn CMD_RET_USAGE;\n+\n+\talgo = tpm2_name_to_algorithm(argv[1]);\n+\tif (algo == TPM2_ALG_INVAL)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (!pcr.count) {\n+\t\t/*\n+\t\t * Get current active algorithms (banks), PCRs and mask via the\n+\t\t * first call\n+\t\t */\n+\t\tret = tpm2_get_pcr_info(dev, &pcr);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tfor (i = 0; i < pcr.count; i++) {\n+\t\t\tstruct tpms_pcr_selection *sel = &pcr.selection[i];\n+\t\t\tconst char *name;\n+\n+\t\t\tif (!tpm2_is_active_bank(sel))\n+\t\t\t\tcontinue;\n+\n+\t\t\tmask = select_mask(mask, sel->hash, true);\n+\t\t\tname = tpm2_algorithm_name(sel->hash);\n+\t\t\tif (name)\n+\t\t\t\tprintf(\"Active bank[%d]: %s\\n\", i, name);\n+\t\t}\n+\t}\n+\n+\tif (!is_algo_in_pcrs(algo, &pcr)) {\n+\t\tprintf(\"%s is not supported by the tpm device\\n\", argv[1]);\n+\t\treturn CMD_RET_USAGE;\n+\t}\n+\n+\tmask = select_mask(mask, algo, bon);\n+\tret = tpm2_pcr_config_algo(dev, mask, &pcr, &pcr_len);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn report_return_code(tpm2_send_pcr_allocate(dev, pw, pw_sz, &pcr,\n+\t\t\t\t\t\t\t pcr_len));\n+}\n+\n+int do_tpm2_dam_reset(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\tconst char *pw = (argc < 2) ? NULL : argv[1];\n+\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n+\tstruct udevice *dev;\n+\tint ret;\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (argc > 2)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tif (pw_sz > TPM2_DIGEST_LEN)\n+\t\treturn -EINVAL;\n+\n+\treturn report_return_code(tpm2_dam_reset(dev, pw, pw_sz));\n+}\n+\n+int do_tpm2_dam_parameters(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\t char *const argv[])\n+{\n+\tconst char *pw = (argc < 5) ? NULL : argv[4];\n+\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n+\t/*\n+\t * No Dictionary Attack Mitigation (DAM) means:\n+\t * maxtries = 0xFFFFFFFF, recovery_time = 1, lockout_recovery = 0\n+\t */\n+\tunsigned long int max_tries;\n+\tunsigned long int recovery_time;\n+\tunsigned long int lockout_recovery;\n+\tstruct udevice *dev;\n+\tint ret;\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (argc < 4 || argc > 5)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tif (pw_sz > TPM2_DIGEST_LEN)\n+\t\treturn -EINVAL;\n+\n+\tif (strict_strtoul(argv[1], 0, &max_tries))\n+\t\treturn CMD_RET_USAGE;\n+\n+\tif (strict_strtoul(argv[2], 0, &recovery_time))\n+\t\treturn CMD_RET_USAGE;\n+\n+\tif (strict_strtoul(argv[3], 0, &lockout_recovery))\n+\t\treturn CMD_RET_USAGE;\n+\n+\tlog(LOGC_NONE, LOGL_INFO, \"Changing dictionary attack parameters:\\n\");\n+\tlog(LOGC_NONE, LOGL_INFO, \"- maxTries: %lu\", max_tries);\n+\tlog(LOGC_NONE, LOGL_INFO, \"- recoveryTime: %lu\\n\", recovery_time);\n+\tlog(LOGC_NONE, LOGL_INFO, \"- lockoutRecovery: %lu\\n\", lockout_recovery);\n+\n+\treturn report_return_code(tpm2_dam_parameters(dev, pw, pw_sz, max_tries,\n+\t\t\t\t\t\t recovery_time,\n+\t\t\t\t\t\t lockout_recovery));\n+}\n+\n+int do_tpm2_change_auth(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\tchar *const argv[])\n+{\n+\tu32 handle;\n+\tconst char *newpw = argv[2];\n+\tconst char *oldpw = (argc == 3) ? NULL : argv[3];\n+\tconst ssize_t newpw_sz = strlen(newpw);\n+\tconst ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;\n+\tstruct udevice *dev;\n+\tint ret;\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (argc < 3 || argc > 4)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tif (newpw_sz > TPM2_DIGEST_LEN || oldpw_sz > TPM2_DIGEST_LEN)\n+\t\treturn -EINVAL;\n+\n+\tif (!strcasecmp(\"TPM2_RH_LOCKOUT\", argv[1]))\n+\t\thandle = TPM2_RH_LOCKOUT;\n+\telse if (!strcasecmp(\"TPM2_RH_ENDORSEMENT\", argv[1]))\n+\t\thandle = TPM2_RH_ENDORSEMENT;\n+\telse if (!strcasecmp(\"TPM2_RH_OWNER\", argv[1]))\n+\t\thandle = TPM2_RH_OWNER;\n+\telse if (!strcasecmp(\"TPM2_RH_PLATFORM\", argv[1]))\n+\t\thandle = TPM2_RH_PLATFORM;\n+\telse\n+\t\treturn CMD_RET_USAGE;\n+\n+\treturn report_return_code(tpm2_change_auth(dev, handle, newpw, newpw_sz,\n+\t\t\t\t\t\t oldpw, oldpw_sz));\n+}\n+\n+int do_tpm2_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\t char *const argv[])\n+{\n+\tu32 index = simple_strtoul(argv[1], NULL, 0);\n+\tchar *key = argv[2];\n+\tconst char *pw = (argc < 4) ? NULL : argv[3];\n+\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n+\tstruct udevice *dev;\n+\tint ret;\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (strlen(key) != TPM2_DIGEST_LEN)\n+\t\treturn -EINVAL;\n+\n+\tif (argc < 3 || argc > 4)\n+\t\treturn CMD_RET_USAGE;\n+\n+\treturn report_return_code(tpm2_pcr_setauthpolicy(dev, pw, pw_sz, index,\n+\t\t\t\t\t\t\t key));\n+}\n+\n+int do_tpm2_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,\n+\t\t\t int argc, char *const argv[])\n+{\n+\tu32 index = simple_strtoul(argv[1], NULL, 0);\n+\tchar *key = argv[2];\n+\tconst ssize_t key_sz = strlen(key);\n+\tconst char *pw = (argc < 4) ? NULL : argv[3];\n+\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n+\tstruct udevice *dev;\n+\tint ret;\n+\n+\tret = get_tpm(&dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (strlen(key) != TPM2_DIGEST_LEN)\n+\t\treturn -EINVAL;\n+\n+\tif (argc < 3 || argc > 4)\n+\t\treturn CMD_RET_USAGE;\n+\n+\treturn report_return_code(tpm2_pcr_setauthvalue(dev, pw, pw_sz, index,\n+\t\t\t\t\t\t\tkey, key_sz));\n+}\ndiff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c\nindex 847b2691581..a131a81d1a4 100644\n--- a/cmd/tpm-v2.c\n+++ b/cmd/tpm-v2.c\n@@ -1,507 +1,51 @@\n // SPDX-License-Identifier: GPL-2.0+\n /*\n+ * TPM2 command frontend - command table, dispatcher, and help text\n+ *\n+ * The actual command implementations are provided by the backend:\n+ * - native_tpm2.c: U-Boot native TPM2 APIs (driver model)\n+ * - wolftpm.c: wolfTPM library APIs\n+ *\n * Copyright (c) 2018 Bootlin\n * Author: Miquel Raynal <miquel.raynal@bootlin.com>\n */\n \n #include <command.h>\n-#include <dm.h>\n-#include <log.h>\n-#include <mapmem.h>\n #include <tpm-common.h>\n-#include <tpm-v2.h>\n-#include \"tpm-user-utils.h\"\n-\n-static int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,\n-\t\t\t char *const argv[])\n-{\n-\tenum tpm2_startup_types mode;\n-\tstruct udevice *dev;\n-\tint ret;\n-\tbool bon = true;\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\t/* argv[2] is optional to perform a TPM2_CC_SHUTDOWN */\n-\tif (argc > 3 || (argc == 3 && strcasecmp(\"off\", argv[2])))\n-\t\treturn CMD_RET_USAGE;\n-\n-\tif (!strcasecmp(\"TPM2_SU_CLEAR\", argv[1])) {\n-\t\tmode = TPM2_SU_CLEAR;\n-\t} else if (!strcasecmp(\"TPM2_SU_STATE\", argv[1])) {\n-\t\tmode = TPM2_SU_STATE;\n-\t} else {\n-\t\tprintf(\"Couldn't recognize mode string: %s\\n\", argv[1]);\n-\t\treturn CMD_RET_FAILURE;\n-\t}\n-\n-\tif (argv[2])\n-\t\tbon = false;\n-\n-\treturn report_return_code(tpm2_startup(dev, bon, mode));\n-}\n-\n-static int do_tpm2_self_test(struct cmd_tbl *cmdtp, int flag, int argc,\n-\t\t\t char *const argv[])\n-{\n-\tenum tpm2_yes_no full_test;\n-\tstruct udevice *dev;\n-\tint ret;\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\tif (argc != 2)\n-\t\treturn CMD_RET_USAGE;\n-\n-\tif (!strcasecmp(\"full\", argv[1])) {\n-\t\tfull_test = TPMI_YES;\n-\t} else if (!strcasecmp(\"continue\", argv[1])) {\n-\t\tfull_test = TPMI_NO;\n-\t} else {\n-\t\tprintf(\"Couldn't recognize test mode: %s\\n\", argv[1]);\n-\t\treturn CMD_RET_FAILURE;\n-\t}\n-\n-\treturn report_return_code(tpm2_self_test(dev, full_test));\n-}\n-\n-static int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag, int argc,\n-\t\t\t char *const argv[])\n-{\n-\tu32 handle = 0;\n-\tconst char *pw = (argc < 3) ? NULL : argv[2];\n-\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n-\tstruct udevice *dev;\n-\tint ret;\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tif (argc < 2 || argc > 3)\n-\t\treturn CMD_RET_USAGE;\n-\n-\tif (pw_sz > TPM2_DIGEST_LEN)\n-\t\treturn -EINVAL;\n-\n-\tif (!strcasecmp(\"TPM2_RH_LOCKOUT\", argv[1]))\n-\t\thandle = TPM2_RH_LOCKOUT;\n-\telse if (!strcasecmp(\"TPM2_RH_PLATFORM\", argv[1]))\n-\t\thandle = TPM2_RH_PLATFORM;\n-\telse\n-\t\treturn CMD_RET_USAGE;\n-\n-\treturn report_return_code(tpm2_clear(dev, handle, pw, pw_sz));\n-}\n-\n-static int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag, int argc,\n-\t\t\t char *const argv[])\n-{\n-\tstruct udevice *dev;\n-\tstruct tpm_chip_priv *priv;\n-\tu32 index = simple_strtoul(argv[1], NULL, 0);\n-\tvoid *digest = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);\n-\tint algo = TPM2_ALG_SHA256;\n-\tint algo_len;\n-\tint ret;\n-\tu32 rc;\n-\n-\tif (argc < 3 || argc > 4)\n-\t\treturn CMD_RET_USAGE;\n-\tif (argc == 4) {\n-\t\talgo = tpm2_name_to_algorithm(argv[3]);\n-\t\tif (algo == TPM2_ALG_INVAL)\n-\t\t\treturn CMD_RET_FAILURE;\n-\t}\n-\talgo_len = tpm2_algorithm_to_len(algo);\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tpriv = dev_get_uclass_priv(dev);\n-\tif (!priv)\n-\t\treturn -EINVAL;\n-\n-\tif (index >= priv->pcr_count)\n-\t\treturn -EINVAL;\n-\n-\trc = tpm2_pcr_extend(dev, index, algo, digest, algo_len);\n-\tif (!rc) {\n-\t\tprintf(\"PCR #%u extended with %d byte %s digest\\n\", index,\n-\t\t algo_len, tpm2_algorithm_name(algo));\n-\t\tprint_byte_string(digest, algo_len);\n-\t}\n-\n-\tunmap_sysmem(digest);\n-\n-\treturn report_return_code(rc);\n-}\n-\n-static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,\n-\t\t\t char *const argv[])\n-{\n-\tenum tpm2_algorithms algo = TPM2_ALG_SHA256;\n-\tstruct udevice *dev;\n-\tstruct tpm_chip_priv *priv;\n-\tu32 index, rc;\n-\tint algo_len;\n-\tunsigned int updates;\n-\tvoid *data;\n-\tint ret;\n-\n-\tif (argc < 3 || argc > 4)\n-\t\treturn CMD_RET_USAGE;\n-\tif (argc == 4) {\n-\t\talgo = tpm2_name_to_algorithm(argv[3]);\n-\t\tif (algo == TPM2_ALG_INVAL)\n-\t\t\treturn CMD_RET_FAILURE;\n-\t}\n-\talgo_len = tpm2_algorithm_to_len(algo);\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tpriv = dev_get_uclass_priv(dev);\n-\tif (!priv)\n-\t\treturn -EINVAL;\n-\n-\tindex = simple_strtoul(argv[1], NULL, 0);\n-\tif (index >= priv->pcr_count)\n-\t\treturn -EINVAL;\n-\n-\tdata = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);\n-\n-\trc = tpm2_pcr_read(dev, index, priv->pcr_select_min, algo,\n-\t\t\t data, algo_len, &updates);\n-\tif (!rc) {\n-\t\tprintf(\"PCR #%u %s %d byte content (%u known updates):\\n\", index,\n-\t\t tpm2_algorithm_name(algo), algo_len, updates);\n-\t\tprint_byte_string(data, algo_len);\n-\t}\n-\n-\tunmap_sysmem(data);\n-\n-\treturn report_return_code(rc);\n-}\n-\n-static int do_tpm_get_capability(struct cmd_tbl *cmdtp, int flag, int argc,\n-\t\t\t\t char *const argv[])\n-{\n-\tu32 capability, property, rc;\n-\tu8 *data;\n-\tsize_t count;\n-\tint i, j;\n-\tstruct udevice *dev;\n-\tint ret;\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tif (argc != 5)\n-\t\treturn CMD_RET_USAGE;\n-\n-\tcapability = simple_strtoul(argv[1], NULL, 0);\n-\tproperty = simple_strtoul(argv[2], NULL, 0);\n-\tdata = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);\n-\tcount = simple_strtoul(argv[4], NULL, 0);\n-\n-\trc = tpm2_get_capability(dev, capability, property, data, count);\n-\tif (rc)\n-\t\tgoto unmap_data;\n-\n-\tprintf(\"Capabilities read from TPM:\\n\");\n-\tfor (i = 0; i < count; i++) {\n-\t\tprintf(\"Property 0x\");\n-\t\tfor (j = 0; j < 4; j++)\n-\t\t\tprintf(\"%02x\", data[(i * 8) + j + sizeof(u32)]);\n-\t\tprintf(\": 0x\");\n-\t\tfor (j = 4; j < 8; j++)\n-\t\t\tprintf(\"%02x\", data[(i * 8) + j + sizeof(u32)]);\n-\t\tprintf(\"\\n\");\n-\t}\n-\n-unmap_data:\n-\tunmap_sysmem(data);\n-\n-\treturn report_return_code(rc);\n-}\n-\n-static u32 select_mask(u32 mask, enum tpm2_algorithms algo, bool select)\n-{\n-\tsize_t i;\n-\n-\tfor (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {\n-\t\tif (hash_algo_list[i].hash_alg != algo)\n-\t\t\tcontinue;\n-\n-\t\tif (select)\n-\t\t\tmask |= hash_algo_list[i].hash_mask;\n-\t\telse\n-\t\t\tmask &= ~hash_algo_list[i].hash_mask;\n-\n-\t\tbreak;\n-\t}\n-\n-\treturn mask;\n-}\n-\n-static bool\n-is_algo_in_pcrs(enum tpm2_algorithms algo, struct tpml_pcr_selection *pcrs)\n-{\n-\tsize_t i;\n-\n-\tfor (i = 0; i < pcrs->count; i++) {\n-\t\tif (algo == pcrs->selection[i].hash)\n-\t\t\treturn true;\n-\t}\n-\n-\treturn false;\n-}\n-\n-static int do_tpm2_pcrallocate(struct cmd_tbl *cmdtp, int flag, int argc,\n-\t\t\t char *const argv[])\n-{\n-\tstruct udevice *dev;\n-\tint ret;\n-\tenum tpm2_algorithms algo;\n-\tconst char *pw = (argc < 4) ? NULL : argv[3];\n-\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n-\tstatic struct tpml_pcr_selection pcr = { 0 };\n-\tu32 pcr_len = 0;\n-\tbool bon = false;\n-\tstatic u32 mask;\n-\tint i;\n-\n-\t/* argv[1]: algorithm (bank), argv[2]: on/off */\n-\tif (argc < 3 || argc > 4)\n-\t\treturn CMD_RET_USAGE;\n-\n-\tif (!strcasecmp(\"on\", argv[2]))\n-\t\tbon = true;\n-\telse if (strcasecmp(\"off\", argv[2]))\n-\t\treturn CMD_RET_USAGE;\n-\n-\talgo = tpm2_name_to_algorithm(argv[1]);\n-\tif (algo == TPM2_ALG_INVAL)\n-\t\treturn CMD_RET_USAGE;\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tif (!pcr.count) {\n-\t\t/*\n-\t\t * Get current active algorithms (banks), PCRs and mask via the\n-\t\t * first call\n-\t\t */\n-\t\tret = tpm2_get_pcr_info(dev, &pcr);\n-\t\tif (ret)\n-\t\t\treturn ret;\n-\n-\t\tfor (i = 0; i < pcr.count; i++) {\n-\t\t\tstruct tpms_pcr_selection *sel = &pcr.selection[i];\n-\t\t\tconst char *name;\n-\n-\t\t\tif (!tpm2_is_active_bank(sel))\n-\t\t\t\tcontinue;\n-\n-\t\t\tmask = select_mask(mask, sel->hash, true);\n-\t\t\tname = tpm2_algorithm_name(sel->hash);\n-\t\t\tif (name)\n-\t\t\t\tprintf(\"Active bank[%d]: %s\\n\", i, name);\n-\t\t}\n-\t}\n-\n-\tif (!is_algo_in_pcrs(algo, &pcr)) {\n-\t\tprintf(\"%s is not supported by the tpm device\\n\", argv[1]);\n-\t\treturn CMD_RET_USAGE;\n-\t}\n-\n-\tmask = select_mask(mask, algo, bon);\n-\tret = tpm2_pcr_config_algo(dev, mask, &pcr, &pcr_len);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\treturn report_return_code(tpm2_send_pcr_allocate(dev, pw, pw_sz, &pcr,\n-\t\t\t\t\t\t\t pcr_len));\n-}\n-\n-static int do_tpm_dam_reset(struct cmd_tbl *cmdtp, int flag, int argc,\n-\t\t\t char *const argv[])\n-{\n-\tconst char *pw = (argc < 2) ? NULL : argv[1];\n-\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n-\tstruct udevice *dev;\n-\tint ret;\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tif (argc > 2)\n-\t\treturn CMD_RET_USAGE;\n-\n-\tif (pw_sz > TPM2_DIGEST_LEN)\n-\t\treturn -EINVAL;\n-\n-\treturn report_return_code(tpm2_dam_reset(dev, pw, pw_sz));\n-}\n-\n-static int do_tpm_dam_parameters(struct cmd_tbl *cmdtp, int flag, int argc,\n-\t\t\t\t char *const argv[])\n-{\n-\tconst char *pw = (argc < 5) ? NULL : argv[4];\n-\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n-\t/*\n-\t * No Dictionary Attack Mitigation (DAM) means:\n-\t * maxtries = 0xFFFFFFFF, recovery_time = 1, lockout_recovery = 0\n-\t */\n-\tunsigned long int max_tries;\n-\tunsigned long int recovery_time;\n-\tunsigned long int lockout_recovery;\n-\tstruct udevice *dev;\n-\tint ret;\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tif (argc < 4 || argc > 5)\n-\t\treturn CMD_RET_USAGE;\n-\n-\tif (pw_sz > TPM2_DIGEST_LEN)\n-\t\treturn -EINVAL;\n-\n-\tif (strict_strtoul(argv[1], 0, &max_tries))\n-\t\treturn CMD_RET_USAGE;\n-\n-\tif (strict_strtoul(argv[2], 0, &recovery_time))\n-\t\treturn CMD_RET_USAGE;\n-\n-\tif (strict_strtoul(argv[3], 0, &lockout_recovery))\n-\t\treturn CMD_RET_USAGE;\n-\n-\tlog(LOGC_NONE, LOGL_INFO, \"Changing dictionary attack parameters:\\n\");\n-\tlog(LOGC_NONE, LOGL_INFO, \"- maxTries: %lu\", max_tries);\n-\tlog(LOGC_NONE, LOGL_INFO, \"- recoveryTime: %lu\\n\", recovery_time);\n-\tlog(LOGC_NONE, LOGL_INFO, \"- lockoutRecovery: %lu\\n\", lockout_recovery);\n-\n-\treturn report_return_code(tpm2_dam_parameters(dev, pw, pw_sz, max_tries,\n-\t\t\t\t\t\t recovery_time,\n-\t\t\t\t\t\t lockout_recovery));\n-}\n-\n-static int do_tpm_change_auth(struct cmd_tbl *cmdtp, int flag, int argc,\n-\t\t\t char *const argv[])\n-{\n-\tu32 handle;\n-\tconst char *newpw = argv[2];\n-\tconst char *oldpw = (argc == 3) ? NULL : argv[3];\n-\tconst ssize_t newpw_sz = strlen(newpw);\n-\tconst ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;\n-\tstruct udevice *dev;\n-\tint ret;\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tif (argc < 3 || argc > 4)\n-\t\treturn CMD_RET_USAGE;\n-\n-\tif (newpw_sz > TPM2_DIGEST_LEN || oldpw_sz > TPM2_DIGEST_LEN)\n-\t\treturn -EINVAL;\n-\n-\tif (!strcasecmp(\"TPM2_RH_LOCKOUT\", argv[1]))\n-\t\thandle = TPM2_RH_LOCKOUT;\n-\telse if (!strcasecmp(\"TPM2_RH_ENDORSEMENT\", argv[1]))\n-\t\thandle = TPM2_RH_ENDORSEMENT;\n-\telse if (!strcasecmp(\"TPM2_RH_OWNER\", argv[1]))\n-\t\thandle = TPM2_RH_OWNER;\n-\telse if (!strcasecmp(\"TPM2_RH_PLATFORM\", argv[1]))\n-\t\thandle = TPM2_RH_PLATFORM;\n-\telse\n-\t\treturn CMD_RET_USAGE;\n-\n-\treturn report_return_code(tpm2_change_auth(dev, handle, newpw, newpw_sz,\n-\t\t\t\t\t\t oldpw, oldpw_sz));\n-}\n-\n-static int do_tpm_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag, int argc,\n-\t\t\t\t char *const argv[])\n-{\n-\tu32 index = simple_strtoul(argv[1], NULL, 0);\n-\tchar *key = argv[2];\n-\tconst char *pw = (argc < 4) ? NULL : argv[3];\n-\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n-\tstruct udevice *dev;\n-\tint ret;\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tif (strlen(key) != TPM2_DIGEST_LEN)\n-\t\treturn -EINVAL;\n-\n-\tif (argc < 3 || argc > 4)\n-\t\treturn CMD_RET_USAGE;\n-\n-\treturn report_return_code(tpm2_pcr_setauthpolicy(dev, pw, pw_sz, index,\n-\t\t\t\t\t\t\t key));\n-}\n-\n-static int do_tpm_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,\n-\t\t\t\t int argc, char *const argv[])\n-{\n-\tu32 index = simple_strtoul(argv[1], NULL, 0);\n-\tchar *key = argv[2];\n-\tconst ssize_t key_sz = strlen(key);\n-\tconst char *pw = (argc < 4) ? NULL : argv[3];\n-\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n-\tstruct udevice *dev;\n-\tint ret;\n-\n-\tret = get_tpm(&dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tif (strlen(key) != TPM2_DIGEST_LEN)\n-\t\treturn -EINVAL;\n-\n-\tif (argc < 3 || argc > 4)\n-\t\treturn CMD_RET_USAGE;\n-\n-\treturn report_return_code(tpm2_pcr_setauthvalue(dev, pw, pw_sz, index,\n-\t\t\t\t\t\t\tkey, key_sz));\n-}\n+#include \"tpm2-backend.h\"\n \n static struct cmd_tbl tpm2_commands[] = {\n-\tU_BOOT_CMD_MKENT(device, 0, 1, do_tpm_device, \"\", \"\"),\n-\tU_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, \"\", \"\"),\n-\tU_BOOT_CMD_MKENT(state, 0, 1, do_tpm_report_state, \"\", \"\"),\n-\tU_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(device, 0, 1, do_tpm2_device, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(info, 0, 1, do_tpm2_info, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(state, 0, 1, do_tpm2_state, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(init, 0, 1, do_tpm2_init, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(autostart, 0, 1, do_tpm2_autostart, \"\", \"\"),\n \tU_BOOT_CMD_MKENT(startup, 0, 1, do_tpm2_startup, \"\", \"\"),\n-\tU_BOOT_CMD_MKENT(self_test, 0, 1, do_tpm2_self_test, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(self_test, 0, 1, do_tpm2_selftest, \"\", \"\"),\n \tU_BOOT_CMD_MKENT(clear, 0, 1, do_tpm2_clear, \"\", \"\"),\n \tU_BOOT_CMD_MKENT(pcr_extend, 0, 1, do_tpm2_pcr_extend, \"\", \"\"),\n-\tU_BOOT_CMD_MKENT(pcr_read, 0, 1, do_tpm_pcr_read, \"\", \"\"),\n-\tU_BOOT_CMD_MKENT(get_capability, 0, 1, do_tpm_get_capability, \"\", \"\"),\n-\tU_BOOT_CMD_MKENT(dam_reset, 0, 1, do_tpm_dam_reset, \"\", \"\"),\n-\tU_BOOT_CMD_MKENT(dam_parameters, 0, 1, do_tpm_dam_parameters, \"\", \"\"),\n-\tU_BOOT_CMD_MKENT(change_auth, 0, 1, do_tpm_change_auth, \"\", \"\"),\n-\tU_BOOT_CMD_MKENT(autostart, 0, 1, do_tpm_autostart, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(pcr_read, 0, 1, do_tpm2_pcr_read, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(get_capability, 0, 1, do_tpm2_get_capability, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(dam_reset, 0, 1, do_tpm2_dam_reset, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(dam_parameters, 0, 1, do_tpm2_dam_parameters, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(change_auth, 0, 1, do_tpm2_change_auth, \"\", \"\"),\n \tU_BOOT_CMD_MKENT(pcr_setauthpolicy, 0, 1,\n-\t\t\t do_tpm_pcr_setauthpolicy, \"\", \"\"),\n+\t\t\t do_tpm2_pcr_setauthpolicy, \"\", \"\"),\n \tU_BOOT_CMD_MKENT(pcr_setauthvalue, 0, 1,\n-\t\t\t do_tpm_pcr_setauthvalue, \"\", \"\"),\n-\tU_BOOT_CMD_MKENT(pcr_allocate, 0, 1, do_tpm2_pcrallocate, \"\", \"\"),\n+\t\t\t do_tpm2_pcr_setauthvalue, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(pcr_allocate, 0, 1, do_tpm2_pcr_allocate, \"\", \"\"),\n+#ifdef CONFIG_TPM_WOLF\n+\tU_BOOT_CMD_MKENT(caps, 0, 1, do_tpm2_caps, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(pcr_print, 0, 1, do_tpm2_pcr_print, \"\", \"\"),\n+#ifdef WOLFTPM_FIRMWARE_UPGRADE\n+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)\n+\tU_BOOT_CMD_MKENT(firmware_update, 0, 1,\n+\t\t\t do_tpm2_firmware_update, \"\", \"\"),\n+\tU_BOOT_CMD_MKENT(firmware_cancel, 0, 1,\n+\t\t\t do_tpm2_firmware_cancel, \"\", \"\"),\n+#endif /* WOLFTPM_SLB9672 || WOLFTPM_SLB9673 */\n+#endif /* WOLFTPM_FIRMWARE_UPGRADE */\n+#endif /* CONFIG_TPM_WOLF */\n };\n \n struct cmd_tbl *get_tpm2_commands(unsigned int *size)\n@@ -511,7 +55,22 @@ struct cmd_tbl *get_tpm2_commands(unsigned int *size)\n \treturn tpm2_commands;\n }\n \n-U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, \"Issue a TPMv2.x command\",\n+static int do_tpm2(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[])\n+{\n+\tstruct cmd_tbl *cmd;\n+\n+\tif (argc < 2)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tcmd = find_cmd_tbl(argv[1], tpm2_commands, ARRAY_SIZE(tpm2_commands));\n+\tif (!cmd)\n+\t\treturn CMD_RET_USAGE;\n+\n+\treturn cmd->cmd(cmdtp, flag, argc - 1, argv + 1);\n+}\n+\n+U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm2, \"Issue a TPMv2.x command\",\n \"<command> [<arguments>]\\n\"\n \"\\n\"\n \"device [num device]\\n\"\n@@ -521,7 +80,7 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, \"Issue a TPMv2.x command\",\n \"state\\n\"\n \" Show internal state from the TPM (if available)\\n\"\n \"autostart\\n\"\n-\" Initalize the tpm, perform a Startup(clear) and run a full selftest\\n\"\n+\" Initialize the tpm, perform a Startup(clear) and run a full selftest\\n\"\n \" sequence\\n\"\n \"init\\n\"\n \" Initialize the software stack. Always the first command to issue.\\n\"\n@@ -573,6 +132,10 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, \"Issue a TPMv2.x command\",\n \" <password>: optional password of the LOCKOUT hierarchy\\n\"\n \"change_auth <hierarchy> <new_pw> [<old_pw>]\\n\"\n \" <hierarchy>: the hierarchy\\n\"\n+\" * TPM2_RH_LOCKOUT\\n\"\n+\" * TPM2_RH_ENDORSEMENT\\n\"\n+\" * TPM2_RH_OWNER\\n\"\n+\" * TPM2_RH_PLATFORM\\n\"\n \" <new_pw>: new password for <hierarchy>\\n\"\n \" <old_pw>: optional previous password of <hierarchy>\\n\"\n \"pcr_setauthpolicy|pcr_setauthvalue <pcr> <key> [<password>]\\n\"\n@@ -596,4 +159,18 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, \"Issue a TPMv2.x command\",\n \" * off - Clear all available PCRs associated with the specified\\n\"\n \" algorithm (bank)\\n\"\n \" <password>: optional password\\n\"\n+#ifdef CONFIG_TPM_WOLF\n+\"caps\\n\"\n+\" Show TPM capabilities and info\\n\"\n+\"pcr_print\\n\"\n+\" Prints the current PCR state\\n\"\n+#ifdef WOLFTPM_FIRMWARE_UPGRADE\n+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)\n+\"firmware_update <manifest_addr> <manifest_sz> <firmware_addr> <firmware_sz>\\n\"\n+\" Update TPM firmware\\n\"\n+\"firmware_cancel\\n\"\n+\" Cancel TPM firmware update\\n\"\n+#endif /* WOLFTPM_SLB9672 || WOLFTPM_SLB9673 */\n+#endif /* WOLFTPM_FIRMWARE_UPGRADE */\n+#endif /* CONFIG_TPM_WOLF */\n );\ndiff --git a/cmd/tpm2-backend.h b/cmd/tpm2-backend.h\nnew file mode 100644\nindex 00000000000..39e9a3a6b7b\n--- /dev/null\n+++ b/cmd/tpm2-backend.h\n@@ -0,0 +1,66 @@\n+/* SPDX-License-Identifier: GPL-2.0+ */\n+/*\n+ * TPM2 backend function declarations\n+ *\n+ * Each backend (native_tpm2.c or wolftpm.c) implements these functions.\n+ * The frontend (tpm-v2.c) references them in the command table.\n+ */\n+\n+#ifndef __TPM2_BACKEND_H\n+#define __TPM2_BACKEND_H\n+\n+#include <command.h>\n+\n+/* Common TPM2 command handlers - both backends must implement these */\n+int do_tpm2_device(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_info(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_state(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_init(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_autostart(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_selftest(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_get_capability(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\t char *const argv[]);\n+int do_tpm2_dam_reset(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_dam_parameters(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\t char *const argv[]);\n+int do_tpm2_change_auth(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\tchar *const argv[]);\n+int do_tpm2_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\t char *const argv[]);\n+int do_tpm2_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\t char *const argv[]);\n+int do_tpm2_pcr_allocate(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\t char *const argv[]);\n+\n+/* wolfTPM-only command handlers */\n+#ifdef CONFIG_TPM_WOLF\n+int do_tpm2_caps(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+int do_tpm2_pcr_print(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t char *const argv[]);\n+#ifdef WOLFTPM_FIRMWARE_UPGRADE\n+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)\n+int do_tpm2_firmware_update(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\t char *const argv[]);\n+int do_tpm2_firmware_cancel(struct cmd_tbl *cmdtp, int flag, int argc,\n+\t\t\t char *const argv[]);\n+#endif /* WOLFTPM_SLB9672 || WOLFTPM_SLB9673 */\n+#endif /* WOLFTPM_FIRMWARE_UPGRADE */\n+#endif /* CONFIG_TPM_WOLF */\n+\n+#endif /* __TPM2_BACKEND_H */\ndiff --git a/cmd/wolftpm.c b/cmd/wolftpm.c\nnew file mode 100644\nindex 00000000000..06ea8d47c8a\n--- /dev/null\n+++ b/cmd/wolftpm.c\n@@ -0,0 +1,1170 @@\n+// SPDX-License-Identifier: GPL-2.0+\n+/*\n+ * TPM2 command implementation using wolfTPM library\n+ *\n+ * Copyright (C) 2025 wolfSSL Inc.\n+ * Author: Aidan Garske <aidan@wolfssl.com>\n+ */\n+\n+#define LOG_CATEGORY UCLASS_BOOTSTD\n+\n+#include <wolftpm/tpm2.h>\n+#include <wolftpm/tpm2_wrap.h>\n+#include <wolftpm/tpm2_packet.h>\n+#include <wolftpm.h>\n+\n+#include <stdio.h>\n+#include <hash.h>\n+#ifndef WOLFTPM2_NO_WRAPPER\n+\n+#include <hal/tpm_io.h>\n+#include <examples/wrap/wrap_test.h>\n+\n+/* U-boot specific includes */\n+#include <command.h>\n+#include <tpm-common.h>\n+#include <vsprintf.h>\n+#include <mapmem.h>\n+#include <errno.h>\n+#include <log.h>\n+#include <string.h>\n+\n+/* Firmware update info structure for Infineon TPM */\n+#ifdef WOLFTPM_FIRMWARE_UPGRADE\n+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)\n+struct fw_info {\n+\tbyte *manifest_buf;\n+\tbyte *firmware_buf;\n+\tsize_t manifest_bufSz;\n+\tsize_t firmware_bufSz;\n+};\n+#endif\n+#endif\n+\n+/******************************************************************************/\n+/* --- BEGIN Common Commands -- */\n+/******************************************************************************/\n+\n+int do_tpm2_device(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tWOLFTPM2_DEV dev;\n+\tWOLFTPM2_CAPS caps;\n+\tint rc;\n+\n+\t/* Expected 1 arg only in native SPI mode (no device switching) */\n+\tif (argc != 1)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Try to initialize and get device info */\n+\trc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);\n+\tif (!rc) {\n+\t\trc = wolfTPM2_GetCapabilities(&dev, &caps);\n+\t\tif (!rc) {\n+\t\t\tprintf(\"TPM Device 0: %s (%s) FW=%d.%d\\n\",\n+\t\t\t\t caps.mfgStr, caps.vendorStr,\n+\t\t\t\t caps.fwVerMajor, caps.fwVerMinor);\n+\t\t}\n+\t\twolfTPM2_Cleanup(&dev);\n+\t}\n+\n+\tif (rc != 0) {\n+\t\tprintf(\"No TPM device found (rc=%d: %s)\\n\", rc, TPM2_GetRCString(rc));\n+\t\treturn CMD_RET_FAILURE;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int do_tpm2_info(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tWOLFTPM2_DEV dev;\n+\tWOLFTPM2_CAPS caps;\n+\tint rc;\n+\n+\tif (argc != 1)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device */\n+\trc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);\n+\tif (!rc) {\n+\t\trc = wolfTPM2_GetCapabilities(&dev, &caps);\n+\t\tif (!rc) {\n+\t\t\tprintf(\"TPM 2.0: %s (%s)\\n\", caps.mfgStr, caps.vendorStr);\n+\t\t\tprintf(\" Firmware: %d.%d (0x%08X)\\n\",\n+\t\t\t\t caps.fwVerMajor, caps.fwVerMinor, caps.fwVerVendor);\n+\t\t\tprintf(\" Type: 0x%08X\\n\", caps.tpmType);\n+\t\t}\n+\t\twolfTPM2_Cleanup(&dev);\n+\t}\n+\n+\tif (rc != 0) {\n+\t\tprintf(\"Couldn't get TPM info (rc=%d: %s)\\n\", rc, TPM2_GetRCString(rc));\n+\t\treturn CMD_RET_FAILURE;\n+\t}\n+\n+\tlog_debug(\"tpm2 info: rc = %d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\treturn 0;\n+}\n+\n+int do_tpm2_state(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tWOLFTPM2_DEV dev;\n+\tWOLFTPM2_CAPS caps;\n+\tint rc;\n+\n+\tif (argc != 1)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device */\n+\trc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);\n+\tif (!rc) {\n+\t\trc = wolfTPM2_GetCapabilities(&dev, &caps);\n+\t\tif (!rc) {\n+\t\t\tprintf(\"TPM State:\\n\");\n+\t\t\tprintf(\" Manufacturer: %s\\n\", caps.mfgStr);\n+\t\t\tprintf(\" Vendor: %s\\n\", caps.vendorStr);\n+\t\t\tprintf(\" Firmware: %d.%d\\n\", caps.fwVerMajor, caps.fwVerMinor);\n+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)\n+\t\t\tprintf(\" Mode: Infineon SLB967x (Native SPI)\\n\");\n+\t\t\tprintf(\" OpMode: %d\\n\", caps.opMode);\n+#else\n+\t\t\tprintf(\" Mode: Native wolfTPM SPI\\n\");\n+#endif\n+\t\t}\n+\t\twolfTPM2_Cleanup(&dev);\n+\t}\n+\n+\tif (rc != 0) {\n+\t\tprintf(\"Couldn't get TPM state (rc=%d: %s)\\n\", rc, TPM2_GetRCString(rc));\n+\t\treturn CMD_RET_FAILURE;\n+\t}\n+\n+\tlog_debug(\"tpm2 state: rc = %d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\treturn 0;\n+}\n+\n+int do_tpm2_init(struct cmd_tbl *cmdtp, int flag, int argc,\n+\tchar *const argv[])\n+{\n+\tWOLFTPM2_DEV dev;\n+\n+\tif (argc != 1)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device */\n+\treturn TPM2_Init_Device(&dev, NULL);\n+}\n+\n+int do_tpm2_autostart(struct cmd_tbl *cmdtp, int flag, int argc,\n+\tchar *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\n+\tif (argc != 1)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc != TPM_RC_SUCCESS)\n+\t\treturn rc;\n+\n+\t/* Perform a startup clear - doStartup=1: Just starts up the TPM */\n+\trc = wolfTPM2_Reset(&dev, 0, 1);\n+\t/* TPM_RC_INITIALIZE means already started - treat as success */\n+\tif (rc == TPM_RC_INITIALIZE)\n+\t\trc = TPM_RC_SUCCESS;\n+\tif (rc != TPM_RC_SUCCESS) {\n+\t\tlog_debug(\"wolfTPM2_Reset failed 0x%x: %s\\n\", rc,\n+\t\t\tTPM2_GetRCString(rc));\n+\t\treturn rc;\n+\t}\n+\n+\t/* Perform a full self test */\n+\trc = wolfTPM2_SelfTest(&dev);\n+\tif (rc != TPM_RC_SUCCESS)\n+\t\tlog_debug(\"wolfTPM2_SelfTest failed 0x%x: %s\\n\", rc,\n+\t\t\tTPM2_GetRCString(rc));\n+\n+\tlog_debug(\"tpm2 autostart: rc = %d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+/******************************************************************************/\n+/* --- END Common Commands -- */\n+/******************************************************************************/\n+\n+/******************************************************************************/\n+/* --- START TPM 2.0 Commands -- */\n+/******************************************************************************/\n+\n+int do_tpm2_get_capability(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tGetCapability_In in;\n+\tGetCapability_Out out;\n+\tu32 capability, property, rc;\n+\tu8 *data;\n+\tsize_t count;\n+\tint i, j;\n+\n+\tif (argc != 5)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tcapability = simple_strtoul(argv[1], NULL, 0);\n+\tproperty = simple_strtoul(argv[2], NULL, 0);\n+\tdata = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);\n+\tcount = simple_strtoul(argv[4], NULL, 0);\n+\n+\tmemset(&in, 0, sizeof(in));\n+\tmemset(&out, 0, sizeof(out));\n+\tin.capability = capability;\n+\tin.property = property;\n+\tin.propertyCount = count;\n+\trc = TPM2_GetCapability(&in, &out);\n+\tif (!rc) {\n+\t\tmemcpy(data, &out.capabilityData.data, sizeof(out.capabilityData.data));\n+\n+\t\tprintf(\"Capabilities read from TPM:\\n\");\n+\t\tfor (i = 0; i < count; i++) {\n+\t\t\tprintf(\"Property 0x\");\n+\t\t\tfor (j = 0; j < 4; j++)\n+\t\t\t\tprintf(\"%02x\", data[(i * 8) + j + sizeof(u32)]);\n+\t\t\tprintf(\": 0x\");\n+\t\t\tfor (j = 4; j < 8; j++)\n+\t\t\t\tprintf(\"%02x\", data[(i * 8) + j + sizeof(u32)]);\n+\t\t\tprintf(\"\\n\");\n+\t\t}\n+\t}\n+\n+\tunmap_sysmem(data);\n+\n+\tlog_debug(\"tpm2 get_capability: rc = %d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+int do_tpm2_caps(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tWOLFTPM2_CAPS caps;\n+\n+\tif (argc != 1)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc != TPM_RC_SUCCESS)\n+\t\treturn rc;\n+\n+\trc = wolfTPM2_GetCapabilities(&dev, &caps);\n+\tif (rc != TPM_RC_SUCCESS)\n+\t\tgoto cleanup;\n+\n+\tlog_debug(\"Mfg %s (%d), Vendor %s, Fw %u.%u (0x%x), \"\n+\t\t\"FIPS 140-2 %d, CC-EAL4 %d\\n\",\n+\t\tcaps.mfgStr, caps.mfg, caps.vendorStr, caps.fwVerMajor,\n+\t\tcaps.fwVerMinor, caps.fwVerVendor, caps.fips140_2, caps.cc_eal4);\n+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)\n+\tlog_debug(\"Operational mode: %s (0x%x)\\n\",\n+\t\tTPM2_IFX_GetOpModeStr(caps.opMode), caps.opMode);\n+\tlog_debug(\"KeyGroupId 0x%x, FwCounter %d (%d same)\\n\",\n+\t\tcaps.keyGroupId, caps.fwCounter, caps.fwCounterSame);\n+#endif\n+\n+\t/* List the active persistent handles */\n+\trc = wolfTPM2_GetHandles(PERSISTENT_FIRST, NULL);\n+\tif (rc >= TPM_RC_SUCCESS)\n+\t\tlog_debug(\"Found %d persistent handles\\n\", rc);\n+\n+\t/* Print the available PCR's */\n+\trc = TPM2_PCRs_Print();\n+\n+cleanup:\n+\t/* Only doShutdown=1: Just shut down the TPM */\n+\twolfTPM2_Reset(&dev, 1, 0);\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 caps: rc = %d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+#ifdef WOLFTPM_FIRMWARE_UPGRADE\n+#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)\n+int do_tpm2_firmware_update(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tWOLFTPM2_CAPS caps;\n+\tstruct fw_info fwinfo;\n+\tulong manifest_addr, firmware_addr;\n+\tsize_t manifest_sz, firmware_sz;\n+\tuint8_t manifest_hash[TPM_SHA384_DIGEST_SIZE];\n+\tint recovery = 0;\n+\n+\tmemset(&fwinfo, 0, sizeof(fwinfo));\n+\n+\t/* Need 5 args: command + 4 arguments */\n+\tif (argc != 5) {\n+\t\tlog_debug(\"Error: Expected 5 arguments but got %d\\n\", argc);\n+\t\treturn CMD_RET_USAGE;\n+\t}\n+\tprintf(\"TPM2 Firmware Update\\n\");\n+\n+\t/* Convert all arguments from strings to numbers */\n+\tmanifest_addr = simple_strtoul(argv[1], NULL, 0);\n+\tmanifest_sz = simple_strtoul(argv[2], NULL, 0);\n+\tfirmware_addr = simple_strtoul(argv[3], NULL, 0);\n+\tfirmware_sz = simple_strtoul(argv[4], NULL, 0);\n+\n+\t/* Map the memory addresses */\n+\tfwinfo.manifest_buf = map_sysmem(manifest_addr, manifest_sz);\n+\tfwinfo.firmware_buf = map_sysmem(firmware_addr, firmware_sz);\n+\tfwinfo.manifest_bufSz = manifest_sz;\n+\tfwinfo.firmware_bufSz = firmware_sz;\n+\n+\tif (fwinfo.manifest_buf == NULL || fwinfo.firmware_buf == NULL) {\n+\t\tlog_debug(\"Error: Invalid memory addresses\\n\");\n+\t\treturn CMD_RET_FAILURE;\n+\t}\n+\n+\tprintf(\"Infineon Firmware Update Tool\\n\");\n+\tprintf(\"\\tManifest Address: 0x%lx (size: %zu)\\n\",\n+\t\tmanifest_addr, manifest_sz);\n+\tprintf(\"\\tFirmware Address: 0x%lx (size: %zu)\\n\",\n+\t\tfirmware_addr, firmware_sz);\n+\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc != TPM_RC_SUCCESS)\n+\t\tgoto fw_cleanup;\n+\n+\trc = wolfTPM2_GetCapabilities(&dev, &caps);\n+\tif (rc != TPM_RC_SUCCESS)\n+\t\tgoto fw_cleanup;\n+\n+\tTPM2_IFX_PrintInfo(&caps);\n+\tif (caps.keyGroupId == 0)\n+\t\tlog_debug(\"Error getting key group id from TPM!\\n\");\n+\tif (caps.opMode == 0x02 || (caps.opMode & 0x80))\n+\t\trecovery = 1;\n+\n+\tif (recovery) {\n+\t\tprintf(\"Firmware Update (recovery mode):\\n\");\n+\t\trc = wolfTPM2_FirmwareUpgradeRecover(&dev,\n+\t\t\tfwinfo.manifest_buf, (uint32_t)fwinfo.manifest_bufSz,\n+\t\t\tTPM2_IFX_FwData_Cb, &fwinfo);\n+\t} else {\n+\t\t/* Normal mode - hash with wc_Sha384Hash */\n+\t\tprintf(\"Firmware Update (normal mode):\\n\");\n+\t\trc = wc_Sha384Hash(fwinfo.manifest_buf,\n+\t\t\t(uint32_t)fwinfo.manifest_bufSz, manifest_hash);\n+\t\tif (rc != TPM_RC_SUCCESS)\n+\t\t\tgoto fw_cleanup;\n+\t\trc = wolfTPM2_FirmwareUpgradeHash(&dev, TPM_ALG_SHA384,\n+\t\t\tmanifest_hash, (uint32_t)sizeof(manifest_hash),\n+\t\t\tfwinfo.manifest_buf, (uint32_t)fwinfo.manifest_bufSz,\n+\t\t\tTPM2_IFX_FwData_Cb, &fwinfo);\n+\t}\n+\n+\tif (!rc)\n+\t\tTPM2_IFX_PrintInfo(&caps);\n+\n+fw_cleanup:\n+\tif (fwinfo.manifest_buf)\n+\t\tunmap_sysmem(fwinfo.manifest_buf);\n+\tif (fwinfo.firmware_buf)\n+\t\tunmap_sysmem(fwinfo.firmware_buf);\n+\n+\tif (rc != TPM_RC_SUCCESS)\n+\t\tlog_debug(\"Infineon firmware update failed 0x%x: %s\\n\",\n+\t\t\trc, TPM2_GetRCString(rc));\n+\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 firmware_update: rc=%d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+int do_tpm2_firmware_cancel(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tuint8_t cmd[TPM2_HEADER_SIZE + 2];\n+\tuint16_t val16;\n+\n+\tif (argc != 1)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc == TPM_RC_SUCCESS) {\n+\t\t/* Setup command size in header */\n+\t\tval16 = TPM2_HEADER_SIZE + 2;\n+\t\tmemcpy(cmd, &val16, sizeof(val16));\n+\t\tval16 = 0;\n+\t\tmemcpy(&cmd[TPM2_HEADER_SIZE], &val16, sizeof(val16));\n+\n+\t\trc = TPM2_IFX_FieldUpgradeCommand(TPM_CC_FieldUpgradeAbandonVendor,\n+\t\t\tcmd, sizeof(cmd));\n+\t\tif (rc != TPM_RC_SUCCESS) {\n+\t\t\tlog_debug(\"Firmware abandon failed 0x%x: %s\\n\",\n+\t\t\t\trc, TPM2_GetRCString(rc));\n+\t\t}\n+\t}\n+\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 firmware_cancel: rc=%d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+#endif /* WOLFTPM_SLB9672 || WOLFTPM_SLB9673 */\n+#endif /* WOLFTPM_FIRMWARE_UPGRADE */\n+\n+int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tStartup_In startupIn;\n+\tShutdown_In shutdownIn;\n+\tint doStartup = YES;\n+\n+\t/* startup TPM2_SU_CLEAR|TPM2_SU_STATE [off] */\n+\tif (argc < 2 || argc > 3)\n+\t\treturn CMD_RET_USAGE;\n+\t/* Check if shutdown requested */\n+\tif (argc == 3) {\n+\t\tif (strcmp(argv[2], \"off\") != 0)\n+\t\t\treturn CMD_RET_USAGE;\n+\t\tdoStartup = NO; /* shutdown */\n+\t}\n+\tprintf(\"TPM2 Startup\\n\");\n+\n+\tmemset(&startupIn, 0, sizeof(startupIn));\n+\tmemset(&shutdownIn, 0, sizeof(shutdownIn));\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc != TPM_RC_SUCCESS)\n+\t\treturn rc;\n+\n+\tif (!strcmp(argv[1], \"TPM2_SU_CLEAR\")) {\n+\t\tif (doStartup == YES)\n+\t\t\tstartupIn.startupType = TPM_SU_CLEAR;\n+\t\telse\n+\t\t\tshutdownIn.shutdownType = TPM_SU_CLEAR;\n+\t} else if (!strcmp(argv[1], \"TPM2_SU_STATE\")) {\n+\t\tif (doStartup == YES)\n+\t\t\tstartupIn.startupType = TPM_SU_STATE;\n+\t\telse\n+\t\t\tshutdownIn.shutdownType = TPM_SU_STATE;\n+\t} else {\n+\t\tlog_debug(\"Couldn't recognize mode string: %s\\n\", argv[1]);\n+\t\twolfTPM2_Cleanup(&dev);\n+\t\treturn CMD_RET_FAILURE;\n+\t}\n+\n+\t/* startup */\n+\tif (doStartup == YES) {\n+\t\trc = TPM2_Startup(&startupIn);\n+\t\t/* TPM_RC_INITIALIZE = Already started */\n+\t\tif (rc != TPM_RC_SUCCESS && rc != TPM_RC_INITIALIZE) {\n+\t\t\tlog_debug(\"TPM2 Startup: Result = 0x%x (%s)\\n\", rc,\n+\t\t\t\tTPM2_GetRCString(rc));\n+\t\t}\n+\t/* shutdown */\n+\t} else {\n+\t\trc = TPM2_Shutdown(&shutdownIn);\n+\t\tif (rc != TPM_RC_SUCCESS) {\n+\t\t\tlog_debug(\"TPM2 Shutdown: Result = 0x%x (%s)\\n\", rc,\n+\t\t\t\tTPM2_GetRCString(rc));\n+\t\t}\n+\t}\n+\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tif (rc >= 0)\n+\t\trc = 0;\n+\n+\tlog_debug(\"tpm2 startup (%s): rc = %d (%s)\\n\",\n+\t\tdoStartup ? \"startup\" : \"shutdown\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+int do_tpm2_selftest(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tTPMI_YES_NO fullTest = YES;\n+\n+\t/* Need 2 arg: command + type */\n+\tif (argc != 2)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc == TPM_RC_SUCCESS) {\n+\t\tif (!strcmp(argv[1], \"full\")) {\n+\t\t\tfullTest = YES;\n+\t\t} else if (!strcmp(argv[1], \"continue\")) {\n+\t\t\tfullTest = NO;\n+\t\t} else {\n+\t\t\tlog_debug(\"Couldn't recognize test mode: %s\\n\", argv[1]);\n+\t\t\twolfTPM2_Cleanup(&dev);\n+\t\t\treturn CMD_RET_FAILURE;\n+\t\t}\n+\n+\t\t/* full test */\n+\t\tif (fullTest == YES) {\n+\t\t\trc = wolfTPM2_SelfTest(&dev);\n+\t\t\tif (rc != TPM_RC_SUCCESS) {\n+\t\t\t\tlog_debug(\"TPM2 Self Test: Result = 0x%x (%s)\\n\", rc,\n+\t\t\t\t\tTPM2_GetRCString(rc));\n+\t\t\t}\n+\t\t/* continue test */\n+\t\t} else {\n+\t\t\trc = wolfTPM2_SelfTest(&dev);\n+\t\t\tif (rc != TPM_RC_SUCCESS) {\n+\t\t\t\tlog_debug(\"TPM2 Self Test: Result = 0x%x (%s)\\n\", rc,\n+\t\t\t\t\tTPM2_GetRCString(rc));\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 selftest (%s): rc = %d (%s)\\n\",\n+\t\tfullTest ? \"full\" : \"continue\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tClear_In clearIn;\n+\tTPMI_RH_CLEAR handle;\n+\n+\t/* Need 2 arg: command + type */\n+\tif (argc != 2)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tif (!strcasecmp(\"TPM2_RH_LOCKOUT\", argv[1]))\n+\t\thandle = TPM_RH_LOCKOUT;\n+\telse if (!strcasecmp(\"TPM2_RH_PLATFORM\", argv[1]))\n+\t\thandle = TPM_RH_PLATFORM;\n+\telse\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc == TPM_RC_SUCCESS) {\n+\t\t/* Set up clear */\n+\t\tmemset(&clearIn, 0, sizeof(clearIn));\n+\t\tclearIn.authHandle = handle;\n+\n+\t\trc = TPM2_Clear(&clearIn);\n+\t\tif (rc != TPM_RC_SUCCESS) {\n+\t\t\tlog_debug(\"TPM2 Clear: Result = 0x%x (%s)\\n\", rc,\n+\t\t\t\tTPM2_GetRCString(rc));\n+\t\t}\n+\t}\n+\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 clear (%s): rc = %d (%s)\\n\",\n+\t\thandle == TPM_RH_LOCKOUT ? \"TPM2_RH_LOCKOUT\" : \"TPM2_RH_PLATFORM\",\n+\t\trc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tuint32_t pcrIndex;\n+\tint algo = TPM_ALG_SHA256;\n+\tint digestLen;\n+\tvoid *digest;\n+\tulong digest_addr;\n+\n+\t/* Need 3-4 args: command + pcr + digest_addr + [algo] */\n+\tif (argc < 3 || argc > 4)\n+\t\treturn CMD_RET_USAGE;\n+\tprintf(\"TPM2 PCR Extend\\n\");\n+\n+\tpcrIndex = simple_strtoul(argv[1], NULL, 0);\n+\tdigest_addr = simple_strtoul(argv[2], NULL, 0);\n+\n+\t/* Optional algorithm */\n+\tif (argc == 4) {\n+\t\talgo = TPM2_GetAlgId(argv[3]);\n+\t\tif (algo < 0) {\n+\t\t\tlog_debug(\"Couldn't recognize algorithm: %s\\n\", argv[3]);\n+\t\t\treturn CMD_RET_FAILURE;\n+\t\t}\n+\t\tlog_debug(\"Using algorithm: %s\\n\", TPM2_GetAlgName(algo));\n+\t}\n+\n+\t/* Get digest length based on algorithm */\n+\tdigestLen = TPM2_GetHashDigestSize(algo);\n+\tif (digestLen <= 0) {\n+\t\tlog_debug(\"Invalid algorithm digest length\\n\");\n+\t\treturn CMD_RET_FAILURE;\n+\t}\n+\n+\t/* Map digest from memory address */\n+\tdigest = map_sysmem(digest_addr, digestLen);\n+\tif (digest == NULL) {\n+\t\tlog_debug(\"Error: Invalid digest memory address\\n\");\n+\t\treturn CMD_RET_FAILURE;\n+\t}\n+\n+\tlog_debug(\"TPM2 PCR Extend: PCR %u with %s digest\\n\",\n+\t\t(unsigned int)pcrIndex, TPM2_GetAlgName(algo));\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc != TPM_RC_SUCCESS) {\n+\t\tunmap_sysmem(digest);\n+\t\treturn rc;\n+\t}\n+\n+\t/* Extend the PCR */\n+\trc = wolfTPM2_ExtendPCR(&dev, pcrIndex, algo, digest, digestLen);\n+\tif (rc != TPM_RC_SUCCESS) {\n+\t\tlog_debug(\"TPM2_PCR_Extend failed 0x%x: %s\\n\", rc,\n+\t\t\tTPM2_GetRCString(rc));\n+\t}\n+\n+\tunmap_sysmem(digest);\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 pcr_extend: rc = %d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+int do_tpm2_pcr_read(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tuint32_t pcrIndex;\n+\tint algo = TPM_ALG_SHA256;\n+\tvoid *digest;\n+\tulong digest_addr;\n+\tint digestLen;\n+\n+\t/* Need 3-4 args: command + pcr + digest_addr + [algo] */\n+\tif (argc < 3 || argc > 4)\n+\t\treturn CMD_RET_USAGE;\n+\n+\tpcrIndex = simple_strtoul(argv[1], NULL, 0);\n+\tdigest_addr = simple_strtoul(argv[2], NULL, 0);\n+\n+\t/* Optional algorithm */\n+\tif (argc == 4) {\n+\t\talgo = TPM2_GetAlgId(argv[3]);\n+\t\tif (algo < 0) {\n+\t\t\tlog_debug(\"Couldn't recognize algorithm: %s\\n\", argv[3]);\n+\t\t\treturn CMD_RET_FAILURE;\n+\t\t}\n+\t\tlog_debug(\"Using algorithm: %s\\n\", TPM2_GetAlgName(algo));\n+\t}\n+\n+\t/* Get digest length based on algorithm */\n+\tdigestLen = TPM2_GetHashDigestSize(algo);\n+\tif (digestLen <= 0) {\n+\t\tlog_debug(\"Invalid algorithm digest length\\n\");\n+\t\treturn CMD_RET_FAILURE;\n+\t}\n+\n+\t/* Map digest from memory address */\n+\tdigest = map_sysmem(digest_addr, digestLen);\n+\tif (digest == NULL) {\n+\t\tlog_debug(\"Error: Invalid digest memory address\\n\");\n+\t\treturn CMD_RET_FAILURE;\n+\t}\n+\n+\tlog_debug(\"TPM2 PCR Read: PCR %u to %s digest\\n\",\n+\t\t(unsigned int)pcrIndex, TPM2_GetAlgName(algo));\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc != TPM_RC_SUCCESS) {\n+\t\tunmap_sysmem(digest);\n+\t\treturn rc;\n+\t}\n+\n+\t/* Read the PCR */\n+\trc = wolfTPM2_ReadPCR(&dev, pcrIndex, algo, digest, &digestLen);\n+\tif (rc != TPM_RC_SUCCESS) {\n+\t\tlog_debug(\"TPM2_PCR_Read failed 0x%x: %s\\n\", rc,\n+\t\t\tTPM2_GetRCString(rc));\n+\t}\n+\n+\tunmap_sysmem(digest);\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 pcr_read: rc = %d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+int do_tpm2_pcr_allocate(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tPCR_Allocate_In in;\n+\tPCR_Allocate_Out out;\n+\tTPM2B_AUTH auth;\n+\n+\t/* Need 3-4 args: command + algorithm + on/off + [password] */\n+\tif (argc < 3 || argc > 4)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc != TPM_RC_SUCCESS)\n+\t\treturn rc;\n+\n+\t/* Setup PCR Allocation command */\n+\tmemset(&in, 0, sizeof(in));\n+\tin.authHandle = TPM_RH_PLATFORM;\n+\n+\t/* Single PCR bank allocation */\n+\tin.pcrAllocation.count = 1; /* Change only one bank */\n+\tin.pcrAllocation.pcrSelections[0].hash = TPM2_GetAlgId(argv[1]);\n+\tin.pcrAllocation.pcrSelections[0].sizeofSelect = PCR_SELECT_MAX;\n+\n+\t/* Set all PCRs for this algorithm */\n+\tif (!strcmp(argv[2], \"on\")) {\n+\t\tmemset(in.pcrAllocation.pcrSelections[0].pcrSelect, 0xFF,\n+\t\t\tPCR_SELECT_MAX);\n+\t} else if (!strcmp(argv[2], \"off\")) {\n+\t\t/* Clear all PCRs for this algorithm */\n+\t\tmemset(in.pcrAllocation.pcrSelections[0].pcrSelect, 0x00,\n+\t\t\tPCR_SELECT_MAX);\n+\t} else {\n+\t\tlog_debug(\"Couldn't recognize allocate mode: %s\\n\", argv[2]);\n+\t\twolfTPM2_Cleanup(&dev);\n+\t\treturn CMD_RET_USAGE;\n+\t}\n+\tlog_debug(\"Attempting to set %s bank to %s\\n\",\n+\t\tTPM2_GetAlgName(in.pcrAllocation.pcrSelections[0].hash),\n+\t\targv[2]);\n+\n+\t/* Set auth password if provided */\n+\tif (argc == 4) {\n+\t\tmemset(&auth, 0, sizeof(auth));\n+\t\tauth.size = strlen(argv[3]);\n+\t\tmemcpy(auth.buffer, argv[3], auth.size);\n+\t\trc = wolfTPM2_SetAuth(&dev, 0, TPM_RH_PLATFORM, &auth, 0, NULL);\n+\t\tif (rc != TPM_RC_SUCCESS) {\n+\t\t\tlog_debug(\"wolfTPM2_SetAuth failed 0x%x: %s\\n\", rc,\n+\t\t\t\tTPM2_GetRCString(rc));\n+\t\t\twolfTPM2_Cleanup(&dev);\n+\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n+\t/* Allocate the PCR */\n+\trc = TPM2_PCR_Allocate(&in, &out);\n+\tif (rc != TPM_RC_SUCCESS) {\n+\t\tlog_debug(\"TPM2_PCR_Allocate failed 0x%x: %s\\n\", rc,\n+\t\t\tTPM2_GetRCString(rc));\n+\t}\n+\n+\t/* Print current PCR state */\n+\tprintf(\"\\n\\tNOTE: A TPM restart is required for changes to take effect\\n\");\n+\tprintf(\"\\nCurrent PCR state:\\n\");\n+\tTPM2_PCRs_Print();\n+\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tprintf(\"Allocation Success: %s\\n\",\n+\t\tout.allocationSuccess ? \"YES\" : \"NO\");\n+\tlog_debug(\"tpm2 pcr_allocate %s (%s): rc = %d (%s)\\n\",\n+\t\tTPM2_GetAlgName(in.pcrAllocation.pcrSelections[0].hash),\n+\t\targv[2], rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+/*\n+ * Without wolfCrypt, parameter encryption is not available.\n+ * A session is required to protect the new platform auth.\n+ */\n+#ifndef WOLFTPM2_NO_WOLFCRYPT\n+static int TPM2_PCR_SetAuth(int argc, char *const argv[],\n+\tint isPolicy)\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tWOLFTPM2_SESSION session;\n+\tTPM2B_AUTH auth;\n+\tconst char *pw = (argc < 4) ? NULL : argv[3];\n+\tconst char *key = argv[2];\n+\tconst ssize_t key_sz = strlen(key);\n+\tu32 pcrIndex = simple_strtoul(argv[1], NULL, 0);\n+\n+\t/* Need 3-4 args: command + pcr + auth + [platform_auth] */\n+\tif (argc < 3 || argc > 4)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device for value/policy */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc != TPM_RC_SUCCESS)\n+\t\treturn rc;\n+\n+\t/* Start the session */\n+\trc = wolfTPM2_StartSession(&dev, &session, NULL, NULL,\n+\t\tisPolicy ? TPM_SE_POLICY : TPM_SE_HMAC, TPM_ALG_NULL);\n+\tif (rc != TPM_RC_SUCCESS) {\n+\t\tlog_debug(\"wolfTPM2_StartSession failed 0x%x: %s\\n\", rc,\n+\t\t\tTPM2_GetRCString(rc));\n+\t\twolfTPM2_Cleanup(&dev);\n+\t\treturn rc;\n+\t}\n+\n+\t/* Set the platform auth if provided */\n+\tif (pw) {\n+\t\tTPM2B_AUTH platformAuth;\n+\n+\t\tmemset(&platformAuth, 0, sizeof(platformAuth));\n+\t\tplatformAuth.size = strlen(pw);\n+\t\tmemcpy(platformAuth.buffer, pw, platformAuth.size);\n+\t\trc = wolfTPM2_SetAuth(&dev, 0, TPM_RH_PLATFORM,\n+\t\t\t&platformAuth, 0, NULL);\n+\t\tif (rc != TPM_RC_SUCCESS) {\n+\t\t\tlog_debug(\"wolfTPM2_SetAuth failed 0x%x: %s\\n\", rc,\n+\t\t\t\tTPM2_GetRCString(rc));\n+\t\t\twolfTPM2_UnloadHandle(&dev, &session.handle);\n+\t\t\twolfTPM2_Cleanup(&dev);\n+\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n+\tprintf(\"Setting %s auth for PCR %u\\n\",\n+\t\tisPolicy ? \"policy\" : \"value\", pcrIndex);\n+\n+\t/* Set up the auth value/policy */\n+\tmemset(&auth, 0, sizeof(auth));\n+\tauth.size = key_sz;\n+\tmemcpy(auth.buffer, key, key_sz);\n+\n+\tif (isPolicy) {\n+\t\t/* Use TPM2_PCR_SetAuthPolicy command */\n+\t\tPCR_SetAuthPolicy_In in;\n+\n+\t\tmemset(&in, 0, sizeof(in));\n+\t\tin.authHandle = TPM_RH_PLATFORM;\n+\t\tin.authPolicy = auth;\n+\t\tin.hashAlg = TPM_ALG_SHA256; /* Default to SHA256 */\n+\t\tin.pcrNum = pcrIndex;\n+\t\trc = TPM2_PCR_SetAuthPolicy(&in);\n+\t} else {\n+\t\t/* Use TPM2_PCR_SetAuthValue command */\n+\t\tPCR_SetAuthValue_In in;\n+\n+\t\tmemset(&in, 0, sizeof(in));\n+\t\tin.pcrHandle = pcrIndex;\n+\t\tin.auth = auth;\n+\t\trc = TPM2_PCR_SetAuthValue(&in);\n+\t}\n+\n+\tif (rc != TPM_RC_SUCCESS) {\n+\t\tlog_debug(\"TPM2_PCR_SetAuth%s failed 0x%x: %s\\n\",\n+\t\t\tisPolicy ? \"Policy\" : \"Value\",\n+\t\t\trc, TPM2_GetRCString(rc));\n+\t}\n+\n+\twolfTPM2_UnloadHandle(&dev, &session.handle);\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 set_auth %s: rc = %d (%s)\\n\",\n+\t\tisPolicy ? \"Policy\" : \"Value\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+int do_tpm2_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\treturn TPM2_PCR_SetAuth(argc, argv, YES);\n+}\n+\n+int do_tpm2_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\treturn TPM2_PCR_SetAuth(argc, argv, NO);\n+}\n+\n+int do_tpm2_change_auth(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tWOLFTPM2_SESSION session;\n+\tconst char *newpw = argv[2];\n+\tconst char *oldpw = (argc == 4) ? argv[3] : NULL;\n+\tconst ssize_t newpw_sz = strlen(newpw);\n+\tconst ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;\n+\tHierarchyChangeAuth_In in;\n+\tTPM2B_AUTH newAuth;\n+\n+\t/* Need 3-4 args: command + hierarchy + new_pw + [old_pw] */\n+\tif (argc < 3 || argc > 4)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc != TPM_RC_SUCCESS)\n+\t\treturn rc;\n+\n+\tmemset(&in, 0, sizeof(in));\n+\n+\t/* Set the handle */\n+\tif (!strcmp(argv[1], \"TPM2_RH_LOCKOUT\"))\n+\t\tin.authHandle = TPM_RH_LOCKOUT;\n+\telse if (!strcmp(argv[1], \"TPM2_RH_ENDORSEMENT\"))\n+\t\tin.authHandle = TPM_RH_ENDORSEMENT;\n+\telse if (!strcmp(argv[1], \"TPM2_RH_OWNER\"))\n+\t\tin.authHandle = TPM_RH_OWNER;\n+\telse if (!strcmp(argv[1], \"TPM2_RH_PLATFORM\"))\n+\t\tin.authHandle = TPM_RH_PLATFORM;\n+\telse {\n+\t\twolfTPM2_Cleanup(&dev);\n+\t\treturn CMD_RET_USAGE;\n+\t}\n+\n+\t/* Validate password length if provided */\n+\tif (newpw_sz > TPM_SHA256_DIGEST_SIZE ||\n+\t\toldpw_sz > TPM_SHA256_DIGEST_SIZE) {\n+\t\twolfTPM2_Cleanup(&dev);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Start auth session */\n+\trc = wolfTPM2_StartSession(&dev, &session, NULL, NULL,\n+\t\tTPM_SE_HMAC, TPM_ALG_CFB);\n+\tif (rc != TPM_RC_SUCCESS) {\n+\t\tlog_debug(\"wolfTPM2_StartSession failed 0x%x: %s\\n\", rc,\n+\t\t\tTPM2_GetRCString(rc));\n+\t\twolfTPM2_Cleanup(&dev);\n+\t\treturn rc;\n+\t}\n+\n+\t/* If old password exists then set it as the current auth */\n+\tif (oldpw) {\n+\t\tTPM2B_AUTH oldAuth;\n+\n+\t\tmemset(&oldAuth, 0, sizeof(oldAuth));\n+\t\toldAuth.size = oldpw_sz;\n+\t\tmemcpy(oldAuth.buffer, oldpw, oldpw_sz);\n+\t\trc = wolfTPM2_SetAuthPassword(&dev, 0, &oldAuth);\n+\t\tif (rc != TPM_RC_SUCCESS) {\n+\t\t\tlog_debug(\"wolfTPM2_SetAuthPassword failed 0x%x: %s\\n\", rc,\n+\t\t\t\tTPM2_GetRCString(rc));\n+\t\t\twolfTPM2_UnloadHandle(&dev, &session.handle);\n+\t\t\twolfTPM2_Cleanup(&dev);\n+\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n+\tmemset(&newAuth, 0, sizeof(newAuth));\n+\tnewAuth.size = newpw_sz;\n+\tmemcpy(newAuth.buffer, newpw, newpw_sz);\n+\tin.newAuth = newAuth;\n+\n+\t/* Change the auth based on the hierarchy */\n+\trc = wolfTPM2_ChangeHierarchyAuth(&dev, &session, in.authHandle);\n+\tif (rc != TPM_RC_SUCCESS) {\n+\t\tlog_debug(\"wolfTPM2_ChangeHierarchyAuth failed 0x%x: %s\\n\", rc,\n+\t\t\tTPM2_GetRCString(rc));\n+\t} else {\n+\t\tlog_debug(\"Successfully changed auth for %s\\n\", argv[1]);\n+\t}\n+\n+\twolfTPM2_UnloadHandle(&dev, &session.handle);\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 change_auth: rc = %d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+#else /* WOLFTPM2_NO_WOLFCRYPT */\n+int do_tpm2_change_auth(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tprintf(\"wolfCrypt support required for change_auth\\n\");\n+\treturn CMD_RET_FAILURE;\n+}\n+\n+int do_tpm2_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tprintf(\"wolfCrypt support required for pcr_setauthpolicy\\n\");\n+\treturn CMD_RET_FAILURE;\n+}\n+\n+int do_tpm2_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tprintf(\"wolfCrypt support required for pcr_setauthvalue\\n\");\n+\treturn CMD_RET_FAILURE;\n+}\n+#endif /* !WOLFTPM2_NO_WOLFCRYPT */\n+\n+int do_tpm2_pcr_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\n+\t/* Need 1 arg: command */\n+\tif (argc != 1)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc == TPM_RC_SUCCESS) {\n+\t\t/* Print the current PCR state */\n+\t\tTPM2_PCRs_Print();\n+\t}\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 pcr_print: rc = %d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+int do_tpm2_dam_reset(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tconst char *pw = (argc < 2) ? NULL : argv[1];\n+\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n+\tDictionaryAttackLockReset_In in;\n+\tTPM2_AUTH_SESSION session[MAX_SESSION_NUM];\n+\n+\t/* Need 1-2 args: command + [password] */\n+\tif (argc > 2)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Validate password length if provided */\n+\tif (pw && pw_sz > TPM_SHA256_DIGEST_SIZE) {\n+\t\tlog_debug(\"Error: Password too long\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc == TPM_RC_SUCCESS) {\n+\t\t/* set lock handle */\n+\t\tmemset(&in, 0, sizeof(in));\n+\t\tin.lockHandle = TPM_RH_LOCKOUT;\n+\n+\t\t/* Setup auth session only if password provided */\n+\t\tmemset(session, 0, sizeof(session));\n+\t\tsession[0].sessionHandle = TPM_RS_PW;\n+\t\tif (pw) {\n+\t\t\tsession[0].auth.size = pw_sz;\n+\t\t\tmemcpy(session[0].auth.buffer, pw, pw_sz);\n+\t\t}\n+\t\tTPM2_SetSessionAuth(session);\n+\n+\t\trc = TPM2_DictionaryAttackLockReset(&in);\n+\t\tlog_debug(\"TPM2_Dam_Reset: Result = 0x%x (%s)\\n\", rc,\n+\t\t\tTPM2_GetRCString(rc));\n+\t}\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 dam_reset: rc = %d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+int do_tpm2_dam_parameters(struct cmd_tbl *cmdtp, int flag,\n+\tint argc, char *const argv[])\n+{\n+\tint rc;\n+\tWOLFTPM2_DEV dev;\n+\tconst char *pw = (argc < 5) ? NULL : argv[4];\n+\tconst ssize_t pw_sz = pw ? strlen(pw) : 0;\n+\tDictionaryAttackParameters_In in;\n+\tTPM2_AUTH_SESSION session[MAX_SESSION_NUM];\n+\n+\t/*\n+\t * Need 4-5 args: command + max_tries + recovery_time +\n+\t * lockout_recovery + [password]\n+\t */\n+\tif (argc < 4 || argc > 5)\n+\t\treturn CMD_RET_USAGE;\n+\n+\t/* Validate password length if provided */\n+\tif (pw && pw_sz > TPM_SHA256_DIGEST_SIZE) {\n+\t\tlog_debug(\"Error: Password too long\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Init the TPM2 device */\n+\trc = TPM2_Init_Device(&dev, NULL);\n+\tif (rc == TPM_RC_SUCCESS) {\n+\t\t/* Set parameters */\n+\t\tmemset(&in, 0, sizeof(in));\n+\t\tin.newMaxTries = simple_strtoul(argv[1], NULL, 0);\n+\t\tin.newRecoveryTime = simple_strtoul(argv[2], NULL, 0);\n+\t\tin.lockoutRecovery = simple_strtoul(argv[3], NULL, 0);\n+\n+\t\t/* set lock handle */\n+\t\tin.lockHandle = TPM_RH_LOCKOUT;\n+\n+\t\t/* Setup auth session only if password provided */\n+\t\tmemset(session, 0, sizeof(session));\n+\t\tsession[0].sessionHandle = TPM_RS_PW;\n+\t\tif (pw) {\n+\t\t\tsession[0].auth.size = pw_sz;\n+\t\t\tmemcpy(session[0].auth.buffer, pw, pw_sz);\n+\t\t}\n+\t\tTPM2_SetSessionAuth(session);\n+\n+\t\t/* Set DAM parameters */\n+\t\trc = TPM2_DictionaryAttackParameters(&in);\n+\t\tif (rc != TPM_RC_SUCCESS) {\n+\t\t\tlog_debug(\"TPM2_DictionaryAttackParameters failed 0x%x: %s\\n\", rc,\n+\t\t\t\tTPM2_GetRCString(rc));\n+\t\t}\n+\n+\t\tprintf(\"Changing dictionary attack parameters:\\n\");\n+\t\tprintf(\" maxTries: %u\\n\", in.newMaxTries);\n+\t\tprintf(\" recoveryTime: %u\\n\", in.newRecoveryTime);\n+\t\tprintf(\" lockoutRecovery: %u\\n\", in.lockoutRecovery);\n+\t}\n+\twolfTPM2_Cleanup(&dev);\n+\n+\tlog_debug(\"tpm2 dam_parameters: rc = %d (%s)\\n\", rc, TPM2_GetRCString(rc));\n+\n+\treturn rc;\n+}\n+\n+#endif /* !WOLFTPM2_NO_WRAPPER */\n", "prefixes": [ "v3", "08/12" ] }