From eeb719654798e8a00d54890ecdb7b9e15e0c4151 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Tue, 21 Apr 2026 09:15:39 -0700 Subject: [PATCH] Phase 11: Add docs for fwtpm and tpm --- README.md | 1 + docs/FWTPM.md | 110 ++++++++++++++++++++++++++++++++++++++++++++ docs/README.md | 14 ++++++ src/fwtpm/README.md | 5 ++ 4 files changed, 130 insertions(+) diff --git a/README.md b/README.md index ab10b856..bf56e13f 100644 --- a/README.md +++ b/README.md @@ -38,6 +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-v185`. Both the client library and the fwTPM server implement the eight new v1.85 PQC commands. See [docs/FWTPM.md](docs/FWTPM.md#tpm-20-v185-post-quantum-support) for details. Note: See [examples/README.md](examples/README.md) for details on using the examples. diff --git a/docs/FWTPM.md b/docs/FWTPM.md index 0f1621d4..0f184d47 100644 --- a/docs/FWTPM.md +++ b/docs/FWTPM.md @@ -686,3 +686,113 @@ re-deriving expensive RSA keys on repeated `CreatePrimary` calls. Hierarchy seeds are managed by `ChangePPS` (platform) and `ChangeEPS` (endorsement). `Clear` regenerates owner and endorsement seeds. The null seed is re-randomized on every `Startup(CLEAR)`. + + +## TPM 2.0 v1.85 Post-Quantum Support + +Enabled with `--enable-v185` at configure time. Implements the post-quantum +additions from TCG TPM 2.0 Library Specification v1.85 using wolfCrypt's +FIPS 203 / FIPS 204 modules. + +### Algorithms + +| Alg | Parameter Sets | Use | +|---|---|---| +| `TPM_ALG_MLKEM` (0x00A0) | MLKEM-512 / 768 / 1024 | Key encapsulation (decrypt-only keys) | +| `TPM_ALG_MLDSA` (0x00A1) | MLDSA-44 / 65 / 87 | Pure ML-DSA message signing | +| `TPM_ALG_HASH_MLDSA` (0x00A2) | MLDSA-44 / 65 / 87 | Pre-hashed ML-DSA signing | + +### Commands + +The eight v1.85 PQC commands in `src/fwtpm/fwtpm_command.c`: + +| Command | CC | Purpose | +|---|---|---| +| `TPM2_Encapsulate` | `0x000001A7` | ML-KEM encapsulation, returns sharedSecret + ciphertext | +| `TPM2_Decapsulate` | `0x000001A8` | ML-KEM decapsulation from ciphertext (requires USER auth) | +| `TPM2_SignSequenceStart` | `0x000001AA` | Begin ML-DSA sign sequence | +| `TPM2_SignSequenceComplete` | `0x000001A4` | Finalize sign sequence with message buffer | +| `TPM2_VerifySequenceStart` | `0x000001A9` | Begin ML-DSA verify sequence | +| `TPM2_VerifySequenceComplete` | `0x000001A3` | Finalize verify sequence, returns TPMT_TK_VERIFIED | +| `TPM2_SignDigest` | `0x000001A6` | One-shot digest sign (Hash-ML-DSA or ext-μ ML-DSA) | +| `TPM2_VerifyDigestSignature` | `0x000001A5` | Verify digest signature | + +### Primary Key Derivation + +PQC primary keys follow the same deterministic derivation model as RSA/ECC: +hierarchy seed + template → KDFa-derived seed → FIPS 203/204 key expansion. + +- **ML-DSA**: `KDFa(nameAlg, seed, "MLDSA", hashUnique) → 32-byte Xi` → + `wc_dilithium_make_key_from_seed` → (pub, expanded-priv). The wire format stores + only the 32-byte Xi per TCG Part 2 Table 210. +- **Hash-ML-DSA**: label is `"HASH_MLDSA"`; same seed size and expansion. +- **ML-KEM**: `KDFa(nameAlg, seed, "MLKEM", hashUnique) → 64-byte (d‖z)` → + `wc_MlKemKey_MakeKeyWithRandom` → (ek, dk). Wire format stores only 64-byte + seed per TCG Part 2 Table 206. + +All three labels are logged in `docs/v185_pqc/SPEC_DECISIONS.md` as DEC-0001 +(interpretation, pending TCG Part 4 v185 publication). + +### Sign / Verify Sequences + +Pure ML-DSA is **one-shot** — `TPM2_SequenceUpdate` on a Pure ML-DSA sign +sequence returns `TPM_RC_ONE_SHOT_SIGNATURE`; the message must arrive via the +`buffer` parameter of `TPM2_SignSequenceComplete`. Verify sequences accumulate +the message via `TPM2_SequenceUpdate` since `TPM2_VerifySequenceComplete` has no +buffer parameter. + +Hash-ML-DSA sequences (both sign and verify) use wolfCrypt's `wc_HashAlg` context +to stream the message into the key's hash algorithm; `TPM2_SignSequenceComplete` +finalizes the hash and calls `wc_dilithium_sign_ctx_hash`. + +Signature wire formats differ per spec Part 2 Table 217: + +- **Pure ML-DSA** → `TPM2B_SIGNATURE_MLDSA`: `sigAlg + size + bytes` +- **Hash-ML-DSA** → `TPMS_SIGNATURE_HASH_MLDSA`: `sigAlg + hashAlg + size + bytes` + +### Buffer Constants + +Under `WOLFTPM_V185`, buffers are lifted to accommodate ML-DSA-87 signatures +(4627 bytes) and public keys (2592 bytes): + +| Symbol | v1.38 | v1.85 | +|---|---|---| +| `FWTPM_MAX_COMMAND_SIZE` | 4096 | 8192 | +| `FWTPM_MAX_PUB_BUF` | 512 | 2720 | +| `FWTPM_MAX_DER_SIG_BUF` | 256 | 4736 | +| `FWTPM_MAX_KEM_CT_BUF` | — | 1600 | +| `FWTPM_TIS_FIFO_SIZE` | 4096 | 8192 | +| `FWTPM_NV_PUBAREA_EST` | 600 | 2720 | + +### Deferred / Out of Scope + +Three v1.85 features are deferred with documented reasons: + +1. **ML-KEM-salted sessions** — Part 3 §11.1 (`TPM2_StartAuthSession`) does not + describe an ML-KEM bullet alongside RSA-OAEP and ECDH paths, even though + Part 2 §11.4.2 Table 222 defines the `mlkem` arm of `TPMU_ENCRYPTED_SECRET`. + Part 4 v185 (which would normatively specify this) is not yet published. + Current behavior: `TPM2_StartAuthSession` returns `TPM_RC_KEY` for ML-KEM + tpmKey. See `SPEC_DECISIONS.md` DEC-0002. +2. **External-μ ML-DSA signing** — wolfCrypt has no μ-direct sign API. Part 2 + §12.2.3.7 text says "512-byte external Mu" but FIPS 204 Algorithm 7 Line 6 + produces 64 bytes (SHAKE256 output). Pending wolfCrypt API addition and + TCG errata confirmation. Current behavior: `TPM_RC_SCHEME` for ext-μ paths, + `TPM_RC_EXT_MU` for Pure ML-DSA keys without `allowExternalMu`. See DEC-0006. +3. **ECC KEM arm of Encapsulate/Decapsulate** — Part 2 §10.3.13 Table 100 has + both `mlkem` and `ecdh` arms, but the table note explicitly allows + implementations to modify the union based on supported algorithms. Current + fwTPM supports the `mlkem` arm only. + +### Test Coverage + +`tests/fwtpm_unit_tests.c` includes ten PQC tests exercising the full path: + +- CreatePrimary for MLKEM-768 and MLDSA-65 +- Full Encap/Decap round-trip (shared secret byte match) +- Hash-ML-DSA SignDigest / VerifyDigestSignature round-trip +- Pure ML-DSA sign sequence + verify sequence round-trip +- Dual-source KAT tests (NIST ACVP + wolfSSL internal vectors) for MLDSA-44 + verify, MLDSA-44 keygen determinism, MLKEM-512 encapsulation with pinned + randomness, and MLKEM-512 keygen determinism +- LoadExternal of a NIST ACVP MLDSA-44 public key through the fwTPM handler diff --git a/docs/README.md b/docs/README.md index e692172e..bd306519 100644 --- a/docs/README.md +++ b/docs/README.md @@ -37,6 +37,20 @@ Platform Configuration Registers (PCRs) are one of the essential features of a T wolfTPM contains hash digests for SHA-1 and SHA-256 with an index 0-23. These hash digests can be extended to prove the integrity of a boot sequence (secure boot). +### Post-Quantum Cryptography (TPM 2.0 v1.85) + +wolfTPM implements the post-quantum additions from **TCG TPM 2.0 Library Specification v1.85** when built with `--enable-v185`. Supported algorithms: + +* **ML-DSA** (Module-Lattice-Based Digital Signature, NIST FIPS 204) at parameter sets 44, 65, and 87 — for signing and verification. +* **Hash-ML-DSA** (pre-hashed ML-DSA variant) at the same parameter sets — for signing arbitrary digests. +* **ML-KEM** (Module-Lattice-Based Key-Encapsulation Mechanism, NIST FIPS 203) at parameter sets 512, 768, and 1024 — for key encapsulation and decapsulation. + +Eight new TPM 2.0 commands are supported: `TPM2_Encapsulate`, `TPM2_Decapsulate`, `TPM2_SignDigest`, `TPM2_VerifyDigestSignature`, `TPM2_SignSequenceStart`, `TPM2_SignSequenceComplete`, `TPM2_VerifySequenceStart`, `TPM2_VerifySequenceComplete`. + +Algorithm behavior matches FIPS 203 / FIPS 204 via wolfCrypt's ML-KEM and ML-DSA (Dilithium) modules, validated against NIST ACVP test vectors. + +The firmware TPM (fwTPM) server also implements v1.85 PQC — see [FWTPM.md](FWTPM.md#tpm-20-v185-post-quantum-support) for algorithm, command, primary-key derivation, and sequence-handler details. + ## Building wolfTPM To build the wolfTPM library, it's required to first build and install the wolfSSL library. This can be downloaded from the download page, or through a "git clone" command, shown below: diff --git a/src/fwtpm/README.md b/src/fwtpm/README.md index e521b20b..45dac749 100644 --- a/src/fwtpm/README.md +++ b/src/fwtpm/README.md @@ -9,6 +9,11 @@ examples and tpm2-tools) and TIS register-level transport over shared memory or SPI/I2C for bare-metal integration. Implements 105 of 113 TPM 2.0 v1.38 commands (93% coverage) with HAL abstractions for IO and NV storage portability. +Post-quantum cryptography support is available with `--enable-v185`, adding +ML-DSA (FIPS 204) signing and ML-KEM (FIPS 203) key encapsulation per TCG +TPM 2.0 Library Specification v1.85. See [`docs/FWTPM.md`](../../docs/FWTPM.md#tpm-20-v185-post-quantum-support) +for algorithm and command details. + ## Building wolfSSL must be built with `--enable-keygen` and `WC_RSA_NO_PADDING`: