Commit Graph

314 Commits (1d8ea0cfd2df6188701f6fd8c0aba9ad3bc1b743)

Author SHA1 Message Date
aidan garske 67feae3d8b 6744 - Exercise crypto-callback ECDSA invalid-signature branch in test 2026-07-07 13:30:59 -07:00
aidan garske ee00c70468 6746 - Right-align short ECC coordinates in wolfTPM2_EccKey_TpmToWolf 2026-07-07 13:26:00 -07:00
aidan garske 9a56a4632d 6745 - Fix RSA exponent byte order in wolfTPM2_RsaKey_TpmToWolf 2026-07-07 13:19:17 -07:00
aidan garske c29d5ecf3a 6743 - Add CalcHmac KAT and cpHash/attributes binding checks 2026-07-07 13:16:02 -07:00
aidan garske 7b853561ae 6742 - Add KDFe known-answer vector to pin hash-input construction 2026-07-07 13:14:20 -07:00
aidan garske e41d2c91d9 6738 - Require explicit master password in wolfTPM2_SetIdentityAuth 2026-07-07 12:41:16 -07:00
aidan garske cd46447d0b 6749 - Bound ECDH response x-coordinate against caller buffer capacity 2026-07-07 12:41:03 -07:00
aidan garske 7e8aec50f1 6748 - Gate fwTPM TestParms PQC arms on WOLFTPM_MLDSA/WOLFTPM_MLKEM 2026-07-07 12:40:08 -07:00
aidan garske 3580000772 F-6554 - Bound response parameterSize against response size in TPM2_ResponseProcess 2026-06-30 12:15:36 -07:00
Aidan Garske 5506a191a2
Merge pull request #540 from dgarske/fwtpm_flash_nv_and_uart_symlink
fwTPM: append-only NV journal for write-once flash + swtpm UART symlinks
2026-06-29 12:40:45 -07:00
David Garske b8709b13dd fwTPM: append-only NV journal for write-once flash ports and swtpm UART symlink support 2026-06-29 11:33:19 -07:00
David Garske 9ddd51b06d Add parameter-encryption regression tests and PQC example coverage 2026-06-29 09:56:44 -07:00
aidan garske 720d90285a Address review: guard retry code with WOLFTPM_NO_RETRY, drop wrappers, document option 2026-06-25 15:18:25 -07:00
aidan garske 550cea93ab Add transparent TPM_RC_RETRY resubmit at command chokepoint 2026-06-25 15:18:24 -07:00
David Garske 1601a78890
Merge pull request #541 from aidangarske/fwtpm-da-hardening
fwTPM: Dictionary Attack (DA) hardening and DA/noDA test coverage
2026-06-25 15:11:51 -07:00
aidan garske df0fb838d9 fwTPM: harden Dictionary Attack (DA) protection to TCG spec and add DA/noDA test coverage 2026-06-25 09:09:36 -07:00
aidan garske 41a89aa5a8 Add _ex wrappers to select session, RSA OAEP and PQC template hash algorithms 2026-06-24 11:15:38 -07:00
aidan garske ac87e6bb7a F-6318 - Create readKeyBlob test files with owner-only permissions 2026-06-22 13:03:13 -07:00
aidan garske 68f4084830 F-6312 - Cover ECC, KEYEDHASH, SYMCIPHER arms in AppendSensitive clamp test 2026-06-22 12:38:24 -07:00
aidan garske 9e7769a08a F-6318 - Return BUFFER_E on short private read in readKeyBlob 2026-06-22 12:37:54 -07:00
aidan garske b5be21d275 F-6314 - Add maximum-size TPM2B sensitive roundtrip test 2026-06-22 12:04:42 -07:00
aidan garske 05f6cb7fd0 F-6317 - Add testable SPDM I/O response-size validation helper 2026-06-22 12:02:29 -07:00
aidan garske 02bc64173a F-6316 - Add testable TIS response-size validation helper 2026-06-22 12:00:04 -07:00
aidan garske af8fe5b72b F-6313 - Clear publicArea when ParsePublic reads zero size 2026-06-22 11:56:46 -07:00
aidan garske 98a5f95fff F-6312 - Clamp classic-arm inner size in TPM2_Packet_AppendSensitive 2026-06-22 11:55:03 -07:00
aidan garske 7e060e1915 F-6315 - Add testable swtpm response-size validation helper 2026-06-22 11:37:35 -07:00
aidan garske c6b2104f3f F-6318 - Validate priv size marker before read in readKeyBlob 2026-06-22 11:28:56 -07:00
David Garske 85757e94a2
Merge pull request #527 from aidangarske/pqc-granular-macros
Fine-grained PQC (v1.85) build macros: trim ML-DSA/ML-KEM by algorithm and operation
2026-06-16 15:11:54 -07:00
aidan garske 8512df5bf7 fwTPM: always set continueSession in password authorization response (issue #529) 2026-06-16 13:50:46 -07:00
aidan garske ad08b88d6e Add fine-grained PQC build macros to trim v1.85 ML-DSA/ML-KEM by algorithm and operation 2026-06-15 15:49:34 -07:00
David Garske ba6563edac
Merge pull request #520 from aidangarske/pqc-tpm-fixes
Fix PQC minor leak, capability-gate tests, add negative examples, add PQC benchmarks
2026-06-09 15:13:08 -07:00
David Garske 5b8e46f77b
Merge pull request #523 from aidangarske/fenrir-fixes-15
Harden Testing and fwTPM/src
2026-06-09 15:11:55 -07:00
aidan garske 0ed88b3753 tests: add HashFinish undersized-buffer regression test 2026-06-09 12:29:31 -07:00
David Garske 01301c40d0 Fix ecc-default-curve-p384 CI: P256-sized buffer overflow + scope to make check
test_wolfTPM2_LoadEccPublicKey_Ex harvested SRK X/Y coordinates into
byte[32] buffers and reloaded them hardcoding TPM_ECC_NIST_P256. Under
-DWOLFTPM2_ECC_DEFAULT_CURVE=TPM_ECC_NIST_P384 the SRK is P384, so the
48-byte coordinates overflowed the 32-byte stack buffers (FORTIFY abort,
the failing CI job). Size the buffers to MAX_ECC_KEY_BYTES and reload
using the SRK's actual curve/nameAlg so the test is curve-agnostic.

Scope the ecc-default-curve-p384 job to 'make check': unit.test exercises
the SRK/AIK -> P384/SHA384 upgrade and explicit-curve/ECDHE honoring
end-to-end. run_examples.sh is omitted because several demos (pcr/quote,
boot/secure_rot, native_test) hardcode SHA256 for the ECC sign/quote
scheme - a demo limitation, not a library issue.
2026-06-09 11:09:06 -07:00
David Garske 4590e79e14 Improve testing for WOLFTPM2_ECC_DEFAULT_CURVE 2026-06-09 10:43:27 -07:00
Aidan Garske 557aae6d03 wolfTPM v1.85 PQC: leak fix, capability-gated tests, negative examples, benchmark 2026-06-08 23:08:27 +01:00
David Garske 6c11045492 Add new WOLFTPM2_ECC_DEFAULT_CURVE 2026-06-05 12:44:48 -07:00
aidan garske 5699061b53 fwtpm: scope context replay to sessions and accept unsalted param-enc 2026-06-03 10:57:13 -07:00
aidan garske 57f49c79f8 F-4673 - Track live context sequences for any-order single-use load 2026-06-03 10:37:09 -07:00
aidan garske 5453e6ff26 F-5654 F-5719 F-5277 F-5122 F-4845 F-4955 - Harden fwTPM fixes per review 2026-06-03 10:37:08 -07:00
aidan garske 34930558e3 F-5648 F-5649 - Add HMAC verify truncation and compute buffer-size tests 2026-06-03 10:37:08 -07:00
aidan garske 5617f43aae F-5277 F-5122 - Store and enforce policy cpHashA command binding 2026-06-03 10:36:32 -07:00
aidan garske 77f502279e F-5105 F-5106 F-5107 - Require signing key for attestation commands 2026-06-03 10:36:32 -07:00
aidan garske 6c9a64efd7 F-5102 F-5119 F-5833 - Authenticate NV journal with integrity MAC 2026-06-03 10:36:32 -07:00
aidan garske 2f059c34b6 F-5101 F-5108 - Flush transient state on command client change 2026-06-03 10:36:32 -07:00
aidan garske 60aef67a05 F-4673 - Bind context sequence counter to blob and reject replay 2026-06-03 10:36:32 -07:00
aidan garske c03db2d23d F-5678 - Populate attestation clockInfo from live TPM state 2026-06-03 10:36:32 -07:00
aidan garske 6f3c20fe07 F-4953 F-5095 - Enforce key-declared signing scheme over wire scheme 2026-06-03 10:36:31 -07:00
aidan garske 4e7c88b995 F-5722 - Enforce per-hierarchy persistent sub-range in EvictControl 2026-06-03 10:36:31 -07:00
aidan garske b1a4528393 F-5677 - Reject newMaxTries=0 in DictionaryAttackParameters 2026-06-03 10:36:31 -07:00
aidan garske 9245b19203 F-5719 - Bind and enforce PolicyLocality constraint on policy sessions 2026-06-03 10:36:31 -07:00
aidan garske 84705f08ca F-5721 - Enforce DRTM PCR locality in fwTPM PCR_Event 2026-06-03 10:36:31 -07:00
aidan garske cb32e61d26 F-5654 F-5655 - Validate selftest params and report test status 2026-06-03 10:36:31 -07:00
aidan garske 991ae59be4 F-4841 F-5832 - Enforce NV read authorization in PolicyNV and PolicyAuthorizeNV 2026-06-03 10:36:31 -07:00
aidan garske a62c5b124b F-5104 - Require restricted signing key in fwTPM Quote 2026-06-03 10:36:31 -07:00
aidan garske d7beca2444 F-5120 - Reject TPM_RH_NULL and non-storage newParent in Rewrap 2026-06-03 10:36:31 -07:00
aidan garske eb359d33e1 F-5097 F-5103 F-5831 - Enforce decrypt attribute on ECDH commands 2026-06-03 10:36:31 -07:00
David Garske dafb0f62cf F-4742 fix and test case 2026-06-01 15:57:40 -07:00
aidan garske 010ea7d1d8 Replace em-dashes with hyphens in comments per review 2026-05-26 17:00:19 -07:00
aidan garske c97fe5c8b5 F-4742 — Revert zero-digest reject; NULL ticket is spec-compliant per Part 2 Sec.10.6.5 2026-05-26 17:00:19 -07:00
aidan garske 6003e7256e F-4170 + F-4171 — Fix TPMT_HA HMAC arm wire marshaling on sign and verify 2026-05-26 17:00:18 -07:00
aidan garske 16e3eccb37 F-4742 — PolicyAuthorize zero-ticket bypass forges policyDigest chain
FwCmd_PolicyAuthorize gated the entire HMAC verification block on
ticketDigestSz > 0 (same pattern as the prior FwCmd_PolicyTicket fix).
An attacker could submit ticketTag=TPM_ST_VERIFIED with
ticketDigestSz=0, pass the tag check, skip FwComputeTicketHmac and
TPM2_ConstantCompare entirely, and fall through to the policyDigest
extension using attacker-supplied approvedPolicy and keySignName.

This is the root of the F-4742 chain: combined with an empty-HMAC
policy session, the forged policyDigest matches the entity's authPolicy
in FWTPM_ProcessCommand and grants access to any PolicyAuthorize-
protected object whose userWithAuth is clear, without possession of
any signing key. Cutting the chain at PolicyAuthorize blocks the whole
sequence. The empty-HMAC behavior on policy sessions is intentional
per the existing in-code comment (spec-conformant when neither
PolicyAuthValue nor PolicyPassword has been called) and is not
modified here.

Reject ticketDigestSz==0 with TPM_RC_TICKET after the tag check, and
drop the redundant ticketDigestSz > 0 guard from the HMAC block so
verification runs unconditionally for every accepted ticket.

Add a negative test that issues TPM2_PolicyAuthorize with
TPM_ST_VERIFIED and digest size 0 against a policy session and asserts
TPM_RC_TICKET.
2026-05-26 17:00:18 -07:00
aidan garske 2abe5e13f6 F-4375 — LoadExternal SYMCIPHER OOB write via dead bounds check
FwCmd_LoadExternal's SYMCIPHER copy path gated the XMEMCPY into
privKeyDer only on qSz > FWTPM_MAX_DER_SIG_BUF, duplicating the outer
parse check rather than testing the destination size. On v1.85 builds
with any ML-DSA parameter set enabled FWTPM_MAX_DER_SIG_BUF grows to
2548–4755 while FWTPM_MAX_PRIVKEY_DER stays at 1280 (or 256 in NO_RSA
builds), so any qSz between FWTPM_MAX_PRIVKEY_DER + 1 and
FWTPM_MAX_DER_SIG_BUF wrote up to 3475 attacker-controlled bytes past
the destination buffer.

Replace the dead guard with an explicit valid-AES-key-size check per
TPM 2.0 Part 2 Sec.11.1.9 — accept only 16, 24, or 32 bytes for a
SYMCIPHER sensitive area and return TPM_RC_SIZE otherwise. Every
allowed length is well within FWTPM_MAX_PRIVKEY_DER on every supported
build, so the destination overflow is no longer reachable.

Add a negative test that submits SYMCIPHER LoadExternal with qSz=33
(passes the FWTPM_MAX_DER_SIG_BUF gate on non-v1.85 builds, exceeds
both the AES set and the destination on v1.85 builds) and asserts
TPM_RC_SIZE.
2026-05-26 17:00:18 -07:00
aidan garske 08a197ab06 F-4374 — PolicyTicket zero-digest bypass forges PolicySigned extension
FwCmd_PolicyTicket gated the entire HMAC verification block on
ticketDigestSz > 0. A caller could submit ticketTag=TPM_ST_AUTH_SIGNED
with ticketDigestSz=0, pass the tag check, skip FwComputeTicketHmac and
TPM2_ConstantCompare entirely, and fall through to FwPolicyExtend with
attacker-supplied authName/policyRef as if a valid PolicySigned or
PolicySecret ticket had been presented. The forged extension then
satisfied any PolicySigned or PolicySecret clause for an arbitrary
named entity without possession of any signing key.

Reject ticketDigestSz==0 with TPM_RC_TICKET immediately after the tag
check, and drop the redundant ticketDigestSz > 0 guard from the HMAC
block so verification runs unconditionally for every accepted ticket.

Add a negative test that issues TPM2_PolicyTicket with ticketTag
TPM_ST_AUTH_SIGNED and digest size 0 against a policy session and
asserts TPM_RC_TICKET.
2026-05-26 17:00:18 -07:00
aidan garske 00079a610f F-4373 — TPM2_Clear unauthenticated wipe via TPM_ST_NO_SESSIONS bypass
FWTPM_ProcessCommand parsed the auth area only under
if (cmdTag == TPM_ST_SESSIONS), so a NO_SESSIONS command with
authHandleCnt > 0 left cmdAuthCnt at 0 and bypassed every downstream
policy, password, and HMAC enforcement loop. An 18-byte unauthenticated
TPM2_Clear wiped owner and endorsement state, reseeded both hierarchies,
and reset PCRs.

Add a centralized gate immediately after the command-table lookup that
returns TPM_RC_AUTH_MISSING when the tag is TPM_ST_NO_SESSIONS but the
handler declares authHandleCnt > 0. Matches the spec rule that any auth
role requires TPM_ST_SESSIONS, and closes the same gap that already had
per-handler guards on a few callers.

Add a negative test that issues TPM2_Clear with TPM_ST_NO_SESSIONS and
asserts TPM_RC_AUTH_MISSING is returned without any state mutation.
2026-05-26 17:00:18 -07:00
aidan garske a53c28be00 F-4377 — Revert NULL-hierarchy reject; NULL tickets are spec-compliant 2026-05-26 13:40:33 -07:00
aidan garske 6914245bad F-4378 — Enforce per-PCR locality table in FwCmd_PCR_Reset 2026-05-26 12:34:46 -07:00
aidan garske b3ca0273ea F-4750 — Enforce authPolicy.size matches hashAlg in FwCmd_SetPrimaryPolicy 2026-05-26 12:30:18 -07:00
aidan garske f1117a609f F-4747 — Reject persistent objectHandle in EvictControl make-persistent path 2026-05-26 12:29:15 -07:00
aidan garske 566faa55c0 F-4746 — Reject out-of-range persistentHandle in FwCmd_EvictControl 2026-05-26 12:28:13 -07:00
aidan garske a8d7c84bed F-4745 — Look up ctx->pcrAuth in FwLookupEntityAuth for PCR handles 2026-05-26 12:27:00 -07:00
aidan garske 75216a3db0 F-4744 — Reject zero-digest creation ticket in FwCmd_CertifyCreation 2026-05-26 12:19:31 -07:00
aidan garske c1f7032941 F-4377 — Reject NULL-hierarchy ticket in FwCmd_PolicyAuthorize 2026-05-26 12:17:49 -07:00
Tobias Frauenschläger 77e31c0ebb ML-DSA renaming 2026-05-20 13:09:26 -07:00
aidan garske 1e6393938b Fix empty brace scope scan findings 2026-05-14 17:50:08 -07:00
Aidan Garske 852c2d2408 F-3715 - Test SHA3/PQC GetAlgId, EncryptDecryptBlock alignment, and Decode wrap-key scaling 2026-05-11 21:56:45 -07:00
Aidan Garske 8db493a96c F-3719 - Add KAT for TPM2_ParamEnc_AESCFB cross-checking KDFa+AES-CFB 2026-05-11 20:35:44 -07:00
David Garske 3bd3f0a8d1 Add capabilities to properly show FIPS 140-3 2026-05-11 11:35:01 -07:00
Aidan Garske 6f8bae6c58 Fix changes to pqc header file rename 2026-05-08 10:04:01 -07:00
Aidan Garske d518bffe97 fwTPM v185: final skoll reivew pass 2026-04-29 10:29:51 -07:00
Aidan Garske 484df3cdf3 fwTPM v185: Skoll review-cycle fixes (TCG + multi-scan) 2026-04-29 10:29:51 -07:00
Aidan Garske 86188f5754 fwTPM v185: TCG Phase B compliance — full sign/verify, KEM, and seed support
Bring TPM 2.0 v1.85 fwTPM implementation to full TCG compliance for the
  sign/verify, KEM, and key-exchange paths. This unblocks interop with the
  TCG simulator and removes four scope gaps surfaced by Skoll TCG review.

  TCG Phase B fixes (4 of 4):

  - TCG-HIGH-3: TPM2_VerifySequenceComplete now binds the streamed message
    bytes in the TPMT_TK_VERIFIED ticket per Part 2 Sec.10.6.5 Eq (5).
    Hash-ML-DSA SequenceUpdate mirrors bytes into seq->msgBuf alongside
    the hash accumulator, so the ticket builder has the material at
    Complete time. Pure ML-DSA already had this; both paths now share one
    ticket-data construction.

  - TCG-HIGH-2: ECC DHKEM Encapsulate/Decapsulate per RFC 9180 Sec.4.1 +
    Part 2 Sec.12.2.3.5. Added FwEncapsulateEcdhDhkem/FwDecapsulateEcdhDhkem
    helpers in fwtpm_crypto.c implementing LabeledExtract/LabeledExpand over
    HKDF. Curve-hash pairings: P-256/SHA256 (kem_id 0x0010), P-384/SHA384
    (0x0011), P-521/SHA512 (0x0012). Wire ciphertext is SEC1-uncompressed
    ephemeral public key. Added TPM_ALG_HKDF=0x001F to wolftpm/tpm2.h.

  - TCG-HIGH-4: ML-KEM Labeled KEM in FwEncryptSeed/FwDecryptSeed per
    Part 1 Sec.47.4 Eq.66:
      seed = KDFa(nameAlg, K, label, ciphertext, publicKey, bits)
    This unlocks ML-KEM as TPM2_StartAuthSession salt key, TPM2_Import
    newParent, TPM2_MakeCredential issuer, etc.

  - TCG-HIGH-1: Classical RSA/ECC sign+verify in v1.85 sequence/digest
    commands. Extended FwCmd_SignDigest, FwCmd_VerifyDigestSignature,
    FwCmd_SignSequenceStart/Complete, FwCmd_VerifySequenceStart/Complete,
    and the SequenceUpdate dispatch to accept TPM_ALG_RSA/TPM_ALG_ECC keys.
    Reuses existing FwSignDigestAndAppend + FwVerifySignatureCore helpers;
    signature scheme/hashAlg resolved from the key's metadata.

  Earlier review-cycle fixes also included in this commit:

  - src/tpm2.c: TPM2_VerifySequenceComplete/VerifyDigestSignature use
    TPM2_Packet_ParseU16Buf for atomic clamp+skip of the validation digest
    field. TPM2_Encapsulate CmdInfo flags switched to CMD_FLAG_DEC2 (the
    protected value is the first response param, not a command param).

  - src/tpm2_wrap.c: wolfTPM2_VerifySequenceComplete moved per-key-type
    sigSz validation ahead of the internal SequenceUpdate to avoid leaking
    the sequence handle on BUFFER_E (CWE-772). Added ECC arm. Added defensive
    ForceZero in wolfTPM2_EncryptSecret_MLKEM on the failure path so partial
    KDFa output cannot leak via callers that ignore rc.

  - src/tpm2_packet.c: comment fix MAX_MLDSA_KEY_BYTES -> MAX_MLDSA_PRIV_SEED_SIZE.

  - wolftpm/tpm2.h: TPM_RC_PARMS moved out of WOLFTPM_V185 guard (it has
    been part of TCG Part 2 since v1.16, not v1.85 — Windows CI fix).

  - tests/unit_tests.c: align tab-formatted Test TPM Wrapper output lines
    to the same column as the rest.

  Tests:
  - 6 new fwtpm_unit tests (Hash-MLDSA ticket binds message, ECC DHKEM
    roundtrip, ML-KEM seed roundtrip, ECDSA SignDigest+VerifyDigestSignature
    roundtrip, ECDSA SignSequence+VerifySequence roundtrip).
  - 1 existing negative test updated: VerifyDigestSignature with RSASSA on
    ML-DSA key now returns TPM_RC_KEY (key-type mismatch) instead of
    TPM_RC_SCHEME (which previously meant scheme unsupported).

  Validation: tests/fwtpm_unit.test 117/0; tests/fwtpm_check.sh 2/0/1 (incl.
  308/0 tpm2-tools compat against fwtpm_server); make check FAIL: 0.
2026-04-29 10:29:51 -07:00
Aidan Garske 539c94b68e fwTPM v185: Fix autodetect 2026-04-29 10:29:51 -07:00
Aidan Garske 9ce41885e0 fwTPM v185: PR review fixes + TCG/security hardening
Build / portability:
  - Drop #pragma message in fwtpm_crypto.c (MSVC-incompatible)
  - Replace non-ASCII section sign with Sec. across all sources/docs

  Configure:
  - Add --enable-pqc alias for --enable-v185 (same WOLFTPM_V185 macro)
  - Auto-detect: when --enable-fwtpm + wolfCrypt has dilithium.h+mlkem.h
    and neither flag is set, configure auto-enables PQC; --disable-pqc
    opts out
  - Both flags probe the wolfSSL PQC headers and fail at configure time
    with a clear hint when missing

  Spec / security hardening:
  - VerifySequenceComplete now emits TPM_ST_DIGEST_VERIFIED (with hashAlg
    metadata) for Hash-ML-DSA tickets, MESSAGE_VERIFIED for Pure ML-DSA
    (was mis-tagging digests as messages, breaking PolicyTicket consumers)
  - Sign/VerifySequenceComplete: free the slot on TPM_RC_SIGN_CONTEXT_KEY
    too, so wrong-key Complete cannot exhaust FWTPM_MAX_SIGN_SEQ slots
    (CWE-772 DoS)
  - TestParms PQC arms return TPM_RC_PARMS (spec-correct) instead of
    TPM_RC_VALUE; reject MLDSA/MLKEM parameter sets not actually compiled
    in; parse TPMS_MLKEM_PARMS.symmetric via TPM2_Packet_ParseSymmetric
  - GetCapability TPMA_ML_PARAMETER_SETS gates each MLDSA/MLKEM bit on the
    per-set wolfCrypt availability macro (subset builds advertise truth)
  - TPM2_VerifySignature client parser now defensive: only consume the
    v1.85 metaAlg when tag==DIGEST_VERIFIED && hierarchy!=RH_NULL
  - VerifyDigestSignature: hard-fail on keyName overflow instead of
    silently emitting a ticket missing the name binding
  - TPM_GENERATED_VALUE prefix check guarded with rc==0
  - Drop dead (void)cmdSize casts in Sign/VerifySequenceStart
  - wolfTPM2_EncryptSecret_MLKEM: track wc_InitRng_ex/wc_MlKemKey_Init
    success flags so Free is only called on initialized state
  - UBSan-v185 sanitizer cflags: explicitly disable signed-integer-overflow
    and shift checks (matches the comment about wolfSSL Hash_df 440<<24)

  Embedded RAM:
  - FWTPM_NV_PUBAREA_EST derives from FWTPM_MAX_MLDSA_PUB_SIZE /
    FWTPM_MAX_MLKEM_PUB_SIZE auto-shrink macros (subset builds save NV)
  - tpm2_types.h MAX_MLDSA_*/MAX_MLKEM_* stay at worst-case (ABI floor
    for TPM2B wire buffers) with comment

  Tests:
  - Negative test for Hash-MLDSA VerifySeqComplete ticket tag
  - Negative test exposing sign-seq slot leak on TPM_RC_SIGN_CONTEXT_KEY
  - Roundtrip test for wolfTPM2_SignDigest + VerifyDigestSignature

  Documentation:
  - README, FWTPM.md, fwtpm/README.md, examples/pqc/README.md mention
    both --enable-pqc and --enable-v185 + auto-detect
  - README wolfSSL line: --enable-pkcallbacks + WC_RSA_NO_PADDING
  - fwtpm/README.md: drop FWTPM_SPEC_* labels (macros never existed),
    remove v1.85 Additions table (all 8 commands implemented), update
    coverage table to 137/113/24 (82%); note remaining gaps are
    inherited v1.59/v1.84 commands, not PQC
  - fwtpm_nv.h:52: clarify 2592 vs 2720 math (PQC pub key + header slack)
2026-04-29 10:29:51 -07:00
Aidan Garske f568e048bd fwTPM v185: TCG/security review fixes + embedded RAM auto-shrink
Code quality / defensive fixes:
  - TPM2_Encap/Decap: drop bare scope braces, hoist wireSize locals
  - FwCmd_SequenceUpdate: clarify Pure ML-DSA sign accumulation comment
  - FwAllocSignSeq: _Static_assert transient slot range stays valid
  - keygen: drop unused hashMldsaHash local, pass TPM_ALG_SHA256 directly
  - FwCmd_Encapsulate: skip auth area when cmdTag == TPM_ST_SESSIONS
  - writeKeyBlob: restore no-op TPM_RC_SUCCESS in NO_FILESYSTEM build
  - FwCmd_SignDigest restricted-key ticket compare: TPM2_ConstantCompare
  - FwCmd_VerifySequenceComplete: hard-fail if ticket data binding lost
    (no silent fallback that emits a weakened ticket)
  - wolfTPM2_VerifySequenceComplete: validate sigSz before SequenceUpdate
    so BUFFER_E does not leak the TPM-side sequence handle
  - FwCmd_VerifySequenceComplete: heap-allocate ~1KB ticketData via
    FWTPM_DECLARE_BUF / FWTPM_ALLOC_BUF (matches sibling buffers)

  v1.85 capability + scope:
  - GetCapability: report TPM_PT_FIRMWARE_SVN/MAX_SVN = 0
  - Allow Pure ML-DSA streaming via SequenceUpdate per FIPS 204 (SHAKE256
    absorbing is incremental); SignSequenceComplete concatenates msgBuf
    with the trailing complete-time buffer and signs the full message
  - Document v1.85 scope: Encap/Decap is ML-KEM only; Sign/VerifySequence
    and SignDigest/VerifyDigestSignature are ML-DSA / Hash-ML-DSA only
    (classical schemes still go via TPM2_Sign / TPM2_VerifySignature)

  TCG ticket wire-format fixes (security):
  - TPMT_TK_HASHCHECK: SignDigest now validates tag = TPM_ST_HASHCHECK
    unconditionally (TPM_RC_TAG); wolfTPM2_SignDigest wrapper synthesizes
    the NULL Hashcheck instead of sending tag=0/hierarchy=0 from XMEMSET
  - NULL Verified Tickets: FwAppendTicket no longer appends metadata
    bytes when hierarchy == TPM_RH_NULL; client parser conditions
    metaAlg consumption on hierarchy != TPM_RH_NULL (Part 2 §10.6.5)

  Embedded RAM auto-shrink (v1.85):
  - New FWTPM_MAX_MLDSA_{SIG,PUB}_SIZE / FWTPM_MAX_MLKEM_{CT,PUB}_SIZE
    resolve to the largest enabled parameter set via wolfCrypt's
    WOLFSSL_NO_ML_DSA_{44,65,87} / WOLFSSL_NO_KYBER{512,768,1024} gates
  - FWTPM_MAX_DER_SIG_BUF, FWTPM_MAX_PUB_BUF, FWTPM_MAX_KEM_CT_BUF
    derive from those (no per-board override needed)
  - FWTPM_MAX_COMMAND_SIZE / FWTPM_TIS_FIFO_SIZE only lift to 8192 when
    MLDSA-65 or MLDSA-87 is enabled; MLDSA-44-only and MLKEM-only
    v1.85 builds stay at 4096
  - docs/FWTPM.md: per-build size table + override + small-stack notes

  Test coverage:
  - examples/run_examples.sh: invoke pqc/mldsa_sign and pqc/mlkem_encap
    inside the v1.85 block
  - tests/fwtpm_unit_tests.c:
    * SignDigest with malformed HASHCHECK tag rejected (TPM_RC_TAG)
    * FwAppendTicket NULL DIGEST_VERIFIED emits no metadata
    * SignSeqComplete Pure-MLDSA streaming (FIPS 204 §6) — replaces
      obsolete one-shot rejection assertion
  - tests/unit_tests.c:
    * Hash-ML-DSA SignSeqUpdate streaming end-to-end + arg validation
    * TPMT_SIGNATURE round-trip for ML-DSA / Hash-ML-DSA arms
    * TPM2B_PUBLIC round-trip for ML-DSA / Hash-ML-DSA / ML-KEM arms
2026-04-29 10:28:44 -07:00
Aidan Garske 72fd6f40c6 fwTPM: thread ticketTag through FwComputeTicketHmac (sym verify+produce) 2026-04-29 10:28:44 -07:00
Aidan Garske 9b9406837e Fix CI: TCG + Skoll review feedback 2026-04-29 10:28:44 -07:00
Aidan Garske d9143e3084 fwTPM v1.85: TCG + Skoll review fixes (round 2)
Closes 13 findings across two reviews of the v1.85 PQC paths.

   Tickets (TPMT_TK_VERIFIED / TPMT_TK_HASHCHECK / TPMT_TK_CREATION):
   - FwAppendTicket binds tag (always) and metadata (DIGEST_VERIFIED only)
     into the HMAC per Part 2 §10.6.5 Eq (5). Streamed via chunked
     wc_HmacUpdate, no temp buffer. All 5 callers updated; the hand-rolled
     VerifyDigestSignature path collapses into FwAppendTicket.
   - FWTPM_Object gains a hierarchy field, captured at every load/create
     site (CreatePrimary, Load, LoadExternal, CreateLoaded). Replaces
     hardcoded TPM_RH_OWNER in VerifySignature, VerifySequenceComplete,
     VerifyDigestSignature, ContextSave, and Create's creation ticket.
   - VerifySequenceComplete snapshots the verified digest before
     wc_HashFinal so Hash-ML-DSA tickets bind (digest || keyName) rather
     than just keyName — pre-fix, two distinct verified digests on the
     same key produced byte-identical tickets (universal reuse).

   Authorization:
   - Sign/VerifySequenceStart split TPM_RC_KEY (non-signing key, e.g.
     ML-KEM) from TPM_RC_SCHEME (signing key, scheme unsupported) using
     TPMA_OBJECT_sign per Part 3 §17.5.1 / §17.6.1.
   - SignDigest restricted-key path validates TPMT_TK_HASHCHECK HMAC
     per Part 3 §20.7.1 instead of blanket-rejecting; x509sign keeps
     the TPM_RC_ATTRIBUTES short-circuit.
   - Decapsulate, SignDigest, SignSequenceComplete reject NO_SESSIONS
     with TPM_RC_AUTH_MISSING (Auth Role: USER, Tables 62/124/126).

   Restricted-key TPM_GENERATED_VALUE check:
   - FWTPM_SignSeq.firstBytes[4] populated by SequenceUpdate covers the
     Hash-ML-DSA path where bytes are otherwise consumed by hashCtx;
     topped-up from the Complete trailing buffer for Pure-MLDSA one-shot.
     Closes the Update-then-empty-Complete bypass.

   Client-side (src/tpm2.c):
   - TPM2_VerifySequenceComplete defensively dispatches on validation.tag
     for TPMU_TK_VERIFIED_META, mirroring TPM2_VerifyDigestSignature.

   Other:
   - TPM2_Packet_AppendSensitive caps mldsa/mlkem .size to buffer length.
   - pqc_mssim_e2e.c zeroizes ss1/ss2 on cleanup.
   - Untrack examples/pqc/pqc_mssim_e2e (libtool wrapper with hardcoded
     /home/aidangarske path; .gitignore already covered it).
   - #pragma message at WOLFTPM_V185 build-time flagging that the PQC
     primary-key KDFa labels are interpretation pending TCG Part 4 v1.85;
     suppressible via -DWOLFTPM_V185_LABELS_ACK.

   Tests: 11 new fixtures in tests/fwtpm_unit_tests.c, 4 existing tests
   updated to assert new spec-mandated RCs. fwtpm_unit.test reports 105
   passing, zero failures.
2026-04-29 10:28:44 -07:00
Aidan Garske 0801a30ede fwTPM v1.85: TCG compliance fixes + PQC CI matrix
Closes 13 spec-conformance findings flagged by two TCG compliance reviews
  of the v1.85 PQC handlers. Each fix maps to a specific Part 2 / Part 3
  section; all are exercised by negative test fixtures in
  tests/fwtpm_unit_tests.c that bite-verify each fix in isolation.

  Spec-RC corrections (one-line each):
  - Drop TPMA_ML_PARAMETER_SET_extMu from TPM_PT_ML_PARAMETER_SETS — Part 2
    §12.2.3.6 (no μ-direct sign API in wolfCrypt yet).
  - Sign* handlers return TPM_RC_SCHEME (not TPM_RC_KEY) for valid keys
    with unsupported scheme — Part 3 §17.5.1 / §20.7.1.
  - SignDigest / VerifyDigestSignature return TPM_RC_ATTRIBUTES (not
    TPM_RC_EXT_MU) when key's allowExternalMu=NO — EXT_MU is reserved for
    capability errors, ATTRIBUTES for key-attribute errors.

  Validation additions:
  - SignDigest rejects restricted and x509sign keys at entry
    (TPM_RC_ATTRIBUTES, Part 3 §20.7.1).
  - VerifyDigestSignature enforces sigHashAlg == key.hashAlg
    (TPM_RC_SCHEME, Part 3 §20.4.1) and digest size == hashAlg digest size
    (TPM_RC_SIZE).
  - CreatePrimary / Create / CreateLoaded / TestParms reject MLDSA with
    allowExternalMu=YES at object-creation time (TPM_RC_EXT_MU, Part 2
    §12.2.3.6) instead of letting the request succeed and fail later.
  - TestParms validates ML-DSA / Hash-ML-DSA / ML-KEM parameterSet ranges.
  - SignSequenceComplete rejects restricted keys signing messages whose
    first 4 bytes are TPM_GENERATED_VALUE (0xFF544347) (TPM_RC_VALUE,
    Part 3 §20.6.1).
  - SignSequenceComplete rejects x509sign keys (TPM_RC_ATTRIBUTES).
  - TPM_RC_ONE_SHOT_SIGNATURE moved from SequenceUpdate to
    SignSequenceComplete (Part 3 §20.6.1: it's a Complete-time RC about
    non-empty sequence, not an Update-time RC).

  Structural fixes:
  - TPMA_OBJECT_x509sign (bit 19, Part 2 §8.3.3 v1.85) added to the enum
    in wolftpm/tpm2.h and enforced in the two sign-side handlers.
  - TPM_PT_ML_PARAMETER_SETS bits gated on wolfCrypt build symbols
    (WOLFSSL_HAVE_MLKEM / KYBER_*, WOLFSSL_WC_DILITHIUM / HAVE_DILITHIUM)
    so the capability matches what the build actually delivers.
  - wolfTPM2_EncryptSecret_MLKEM applies KDFa(SECRET, ct, pub) over the
    ML-KEM shared secret per Part 1 §47.4 Eq 66 (Labeled-KEM); previous
    code emitted raw K as the salt.
  - VerifySequenceComplete and VerifyDigestSignature emit hierarchy-bound
    TPMT_TK_VERIFIED tickets (Part 2 §10.6.5) instead of the
    TPM_RH_NULL + empty-HMAC stub.

  Tests (tests/fwtpm_unit_tests.c, 8 new + 4 updated, all under fwtpm_unit):
  - 8 new spec-bite negatives, one per finding where a single-RC test is
    meaningful. Each was bite-verified by reverting its source fix and
    confirming the test fails with a different RC.
  - 4 existing negatives updated to assert the new spec-mandated RCs and
    reshaped where the rejection point moved (SequenceUpdate → Complete).

  CI:
  - New .github/workflows/pqc-examples.yml: builds + smoke-runs the v1.85
    examples + invokes tests/check_doc_constants.sh on each PR.
  - tests/check_doc_constants.sh greps every FWTPM_* size/seed/digest
    constant from wolftpm/fwtpm/fwtpm.h and asserts each is mentioned in
    docs/FWTPM.md (catches doc drift like the v1.85
    FWTPM_MAX_COMMAND_SIZE 4096→8192 bump). docs/FWTPM.md gains 6 missing
    entries (CMD_AUTHS, SENSITIVE_SIZE, SIGN_SEQ, SYM_KEY_SIZE,
    HMAC_KEY_SIZE, HMAC_DIGEST_SIZE) so the check passes clean.
  - fuzz.yml / fwtpm-test.yml / make-test-swtpm.yml / sanitizer.yml each
    gain a v1.85 matrix entry running the same checks under
    --enable-v185 + wolfSSL --enable-dilithium --enable-mlkem
    --enable-experimental.
2026-04-29 10:28:44 -07:00
Aidan Garske 71e28c12a8 Extend fuzz CI matrix to cover v1.85 PQC paths
tests/fuzz/tpm2.dict gains:
  - 8 new command codes (Encapsulate 0x1A7, Decapsulate 0x1A8,
    SignSequenceStart 0x1AA, SignSequenceComplete 0x1A4,
    VerifySequenceStart 0x1A9, VerifySequenceComplete 0x1A3,
    SignDigest 0x1A6, VerifyDigestSignature 0x1A5)
  - 3 PQC algorithm IDs (MLKEM 0x00A0, MLDSA 0x00A1, HASH_MLDSA 0x00A2)
  - 6 parameter-set values (MLKEM 512/768/1024, MLDSA 44/65/87)
  - 3 new response codes (RC_EXT_MU, RC_ONE_SHOT_SIGNATURE,
    RC_SIGN_CONTEXT_KEY)

  tests/fuzz/gen_corpus.py gains 10 PQC seed files:
  - pqc_encapsulate_mlkem, pqc_decapsulate_mlkem
  - pqc_signseqstart_mldsa, pqc_signseqcomplete_mldsa
  - pqc_verifyseqstart_mldsa, pqc_verifyseqcomplete_mldsa
  - pqc_signdigest_mldsa, pqc_verifydigestsig_mldsa
  - pqc_createprimary_mlkem, pqc_createprimary_mldsa

  These give libFuzzer starting shapes for the 8 new command paths rather
  than relying on coverage-guided discovery from scratch.

  .github/workflows/fuzz.yml matrix expanded:
  - Existing 2 entries (fuzz-full, fuzz-smoke) classical-only, unchanged
    flags, zero regression risk
  - New fuzz-full-pqc (10-min weekly) and fuzz-smoke-pqc (60s every PR)
    build wolfSSL with --enable-dilithium --enable-mlkem --enable-
    experimental --enable-harden and wolfTPM with --enable-v185, use
    -max_len=8192 to accommodate MLDSA-87 sigs (4627 bytes).
2026-04-29 10:28:44 -07:00
Aidan Garske 08b266b264 Remove Layer C fixture skeleton (tests/fixtures/v185_pqc)
The harness was Phase-1 scaffolding: driver does JSON well-formedness
  only; 6 of 8 fixtures carry TBD_PHASE_* placeholders; no byte-level
  spec assertion. Its unique value (catching client and server both
  misread the spec the same wa) requires a second v1.85 implementation
  to compare against — none exists today, and wolfTPM's wire correctness
  is already covered end-to-end by:

  - tests/fwtpm_unit.test (88 cases, in-process)
  - tests/unit.test via mssim (31 wrapper cases)
  - tests/pqc_mssim_e2e.sh (dedicated PQC round-trip)
  - examples/run_examples.sh (18-way keygen+keyload matrix)
  - scripts/tpm2_tools_test.sh (308 tpm2-tools compatibility cases)

  Rebuild from scratch if/when a second v1.85 TPM ships for interop.
2026-04-29 10:28:44 -07:00
Aidan Garske 3110a3d281 fwTPM: add PQC branches to CreateLoaded + tests
FwCmd_CreateLoaded previously handled only RSA/ECC/KEYEDHASH/SYMCIPHER;
  any caller issuing TPM2_CreateLoaded with an MLDSA or MLKEM template
  hit the default case and got TPM_RC_TYPE. The switch now mirrors the
  same three PQC arms that FwCmd_Create landed earlier (src/fwtpm/
  fwtpm_command.c lines 3649-3689):

  - TPM_ALG_MLDSA / TPM_ALG_HASH_MLDSA: draw a 32-byte Xi seed via
    wc_RNG_GenerateBlock, expand through FwGenerateMldsaKey, write the
    expanded public key to inPublic.unique.mldsa. The wire-format private
    portion is the 32-byte seed.
  - TPM_ALG_MLKEM: same pattern with a 64-byte d||z seed and
    FwGenerateMlkemKey.

  Both arms guarded on WOLFTPM_V185 to keep the non-PQC build unchanged.

  Test coverage:
  - new test_fwtpm_create_loaded_mldsa creates an RSA SRK then
    CreateLoaded an MLDSA-65 child under it, asserts TPM_RC_SUCCESS and
    a non-zero transient handle, flushes both.
  - new test_fwtpm_create_loaded_mlkem is the MLKEM-768 mirror.
  - new BuildCreateLoadedCmd helper reuses BuildCreatePrimaryCmd's
    TPMT_PUBLIC emitter and rewrites command code + parent handle,
    stripping the trailing outsideInfo + creationPCR fields that
    CreatePrimary has but CreateLoaded does not (spec Part 3 §30.2).
  - Note: server's FwCmd_CreateLoaded accepts only loaded-object parents,
    not hierarchy handles; tests CreatePrimary first to get a usable
    parent. Hierarchy-as-parent is a separate v1.38 spec feature tracked
    for follow-up.
2026-04-29 10:28:44 -07:00
Aidan Garske e86b8971df Add MLKEM arm to wolfTPM2_EncryptSecret + TPMU_ENCRYPTED_SECRET
Per TCG TPM 2.0 Library v1.85 Part 1 §24 (p.316) and Part 2 Table 222,
  v1.85 adds ML-KEM as a valid key-exchange type for encryptedSalt
  (TPM2_StartAuthSession), inSymSeed (Duplicate/Import/Rewrap), and
  credentialBlob (ActivateCredential/MakeCredential). The caller
  encapsulates under the TPM's ML-KEM public key: the 32-byte shared
  secret becomes the session salt, the ciphertext goes on the wire.

  Changes:
  - wolftpm/tpm2.h: add mlkem[MAX_MLKEM_CT_SIZE] arm to
    TPMU_ENCRYPTED_SECRET union (gated on WOLFTPM_V185). Without this the
    union sized at MAX_RSA_KEY_BYTES (512) could not hold an ML-KEM-768
    ciphertext (1088 bytes) let alone ML-KEM-1024 (1568 bytes).
  - src/tpm2_wrap.c: new static wolfTPM2_EncryptSecret_MLKEM helper that
    inits an MlKemKey from tpmKey->pub.unique.mlkem, calls
    wc_MlKemKey_Encapsulate, writes shared secret to data->buffer and
    ciphertext to secret->secret. Dispatch switch in wolfTPM2_EncryptSecret
    gains a TPM_ALG_MLKEM case. ML-DSA intentionally omitted — signing
    keys have no encrypt operation (spec Table 222 has no mldsa arm).
  - tests/unit_tests.c: test_wolfTPM2_EncryptSecret now creates a real
    MLKEM-768 primary and asserts data.size == 32 and secret.size == 1088.
2026-04-29 10:27:50 -07:00
Aidan Garske c2b631ebf5 Align unit_tests.c output + MLKEM ct threading + drop dead MLDSA SignDigest
Widen printf format strings in tests/unit_tests.c so every Passed /
  Failed / Skipped line lands at the same column regardless of test
  name length. Pattern is inline: printf(Test TPM Wrapper: %-40s ...).
  No new header or helper; fwtpm_unit_tests.c is untouched and keeps its
  local fwtpm_pass column-alignment helper.

  Bug fixes carried alongside:
  - test_wolfTPM2_MLKEM_Encapsulate now writes ct to a caller buffer,
    test_wolfTPM2_PQC threads it into Decapsulate. Previously Decap was
    being called with an all-zero 2048-byte buffer which the server
    correctly rejected with TPM_RC_SIZE.
  - test_wolfTPM2_PQC now creates a real MLDSA-65 primary key via
    wolfTPM2_CreatePrimaryKey and a real MLKEM-768 primary before running
    the sequence / encap tests. Pure-MLDSA Sign uses one-shot at Complete
    (no SequenceUpdate) per Part 3 §17.5; Verify still uses Update per
    §20.3.
  - Removed test_wolfTPM2_MLDSA_SignDigest + test_wolfTPM2_MLDSA_Verify-
    DigestSignature: those always hit the skip path because Pure-MLDSA
    external-μ sign needs wolfCrypt's mu-direct API (static
    dilithium_sign_with_seed_mu, not WOLFSSL_API). Tracked as task #95.
    Hash-ML-DSA paths still cover SignDigest / VerifyDigestSignature
    wire format via the examples/pqc/pqc_mssim_e2e.c E2E test.
2026-04-29 10:27:50 -07:00
Aidan Garske 552032d357 fwTPM PQC: mssim E2E test + output formatting
Cross-process PQC validation: new examples/pqc/pqc_mssim_e2e exercises
  wolfTPM2_* client wrappers against a running fwtpm_server over the
  mssim (SWTPM) socket transport. Two round-trips in one binary:

  - MLKEM-768 Encap/Decap: asserts ciphertext = 1088 bytes and the two
    derived shared secrets are byte-identical.
  - HashMLDSA-65 SignDigest/Verify: asserts signature = 3309 bytes and
    the validation ticket carries TPM_ST_DIGEST_VERIFIED.

  tests/pqc_mssim_e2e.sh spawns fwtpm_server, waits for TCP readiness,
  runs the client, and cleans up. Proves client marshaling + mssim
  framing + fwtpm_server unmarshaling + PQC handler dispatch agree over
  a real socket between two separately-compiled processes — orthogonal
  to the in-process fwtpm_unit.test suite.

  Infrastructure:
  - configure.ac: new AM_CONDITIONAL BUILD_V185 so the example only
    builds when --enable-v185 is passed (matches the pattern of
    BUILD_SWTPM, BUILD_DEVTPM, etc.).
  - examples/include.am, examples/pqc/include.am: register the example.

  Output polish: replaced 85 inconsistent calls with a
  fwtpm_pass(name, is_pqc) helper that produces aligned
  columns. PQC tests are tagged [PQC] so they're visually distinct
  from the classical suite at a glance. All 86 existing tests still pass.
2026-04-29 10:27:50 -07:00
Aidan Garske f42c57f662 fwTPM PQC: boundary + scaling tests
Five new tests exercising corner conditions not previously covered:

   - SignSeq slot exhaustion: fills all FWTPM_MAX_SIGN_SEQ (4) slots,
     asserts the 5th start returns TPM_RC_OBJECT_MEMORY.
   - SignSeq long-message boundary: accumulates exactly
     FWTPM_MAX_DATA_BUF (1024) bytes across SequenceUpdate calls on a
     Pure-MLDSA verify sequence; one extra byte overflows with
     TPM_RC_MEMORY.
   - MLDSA-87 max-buffer round-trip: full Sign sequence at the largest
     parameter set, asserting the 4627-byte signature encodes cleanly
     through the response path. Pressures FWTPM_MAX_DER_SIG_BUF (4736)
     and FWTPM_MAX_COMMAND_SIZE (8192).
   - MLKEM-1024 max-buffer round-trip: CreatePrimary + Encapsulate at
     the largest KEM parameter set; asserts ct size = 1568 per Table 204.
   - Hash-ML-DSA sequence round-trip at MLDSA-44, MLDSA-65, MLDSA-87:
     SignSequenceStart -> chunked SequenceUpdate -> SignSequenceComplete,
     verifying the hash-accumulator path works for all three parameter
     sets and the signature response carries the correct alg/hash/size
     triple.

   Also adds BuildCreatePrimaryCmdParam helper so tests can vary the
   parameter set without duplicating the full template.
2026-04-29 10:27:17 -07:00
Aidan Garske 25b0157d62 fwTPM PQC: NV persistence round-trip test
An MLDSA-65 persistent key must survive a full FWTPM_Init / Cleanup
   cycle with only the NV backing file as handoff. The new test exercises
   FWTPM_NV_Save / Load end-to-end for a PQC object and verifies the
   FWTPM_NV_PUBAREA_EST (2720-byte) lift is wide enough for the serialized
   MLDSA public area. Compares outPublic bytes across the restart via
   XMEMCMP.

   Also strips plan-phase labels from in-source comments — those belong
   in commit messages, not code.
2026-04-29 10:27:17 -07:00
Aidan Garske 88991157b6 Phase 12 Task 2: PQC negative-RC tests (9 handlers)
One test per error emission in the PQC handler catalog, asserting
   the exact TPM_RC_* that each spec citation mandates:

   - Encapsulate:   TPM_RC_HANDLE, TPM_RC_KEY        (Part 3 §14.10)
   - Decapsulate:   TPM_RC_KEY, TPM_RC_SIZE          (Part 3 §14.11)
   - SignSeqStart:  TPM_RC_KEY, TPM_RC_HANDLE        (Part 3 §17.5)
   - VerifySeqStart: TPM_RC_VALUE (non-zero hint)    (Part 2 §11.3.9)
   - SignSeqComplete: TPM_RC_HANDLE                  (Part 3 §20.6)
   - VerifySeqComplete: TPM_RC_HANDLE                (Part 3 §20.3)
   - SignDigest:    TPM_RC_EXT_MU, TPM_RC_KEY        (Part 3 §20.7)
   - VerifyDigestSig: TPM_RC_SCHEME                  (Part 3 §20.4)
   - SequenceUpdate: TPM_RC_ONE_SHOT_SIGNATURE       (Part 3 §17.5)

   Two small helpers (fwtpm_neg_mk_mlkem_primary /
   fwtpm_neg_mk_mldsa_primary) set up valid objects so each negative
   test reaches exactly the guard being validated.
2026-04-29 10:27:17 -07:00
Aidan Garske 729ece69c9 Phase 12 Task 3: PQC capability reporting + spec RC fix
- Wire TPM_PT_ML_PARAMETER_SETS into FwCmd_GetCapability allProps[]
     reporting all 6 MLKEM/MLDSA parameter sets + extMu (bits 0-6).
   - Add TPM_ALG_MLKEM / TPM_ALG_MLDSA / TPM_ALG_HASH_MLDSA to algList[]
     so TPM_CAP_ALGS advertises PQC support.
   - test_fwtpm_getcap_pqc asserts both responses match spec Table 46.
   - Fix: change 7 TPM_RC_VALUE emissions to TPM_RC_PARMS in
     fwtpm_crypto.c for unsupported ML-KEM/ML-DSA parameter sets
     per Part 2 Tables 204/207.
2026-04-29 10:27:17 -07:00
Aidan Garske a2a902a6a2 Phase 12 Task 1: PQC primary-key determinism tests
tests/fwtpm_unit_tests.c:
   - test_fwtpm_mldsa_primary_determinism — CreatePrimary(MLDSA-65)
     twice with identical template; extract unique.mldsa bytes from each
     outPublic; assert byte-identical.
   - test_fwtpm_mlkem_primary_determinism — same pattern for MLKEM-768.

   Proves: same hierarchy seed + same template -> byte-identical PQC
   primary public key. This validates Phase 3 KDFa derivation + DEC-0001
   label choice (MLDSA / MLKEM) + wolfCrypt deterministic keygen
   compose correctly. Closes Gap 7 of the Phase 12 plan.

   12 PQC tests pass, 0 failures.
2026-04-29 10:27:17 -07:00
Aidan Garske a1b08dbd8f Phase 10: dual-source NIST ACVP + wolfSSL KAT testing
tests/pqc_kat_vectors.h (new, 802 LoC of hex arrays):
  - 4 NIST ACVP vectors (authoritative spec-truth):
    - ML-DSA-44 sigVer (pk + msg + ctx + sig, valid signature)
      from usnistgov/ACVP-Server ML-DSA-sigVer-FIPS204 tgId=1 tcId=6
    - ML-KEM-512 encap (ek + m -> expected (c, k))
      from usnistgov/ACVP-Server ML-KEM-encapDecap-FIPS203 tgId=1 tcId=1
  - 4 wolfSSL internal vectors (regression lock):
    - ML-DSA-44 keygen (seed -> pk) from tests/api/test_mldsa.c:3111
    - ML-KEM-512 keygen (seed -> ek) from tests/api/test_mlkem.c:48

  tests/fwtpm_unit_tests.c (+173 LoC):
  - test_fwtpm_mldsa_nist_kat_verify: wolfCrypt-layer verify against NIST
    pinned vector; proves wc_dilithium_verify_ctx_msg is FIPS 204 correct.
  - test_fwtpm_mldsa_wolfssl_keygen_kat: seed -> expected pk byte match.
  - test_fwtpm_mlkem_nist_kat_encap: EncapsulateWithRandom with pinned
    randomness produces NIST expected (c, k); proves FIPS 203 correct.
  - test_fwtpm_mlkem_wolfssl_keygen_kat: seed -> expected ek byte match.
  - test_fwtpm_mldsa_loadexternal_verify: loads NIST MLDSA-44 pub into
    fwTPM via TPM2_LoadExternal (public-only, hierarchy NULL), proves
    the handler accepts PQC pub areas end-to-end.

  All 10 PQC tests pass alongside existing suite. No fwTPM handler
  changes needed — Phase 2 marshaling and the existing LoadExternal
  inPrivSize==0 path handle PQC public-only load natively.
