From 892726e6b5bb87430bea56377cb7b39d935537de Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 1 Apr 2024 17:21:18 -0700 Subject: [PATCH] Added support for Infineon SLB9672/SLB9673 Firmware upgrade (see examples/firmware/README.md) Added Infineon Modus Toolbox support. See `wolfssl/IDE/Infineon/README.md` for setup instructions. Added support for Infineon CyHal I2C support. Added Firmware extraction tool Added Firmware update example application `examples/firmware/ifx_fw_update`. Added support for vendor capabilities `TPM_CAP_VENDOR_PROPERTY`. Added `XSLEEP_MS` macro for firmware update delay. Added support for getting key group id, operational mode and update counts. Added support for abandoning an update. Added support for firmware update done, but not finalized Fix auto-detect to not define SLB9672/SLB9673. --- .cyignore | 4 + .gitignore | 2 + Makefile.am | 1 + configure.ac | 14 + examples/boot/include.am | 2 + examples/firmware/Makefile | 13 + examples/firmware/README.md | 104 ++++++++ examples/firmware/ifx_fw_extract.c | 321 +++++++++++++++++++++++ examples/firmware/ifx_fw_update.c | 235 +++++++++++++++++ examples/firmware/ifx_fw_update.h | 35 +++ examples/firmware/include.am | 24 ++ examples/include.am | 1 + examples/wrap/wrap_test.c | 4 + hal/tpm_io.c | 6 +- hal/tpm_io.h | 6 + hal/tpm_io_infineon.c | 143 ++++++++++- hal/tpm_io_linux.c | 2 +- src/tpm2.c | 73 +++++- src/tpm2_packet.c | 17 -- src/tpm2_wrap.c | 400 ++++++++++++++++++++++++++++- wolftpm/tpm2.h | 26 +- wolftpm/tpm2_packet.h | 17 ++ wolftpm/tpm2_types.h | 46 +++- wolftpm/tpm2_wrap.h | 18 ++ 24 files changed, 1469 insertions(+), 45 deletions(-) create mode 100644 .cyignore create mode 100644 examples/firmware/Makefile create mode 100644 examples/firmware/README.md create mode 100644 examples/firmware/ifx_fw_extract.c create mode 100644 examples/firmware/ifx_fw_update.c create mode 100644 examples/firmware/ifx_fw_update.h create mode 100644 examples/firmware/include.am diff --git a/.cyignore b/.cyignore new file mode 100644 index 0000000..0a3ff1d --- /dev/null +++ b/.cyignore @@ -0,0 +1,4 @@ +# wolfTPM folders +$(SEARCH_wolftpm)/IDE +$(SEARCH_wolftpm)/examples +$(SEARCH_wolftpm)/tests \ No newline at end of file diff --git a/.gitignore b/.gitignore index b8b7b2a..ea9d1b8 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,8 @@ examples/attestation/activate_credential examples/boot/secure_rot examples/boot/secret_seal examples/boot/secret_unseal +examples/firmware/ifx_fw_extract +examples/firmware/ifx_fw_update # Generated Cert Files certs/ca-*.pem diff --git a/Makefile.am b/Makefile.am index 90c1148..dc750f0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,6 +43,7 @@ include wrapper/include.am include hal/include.am include cmake/include.am +EXTRA_DIST+= .cyignore EXTRA_DIST+= README.md EXTRA_DIST+= ChangeLog.md EXTRA_DIST+= LICENSE diff --git a/configure.ac b/configure.ac index 7d2101e..0841058 100644 --- a/configure.ac +++ b/configure.ac @@ -408,6 +408,18 @@ then fi +# Built-in TPM firmware upgrade support +AC_ARG_ENABLE([firmware], + [AS_HELP_STRING([--enable-firmware],[Enable support for TPM firmware upgrades (default: enabled)])], + [ ENABLED_FIRMWARE=$enableval ], + [ ENABLED_FIRMWARE=yes ] + ) +if test "x$ENABLED_FIRMWARE" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_FIRMWARE_UPGRADE" +fi + + # HARDEN FLAGS AX_HARDEN_CC_COMPILER_FLAGS @@ -431,6 +443,7 @@ AM_CONDITIONAL([BUILD_WINAPI], [test "x$ENABLED_WINAPI" = "xyes"]) AM_CONDITIONAL([BUILD_NUVOTON], [test "x$ENABLED_NUVOTON" = "xyes"]) AM_CONDITIONAL([BUILD_CHECKWAITSTATE], [test "x$ENABLED_CHECKWAITSTATE" = "xyes"]) AM_CONDITIONAL([BUILD_AUTODETECT], [test "x$ENABLED_AUTODETECT" = "xyes"]) +AM_CONDITIONAL([BUILD_FIRMWARE], [test "x$ENABLED_FIRMWARE" = "xyes"]) AM_CONDITIONAL([BUILD_HAL], [test "x$ENABLED_EXAMPLE_HAL" = "xyes" || test "x$ENABLED_MMIO" = "xyes"]) @@ -556,3 +569,4 @@ echo " * Microchip ATTPM20: $ENABLED_MICROCHIP" echo " * Nuvoton NPCT75x: $ENABLED_NUVOTON" echo " * Runtime Module Detection: $ENABLED_AUTODETECT" +echo " * Firmware Upgrade Support: $ENABLED_FIRMWARE" diff --git a/examples/boot/include.am b/examples/boot/include.am index d7ec884..7a19340 100644 --- a/examples/boot/include.am +++ b/examples/boot/include.am @@ -1,6 +1,8 @@ # vim:ft=automake # All paths should be given relative to the root +EXTRA_DIST += examples/boot/README.md + if BUILD_EXAMPLES noinst_HEADERS += examples/boot/boot.h diff --git a/examples/firmware/Makefile b/examples/firmware/Makefile new file mode 100644 index 0000000..1bc53d2 --- /dev/null +++ b/examples/firmware/Makefile @@ -0,0 +1,13 @@ +CC=gcc +CFLAGS=-Wall -Werror -Wextra -g +LIBS= + +all: clean ifx_fw_extract + +ifx_fw_extract: ifx_fw_extract.o + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + +.PHONY: clean + +clean: + rm -f *.o ifx_fw_extract diff --git a/examples/firmware/README.md b/examples/firmware/README.md new file mode 100644 index 0000000..45e4a60 --- /dev/null +++ b/examples/firmware/README.md @@ -0,0 +1,104 @@ +# TPM Firmware Update Support + +Currently wolfTPM supports firmware update capability for the Infineon SLB9672 (SPI) and SLB9673 (I2C) TPM 2.0 modules. Infineon has open sourced their firmware update. + +## Infineon Firmware + +### Extracting the firmware + +Infineon releases firmware as a .bin file (example: TPM20_15.23.17664.0_R1.BIN). + +The .bin contains a 16-byte GUID header, at least one manifest based on key group and the firmware. A typical manifest is 3KB and firmware is 920KB. + +We have included a host side tool `ifx_fw_extract` for extracting the manifest and firmware data file required for a TPM upgrade. + +Example usage: + +```sh +# Build host tool +make + +# Help +./ifx_fw_extract --help +Usage: + ifx_fw_extract + ifx_fw_extract + +# Find key groups in .bin +./ifx_fw_extract TPM20_26.13.17770.0_R1.BIN +Reading TPM20_26.13.17770.0_R1.BIN +Found group 00000007 + +# Extract manifest and firmware data files for key group +./ifx_fw_extract TPM20_26.13.17770.0_R1.BIN 7 TPM20_26.13.17770.0_R1.MANIFEST TPM20_26.13.17770.0_R1.DATA +Reading TPM20_26.13.17770.0_R1.BIN +Found group 00000007 +Chosen group found: 00000007 +Manifest size is 3224 +Data size is 934693 +Writing TPM20_26.13.17770.0_R1.MANIFEST +Writing TPM20_26.13.17770.0_R1.DATA +``` + +### Updating the firmware + +The `ifx_fw_update` tool uses the manifest (header) and firmware data file. + +The TPM has a vendor capability for getting the key group id. This is populated in the `WOLFTPM2_CAPS.keyGroupId` when `wolfTPM2_GetCapabilities` is called. This value should match the firmware extract tool `keygroup_id`. + +```sh +# Help +./ifx_fw_update --help +Infineon Firmware Update Usage: + ./ifx_fw_update (get info) + ./ifx_fw_update --abandon (cancel) + ./ifx_fw_update + +# Run without arguments to display the current firmware information including key group id and operational mode +./ifx_fw_update +Infineon Firmware Update Tool +TPM2: Caps 0x1ae00082, Did 0x001c, Vid 0x15d1, Rid 0x16 +TPM2_Startup pass +Mfg IFX (1), Vendor SLB9673, Fw 26.13 (0x456a) +Operational mode: Normal TPM operational mode (0x0) +KeyGroupId 0x7, FwCounter 1254 (255 same) + +# Run with manifest and firmware files +./ifx_fw_update TPM20_26.13.17770.0_R1.MANIFEST TPM20_26.13.17770.0_R1.DATA +Infineon Firmware Update Tool + Manifest File: TPM20_26.13.17770.0_R1.MANIFEST + Firmware File: TPM20_26.13.17770.0_R1.DATA +TPM2: Caps 0x1ae00082, Did 0x001c, Vid 0x15d1, Rid 0x16 +TPM2_Startup pass +Mfg IFX (1), Vendor SLB9673, Fw 26.13 (0x456a) +Operational mode: Normal TPM operational mode (0x0) +KeyGroupId 0x7, FwCounter 1254 (255 same) +TPM2_StartAuthSession: handle 0x3000000, algorithm NULL +TPM2_FlushContext: Closed handle 0x3000000 +TPM2_StartAuthSession: handle 0x3000000, algorithm NULL +Firmware manifest chunk 1024 offset (0 / 3224), state 1 +Firmware manifest chunk 1024 offset (1024 / 3224), state 2 +Firmware manifest chunk 1024 offset (2048 / 3224), state 2 +Firmware manifest chunk 152 offset (3072 / 3224), state 0 +Firmware data chunk offset 0 +Firmware data chunk offset 1024 +Firmware data chunk offset 2048 +Firmware data chunk offset 3072 +... +Firmware data chunk offset 932864 +Firmware data chunk offset 933888 +Firmware data done +Mfg IFX (1), Vendor , Fw 0.0 (0x0) +Operational mode: After finalize or abandon, reboot required (0x4) +KeyGroupId 0x7, FwCounter 1253 (254 same) +TPM2_Shutdown failed 304: Unknown + +# Reset or power cycle TPM +./ifx_fw_update +Infineon Firmware Update Tool +TPM2: Caps 0x1ae00082, Did 0x001c, Vid 0x15d1, Rid 0x16 +TPM2_Startup pass +Mfg IFX (1), Vendor SLB9673, Fw 26.13 (0x456a) +Operational mode: Normal TPM operational mode (0x0) +KeyGroupId 0x7, FwCounter 1253 (254 same) +``` diff --git a/examples/firmware/ifx_fw_extract.c b/examples/firmware/ifx_fw_extract.c new file mode 100644 index 0000000..7888489 --- /dev/null +++ b/examples/firmware/ifx_fw_extract.c @@ -0,0 +1,321 @@ +/* ifx_fw_extract.c + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfTPM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Tool source based on simple-update example from + * Infineon Technologies AG (www.infineon.com). + * This is a stand-alone host side tool for extracting the firmware + * manifest and data files from a supplied .bin + */ + +#define _DEFAULT_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Endianess helpers */ +#if defined(__MACH__) || defined(__APPLE__) + #include + #include + + #define htobe16(x) OSSwapHostToBigInt16(x) + #define htole16(x) OSSwapHostToLittleInt16(x) + #define be16toh(x) OSSwapBigToHostInt16(x) + #define le16toh(x) OSSwapLittleToHostInt16(x) + + #define htobe32(x) OSSwapHostToBigInt32(x) + #define htole32(x) OSSwapHostToLittleInt32(x) + #define be32toh(x) OSSwapBigToHostInt32(x) + #define le32toh(x) OSSwapLittleToHostInt32(x) + + #define htobe64(x) OSSwapHostToBigInt64(x) + #define htole64(x) OSSwapHostToLittleInt64(x) + #define be64toh(x) OSSwapBigToHostInt64(x) + #define le64toh(x) OSSwapLittleToHostInt64(x) +#else + #include +#endif + +/* Helper to print file and line */ +#define LOG(t) { printf(__FILE__":%i: %s\n", __LINE__, t); } + +#define READ_BE16(dest, buf, size, off) { \ + if (off + sizeof(dest) >= size) { \ + LOG("FW file too short"); \ + return -1; \ + } \ + memcpy(&dest, &fw[off], sizeof(dest)); \ + dest = be16toh(dest); \ + off += sizeof(dest); \ +} + +#define READ_BE32(dest, buf, size, off) { \ + if (off + sizeof(dest) >= size) { \ + LOG("FW file too short"); \ + return -1; \ + } \ + memcpy(&dest, &fw[off], sizeof(dest)); \ + dest = be32toh(dest); \ + off += sizeof(dest); \ +} + + +/* macros for stdio */ +#define XFILE FILE* +#define XFOPEN fopen +#define XFSEEK fseek +#define XFTELL ftell +#define XREWIND rewind +#define XFREAD fread +#define XFWRITE fwrite +#define XFCLOSE fclose +#define XSEEK_END SEEK_END +#define XBADFILE NULL +#define XFGETS fgets +#define XFEOF feof + +/* internal error codes */ +#define MEMORY_E -125 /* out of memory error */ +#define BUFFER_E -132 /* output buffer too small or input too large */ +#define BAD_FUNC_ARG -173 /* Bad function argument provided */ + + +static int extractFW( + uint8_t *fw, size_t fw_size, uint32_t keygroup_id, + uint8_t **manifest, size_t *manifest_size, + uint8_t **data, size_t *data_size) +{ + size_t offset = 0, offset2; + uint16_t size16, num; + uint32_t size32, group; + + const uint8_t guid[] = { 0x1a, 0x53, 0x66, 0x7a, + 0xfb, 0x12, 0x47, 0x9e, + 0xac, 0x58, 0xec, 0x99, + 0x58, 0x86, 0x10, 0x94 }; + + if (offset + sizeof(guid) > fw_size) { + LOG("FW file too short"); + return -1; + } + if (memcmp(&fw[offset], &guid[0], sizeof(guid)) != 0) { + LOG("Wrong GUID"); + return -1; + } + offset += sizeof(guid) + 1; + + READ_BE16(size16, fw, fw_size, offset); + offset += size16 + 1; + + READ_BE16(size16, fw, fw_size, offset); + offset += size16; + + READ_BE16(size16, fw, fw_size, offset); + offset2 = offset; + offset += size16; + + READ_BE16(size16, fw, offset, offset2); + offset2 += size16; + + READ_BE16(num, fw, offset, offset2); + + *manifest = NULL; + for (int i = 0; i < num; i++) { + READ_BE32(group, fw, offset, offset2); + printf("Found group %08x\n", group); + + READ_BE16(size16, fw, offset, offset2); + + if (group == keygroup_id) { + printf("Chosen group found: %08x\n", group); + *manifest = &fw[offset2]; + *manifest_size = size16; + } + offset2 += size16; + } + if (*manifest == NULL) { + if (keygroup_id == 0) { + /* just list key groups */ + return 0; + } + LOG("Chosen group not found"); + return -1; + } + + printf("Manifest size is %zi\n", *manifest_size); + if (offset2 != offset) { + LOG("Bad Manifest size"); + return -1; + } + + READ_BE32(size32, fw, fw_size, offset); + if (offset + size32 >= fw_size) { + LOG("FW file too short"); + return -1; + } + *data = &fw[offset]; + *data_size = size32; + offset += size32; + printf("Data size is %zi\n", *data_size); + + READ_BE16(size16, fw, fw_size, offset); + offset += size16 + 4; + + if (offset != fw_size) { + LOG("Wrong FW file size"); + printf("offset at %zi, fw_size at %zi\n", offset, fw_size); + return -1; + } + + return 0; +} + +static int readfile(const char* fname, uint8_t** buf, size_t* bufLen) +{ + int ret = 0; + ssize_t fileSz, readLen; + XFILE fp; + + if (fname == NULL || buf == NULL || bufLen == NULL) + return BAD_FUNC_ARG; + + /* open file (read-only binary) */ + fp = XFOPEN(fname, "rb"); + if (fp == XBADFILE) { + fprintf(stderr, "Error loading %s\n", fname); + return BUFFER_E; + } + + XFSEEK(fp, 0, XSEEK_END); + fileSz = XFTELL(fp); + XREWIND(fp); + if (fileSz > 0) { + if (*buf == NULL) { + *buf = (uint8_t*)malloc(fileSz); + if (*buf == NULL) + ret = MEMORY_E; + } + else if (*buf != NULL && fileSz > (ssize_t)*bufLen) { + ret = BUFFER_E; + } + *bufLen = (size_t)fileSz; + if (ret == 0) { + readLen = XFREAD(*buf, 1, *bufLen, fp); + ret = (readLen == (ssize_t)*bufLen) ? 0 : -1; + } + } + else { + ret = BUFFER_E; + } + XFCLOSE(fp); + return ret; +} + +static int writefile(const char* filename, const uint8_t *buf, size_t bufSz) +{ + int rc = -1; + XFILE fp; + size_t fileSz = 0; + + if (filename == NULL || buf == NULL) + return BAD_FUNC_ARG; + + fp = XFOPEN(filename, "wb"); + if (fp != XBADFILE) { + fileSz = XFWRITE(buf, 1, bufSz, fp); + /* sanity check */ + if (fileSz == bufSz) { + rc = 0; + } + printf("Wrote %d bytes to %s\n", (int)fileSz, filename); + XFCLOSE(fp); + } + + return rc; +} + +int main(int argc, char **argv) +{ + int rc; + uint8_t *manifest = NULL, *data = NULL, *fw = NULL; + size_t manifest_size, data_size, fw_size; + uint32_t keygroup_id = 0; + + if (argc <= 1 || + strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || + strcmp(argv[argc-1], "-h") == 0 || strcmp(argv[argc-1], "--help") == 0) + { + printf("Usage:\n"); + printf(" ifx_fw_extract \n"); + printf(" ifx_fw_extract \n"); + exit(1); + } + + if (argc >= 2) { + if (readfile(argv[1], &fw, &fw_size) < 0) { + LOG("Cannot read FW file."); + rc = EXIT_FAILURE; + goto exit; + } + + if (argc >= 3) { + if (sscanf(argv[2], "0x%08x", &keygroup_id) != 1 && sscanf(argv[2], "%08x", &keygroup_id) != 1) { + LOG("Cannot read keygroup_id."); + rc = EXIT_FAILURE; + goto exit; + } + } + rc = extractFW(fw, fw_size, keygroup_id, + &manifest, &manifest_size, + &data, &data_size); + if (rc != 0) { + printf(__FILE__":%i: Received error 0x%08x\n", __LINE__, rc); + goto exit; + } + + if (argc >= 5) { + if (writefile(argv[3], manifest, manifest_size) < 0) { + rc = EXIT_FAILURE; + goto exit; + } + if (writefile(argv[4], data, data_size) < 0) { + rc = EXIT_FAILURE; + goto exit; + } + } + rc = 0; + } + else { + printf("Bad arguments.\n"); + rc = EXIT_FAILURE; + goto exit; + } + +exit: + if (fw != NULL) + free(fw); + return rc; +} diff --git a/examples/firmware/ifx_fw_update.c b/examples/firmware/ifx_fw_update.c new file mode 100644 index 0000000..35d35bf --- /dev/null +++ b/examples/firmware/ifx_fw_update.c @@ -0,0 +1,235 @@ +/* ifx_fw_update.c + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfTPM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* This tool will perform a firmware update on Infineon SLB9672 or SLB9673 + * TPM 2.0 module */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFTPM_FIRMWARE_UPGRADE + +#include +#include +#include + +/******************************************************************************/ +/* --- BEGIN TPM2.0 Firmware Update tool -- */ +/******************************************************************************/ + +static void usage(void) +{ + printf("Infineon Firmware Update Usage:\n"); + printf("\t./ifx_fw_update (get info)\n"); + printf("\t./ifx_fw_update --abandon (cancel)\n"); + printf("\t./ifx_fw_update \n"); +} + +typedef struct { + byte* manifest_buf; + byte* firmware_buf; + size_t manifest_bufSz; + size_t firmware_bufSz; +} fw_info_t; + +static int TPM2_IFX_FwData_Cb(uint8_t* data, uint32_t data_req_sz, + uint32_t offset, void* cb_ctx) +{ + fw_info_t* fwinfo = (fw_info_t*)cb_ctx; + if (offset > fwinfo->firmware_bufSz) { + return BUFFER_E; + } + if (offset + data_req_sz > (uint32_t)fwinfo->firmware_bufSz) { + data_req_sz = (uint32_t)fwinfo->firmware_bufSz - offset; + } + if (data_req_sz > 0) { + XMEMCPY(data, &fwinfo->firmware_buf[offset], data_req_sz); + } + return data_req_sz; +} + +static const char* TPM2_IFX_GetOpModeStr(int opMode) +{ + const char* opModeStr = "Unknown"; + switch (opMode) { + case 0x00: + opModeStr = "Normal TPM operational mode"; + break; + case 0x01: + opModeStr = "TPM firmware update mode (abandon possible)"; + break; + case 0x02: + opModeStr = "TPM firmware update mode (abandon not possible)"; + break; + case 0x03: + opModeStr = "After successful update, but before finalize"; + break; + case 0x04: + opModeStr = "After finalize or abandon, reboot required"; + break; + default: + break; + } + return opModeStr; +} + +static int TPM2_IFX_PrintInfo(WOLFTPM2_DEV* dev) +{ + int rc; + WOLFTPM2_CAPS caps; + rc = wolfTPM2_GetCapabilities(dev, &caps); + if (rc == TPM_RC_SUCCESS) { + printf("Mfg %s (%d), Vendor %s, Fw %u.%u (0x%x)\n", + caps.mfgStr, caps.mfg, caps.vendorStr, caps.fwVerMajor, + caps.fwVerMinor, caps.fwVerVendor); + printf("Operational mode: %s (0x%x)\n", + TPM2_IFX_GetOpModeStr(caps.opMode), caps.opMode); + printf("KeyGroupId 0x%x, FwCounter %d (%d same)\n", + caps.keyGroupId, caps.fwCounter, caps.fwCounterSame); + if (caps.keyGroupId == 0) { + printf("Error getting key group id from TPM!\n"); + rc = -1; + } + } + return rc; +} + +int TPM2_IFX_Firmware_Update(void* userCtx, int argc, char *argv[]) +{ + int rc; + WOLFTPM2_DEV dev; + const char* manifest_file = NULL; + const char* firmware_file = NULL; + fw_info_t fwinfo; + int abandon = 0; + + XMEMSET(&fwinfo, 0, sizeof(fwinfo)); + + if (argc >= 2) { + if (XSTRCMP(argv[1], "-?") == 0 || + XSTRCMP(argv[1], "-h") == 0 || + XSTRCMP(argv[1], "--help") == 0) { + usage(); + return 0; + } + if (XSTRCMP(argv[1], "--abandon") == 0) { + abandon = 1; + } + else { + manifest_file = argv[1]; + if (argc >= 3) { + firmware_file = argv[2]; + } + } + } + + printf("Infineon Firmware Update Tool\n"); + if (manifest_file != NULL) + printf("\tManifest File: %s\n", manifest_file); + if (firmware_file != NULL) + printf("\tFirmware File: %s\n", firmware_file); + + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + + rc = TPM2_IFX_PrintInfo(&dev); + if (rc != 0) { + goto exit; + } + + if (abandon) { + printf("Firmware Update Abandon:\n"); + rc = wolfTPM2_FirmwareUpgradeCancel(&dev); + if (rc != 0) { + printf("Abandon failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + } + else { + printf("Success: Please reset or power cycle TPM\n"); + } + return rc; + } + + if (manifest_file == NULL || firmware_file == NULL) { + if (argc > 1) { + printf("Manifest file or firmware file arguments missing!\n"); + } + goto exit; + } + + /* load manifest and data files */ + rc = loadFile(manifest_file, + &fwinfo.manifest_buf, &fwinfo.manifest_bufSz); + if (rc == 0) { + rc = loadFile(firmware_file, + &fwinfo.firmware_buf, &fwinfo.firmware_bufSz); + } + if (rc == 0) { + rc = wolfTPM2_FirmwareUpgrade(&dev, + fwinfo.manifest_buf, (uint32_t)fwinfo.manifest_bufSz, + TPM2_IFX_FwData_Cb, &fwinfo); + } + if (rc == 0) { + rc = TPM2_IFX_PrintInfo(&dev); + } + +exit: + + if (rc != 0) { + printf("Infineon firmware update failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); + } + + XFREE(fwinfo.firmware_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(fwinfo.manifest_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfTPM2_Cleanup(&dev); + + return rc; +} + +/******************************************************************************/ +/* --- END TPM2.0 Firmware Update tool -- */ +/******************************************************************************/ + +#endif /* WOLFTPM_FIRMWARE_UPGRADE */ + +#ifndef NO_MAIN_DRIVER +int main(int argc, char *argv[]) +{ + int rc = -1; + +#ifdef WOLFTPM_FIRMWARE_UPGRADE + rc = TPM2_IFX_Firmware_Update(NULL, argc, argv); +#else + printf("Support for firmware upgrade not compiled in! " + "See --enable-firmware or WOLFTPM_FIRMWARE_UPGRADE\n"); + (void)argc; + (void)argv; +#endif /* WOLFTPM_FIRMWARE_UPGRADE */ + + return rc; +} +#endif diff --git a/examples/firmware/ifx_fw_update.h b/examples/firmware/ifx_fw_update.h new file mode 100644 index 0000000..34d9fa5 --- /dev/null +++ b/examples/firmware/ifx_fw_update.h @@ -0,0 +1,35 @@ +/* ifx_firmware_update.h + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfTPM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef _IFX_FIRMWARE_H_ +#define _IFX_FIRMWARE_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +int TPM2_IFX_Firmware_Update(void* userCtx, int argc, char *argv[]); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _IFX_FIRMWARE_H_ */ diff --git a/examples/firmware/include.am b/examples/firmware/include.am new file mode 100644 index 0000000..f233fe4 --- /dev/null +++ b/examples/firmware/include.am @@ -0,0 +1,24 @@ +# vim:ft=automake +# All paths should be given relative to the root + +EXTRA_DIST += examples/firmware/README.md +EXTRA_DIST += examples/firmware/Makefile + +# Host side tool for extracting the firmware manifest and data +EXTRA_DIST += examples/firmware/ifx_fw_extract.c + +if BUILD_EXAMPLES +if BUILD_INFINEON +noinst_PROGRAMS += examples/firmware/ifx_fw_update +noinst_HEADERS += examples/firmware/ifx_fw_update.h +examples_firmware_ifx_fw_update_SOURCES = examples/firmware/ifx_fw_update.c \ + examples/tpm_test_keys.c +examples_firmware_ifx_fw_update_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_firmware_ifx_fw_update_DEPENDENCIES = src/libwolftpm.la +endif +endif + +example_firmwaredir = $(exampledir)/firmware +dist_example_firmware_DATA = examples/firmware/ifx_fw_update.c + +DISTCLEANFILES+= examples/firmware/.libs/ifx_fw_update diff --git a/examples/include.am b/examples/include.am index 421fa33..2599321 100644 --- a/examples/include.am +++ b/examples/include.am @@ -16,6 +16,7 @@ include examples/nvram/include.am include examples/gpio/include.am include examples/seal/include.am include examples/attestation/include.am +include examples/firmware/include.am if BUILD_EXAMPLES EXTRA_DIST += examples/run_examples.sh diff --git a/examples/wrap/wrap_test.c b/examples/wrap/wrap_test.c index 4504a61..ddf8377 100644 --- a/examples/wrap/wrap_test.c +++ b/examples/wrap/wrap_test.c @@ -198,6 +198,10 @@ int TPM2_Wrapper_TestArgs(void* userCtx, int argc, char *argv[]) "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) + printf("\tKeyGroupId 0x%x, Operational Mode 0x%x, FwCounter %d (%d same)\n", + caps.keyGroupId, caps.opMode, caps.fwCounter, caps.fwCounterSame); +#endif /* List the active persistent handles */ rc = wolfTPM2_GetHandles(PERSISTENT_FIRST, NULL); diff --git a/hal/tpm_io.c b/hal/tpm_io.c index d6faba1..f132430 100644 --- a/hal/tpm_io.c +++ b/hal/tpm_io.c @@ -65,7 +65,7 @@ #include "hal/tpm_io_qnx.c" #elif defined(__XILINX__) #include "hal/tpm_io_xilinx.c" -#elif defined(WOLFTPM_INFINEON_TRICORE) +#elif defined(WOLFTPM_INFINEON_TRICORE) || defined(CY_USING_HAL) #include "hal/tpm_io_infineon.c" #elif defined(WOLFTPM_MICROCHIP_HARMONY) #include "hal/tpm_io_microchip.c" @@ -89,6 +89,8 @@ static int TPM2_IoCb_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, ret = TPM2_IoCb_QNX_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); #elif defined(__XILINX__) ret = TPM2_IoCb_Xilinx_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); +#elif defined(CY_USING_HAL) + ret = TPM2_IoCb_Infineon_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); #elif defined(WOLFTPM_INFINEON_TRICORE) ret = TPM2_IoCb_Infineon_TriCore_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); #elif defined(WOLFTPM_MICROCHIP_HARMONY) @@ -140,6 +142,8 @@ int TPM2_IoCb(TPM2_CTX* ctx, INT32 isRead, UINT32 addr, #elif defined(WOLFSSL_STM32_CUBEMX) /* Use STM32 CubeMX HAL for I2C */ ret = TPM2_IoCb_STCubeMX_I2C(ctx, isRead, addr, buf, size, userCtx); + #elif defined(CY_USING_HAL) + ret = TPM2_IoCb_Infineon_I2C(ctx, isRead, addr, buf, size, userCtx); #else /* TODO: Add your platform here for HW I2C interface */ printf("Add your platform here for HW I2C interface\n"); diff --git a/hal/tpm_io.h b/hal/tpm_io.h index 402412b..371782a 100644 --- a/hal/tpm_io.h +++ b/hal/tpm_io.h @@ -82,6 +82,9 @@ WOLFTPM_LOCAL int TPM2_IoCb_Linux_I2C(TPM2_CTX* ctx, int isRead, word32 addr, by #elif defined(WOLFSSL_STM32_CUBEMX) WOLFTPM_LOCAL int TPM2_IoCb_STCubeMX_I2C(TPM2_CTX* ctx, int isRead, word32 addr, byte* buf, word16 size, void* userCtx); +#elif defined(CY_USING_HAL) +WOLFTPM_LOCAL int TPM2_IoCb_Infineon_I2C(TPM2_CTX* ctx, int isRead, word32 addr, + byte* buf, word16 size, void* userCtx); #endif /* __linux__ */ #else /* SPI */ @@ -104,6 +107,9 @@ WOLFTPM_LOCAL int TPM2_IoCb_QNX_SPI(TPM2_CTX* ctx, const byte* txBuf, #elif defined(__XILINX__) WOLFTPM_LOCAL int TPM2_IoCb_Xilinx_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, word16 xferSz, void* userCtx); +#elif defined(CY_USING_HAL) +WOLFTPM_LOCAL int TPM2_IoCb_Infineon_SPI(TPM2_CTX* ctx, const byte* txBuf, + byte* rxBuf, word16 xferSz, void* userCtx); #elif defined(WOLFTPM_INFINEON_TRICORE) WOLFTPM_LOCAL int TPM2_IoCb_Infineon_TriCore_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, word16 xferSz, void* userCtx); diff --git a/hal/tpm_io_infineon.c b/hal/tpm_io_infineon.c index 04bca15..6baa687 100644 --- a/hal/tpm_io_infineon.c +++ b/hal/tpm_io_infineon.c @@ -1,6 +1,6 @@ /* tpm_io_infineon.c * - * Copyright (C) 2006-2022 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfTPM. * @@ -19,7 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -/* This example shows IO interfaces for Infineon TriCore hardware: +/* This example shows IO interfaces for Infineon CyHal or TriCore hardware: + * - PSoC6 CyHal set automatically with `CY_USING_HAL`. * - TC2XX/TC3XX using macro: `WOLFTPM_INFINEON_TRICORE`. */ @@ -42,12 +43,131 @@ defined(WOLFTPM_SWTPM) || \ defined(WOLFTPM_WINAPI) ) -/* Use the max speed by default - see tpm2_types.h for chip specific max values */ -#ifndef TPM2_SPI_HZ - #define TPM2_SPI_HZ TPM2_SPI_MAX_HZ -#endif +#ifdef WOLFTPM_I2C + #ifndef TPM_I2C_TRIES + #define TPM_I2C_TRIES 10 + #endif + #ifndef TPM2_I2C_ADDR + #define TPM2_I2C_ADDR 0x2e + #endif -#if defined(WOLFTPM_INFINEON_TRICORE) + #if defined(CY_USING_HAL) + #include "cyhal_i2c.h" + + static int tpm_ifx_i2c_read(void* userCtx, word32 reg, byte* data, int len) + { + int ret = TPM_RC_FAILURE; + cy_rslt_t result; + cyhal_i2c_t* i2c = (cyhal_i2c_t*)userCtx; + int timeout = TPM_I2C_TRIES; + byte buf[1]; + + /* TIS layer should never provide a buffer larger than this, + * but double check for good coding practice */ + if (i2c == NULL || len > MAX_SPI_FRAMESIZE) + return BAD_FUNC_ARG; + + buf[0] = (reg & 0xFF); /* convert to simple 8-bit address for I2C */ + + /* The I2C takes about 80us to wake up and will NAK until it is ready */ + do { + /* Write address to read from - retry until ack */ + result = cyhal_i2c_master_write(i2c, TPM2_I2C_ADDR, buf, sizeof(buf), + 0, true); + /* for read we always need this guard time (success wake or real read) */ + XSLEEP_MS(1); /* guard time - should be 250us */ + } while (result != CY_RSLT_SUCCESS && --timeout > 0); + + if (result == CY_RSLT_SUCCESS) { + timeout = TPM_I2C_TRIES; + do { + result = cyhal_i2c_master_read(i2c, TPM2_I2C_ADDR, data, len, + 0, true); + if (result != CY_RSLT_SUCCESS) { + XSLEEP_MS(1); /* guard time - should be 250us */ + } + } while (result != CY_RSLT_SUCCESS && --timeout > 0); + } + if (result == CY_RSLT_SUCCESS) { + ret = TPM_RC_SUCCESS; + } + else { + printf("CyHAL I2C Read failure %d (tries %d)\n", + (int)result, TPM_I2C_TRIES - timeout); + } + return ret; + } + + static int tpm_ifx_i2c_write(void* userCtx, word32 reg, byte* data, int len) + { + int ret = TPM_RC_FAILURE; + cy_rslt_t result; + cyhal_i2c_t* i2c = (cyhal_i2c_t*)userCtx; + int timeout = TPM_I2C_TRIES; + byte buf[MAX_SPI_FRAMESIZE+1]; + + /* TIS layer should never provide a buffer larger than this, + * but double check for good coding practice */ + if (i2c == NULL || len > MAX_SPI_FRAMESIZE) + return BAD_FUNC_ARG; + + /* Build packet with TPM register and data */ + buf[0] = (reg & 0xFF); /* convert to simple 8-bit address for I2C */ + XMEMCPY(buf + 1, data, len); + + /* The I2C takes about 80us to wake up and will NAK until it is ready */ + do { + result = cyhal_i2c_master_write(i2c, TPM2_I2C_ADDR, buf, len+1, + 0, true); + if (result != CY_RSLT_SUCCESS) { + XSLEEP_MS(1); /* guard time - should be 250us */ + } + } while (result != CY_RSLT_SUCCESS && --timeout > 0); + if (result == CY_RSLT_SUCCESS) { + ret = TPM_RC_SUCCESS; + } + else { + printf("CyHAL I2C Write failure %d\n", (int)result); + } + return ret; + } + + int TPM2_IoCb_Infineon_I2C(TPM2_CTX* ctx, int isRead, word32 addr, + byte* buf, word16 size, void* userCtx) + { + int ret = TPM_RC_FAILURE; + if (userCtx != NULL) { + if (isRead) + ret = tpm_ifx_i2c_read(userCtx, addr, buf, size); + else + ret = tpm_ifx_i2c_write(userCtx, addr, buf, size); + } + (void)ctx; + return ret; + } + + #else + #error Infineon I2C support on this platform not supported yet + #endif /* CY_USING_HAL or WOLFTPM_INFINEON_TRICORE */ + +#else /* SPI */ + + #ifndef TPM2_SPI_HZ + /* Use the max speed by default + * See tpm2_types.h for chip specific max values */ + #define TPM2_SPI_HZ TPM2_SPI_MAX_HZ + #endif + #ifdef WOLFTPM_CHECK_WAIT_STATE + #error SPI check wait state logic not supported + #endif + + #if defined(CY_USING_HAL) + int TPM2_IoCb_Infineon_SPI(TPM2_CTX* ctx, const byte* txBuf, + byte* rxBuf, word16 xferSz, void* userCtx) + { + + } + #elif defined(WOLFTPM_INFINEON_TRICORE) #include #include @@ -60,10 +180,6 @@ { int ret = TPM_RC_FAILURE; - #ifdef WOLFTPM_CHECK_WAIT_STATE - #error SPI check wait state logic not supported - #endif - /* wait for SPI not busy */ while (IfxQspi_SpiMaster_getStatus(&spiMasterChannel) == SpiIf_Status_busy) {}; @@ -79,8 +195,11 @@ return ret; } + #else + #error Infineon I2C support on this platform not supported yet + #endif /* CY_USING_HAL or WOLFTPM_INFINEON_TRICORE */ +#endif /* SPI or I2C */ -#endif /* WOLFTPM_INFINEON_TRICORE */ #endif /* !(WOLFTPM_LINUX_DEV || WOLFTPM_SWTPM || WOLFTPM_WINAPI) */ #endif /* WOLFTPM_INCLUDE_IO_FILE */ diff --git a/hal/tpm_io_linux.c b/hal/tpm_io_linux.c index 193498d..8e340c6 100644 --- a/hal/tpm_io_linux.c +++ b/hal/tpm_io_linux.c @@ -65,7 +65,7 @@ #include #ifdef WOLFTPM_I2C - /* I2C - (Only tested with ST33HTPH I2C) */ + /* I2C - (Only tested with SLB9673 and ST33 I2C) */ #define TPM2_I2C_ADDR 0x2e #define TPM2_I2C_DEV "/dev/i2c-1" #define TPM2_I2C_HZ 400000 /* 400kHz */ diff --git a/src/tpm2.c b/src/tpm2.c index 883fea7..89f6b13 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -575,7 +575,7 @@ TPM_RC TPM2_SetHalIoCb(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx) } /* If timeoutTries <= 0 then it will not try and startup chip and will - use existing default locality */ + * use existing default locality */ TPM_RC TPM2_Init_ex(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx, int timeoutTries) { @@ -870,6 +870,20 @@ TPM_RC TPM2_GetCapability(GetCapability_In* in, GetCapability_Out* out) } break; } + case TPM_CAP_VENDOR_PROPERTY: + { + out->capabilityData.data.vendor.size = + packet.size - packet.pos; + if (out->capabilityData.data.vendor.size > + sizeof(out->capabilityData.data.vendor.buffer)) { + out->capabilityData.data.vendor.size = + sizeof(out->capabilityData.data.vendor.buffer); + } + TPM2_Packet_ParseBytes(&packet, + out->capabilityData.data.vendor.buffer, + out->capabilityData.data.vendor.size); + break; + } default: #ifdef DEBUG_WOLFTPM printf("Unknown capability type 0x%x\n", @@ -5394,6 +5408,63 @@ int TPM2_NTC2_GetConfig(NTC2_GetConfig_Out* out) return rc; } #endif /* WOLFTPM_NUVOTON */ + + +#ifdef WOLFTPM_FIRMWARE_UPGRADE +#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673) +int TPM2_IFX_FieldUpgradeStart(TPM_HANDLE sessionHandle, + uint8_t* data, uint32_t size) +{ + int rc; + TPM2_CTX* ctx = TPM2_GetActiveCtx(); + TPMS_AUTH_COMMAND session; + + rc = TPM2_AcquireLock(ctx); + if (rc == TPM_RC_SUCCESS) { + TPM2_Packet packet; + int tmpSz = 0; + TPM2_Packet_Init(ctx, &packet); + TPM2_Packet_AppendU32(&packet, TPM_RH_PLATFORM); + + XMEMSET(&session, 0, sizeof(session)); + session.sessionHandle = sessionHandle; + + TPM2_Packet_MarkU32(&packet, &tmpSz); + TPM2_Packet_AppendAuthCmd(&packet, &session); + TPM2_Packet_PlaceU32(&packet, tmpSz); + + TPM2_Packet_AppendBytes(&packet, data, size); + + TPM2_Packet_Finalize(&packet, TPM_ST_SESSIONS, + TPM_CC_FieldUpgradeStartVendor); + + rc = TPM2_SendCommand(ctx, &packet); + + TPM2_ReleaseLock(ctx); + } + return rc; +} +int TPM2_IFX_FieldUpgradeCommand(TPM_CC cc, uint8_t* data, uint32_t size) +{ + int rc; + TPM2_CTX* ctx = TPM2_GetActiveCtx(); + + rc = TPM2_AcquireLock(ctx); + if (rc == TPM_RC_SUCCESS) { + TPM2_Packet packet; + TPM2_Packet_Init(ctx, &packet); + TPM2_Packet_AppendBytes(&packet, data, size); + TPM2_Packet_Finalize(&packet, TPM_ST_NO_SESSIONS, cc); + rc = TPM2_SendCommand(ctx, &packet); + TPM2_ReleaseLock(ctx); + } + return rc; +} + + +#endif /* WOLFTPM_SLB9672 || WOLFTPM_SLB9673 */ +#endif /* WOLFTPM_FIRMWARE_UPGRADE */ + /******************************************************************************/ /* --- END Manufacture Specific TPM API's -- */ /******************************************************************************/ diff --git a/src/tpm2_packet.c b/src/tpm2_packet.c index 0cb830e..e7f687f 100644 --- a/src/tpm2_packet.c +++ b/src/tpm2_packet.c @@ -25,23 +25,6 @@ #include -/* Endianess Helpers */ -#ifdef LITTLE_ENDIAN_ORDER - #define cpu_to_be16(d) ByteReverseWord16(d) - #define cpu_to_be32(d) ByteReverseWord32(d) - #define cpu_to_be64(d) ByteReverseWord64(d) - #define be16_to_cpu(d) ByteReverseWord16(d) - #define be32_to_cpu(d) ByteReverseWord32(d) - #define be64_to_cpu(d) ByteReverseWord64(d) -#else - #define cpu_to_be16(d) (d) - #define cpu_to_be32(d) (d) - #define cpu_to_be64(d) (d) - #define be16_to_cpu(d) (d) - #define be32_to_cpu(d) (d) - #define be64_to_cpu(d) (d) -#endif - /* convert 16 bit integer to opaque */ static inline void c16toa(word16 wc_u16, byte* c) { diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index ce9e398..2996367 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -619,6 +619,15 @@ int wolfTPM2_SelfTest(WOLFTPM2_DEV* dev) * TPM_PT_MODES = Bit 0 = FIPS_140_2 */ +#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673) + /* Infineon SLB9672 or SLB9673 Firmware Upgrade support */ + #define TPM_PT_VENDOR_FIX 0x80000000 + #define TPM_PT_VENDOR_FIX_FU_COUNTER (TPM_PT_VENDOR_FIX + 3) + #define TPM_PT_VENDOR_FIX_FU_COUNTER_SAME (TPM_PT_VENDOR_FIX + 4) + #define TPM_PT_VENDOR_FIX_FU_OPERATION_MODE (TPM_PT_VENDOR_FIX + 7) + #define TPM_PT_VENDOR_FIX_FU_KEYGROUP_ID (TPM_PT_VENDOR_FIX + 8) +#endif + /* ST33TP * TPM_PT_MANUFACTURER 0x53544D20: "STM" * TPM_PT_FIRMWARE_VERSION_1 TPM FW version: 0x00006400 @@ -698,6 +707,44 @@ static int wolfTPM2_ParseCapabilities(WOLFTPM2_CAPS* caps, return rc; } +#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673) +static int tpm2_ifx_cap_vendor_get(WOLFTPM2_CAPS* cap, uint32_t property, + uint8_t* val, size_t valSz) +{ + int rc; + GetCapability_In in; + GetCapability_Out out; + + XMEMSET(&in, 0, sizeof(in)); + XMEMSET(&out, 0, sizeof(out)); + in.capability = TPM_CAP_VENDOR_PROPERTY; + in.property = property; + in.propertyCount = 1; + rc = TPM2_GetCapability(&in, &out); + if (rc == TPM_RC_SUCCESS) { + TPM2B_MAX_BUFFER* buf = &out.capabilityData.data.vendor; + /* 4 bytes=count + 2 bytes=len + vendor value */ + if (buf->buffer[3] == 1 && buf->buffer[5] == valSz) { + XMEMCPY(val, &buf->buffer[6], valSz); + if (valSz == 2) { + *((uint16_t*)val) = be16_to_cpu(*((uint16_t*)val)); + } + else if (valSz == 4) { + *((uint32_t*)val) = be32_to_cpu(*((uint32_t*)val)); + } + } + } + else { + #ifdef DEBUG_WOLFTPM + printf("TPM2_GetCapability vendor prop 0x%x failed 0x%x: %s\n", + property, rc, TPM2_GetRCString(rc)); + #endif + } + (void)cap; + return rc; +} +#endif + static int wolfTPM2_GetCapabilities_NoDev(WOLFTPM2_CAPS* cap) { int rc; @@ -712,14 +759,15 @@ static int wolfTPM2_GetCapabilities_NoDev(WOLFTPM2_CAPS* cap) /* Get Capabilities TPM_PT_MANUFACTURER thru TPM_PT_FIRMWARE_VERSION_2 */ XMEMSET(&in, 0, sizeof(in)); + XMEMSET(&out, 0, sizeof(out)); in.capability = TPM_CAP_TPM_PROPERTIES; in.property = TPM_PT_MANUFACTURER; in.propertyCount = 8; rc = TPM2_GetCapability(&in, &out); if (rc != TPM_RC_SUCCESS) { #ifdef DEBUG_WOLFTPM - printf("TPM2_GetCapability failed 0x%x: %s\n", rc, - TPM2_GetRCString(rc)); + printf("TPM2_GetCapability manufacture failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); #endif return rc; } @@ -729,19 +777,40 @@ static int wolfTPM2_GetCapabilities_NoDev(WOLFTPM2_CAPS* cap) /* Get Capability TPM_PT_MODES */ XMEMSET(&in, 0, sizeof(in)); + XMEMSET(&out, 0, sizeof(out)); in.capability = TPM_CAP_TPM_PROPERTIES; in.property = TPM_PT_MODES; in.propertyCount = 1; rc = TPM2_GetCapability(&in, &out); if (rc != TPM_RC_SUCCESS) { #ifdef DEBUG_WOLFTPM - printf("TPM2_GetCapability failed 0x%x: %s\n", rc, - TPM2_GetRCString(rc)); + printf("TPM2_GetCapability modes failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); #endif return rc; } rc = wolfTPM2_ParseCapabilities(cap, &out.capabilityData.data.tpmProperties); +#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673) + /* Get vendor specific information */ + if (rc == 0) { + rc = tpm2_ifx_cap_vendor_get(cap, TPM_PT_VENDOR_FIX_FU_OPERATION_MODE, + &cap->opMode, sizeof(cap->opMode)); + } + if (rc == 0) { + rc = tpm2_ifx_cap_vendor_get(cap, TPM_PT_VENDOR_FIX_FU_KEYGROUP_ID, + (uint8_t*)&cap->keyGroupId, sizeof(cap->keyGroupId)); + } + if (rc == 0) { + rc = tpm2_ifx_cap_vendor_get(cap, TPM_PT_VENDOR_FIX_FU_COUNTER, + (uint8_t*)&cap->fwCounter, sizeof(cap->fwCounter)); + } + if (rc == 0) { + rc = tpm2_ifx_cap_vendor_get(cap, TPM_PT_VENDOR_FIX_FU_COUNTER_SAME, + (uint8_t*)&cap->fwCounterSame, sizeof(cap->fwCounterSame)); + } +#endif + return rc; } @@ -1144,7 +1213,7 @@ static int wolfTPM2_EncryptSecret_ECC(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* tpm TPM2B_ECC_POINT pubPoint, secretPoint; ecc_point r[1]; mp_int prime, a; - word32 keySz; + word32 keySz = 0; publicArea = &tpmKey->pub.publicArea; XMEMSET(&rng, 0, sizeof(rng)); @@ -4454,7 +4523,7 @@ int wolfTPM2_NVReadCert(WOLFTPM2_DEV* dev, TPM_HANDLE handle, /* Perform read of NV without auth password */ nv.handle.hndl = handle; - rc = wolfTPM2_NVReadAuth(dev, &nv, handle, buffer, len, 0); + rc = wolfTPM2_NVReadAuth(dev, &nv, handle, buffer, (word32*)len, 0); return rc; } @@ -7123,4 +7192,323 @@ int wolfTPM2_SetIdentityAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* handle, + +/******************************************************************************/ +/* --- BEGIN Firmware Upgrade Support -- */ +/******************************************************************************/ + +#ifdef WOLFTPM_FIRMWARE_UPGRADE +#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673) + +/* Maximum size of firmware chunks */ +#define IFX_FW_MAX_CHUNK_SZ 1024 + +/* Setup the policy to enable firmware upgrade start */ +static int tpm2_ifx_firmware_enable_policy(WOLFTPM2_DEV* dev) +{ + int rc; + PolicyCommandCode_In policyCC; + SetPrimaryPolicy_In policy; + WOLFTPM2_SESSION tpmSession; + + XMEMSET(&tpmSession, 0, sizeof(tpmSession)); + XMEMSET(&policyCC, 0, sizeof(policyCC)); + XMEMSET(&policy, 0, sizeof(policy)); + + rc = wolfTPM2_StartSession(dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, TPM_ALG_NULL); + if (rc == TPM_RC_SUCCESS) { + policyCC.policySession = tpmSession.handle.hndl; + policyCC.code = TPM_CC_FieldUpgradeStartVendor; + rc = TPM2_PolicyCommandCode(&policyCC); + if (rc == TPM_RC_SUCCESS) { + word32 policySz = (word32)sizeof(policy.authPolicy.buffer); + rc = wolfTPM2_GetPolicyDigest(dev, tpmSession.handle.hndl, + policy.authPolicy.buffer, &policySz); + policy.authPolicy.size = policySz; + } + wolfTPM2_UnloadHandle(dev, &tpmSession.handle); + } + if (rc == TPM_RC_SUCCESS) { + policy.authHandle = TPM_RH_PLATFORM; + policy.hashAlg = TPM_ALG_SHA256; + rc = TPM2_SetPrimaryPolicy(&policy); + } + +#ifdef DEBUG_WOLFTPM + if (rc != TPM_RC_SUCCESS) { + printf("Enable firmware start policy failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); + } +#endif + return rc; +} + +static int tpm2_ifx_firmware_start(WOLFTPM2_DEV* dev, TPM_ALG_ID hashAlg, + uint8_t* manifest_hash, uint32_t manifest_hash_sz) +{ + int rc; + WOLFTPM2_SESSION tpmSession; + PolicyCommandCode_In policyCC; + + XMEMSET(&tpmSession, 0, sizeof(tpmSession)); + XMEMSET(&policyCC, 0, sizeof(policyCC)); + + rc = wolfTPM2_StartSession(dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, TPM_ALG_NULL); + if (rc == TPM_RC_SUCCESS) { + policyCC.policySession = tpmSession.handle.hndl; + policyCC.code = TPM_CC_FieldUpgradeStartVendor; + rc = TPM2_PolicyCommandCode(&policyCC); + if (rc == TPM_RC_SUCCESS) { + /* build command for manifest header */ + uint16_t val16; + /* max cmd: type (1) + data sz (2) + hash alg (2) + max digest (64) */ + uint8_t cmd[1 + 2 + 2 + TPM_SHA512_DIGEST_SIZE]; + cmd[0] = 0x01; /* type */ + val16 = be16_to_cpu(manifest_hash_sz + 2); + XMEMCPY(&cmd[1], &val16, sizeof(val16)); /* data size */ + val16 = be16_to_cpu(hashAlg); + XMEMCPY(&cmd[3], &val16, sizeof(val16)); /* hash algorithm */ + XMEMCPY(&cmd[5], manifest_hash, manifest_hash_sz); + + rc = TPM2_IFX_FieldUpgradeStart(tpmSession.handle.hndl, + cmd, 1 + 2 + 2 + manifest_hash_sz); + } + if (rc == TPM_RC_SUCCESS) { + /* delay to give the TPM time to switch modes */ + XSLEEP_MS(300); + /* it is not required to release session handle, + * since TPM reset into firmware upgrade mode */ + + #if !defined(WOLFTPM_LINUX_DEV) && !defined(WOLFTPM_SWTPM) && \ + !defined(WOLFTPM_WINAPI) + /* Do chip startup and request locality again */ + rc = TPM2_ChipStartup(&dev->ctx, 10); + #endif + } + else { + wolfTPM2_UnloadHandle(dev, &tpmSession.handle); + } + } +#ifdef DEBUG_WOLFTPM + if (rc != TPM_RC_SUCCESS) { + printf("Firmware upgrade start failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); + } +#endif + return rc; +} + +static int tpm2_ifx_firmware_manifest(WOLFTPM2_DEV* dev, + uint8_t* manifest, uint32_t manifest_sz) +{ + int rc = TPM_RC_FAILURE; + uint32_t offset, chunk_sz; + uint8_t state; /* 1=start, 2=more, 0=done */ + + (void)dev; + for (offset = 0; offset < manifest_sz; offset += chunk_sz) { + /* max cmd: type (1) + chunk sz (2) + max chunk (1024) */ + uint8_t cmd[1 + 2 + IFX_FW_MAX_CHUNK_SZ]; + uint16_t val16; + + chunk_sz = manifest_sz - offset; + if (chunk_sz > IFX_FW_MAX_CHUNK_SZ) { + chunk_sz = IFX_FW_MAX_CHUNK_SZ; + state = (offset == 0) ? 1 : 2; + } + else { + state = 0; + } + #ifdef DEBUG_WOLFTPM + printf("Firmware manifest chunk %u offset (%u / %u), state %d\n", + chunk_sz, offset, manifest_sz, state); + #endif + + cmd[0] = state; + val16 = be16_to_cpu(chunk_sz); + XMEMCPY(&cmd[1], &val16, sizeof(val16)); /* chunk size */ + XMEMCPY(&cmd[3], &manifest[offset], chunk_sz); + + rc = TPM2_IFX_FieldUpgradeCommand(TPM_CC_FieldUpgradeManifestVendor, + cmd, 1 + 2 + chunk_sz); + if (rc != TPM_RC_SUCCESS) { + break; + } + } +#ifdef DEBUG_WOLFTPM + if (rc != TPM_RC_SUCCESS) { + printf("Firmware upgrade manifest failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); + } +#endif + return rc; +} + +static int tpm2_ifx_firmware_data(WOLFTPM2_DEV* dev, + wolfTPM2FwDataCb cb, void* cb_ctx) +{ + int rc; + uint32_t offset, chunk_sz; + uint8_t cmd[2 + IFX_FW_MAX_CHUNK_SZ]; + uint16_t val16; + + (void)dev; + for (offset = 0; ; offset += chunk_sz) { + XMEMSET(cmd, 0, sizeof(cmd)); + + /* get chunk */ + rc = cb(&cmd[2], IFX_FW_MAX_CHUNK_SZ, offset, cb_ctx); + if (rc > 0 && rc <= IFX_FW_MAX_CHUNK_SZ) { + chunk_sz = rc; + rc = 0; + } + else if (rc == 0) { + #ifdef DEBUG_WOLFTPM + printf("Firmware data done\n"); + #endif + break; + } + else { + #ifdef DEBUG_WOLFTPM + printf("Firmware data callback error! %d\n", rc); + #endif + break; + } + + #ifdef DEBUG_WOLFTPM + printf("Firmware data chunk offset %u\n", offset); + #endif + + val16 = be16_to_cpu(chunk_sz); + XMEMCPY(&cmd[0], &val16, sizeof(val16)); /* chunk size */ + + rc = TPM2_IFX_FieldUpgradeCommand(TPM_CC_FieldUpgradeDataVendor, + cmd, 2 + chunk_sz); + if (rc != TPM_RC_SUCCESS) { + break; + } + } + + if (rc == TPM_RC_SUCCESS) { + /* Give the TPM time to start the new firmware */ + XSLEEP_MS(300); + + #if !defined(WOLFTPM_LINUX_DEV) && !defined(WOLFTPM_SWTPM) && \ + !defined(WOLFTPM_WINAPI) + /* Do chip startup and request locality again */ + rc = TPM2_ChipStartup(&dev->ctx, 10); + #endif + } +#ifdef DEBUG_WOLFTPM + else { + printf("Firmware upgrade data failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); + } +#endif + return rc; +} + +static int tpm2_ifx_firmware_final(WOLFTPM2_DEV* dev) +{ + int rc; + uint8_t cmd[2]; + uint16_t val16; + + (void)dev; + + val16 = 0; + XMEMCPY(&cmd[0], &val16, sizeof(val16)); /* data size */ + + rc = TPM2_IFX_FieldUpgradeCommand(TPM_CC_FieldUpgradeFinalizeVendor, + cmd, sizeof(cmd)); +#ifdef DEBUG_WOLFTPM + if (rc != TPM_RC_SUCCESS) { + printf("Firmware finalize failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); + } +#endif + return rc; +} + +int wolfTPM2_FirmwareUpgrade(WOLFTPM2_DEV* dev, + uint8_t* manifest, uint32_t manifest_sz, + wolfTPM2FwDataCb cb, void* cb_ctx) +{ + int rc; + WOLFTPM2_CAPS caps; + TPM_ALG_ID hashAlg; + uint8_t manifest_hash[TPM_SHA384_DIGEST_SIZE]; + uint32_t manifest_hash_sz = (uint32_t)sizeof(manifest_hash); + + /* check the operational mode */ + rc = wolfTPM2_GetCapabilities(dev, &caps); + if (rc == TPM_RC_SUCCESS) { + if (caps.opMode == 0x03) { + /* firmware update is done, just needs finalized and TPM reset */ + #ifdef DEBUG_WOLFTPM + printf("Firmware update done, finalizing\n"); + #endif + return tpm2_ifx_firmware_final(dev); + } + } + + /* hash the manifest */ + hashAlg = TPM_ALG_SHA384; /* use SHA2-384 or SHA2-512 for manifest hash */ + rc = wc_Sha384Hash(manifest, manifest_sz, manifest_hash); + if (rc == TPM_RC_SUCCESS) { + rc = tpm2_ifx_firmware_enable_policy(dev); + } + if (rc == TPM_RC_SUCCESS) { + rc = tpm2_ifx_firmware_start(dev, hashAlg, manifest_hash, manifest_hash_sz); + } + if (rc == TPM_RC_SUCCESS) { + rc = tpm2_ifx_firmware_manifest(dev, manifest, manifest_sz); + } + if (rc == TPM_RC_SUCCESS) { + rc = tpm2_ifx_firmware_data(dev, cb, cb_ctx); + } + if (rc == TPM_RC_SUCCESS) { + rc = tpm2_ifx_firmware_final(dev); + } +#ifdef DEBUG_WOLFTPM + if (rc != TPM_RC_SUCCESS) { + printf("Firmware update failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); + } +#endif + return rc; +} + +/* terminate a firmware update */ +int wolfTPM2_FirmwareUpgradeCancel(WOLFTPM2_DEV* dev) +{ + int rc; + uint8_t cmd[2]; + uint16_t val16; + + (void)dev; + + val16 = 0; /* data size */ + XMEMCPY(&cmd[0], &val16, sizeof(val16)); + + rc = TPM2_IFX_FieldUpgradeCommand(TPM_CC_FieldUpgradeAbandonVendor, + cmd, sizeof(cmd)); +#ifdef DEBUG_WOLFTPM + if (rc != TPM_RC_SUCCESS) { + printf("Firmware abandon failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); + } +#endif + return rc; +} + +#endif /* WOLFTPM_SLB9672 || WOLFTPM_SLB9673 */ +#endif /* WOLFTPM_FIRMWARE_UPGRADE */ + +/******************************************************************************/ +/* --- END Firmware Upgrade Support -- */ +/******************************************************************************/ + #endif /* !WOLFTPM2_NO_WRAPPER */ diff --git a/wolftpm/tpm2.h b/wolftpm/tpm2.h index 39389ae..5dd01cd 100644 --- a/wolftpm/tpm2.h +++ b/wolftpm/tpm2.h @@ -261,6 +261,13 @@ typedef enum { TPM_CC_NTC2_PreConfig = CC_VEND + 0x0211, TPM_CC_NTC2_GetConfig = CC_VEND + 0x0213, #endif +#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673) + TPM_CC_FieldUpgradeStartVendor = CC_VEND + 0x12F, + TPM_CC_FieldUpgradeAbandonVendor = CC_VEND + 0x130, + TPM_CC_FieldUpgradeManifestVendor = CC_VEND + 0x131, + TPM_CC_FieldUpgradeDataVendor = CC_VEND + 0x132, + TPM_CC_FieldUpgradeFinalizeVendor = CC_VEND + 0x133, +#endif } TPM_CC_T; typedef UINT32 TPM_CC; @@ -1017,6 +1024,7 @@ typedef union TPMU_CAPABILITIES { TPML_TAGGED_PCR_PROPERTY pcrProperties; /* TPM_CAP_PCR_PROPERTIES */ TPML_ECC_CURVE eccCurves; /* TPM_CAP_ECC_CURVES */ TPML_TAGGED_POLICY authPolicies; /* TPM_CAP_AUTH_POLICIES */ + TPM2B_MAX_BUFFER vendor; } TPMU_CAPABILITIES; typedef struct TPMS_CAPABILITY_DATA { @@ -2823,7 +2831,20 @@ WOLFTPM_API TPM_RC TPM2_NV_Certify(NV_Certify_In* in, NV_Certify_Out* out); WOLFTPM_API TPM_RC TPM2_GetRandom2(GetRandom2_In* in, GetRandom2_Out* out); WOLFTPM_API TPM_RC TPM2_GetProductInfo(uint8_t* info, uint16_t size); -#endif +#endif /* ST33 Vendor Specific */ + + +#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673) || \ + defined(WOLFTPM_AUTODETECT) + +#ifdef WOLFTPM_FIRMWARE_UPGRADE +WOLFTPM_API int TPM2_IFX_FieldUpgradeStart(TPM_HANDLE sessionHandle, + uint8_t* data, uint32_t size); +WOLFTPM_API int TPM2_IFX_FieldUpgradeCommand(TPM_CC cc, uint8_t* data, uint32_t size); +#endif /* WOLFTPM_FIRMWARE_UPGRADE */ + +#endif /* Infineon SLB Vendor Specific */ + /* Vendor Specific GPIO */ #ifdef WOLFTPM_ST33 @@ -2959,8 +2980,7 @@ WOLFTPM_API TPM_RC TPM2_NV_Certify(NV_Certify_In* in, NV_Certify_Out* out); CFG_STRUCT preConfig; } NTC2_GetConfig_Out; WOLFTPM_API int TPM2_NTC2_GetConfig(NTC2_GetConfig_Out* out); - -#endif /* WOLFTPM_ST33 || WOLFTPM_AUTODETECT */ +#endif /* Vendor GPIO Commands */ /* Non-standard API's */ diff --git a/wolftpm/tpm2_packet.h b/wolftpm/tpm2_packet.h index 76ac00a..fa9da7f 100644 --- a/wolftpm/tpm2_packet.h +++ b/wolftpm/tpm2_packet.h @@ -30,6 +30,23 @@ #define TPM2_HEADER_SIZE 10 /* expected TPM2 header size */ +/* Endianess Helpers */ +#ifdef LITTLE_ENDIAN_ORDER + #define cpu_to_be16(d) ByteReverseWord16(d) + #define cpu_to_be32(d) ByteReverseWord32(d) + #define cpu_to_be64(d) ByteReverseWord64(d) + #define be16_to_cpu(d) ByteReverseWord16(d) + #define be32_to_cpu(d) ByteReverseWord32(d) + #define be64_to_cpu(d) ByteReverseWord64(d) +#else + #define cpu_to_be16(d) (d) + #define cpu_to_be32(d) (d) + #define cpu_to_be64(d) (d) + #define be16_to_cpu(d) (d) + #define be32_to_cpu(d) (d) + #define be64_to_cpu(d) (d) +#endif + /* For reference here is the TPM2 header (not used) */ typedef struct TPM2_HEADER { UINT16 tag; diff --git a/wolftpm/tpm2_types.h b/wolftpm/tpm2_types.h index aa81435..82333dd 100644 --- a/wolftpm/tpm2_types.h +++ b/wolftpm/tpm2_types.h @@ -308,13 +308,19 @@ typedef int64_t INT64; #define TPM2_SPI_MAX_HZ TPM2_SPI_MAX_HZ_NUVOTON #endif #else - /* Infineon OPTIGA SLB9670/SLB9672 */ + /* Infineon OPTIGA SLB9670/SLB9672/SLB9673 */ #ifdef WOLFTPM_SLB9670 /* Max: 43MHz */ #define TPM2_SPI_MAX_HZ_INFINEON 43000000 - #else - #undef WOLFTPM_SLB9672 - #define WOLFTPM_SLB9672 + #elif !defined(WOLFTPM_AUTODETECT) + #ifdef WOLFTPM_I2C + #undef WOLFTPM_SLB9673 + #define WOLFTPM_SLB9673 + #else + #undef WOLFTPM_SLB9672 + #define WOLFTPM_SLB9672 + #endif + /* Max: 33MHz */ #define TPM2_SPI_MAX_HZ_INFINEON 33000000 #endif @@ -441,6 +447,29 @@ typedef int64_t INT64; #define XTPM_WAIT() /* just poll without delay by default */ #endif +/* sleep helper, used in firmware update */ +#ifndef XSLEEP_MS + #ifdef WIN32 + #include + #define XSLEEP_MS(ms) Sleep(ms) + #elif defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L + #include + #define XSLEEP_MS(ms) ({ \ + struct timespec ts; \ + ts.tv_sec = ms / 1000; \ + ts.tv_nsec = (ms % 1000) * 1000000; \ + nanosleep(&ts, NULL); \ + }) + #else + #include + #define XSLEEP_MS(ms) ({ \ + if (ms >= 1000) \ + sleep(ms / 1000); \ + usleep((ms % 1000) * 1000); \ + }) + #endif +#endif + #ifndef BUFFER_ALIGNMENT #define BUFFER_ALIGNMENT 4 #endif @@ -645,6 +674,15 @@ typedef int64_t INT64; #define WOLFTPM2_PEM_DECODE #endif +/* Firmware upgrade requires wolfCrypt for hash and supported + * only for Infineon SLB9672/SLB9673 */ +#if defined(WOLFTPM_FIRMWARE_UPGRADE) && \ + (defined(WOLFTPM2_NO_WOLFCRYPT) || \ + (!defined(WOLFTPM_SLB9672) && !defined(WOLFTPM_SLB9673))) + #undef WOLFTPM_FIRMWARE_UPGRADE +#endif + + /* ---------------------------------------------------------------------------*/ /* ENDIANESS HELPERS */ /* ---------------------------------------------------------------------------*/ diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 4f9cd78..4889a27 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -118,6 +118,12 @@ typedef struct WOLFTPM2_CAPS { word16 fwVerMajor; word16 fwVerMinor; word32 fwVerVendor; +#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673) + word32 keyGroupId; + word16 fwCounter; + word16 fwCounterSame; + byte opMode; +#endif /* bits */ word16 fips140_2 : 1; /* using FIPS mode */ @@ -3567,6 +3573,18 @@ WOLFTPM_LOCAL int GetKeyTemplateECC(TPMT_PUBLIC* publicTemplate, TPM_ALG_ID nameAlg, TPMA_OBJECT objectAttributes, TPM_ECC_CURVE curve, TPM_ALG_ID sigScheme, TPM_ALG_ID sigHash); + +#ifdef WOLFTPM_FIRMWARE_UPGRADE +typedef int (*wolfTPM2FwDataCb)( + uint8_t* data, uint32_t data_req_sz, uint32_t offset, void* cb_ctx); + +WOLFTPM_API int wolfTPM2_FirmwareUpgrade(WOLFTPM2_DEV* dev, + uint8_t* manifest, uint32_t manifest_sz, + wolfTPM2FwDataCb cb, void* cb_ctx); +WOLFTPM_API int wolfTPM2_FirmwareUpgradeCancel(WOLFTPM2_DEV* dev); + +#endif /* WOLFTPM_FIRMWARE_UPGRADE */ + #ifdef __cplusplus } /* extern "C" */ #endif