diff --git a/examples/u-boot/README.md b/examples/u-boot/README.md new file mode 100644 index 0000000..c9597b6 --- /dev/null +++ b/examples/u-boot/README.md @@ -0,0 +1,152 @@ +# wolfTPM Support For Das U-boot + +wolfTPM provides experimental support for U-Boot with the following key features: + +- Utilizes SOFT SPI driver in U-Boot for TPM communication +- Implements TPM 2.0 driver functionality through its internal TIS layer +- Provides native API access to all TPM 2.0 commands +- Includes wrapper API for common TPM 2.0 operations +- Supports two integration paths: + - `__linux__`: Uses existing tpm interface via tpm2_linux.c + - `__UBOOT__`: Direct SPI communication through tpm_io_uboot.c + +## wolfTPM U-Boot Commands + +The following commands are available through the `wolftpm` interface: + +### Basic Commands + +- `help` - Show help text +- `device [num device]` - Show all devices or set the specified device +- `info` - Show information about the TPM +- `state` - Show internal state from the TPM (if available) +- `autostart` - Initialize the TPM, perform a Startup(clear) and run a full selftest sequence +- `init` - Initialize the software stack (must be first command) +- `startup []` - Issue a TPM2_Startup command + - ``: TPM2_SU_CLEAR (reset state) or TPM2_SU_STATE (preserved state) + - `[]`: optional shutdown with "off" +- `self_test ` - Test TPM capabilities + - ``: "full" (all tests) or "continue" (untested tests only) + +### PCR Operations + +- `pcr_extend []` - Extend PCR with digest +- `pcr_read []` - Read PCR to memory +- `pcr_allocate []` - Reconfig PCR bank algorithm +- `pcr_setauthpolicy | pcr_setauthvalue []` - Change PCR access key +- `pcr_print` - Print current PCR state + +### Security Management + +- `clear ` - Issue TPM2_Clear command + - ``: TPM2_RH_LOCKOUT or TPM2_RH_PLATFORM +- `change_auth []` - Change hierarchy password + - ``: TPM2_RH_LOCKOUT, TPM2_RH_ENDORSEMENT, TPM2_RH_OWNER, or TPM2_RH_PLATFORM +- `dam_reset []` - Reset internal error counter +- `dam_parameters []` - Set DAM parameters +- `caps` - Show TPM capabilities and info + +### Firmware Management + +- `firmware_update ` - Update TPM firmware +- `firmware_cancel` - Cancel TPM firmware update + +## Enabling wolfTPM in U-Boot + +Enable wolfTPM support in U-Boot by adding these options to your board's defconfig: + +``` +CONFIG_TPM=y +CONFIG_TPM_V2=y +CONFIG_TPM_WOLF=y +CONFIG_CMD_WOLFTPM=y +``` + +Or use `make menuconfig` and enable: +- Device Drivers → TPM → TPM 2.0 Support +- Device Drivers → TPM → wolfTPM Support +- Command line interface → Security commands → Enable wolfTPM commands + +## Building and Running wolfTPM with U-Boot using QEMU + +To build and run wolfTPM with U-Boot using QEMU and a tpm simulator, follow these steps: + +1. Install swtpm: +``` +git clone git@github.com:stefanberger/swtpm.git +cd swtpm +./autogen.sh +make +``` + +2. Build U-Boot: +``` +make distclean +export CROSS_COMPILE=aarch64-linux-gnu- +export ARCH=aarch64 +make qemu_arm64_defconfig +make -j4 +``` + +3. Create TPM directory: +``` +mkdir -p /tmp/mytpm1 +``` + +4. Start swtpm (in first terminal): +``` +swtpm socket --tpm2 --tpmstate dir=/tmp/mytpm1 --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock --log level=20 +``` + +5. Start QEMU (in second terminal): +``` +qemu-system-aarch64 -machine virt -nographic -cpu cortex-a57 -bios u-boot.bin -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock -tpmdev emulator,id=tpm0,chardev=chrtpm -device tpm-tis-device,tpmdev=tpm0 +``` + +6. Example output: + +``` +U-Boot 2025.07-rc1-ge15cbf232ddf-dirty (May 06 2025 - 16:25:56 -0700) + +DRAM: 128 MiB +using memory 0x46658000-0x47698000 for malloc() +Core: 52 devices, 15 uclasses, devicetree: board +Flash: 64 MiB +Loading Environment from Flash... *** Warning - bad CRC, using default environment + +In: serial,usbkbd +Out: serial,vidconsole +Err: serial,vidconsole +No USB controllers found +Net: eth0: virtio-net#32 + +Hit any key to stop autoboot: 0 +=> tpm2 help +tpm2 - Issue a TPMv2.x command + +Usage: +tpm2 [] + +device [num device] + Show all devices or set the specified device +info + Show information about the TPM. +``` + +7. Example commands: + +``` +=> tpm2 info +tpm_tis@0 v2.0: VendorID 0x1014, DeviceID 0x0001, RevisionID 0x01 [open] +=> tpm2 startup TPM2_SU_CLEAR +=> tpm2 get_capability 0x6 0x20e 0x200 1 +Capabilities read from TPM: +Property 0x6a2e45a9: 0x6c3646a9 +=> tpm2 pcr_read 10 0x100000 +PCR #10 sha256 32 byte content (20 known updates): + 20 25 73 0a 00 56 61 6c 75 65 3a 0a 00 23 23 20 + 4f 75 74 20 6f 66 20 6d 65 6d 6f 72 79 0a 00 23 +``` + +8. Exiting the QEMU: +Press Ctrl-A followed by X diff --git a/examples/wrap/caps.c b/examples/wrap/caps.c index 6da35c6..7c0965a 100644 --- a/examples/wrap/caps.c +++ b/examples/wrap/caps.c @@ -130,7 +130,8 @@ int TPM2_Wrapper_CapsArgs(void* userCtx, int argc, char *argv[]) TPM2_PCRs_Print(); exit: - wolfTPM2_Shutdown(&dev, 0); /* 0=just shutdown, no startup */ + /* Only doShutdown=1: Just shutdown the TPM */ + wolfTPM2_Reset(&dev, 1, 0); wolfTPM2_Cleanup(&dev); diff --git a/examples/wrap/wrap_test.c b/examples/wrap/wrap_test.c index 52abbd3..1d8dc29 100644 --- a/examples/wrap/wrap_test.c +++ b/examples/wrap/wrap_test.c @@ -1010,7 +1010,8 @@ exit: wolfTPM2_UnloadHandle(&dev, &ekKey.handle); wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); - wolfTPM2_Shutdown(&dev, 0); /* 0=just shutdown, no startup */ + /* Only doShutdown=1: Just shutdown the TPM */ + wolfTPM2_Reset(&dev, 1, 0); wolfTPM2_Cleanup(&dev); diff --git a/hal/include.am b/hal/include.am index eed3ed9..48389c6 100644 --- a/hal/include.am +++ b/hal/include.am @@ -13,6 +13,7 @@ src_libwolftpm_la_SOURCES += \ hal/tpm_io_microchip.c \ hal/tpm_io_st.c \ hal/tpm_io_qnx.c \ + hal/tpm_io_uboot.c \ hal/tpm_io_xilinx.c endif diff --git a/hal/tpm_io.c b/hal/tpm_io.c index 19ecd14..b3297cb 100644 --- a/hal/tpm_io.c +++ b/hal/tpm_io.c @@ -53,6 +53,8 @@ #if defined(WOLFTPM_MMIO) #include "tpm_io_mmio.c" +#elif defined(__UBOOT__) +#include "hal/tpm_io_uboot.c" #elif defined(__linux__) #include "hal/tpm_io_linux.c" #elif defined(WOLFSSL_STM32_CUBEMX) @@ -78,8 +80,10 @@ static int TPM2_IoCb_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, word16 xferSz, void* userCtx) { int ret = TPM_RC_FAILURE; - -#if defined(__linux__) + +#if defined(__UBOOT__) + ret = TPM2_IoCb_Uboot_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); +#elif defined(__linux__) ret = TPM2_IoCb_Linux_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); #elif defined(WOLFSSL_STM32_CUBEMX) ret = TPM2_IoCb_STCubeMX_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); diff --git a/hal/tpm_io.h b/hal/tpm_io.h index afdd364..5c7df05 100644 --- a/hal/tpm_io.h +++ b/hal/tpm_io.h @@ -49,6 +49,7 @@ * - Xilinx Zynq * - Barebox * - QNX + * - uboot * - Infineon Tri-Core * - Microchip MPLAB X Harmony (WOLFTPM_MICROCHIP_HARMONY) * Using custom IO Callback is always possible. @@ -101,6 +102,9 @@ WOLFTPM_LOCAL int TPM2_IoCb_Atmel_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rx #elif defined(__BAREBOX__) WOLFTPM_LOCAL int TPM2_IoCb_Barebox_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, word16 xferSz, void* userCtx); +#elif defined(__UBOOT__) +WOLFTPM_LOCAL int TPM2_IoCb_Uboot_SPI(TPM2_CTX* ctx, const byte* txBuf, + byte* rxBuf, word16 xferSz, void* userCtx); #elif defined(__linux__) WOLFTPM_LOCAL int TPM2_IoCb_Linux_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, word16 xferSz, void* userCtx); diff --git a/hal/tpm_io_uboot.c b/hal/tpm_io_uboot.c new file mode 100644 index 0000000..b41612e --- /dev/null +++ b/hal/tpm_io_uboot.c @@ -0,0 +1,82 @@ +/* tpm_io_uboot.c + * + * Copyright (C) 2006-2025 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-1301, USA + */ + +/* This example shows IO interfaces for U-boot */ + +#include +#include +#include "tpm_io.h" + +/******************************************************************************/ +/* --- BEGIN IO Callback Logic -- */ +/******************************************************************************/ + +/* Included via tpm_io.c if WOLFTPM_INCLUDE_IO_FILE is defined */ +#ifdef WOLFTPM_INCLUDE_IO_FILE + +#if ! (defined(WOLFTPM_LINUX_DEV) || \ + 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 + +#if defined(__UBOOT__) + #include + int TPM2_IoCb_Uboot_SPI(TPM2_CTX* ctx, const byte* txBuf, + byte* rxBuf, word16 xferSz, void* userCtx) + { + int ret = 0; + struct udevice *dev; + + /* Get the TPM device */ + if (ret == 0) { + ret = tcg2_platform_get_tpm2(&dev); + if ( ret != 0 || dev == NULL) { + #ifdef DEBUG_WOLFTPM + printf("Failed to get TPM device with error: %d\n", ret); + #endif + return TPM_RC_FAILURE; + } + } + + /* Transfer the device data using tpm_xfer */ + if (ret == 0) { + ret = tpm_xfer(dev, txBuf, xferSz, rxBuf, &xferSz); + if (ret != 0) { + #ifdef DEBUG_WOLFTPM + printf("tpm_xfer failed with error: %d\n", ret); + #endif + return TPM_RC_FAILURE; + } + } + + return TPM_RC_SUCCESS; + } +#endif /* __UBOOT__ */ +#endif /* WOLFTPM_LINUX_DEV || WOLFTPM_SWTPM || WOLFTPM_WINAPI */ +#endif /* WOLFTPM_INCLUDE_IO_FILE */ + +/******************************************************************************/ +/* --- END IO Callback Logic -- */ +/******************************************************************************/ diff --git a/src/tpm2.c b/src/tpm2.c index 0ead8c3..6a3a7ae 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -6117,6 +6117,99 @@ const char* TPM2_GetAlgName(TPM_ALG_ID alg) return "Unknown"; } +TPM_ALG_ID TPM2_GetAlgId(const char* name) +{ + if (!name) + return TPM_ALG_ERROR; + + if (!XSTRCMP(name, "RSA")) + return TPM_ALG_RSA; + if (!XSTRCMP(name, "SHA1")) + return TPM_ALG_SHA1; + if (!XSTRCMP(name, "HMAC")) + return TPM_ALG_HMAC; + if (!XSTRCMP(name, "AES")) + return TPM_ALG_AES; + if (!XSTRCMP(name, "MGF1")) + return TPM_ALG_MGF1; + if (!XSTRCMP(name, "KEYEDHASH")) + return TPM_ALG_KEYEDHASH; + if (!XSTRCMP(name, "XOR")) + return TPM_ALG_XOR; + if (!XSTRCMP(name, "SHA256")) + return TPM_ALG_SHA256; + if (!XSTRCMP(name, "SHA384")) + return TPM_ALG_SHA384; + if (!XSTRCMP(name, "SHA512")) + return TPM_ALG_SHA512; + if (!XSTRCMP(name, "NULL")) + return TPM_ALG_NULL; + if (!XSTRCMP(name, "SM3_256")) + return TPM_ALG_SM3_256; + if (!XSTRCMP(name, "SM4")) + return TPM_ALG_SM4; + if (!XSTRCMP(name, "RSASSA")) + return TPM_ALG_RSASSA; + if (!XSTRCMP(name, "RSAES")) + return TPM_ALG_RSAES; + if (!XSTRCMP(name, "RSAPSS")) + return TPM_ALG_RSAPSS; + if (!XSTRCMP(name, "OAEP")) + return TPM_ALG_OAEP; + if (!XSTRCMP(name, "ECDSA")) + return TPM_ALG_ECDSA; + if (!XSTRCMP(name, "ECDH")) + return TPM_ALG_ECDH; + if (!XSTRCMP(name, "ECDAA")) + return TPM_ALG_ECDAA; + if (!XSTRCMP(name, "SM2")) + return TPM_ALG_SM2; + if (!XSTRCMP(name, "ECSCHNORR")) + return TPM_ALG_ECSCHNORR; + if (!XSTRCMP(name, "ECMQV")) + return TPM_ALG_ECMQV; + if (!XSTRCMP(name, "KDF1_SP800_56A")) + return TPM_ALG_KDF1_SP800_56A; + if (!XSTRCMP(name, "KDF2")) + return TPM_ALG_KDF2; + if (!XSTRCMP(name, "KDF1_SP800_108")) + return TPM_ALG_KDF1_SP800_108; + if (!XSTRCMP(name, "ECC")) + return TPM_ALG_ECC; + if (!XSTRCMP(name, "SYMCIPHER")) + return TPM_ALG_SYMCIPHER; + if (!XSTRCMP(name, "AES-CTR")) + return TPM_ALG_CTR; + if (!XSTRCMP(name, "AES-OFB")) + return TPM_ALG_OFB; + if (!XSTRCMP(name, "AES-CBC")) + return TPM_ALG_CBC; + if (!XSTRCMP(name, "AES-CFB")) + return TPM_ALG_CFB; + if (!XSTRCMP(name, "AES-ECB")) + return TPM_ALG_ECB; + + return TPM_ALG_ERROR; +} + +#ifdef DEBUG_WOLFTPM +const char* TPM2_GetHierarchyDesc(TPMI_RH_HIERARCHY_AUTH authHandle) +{ + switch (authHandle) { + case TPM_RH_LOCKOUT: + return "Lockout"; + case TPM_RH_ENDORSEMENT: + return "Endorsement"; + case TPM_RH_OWNER: + return "Owner"; + case TPM_RH_PLATFORM: + return "Platform"; + default: + return "Unknown"; + } +} +#endif /* DEBUG_WOLFTPM */ + int TPM2_GetCurveSize(TPM_ECC_CURVE curveID) { switch (curveID) { diff --git a/src/tpm2_linux.c b/src/tpm2_linux.c index 6f7e8c1..fefca7d 100644 --- a/src/tpm2_linux.c +++ b/src/tpm2_linux.c @@ -28,6 +28,61 @@ #ifdef WOLFTPM_LINUX_DEV #include #include + +#if defined(__UBOOT__) + +#include +#include + +/* import u-boot function helper to get device */ +extern int tcg2_platform_get_tpm2(struct udevice **dev); + +/* Use the U-Boot TPM device and TIS layer */ +int TPM2_LINUX_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet) +{ + int rc; + struct udevice *dev; + size_t rspSz = 0; + +#ifdef WOLFTPM_DEBUG_VERBOSE + printf("Command size: %d\n", packet->pos); + TPM2_PrintBin(packet->buf, packet->pos); +#endif + + /* Get the TPM2 U-boot device */ + rc = tcg2_platform_get_tpm2(&dev); + if (rc != 0 || dev == NULL) { + #ifdef DEBUG_WOLFTPM + printf("Failed to find TPM2 U-boot device: %d\n", rc); + #endif + rc = TPM_RC_FAILURE; + } + if (rc == 0) { + /* Transfer the device data using tpm_xfer */ + rspSz = packet->size; + rc = tpm_xfer(dev, packet->buf, packet->pos, packet->buf, &rspSz); + if (rc != 0) { + #ifdef DEBUG_WOLFTPM + printf("tpm_xfer failed with error: %d\n", rc); + #endif + rc = TPM_RC_FAILURE; + } + } + +#ifdef WOLFTPM_DEBUG_VERBOSE + if (rspSz > 0) { + printf("Response size: %d\n", (int)rspSz); + TPM2_PrintBin(packet->buf, rspSz); + } +#endif + + (void)ctx; + + return rc; +} + +#else /* __linux__ */ + #include #include #include @@ -125,4 +180,5 @@ int TPM2_LINUX_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet) return rc; } -#endif +#endif /* __UBOOT__ __linux__ */ +#endif /* WOLFTPM_LINUX_DEV */ diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 220447f..598ed7d 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -5672,10 +5672,10 @@ int wolfTPM2_HmacFinish(WOLFTPM2_DEV* dev, WOLFTPM2_HMAC* hmac, return rc; } -/* performs a reset sequence */ -int wolfTPM2_Shutdown(WOLFTPM2_DEV* dev, int doStartup) +/* performs a reset, shutdown, or startup sequence */ +int wolfTPM2_Reset(WOLFTPM2_DEV* dev, int doShutdown, int doStartup) { - int rc; + int rc = TPM_RC_SUCCESS; Shutdown_In shutdownIn; Startup_In startupIn; @@ -5684,17 +5684,20 @@ int wolfTPM2_Shutdown(WOLFTPM2_DEV* dev, int doStartup) } /* shutdown */ - XMEMSET(&shutdownIn, 0, sizeof(shutdownIn)); - shutdownIn.shutdownType = TPM_SU_CLEAR; - rc = TPM2_Shutdown(&shutdownIn); - if (rc != TPM_RC_SUCCESS) { - #ifdef DEBUG_WOLFTPM - printf("TPM2_Shutdown failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); - #endif + if (doShutdown == 1) { + XMEMSET(&shutdownIn, 0, sizeof(shutdownIn)); + shutdownIn.shutdownType = TPM_SU_CLEAR; + rc = TPM2_Shutdown(&shutdownIn); + if (rc != TPM_RC_SUCCESS) { + #ifdef DEBUG_WOLFTPM + printf("TPM2_Shutdown failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); + #endif + } } /* startup */ - if (doStartup) { + if (doStartup == 1 && rc == TPM_RC_SUCCESS) { XMEMSET(&startupIn, 0, sizeof(startupIn)); startupIn.startupType = TPM_SU_CLEAR; rc = TPM2_Startup(&startupIn); @@ -5703,17 +5706,22 @@ int wolfTPM2_Shutdown(WOLFTPM2_DEV* dev, int doStartup) printf("TPM2_Startup failed %d: %s\n", rc, wolfTPM2_GetRCString(rc)); #endif - return rc; } } #ifdef DEBUG_WOLFTPM - printf("wolfTPM2_Shutdown complete\n"); + printf("wolfTPM2_Reset complete\n"); #endif return rc; } +/* performs a shutdown or reset sequence */ +int wolfTPM2_Shutdown(WOLFTPM2_DEV* dev, int doStartup) +{ + return wolfTPM2_Reset(dev, 1, doStartup); +} + int wolfTPM2_UnloadHandles(WOLFTPM2_DEV* dev, word32 handleStart, word32 handleCount) { @@ -5739,18 +5747,21 @@ int wolfTPM2_UnloadHandles_AllTransient(WOLFTPM2_DEV* dev) return wolfTPM2_UnloadHandles(dev, TRANSIENT_FIRST, MAX_HANDLE_NUM); } - -int wolfTPM2_ChangePlatformAuth(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session) +int wolfTPM2_ChangeHierarchyAuth(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session, + TPMI_RH_HIERARCHY_AUTH authHandle) { int rc = 0; HierarchyChangeAuth_In in; +#ifdef DEBUG_WOLFTPM + const char* desc = NULL; +#endif if (dev == NULL) { return BAD_FUNC_ARG; } XMEMSET(&in, 0, sizeof(in)); - in.authHandle = TPM_RH_PLATFORM; + in.authHandle = authHandle; /* use parameter encryption if session supplied */ if (session != NULL) { @@ -5771,16 +5782,17 @@ int wolfTPM2_ChangePlatformAuth(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session) rc = TPM2_HierarchyChangeAuth(&in); } #ifdef DEBUG_WOLFTPM + desc = TPM2_GetHierarchyDesc(authHandle); + if (rc == 0) { - printf("Platform auth set to %d bytes of random\n", in.newAuth.size); + printf("%s auth set to %d bytes of random\n", desc, in.newAuth.size); #ifdef WOLFTPM_DEBUG_VERBOSE printf("\tAuth Sz %d\n", in.newAuth.size); TPM2_PrintBin(in.newAuth.buffer, in.newAuth.size); #endif - } - else { - printf("Error %d setting platform auth! %s\n", - rc, wolfTPM2_GetRCString(rc)); + } else { + printf("Error %d setting %s auth! %s\n", + rc, desc, wolfTPM2_GetRCString(rc)); } #endif /* ensure the random secret is not left in stack */ @@ -5788,6 +5800,11 @@ int wolfTPM2_ChangePlatformAuth(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session) return rc; } +int wolfTPM2_ChangePlatformAuth(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session) +{ + return wolfTPM2_ChangeHierarchyAuth(dev, session, TPM_RH_PLATFORM); +} + /******************************************************************************/ /* --- END Wrapper Device Functions-- */ /******************************************************************************/ @@ -8017,6 +8034,7 @@ int wolfTPM2_FirmwareUpgradeHash(WOLFTPM2_DEV* dev, TPM_ALG_ID hashAlg, return rc; } +#ifndef WOLFTPM2_NO_WOLFCRYPT int wolfTPM2_FirmwareUpgrade(WOLFTPM2_DEV* dev, uint8_t* manifest, uint32_t manifest_sz, wolfTPM2FwDataCb cb, void* cb_ctx) @@ -8033,6 +8051,7 @@ int wolfTPM2_FirmwareUpgrade(WOLFTPM2_DEV* dev, } return rc; } +#endif int wolfTPM2_FirmwareUpgradeRecover(WOLFTPM2_DEV* dev, uint8_t* manifest, uint32_t manifest_sz, diff --git a/tests/unit_tests.c b/tests/unit_tests.c index 948ea15..99e9b31 100644 --- a/tests/unit_tests.c +++ b/tests/unit_tests.c @@ -357,6 +357,12 @@ static void test_TPM2_KDFa(void) rc >= 0 ? "Passed" : "Failed"); } +static void test_GetAlgId(void) +{ + TPM_ALG_ID alg = TPM2_GetAlgId("SHA256"); + AssertIntEQ(alg, TPM_ALG_SHA256); +} + static void test_wolfTPM2_CSR(void) { #if defined(WOLFTPM2_CERT_GEN) && !defined(WOLFTPM2_NO_HEAP) && \ @@ -663,6 +669,7 @@ int unit_tests(int argc, char *argv[]) test_wolfTPM2_GetRandom(); test_TPM2_PCRSel(); test_TPM2_KDFa(); + test_GetAlgId(); test_wolfTPM2_ReadPublicKey(); test_wolfTPM2_CSR(); #if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFTPM2_PEM_DECODE) && \ diff --git a/wolftpm/tpm2.h b/wolftpm/tpm2.h index 018e243..95bba2a 100644 --- a/wolftpm/tpm2.h +++ b/wolftpm/tpm2.h @@ -3550,6 +3550,46 @@ WOLFTPM_API const char* TPM2_GetRCString(int rc); */ WOLFTPM_API const char* TPM2_GetAlgName(TPM_ALG_ID alg); +/*! + \ingroup TPM2_Proprietary + \brief Translates a TPM algorithm name to its TPM algorithm ID + + \return a TPM algorithm ID + \return TPM_ALG_ERROR if invalid algorithm name + + \param name a pointer to a string constant specifying a valid TPM algorithm + name + + _Example_ + \code + TPM_ALG_ID alg = TPM2_GetAlgId("SHA256"); + if (alg == TPM_ALG_ERROR) { + //TPM2_GetAlgId failed + } + \endcode +*/ +WOLFTPM_API TPM_ALG_ID TPM2_GetAlgId(const char* name); + +#ifdef DEBUG_WOLFTPM +/*! + \ingroup TPM2_Proprietary + \brief Get readable string for TPM 2.0 hierarchy + + \return pointer to a string constant + + \param authHandle value of type TPMI_RH_HIERARCHY_AUTH specifying a valid + TPM 2.0 hierarchy + + _Example_ + \code + TPMI_RH_HIERARCHY_AUTH authHandle = TPM_RH_OWNER; + + printf("\tHierarchy: %s\n", TPM2_GetHierarchyDesc(authHandle)); + \endcode +*/ +WOLFTPM_API const char* TPM2_GetHierarchyDesc(TPMI_RH_HIERARCHY_AUTH authHandle); +#endif + /*! \ingroup TPM2_Proprietary \brief Determine the size in bytes of any TPM ECC Curve diff --git a/wolftpm/tpm2_packet.h b/wolftpm/tpm2_packet.h index 2ac5456..38ead40 100644 --- a/wolftpm/tpm2_packet.h +++ b/wolftpm/tpm2_packet.h @@ -30,21 +30,57 @@ #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) +/* Endianess Helpers + * Check if byte-order functions are already defined by the system: + * U-boot defines these functions, so we need to check if they are + * already defined. + */ +#ifndef cpu_to_be16 + #ifdef LITTLE_ENDIAN_ORDER + #define cpu_to_be16(d) ByteReverseWord16(d) + #else + #define cpu_to_be16(d) (d) + #endif +#endif + +#ifndef cpu_to_be32 + #ifdef LITTLE_ENDIAN_ORDER + #define cpu_to_be32(d) ByteReverseWord32(d) + #else + #define cpu_to_be32(d) (d) + #endif +#endif + +#ifndef cpu_to_be64 + #ifdef LITTLE_ENDIAN_ORDER + #define cpu_to_be64(d) ByteReverseWord64(d) + #else + #define cpu_to_be64(d) (d) + #endif +#endif + +#ifndef be16_to_cpu + #ifdef LITTLE_ENDIAN_ORDER + #define be16_to_cpu(d) ByteReverseWord16(d) + #else + #define be16_to_cpu(d) (d) + #endif +#endif + +#ifndef be32_to_cpu + #ifdef LITTLE_ENDIAN_ORDER + #define be32_to_cpu(d) ByteReverseWord32(d) + #else + #define be32_to_cpu(d) (d) + #endif +#endif + +#ifndef be64_to_cpu + #ifdef LITTLE_ENDIAN_ORDER + #define be64_to_cpu(d) ByteReverseWord64(d) + #else + #define be64_to_cpu(d) (d) + #endif #endif /* For reference here is the TPM2 header (not used) */ diff --git a/wolftpm/tpm2_types.h b/wolftpm/tpm2_types.h index 678e172..ff0173b 100644 --- a/wolftpm/tpm2_types.h +++ b/wolftpm/tpm2_types.h @@ -33,8 +33,14 @@ #include #endif -#ifdef __cplusplus - extern "C" { +#ifndef WOLFTPM2_NO_WOLFCRYPT + #ifndef WOLFSSL_USER_SETTINGS + #include + #endif +#else + #ifdef WOLFTPM_USER_SETTINGS + #include "user_settings.h" + #endif #endif #ifdef WOLFTPM_WINAPI @@ -44,6 +50,10 @@ #include #endif +#ifdef __cplusplus + extern "C" { +#endif + /* ---------------------------------------------------------------------------*/ /* TPM TYPES */ /* ---------------------------------------------------------------------------*/ @@ -81,9 +91,6 @@ typedef int64_t INT64; /* ---------------------------------------------------------------------------*/ #ifndef WOLFTPM2_NO_WOLFCRYPT - #ifndef WOLFSSL_USER_SETTINGS - #include - #endif /* enforce NO_THREAD_LS within wolfTPM */ #ifdef NO_THREAD_LS #undef HAVE_THREAD_LS @@ -142,10 +149,6 @@ typedef int64_t INT64; #include #include - #ifdef WOLFTPM_USER_SETTINGS - #include "user_settings.h" - #endif - typedef uint8_t byte; typedef uint16_t word16; typedef uint32_t word32; @@ -704,11 +707,9 @@ typedef int64_t INT64; #define WOLFTPM2_PEM_DECODE #endif -/* Firmware upgrade requires wolfCrypt for hashing. - * Supported only for Infineon SLB9672/SLB9673 */ -#if defined(WOLFTPM_FIRMWARE_UPGRADE) && \ - (defined(WOLFTPM2_NO_WOLFCRYPT) || \ - (!defined(WOLFTPM_SLB9672) && !defined(WOLFTPM_SLB9673))) +/* Firmware upgrade supported only for Infineon SLB9672/SLB9673 */ +#if defined(WOLFTPM_FIRMWARE_UPGRADE) && (!defined(WOLFTPM_AUTODETECT) && \ + (!defined(WOLFTPM_SLB9672) && !defined(WOLFTPM_SLB9673))) #undef WOLFTPM_FIRMWARE_UPGRADE #endif diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 5a75c6b..e303bde 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -2590,6 +2590,27 @@ WOLFTPM_API int wolfTPM2_EncryptDecrypt(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, WOLFTPM_API int wolfTPM2_SetCommand(WOLFTPM2_DEV* dev, TPM_CC commandCode, int enableFlag); +/*! + \ingroup wolfTPM2_Wrappers + \brief Helper function to shutdown, startup or reset the TPM + \note The behavior depends on the doStartup and doShutdown flags: + \note - Both flags set to 1: Performs a full TPM restart (shutdown then startup) + \note - Only doStartup=1: Just starts up the TPM + \note - Only doShutdown=1: Just shuts down the TPM + + \return TPM_RC_SUCCESS: successful + \return TPM_RC_FAILURE: generic failure (check TPM IO and TPM return code) + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a TPM2_DEV struct + \param doStartup integer value, non-zero values represent "perform Startup after Shutdown" + \param doShutdown integer value, non-zero values represent "perform Shutdown" + + \sa wolfTPM2_Init + \sa wolfTPM2_Reset +*/ +WOLFTPM_API int wolfTPM2_Reset(WOLFTPM2_DEV* dev, int doShutdown, int doStartup); + /*! \ingroup wolfTPM2_Wrappers \brief Helper function to shutdown or reset the TPM @@ -2603,6 +2624,7 @@ WOLFTPM_API int wolfTPM2_SetCommand(WOLFTPM2_DEV* dev, TPM_CC commandCode, \param doStartup integer value, non-zero values represent "perform Startup after Shutdown" \sa wolfTPM2_Init + \sa wolfTPM2_Shutdown */ WOLFTPM_API int wolfTPM2_Shutdown(WOLFTPM2_DEV* dev, int doStartup); @@ -3262,7 +3284,7 @@ WOLFTPM_API int wolfTPM2_CSR_Generate(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, /*! \ingroup wolfTPM2_Wrappers - \brief Helper to set the platform heirarchy authentication value to random. + \brief Helper to set the platform hierarchy authentication value to random. Setting the platform auth to random value is used to prevent application from being able to use platform hierarchy. This is defined in section 10 of the TCG PC Client Platform specification. @@ -3275,10 +3297,30 @@ WOLFTPM_API int wolfTPM2_CSR_Generate(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, \param session the current session, a session is required to protect the new platform auth \sa TPM2_HierarchyChangeAuth + \sa wolfTPM2_ChangeHierarchyAuth */ WOLFTPM_API int wolfTPM2_ChangePlatformAuth(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session); +/*! + \ingroup wolfTPM2_Wrappers + \brief Helper to set the hierarchy authentication value to random. + Setting the platform auth to random value is used to prevent application + from being able to use platform hierarchy. This is defined in section 10 + of the TCG PC Client Platform specification. + \return Success: Positive integer (size of the output) + \return TPM_RC_FAILURE: generic failure (check TPM IO and TPM return code) + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a TPM2_DEV struct + \param session the current session, a session is required to protect the new platform auth + \param authHandle the auth hierarchy (example: TPM_RH_PLATFORM or TPM_RH_LOCKOUT) + + \sa TPM2_HierarchyChangeAuth + \sa wolfTPM2_ChangePlatformAuth +*/ +WOLFTPM_API int wolfTPM2_ChangeHierarchyAuth(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session, + TPMI_RH_HIERARCHY_AUTH authHandle); /* moved to tpm.h native code. macros here for backwards compatibility */ #define wolfTPM2_SetupPCRSel TPM2_SetupPCRSel