2026-04-29 10:26:00 -07:00
Aidan Garske ef31aa8f79 Phase 8a: add PQC end-to-end tests; fix FIPS 204 hedged-sign RNG
tests/fwtpm_unit_tests.c:
  - Extend BuildCreatePrimaryCmd to emit MLKEM-768, MLDSA-65, and
    Hash-MLDSA-65/SHA-256 TPMT_PUBLIC templates per Part 2 Table 232.
  - test_fwtpm_create_primary_mlkem: sanity-check MLKEM keygen path.
  - test_fwtpm_create_primary_mldsa: sanity-check MLDSA keygen path.
  - test_fwtpm_mlkem_roundtrip: CreatePrimary MLKEM-768 → Encapsulate →
    Decapsulate, asserts both shared secrets are 32 bytes and identical.
    Proves Phase 3 KDFa derivation + Phase 4 encap/decap crypto + wire
    format for TPM2B_SHARED_SECRET and TPM2B_KEM_CIPHERTEXT.
  - test_fwtpm_mldsa_digest_roundtrip: CreatePrimary Hash-MLDSA-65 →
    SignDigest → VerifyDigestSignature, asserts TPM_ST_DIGEST_VERIFIED
    ticket. Proves Phase 5 digest handlers and Bug M-4 metadata format.
  - test_fwtpm_mldsa_sequence_roundtrip: CreatePrimary Pure MLDSA-65 →
    SignSequenceStart → SignSequenceComplete → VerifySequenceStart →
    SequenceUpdate → VerifySequenceComplete, asserts TPM_ST_MESSAGE_
    VERIFIED. Proves Phase 5 sign path, Phase 5b one-shot semantics and
    message accumulator, and Bug M-1 Pure-MLDSA wire format.

  Wired into main(); all five tests pass on --enable-v185.

  src/fwtpm/fwtpm_crypto.c, wolftpm/fwtpm/fwtpm_crypto.h:
  - Fix: FwSignMldsaMessage and FwSignMldsaHash now take a WC_RNG*.
    wolfCrypt wc_dilithium_sign_ctx_msg / sign_ctx_hash require a
    non-NULL RNG to source the 32-byte  value for hedged signing
    (FIPS 204 Algorithm 2 step 7). The Phase 5 code passed NULL and
    returned BAD_FUNC_ARG at runtime. Both hedged and deterministic
    signing are FIPS 204 compliant; wolfCrypt's non-_with_seed API
    chose hedged, matching normal TPM side-channel practice.

  src/fwtpm/fwtpm_command.c:
  - Pass &ctx->rng to the two updated sign helpers from FwCmd_SignDigest
    and FwCmd_SignSequenceComplete.
2026-04-29 10:26:00 -07:00
Aidan Garske 62f336807c Phase 1: Add Fixture tests known posotives 2026-04-29 10:26:00 -07:00
aidan garske feaa06c3d3 Fix PQC code review issues for v185 support
- Add TPM2B_MLDSA_SIGNATURE type with proper 4627-byte buffer for ML-DSA-87
    signatures instead of reusing TPM2B_MAX_BUFFER (1024 bytes)

  - Add bounds checking and byte skipping for MLDSA/MLKEM public key parsing
    in TPM2_Packet_ParsePublic to prevent buffer overflow

  - Add bounds checking for ML-DSA signature parsing in
    TPM2_Packet_ParseSignature with proper wire size tracking

  - Add bounds checking to Encapsulate/Decapsulate response parsing
    (sharedSecret and ciphertext buffers)

  - Add negative size validation for contextSz, digestSz, dataSz parameters
    in wrapper functions: wolfTPM2_SignSequenceStart, wolfTPM2_SignSequenceComplete,
    wolfTPM2_VerifySequenceStart, wolfTPM2_VerifySequenceComplete,
    wolfTPM2_SignDigest, wolfTPM2_VerifyDigestSignature

  - Fix misleading MAX_SIGNATURE_CTX_SIZE comment - this is for domain
    separation context (255 bytes), not signature size

  - Change TPMT_PUBLIC size check from assertion to warning for embedded
    systems compatibility
2026-04-29 10:26:00 -07:00
aidan garske 487387d349 Add v185 rc4 tpm2.0 PQC MLDSA MLKEM Support 2026-04-29 10:26:00 -07:00
Aidan 2cc208906c F-3274 follow-up - tests/fwtpm_unit_tests: gate ECC sign helper for FWTPM_NO_NV builds too 2026-04-28 13:14:34 -07:00
Aidan 4817e79927 Skoll review fixes 2026-04-28 12:36:21 -07:00
Aidan f66ca1e189 F-3510 - https://fenrir.wolfssl.com/finding/3510 - wolftpm: TPM2_Packet_AppendSignature/ParseSignature explicitly handles TPM_ALG_NULL and warns on unrecognized sigAlg 2026-04-28 10:56:30 -07:00
Aidan 9beaf2f326 F-3501 - https://fenrir.wolfssl.com/finding/3501 - wolfTPM2_GetKeyTemplate_KeyedHash: scheme defaults to TPM_ALG_NULL when neither sign nor decrypt is requested 2026-04-28 10:53:43 -07:00
Aidan 2e00720eb4 F-3509 - https://fenrir.wolfssl.com/finding/3509 - wolftpm: TPM2_Packet_ParsePoint resyncs to outer point->size to prevent inner-size desync drift 2026-04-28 10:37:26 -07:00
Aidan 07bdb82195 F-3508 - https://fenrir.wolfssl.com/finding/3508 - wolftpm: TPM2_Packet_ParsePublic resyncs to outer pub->size to prevent inner-size desync drift 2026-04-28 10:33:52 -07:00
Aidan 3ec5485f19 F-3500 - https://fenrir.wolfssl.com/finding/3500 - wolfTPM2_NVCreateAuthPolicy: derive nameAlg from authPolicySz so SHA-384/SHA-512 policies are satisfiable 2026-04-28 10:28:42 -07:00
Aidan 68bf667c91 F-3499 - https://fenrir.wolfssl.com/finding/3499 - wolfTPM2_SignHashScheme/VerifyHashTicket: reject mismatched digest size for RSA, gate ECDSA
pad/truncate
2026-04-28 10:24:06 -07:00
Aidan ae4ebe764d F-3498 - https://fenrir.wolfssl.com/finding/3498 - wolfTPM2_RsaEncrypt/Decrypt return BUFFER_E for oversized input instead of silently truncating 2026-04-28 10:12:58 -07:00
Aidan b7d52b5810 F-3497 - https://fenrir.wolfssl.com/finding/3497 - wolfTPM2_LoadEccPublicKey_ex: caller-controlled scheme, hashAlg, and objectAttributes for ECDH peer keys 2026-04-28 10:10:31 -07:00
Aidan cae955fa21 F-3504 - https://fenrir.wolfssl.com/finding/3504 - wolftpm: map wolfCrypt Brainpool curves to TPM_ECC_BP_*_R1 (0x003X), not Barreto-Naehrig BN_P256 2026-04-28 09:58:36 -07:00
Aidan d04a78ee6c F-3502 - https://fenrir.wolfssl.com/finding/3502 - wolftpm: TPM2_Packet_ParseAttest decodes TPM_ST_ATTEST_NV_DIGEST as TPMS_NV_DIGEST_CERTIFY_INFO 2026-04-28 09:53:12 -07:00
Aidan 588455fd39 F-3274 - https://fenrir.wolfssl.com/finding/3274 - fwtpm: FwCmd_CertifyCreation consumes ECDAA count field per Part 2 Sec. 11.2.1.5 2026-04-28 09:42:41 -07:00
Aidan aa1957895d F-3273 - https://fenrir.wolfssl.com/finding/3273 - fwtpm: FwCmd_Sign consumes ECDAA count field per Part 2 §11.2.1.5 2026-04-28 09:34:06 -07:00
Aidan 1d7f46093e F-3272 - https://fenrir.wolfssl.com/finding/3272 - fwtpm: FwParseAttestParams consumes ECDAA count field per Part 2 §11.2.1.5 2026-04-28 09:29:10 -07:00
Aidan 3b0147d48a F-3496 - https://fenrir.wolfssl.com/finding/3496 - wolfTPM2_StartSession: enable parameter encryption attrs for salted sessions, not only bind+salt 2026-04-28 09:25:48 -07:00
Aidan f62070ac46 F-3503 - https://fenrir.wolfssl.com/finding/3503 - fwtpm: emit TPM_ST_ATTEST_NV_DIGEST when NV_Certify size and offset are both zero 2026-04-28 09:03:10 -07:00
David Garske f8d06b9589 PR review fixes 2026-04-22 10:09:56 -07:00
David Garske 0f87ce183b Build, portability, and CI fixes for v4.0.0
- configure.ac: switch wolfCrypt link probe to AC_LINK_IFELSE with real
  headers so CC=g++ builds don't fail on name-mangling; gate fwTPM/swTPM
  autodetect on ENABLED_WOLFCRYPT=yes (fwTPM requires wolfCrypt)
