Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
487387d
Add v185 rc4 tpm2.0 PQC MLDSA MLKEM Support
aidangarske Mar 11, 2026
871a930
Correct Encapsulate_Out feild order
aidangarske Mar 19, 2026
5e67459
Fix PQC definitions and command codes for v185
aidangarske Mar 19, 2026
feaa06c
Fix PQC code review issues for v185 support
aidangarske Mar 19, 2026
dadad74
Address copilot review, add bounds checks, less than 0 checks
aidangarske Mar 20, 2026
f90429e
Increase the command response buffer sizes
aidangarske Apr 6, 2026
14a9036
confitionally increase buffer size
aidangarske Apr 6, 2026
62f3368
Phase 1: Add Fixture tests known posotives
aidangarske Apr 17, 2026
cf6a140
Phase 2: v185 types, marshaling fixes, fwTPM buffer lifts, stub dispatch
aidangarske Apr 17, 2026
49fb236
Phase 3: v185 PQC primary key derivation (ML-DSA / ML-KEM)
aidangarske Apr 17, 2026
d47fbea
Phase 4: v185 PQC ML-KEM Encapsulate / Decapsulate handlers
aidangarske Apr 17, 2026
1fa328b
Phase 5: v185 PQC ML-DSA sign/verify handlers
aidangarske Apr 17, 2026
3274d0c
Phase 7: lift NV marshal buffer estimate for PQC public areas
aidangarske Apr 17, 2026
c1894af
Phase 5b: finish Pure ML-DSA verify sequence path
aidangarske Apr 17, 2026
bef9911
Phase 5c: Hash-ML-DSA sequence accumulator
aidangarske Apr 17, 2026
ef31aa8
Phase 8a: add PQC end-to-end tests; fix FIPS 204 hedged-sign RNG
aidangarske Apr 20, 2026
a1b08db
Phase 10: dual-source NIST ACVP + wolfSSL KAT testing
aidangarske Apr 20, 2026
eeb7196
Phase 11: Add docs for fwtpm and tpm
aidangarske Apr 21, 2026
a2a902a
Phase 12 Task 1: PQC primary-key determinism tests
aidangarske Apr 21, 2026
729ece6
Phase 12 Task 3: PQC capability reporting + spec RC fix
aidangarske Apr 21, 2026
8899115
Phase 12 Task 2: PQC negative-RC tests (9 handlers)
aidangarske Apr 21, 2026
25b0157
fwTPM PQC: NV persistence round-trip test
aidangarske Apr 21, 2026
f42c57f
fwTPM PQC: boundary + scaling tests
aidangarske Apr 21, 2026
552032d
fwTPM PQC: mssim E2E test + output formatting
aidangarske Apr 21, 2026
4ead816
fwTPM PQC: finish v1.85 protocol wiring for Sign/Verify over mssim
aidangarske Apr 22, 2026
c2b631e
Align unit_tests.c output + MLKEM ct threading + drop dead MLDSA Sign…
aidangarske Apr 22, 2026
e86b897
Add MLKEM arm to wolfTPM2_EncryptSecret + TPMU_ENCRYPTED_SECRET
aidangarske Apr 22, 2026
4491c20
Add PQC options to examples/keygen + ML-KEM encap example
aidangarske Apr 22, 2026
8311223
docs: add v1.85 PQC build + usage section to main README and examples
aidangarske Apr 22, 2026
1b90965
Add Sign + verify examples
aidangarske Apr 22, 2026
3110a3d
fwTPM: add PQC branches to CreateLoaded + tests
aidangarske Apr 22, 2026
08b266b
Remove Layer C fixture skeleton (tests/fixtures/v185_pqc)
aidangarske Apr 22, 2026
71e28c1
Extend fuzz CI matrix to cover v1.85 PQC paths
aidangarske Apr 22, 2026
723b582
Strip SPEC_DECISIONS.md pointers from shipped code + docs
aidangarske Apr 22, 2026
0801a30
fwTPM v1.85: TCG compliance fixes + PQC CI matrix
aidangarske Apr 23, 2026
d9143e3
fwTPM v1.85: TCG + Skoll review fixes (round 2)
aidangarske Apr 24, 2026
9b94068
Fix CI: TCG + Skoll review feedback
aidangarske Apr 24, 2026
72fd6f4
fwTPM: thread ticketTag through FwComputeTicketHmac (sym verify+produce)
aidangarske Apr 24, 2026
abe08f5
fwTPM v1.85: CI fixes + MSan uninit-read in FwCmd_Create
aidangarske Apr 24, 2026
2a9ec7f
fwTPM v185: Fix CI
aidangarske Apr 24, 2026
8a9be3e
fwTPM v185: MSan-detected uninit reads (4 real bugs) + CI debug
aidangarske Apr 24, 2026
4df63f1
fwTPM v185: include wc_mlkem.h for stack-alloc + verbose CI debug
aidangarske Apr 24, 2026
3f7db58
fix keyload ecc 159 in CI: writeKeyBlob silent write failure
aidangarske Apr 27, 2026
f568e04
fwTPM v185: TCG/security review fixes + embedded RAM auto-shrink
aidangarske Apr 27, 2026
9ce4188
fwTPM v185: PR review fixes + TCG/security hardening
aidangarske Apr 27, 2026
539c94b
fwTPM v185: Fix autodetect
aidangarske Apr 27, 2026
df7d06c
Fix minor build error without PQC enabled
dgarske Apr 28, 2026
86188f5
fwTPM v185: TCG Phase B compliance — full sign/verify, KEM, and seed …
aidangarske Apr 28, 2026
484df3c
fwTPM v185: Skoll review-cycle fixes (TCG + multi-scan)
aidangarske Apr 28, 2026
960ba43
fwTPM v185: CI fixes for non-PQC builds + Tier 5 server lifetime
aidangarske Apr 28, 2026
d518bff
fwTPM v185: final skoll reivew pass
aidangarske Apr 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 51 additions & 3 deletions .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,34 @@ jobs:
fail-fast: false
matrix:
include:
# Full fuzz run (weekly/manual) - 10 minutes
# Classical (v1.38) full fuzz run (weekly/manual) - 10 minutes
- name: fuzz-full
fuzz_time: 600
smoke_only: false
# Quick smoke test (PR) - 60 seconds
wolfssl_extra_flags: ""
wolftpm_extra_flags: ""
max_len: 4096
# Classical (v1.38) quick smoke test (PR) - 60 seconds
- name: fuzz-smoke
fuzz_time: 60
smoke_only: true
wolfssl_extra_flags: ""
wolftpm_extra_flags: ""
max_len: 4096
# v1.85 PQC full fuzz run (weekly/manual) - 10 minutes
- name: fuzz-full-pqc
fuzz_time: 600
smoke_only: false
wolfssl_extra_flags: "--enable-dilithium --enable-mlkem --enable-experimental --enable-harden"
wolftpm_extra_flags: "--enable-v185"
max_len: 8192
# v1.85 PQC quick smoke test (PR) - 60 seconds
- name: fuzz-smoke-pqc
fuzz_time: 60
smoke_only: true
wolfssl_extra_flags: "--enable-dilithium --enable-mlkem --enable-experimental --enable-harden"
wolftpm_extra_flags: "--enable-v185"
max_len: 8192

