diff --git a/.github/workflows/pqc-build-matrix.yml b/.github/workflows/pqc-build-matrix.yml new file mode 100644 index 00000000..6ffabb70 --- /dev/null +++ b/.github/workflows/pqc-build-matrix.yml @@ -0,0 +1,161 @@ +name: PQC Build Matrix (v1.85 trimming) + +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + types: [opened, synchronize, reopened, ready_for_review] + repository_dispatch: + types: [nightly-trigger] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +# Exhaustive build of every ML-DSA x ML-KEM trimming combination, for both the +# client library (--disable-fwtpm) and the fwTPM server (--enable-fwtpm), to +# 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. +jobs: + build: + if: github.event_name != 'pull_request' || github.event.pull_request.draft == false + runs-on: ubuntu-latest + timeout-minutes: 25 + strategy: + fail-fast: false + matrix: + include: + - name: cli-mldsa_all-mlkem_all + wolftpm_config: --enable-pqc --enable-mldsa=all --enable-mlkem=all --disable-fwtpm --disable-examples + - name: cli-mldsa_all-mlkem_enc + wolftpm_config: --enable-pqc --enable-mldsa=all --enable-mlkem=enc --disable-fwtpm --disable-examples + - name: cli-mldsa_all-mlkem_dec + wolftpm_config: --enable-pqc --enable-mldsa=all --enable-mlkem=dec --disable-fwtpm --disable-examples + - name: cli-mldsa_all-mlkem_no + wolftpm_config: --enable-pqc --enable-mldsa=all --enable-mlkem=no --disable-fwtpm --disable-examples + - name: cli-mldsa_signonly-mlkem_all + wolftpm_config: --enable-pqc --enable-mldsa=sign-only --enable-mlkem=all --disable-fwtpm --disable-examples + - name: cli-mldsa_signonly-mlkem_enc + wolftpm_config: --enable-pqc --enable-mldsa=sign-only --enable-mlkem=enc --disable-fwtpm --disable-examples + - name: cli-mldsa_signonly-mlkem_dec + wolftpm_config: --enable-pqc --enable-mldsa=sign-only --enable-mlkem=dec --disable-fwtpm --disable-examples + - name: cli-mldsa_signonly-mlkem_no + wolftpm_config: --enable-pqc --enable-mldsa=sign-only --enable-mlkem=no --disable-fwtpm --disable-examples + - name: cli-mldsa_verifyonly-mlkem_all + wolftpm_config: --enable-pqc --enable-mldsa=verify-only --enable-mlkem=all --disable-fwtpm --disable-examples + - name: cli-mldsa_verifyonly-mlkem_enc + wolftpm_config: --enable-pqc --enable-mldsa=verify-only --enable-mlkem=enc --disable-fwtpm --disable-examples + - name: cli-mldsa_verifyonly-mlkem_dec + wolftpm_config: --enable-pqc --enable-mldsa=verify-only --enable-mlkem=dec --disable-fwtpm --disable-examples + - name: cli-mldsa_verifyonly-mlkem_no + wolftpm_config: --enable-pqc --enable-mldsa=verify-only --enable-mlkem=no --disable-fwtpm --disable-examples + - name: cli-mldsa_no-mlkem_all + wolftpm_config: --enable-pqc --enable-mldsa=no --enable-mlkem=all --disable-fwtpm --disable-examples + - name: cli-mldsa_no-mlkem_enc + wolftpm_config: --enable-pqc --enable-mldsa=no --enable-mlkem=enc --disable-fwtpm --disable-examples + - name: cli-mldsa_no-mlkem_dec + wolftpm_config: --enable-pqc --enable-mldsa=no --enable-mlkem=dec --disable-fwtpm --disable-examples + - name: fw-mldsa_all-mlkem_all + wolftpm_config: --enable-pqc --enable-mldsa=all --enable-mlkem=all --enable-fwtpm --disable-examples + - name: fw-mldsa_all-mlkem_enc + wolftpm_config: --enable-pqc --enable-mldsa=all --enable-mlkem=enc --enable-fwtpm --disable-examples + - name: fw-mldsa_all-mlkem_dec + wolftpm_config: --enable-pqc --enable-mldsa=all --enable-mlkem=dec --enable-fwtpm --disable-examples + - name: fw-mldsa_all-mlkem_no + wolftpm_config: --enable-pqc --enable-mldsa=all --enable-mlkem=no --enable-fwtpm --disable-examples + - name: fw-mldsa_signonly-mlkem_all + wolftpm_config: --enable-pqc --enable-mldsa=sign-only --enable-mlkem=all --enable-fwtpm --disable-examples + - name: fw-mldsa_signonly-mlkem_enc + wolftpm_config: --enable-pqc --enable-mldsa=sign-only --enable-mlkem=enc --enable-fwtpm --disable-examples + - name: fw-mldsa_signonly-mlkem_dec + wolftpm_config: --enable-pqc --enable-mldsa=sign-only --enable-mlkem=dec --enable-fwtpm --disable-examples + - name: fw-mldsa_signonly-mlkem_no + wolftpm_config: --enable-pqc --enable-mldsa=sign-only --enable-mlkem=no --enable-fwtpm --disable-examples + - name: fw-mldsa_verifyonly-mlkem_all + wolftpm_config: --enable-pqc --enable-mldsa=verify-only --enable-mlkem=all --enable-fwtpm --disable-examples + - name: fw-mldsa_verifyonly-mlkem_enc + wolftpm_config: --enable-pqc --enable-mldsa=verify-only --enable-mlkem=enc --enable-fwtpm --disable-examples + - name: fw-mldsa_verifyonly-mlkem_dec + wolftpm_config: --enable-pqc --enable-mldsa=verify-only --enable-mlkem=dec --enable-fwtpm --disable-examples + - name: fw-mldsa_verifyonly-mlkem_no + wolftpm_config: --enable-pqc --enable-mldsa=verify-only --enable-mlkem=no --enable-fwtpm --disable-examples + - name: fw-mldsa_no-mlkem_all + wolftpm_config: --enable-pqc --enable-mldsa=no --enable-mlkem=all --enable-fwtpm --disable-examples + - name: fw-mldsa_no-mlkem_enc + wolftpm_config: --enable-pqc --enable-mldsa=no --enable-mlkem=enc --enable-fwtpm --disable-examples + - name: fw-mldsa_no-mlkem_dec + wolftpm_config: --enable-pqc --enable-mldsa=no --enable-mlkem=dec --enable-fwtpm --disable-examples + - name: cli-disable-pqc + wolftpm_config: --disable-pqc --disable-fwtpm --disable-examples + - name: cli-v185-full + wolftpm_config: --enable-v185 --disable-fwtpm --disable-examples + - name: cli-verifyencap-nohash + wolftpm_config: --enable-pqc --enable-mldsa=verify-only --enable-mlkem=enc --disable-hash-mldsa --disable-fwtpm --disable-examples + - name: fw-disable-pqc + wolftpm_config: --disable-pqc --enable-fwtpm --disable-examples + - name: fw-v185-full + wolftpm_config: --enable-v185 --enable-fwtpm --disable-examples + - name: fw-verifyencap-nohash + wolftpm_config: --enable-pqc --enable-mldsa=verify-only --enable-mlkem=enc --disable-hash-mldsa --enable-fwtpm --disable-examples + + steps: + - name: Checkout wolfTPM + uses: actions/checkout@v4 + + - name: Setup wolfSSL with PQC + uses: ./.github/actions/setup-wolfssl + with: + configure-flags: >- + --enable-wolftpm --enable-pkcallbacks --enable-keygen + --enable-dilithium --enable-mlkem --enable-experimental --enable-harden + --enable-aescfb + cflags: -DWC_RSA_NO_PADDING + + - name: Build wolfTPM (${{ 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: pqc-build-${{ 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. + if: github.event_name != 'pull_request' || github.event.pull_request.draft == false + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout wolfTPM + uses: actions/checkout@v4 + - name: Setup wolfSSL with PQC + uses: ./.github/actions/setup-wolfssl + with: + configure-flags: >- + --enable-wolftpm --enable-pkcallbacks --enable-keygen + --enable-dilithium --enable-mlkem --enable-experimental --enable-harden + --enable-aescfb + cflags: -DWC_RSA_NO_PADDING + - name: configure must reject mldsa=no + mlkem=no + run: | + ./autogen.sh + if ./configure --enable-pqc --enable-mldsa=no --enable-mlkem=no \ + --disable-fwtpm --disable-examples 2>err.log; then + echo "ERROR: configure accepted a no-PQC-algorithm build"; exit 1 + fi + grep -q "leaves no PQC algorithm" err.log \ + || { echo "ERROR: wrong/no error message"; cat err.log; exit 1; } + echo "PASS: rejected with the expected message" diff --git a/ChangeLog.md b/ChangeLog.md index 33bc0585..00238f71 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,21 @@ # Release Notes +## wolfTPM Release 4.1.0 (TBD) + +**Detail** + +* Added fine-grained post-quantum build macros so the v1.85 PQC footprint can be + trimmed to the operations actually used. New layered gates: `WOLFTPM_PQC` + (lean ML-DSA / ML-KEM, the new meaning of `--enable-pqc`) sits under the full + `WOLFTPM_V185`; `WOLFTPM_MLDSA` / `WOLFTPM_MLKEM` per algorithm; and + `WOLFTPM_MLDSA_SIGN` / `WOLFTPM_MLDSA_VERIFY` / `WOLFTPM_MLKEM_ENCAP` / + `WOLFTPM_MLKEM_DECAP` / `WOLFTPM_HASH_MLDSA` per operation, with matching + `WOLFTPM_NO_*` opt-outs resolved in `wolftpm/tpm2_pqc.h`. +* Added `--enable-mldsa[=all|sign-only|verify-only|no]`, + `--enable-mlkem[=all|enc|dec|no]`, and `--disable-hash-mldsa` configure flags + (mirroring the wolfSSL syntax). `--enable-pqc` now selects the lean PQC subset + and excludes the non-PQC v1.85 spec code; `--enable-v185` is unchanged (full). + ## wolfTPM Release 4.0.0 (Apr 22, 2026) **Summary** diff --git a/README.md b/README.md index f7744b34..bbe164bc 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Portable TPM 2.0 project designed for embedded use. * Support for HMAC Sessions. * Support for reading Endorsement certificates (EK Credential Profile). * Includes a portable firmware TPM 2.0 implementation (fwTPM, also known as fTPM / swtpm) for embedded platforms without a discrete TPM chip. See [Firmware TPM (fwTPM / fTPM / swtpm)](#firmware-tpm-fwtpm--ftpm--swtpm) below. -* **Post-quantum cryptography support** via TPM 2.0 Library Specification v1.85: ML-DSA (FIPS 204) signing and ML-KEM (FIPS 203) key encapsulation, enabled with `--enable-pqc` (alias for `--enable-v185`). Auto-detected when `--enable-fwtpm` is built against a wolfCrypt that has ML-DSA + ML-KEM. Both the client library and the fwTPM server implement the eight new v1.85 PQC commands. See [Post-Quantum Cryptography (v1.85)](#post-quantum-cryptography-v185) below. +* **Post-quantum cryptography support** via TPM 2.0 Library Specification v1.85: ML-DSA (FIPS 204) signing and ML-KEM (FIPS 203) key encapsulation, enabled with `--enable-v185` (full v1.85) or the leaner `--enable-pqc` (ML-DSA / ML-KEM only), with per-operation trimming via `--enable-mldsa`/`--enable-mlkem`. Auto-detected when `--enable-fwtpm` is built against a wolfCrypt that has ML-DSA + ML-KEM. Both the client library and the fwTPM server implement the eight new v1.85 PQC commands. See [Post-Quantum Cryptography (v1.85)](#post-quantum-cryptography-v185) below. * **SPDM attestation support** (DMTF DSP0274) over the TCG SPDM-over-TPM binding, with a TCG certificate handshake and a DSP0274 pre-shared-key (PSK) handshake, enabled with `--enable-spdm`. The fwTPM server includes an SPDM 1.3 responder so the stack can be exercised end-to-end in CI without discrete silicon. See [SPDM Attestation](#spdm-attestation) below. Note: See [examples/README.md](examples/README.md) for details on using the examples. @@ -101,10 +101,41 @@ sudo make install make ``` -`--enable-pqc` is an alias for `--enable-v185`; both turn on the same -WOLFTPM_V185 build flag. If you omit them but `--enable-fwtpm` is set -and wolfCrypt has ML-DSA + ML-KEM available, configure auto-detects -PQC and enables it. Pass `--disable-pqc` to opt out explicitly. +`--enable-v185` turns on the full v1.85 build (`WOLFTPM_V185`): the PQC +algorithms plus the non-PQC v1.85 spec additions. `--enable-pqc` turns on +just the lean PQC subset (`WOLFTPM_PQC`) — ML-DSA / ML-KEM only — which is +smaller for deployments that do not need the rest of v1.85. If you omit both +but `--enable-fwtpm` is set and wolfCrypt has ML-DSA + ML-KEM available, +configure auto-detects and enables full v1.85. Pass `--disable-pqc` to opt +out explicitly. + +#### Trimming the PQC footprint + +To compile only the operations you call (smaller binary, no malloc needed), +mirror the wolfSSL flags: + +``` +# ML-DSA verify-only + ML-KEM encapsulate-only (no sign, no decapsulate) +./configure --enable-pqc --enable-mldsa=verify-only --enable-mlkem=enc +``` + +| Flag | Values | Drops | +|------|--------|-------| +| `--enable-mldsa` | `all` (default) / `sign-only` / `verify-only` / `no` | the unselected ML-DSA operation | +| `--enable-mlkem` | `all` (default) / `enc` / `dec` / `no` | the unselected ML-KEM operation | +| `--disable-hash-mldsa` | — | pre-hash ML-DSA key support | + +These map to `WOLFTPM_NO_MLDSA_SIGN`, `WOLFTPM_NO_MLKEM_DECAP`, etc., which +embedded integrators can also pass directly via `CFLAGS` without autotools. +Existing `--enable-v185` builds are unaffected (every operation defaults on). +Disabling both algorithms (`--enable-mldsa=no --enable-mlkem=no`) is a configure +error — use `--disable-pqc` to build without any post-quantum support. + +The same flags also trim the fwTPM server: `--enable-fwtpm +--enable-mldsa=verify-only` builds a server that implements only ML-DSA verify +(the sign command handlers, dispatch entries, and crypto are compiled out). +fwTPM always builds the full v1.85 spec surface, so the trims apply on top of +`WOLFTPM_V185`. ### Running the examples diff --git a/configure.ac b/configure.ac index 48305131..2a56f5b3 100644 --- a/configure.ac +++ b/configure.ac @@ -787,20 +787,43 @@ AC_ARG_ENABLE([v185], [ ENABLED_V185=detect ] ) AC_ARG_ENABLE([pqc], - [AS_HELP_STRING([--enable-pqc],[Alias for --enable-v185 (post-quantum: ML-DSA / ML-KEM)])], + [AS_HELP_STRING([--enable-pqc],[Enable the lean post-quantum subset (ML-DSA / ML-KEM only, excludes the non-PQC v1.85 spec code that --enable-v185 adds)])], [ ENABLED_PQC=$enableval ], [ ENABLED_PQC=detect ] ) -# An explicit "yes" on either flag wins. An explicit "no" on either -# disables. Mixed (e.g. --enable-pqc + --disable-v185) treats explicit -# "no" as the safer choice and disables. +# Per-algorithm / per-operation trimming, mirroring the wolfSSL flag syntax. +# These only take effect when PQC (or v1.85) is enabled; default is everything. +AC_ARG_ENABLE([mldsa], + [AS_HELP_STRING([--enable-mldsa@<:@=all|sign-only|verify-only|no@:>@],[Limit wolfTPM ML-DSA support (default: all)])], + [ ENABLED_TPM_MLDSA=$enableval ], + [ ENABLED_TPM_MLDSA=all ] + ) +AC_ARG_ENABLE([mlkem], + [AS_HELP_STRING([--enable-mlkem@<:@=all|enc|dec|no@:>@],[Limit wolfTPM ML-KEM support (default: all)])], + [ ENABLED_TPM_MLKEM=$enableval ], + [ ENABLED_TPM_MLKEM=all ] + ) +AC_ARG_ENABLE([hash-mldsa], + [AS_HELP_STRING([--disable-hash-mldsa],[Drop pre-hash ML-DSA key support (default: enabled with ML-DSA)])], + [ ENABLED_TPM_HASH_MLDSA=$enableval ], + [ ENABLED_TPM_HASH_MLDSA=yes ] + ) + +# Resolve the entry points into one mode: no / pqc (lean) / v185 (full). +# --enable-v185 => full v1.85 (non-PQC spec code + PQC), also defines PQC +# --enable-pqc => lean PQC subset only (smaller) +# An explicit "no" on either disables. --enable-v185 wins over --enable-pqc. +ENABLED_PQC_MODE=no if test "x$ENABLED_V185" = "xno" || test "x$ENABLED_PQC" = "xno" then - ENABLED_V185=no -elif test "x$ENABLED_V185" = "xyes" || test "x$ENABLED_PQC" = "xyes" + ENABLED_PQC_MODE=no +elif test "x$ENABLED_V185" = "xyes" +then + ENABLED_PQC_MODE=v185 +elif test "x$ENABLED_PQC" = "xyes" then - ENABLED_V185=yes + ENABLED_PQC_MODE=pqc else # Neither flag specified — try auto-detect, but only when the natural # consumer (fwTPM + wolfCrypt) is being built. Without fwTPM there is @@ -832,17 +855,21 @@ else if test "x$WOLFTPM_HAVE_MLDSA_FN" = "xyes" && \ test "x$WOLFTPM_HAVE_MLKEM_FN" = "xyes" then - AC_MSG_NOTICE([wolfCrypt ML-DSA + ML-KEM detected; auto-enabling --enable-v185 (use --disable-v185 or --disable-pqc to opt out)]) - ENABLED_V185=yes - else - ENABLED_V185=no + AC_MSG_NOTICE([wolfCrypt ML-DSA + ML-KEM detected; auto-enabling --enable-v185 (use --disable-v185/--disable-pqc to opt out, or --enable-pqc for the lean PQC subset)]) + ENABLED_PQC_MODE=v185 fi - else - ENABLED_V185=no fi fi -if test "x$ENABLED_V185" = "xyes" +# fwTPM server source is gated on WOLFTPM_V185; the lean PQC subset targets +# the client library. If building fwTPM, promote lean PQC to full v1.85. +if test "x$ENABLED_PQC_MODE" = "xpqc" && test "x$ENABLED_FWTPM" = "xyes" +then + AC_MSG_NOTICE([fwTPM requires full v1.85; promoting --enable-pqc to --enable-v185]) + ENABLED_PQC_MODE=v185 +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 @@ -874,9 +901,41 @@ then [AC_MSG_RESULT([no]) AC_MSG_ERROR([wolfTPM PQC requires wolfSSL >= v5.8.0-stable. Please upgrade wolfSSL.])]) - AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_V185" + if test "x$ENABLED_PQC_MODE" = "xv185" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_V185" + else + AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_PQC" + fi + + # Per-algorithm / per-operation trimming (emit WOLFTPM_NO_* opt-outs). + case "x$ENABLED_TPM_MLDSA" in + xall|xyes) ;; + xno) AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_NO_MLDSA" ;; + xsign-only) AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_NO_MLDSA_VERIFY" ;; + xverify-only) AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_NO_MLDSA_SIGN" ;; + *) AC_MSG_ERROR([invalid --enable-mldsa=$ENABLED_TPM_MLDSA (use all|sign-only|verify-only|no)]) ;; + esac + case "x$ENABLED_TPM_MLKEM" in + xall|xyes) ;; + xno) AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_NO_MLKEM" ;; + xenc) AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_NO_MLKEM_DECAP" ;; + xdec) AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_NO_MLKEM_ENCAP" ;; + *) AC_MSG_ERROR([invalid --enable-mlkem=$ENABLED_TPM_MLKEM (use all|enc|dec|no)]) ;; + esac + # v1.85 is a post-quantum spec; enabling it with no PQC algorithm at all + # is contradictory — point the user at --disable-pqc instead. + if test "x$ENABLED_TPM_MLDSA" = "xno" && test "x$ENABLED_TPM_MLKEM" = "xno" + then + AC_MSG_ERROR([--enable-pqc/--enable-v185 with both --enable-mldsa=no and --enable-mlkem=no leaves no PQC algorithm; use --disable-pqc to build without post-quantum support]) + fi + if test "x$ENABLED_TPM_HASH_MLDSA" = "xno" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_NO_HASH_MLDSA" + fi fi -AM_CONDITIONAL([BUILD_V185], [test "x$ENABLED_V185" = "xyes"]) +AM_CONDITIONAL([BUILD_V185], [test "x$ENABLED_PQC_MODE" = "xv185"]) +AM_CONDITIONAL([BUILD_PQC], [test "x$ENABLED_PQC_MODE" != "xno"]) # HARDEN FLAGS AX_HARDEN_CC_COMPILER_FLAGS @@ -1075,3 +1134,10 @@ echo " * fwTPM TIS/SHM: $ENABLED_FWTPM_TIS" echo " * Runtime Module Detection: $ENABLED_AUTODETECT" echo " * Firmware Upgrade Support: $ENABLED_FIRMWARE" echo " * SPDM Support: $ENABLED_SPDM" +echo " * Post-Quantum (v185/pqc): $ENABLED_PQC_MODE" +if test "x$ENABLED_PQC_MODE" != "xno" +then +echo " ML-DSA: $ENABLED_TPM_MLDSA" +echo " ML-KEM: $ENABLED_TPM_MLKEM" +echo " Hash-ML-DSA: $ENABLED_TPM_HASH_MLDSA" +fi diff --git a/examples/bench/bench.c b/examples/bench/bench.c index 437a86d1..64f1868d 100644 --- a/examples/bench/bench.c +++ b/examples/bench/bench.c @@ -215,7 +215,7 @@ static int bench_sym_aes(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* storageKey, return rc; } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* Benchmark Pure ML-DSA: key gen, sign and verify (sign/verify sequence). */ static int bench_pqc_mldsa(WOLFTPM2_DEV* dev, double maxDuration, double maxKeyGenDurSec) @@ -353,7 +353,7 @@ static int bench_pqc_mlkem(WOLFTPM2_DEV* dev, double maxDuration, wolfTPM2_UnloadHandle(dev, &mlkemKey.handle); return rc; } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ static void usage(void) { @@ -677,7 +677,7 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) rc = wolfTPM2_UnloadHandle(&dev, &eccKey.handle); if (rc != 0) goto exit; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* Post-quantum (TPM 2.0 v1.85). Skipped under parameter encryption: the * large PQC public-key responses exceed the parameter-decryption buffer * (TPM_RC_... BUFFER_E). Free the storage key first so the larger PQC keys diff --git a/examples/keygen/keygen.c b/examples/keygen/keygen.c index c0f59aad..2c87065c 100644 --- a/examples/keygen/keygen.c +++ b/examples/keygen/keygen.c @@ -75,7 +75,7 @@ static void usage(void) printf("* -sym: Use Symmetric Cipher for key generation\n"); printf("\tDefault Symmetric Cipher is AES CTR with 256 bits\n"); printf("* -keyedhash: Use Keyed Hash for key generation\n"); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC printf("* -mldsa[=44|65|87]: Use ML-DSA for signing (v1.85, default 65)\n"); printf("* -hash_mldsa[=44|65|87]: Use Hash-ML-DSA for signing " "(v1.85, default 65 with SHA-256 pre-hash)\n"); @@ -102,7 +102,7 @@ static void usage(void) printf("\t* Symmetric key, AES, CBC mode, 128 bits, "\ "with XOR parameter encryption\n"); printf("\t\t keygen -sym=aescbc256 -xor\n"); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC printf("\t* ML-DSA-65 signing key\n"); printf("\t\t keygen -mldsa\n"); printf("\t* Hash-ML-DSA-87 with SHA-256 pre-hash\n"); @@ -112,7 +112,7 @@ static void usage(void) #endif } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC static int mldsaParamSet(const char* optVal, TPMI_MLDSA_PARAMETER_SET* ps) { int n = XATOI(optVal); @@ -136,7 +136,7 @@ static int mlkemParamSet(const char* optVal, TPMI_MLKEM_PARAMETER_SET* ps) default: return TPM_RC_FAILURE; } } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ static int symChoice(const char* symMode, TPM_ALG_ID* algSym, int* keyBits) { @@ -176,7 +176,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) TPMI_ALG_PUBLIC srkAlg = TPM_ALG_RSA; /* default matches seal.c / keyload.c */ TPM_ALG_ID algSym = TPM_ALG_CTR; /* default Symmetric Cipher, see usage */ TPM_ALG_ID paramEncAlg = TPM_ALG_NULL; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC TPMI_MLDSA_PARAMETER_SET mldsaPs = TPM_MLDSA_65; /* default */ TPMI_MLKEM_PARAMETER_SET mlkemPs = TPM_MLKEM_768; /* default */ #endif @@ -228,7 +228,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) alg = TPM_ALG_KEYEDHASH; bAIK = 0; } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC else if (XSTRCMP(argv[argc-1], "-mldsa") == 0 || XSTRNCMP(argv[argc-1], "-mldsa=", XSTRLEN("-mldsa=")) == 0) { @@ -265,7 +265,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) alg = TPM_ALG_MLKEM; bAIK = 0; } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ else if (XSTRCMP(argv[argc-1], "-t") == 0) { bAIK = 0; } @@ -405,7 +405,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) "not symmetric or keyedhash keys.\n"); rc = BAD_FUNC_ARG; } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC else if (alg == TPM_ALG_MLDSA || alg == TPM_ALG_HASH_MLDSA || alg == TPM_ALG_MLKEM) { printf("AIK template is RSA or ECC only; PQC keys use their " @@ -454,7 +454,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) TPM_ALG_SHA256, YES, NO); publicTemplate.objectAttributes |= TPMA_OBJECT_sensitiveDataOrigin; } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC else if (alg == TPM_ALG_MLDSA) { printf("ML-DSA template (parameter set %u)\n", (unsigned)mldsaPs); @@ -484,7 +484,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) TPMA_OBJECT_userWithAuth | TPMA_OBJECT_noDA, mlkemPs); } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ else { rc = BAD_FUNC_ARG; } diff --git a/examples/pqc/include.am b/examples/pqc/include.am index fe0864a6..bcd01959 100644 --- a/examples/pqc/include.am +++ b/examples/pqc/include.am @@ -2,7 +2,7 @@ # All paths should be given relative to the root if BUILD_EXAMPLES -if BUILD_V185 +if BUILD_PQC noinst_PROGRAMS += examples/pqc/pqc_mssim_e2e examples_pqc_pqc_mssim_e2e_SOURCES = examples/pqc/pqc_mssim_e2e.c diff --git a/examples/pqc/mldsa_sign.c b/examples/pqc/mldsa_sign.c index 783ba598..5423402b 100644 --- a/examples/pqc/mldsa_sign.c +++ b/examples/pqc/mldsa_sign.c @@ -40,7 +40,8 @@ #include #include -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_V185) +#if !defined(WOLFTPM2_NO_WRAPPER) && \ + defined(WOLFTPM_MLDSA_SIGN) && defined(WOLFTPM_MLDSA_VERIFY) static void usage(void) { @@ -199,12 +200,13 @@ static int mldsa_sign_run(int argc, char *argv[]) return rc; } -#endif /* !WOLFTPM2_NO_WRAPPER && WOLFTPM_V185 */ +#endif /* !WOLFTPM2_NO_WRAPPER && PQC ops */ #ifndef NO_MAIN_DRIVER int main(int argc, char *argv[]) { -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_V185) +#if !defined(WOLFTPM2_NO_WRAPPER) && \ + defined(WOLFTPM_MLDSA_SIGN) && defined(WOLFTPM_MLDSA_VERIFY) int rc = mldsa_sign_run(argc, argv); return (rc == 0) ? 0 : 1; #else diff --git a/examples/pqc/mldsa_verify_neg.c b/examples/pqc/mldsa_verify_neg.c index c25a4f30..a9797c54 100644 --- a/examples/pqc/mldsa_verify_neg.c +++ b/examples/pqc/mldsa_verify_neg.c @@ -34,7 +34,8 @@ #include #include -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_V185) +#if !defined(WOLFTPM2_NO_WRAPPER) && \ + defined(WOLFTPM_MLDSA_SIGN) && defined(WOLFTPM_MLDSA_VERIFY) static void usage(void) { @@ -238,12 +239,13 @@ static int mldsa_verify_neg_run(int argc, char *argv[]) return rc; } -#endif /* !WOLFTPM2_NO_WRAPPER && WOLFTPM_V185 */ +#endif /* !WOLFTPM2_NO_WRAPPER && PQC ops */ #ifndef NO_MAIN_DRIVER int main(int argc, char *argv[]) { -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_V185) +#if !defined(WOLFTPM2_NO_WRAPPER) && \ + defined(WOLFTPM_MLDSA_SIGN) && defined(WOLFTPM_MLDSA_VERIFY) int rc = mldsa_verify_neg_run(argc, argv); return (rc == 0) ? 0 : 1; #else diff --git a/examples/pqc/mlkem_decap_neg.c b/examples/pqc/mlkem_decap_neg.c index ed072d2c..01741d98 100644 --- a/examples/pqc/mlkem_decap_neg.c +++ b/examples/pqc/mlkem_decap_neg.c @@ -35,7 +35,8 @@ #include #include -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_V185) +#if !defined(WOLFTPM2_NO_WRAPPER) && \ + defined(WOLFTPM_MLKEM_ENCAP) && defined(WOLFTPM_MLKEM_DECAP) static void usage(void) { @@ -194,12 +195,13 @@ static int mlkem_decap_neg_run(int argc, char *argv[]) return rc; } -#endif /* !WOLFTPM2_NO_WRAPPER && WOLFTPM_V185 */ +#endif /* !WOLFTPM2_NO_WRAPPER && PQC ops */ #ifndef NO_MAIN_DRIVER int main(int argc, char *argv[]) { -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_V185) +#if !defined(WOLFTPM2_NO_WRAPPER) && \ + defined(WOLFTPM_MLKEM_ENCAP) && defined(WOLFTPM_MLKEM_DECAP) int rc = mlkem_decap_neg_run(argc, argv); return (rc == 0) ? 0 : 1; #else diff --git a/examples/pqc/mlkem_encap.c b/examples/pqc/mlkem_encap.c index e7e68709..f9bbeb94 100644 --- a/examples/pqc/mlkem_encap.c +++ b/examples/pqc/mlkem_encap.c @@ -33,7 +33,8 @@ #include #include -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_V185) +#if !defined(WOLFTPM2_NO_WRAPPER) && \ + defined(WOLFTPM_MLKEM_ENCAP) && defined(WOLFTPM_MLKEM_DECAP) static void usage(void) { @@ -174,12 +175,13 @@ static int mlkem_encap_run(int argc, char *argv[]) return rc; } -#endif /* !WOLFTPM2_NO_WRAPPER && WOLFTPM_V185 */ +#endif /* !WOLFTPM2_NO_WRAPPER && PQC ops */ #ifndef NO_MAIN_DRIVER int main(int argc, char *argv[]) { -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_V185) +#if !defined(WOLFTPM2_NO_WRAPPER) && \ + defined(WOLFTPM_MLKEM_ENCAP) && defined(WOLFTPM_MLKEM_DECAP) int rc = mlkem_encap_run(argc, argv); return (rc == 0) ? 0 : 1; #else diff --git a/examples/pqc/pqc_mssim_e2e.c b/examples/pqc/pqc_mssim_e2e.c index c4b733d4..ef3c2428 100644 --- a/examples/pqc/pqc_mssim_e2e.c +++ b/examples/pqc/pqc_mssim_e2e.c @@ -34,7 +34,10 @@ #include #include -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_V185) +#if !defined(WOLFTPM2_NO_WRAPPER) && \ + defined(WOLFTPM_MLDSA_SIGN) && defined(WOLFTPM_MLDSA_VERIFY) && \ + defined(WOLFTPM_MLKEM_ENCAP) && defined(WOLFTPM_MLKEM_DECAP) && \ + defined(WOLFTPM_HASH_MLDSA) /* Guard against the CopyPubT-class bug where the server-side key exists * and the handle works, but the client-side TPM2B buffer is zero-filled @@ -245,11 +248,11 @@ int main(int argc, char** argv) return 1; } -#else /* !WOLFTPM_V185 || WOLFTPM2_NO_WRAPPER */ +#else /* PQC ops not all enabled, or no wrapper */ int main(void) { - printf("pqc_mssim_e2e: WOLFTPM_V185 + wrapper API required; skipping.\n"); + printf("pqc_mssim_e2e: PQC (ML-DSA+ML-KEM) + wrapper API required; skipping.\n"); return 77; /* autoconf convention for SKIP */ } diff --git a/examples/run_examples.sh b/examples/run_examples.sh index 175872ff..00ef0d0c 100755 --- a/examples/run_examples.sh +++ b/examples/run_examples.sh @@ -25,7 +25,7 @@ fi if [ -z "$WOLFCRYPT_RSA" ]; then WOLFCRYPT_RSA=1 fi -# Detect WOLFTPM_V185 (post-quantum keys). Probe several known generated / +# Detect WOLFTPM_V185/WOLFTPM_PQC (post-quantum keys). Probe several known generated / # installed header locations: autoconf may write src/config.h or config.h # depending on AC_CONFIG_HEADERS, and tracked headers under wolftpm/ may # also gate the macro. ENABLE_V185 may be set by the caller to override. @@ -34,7 +34,7 @@ if [ -z "$ENABLE_V185" ]; then for cfg in src/config.h config.h ../src/config.h ../config.h \ wolftpm/options.h wolftpm/version.h; do if [ -f "$cfg" ] && grep -qE \ - '^[[:space:]]*#[[:space:]]*define[[:space:]]+WOLFTPM_V185([[:space:]]|$)' \ + '^[[:space:]]*#[[:space:]]*define[[:space:]]+WOLFTPM_(V185|PQC)([[:space:]]|$)' \ "$cfg"; then ENABLE_V185=1 break diff --git a/src/fwtpm/fwtpm_command.c b/src/fwtpm/fwtpm_command.c index e6930236..187920f5 100644 --- a/src/fwtpm/fwtpm_command.c +++ b/src/fwtpm/fwtpm_command.c @@ -73,7 +73,7 @@ static TPM_RC FwNvCheckAccess(TPM_HANDLE authHandle, TPMI_RH_NV_INDEX nvHandle, UINT32 attributes, int isWrite); #endif static FWTPM_Object* FwFindObject(FWTPM_CTX* ctx, TPM_HANDLE handle); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA static FWTPM_SignSeq* FwFindSignSeq(FWTPM_CTX* ctx, TPM_HANDLE handle); #endif static FWTPM_HashSeq* FwFindHashSeq(FWTPM_CTX* ctx, TPM_HANDLE handle); @@ -440,7 +440,7 @@ static void FwLookupEntityAuth(FWTPM_CTX* ctx, TPM_HANDLE handle, *authVal = seqEnt->authValue.buffer; *authValSz = seqEnt->authValue.size; } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA else { /* v1.85 sign/verify sequences also carry their own * authValue. Without this lookup the password/HMAC @@ -642,7 +642,7 @@ static int FwComputeSessionHmac(FWTPM_Session* sess, static void FwFlushAllObjects(FWTPM_CTX* ctx); static void FwFlushAllSessions(FWTPM_CTX* ctx); static void FwFreeHashSeq(FWTPM_HashSeq* seq); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA static void FwFreeSignSeq(FWTPM_SignSeq* seq); #endif @@ -686,7 +686,7 @@ static TPM_RC FwCmd_Startup(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, FwFreeHashSeq(&ctx->hashSeq[i]); } } - #ifdef WOLFTPM_V185 + #ifdef WOLFTPM_MLDSA for (i = 0; i < FWTPM_MAX_SIGN_SEQ; i++) { if (ctx->signSeq[i].used) { FwFreeSignSeq(&ctx->signSeq[i]); @@ -2446,7 +2446,7 @@ void FWTPM_ResetCommandClient(FWTPM_CTX* ctx) FwFreeHashSeq(&ctx->hashSeq[i]); } } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA for (i = 0; i < FWTPM_MAX_SIGN_SEQ; i++) { if (ctx->signSeq[i].used) { FwFreeSignSeq(&ctx->signSeq[i]); @@ -2707,7 +2707,7 @@ static TPM_RC FwCmd_CreatePrimary(FWTPM_CTX* ctx, TPM2_Packet* cmd, } #endif /* HAVE_ECC */ -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA /* ML-DSA primary key: derive 32-byte seed xi via KDFa, then run * FIPS 204 deterministic keygen. Private material on the wire * is the seed itself per TCG Part 2 Table 210. */ @@ -2745,6 +2745,9 @@ static TPM_RC FwCmd_CreatePrimary(FWTPM_CTX* ctx, TPM2_Packet* cmd, break; } +#endif /* WOLFTPM_MLDSA */ + +#ifdef WOLFTPM_MLKEM /* ML-KEM primary key: derive 64-byte seed (d||z) via KDFa, then * run FIPS 203 deterministic keygen. Private material on the * wire is the seed per TCG Part 2 Table 206. */ @@ -2762,7 +2765,7 @@ static TPM_RC FwCmd_CreatePrimary(FWTPM_CTX* ctx, TPM2_Packet* cmd, } break; } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ case TPM_ALG_KEYEDHASH: { /* HMAC key or sealed data object. @@ -2981,7 +2984,7 @@ static TPM_RC FwCmd_FlushContext(FWTPM_CTX* ctx, TPM2_Packet* cmd, FwFreeObject(obj); } else { - #ifdef WOLFTPM_V185 + #ifdef WOLFTPM_MLDSA FWTPM_SignSeq* seq = FwFindSignSeq(ctx, flushHandle); if (seq != NULL) { FwFreeSignSeq(seq); @@ -4109,7 +4112,7 @@ static TPM_RC FwCmd_Create(FWTPM_CTX* ctx, TPM2_Packet* cmd, break; } #endif /* HAVE_ECC */ -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA /* ML-DSA ordinary key: seed is random bytes (Part 1 Sec.24.6.2); * FIPS 204 keygen is then deterministic from the seed. */ case TPM_ALG_MLDSA: @@ -4141,7 +4144,9 @@ static TPM_RC FwCmd_Create(FWTPM_CTX* ctx, TPM2_Packet* cmd, } break; } +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_MLKEM case TPM_ALG_MLKEM: { TPMI_MLKEM_PARAMETER_SET ps = inPublic->publicArea.parameters.mlkemDetail.parameterSet; @@ -4158,7 +4163,7 @@ static TPM_RC FwCmd_Create(FWTPM_CTX* ctx, TPM2_Packet* cmd, } break; } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ case TPM_ALG_KEYEDHASH: { /* HMAC key or data object. * If caller supplied sensitive.data, use it as the key @@ -6125,7 +6130,7 @@ static TPM_RC FwCmd_CreateLoaded(FWTPM_CTX* ctx, TPM2_Packet* cmd, break; } #endif /* HAVE_ECC */ -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA /* ML-DSA ordinary key: seed is random bytes (Part 1 Sec.24.6.2); * FIPS 204 keygen is then deterministic from the seed. */ case TPM_ALG_MLDSA: @@ -6157,7 +6162,9 @@ static TPM_RC FwCmd_CreateLoaded(FWTPM_CTX* ctx, TPM2_Packet* cmd, } break; } +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_MLKEM case TPM_ALG_MLKEM: { TPMI_MLKEM_PARAMETER_SET ps = inPublic->publicArea.parameters.mlkemDetail.parameterSet; @@ -6174,7 +6181,7 @@ static TPM_RC FwCmd_CreateLoaded(FWTPM_CTX* ctx, TPM2_Packet* cmd, } break; } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ case TPM_ALG_KEYEDHASH: { TPMI_ALG_HASH hashAlg; TPMI_ALG_KEYEDHASH_SCHEME scheme = @@ -7390,7 +7397,7 @@ static TPM_RC FwCmd_SequenceUpdate(FWTPM_CTX* ctx, TPM2_Packet* cmd, UINT16 dataSize = 0; FWTPM_DECLARE_BUF(dataBuf, FWTPM_MAX_DATA_BUF); FWTPM_HashSeq* seq; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA FWTPM_SignSeq* signSeq = NULL; #endif @@ -7404,7 +7411,7 @@ static TPM_RC FwCmd_SequenceUpdate(FWTPM_CTX* ctx, TPM2_Packet* cmd, TPM2_Packet_ParseU32(cmd, &seqHandle); seq = FwFindHashSeq(ctx, seqHandle); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA if (seq == NULL) { /* Not a hash sequence — check sign/verify sequence slots. */ signSeq = FwFindSignSeq(ctx, seqHandle); @@ -7443,7 +7450,7 @@ static TPM_RC FwCmd_SequenceUpdate(FWTPM_CTX* ctx, TPM2_Packet* cmd, if (rc == 0) { TPM2_Packet_ParseBytes(cmd, dataBuf, dataSize); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA if (signSeq != NULL) { /* Capture leading bytes for the restricted-key * TPM_GENERATED_VALUE check (Part 3 Sec.20.6.1). For Hash-ML-DSA @@ -7540,7 +7547,7 @@ static TPM_RC FwCmd_SequenceComplete(FWTPM_CTX* ctx, TPM2_Packet* cmd, TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; int paramSzPos, paramStart; int trc; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA FWTPM_SignSeq* misRoutedSign = NULL; #endif @@ -7556,7 +7563,7 @@ static TPM_RC FwCmd_SequenceComplete(FWTPM_CTX* ctx, TPM2_Packet* cmd, seq = FwFindHashSeq(ctx, seqHandle); if (seq == NULL) { rc = TPM_RC_HANDLE; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA /* Free a sign/verify slot mis-routed here so it doesn't leak. */ misRoutedSign = FwFindSignSeq(ctx, seqHandle); if (misRoutedSign != NULL) FwFreeSignSeq(misRoutedSign); @@ -13686,11 +13693,11 @@ static TPM_RC FwCmd_Vendor_TCG_Test(FWTPM_CTX* ctx, TPM2_Packet* cmd, return rc; } -#ifdef WOLFTPM_V185 /* ================================================================== */ /* v1.85 PQC Commands */ /* ================================================================== */ +#ifdef WOLFTPM_MLKEM_ENCAP /* --- TPM2_Encapsulate (CC 0x01A7) --- */ static TPM_RC FwCmd_Encapsulate(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, TPM2_Packet* rsp, UINT16 cmdTag) @@ -13764,7 +13771,9 @@ static TPM_RC FwCmd_Encapsulate(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, FWTPM_FREE_VAR(ciphertext); return rc; } +#endif /* WOLFTPM_MLKEM_ENCAP */ +#ifdef WOLFTPM_MLKEM_DECAP /* --- TPM2_Decapsulate (CC 0x01A8) --- */ static TPM_RC FwCmd_Decapsulate(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, TPM2_Packet* rsp, UINT16 cmdTag) @@ -13871,7 +13880,9 @@ static TPM_RC FwCmd_Decapsulate(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, FWTPM_FREE_VAR(ciphertext); return rc; } +#endif /* WOLFTPM_MLKEM_DECAP */ +#ifdef WOLFTPM_MLDSA /* --- Sign/Verify sequence slot helpers --- */ static FWTPM_SignSeq* FwAllocSignSeq(FWTPM_CTX* ctx, TPM_HANDLE* handle) { @@ -13948,7 +13959,9 @@ static TPM_RC FwSignSeqInitHashCtx(FWTPM_SignSeq* seq, TPMI_ALG_HASH hashAlg) seq->hashCtxInit = 1; return TPM_RC_SUCCESS; } +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_MLDSA_SIGN /* --- TPM2_SignSequenceStart (CC 0x01AA) --- */ static TPM_RC FwCmd_SignSequenceStart(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, TPM2_Packet* rsp, UINT16 cmdTag) @@ -14124,7 +14137,9 @@ static TPM_RC FwCmd_SignSequenceStart(FWTPM_CTX* ctx, TPM2_Packet* cmd, } return rc; } +#endif /* WOLFTPM_MLDSA_SIGN */ +#ifdef WOLFTPM_MLDSA_VERIFY /* --- TPM2_VerifySequenceStart (CC 0x01A9) --- */ static TPM_RC FwCmd_VerifySequenceStart(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, TPM2_Packet* rsp, UINT16 cmdTag) @@ -14298,7 +14313,9 @@ static TPM_RC FwCmd_VerifySequenceStart(FWTPM_CTX* ctx, TPM2_Packet* cmd, } return rc; } +#endif /* WOLFTPM_MLDSA_VERIFY */ +#ifdef WOLFTPM_MLDSA_SIGN /* --- TPM2_SignSequenceComplete (CC 0x01A4) --- */ static TPM_RC FwCmd_SignSequenceComplete(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, TPM2_Packet* rsp, UINT16 cmdTag) @@ -14646,7 +14663,9 @@ static TPM_RC FwCmd_SignSequenceComplete(FWTPM_CTX* ctx, TPM2_Packet* cmd, FWTPM_FREE_VAR(sigOut); return rc; } +#endif /* WOLFTPM_MLDSA_SIGN */ +#ifdef WOLFTPM_MLDSA_VERIFY /* --- TPM2_VerifySequenceComplete (CC 0x01A3) --- */ static TPM_RC FwCmd_VerifySequenceComplete(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, TPM2_Packet* rsp, UINT16 cmdTag) @@ -14994,7 +15013,9 @@ static TPM_RC FwCmd_VerifySequenceComplete(FWTPM_CTX* ctx, TPM2_Packet* cmd, FWTPM_FREE_BUF(sigBuf); return rc; } +#endif /* WOLFTPM_MLDSA_VERIFY */ +#ifdef WOLFTPM_MLDSA_SIGN /* --- TPM2_SignDigest (CC 0x01A6) --- */ static TPM_RC FwCmd_SignDigest(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, TPM2_Packet* rsp, UINT16 cmdTag) @@ -15227,7 +15248,9 @@ static TPM_RC FwCmd_SignDigest(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, FWTPM_FREE_VAR(sigOut); return rc; } +#endif /* WOLFTPM_MLDSA_SIGN */ +#ifdef WOLFTPM_MLDSA_VERIFY /* --- TPM2_VerifyDigestSignature (CC 0x01A5) --- */ static TPM_RC FwCmd_VerifyDigestSignature(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, TPM2_Packet* rsp, UINT16 cmdTag) @@ -15462,7 +15485,7 @@ static TPM_RC FwCmd_VerifyDigestSignature(FWTPM_CTX* ctx, TPM2_Packet* cmd, FWTPM_FREE_BUF(sigBuf); return rc; } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLDSA_VERIFY */ /* ================================================================== */ /* Command Dispatch Table */ @@ -15634,15 +15657,21 @@ static const FWTPM_CMD_ENTRY fwCmdTable[] = { #endif /* --- Vendor --- */ { TPM_CC_Vendor_TCG_Test, FwCmd_Vendor_TCG_Test, 0, 0, 0, FW_CMD_FLAG_ENC | FW_CMD_FLAG_DEC }, -#ifdef WOLFTPM_V185 /* --- v1.85 PQC handlers --- */ +#ifdef WOLFTPM_MLKEM_ENCAP { TPM_CC_Encapsulate, FwCmd_Encapsulate, 1, 0, 0, FW_CMD_FLAG_DEC }, +#endif +#ifdef WOLFTPM_MLKEM_DECAP { TPM_CC_Decapsulate, FwCmd_Decapsulate, 1, 1, 0, FW_CMD_FLAG_ENC | FW_CMD_FLAG_DEC }, +#endif +#ifdef WOLFTPM_MLDSA_SIGN { TPM_CC_SignSequenceStart, FwCmd_SignSequenceStart, 1, 0, 1, FW_CMD_FLAG_ENC }, - { TPM_CC_VerifySequenceStart, FwCmd_VerifySequenceStart, 1, 0, 1, FW_CMD_FLAG_ENC }, { TPM_CC_SignSequenceComplete, FwCmd_SignSequenceComplete, 2, 2, 0, FW_CMD_FLAG_ENC }, - { TPM_CC_VerifySequenceComplete, FwCmd_VerifySequenceComplete, 2, 1, 0, 0 }, { TPM_CC_SignDigest, FwCmd_SignDigest, 1, 1, 0, FW_CMD_FLAG_ENC }, +#endif +#ifdef WOLFTPM_MLDSA_VERIFY + { TPM_CC_VerifySequenceStart, FwCmd_VerifySequenceStart, 1, 0, 1, FW_CMD_FLAG_ENC }, + { TPM_CC_VerifySequenceComplete, FwCmd_VerifySequenceComplete, 2, 1, 0, 0 }, { TPM_CC_VerifyDigestSignature, FwCmd_VerifyDigestSignature, 1, 0, 0, FW_CMD_FLAG_ENC }, #endif }; diff --git a/src/fwtpm/fwtpm_crypto.c b/src/fwtpm/fwtpm_crypto.c index 3cce0232..8c62f3e5 100644 --- a/src/fwtpm/fwtpm_crypto.c +++ b/src/fwtpm/fwtpm_crypto.c @@ -59,7 +59,7 @@ #include #endif #include -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC #include #include #include @@ -680,7 +680,7 @@ TPM_RC FwDeriveEccPrimaryKey(TPMI_ALG_HASH nameAlg, } #endif /* HAVE_ECC */ -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA /* ================================================================== */ /* v1.85 PQC primary-key derivation (ML-DSA / ML-KEM) */ /* ================================================================== */ @@ -703,6 +703,9 @@ static int FwGetWcMldsaLevel(TPMI_MLDSA_PARAMETER_SET ps) } } +#endif /* WOLFTPM_MLDSA */ + +#ifdef WOLFTPM_MLKEM /* Map TPM v1.85 ML-KEM parameter set to wolfCrypt ML-KEM type. */ static int FwGetWcMlkemType(TPMI_MLKEM_PARAMETER_SET ps) { @@ -714,6 +717,9 @@ static int FwGetWcMlkemType(TPMI_MLKEM_PARAMETER_SET ps) } } +#endif /* WOLFTPM_MLKEM */ + +#ifdef WOLFTPM_MLDSA /** \brief Derive 32-byte ML-DSA seed xi from hierarchy primary seed via KDFa. * Caller selects label: "MLDSA" for TPM_ALG_MLDSA or "HASH_MLDSA" for * TPM_ALG_HASH_MLDSA (interpretation, pending Part 4 v185 publication). @@ -733,6 +739,9 @@ TPM_RC FwDeriveMldsaPrimaryKeySeed(TPMI_ALG_HASH nameAlg, return TPM_RC_SUCCESS; } +#endif /* WOLFTPM_MLDSA */ + +#ifdef WOLFTPM_MLKEM /** \brief Derive 64-byte ML-KEM seed (d || z) from hierarchy primary seed * via KDFa using the label "MLKEM" (interpretation, pending Part 4 v185 * publication). The derived seed is fed into FIPS 203 deterministic @@ -752,6 +761,9 @@ TPM_RC FwDeriveMlkemPrimaryKeySeed(TPMI_ALG_HASH nameAlg, return TPM_RC_SUCCESS; } +#endif /* WOLFTPM_MLKEM */ + +#ifdef WOLFTPM_MLDSA /** \brief Generate ML-DSA keypair deterministically from a 32-byte seed xi * (FIPS 204 Algorithm 1 ML-DSA.KeyGen). Exports public key to pubOut. * The expanded private key is not returned — callers hold the 32-byte seed @@ -811,6 +823,9 @@ TPM_RC FwGenerateMldsaKey(TPMI_MLDSA_PARAMETER_SET parameterSet, return rc; } +#endif /* WOLFTPM_MLDSA */ + +#ifdef WOLFTPM_MLKEM /** \brief Generate ML-KEM keypair deterministically from a 64-byte seed (d||z) * (FIPS 203 Algorithm 16 ML-KEM.KeyGen_internal). Exports public key to * pubOut. Private key on the wire is the 64-byte seed per TCG Table 206. */ @@ -1368,6 +1383,9 @@ TPM_RC FwDecapsulateEcdhDhkem(WC_RNG* rng, const FWTPM_Object* recipObj, } #endif /* HAVE_ECC */ +#endif /* WOLFTPM_MLKEM */ + +#ifdef WOLFTPM_MLDSA /* Internal helper: rebuild a deterministic ML-DSA keypair from its stored * 32-byte xi seed and return a ready-to-use wc_MlDsaKey plus wcLevel. */ static TPM_RC FwLoadMldsaFromSeed(TPMI_MLDSA_PARAMETER_SET parameterSet, @@ -1639,7 +1657,7 @@ TPM_RC FwVerifyMldsaHash(TPMI_MLDSA_PARAMETER_SET parameterSet, FWTPM_FREE_VAR(keyVar); return rc; } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLDSA */ #ifndef NO_RSA #ifdef WOLFSSL_KEY_GEN @@ -2556,7 +2574,7 @@ TPM_RC FwDecryptSeed(FWTPM_CTX* ctx, } else #endif /* HAVE_ECC */ -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLKEM if (keyObj->pub.type == TPM_ALG_MLKEM) { /* ML-KEM Labeled KEM per Part 1 Sec.47.4 Eq.66: * K = ML-KEM.Decap(privateKey, ciphertext) @@ -2593,7 +2611,7 @@ TPM_RC FwDecryptSeed(FWTPM_CTX* ctx, (void)oaepLabel; (void)oaepLabelSz; } else -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ { (void)ctx; (void)encSeedBuf; (void)encSeedSz; (void)oaepLabel; (void)oaepLabelSz; (void)kdfLabel; @@ -2801,7 +2819,7 @@ TPM_RC FwEncryptSeed(FWTPM_CTX* ctx, } else #endif /* HAVE_ECC */ -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLKEM if (keyObj->pub.type == TPM_ALG_MLKEM) { /* ML-KEM Labeled KEM per Part 1 Sec.47.4 Eq.66: * (K, ciphertext) = ML-KEM.Encap(publicKey) @@ -2849,7 +2867,7 @@ TPM_RC FwEncryptSeed(FWTPM_CTX* ctx, (void)oaepLabel; (void)oaepLabelSz; } else -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ { (void)ctx; (void)oaepLabel; (void)oaepLabelSz; (void)kdfLabel; (void)seedBuf; (void)seedBufSz; (void)seedSzOut; diff --git a/src/tpm2.c b/src/tpm2.c index b97f6db3..7e295979 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -3249,7 +3249,7 @@ TPM_RC TPM2_VerifySignature(VerifySignature_In* in, TPM2_Packet_ParseU16(&packet, &out->validation.tag); TPM2_Packet_ParseU32(&packet, &out->validation.hierarchy); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA_VERIFY /* TPM2_VerifySignature should produce TPM_ST_VERIFIED (metadata * TPMS_EMPTY, no wire bytes) per Part 3 Sec.20.4.1. Parse * defensively so a non-conformant TPM returning @@ -3323,9 +3323,9 @@ TPM_RC TPM2_Sign(Sign_In* in, Sign_Out* out) return rc; } -#ifdef WOLFTPM_V185 /* Post-Quantum Cryptography (PQC) Commands - TPM 2.0 v185 */ +#ifdef WOLFTPM_MLDSA_SIGN TPM_RC TPM2_SignSequenceStart(SignSequenceStart_In* in, SignSequenceStart_Out* out) { @@ -3378,7 +3378,9 @@ TPM_RC TPM2_SignSequenceStart(SignSequenceStart_In* in, } return rc; } +#endif /* WOLFTPM_MLDSA_SIGN */ +#ifdef WOLFTPM_MLDSA_VERIFY TPM_RC TPM2_VerifySequenceStart(VerifySequenceStart_In* in, VerifySequenceStart_Out* out) { @@ -3430,7 +3432,9 @@ TPM_RC TPM2_VerifySequenceStart(VerifySequenceStart_In* in, } return rc; } +#endif /* WOLFTPM_MLDSA_VERIFY */ +#ifdef WOLFTPM_MLDSA_SIGN TPM_RC TPM2_SignSequenceComplete(SignSequenceComplete_In* in, SignSequenceComplete_Out* out) { @@ -3475,7 +3479,9 @@ TPM_RC TPM2_SignSequenceComplete(SignSequenceComplete_In* in, } return rc; } +#endif /* WOLFTPM_MLDSA_SIGN */ +#ifdef WOLFTPM_MLDSA_VERIFY TPM_RC TPM2_VerifySequenceComplete(VerifySequenceComplete_In* in, VerifySequenceComplete_Out* out) { @@ -3525,7 +3531,7 @@ TPM_RC TPM2_VerifySequenceComplete(VerifySequenceComplete_In* in, TPM2_Packet_ParseU16(&packet, &out->validation.tag); TPM2_Packet_ParseU32(&packet, &out->validation.hierarchy); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA_VERIFY /* Spec mandates TPM_ST_MESSAGE_VERIFIED here (Part 3 * Sec.20.3.1, TPMS_EMPTY metadata), but parse defensively in * case a non-conformant TPM returns DIGEST_VERIFIED -- mirrors @@ -3550,7 +3556,9 @@ TPM_RC TPM2_VerifySequenceComplete(VerifySequenceComplete_In* in, } return rc; } +#endif /* WOLFTPM_MLDSA_VERIFY */ +#ifdef WOLFTPM_MLDSA_SIGN TPM_RC TPM2_SignDigest(SignDigest_In* in, SignDigest_Out* out) { TPM_RC rc; @@ -3601,7 +3609,9 @@ TPM_RC TPM2_SignDigest(SignDigest_In* in, SignDigest_Out* out) } return rc; } +#endif /* WOLFTPM_MLDSA_SIGN */ +#ifdef WOLFTPM_MLDSA_VERIFY TPM_RC TPM2_VerifyDigestSignature(VerifyDigestSignature_In* in, VerifyDigestSignature_Out* out) { @@ -3648,7 +3658,7 @@ TPM_RC TPM2_VerifyDigestSignature(VerifyDigestSignature_In* in, TPM2_Packet_ParseU16(&packet, &out->validation.tag); TPM2_Packet_ParseU32(&packet, &out->validation.hierarchy); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA_VERIFY /* v185 rc4 Part 2 Sec.10.6.4 Table 110 — TPMU_TK_VERIFIED_META. * TPM2_VerifyDigestSignature produces TPM_ST_DIGEST_VERIFIED whose * metadata carries a TPM_ALG_ID (the hash/XOF used). Other tag @@ -3673,7 +3683,9 @@ TPM_RC TPM2_VerifyDigestSignature(VerifyDigestSignature_In* in, } return rc; } +#endif /* WOLFTPM_MLDSA_VERIFY */ +#ifdef WOLFTPM_MLKEM_ENCAP TPM_RC TPM2_Encapsulate(Encapsulate_In* in, Encapsulate_Out* out) { TPM_RC rc; @@ -3750,7 +3762,9 @@ TPM_RC TPM2_Encapsulate(Encapsulate_In* in, Encapsulate_Out* out) } return rc; } +#endif /* WOLFTPM_MLKEM_ENCAP */ +#ifdef WOLFTPM_MLKEM_DECAP TPM_RC TPM2_Decapsulate(Decapsulate_In* in, Decapsulate_Out* out) { TPM_RC rc; @@ -3806,7 +3820,7 @@ TPM_RC TPM2_Decapsulate(Decapsulate_In* in, Decapsulate_Out* out) } return rc; } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM_DECAP */ TPM_RC TPM2_SetCommandCodeAuditStatus(SetCommandCodeAuditStatus_In* in) { diff --git a/src/tpm2_packet.c b/src/tpm2_packet.c index df016816..338837b6 100644 --- a/src/tpm2_packet.c +++ b/src/tpm2_packet.c @@ -845,7 +845,7 @@ void TPM2_Packet_AppendSensitive(TPM2_Packet* packet, TPM2B_SENSITIVE* sensitive TPM2_Packet_AppendU16(packet, sens->sym.size); TPM2_Packet_AppendBytes(packet, sens->sym.buffer, sens->sym.size); break; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA case TPM_ALG_MLDSA: case TPM_ALG_HASH_MLDSA: if (sens->mldsa.size > sizeof(sens->mldsa.buffer)) @@ -853,13 +853,15 @@ void TPM2_Packet_AppendSensitive(TPM2_Packet* packet, TPM2B_SENSITIVE* sensitive TPM2_Packet_AppendU16(packet, sens->mldsa.size); TPM2_Packet_AppendBytes(packet, sens->mldsa.buffer, sens->mldsa.size); break; +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_MLKEM case TPM_ALG_MLKEM: if (sens->mlkem.size > sizeof(sens->mlkem.buffer)) sens->mlkem.size = sizeof(sens->mlkem.buffer); TPM2_Packet_AppendU16(packet, sens->mlkem.size); TPM2_Packet_AppendBytes(packet, sens->mlkem.buffer, sens->mlkem.size); break; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ } TPM2_Packet_PlaceU16(packet, tmpSz); @@ -908,7 +910,7 @@ void TPM2_Packet_ParseSensitive(TPM2_Packet* packet, TPM2B_SENSITIVE* sensitive) TPM2_Packet_ParseU16Buf(packet, &sens->sym.size, sens->sym.buffer, (UINT16)sizeof(sens->sym.buffer)); break; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA case TPM_ALG_MLDSA: case TPM_ALG_HASH_MLDSA: /* Mirror the AppendSensitive arms above so PQC TPM2B_SENSITIVE @@ -919,11 +921,13 @@ void TPM2_Packet_ParseSensitive(TPM2_Packet* packet, TPM2B_SENSITIVE* sensitive) TPM2_Packet_ParseU16Buf(packet, &sens->mldsa.size, sens->mldsa.buffer, (UINT16)sizeof(sens->mldsa.buffer)); break; +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_MLKEM case TPM_ALG_MLKEM: TPM2_Packet_ParseU16Buf(packet, &sens->mlkem.size, sens->mlkem.buffer, (UINT16)sizeof(sens->mlkem.buffer)); break; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ default: /* Unknown sensitiveType — skip composite to keep packet position * synchronized with the declared outer size */ @@ -1066,7 +1070,7 @@ void TPM2_Packet_AppendPublicParms(TPM2_Packet* packet, TPMI_ALG_PUBLIC type, TPM2_Packet_AppendU16(packet, parameters->eccDetail.curveID); TPM2_Packet_AppendKdfScheme(packet, ¶meters->eccDetail.kdf); break; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA case TPM_ALG_MLDSA: TPM2_Packet_AppendU16(packet, parameters->mldsaDetail.parameterSet); TPM2_Packet_AppendU8(packet, parameters->mldsaDetail.allowExternalMu); @@ -1075,11 +1079,13 @@ void TPM2_Packet_AppendPublicParms(TPM2_Packet* packet, TPMI_ALG_PUBLIC type, TPM2_Packet_AppendU16(packet, parameters->hash_mldsaDetail.parameterSet); TPM2_Packet_AppendU16(packet, parameters->hash_mldsaDetail.hashAlg); break; +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_MLKEM case TPM_ALG_MLKEM: TPM2_Packet_AppendSymmetric(packet, ¶meters->mlkemDetail.symmetric); TPM2_Packet_AppendU16(packet, parameters->mlkemDetail.parameterSet); break; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ default: TPM2_Packet_AppendSymmetric(packet, ¶meters->asymDetail.symmetric); TPM2_Packet_AppendAsymScheme(packet, ¶meters->asymDetail.scheme); @@ -1109,7 +1115,7 @@ void TPM2_Packet_ParsePublicParms(TPM2_Packet* packet, TPMI_ALG_PUBLIC type, TPM2_Packet_ParseU16(packet, ¶meters->eccDetail.curveID); TPM2_Packet_ParseKdfScheme(packet, ¶meters->eccDetail.kdf); break; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA case TPM_ALG_MLDSA: TPM2_Packet_ParseU16(packet, ¶meters->mldsaDetail.parameterSet); TPM2_Packet_ParseU8(packet, (BYTE*)¶meters->mldsaDetail.allowExternalMu); @@ -1118,11 +1124,13 @@ void TPM2_Packet_ParsePublicParms(TPM2_Packet* packet, TPMI_ALG_PUBLIC type, TPM2_Packet_ParseU16(packet, ¶meters->hash_mldsaDetail.parameterSet); TPM2_Packet_ParseU16(packet, (UINT16*)¶meters->hash_mldsaDetail.hashAlg); break; +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_MLKEM case TPM_ALG_MLKEM: TPM2_Packet_ParseSymmetric(packet, ¶meters->mlkemDetail.symmetric); TPM2_Packet_ParseU16(packet, ¶meters->mlkemDetail.parameterSet); break; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ default: TPM2_Packet_ParseSymmetric(packet, ¶meters->asymDetail.symmetric); TPM2_Packet_ParseAsymScheme(packet, ¶meters->asymDetail.scheme); @@ -1161,19 +1169,21 @@ void TPM2_Packet_AppendPublicArea(TPM2_Packet* packet, TPMT_PUBLIC* publicArea) case TPM_ALG_ECC: TPM2_Packet_AppendEccPoint(packet, &publicArea->unique.ecc); break; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA case TPM_ALG_MLDSA: case TPM_ALG_HASH_MLDSA: TPM2_Packet_AppendU16(packet, publicArea->unique.mldsa.size); TPM2_Packet_AppendBytes(packet, publicArea->unique.mldsa.buffer, publicArea->unique.mldsa.size); break; +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_MLKEM case TPM_ALG_MLKEM: TPM2_Packet_AppendU16(packet, publicArea->unique.mlkem.size); TPM2_Packet_AppendBytes(packet, publicArea->unique.mlkem.buffer, publicArea->unique.mlkem.size); break; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ default: /* TPMS_DERIVE derive; ? */ break; @@ -1229,7 +1239,7 @@ void TPM2_Packet_ParsePublic(TPM2_Packet* packet, TPM2B_PUBLIC* pub) case TPM_ALG_ECC: TPM2_Packet_ParseEccPoint(packet, &pub->publicArea.unique.ecc); break; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA case TPM_ALG_MLDSA: case TPM_ALG_HASH_MLDSA: { @@ -1248,6 +1258,8 @@ void TPM2_Packet_ParsePublic(TPM2_Packet* packet, TPM2B_PUBLIC* pub) } break; } +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_MLKEM case TPM_ALG_MLKEM: { UINT16 wireSize; @@ -1265,7 +1277,7 @@ void TPM2_Packet_ParsePublic(TPM2_Packet* packet, TPM2B_PUBLIC* pub) } break; } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ default: /* TPMS_DERIVE derive; ? */ break; @@ -1324,7 +1336,7 @@ void TPM2_Packet_AppendSignature(TPM2_Packet* packet, TPMT_SIGNATURE* sig) case TPM_ALG_NULL: /* Legitimate zero-payload signature - nothing to append. */ break; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA /* v185 rc4 Part 2 Sec.11.3.5 Table 217 note: Pure ML-DSA is a TPM2B * (size + bytes, no hash field); HashML-DSA is a TPMS (hash + size + bytes). * The union arms differ in type; the switch dispatches accordingly. */ @@ -1341,7 +1353,7 @@ void TPM2_Packet_AppendSignature(TPM2_Packet* packet, TPMT_SIGNATURE* sig) sig->signature.hash_mldsa.signature.buffer, sig->signature.hash_mldsa.signature.size); break; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLDSA */ default: #ifdef DEBUG_WOLFTPM printf("AppendSignature: unrecognized sigAlg 0x%x\n", sig->sigAlg); @@ -1420,7 +1432,7 @@ void TPM2_Packet_ParseSignature(TPM2_Packet* packet, TPMT_SIGNATURE* sig) case TPM_ALG_NULL: /* Legitimate zero-payload signature - nothing to consume. */ break; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA case TPM_ALG_MLDSA: /* Pure ML-DSA signature is a bare TPM2B: size + bytes, no hash. */ TPM2_Packet_ParseU16(packet, &wireSize); @@ -1456,7 +1468,7 @@ void TPM2_Packet_ParseSignature(TPM2_Packet* packet, TPMT_SIGNATURE* sig) wireSize - sig->signature.hash_mldsa.signature.size); } break; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLDSA */ default: #ifdef DEBUG_WOLFTPM printf("ParseSignature: unrecognized sigAlg 0x%x\n", sig->sigAlg); diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 6fd1fc5b..bc1d8de1 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -2283,7 +2283,7 @@ static int wolfTPM2_EncryptSecret_RSA(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* tpm } #endif /* !WOLFTPM2_NO_WOLFCRYPT && !NO_RSA && !WC_NO_RNG */ -#if defined(WOLFTPM_V185) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ +#if defined(WOLFTPM_MLKEM_ENCAP) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ (defined(WOLFSSL_HAVE_MLKEM) || defined(WOLFSSL_KYBER512) || \ defined(WOLFSSL_KYBER768) || defined(WOLFSSL_KYBER1024)) #if defined(HAVE_LIBOQS) @@ -2412,7 +2412,7 @@ static int wolfTPM2_EncryptSecret_MLKEM(const WOLFTPM2_KEY* tpmKey, return rc; } -#endif /* WOLFTPM_V185 && ML-KEM enabled */ +#endif /* WOLFTPM_MLKEM_ENCAP && ML-KEM enabled */ int wolfTPM2_EncryptSecret(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* tpmKey, TPM2B_DATA *data, TPM2B_ENCRYPTED_SECRET *secret, @@ -2446,7 +2446,7 @@ int wolfTPM2_EncryptSecret(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* tpmKey, rc = wolfTPM2_EncryptSecret_RSA(dev, tpmKey, data, secret, label); break; #endif - #if defined(WOLFTPM_V185) && \ + #if defined(WOLFTPM_MLKEM_ENCAP) && \ (defined(WOLFSSL_HAVE_MLKEM) || defined(WOLFSSL_KYBER512) || \ defined(WOLFSSL_KYBER768) || defined(WOLFSSL_KYBER1024)) case TPM_ALG_MLKEM: @@ -5413,9 +5413,9 @@ int wolfTPM2_VerifyHash(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, TPM_ALG_NULL, hashAlg, NULL); } -#ifdef WOLFTPM_V185 /* Post-Quantum Cryptography (PQC) Wrapper Functions - TPM 2.0 v185 */ +#ifdef WOLFTPM_MLDSA_SIGN int wolfTPM2_SignSequenceStart(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, const byte* context, int contextSz, TPM_HANDLE* sequenceHandle) { @@ -5551,7 +5551,7 @@ int wolfTPM2_SignSequenceComplete(WOLFTPM2_DEV* dev, rc = BUFFER_E; } } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA else if (signSeqCompleteOut.signature.sigAlg == TPM_ALG_MLDSA) { /* Pure ML-DSA: bare TPM2B, no hash field. */ int sigOutSz = signSeqCompleteOut.signature.signature.mldsa.size; @@ -5579,7 +5579,7 @@ int wolfTPM2_SignSequenceComplete(WOLFTPM2_DEV* dev, rc = BUFFER_E; } } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLDSA */ else { /* Unknown algorithm */ rc = BUFFER_E; @@ -5588,7 +5588,9 @@ int wolfTPM2_SignSequenceComplete(WOLFTPM2_DEV* dev, return rc; } +#endif /* WOLFTPM_MLDSA_SIGN */ +#ifdef WOLFTPM_MLDSA_VERIFY int wolfTPM2_VerifySequenceStart(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, const byte* context, int contextSz, TPM_HANDLE* sequenceHandle) { @@ -5693,7 +5695,7 @@ int wolfTPM2_VerifySequenceComplete(WOLFTPM2_DEV* dev, return BUFFER_E; } } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA else if (key->pub.publicArea.type == TPM_ALG_MLDSA) { if (sigSz > (int)sizeof(((TPMT_SIGNATURE*)0)->signature.mldsa.buffer)) { return BUFFER_E; @@ -5767,7 +5769,7 @@ int wolfTPM2_VerifySequenceComplete(WOLFTPM2_DEV* dev, signature.signature.rsassa.sig.size = (UINT16)sigSz; XMEMCPY(signature.signature.rsassa.sig.buffer, sig, sigSz); } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA else if (key->pub.publicArea.type == TPM_ALG_MLDSA) { /* Pure ML-DSA: bare TPM2B signature, no hash. */ signature.sigAlg = TPM_ALG_MLDSA; @@ -5789,7 +5791,7 @@ int wolfTPM2_VerifySequenceComplete(WOLFTPM2_DEV* dev, signature.signature.hash_mldsa.signature.size = (UINT16)sigSz; XMEMCPY(signature.signature.hash_mldsa.signature.buffer, sig, sigSz); } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLDSA */ else { /* Unknown key type */ return BAD_FUNC_ARG; @@ -5813,7 +5815,9 @@ int wolfTPM2_VerifySequenceComplete(WOLFTPM2_DEV* dev, return rc; } +#endif /* WOLFTPM_MLDSA_VERIFY */ +#ifdef WOLFTPM_MLDSA_SIGN int wolfTPM2_SignDigest(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, const byte* digest, int digestSz, const byte* context, int contextSz, byte* sig, int* sigSz) @@ -5883,7 +5887,7 @@ int wolfTPM2_SignDigest(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, rc = BUFFER_E; } } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA else if (signDigestOut.signature.sigAlg == TPM_ALG_MLDSA) { /* Pure ML-DSA: bare TPM2B, no hash field. */ int sigOutSz = signDigestOut.signature.signature.mldsa.size; @@ -5910,7 +5914,7 @@ int wolfTPM2_SignDigest(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, rc = BUFFER_E; } } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLDSA */ else { /* Unknown algorithm */ rc = BUFFER_E; @@ -5919,7 +5923,9 @@ int wolfTPM2_SignDigest(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, return rc; } +#endif /* WOLFTPM_MLDSA_SIGN */ +#ifdef WOLFTPM_MLDSA_VERIFY int wolfTPM2_VerifyDigestSignature(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, const byte* digest, int digestSz, const byte* sig, int sigSz, const byte* context, int contextSz, TPMT_TK_VERIFIED* validation) @@ -5984,7 +5990,7 @@ int wolfTPM2_VerifyDigestSignature(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, signature.signature.rsassa.sig.size = (UINT16)sigSz; XMEMCPY(signature.signature.rsassa.sig.buffer, sig, sigSz); } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA else if (key->pub.publicArea.type == TPM_ALG_MLDSA) { /* Pure ML-DSA: bare TPM2B signature, no hash. */ signature.sigAlg = TPM_ALG_MLDSA; @@ -6006,7 +6012,7 @@ int wolfTPM2_VerifyDigestSignature(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, signature.signature.hash_mldsa.signature.size = (UINT16)sigSz; XMEMCPY(signature.signature.hash_mldsa.signature.buffer, sig, sigSz); } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLDSA */ else { /* Unknown key type */ return BAD_FUNC_ARG; @@ -6026,7 +6032,9 @@ int wolfTPM2_VerifyDigestSignature(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, return rc; } +#endif /* WOLFTPM_MLDSA_VERIFY */ +#ifdef WOLFTPM_MLKEM_ENCAP int wolfTPM2_Encapsulate(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, byte* ciphertext, int* ciphertextSz, byte* sharedSecret, int* sharedSecretSz) { @@ -6069,7 +6077,9 @@ int wolfTPM2_Encapsulate(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, return rc; } +#endif /* WOLFTPM_MLKEM_ENCAP */ +#ifdef WOLFTPM_MLKEM_DECAP int wolfTPM2_Decapsulate(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, const byte* ciphertext, int ciphertextSz, byte* sharedSecret, int* sharedSecretSz) { @@ -6111,7 +6121,9 @@ int wolfTPM2_Decapsulate(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, return rc; } +#endif /* WOLFTPM_MLKEM_DECAP */ +#ifdef WOLFTPM_MLDSA /* GetKeyTemplate_MLDSA - Create a key template for ML-DSA signing keys */ int wolfTPM2_GetKeyTemplate_MLDSA(TPMT_PUBLIC* publicTemplate, TPMA_OBJECT objectAttributes, TPMI_MLDSA_PARAMETER_SET parameterSet, @@ -6133,7 +6145,9 @@ int wolfTPM2_GetKeyTemplate_MLDSA(TPMT_PUBLIC* publicTemplate, (allowExternalMu ? YES : NO); return TPM_RC_SUCCESS; } +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_HASH_MLDSA /* GetKeyTemplate_HASH_MLDSA - Create a key template for Pre-Hash ML-DSA signing keys */ int wolfTPM2_GetKeyTemplate_HASH_MLDSA(TPMT_PUBLIC* publicTemplate, TPMA_OBJECT objectAttributes, TPMI_MLDSA_PARAMETER_SET parameterSet, @@ -6154,7 +6168,9 @@ int wolfTPM2_GetKeyTemplate_HASH_MLDSA(TPMT_PUBLIC* publicTemplate, publicTemplate->parameters.hash_mldsaDetail.hashAlg = hashAlg; return TPM_RC_SUCCESS; } +#endif /* WOLFTPM_HASH_MLDSA */ +#ifdef WOLFTPM_MLKEM /* GetKeyTemplate_MLKEM - Create a key template for ML-KEM decryption keys */ int wolfTPM2_GetKeyTemplate_MLKEM(TPMT_PUBLIC* publicTemplate, TPMA_OBJECT objectAttributes, TPMI_MLKEM_PARAMETER_SET parameterSet) @@ -6175,7 +6191,7 @@ int wolfTPM2_GetKeyTemplate_MLKEM(TPMT_PUBLIC* publicTemplate, publicTemplate->parameters.mlkemDetail.symmetric.algorithm = TPM_ALG_NULL; return TPM_RC_SUCCESS; } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ /* Generate ECC key-pair with NULL hierarchy and load (populates handle) */ int wolfTPM2_ECDHGenKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* ecdhKey, int curve_id, @@ -8812,7 +8828,7 @@ static int GetKeyTemplateSize(TPMT_PUBLIC* publicTemplate) case TPM_ALG_SYMCIPHER: ret = publicTemplate->parameters.symDetail.sym.keyBits.sym / 8; break; - #ifdef WOLFTPM_V185 + #ifdef WOLFTPM_MLDSA case TPM_ALG_MLDSA: case TPM_ALG_HASH_MLDSA: { TPMI_MLDSA_PARAMETER_SET ps = @@ -8826,6 +8842,8 @@ static int GetKeyTemplateSize(TPMT_PUBLIC* publicTemplate) else ret = BAD_FUNC_ARG; break; } + #endif /* WOLFTPM_MLDSA */ + #ifdef WOLFTPM_MLKEM case TPM_ALG_MLKEM: { TPMI_MLKEM_PARAMETER_SET ps = publicTemplate->parameters.mlkemDetail.parameterSet; @@ -8836,7 +8854,7 @@ static int GetKeyTemplateSize(TPMT_PUBLIC* publicTemplate) else ret = BAD_FUNC_ARG; break; } - #endif /* WOLFTPM_V185 */ + #endif /* WOLFTPM_MLKEM */ case TPM_ALG_KEYEDHASH: default: ret = BAD_FUNC_ARG; @@ -8920,7 +8938,7 @@ int wolfTPM2_SetKeyTemplate_Unique(TPMT_PUBLIC* publicTemplate, } publicTemplate->unique.sym.size = uniqueSz; break; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA /* TPMU_PUBLIC_ID shares the mldsa arm between MLDSA and HASH_MLDSA * (Part 2 Table 225 note — one union field, two selectors). */ case TPM_ALG_MLDSA: @@ -8943,6 +8961,8 @@ int wolfTPM2_SetKeyTemplate_Unique(TPMT_PUBLIC* publicTemplate, } publicTemplate->unique.mldsa.size = uniqueSz; break; +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_MLKEM case TPM_ALG_MLKEM: if (uniqueSz == 0) { uniqueSz = keySz; @@ -8962,7 +8982,7 @@ int wolfTPM2_SetKeyTemplate_Unique(TPMT_PUBLIC* publicTemplate, } publicTemplate->unique.mlkem.size = uniqueSz; break; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ case TPM_ALG_KEYEDHASH: /* not supported */ ret = BAD_FUNC_ARG; @@ -9351,7 +9371,7 @@ static void wolfTPM2_CopyPubT(TPMT_PUBLIC* out, const TPMT_PUBLIC* in) wolfTPM2_CopyEccParam(&out->unique.ecc.y, &in->unique.ecc.y); break; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_MLDSA case TPM_ALG_MLDSA: out->parameters.mldsaDetail.parameterSet = in->parameters.mldsaDetail.parameterSet; @@ -9378,6 +9398,8 @@ static void wolfTPM2_CopyPubT(TPMT_PUBLIC* out, const TPMT_PUBLIC* in) XMEMCPY(out->unique.mldsa.buffer, in->unique.mldsa.buffer, out->unique.mldsa.size); break; +#endif /* WOLFTPM_MLDSA */ +#ifdef WOLFTPM_MLKEM case TPM_ALG_MLKEM: wolfTPM2_CopySymmetric(&out->parameters.mlkemDetail.symmetric, &in->parameters.mlkemDetail.symmetric); @@ -9390,7 +9412,7 @@ static void wolfTPM2_CopyPubT(TPMT_PUBLIC* out, const TPMT_PUBLIC* in) XMEMCPY(out->unique.mlkem.buffer, in->unique.mlkem.buffer, out->unique.mlkem.size); break; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_MLKEM */ default: wolfTPM2_CopySymmetric(&out->parameters.asymDetail.symmetric, &in->parameters.asymDetail.symmetric); diff --git a/tests/unit_tests.c b/tests/unit_tests.c index 13ea5e1a..8afe674f 100644 --- a/tests/unit_tests.c +++ b/tests/unit_tests.c @@ -845,7 +845,7 @@ static void test_wolfTPM2_EncryptSecret(void) WOLFTPM2_KEY tpmKey; TPM2B_DATA data; TPM2B_ENCRYPTED_SECRET secret; -#if defined(WOLFTPM_V185) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ +#if defined(WOLFTPM_PQC) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ (defined(WOLFSSL_HAVE_MLKEM) || defined(WOLFSSL_KYBER512) || \ defined(WOLFSSL_KYBER768) || defined(WOLFSSL_KYBER1024)) WOLFTPM2_KEY mlkemKey; @@ -875,7 +875,7 @@ static void test_wolfTPM2_EncryptSecret(void) rc = wolfTPM2_EncryptSecret(&dev, &tpmKey, &data, NULL, "SECRET"); AssertIntEQ(rc, BAD_FUNC_ARG); -#if defined(WOLFTPM_V185) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ +#if defined(WOLFTPM_PQC) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ (defined(WOLFSSL_HAVE_MLKEM) || defined(WOLFSSL_KYBER512) || \ defined(WOLFSSL_KYBER768) || defined(WOLFSSL_KYBER1024)) /* MLKEM path (v1.85 Part 1 Sec.24): caller encapsulates under the TPM's @@ -2774,7 +2774,7 @@ static void test_TPM2_Signature_EcSchnorrSm2Serialize(void) "Signature ECSCHNORR/SM2 serialize:"); } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* Round-trip the v1.85 PQC arms of TPMT_SIGNATURE through the packet * marshaler. Pure ML-DSA (Table 217 mldsa arm) is bare TPM2B + bytes — * no hash field. Hash-ML-DSA prefixes a hashAlg before the TPM2B. The @@ -2941,7 +2941,7 @@ static void test_TPM2_Public_PQC_Roundtrip(void) printf("Test TPM Wrapper: %-40s Passed\n", "Public PQC roundtrip:"); } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ static void test_TPM2_Sensitive_Roundtrip(void) { @@ -3057,7 +3057,7 @@ static void test_TPM2_Sensitive_Roundtrip(void) AssertIntEQ(XMEMCMP(sensOut.sensitiveArea.sensitive.sym.buffer, rsaPriv, sizeof(rsaPriv)), 0); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* ML-DSA sensitive roundtrip — regression for missing PQC arm in * TPM2_Packet_ParseSensitive (would silently drop the private bytes * before the parse-side fix). */ @@ -3129,7 +3129,7 @@ static void test_TPM2_Sensitive_Roundtrip(void) AssertIntEQ(sensOut.sensitiveArea.sensitive.mlkem.size, sizeof(rsaPriv)); AssertIntEQ(XMEMCMP(sensOut.sensitiveArea.sensitive.mlkem.buffer, rsaPriv, sizeof(rsaPriv)), 0); -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ printf("Test TPM Wrapper: %-40s Passed\n", "Sensitive roundtrip:"); } @@ -3212,7 +3212,7 @@ static void test_GetAlgId(void) AssertIntEQ(TPM2_GetAlgId("SHA3_256"), TPM_ALG_SHA3_256); AssertIntEQ(TPM2_GetAlgId("SHA3_384"), TPM_ALG_SHA3_384); AssertIntEQ(TPM2_GetAlgId("SHA3_512"), TPM_ALG_SHA3_512); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC AssertIntEQ(TPM2_GetAlgId("ML-KEM"), TPM_ALG_MLKEM); AssertIntEQ(TPM2_GetAlgId("ML-DSA"), TPM_ALG_MLDSA); AssertIntEQ(TPM2_GetAlgId("HashML-DSA"), TPM_ALG_HASH_MLDSA); @@ -4395,7 +4395,7 @@ static void test_TPM2_GetHashDigestSize_AllAlgs(void) printf("Test TPM2:\t\tGetHashDigestSize all algs:\tPassed\n"); } -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* Post-Quantum Cryptography (PQC) Unit Tests - TPM 2.0 v185 */ /* TODO: Remove TPM_RC_COMMAND_CODE skip logic once we have a TPM simulator @@ -5155,7 +5155,7 @@ static void test_wolfTPM2_PQC_Sizes(void) printf("Test TPM Wrapper: %-40s Passed\n", "PQC Sizes:"); } -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ #endif /* !WOLFTPM2_NO_WRAPPER */ @@ -5222,7 +5222,7 @@ int unit_tests(int argc, char *argv[]) test_wolfTPM2_LoadEccPublicKey_Ex(); test_TPM2_KeyedHashScheme_XorSerialize(); test_TPM2_Signature_EcSchnorrSm2Serialize(); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC test_TPM2_Signature_PQC_Serialize(); test_TPM2_Public_PQC_Roundtrip(); #endif @@ -5262,7 +5262,7 @@ int unit_tests(int argc, char *argv[]) test_wolfTPM2_ST33_FirmwareUpgrade(); #endif #endif - #ifdef WOLFTPM_V185 + #ifdef WOLFTPM_PQC /* Run non-TPM-dependent tests first */ test_wolfTPM2_PQC_KeyTemplates(); test_wolfTPM2_PQC_Sizes(); diff --git a/wolftpm/tpm2.h b/wolftpm/tpm2.h index f3a8c0ef..12f81067 100644 --- a/wolftpm/tpm2.h +++ b/wolftpm/tpm2.h @@ -119,7 +119,7 @@ typedef enum { TPM_ALG_CBC = 0x0042, TPM_ALG_CFB = 0x0043, TPM_ALG_ECB = 0x0044, -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* Post-Quantum Algorithms - TPM 2.0 Library v185 */ TPM_ALG_MLKEM = 0x00A0, TPM_ALG_MLDSA = 0x00A1, @@ -144,7 +144,7 @@ typedef enum { } TPM_ECC_CURVE_T; typedef UINT16 TPM_ECC_CURVE; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* ML-KEM Parameter Sets (TCG Algorithm Registry v2.0) */ typedef UINT16 TPMI_MLKEM_PARAMETER_SET; #define TPM_MLKEM_NONE 0x0000 @@ -158,7 +158,7 @@ typedef UINT16 TPMI_MLDSA_PARAMETER_SET; #define TPM_MLDSA_44 0x0001 #define TPM_MLDSA_65 0x0002 #define TPM_MLDSA_87 0x0003 -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ /* Command Codes */ typedef enum { @@ -275,7 +275,7 @@ typedef enum { TPM_CC_CreateLoaded = 0x00000191, TPM_CC_PolicyAuthorizeNV = 0x00000192, TPM_CC_EncryptDecrypt2 = 0x00000193, -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* Post-Quantum Cryptography Commands - TPM 2.0 Library v185 */ TPM_CC_VerifySequenceComplete = 0x000001A3, TPM_CC_SignSequenceComplete = 0x000001A4, @@ -407,7 +407,7 @@ typedef enum { TPM_RC_ECC_POINT = RC_FMT1 + 0x027, /* TCG Part 2 Sec.6.6.3 Table 17 -- present since v1.16, not v1.85 */ TPM_RC_PARMS = RC_FMT1 + 0x02A, -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* v185 rc4 Part 2 Sec.6.6.3 Table 17 additions */ TPM_RC_EXT_MU = RC_FMT1 + 0x02B, TPM_RC_ONE_SHOT_SIGNATURE = RC_FMT1 + 0x02C, @@ -520,7 +520,7 @@ typedef enum { TPM_ST_AUTH_SECRET = 0x8023, TPM_ST_HASHCHECK = 0x8024, TPM_ST_AUTH_SIGNED = 0x8025, -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC TPM_ST_MESSAGE_VERIFIED = 0x8026, TPM_ST_DIGEST_VERIFIED = 0x8027, #endif @@ -955,7 +955,7 @@ enum TPMA_MODES_mask { TPMA_MODES_FIPS_140_3 = 0x00000002, }; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* v185 rc4 Part 2 Sec.8.13 Table 46 - bitfield returned from * TPM2_GetCapability(TPM_CAP_TPM_PROPERTIES, TPM_PT_ML_PARAMETER_SETS) * indicating which ML-KEM/ML-DSA parameter sets the TPM supports. */ @@ -1071,7 +1071,7 @@ typedef struct TPM2B_IV { BYTE buffer[MAX_SYM_BLOCK_SIZE]; } TPM2B_IV; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* Post-Quantum Cryptography (PQC) Types */ typedef struct TPM2B_SIGNATURE_CTX { UINT16 size; @@ -1125,7 +1125,7 @@ typedef struct TPM2B_MLDSA_SIGNATURE { UINT16 size; BYTE buffer[MAX_MLDSA_SIG_SIZE]; } TPM2B_MLDSA_SIGNATURE; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ /* Names */ @@ -1166,7 +1166,7 @@ typedef struct TPMT_TK_CREATION { typedef struct TPMT_TK_VERIFIED { TPM_ST tag; TPMI_RH_HIERARCHY hierarchy; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* v185 rc4 Part 2 Sec.10.6.5 Table 112 / Sec.10.6.4 Table 110 — [tag]metadata. * Empty on the wire for TPM_ST_VERIFIED and TPM_ST_MESSAGE_VERIFIED. * For TPM_ST_DIGEST_VERIFIED carries the TPM_ALG_ID (hash/XOF used). @@ -1640,7 +1640,7 @@ typedef struct TPMS_SIGNATURE_ECC { typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDSA; typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDAA; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* v185 rc4 Part 2 Sec.11.2.7.2 Table 208 — TPMS_SIGNATURE_HASH_MLDSA carries * the pre-hash algorithm together with the signature bytes. Used for * TPM_ALG_HASH_MLDSA signatures only. */ @@ -1648,7 +1648,7 @@ typedef struct TPMS_SIGNATURE_HASH_MLDSA { TPMI_ALG_HASH hash; TPM2B_MLDSA_SIGNATURE signature; } TPMS_SIGNATURE_HASH_MLDSA; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ typedef union TPMU_SIGNATURE { TPMS_SIGNATURE_ECDSA ecdsa; @@ -1657,14 +1657,14 @@ typedef union TPMU_SIGNATURE { TPMS_SIGNATURE_RSAPSS rsapss; TPMT_HA hmac; TPMS_SCHEME_HASH any; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* v185 rc4 Part 2 Sec.11.3.5 Table 217. Note: mldsa arm is TPM2B (bare * signature bytes with no hash field) because Pure ML-DSA does not * select a hash; hash_mldsa arm is TPMS (hash + signature) for the * pre-hashed variant. See Table 217 note. */ TPM2B_MLDSA_SIGNATURE mldsa; TPMS_SIGNATURE_HASH_MLDSA hash_mldsa; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ } TPMU_SIGNATURE; typedef struct TPMT_SIGNATURE { @@ -1680,7 +1680,7 @@ typedef union TPMU_ENCRYPTED_SECRET { BYTE rsa[MAX_RSA_KEY_BYTES]; /* TPM_ALG_RSA */ BYTE symmetric[sizeof(TPM2B_DIGEST)]; /* TPM_ALG_SYMCIPHER */ BYTE keyedHash[sizeof(TPM2B_DIGEST)]; /* TPM_ALG_KEYEDHASH */ -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC BYTE mlkem[MAX_MLKEM_CT_SIZE]; /* TPM_ALG_MLKEM (v1.85 T222) */ #endif } TPMU_ENCRYPTED_SECRET; @@ -1701,7 +1701,7 @@ typedef union TPMU_PUBLIC_ID { TPM2B_PUBLIC_KEY_RSA rsa; /* TPM_ALG_RSA */ TPMS_ECC_POINT ecc; /* TPM_ALG_ECC */ TPMS_DERIVE derive; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC TPM2B_PUBLIC_KEY_MLDSA mldsa; /* TPM_ALG_MLDSA or TPM_ALG_HASH_MLDSA */ TPM2B_PUBLIC_KEY_MLKEM mlkem; /* TPM_ALG_MLKEM */ #endif @@ -1731,7 +1731,7 @@ typedef struct TPMS_ECC_PARMS { TPMT_KDF_SCHEME kdf; } TPMS_ECC_PARMS; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* TPMS_MLDSA_PARMS - TCG v185 RC4 Table 229 */ typedef struct TPMS_MLDSA_PARMS { TPMI_MLDSA_PARAMETER_SET parameterSet; /* ML-DSA parameter set ID */ @@ -1749,7 +1749,7 @@ typedef struct TPMS_MLKEM_PARMS { TPMT_SYM_DEF_OBJECT symmetric; /* For restricted decryption key */ TPMI_MLKEM_PARAMETER_SET parameterSet; /* ML-KEM parameter set */ } TPMS_MLKEM_PARMS; -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ typedef union TPMU_PUBLIC_PARMS { TPMS_KEYEDHASH_PARMS keyedHashDetail; @@ -1757,7 +1757,7 @@ typedef union TPMU_PUBLIC_PARMS { TPMS_RSA_PARMS rsaDetail; TPMS_ECC_PARMS eccDetail; TPMS_ASYM_PARMS asymDetail; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC TPMS_MLDSA_PARMS mldsaDetail; /* TPM_ALG_MLDSA - sign only */ TPMS_HASH_MLDSA_PARMS hash_mldsaDetail; /* TPM_ALG_HASH_MLDSA - sign only */ TPMS_MLKEM_PARMS mlkemDetail; /* TPM_ALG_MLKEM - decrypt only */ @@ -1803,7 +1803,7 @@ typedef union TPMU_SENSITIVE_COMPOSITE { TPM2B_SENSITIVE_DATA bits; /* TPM_ALG_KEYEDHASH */ TPM2B_SYM_KEY sym; /* TPM_ALG_SYMCIPHER */ TPM2B_PRIVATE_VENDOR_SPECIFIC any; -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC TPM2B_PRIVATE_KEY_MLDSA mldsa; /* TPM_ALG_MLDSA/HASH_MLDSA - seed Xi */ TPM2B_PRIVATE_KEY_MLKEM mlkem; /* TPM_ALG_MLKEM - seed (d||z) */ #endif @@ -2799,7 +2799,7 @@ typedef struct { } Sign_Out; WOLFTPM_API TPM_RC TPM2_Sign(Sign_In* in, Sign_Out* out); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* Post-Quantum Cryptography (PQC) Commands - TPM 2.0 v185 */ /* v185 rc4 Part 3 Sec.17.6.3 Table 89 — {keyHandle, auth, context} */ @@ -2895,7 +2895,7 @@ typedef struct { TPM2B_SHARED_SECRET sharedSecret; } Decapsulate_Out; WOLFTPM_API TPM_RC TPM2_Decapsulate(Decapsulate_In* in, Decapsulate_Out* out); -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ typedef struct { TPMI_RH_PROVISION auth; diff --git a/wolftpm/tpm2_types.h b/wolftpm/tpm2_types.h index 87833602..f8ab3fa4 100644 --- a/wolftpm/tpm2_types.h +++ b/wolftpm/tpm2_types.h @@ -48,6 +48,78 @@ #include +/* Resolve the TPM 2.0 v1.85 / post-quantum feature macros into a single, + * consistent set used by every translation unit. Entry points (set by the + * user or by configure) are the umbrella WOLFTPM_V185 / WOLFTPM_PQC and the + * WOLFTPM_NO_* opt-outs; the positive per-algorithm and per-operation macros + * below are derived here so the rest of the tree only tests the resolved set. + * + * WOLFTPM_V185 - full v1.85 spec; guards the non-PQC additions + * (firmware/SVN properties, alg-name/id mappings, + * debug print) and additively defines WOLFTPM_PQC + * WOLFTPM_PQC - ML-DSA / ML-KEM only (lean entry point; excludes + * the non-PQC v1.85 code guarded by WOLFTPM_V185) + * WOLFTPM_MLDSA - ML-DSA family: WOLFTPM_MLDSA_SIGN / _VERIFY / + * WOLFTPM_HASH_MLDSA + * WOLFTPM_MLKEM - ML-KEM family: WOLFTPM_MLKEM_ENCAP / _DECAP + * + * Everything is on by default once its parent is enabled; opt out with the + * matching WOLFTPM_NO_* macro. Existing --enable-v185 builds are unchanged. + */ +/* Tier 1: the full v1.85 umbrella additively enables the PQC subset. The + * non-PQC v1.85 spec code stays guarded by WOLFTPM_V185 directly, so a lean + * WOLFTPM_PQC build (without WOLFTPM_V185) leaves it out. */ +#ifdef WOLFTPM_V185 + #if !defined(WOLFTPM_NO_PQC) && !defined(WOLFTPM_PQC) + #define WOLFTPM_PQC + #endif +#endif +/* Tier 2: PQC algorithm families. */ +#ifdef WOLFTPM_PQC + #if !defined(WOLFTPM_NO_MLDSA) && !defined(WOLFTPM_MLDSA) + #define WOLFTPM_MLDSA + #endif + #if !defined(WOLFTPM_NO_MLKEM) && !defined(WOLFTPM_MLKEM) + #define WOLFTPM_MLKEM + #endif +#endif +/* Tier 3: per-operation gates under each family. */ +#ifdef WOLFTPM_MLDSA + #if !defined(WOLFTPM_NO_MLDSA_SIGN) && !defined(WOLFTPM_MLDSA_SIGN) + #define WOLFTPM_MLDSA_SIGN + #endif + #if !defined(WOLFTPM_NO_MLDSA_VERIFY) && !defined(WOLFTPM_MLDSA_VERIFY) + #define WOLFTPM_MLDSA_VERIFY + #endif + #if !defined(WOLFTPM_NO_HASH_MLDSA) && !defined(WOLFTPM_HASH_MLDSA) + #define WOLFTPM_HASH_MLDSA + #endif +#endif +#ifdef WOLFTPM_MLKEM + #if !defined(WOLFTPM_NO_MLKEM_ENCAP) && !defined(WOLFTPM_MLKEM_ENCAP) + #define WOLFTPM_MLKEM_ENCAP + #endif + #if !defined(WOLFTPM_NO_MLKEM_DECAP) && !defined(WOLFTPM_MLKEM_DECAP) + #define WOLFTPM_MLKEM_DECAP + #endif +#endif +/* Consistency fold-ups: drop a feature whose prerequisites are all disabled. */ +#if defined(WOLFTPM_HASH_MLDSA) && !defined(WOLFTPM_MLDSA_SIGN) && \ + !defined(WOLFTPM_MLDSA_VERIFY) + #undef WOLFTPM_HASH_MLDSA +#endif +#if defined(WOLFTPM_MLDSA) && !defined(WOLFTPM_MLDSA_SIGN) && \ + !defined(WOLFTPM_MLDSA_VERIFY) + #undef WOLFTPM_MLDSA +#endif +#if defined(WOLFTPM_MLKEM) && !defined(WOLFTPM_MLKEM_ENCAP) && \ + !defined(WOLFTPM_MLKEM_DECAP) + #undef WOLFTPM_MLKEM +#endif +#if defined(WOLFTPM_PQC) && !defined(WOLFTPM_MLDSA) && !defined(WOLFTPM_MLKEM) + #undef WOLFTPM_PQC +#endif + #ifdef WOLFTPM_WINAPI #ifdef _WIN32 #include @@ -692,14 +764,14 @@ typedef int64_t INT64; #define NUM_POLICY_PCR 1 #endif #ifndef MAX_COMMAND_SIZE - #ifdef WOLFTPM_V185 + #ifdef WOLFTPM_PQC #define MAX_COMMAND_SIZE 8192 #else #define MAX_COMMAND_SIZE 4096 #endif #endif #ifndef MAX_RESPONSE_SIZE - #ifdef WOLFTPM_V185 + #ifdef WOLFTPM_PQC #define MAX_RESPONSE_SIZE 8192 #else #define MAX_RESPONSE_SIZE 4096 @@ -750,7 +822,7 @@ typedef int64_t INT64; #ifndef MAX_CAP_HANDLES #define MAX_CAP_HANDLES (MAX_CAP_DATA / sizeof(TPM_HANDLE)) #endif -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /* Post-Quantum Cryptography (PQC) Size Definitions - TCG v185 RC4. * These size the public TPM2B_* ABI buffers, so they MUST match the * largest spec-defined parameter set — a client only enabling MLDSA-44 @@ -808,7 +880,7 @@ typedef int64_t INT64; #ifndef MAX_SHARED_SECRET_SIZE #define MAX_SHARED_SECRET_SIZE 64 #endif -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ #ifndef HASH_COUNT #ifndef WOLFTPM2_NO_WOLFCRYPT /* Calculate hash count based on wolfCrypt enables */ diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 83b1f8d9..a2504199 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -2102,7 +2102,7 @@ WOLFTPM_API int wolfTPM2_VerifyHashTicket(WOLFTPM2_DEV* dev, int digestSz, TPMI_ALG_SIG_SCHEME sigAlg, TPMI_ALG_HASH hashAlg, TPMT_TK_VERIFIED* checkTicket); -#ifdef WOLFTPM_V185 +#ifdef WOLFTPM_PQC /*! \ingroup wolfTPM2_Wrappers \brief Post-Quantum Cryptography: Start a signing sequence with context support @@ -2400,7 +2400,7 @@ WOLFTPM_API int wolfTPM2_GetKeyTemplate_HASH_MLDSA(TPMT_PUBLIC* publicTemplate, */ WOLFTPM_API int wolfTPM2_GetKeyTemplate_MLKEM(TPMT_PUBLIC* publicTemplate, TPMA_OBJECT objectAttributes, TPMI_MLKEM_PARAMETER_SET parameterSet); -#endif /* WOLFTPM_V185 */ +#endif /* WOLFTPM_PQC */ /*! \ingroup wolfTPM2_Wrappers