diff --git a/.gitignore b/.gitignore index ce40abff..ea9d1b81 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,7 @@ 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/examples/firmware/README.md b/examples/firmware/README.md index 4420810f..20074a59 100644 --- a/examples/firmware/README.md +++ b/examples/firmware/README.md @@ -33,9 +33,11 @@ Data size is 919879 Writing TPM20_15.23.17664.0_R1.MANIFEST Writing TPM20_15.23.17664.0_R1.DATA -# Generate a SHA2-384 hash of the manifest file -sha384sum -b TPM20_15.23.17664.0_R1.MANIFEST | cut -d ' ' -f 1 | xxd -r -p > TPM20_15.23.17664.0_R1.MANIFESTHASH +./ifx_fw_update --help + +./ifx_fw_update TPM20_15.23.17664.0_R1.MANIFEST TPM20_15.23.17664.0_R1.DATA ``` + There is a TPM vendor command for getting the key group id(s). See `tpm2_ifx_firmware_dumpinfo`. diff --git a/examples/firmware/ifx_fw_update.c b/examples/firmware/ifx_fw_update.c new file mode 100644 index 00000000..57ab695e --- /dev/null +++ b/examples/firmware/ifx_fw_update.c @@ -0,0 +1,177 @@ +/* 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("Usage:\n"); + printf(" 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 + 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 int TPM2_IFX_PrintInfo(WOLFTPM2_DEV* dev) +{ + int rc; + WOLFTPM2_CAPS caps; + + XMEMSET(&caps, 0, sizeof(caps)); + rc = wolfTPM2_GetCapabilities(dev, &caps); + if (rc == TPM_RC_SUCCESS) { + printf("Mfg %s (%d), Vendor %s, Fw %u.%u (0x%x), KeyGroup 0x%x\n", + caps.mfgStr, caps.mfg, caps.vendorStr, caps.fwVerMajor, + caps.fwVerMinor, caps.fwVerVendor, caps.keyGroupId); + } + return rc; +} + +int TPM2_IFX_Firmware_Update(void* userCtx, int argc, char *argv[]) +{ + int rc; + WOLFTPM2_DEV dev; + WOLFTPM2_CAPS caps; + const char* manifest_file = NULL; + const char* firmware_file = NULL; + fw_info_t fwinfo; + + XMEMSET(&fwinfo, 0, sizeof(fwinfo)); + XMEMSET(&caps, 0, sizeof(caps)); + + if (argc >= 2) { + if (XSTRCMP(argv[1], "-?") == 0 || + XSTRCMP(argv[1], "-h") == 0 || + XSTRCMP(argv[1], "--help") == 0) { + usage(); + return 0; + } + + manifest_file = argv[1]; + if (argc >= 3) { + firmware_file = argv[2]; + } + } + + printf("Infineon Firmware Update Tool\n"); + printf("\tManifest File: %s\n", manifest_file); + 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; + } + + if (manifest_file == NULL || firmware_file == NULL) { + printf("Manifest file or firmware file arguments missing!\n"); + goto exit; + } + + 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) { + TPM2_IFX_PrintInfo(&dev); + } + if (rc == 0) { + rc = wolfTPM2_FirmwareUpgrade(&dev, + fwinfo.manifest_buf, (uint32_t)fwinfo.manifest_bufSz, + TPM2_IFX_FwData_Cb, &fwinfo); + } + if (rc == 0) { + 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 00000000..34d9fa5a --- /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 index 82cb2381..2427eda6 100644 --- a/examples/firmware/include.am +++ b/examples/firmware/include.am @@ -2,5 +2,21 @@ # All paths should be given relative to the root EXTRA_DIST += examples/firmware/README.md -EXTRA_DIST += examples/firmware/ifx_fw_extract.c 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 +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 + +example_firmwaredir = $(exampledir)/firmware +dist_example_firmware_DATA = examples/firmware/ifx_fw_update.c + +DISTCLEANFILES+= examples/firmware/.libs/ifx_fw_update diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 715121cf..a5c32c9a 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 @@ -691,6 +700,20 @@ static int wolfTPM2_ParseCapabilities(WOLFTPM2_CAPS* caps, case TPM_PT_MODES: caps->fips140_2 = (val & 0x00000001) ? 1: 0; break; + #if defined(WOLFTPM_FIRMWARE_UPGRADE) && \ + (defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673)) + case TPM_PT_VENDOR_FIX_FU_KEYGROUP_ID: + { + if (val == 0) + continue; + caps->keyGroupId = val; + #ifdef DEBUG_WOLFTPM + printf("Keygroup_id: [%i]:0x%08x\n", i, val); + #endif + break; + } + #endif /* WOLFTPM_FIRMWARE_UPGRADE */ + default: break; } @@ -712,13 +735,14 @@ 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, + printf("TPM2_GetCapability manufacture failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); #endif return rc; @@ -729,19 +753,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, + printf("TPM2_GetCapability modes failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); #endif return rc; } rc = wolfTPM2_ParseCapabilities(cap, &out.capabilityData.data.tpmProperties); +#ifdef WOLFTPM_FIRMWARE_UPGRADE +#if defined(WOLFTPM_SLB9672) || defined(WOLFTPM_SLB9673) + /* Get the keygroup_id */ + XMEMSET(&in, 0, sizeof(in)); + XMEMSET(&out, 0, sizeof(out)); + in.capability = TPM_CAP_VENDOR_PROPERTY; + in.property = TPM_PT_VENDOR_FIX_FU_KEYGROUP_ID; + in.propertyCount = 1; + rc = TPM2_GetCapability(&in, &out); + if (rc != TPM_RC_SUCCESS) { + #ifdef DEBUG_WOLFTPM + printf("TPM2_GetCapability key group failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + #endif + return rc; + } + rc = wolfTPM2_ParseCapabilities(cap, &out.capabilityData.data.tpmProperties); +#endif +#endif /* WOLFTPM_FIRMWARE_UPGRADE */ + return rc; } @@ -7019,45 +7064,6 @@ int wolfTPM2_PolicyAuthorizeMake(TPM_ALG_ID pcrAlg, #define IFX_FW_BIN_GUID \ {0x1a, 0x53, 0x66, 0x7a, 0xfb, 0x12, 0x47, 0x9e,\ 0xac, 0x58, 0xec, 0x99, 0x58, 0x86, 0x10, 0x94} -#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) - -static int tpm2_ifx_firmware_dumpinfo(WOLFTPM2_DEV* dev) -{ - int rc; - uint32_t i; - GetCapability_In in; - GetCapability_Out out; - - /* Get the keygroup_id */ - XMEMSET(&in, 0, sizeof(in)); - XMEMSET(&out, 0, sizeof(out)); - in.capability = TPM_CAP_VENDOR_PROPERTY; - in.property = TPM_PT_VENDOR_FIX_FU_KEYGROUP_ID; - in.propertyCount = 1; - rc = TPM2_GetCapability(&in, &out); - if (rc == TPM_RC_SUCCESS) { - printf("Keygroup_ids:"); - for (i = 0; i < out.capabilityData.data.tpmProperties.count; i++) { - if (out.capabilityData.data.tpmProperties.tpmProperty[i].value == 0) - continue; - printf(" [%i]:0x%08x", i, - be32_to_cpu(out.capabilityData.data.tpmProperties.tpmProperty[i].value)); - } - printf("\n"); - } -#ifdef DEBUG_WOLFTPM - if (rc != TPM_RC_SUCCESS) { - printf("TPM2_GetCapability vendor keygroup failed 0x%x: %s\n", rc, - TPM2_GetRCString(rc)); - } -#endif - (void)dev; - return rc; -} /* Setup the policy to enable firmware upgrade start */ static int tpm2_ifx_firmware_enable_policy(WOLFTPM2_DEV* dev) @@ -7132,7 +7138,7 @@ static int tpm2_ifx_firmware_start(WOLFTPM2_DEV* dev, TPM_ALG_ID hashAlg, } if (rc == TPM_RC_SUCCESS) { /* delay 1 second to give the TPM time to switch modes */ - sleep(1); + XSLEEP_MS(1000); /* it is not required to release session handle, * since TPM reset into firmware upgrade mode */ } @@ -7236,7 +7242,7 @@ static int tpm2_ifx_firmware_data(WOLFTPM2_DEV* dev, if (rc == 0) { /* Give the TPM time to start the new firmware */ - sleep(1); + XSLEEP_MS(1000); } #ifdef DEBUG_WOLFTPM else { @@ -7278,11 +7284,8 @@ int wolfTPM2_FirmwareUpgrade(WOLFTPM2_DEV* dev, uint8_t manifest_hash[TPM_SHA384_DIGEST_SIZE]; uint32_t manifest_hash_sz = (uint32_t)sizeof(manifest_hash); - rc = tpm2_ifx_firmware_dumpinfo(dev); /* dump firmware info */ - if (rc == 0) { - /* hash the manifest */ - rc = wc_Sha384Hash(manifest, manifest_sz, manifest_hash); - } + /* hash the manifest */ + rc = wc_Sha384Hash(manifest, manifest_sz, manifest_hash); if (rc == 0) { rc = tpm2_ifx_firmware_enable_policy(dev); } @@ -7298,9 +7301,6 @@ int wolfTPM2_FirmwareUpgrade(WOLFTPM2_DEV* dev, if (rc == 0) { rc = tpm2_ifx_firmware_final(dev); } - if (rc == 0) { - rc = tpm2_ifx_firmware_dumpinfo(dev); /* dump firmware info */ - } (void)cb; (void)cb_ctx; diff --git a/wolftpm/tpm2_types.h b/wolftpm/tpm2_types.h index 3d7fd4e1..55c61ad3 100644 --- a/wolftpm/tpm2_types.h +++ b/wolftpm/tpm2_types.h @@ -447,6 +447,15 @@ typedef int64_t INT64; #define XTPM_WAIT() /* just poll without delay by default */ #endif +/* sleep helper, used in firmware update */ +#ifndef XSLEEP_MS + #ifdef USE_WINDOWS_API + #define XSLEEP_MS(t) Sleep(t) + #else + #define XSLEEP_MS(t) sleep(t) + #endif +#endif + #ifndef BUFFER_ALIGNMENT #define BUFFER_ALIGNMENT 4 #endif @@ -651,8 +660,11 @@ typedef int64_t INT64; #define WOLFTPM2_PEM_DECODE #endif -/* Firmware upgrade requires wolfCrypt for hash */ -#if defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFTPM_FIRMWARE_UPGRADE) +/* 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 diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index a28feaaa..e3182e29 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -118,6 +118,9 @@ typedef struct WOLFTPM2_CAPS { word16 fwVerMajor; word16 fwVerMinor; word32 fwVerVendor; +#ifdef WOLFTPM_FIRMWARE_UPGRADE + word32 keyGroupId; +#endif /* bits */ word16 fips140_2 : 1; /* using FIPS mode */