Skip to content

fix(verify): TPM qualifying_data check uses implemented key thumbprint#360

Merged
imran-siddique merged 1 commit into
mainfrom
fix/tpm-verifier-qualifying-data
Jun 26, 2026
Merged

fix(verify): TPM qualifying_data check uses implemented key thumbprint#360
imran-siddique merged 1 commit into
mainfrom
fix/tpm-verifier-qualifying-data

Conversation

@imran-siddique

Copy link
Copy Markdown
Contributor

Closes #359.

Problem

The TPM verifier checked qualifying_data == SHA-256(pubkey || session_id) — the old nonce formula — while the TPM provider commits the §3.3 nonce's first 32 bytes (JWK_thumbprint(tee_public_key)). The dispatcher also passed cnf.jwk.x (base64url) into a param fed to bytes.fromhex(), so the check always raised and qualifying_data was never actually verified.

Fix

  • verify_tpm_measurement: replace tee_public_key_hex / session_id with expected_qualifying_data: bytes.
  • verify.py dispatcher re-derives the thumbprint via _jwk_thumbprint_sha256(cnf.jwk.x) and passes it in; comparison is constant-time (hmac.compare_digest).
  • Matches the generic CRYPTO-001 key binding and the SEV-SNP/TDX verifiers.
  • claim-hw-attestation experiment updated to the new signature.
  • Spec: TPM quote commits nonce[:32] (the thumbprint).

Tests

  • Rewrote the qualifying_data unit tests to the new signature.
  • Added two end-to-end verify_trace_claim tests: a quote committing the key's real thumbprint verifies; a quote bound to a different key is rejected.

Verified locally: ruff + mypy clean, 756 unit tests pass (3 skipped).

Still needs real TPM hardware

EK cert-chain validation to the manufacturer CA remains stubbed (unverified_fields), unchanged here.

🤖 Generated with Claude Code

…print

The TPM verifier checked qualifying_data == SHA-256(pubkey || session_id), the old
nonce formula, while the TPM provider commits the §3.3 nonce's first 32 bytes
(the RFC 7638 JWK thumbprint of the key). It was also passed cnf.jwk.x (base64url)
into bytes.fromhex(), so the check always errored. Now the dispatcher re-derives the
thumbprint from cnf.jwk.x and the verifier compares it (constant-time) to the quote's
qualifying_data, matching the generic CRYPTO-001 key binding and the SEV-SNP/TDX paths.

- verify_tpm_measurement: replace tee_public_key_hex/session_id with
  expected_qualifying_data: bytes
- verify.py dispatcher computes expected_qd via _jwk_thumbprint_sha256(cnf.jwk.x)
- claim-hw-attestation experiment updated to the new signature
- tests: rewrite qualifying_data unit tests + add end-to-end verify_trace_claim
  tests for match and key-substitution rejection
- spec: TPM quote commits nonce[:32] (the thumbprint)

Verified: ruff + mypy clean, 756 unit tests pass (3 skipped).
@imran-siddique imran-siddique merged commit 39f0b37 into main Jun 26, 2026
12 checks passed
@imran-siddique imran-siddique deleted the fix/tpm-verifier-qualifying-data branch June 26, 2026 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TPM verifier qualifying_data uses old nonce formula (disagrees with provider)

1 participant