- wolftpm/fwtpm/fwtpm.h: hoist FWTPM_NV_HAL_S and FWTPM_CLOCK_HAL_S out
  of the FWTPM_CTX nested scope so C++ consumers can reference them
- src/fwtpm/fwtpm_command.c, fwtpm_crypto.c: add explicit TPMI_ALG_HASH
  and enum wc_HashType casts to silence strict C++ warnings; drop stale
  KEYEDHASH hashAlg initializer
- src/tpm2_wrap.c: move rc = TPM_RC_SUCCESS into the correct #else branch
  so Linux/winapi paths propagate TPM2_Startup errors
- examples/endorsement/get_ek_certs.c: drop redundant indexType default
- examples/endorsement/verify_ek_cert.c: initialize curveName on the
  WOLFTPM2_NO_WOLFCRYPT/no-ECC path
- examples/native/native_test.c: stop masking TPM2_ZGen_2Phase and
  TPM2_EC_Ephemeral 'command unavailable' as success
- tests/fwtpm_unit_tests.c: use cmdSz (not hardcoded 14) on FlushContext
- CI: add no-examples and st33ktpm2-i2c compile-only matrix entries to
  make-test-swtpm; add release-checks workflow (CC=g++ + scan-build)
2026-04-22 09:27:48 -07:00
David Garske 579ec8cc7f Bump copyright year to 2026 and version to 4.0.0
Release prep for v4.0.0:
- Copyright headers updated 2025 -> 2026 across sources, headers, and examples
- Library version 3.10.0 -> 4.0.0 (libtool 16:8:0 -> 17:0:0)
- configure.ac WOLFSSL_URL http -> https
2026-04-22 09:24:55 -07:00
Aidan c5145d88da F-3271 - https://fenrir.wolfssl.com/finding/3271 - Use TPM2_Packet_AppendSensitive in TPM2_LoadExternal and extend roundtrip test coverage 2026-04-21 14:08:40 -07:00
Aidan f684ab4a8c F-3251 - https://fenrir.wolfssl.com/finding/3251 - Use TPM2_Packet_ParseEccScheme in TPM2_ECC_Parameters to consume ECDAA count 2026-04-21 14:02:52 -07:00
Aidan Garske c8d51e9693
Merge pull request #486 from dgarske/ciports
Add network namespace isolation, macOS CI, and Windows build support for fwTPM
2026-04-21 09:22:57 -07:00
David Garske 19e648442b Add network namespace isolation, macOS CI, and Windows build support for fwTPM
Use unshare --user --net to isolate fwtpm_check.sh TCP ports in CI, eliminating flaky port conflicts on shared runners. Add macOS CI with socket transport tests. Add Windows socket portability (Winsock2) and build-only CI via CMake.
2026-04-21 09:06:44 -07:00
Aidan adc2713145 F-2533 - https://fenrir.wolfssl.com/finding/2533 - Add TPM2_Packet_ParseSensitive counterpart and roundtrip test 2026-04-20 11:38:07 -07:00
Aidan 31bcbb234f F-3005 - https://fenrir.wolfssl.com/finding/3005 - Handle ECSCHNORR and SM2 signature serialization 2026-04-20 11:38:07 -07:00
Aidan 286a44602c F-3004 - https://fenrir.wolfssl.com/finding/3004 - Add kdf field to TPMT_KEYEDHASH_SCHEME XOR serialization 2026-04-20 11:38:07 -07:00
Aidan b57d352c15 F-2962 - https://fenrir.wolfssl.com/finding/2962 - Add SM3_256 and SHA3 digest sizes to TPM2_GetHashDigestSize
F-2963 - https://fenrir.wolfssl.com/finding/2963
  F-2964 - https://fenrir.wolfssl.com/finding/2964
  F-2965 - https://fenrir.wolfssl.com/finding/2965
  F-3003 - https://fenrir.wolfssl.com/finding/3003
  F-3006 - https://fenrir.wolfssl.com/finding/3006
  F-3007 - https://fenrir.wolfssl.com/finding/3007
  F-3008 - https://fenrir.wolfssl.com/finding/3008
2026-04-20 11:38:07 -07:00
Aidan 4588c27203 F-3000 - https://fenrir.wolfssl.com/finding/3000 - Add unit test for wolfTPM2_UnloadHandle persistent handle guard 2026-04-20 11:38:07 -07:00
Aidan 1e65a8fece F-2999 - https://fenrir.wolfssl.com/finding/2999 - Add unit test for wolfTPM2_NVDeleteKey persistent handle range checks 2026-04-20 11:38:07 -07:00
Aidan d450a533ed F-2998 - https://fenrir.wolfssl.com/finding/2998 - Add unit test for wolfTPM2_NVStoreKey persistent handle range checks 2026-04-20 11:38:07 -07:00
Aidan b05c503d71 F-2967 - https://fenrir.wolfssl.com/finding/2967 - Clear ECC private key from stack on error paths in wolfTPM2_ImportEccPrivateKeySeed 2026-04-20 11:38:07 -07:00
Aidan 47aca58edf F-2950 - https://fenrir.wolfssl.com/finding/2950 - Save and restore session[0] in SpdmEnable, SpdmDisable, and SpdmNationsIdentityKeySet 2026-04-20 11:38:07 -07:00
Aidan bf3a39fb4a F-3001 - https://fenrir.wolfssl.com/finding/3001 - Reject NULL IV for non-ECB modes and oversized IV in wolfTPM2_EncryptDecryptBlock 2026-04-20 11:38:07 -07:00
Aidan Garske 0b2a1c31aa
Merge pull request #483 from dgarske/coverity_20260417
Coverity fixes for new fwtpm code
2026-04-17 12:56:16 -07:00
David Garske 34ae62ed09 Coverity fixes for new fwtpm code. 2026-04-17 12:17:36 -07:00
Aidan Garske 7ef21c0645 Address PR #481 review feedback
- Restore userWithAuth attribute in seal example (intentional for
     password-based unsealing)
   - Restore chained if (rc == TPM_RC_SUCCESS) pattern and the
     release-build authSz mismatch check in TPM2_CommandProcess
   - Restore TPM2_Packet_AppendSymmetric call in TPM2_Duplicate
   - Update ParamEncDec_Dispatch test to use fwtpm raw-pointer
     TPM2_ParamEnc_AESCFB signature
2026-04-17 11:02:58 -07:00
Aidan Garske 5c45cfb483 Fix skoll review 2026-04-17 10:02:57 -07:00
Aidan Garske 608e738f00 F-2984 - https://fenrir.wolfssl.com/finding/2984 - Add boundary validation tests for CreateKeySeal_ex and LoadKeyedHashKey 2026-04-17 09:58:38 -07:00
Aidan Garske 73c71217ca F-2978 - https://fenrir.wolfssl.com/finding/2978 - Add userWithAuth to KeySeal template default attributes 2026-04-17 09:58:38 -07:00
Aidan Garske 168296d558 F-2987 - https://fenrir.wolfssl.com/finding/2987 - Fix ECC ECDAA scheme serialization missing count field, RSA RSAES spurious hashAlg, and TPM2_Sign ECDAA count 2026-04-17 09:57:00 -07:00
Aidan Garske a34459d92c F-2985 - https://fenrir.wolfssl.com/finding/2985 - Add known-answer unit test for wolfTPM2_ComputeName 2026-04-17 09:57:00 -07:00
Aidan Garske cd63015325 F-2982 - https://fenrir.wolfssl.com/finding/2982 - Add known-answer unit test for TPM2_HashNvPublic 2026-04-17 09:48:59 -07:00
Aidan Garske 9cec95ffea F-2981 - https://fenrir.wolfssl.com/finding/2981 - Add dispatch-level roundtrip test for TPM2_ParamEnc/Dec_CmdRequest/Response 2026-04-17 09:48:59 -07:00
Aidan Garske 77faffc1b4 F-2977 - https://fenrir.wolfssl.com/finding/2977 - Fix DecodeRsaDer/DecodeEccDer default attributes for private key imports 2026-04-17 09:48:59 -07:00