diff --git a/.github/workflows/pqc-build-matrix.yml b/.github/workflows/pqc-build-matrix.yml index adf8ee7d..15411a4f 100644 --- a/.github/workflows/pqc-build-matrix.yml +++ b/.github/workflows/pqc-build-matrix.yml @@ -18,7 +18,10 @@ concurrency: # prove each per-operation gate compiles and links (lib + server + unit tests). # The (mldsa=no, mlkem=no) combo is intentionally absent: it is a configure # error (no PQC algorithm) verified by the reject-no-pqc job below. Runtime -# make check on the full op set is covered by pqc-examples.yml. +# make check on the full op set is covered by pqc-examples.yml. The +# standalone-pqc job below covers PQC with --disable-wolfcrypt, and is the +# only PQC job that builds the examples and unit tests (every row above uses +# --disable-examples, so example/test compile breaks escape them). jobs: build: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false @@ -134,6 +137,48 @@ jobs: config.log retention-days: 5 + standalone-pqc: + # PQC command marshaling is pure wire format, so it must build with + # --disable-wolfcrypt (embedded client driving a v1.85 TPM, no host + # crypto). Deliberately no setup-wolfssl step: this config links no + # wolfSSL at all, which is exactly what the job proves. Deliberately no + # --disable-examples: a plain `make` compiles examples/pqc/* and + # tests/unit.test, which is where the breakage showed up. + # Build-only -- no TPM is reachable over the SPI HAL on a runner. + if: github.event_name != 'pull_request' || github.event.pull_request.draft == false + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + include: + - name: pqc-spi-nowolfcrypt + wolftpm_config: --enable-pqc --enable-spi --disable-wolfcrypt + - name: v185-nowolfcrypt + wolftpm_config: --enable-v185 --disable-wolfcrypt --disable-autodetect --disable-fwtpm + + steps: + - name: Checkout wolfTPM + uses: actions/checkout@v4 + + - name: Build wolfTPM standalone (${{ matrix.name }}) + run: | + ./autogen.sh + ./configure ${{ matrix.wolftpm_config }} + make -j"$(nproc)" + + - name: Show resolved PQC options + run: grep -E "WOLFTPM_(V185|PQC|NO_ML|NO_HASH|MLDSA|MLKEM)" wolftpm/options.h || true + + - name: Upload failure logs + if: failure() + uses: actions/upload-artifact@v4 + with: + name: standalone-pqc-${{ matrix.name }}-logs + path: | + config.log + retention-days: 5 + reject-no-pqc: # --enable-pqc with both algorithms off must FAIL at configure with a clear # message (no PQC algorithm). Verifies the guard, not just that it builds. diff --git a/configure.ac b/configure.ac index 3af17644..3095eb12 100644 --- a/configure.ac +++ b/configure.ac @@ -963,35 +963,45 @@ fi if test "x$ENABLED_PQC_MODE" != "xno" then - # Explicit opt-in: re-probe so we fail at configure time (with a - # clear hint about wolfSSL flags) rather than deep inside the compile - # with a cryptic error. Header existence alone is not enough -- the - # actual functions must be declared (gated by WOLFSSL_HAVE_MLDSA / - # HAVE_MLKEM in wolfssl/options.h). The probed symbol - # `wc_MlDsaKey_Init` is the canonical FIPS 204 entry point introduced - # by wolfSSL PR #10436 (post-v5.9.1-stable): wolfTPM consumes - # directly, so older wolfSSL that - # only ships is not supported here. - AC_CHECK_DECL([wc_MlDsaKey_Init], [], - [AC_MSG_ERROR([--enable-v185/--enable-pqc requires wolfSSL built with --enable-mldsa (or alias --enable-dilithium) and --enable-experimental, ships post-v5.9.1-stable])], - [[#include - #include ]]) - AC_CHECK_DECL([wc_MlKemKey_Init], [], - [AC_MSG_ERROR([--enable-v185/--enable-pqc requires wolfSSL >= v5.8.0-stable built with --enable-mlkem --enable-experimental])], - [[#include - #include ]]) + # The PQC command set is pure marshaling, so it stands on its own with + # --disable-wolfcrypt (an embedded client driving a v1.85 TPM with no + # host-side crypto). Only probe wolfSSL when it is actually linked -- + # otherwise no -I/-l is added and the probe would test headers this + # build never sees. + if test "x$ENABLED_WOLFCRYPT" = "xyes" + then + # Explicit opt-in: re-probe so we fail at configure time (with a + # clear hint about wolfSSL flags) rather than deep inside the compile + # with a cryptic error. Header existence alone is not enough -- the + # actual functions must be declared (gated by WOLFSSL_HAVE_MLDSA / + # HAVE_MLKEM in wolfssl/options.h). The probed symbol + # `wc_MlDsaKey_Init` is the canonical FIPS 204 entry point introduced + # by wolfSSL PR #10436 (post-v5.9.1-stable): wolfTPM consumes + # directly, so older wolfSSL that + # only ships is not supported here. + AC_CHECK_DECL([wc_MlDsaKey_Init], [], + [AC_MSG_ERROR([--enable-v185/--enable-pqc requires wolfSSL built with --enable-mldsa (or alias --enable-dilithium) and --enable-experimental, ships post-v5.9.1-stable])], + [[#include + #include ]]) + AC_CHECK_DECL([wc_MlKemKey_Init], [], + [AC_MSG_ERROR([--enable-v185/--enable-pqc requires wolfSSL >= v5.8.0-stable built with --enable-mlkem --enable-experimental])], + [[#include + #include ]]) - AC_MSG_CHECKING([wolfSSL version >= v5.8.0 for PQC]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ - #include - #if LIBWOLFSSL_VERSION_HEX < 0x05008000 - #error "wolfSSL < v5.8.0" - #endif - int main(void) { return 0; } - ]])], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_MSG_ERROR([wolfTPM PQC requires wolfSSL >= v5.8.0-stable. Please upgrade wolfSSL.])]) + AC_MSG_CHECKING([wolfSSL version >= v5.8.0 for PQC]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ + #include + #if LIBWOLFSSL_VERSION_HEX < 0x05008000 + #error "wolfSSL < v5.8.0" + #endif + int main(void) { return 0; } + ]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([wolfTPM PQC requires wolfSSL >= v5.8.0-stable. Please upgrade wolfSSL.])]) + else + AC_MSG_NOTICE([--disable-wolfcrypt: PQC is command marshaling only (no host-side ML-DSA/ML-KEM)]) + fi if test "x$ENABLED_PQC_MODE" = "xv185" then diff --git a/tests/unit_tests.c b/tests/unit_tests.c index 449c7977..d216a87c 100644 --- a/tests/unit_tests.c +++ b/tests/unit_tests.c @@ -32,7 +32,7 @@ #include #include #include -#ifdef WOLFTPM_MLDSA_SIGN +#if defined(WOLFTPM_MLDSA_SIGN) && !defined(WOLFTPM2_NO_WOLFCRYPT) #include #endif diff --git a/wolftpm/tpm2_types.h b/wolftpm/tpm2_types.h index 41702f2f..68463eb1 100644 --- a/wolftpm/tpm2_types.h +++ b/wolftpm/tpm2_types.h @@ -279,6 +279,15 @@ typedef int64_t INT64; #define NOT_COMPILED_IN -174 /* Feature not compiled in */ #define LENGTH_ONLY_E -202 /* Returning output length only */ + /* wolfCrypt is not compiled in, so wolfssl/wolfcrypt/memory.h is not + * available. Mirror the upstream volatile byte wipe so callers can + * still zero secrets without the compiler eliding the store. */ + static inline void wc_ForceZero(void* mem, size_t len) + { + volatile byte* z = (volatile byte*)mem; + while (len--) *z++ = 0; + } + #define ENCODING_TYPE_PEM CTC_FILETYPE_PEM #define ENCODING_TYPE_ASN1 CTC_FILETYPE_ASN1