From a729cd5165509a9c6aab60af611f575bbdcd6132 Mon Sep 17 00:00:00 2001 From: Tesfa Mael Date: Fri, 10 Jul 2026 11:51:54 -0700 Subject: [PATCH 1/4] tpm2_types.h: simplify WOLFTPM_NO_RETRY/MAX_RETRIES config The old block force-defined WOLFTPM_MAX_RETRIES=0 under WOLFTPM_NO_RETRY, which is dead (MAX_RETRIES is only read under #ifndef WOLFTPM_NO_RETRY), and silently swallowed the contradictory NO_RETRY + MAX_RETRIES>0 combo. Define the default first, then diagnose the conflict with #error. Keeping MAX_RETRIES defined before the check keeps it -Wundef-clean, including the NO_RETRY-without-MAX_RETRIES case. --- wolftpm/tpm2_types.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wolftpm/tpm2_types.h b/wolftpm/tpm2_types.h index d1893447..de8b7e70 100644 --- a/wolftpm/tpm2_types.h +++ b/wolftpm/tpm2_types.h @@ -577,13 +577,14 @@ typedef int64_t INT64; * keep the raw TPM response code; opt in at runtime with TPM2_SetCommandRetries * or at build time with -DWOLFTPM_MAX_RETRIES=N. Define WOLFTPM_NO_RETRY to * compile the handling out entirely. */ -#ifdef WOLFTPM_NO_RETRY - #undef WOLFTPM_MAX_RETRIES - #define WOLFTPM_MAX_RETRIES 0 -#endif #ifndef WOLFTPM_MAX_RETRIES #define WOLFTPM_MAX_RETRIES 0 #endif +/* WOLFTPM_MAX_RETRIES is always defined by here, so the check below stays + * -Wundef-clean even when WOLFTPM_NO_RETRY is set without WOLFTPM_MAX_RETRIES. */ +#if defined(WOLFTPM_NO_RETRY) && (WOLFTPM_MAX_RETRIES > 0) + #error "WOLFTPM_NO_RETRY conflicts with WOLFTPM_MAX_RETRIES > 0" +#endif #ifndef MAX_SYM_BLOCK_SIZE #define MAX_SYM_BLOCK_SIZE 20 From e087029c7a98f599b748b91a06f9a194d3fedf58 Mon Sep 17 00:00:00 2001 From: Tesfa Mael Date: Fri, 10 Jul 2026 11:51:54 -0700 Subject: [PATCH 2/4] tpm2_types.h: allow freestanding builds via WOLFTPM_NO_STD_HEADERS Targets without a hosted C library cannot build wolfTPM today because tpm2_types.h unconditionally includes and (in the standalone WOLFTPM2_NO_WOLFCRYPT path) //. Guard those standard headers behind WOLFTPM_NO_STD_HEADERS so a freestanding target can supply the fixed-width types and mem/str functions via user_settings.h. No change for hosted builds (macro undefined). Platform delay/sleep headers (unistd/time) stay steered by the existing XTPM_WAIT/XSLEEP_MS hooks and their platform conditionals. --- wolftpm/tpm2_types.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/wolftpm/tpm2_types.h b/wolftpm/tpm2_types.h index de8b7e70..1e225fe2 100644 --- a/wolftpm/tpm2_types.h +++ b/wolftpm/tpm2_types.h @@ -22,7 +22,12 @@ #ifndef __TPM2_TYPES_H__ #define __TPM2_TYPES_H__ +/* Freestanding targets with no hosted C library define WOLFTPM_NO_STD_HEADERS + * and provide the fixed-width integer types (and the mem/str functions used via + * the X* wrappers) through user_settings.h instead of the standard headers. */ +#ifndef WOLFTPM_NO_STD_HEADERS #include +#endif #ifdef WOLFTPM_USER_SETTINGS #include "user_settings.h" @@ -213,7 +218,7 @@ typedef int64_t INT64; #include /* for wolfSSL_ERR_reason_error_string */ #endif - #ifdef DEBUG_WOLFTPM + #if defined(DEBUG_WOLFTPM) && !defined(WOLFTPM_NO_STD_HEADERS) #include #endif @@ -249,9 +254,11 @@ typedef int64_t INT64; #endif #else + #ifndef WOLFTPM_NO_STD_HEADERS #include #include #include + #endif typedef uint8_t byte; typedef uint16_t word16; @@ -369,7 +376,9 @@ typedef int64_t INT64; #endif #ifndef WOLFTPM_CUSTOM_TYPES + #ifndef WOLFTPM_NO_STD_HEADERS #include + #endif #define XSTRTOUL(s,e,b) strtoul((s),(e),(b)) #define XATOI(s) atoi((s)) @@ -1065,7 +1074,9 @@ typedef int64_t INT64; #ifdef INTEL_INTRINSICS /* for non visual studio probably need no long version, 32 bit only * i.e., _rotl and _rotr */ + #ifndef WOLFTPM_NO_STD_HEADERS #include /* get intrinsic definitions */ + #endif #pragma intrinsic(_lrotl, _lrotr) static inline word32 rotlFixed(word32 x, word32 y) { return y ? _lrotl(x, y) : x; From 32c2ba6f7f7b0f65256fd328e9bcaeb6cc3bf886 Mon Sep 17 00:00:00 2001 From: Tesfa Mael Date: Fri, 10 Jul 2026 12:10:45 -0700 Subject: [PATCH 3/4] tpm2_util.c: guard under WOLFTPM_NO_STD_HEADERS Same freestanding contract as tpm2_types.h: a target with no hosted C library supplies its own I/O, so the bare must be guarded too. --- src/tpm2_util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tpm2_util.c b/src/tpm2_util.c index 2b9de825..88560eb2 100644 --- a/src/tpm2_util.c +++ b/src/tpm2_util.c @@ -30,7 +30,9 @@ #include #include +#ifndef WOLFTPM_NO_STD_HEADERS #include +#endif #ifndef WOLFTPM2_NO_WOLFCRYPT #include From 130a3e20f306f331f94eab87ce76ec80d5d9c63d Mon Sep 17 00:00:00 2001 From: Tesfa Mael Date: Fri, 10 Jul 2026 12:10:45 -0700 Subject: [PATCH 4/4] ci: add freestanding WOLFTPM_NO_STD_HEADERS build Builds the standalone (WOLFTPM2_NO_WOLFCRYPT) library under -nostdinc with types supplied via user_settings.h, so a regression that pulls a standard header back in fails CI. Uses ./configure + make (CFLAGS carries -nostdinc). --- .github/workflows/freestanding-build.yml | 63 ++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .github/workflows/freestanding-build.yml diff --git a/.github/workflows/freestanding-build.yml b/.github/workflows/freestanding-build.yml new file mode 100644 index 00000000..ab940b70 --- /dev/null +++ b/.github/workflows/freestanding-build.yml @@ -0,0 +1,63 @@ +name: Freestanding Build (WOLFTPM_NO_STD_HEADERS) + +# Builds the standalone (WOLFTPM2_NO_WOLFCRYPT) library with no hosted C library +# (-nostdinc) to prove WOLFTPM_NO_STD_HEADERS keeps the standard headers out. +# The fixed-width types and mem/str prototypes are supplied via user_settings.h, +# exactly as a bare-metal integrator would. -nostdinc is applied only to the +# build (make CFLAGS), not to configure, whose feature probes need libc. + +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + types: [opened, synchronize, reopened, ready_for_review] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + freestanding: + if: github.event_name != 'pull_request' || github.event.pull_request.draft == false + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Write freestanding user_settings.h (types + mem/str, no libc) + run: | + mkdir -p freestanding + cat > freestanding/user_settings.h <<'EOF' + #ifndef FREESTANDING_USER_SETTINGS_H + #define FREESTANDING_USER_SETTINGS_H + /* Standalone bare-metal-style config: supply the fixed-width integer + * types and mem/str prototypes the library needs, so the standard + * headers stay guarded out by WOLFTPM_NO_STD_HEADERS. */ + #define WOLFTPM2_NO_HEAP + typedef __UINT8_TYPE__ uint8_t; typedef __UINT16_TYPE__ uint16_t; + typedef __UINT32_TYPE__ uint32_t; typedef __UINT64_TYPE__ uint64_t; + typedef __INT8_TYPE__ int8_t; typedef __INT16_TYPE__ int16_t; + typedef __INT32_TYPE__ int32_t; typedef __INT64_TYPE__ int64_t; + typedef __SIZE_TYPE__ size_t; typedef __UINTPTR_TYPE__ uintptr_t; + void *memcpy(void*, const void*, size_t); + void *memset(void*, int, size_t); + int memcmp(const void*, const void*, size_t); + size_t strlen(const char*); + #ifndef NULL + #define NULL ((void*)0) + #endif + #define XTPM_WAIT() + #define XSLEEP_MS(ms) + #endif + EOF + + - name: Configure standalone (no wolfCrypt, SPI HAL, no autodetect/fwtpm/example-HAL) + run: | + ./autogen.sh + ./configure --disable-wolfcrypt --enable-spi \ + --disable-autodetect --disable-fwtpm --disable-hal + + - name: Build library with no standard library (-nostdinc) + run: | + make src/libwolftpm.la \ + CFLAGS="-nostdinc -Ifreestanding -DWOLFTPM_USER_SETTINGS -DWOLFTPM_NO_STD_HEADERS"