steps:
- name: Checkout wolfTPM
Expand All @@ -42,6 +62,7 @@ jobs:
run: |
./autogen.sh
CC=clang ./configure --enable-wolftpm --enable-pkcallbacks --enable-keygen \
${{ matrix.wolfssl_extra_flags }} \
CFLAGS="-fsanitize=fuzzer-no-link,address -fno-omit-frame-pointer -g -O1 -DWC_RSA_NO_PADDING" \
LDFLAGS="-fsanitize=address"
make -j$(nproc)
Expand All @@ -52,13 +73,40 @@ jobs:
run: |
./autogen.sh
CC=clang ./configure --enable-fwtpm --enable-fuzz \
${{ matrix.wolftpm_extra_flags }} \
CFLAGS="-fsanitize=fuzzer-no-link,address -fno-omit-frame-pointer -g -O1" \
LDFLAGS="-fsanitize=address"
make -j$(nproc)

- name: Generate seed corpus
run: python3 tests/fuzz/gen_corpus.py

- name: Verify v1.85 PQC opcode coverage in corpus
if: contains(matrix.name, 'pqc')
run: |
# Without this guard, fuzz-*-pqc could spend 10 minutes fuzzing
# classical paths with -DWOLFTPM_V185 set and never exercise an
# Encapsulate or SignSequenceComplete opcode. Fail fast if any of
# the 8 new v1.85 command codes is absent from the seed corpus.
# Seeds are binary; opcodes appear as raw 4-byte big-endian
# sequences. Hex-dump the concatenated corpus and grep the
# resulting hex stream for each opcode's bytes.
CORPUS_HEX=$(cat tests/fuzz/corpus/*.bin | xxd -p | tr -d '\n')
MISSING=()
for cc in 000001a3 000001a4 000001a5 000001a6 \
000001a7 000001a8 000001a9 000001aa; do
if ! echo "$CORPUS_HEX" | grep -q "$cc"; then
MISSING+=("0x${cc^^}")
fi
done
if [ ${#MISSING[@]} -gt 0 ]; then
echo "ERROR: PQC seed corpus missing the following command codes:"
printf ' %s\n' "${MISSING[@]}"
echo "Update tests/fuzz/gen_corpus.py to emit a seed for each."
exit 1
fi
echo "All 8 v1.85 PQC opcodes (0x1A3-0x1AA) present in seed corpus."

- name: Run fuzzer
env:
ASAN_OPTIONS: "detect_leaks=1:abort_on_error=1:symbolize=1"
Expand All @@ -68,7 +116,7 @@ jobs:
./tests/fuzz/fwtpm_fuzz \
tests/fuzz/corpus/ \
-dict=tests/fuzz/tpm2.dict \
-max_len=4096 \
-max_len=${{ matrix.max_len }} \
-timeout=30 \
-rss_limit_mb=2048 \
-print_final_stats=1 \
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/fwtpm-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,29 @@ jobs:
wolfssl_config: --enable-wolftpm --enable-pkcallbacks --enable-keygen
build_only: false

# v1.85 PQC: full make check + pqc_mssim_e2e.sh + tpm2-tools
# Highest-leverage entry — exercises wrapper unit tests
# (tests/unit_tests.c v1.85 cases) + handler unit tests
# (tests/fwtpm_unit_tests.c v1.85 cases) + the new mssim E2E
# harness against fwtpm_server in one shot. --enable-swtpm omitted
# because configure.ac:287 enables it by default on Linux.
- name: fwtpm-v185
os: ubuntu-latest
wolftpm_config: --enable-fwtpm --enable-v185
wolfssl_config: --enable-wolftpm --enable-pkcallbacks --enable-keygen --enable-dilithium --enable-mlkem --enable-experimental --enable-harden
build_only: false

# v1.85 PQC: build-only safety net with DEBUG_WOLFTPM so any
# printf-format-string drift in v1.85-guarded debug paths breaks
# the build instead of silently corrupting log output. No
# --enable-swtpm because build-only never invokes the socket client.
- name: fwtpm-v185-build-only
os: ubuntu-latest
wolftpm_config: --enable-fwtpm --enable-v185
wolfssl_config: --enable-wolftpm --enable-pkcallbacks --enable-keygen --enable-dilithium --enable-mlkem --enable-experimental --enable-harden
build_only: true
extra_cflags: -DDEBUG_WOLFTPM

# Build-only: fwTPM with RSA disabled
- name: fwtpm-no-rsa
os: ubuntu-latest
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/make-test-swtpm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,24 @@ jobs:
test_command: "make check && WOLFSSL_PATH=./wolfssl NO_PUBASPRIV=1 ./examples/run_examples.sh"
needs_install: true

# v1.85 PQC: swtpm-backed wrapper coverage. Triggers run_examples.sh
# Build-only: --enable-v185 against PQC+pkcallbacks wolfSSL. swtpm
# has no PQC, so runtime PQC tests live in fwtpm-v185.
- name: v185-pqc-swtpm-build
wolfssl_config: "--enable-wolftpm --enable-pkcallbacks --enable-keygen --enable-dilithium --enable-mlkem --enable-experimental --enable-harden"
wolftpm_config: "--enable-v185"
test_command: "make"

# Regression: build the v185-pq-support branch WITHOUT --enable-v185
# to catch #ifdef WOLFTPM_V185 drift in tpm2_packet.c / tpm2_wrap.c
# (a PQC-only declaration leaking out of its guard breaks classical
# builds and would otherwise be invisible in CI — every other
# classical entry runs against master, never against this branch).
- name: v138-regression-after-v185
wolfssl_config: "--enable-wolftpm --enable-pkcallbacks --enable-keygen"
wolftpm_config: "--enable-fwtpm"
test_command: "make check && WOLFSSL_PATH=./wolfssl ./examples/run_examples.sh"

steps:
- name: Checkout wolfTPM
uses: actions/checkout@master
Expand Down
174 changes: 174 additions & 0 deletions .github/workflows/pqc-examples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
name: PQC Examples (v1.85)

on:
push:
branches: [ 'master', 'main', 'release/**' ]
pull_request:
branches: [ '*' ]

jobs:
pqc-examples:
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout wolfTPM
uses: actions/checkout@v4

- name: Checkout wolfSSL
uses: actions/checkout@v4
with:
repository: wolfssl/wolfssl
path: wolfssl
ref: master

- name: Install build deps + tpm2-tools
run: |
sudo apt-get update
sudo apt-get install -y tpm2-tools libtss2-tcti-mssim0

- name: Build wolfSSL with PQC
working-directory: ./wolfssl
run: |
./autogen.sh
./configure --enable-wolftpm --enable-pkcallbacks --enable-keygen \
--enable-dilithium --enable-mlkem --enable-experimental \
--enable-harden \
CFLAGS="-DWC_RSA_NO_PADDING"
make
sudo make install
sudo ldconfig

- name: Build wolfTPM with v1.85 + fwTPM + debug
run: |
./autogen.sh
# --enable-swtpm omitted: it's the Linux configure default
# (configure.ac:287). Passing it explicitly was redundant.
# --enable-debug=verbose: full client + fwTPM dispatch logs so
# CI failures (e.g. keyload integrity) come with TPM-side trace.
./configure --enable-v185 --enable-fwtpm --enable-debug=verbose
make

# ----- Tier 1: make check -----
# Runs unit.test (wrapper) + fwtpm_unit.test (handler) + tpm2-tools
# compatibility + tests/pqc_mssim_e2e.sh in one shot via fwtpm_check.sh.
- name: make check (unit + fwtpm_unit + tpm2-tools + pqc_mssim_e2e.sh)
env:
WOLFSSL_PATH: ${{ github.workspace }}/wolfssl
run: |
FWTPM_USE_FIXED_PORT=1 \
sudo -E unshare --net /bin/bash -c '
set -e
ip link set lo up
make check
'
# make check runs as root via sudo -E unshare; restore ownership of
# any files left in the workspace so later steps (running as the
# unprivileged runner) can rewrite them — otherwise stale root-owned
# blobs (e.g. eccblob.bin) silently break run_examples.sh later.
sudo chown -R "$(id -u):$(id -g)" .

# ----- Tier 2: per-example standalone runs -----
# Each example gets its own GitHub Actions check so a regression
# surfaces with a clear failure signal — not buried inside make check.
- name: Start fwtpm_server for standalone example runs
run: |
rm -f fwtpm_nv.bin
./src/fwtpm/fwtpm_server > /tmp/fwtpm_server.log 2>&1 &
echo $! > /tmp/fwtpm_server.pid
sleep 1
kill -0 $(cat /tmp/fwtpm_server.pid)

- name: PQC keygen — every parameter set
run: |
for ps in 44 65 87; do
./examples/keygen/keygen mldsa_sk.bin -mldsa=$ps || exit 1
./examples/keygen/keygen hmldsa_sk.bin -hash_mldsa=$ps || exit 1
done
for ps in 512 768 1024; do
./examples/keygen/keygen mlkem_sk.bin -mlkem=$ps || exit 1
done

- name: ML-DSA sign + verify example (standalone)
run: ./examples/pqc/mldsa_sign

- name: ML-KEM encap + decap example (standalone)
run: ./examples/pqc/mlkem_encap

- name: Stop Tier 2 fwtpm_server (free port 2321 for E2E)
run: |
if [ -f /tmp/fwtpm_server.pid ]; then
kill "$(cat /tmp/fwtpm_server.pid)" 2>/dev/null || true
rm -f /tmp/fwtpm_server.pid
fi
# Defensive: kill any other default-port server lingering.
pkill -f "fwtpm_server$" 2>/dev/null || true
sleep 1

- name: PQC mssim E2E (MLKEM-768 + HashMLDSA-65 round-trips)
run: ./tests/pqc_mssim_e2e.sh

- name: Restart fwtpm_server for Tier 5 (run_examples.sh)
run: |
# pqc_mssim_e2e.sh started + stopped its own server; Tier 5 needs
# one again. Reuse the same default-port launch as Tier 2.
pkill -f "fwtpm_server" 2>/dev/null || true
sleep 1
rm -f fwtpm_nv.bin
./src/fwtpm/fwtpm_server > /tmp/fwtpm_server.log 2>&1 &
echo $! > /tmp/fwtpm_server.pid
sleep 1
kill -0 "$(cat /tmp/fwtpm_server.pid)"

- name: Doc constants parity check
run: |
./tests/check_doc_constants.sh
rc=$?
if [ $rc -eq 77 ]; then
echo "Step skipped (exit 77 — header or doc missing)"
exit 0
fi
exit $rc

# ----- Tier 5: full run_examples.sh sweep -----
# run_examples.sh does not start its own TPM — it expects one already
# listening. Reuse the fwtpm_server started in Tier 2. Trace each
# command (set -x) so the failing call line is in the CI log; on
# failure, dump run.out (where the script redirects example stdout).
- name: run_examples.sh full pass (auto-detects v1.85, runs 18-way matrix)
env:
WOLFSSL_PATH: ${{ github.workspace }}/wolfssl
run: |
set +e
bash -x ./examples/run_examples.sh
rc=$?
set -e
if [ $rc -ne 0 ]; then
echo "=== run.out (last 200 lines) ==="
tail -200 run.out
echo "=== fwtpm_server.log (last 100 lines) ==="
tail -100 /tmp/fwtpm_server.log
fi
exit $rc

- name: Stop fwtpm_server
if: always()
run: |
if [ -f /tmp/fwtpm_server.pid ]; then
kill $(cat /tmp/fwtpm_server.pid) 2>/dev/null || true
rm -f /tmp/fwtpm_server.pid
fi

- name: Upload failure logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: pqc-examples-logs
path: |
/tmp/fwtpm_server.log
/tmp/fwtpm_check_*.log
test-suite.log
tests/*.log
config.log
run.out
retention-days: 5
40 changes: 38 additions & 2 deletions .github/workflows/sanitizer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,40 @@ jobs:
cflags: "-fsanitize=leak -fno-omit-frame-pointer -g"
ldflags: "-fsanitize=leak"

# v1.85 PQC sanitizer coverage — three entries because each catches
# a different bug class. SWTPM transport is the Linux configure
# default (configure.ac:287); explicit flag omitted everywhere.
# ASan: heap-buffer-overflow / use-after-scope on the new sequence-
# handle objects + PQC marshaling paths.
- name: "ASan-v185"
cflags: "-fsanitize=address -O1 -fno-omit-frame-pointer -g"
ldflags: "-fsanitize=address"
asan_options: "detect_leaks=0"
wolftpm_extra_config: "--enable-v185"
wolfssl_extra_config: "--enable-dilithium --enable-mlkem --enable-experimental --enable-harden"

# UBSan-v185: enables undefined-behavior checks but disables
# `alignment` (wolfSSL dilithium internal sword32 reads from
# byte buffers) and the integer overflow/shift checks (wolfSSL
# Hash_df 440<<24) — both pre-existing wolfSSL UB.
- name: "UBSan-v185"
cc: clang
cflags: "-fsanitize=undefined -fno-sanitize=alignment,signed-integer-overflow,shift -fno-sanitize-recover=all -fno-omit-frame-pointer -g"
ldflags: "-fsanitize=undefined"
ubsan_options: "halt_on_error=1:print_stacktrace=1"
wolftpm_extra_config: "--enable-v185"
wolfssl_extra_config: "--enable-dilithium --enable-mlkem --enable-experimental --enable-harden"

# MSan-v185: Pure ML-DSA one-shot signing and streaming Hash-ML-DSA
# both allocate sequence-handle state incrementally — partial-init
# reads on those buffers are MSan territory, not ASan.
- name: "MSan-v185"
cc: clang
cflags: "-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -O1 -g"
ldflags: "-fsanitize=memory"
wolftpm_extra_config: "--enable-v185"
wolfssl_extra_config: "--enable-dilithium --enable-mlkem --enable-experimental --enable-harden"

steps:
- name: Workaround high-entropy ASLR
run: sudo sysctl vm.mmap_rnd_bits=28
Expand All @@ -53,7 +87,8 @@ jobs:
working-directory: ./wolfssl
run: |
./autogen.sh
./configure --enable-wolftpm --enable-pkcallbacks --enable-keygen \
CC=${{ matrix.cc || 'gcc' }} ./configure --enable-wolftpm --enable-pkcallbacks --enable-keygen \
${{ matrix.wolfssl_extra_config }} \
--prefix=/tmp/wolfssl-install \
CFLAGS="-DWC_RSA_NO_PADDING ${{ matrix.cflags }}" \
LDFLAGS="${{ matrix.ldflags }}"
Expand All @@ -63,7 +98,8 @@ jobs:
- name: Build wolfTPM with fwTPM + ${{ matrix.name }}
run: |
./autogen.sh
./configure --enable-fwtpm --enable-swtpm --enable-debug \
CC=${{ matrix.cc || 'gcc' }} ./configure --enable-fwtpm --enable-swtpm --enable-debug \
${{ matrix.wolftpm_extra_config }} \
--with-wolfcrypt=/tmp/wolfssl-install \
CFLAGS="${{ matrix.cflags }}" \
LDFLAGS="${{ matrix.ldflags }}"
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ examples/keygen/keyload
examples/keygen/keygen
examples/keygen/keyimport
examples/keygen/external_import
examples/pqc/mldsa_sign
examples/pqc/mlkem_encap
examples/pqc/pqc_mssim_e2e
examples/nvram/extend
examples/nvram/store
examples/nvram/read
Expand Down
Loading
Loading