Skip to content

docs(spec): record the TPM decisions, refresh the tier table, seal before event log - #458

Merged
imran-siddique merged 1 commit into
mainfrom
docs/tpm-rfc-decisions
Aug 1, 2026
Merged

imran-siddique merged 1 commit into
mainfrom
docs/tpm-rfc-decisions

Conversation

@imran-siddique

Copy link
Copy Markdown
Member

Closes the open decisions on #439. Docs only, one file: docs/spec/tpm-security-model.md.

This replaces the earlier #454, which was auto-closed when its branch was deleted. Its content was also incomplete for reasons explained at the bottom.

1. Section 7's tier table was stale

Row three described cMCP's TPM tier as an "unsigned self-reported PCR digest". That stopped being true across #441 through #451: the quote is signed, the chain is verified where the host allows it, and the gateway is measured into a TPM_NT_EXTEND NV index.

The row now states what ships, plus the two caveats a one-line summary would bury:

2. Section 5 P2 records the binding decision

Because extends accumulate, one certified value cannot be checked against anything. Decided: certify twice, bracketing the extend.

V0 = NV_Certify(index)     <- TPM-signed
NV_Extend(gateway_digest)
V1 = NV_Certify(index)     <- TPM-signed

verifier: V1 == H(V0 || expected_gateway_digest)

Both values are TPM-signed, so nothing is collector-asserted, and the verifier holds no state. It deliberately does not attempt to prove the history behind V0, which would require remembering prior attestations.

The alternative that looks simpler and is not sound is recorded too: reading the index and committing the result into the quote's qualifying data means the collector asserts the value it read, and a compromised gateway is the adversary.

3. Sealing moves ahead of the event log

P3 and P4 swap. The event log is 0 bytes on both Azure and GCP, so replay cannot be validated on any cloud vTPM we can provision and it is gated on physical client hardware. Sealing the TRACE signing key is reachable today and is the step that converts measurement into enforcement, so it earns more trust per unit of effort. It still depends on P2 finishing, since the policy it seals against is the NV index.

The kept as P4 cross-reference in the P2 rationale is updated to kept as P3 to match.

4. Section 8 and the header: decisions taken

The header said "Draft, awaiting approval" and listed three required approvers; section 8 asked for their sign-off. Those decisions have been made, so the header reads Approved and section 8 records each with a pointer to where it lives. What remains genuinely open is in section 6 and is not ours to settle: client firmware TPM vendor root distribution, and whether Microsoft publishes the Global Virtual TPM CA - 03 chain in a citable location (#453).

Consistency with #455

#455 landed the matching STATUS.md TPM row while this was parked. Both now describe the same host-dependent chain story and the same Global Virtual TPM CA - 03 finding, so the two documents agree.

Why #454 was wrong, and what I did about it

A concurrent session was working in the same clone. It checked out its own branches, which switched the shared working tree mid-task, so several of my edits reported success and were then reverted before commit. 0921a76 and PR #454's body therefore described three changes that were not present in the diff: the P3/P4 reorder, the section 7 refresh, and the section 8 rewrite.

Every change in this PR has been verified present by grep against the committed file rather than trusted from an edit confirmation. The nine checks: header approved, row three updated, host-dependency paragraph, certify-twice decision, P3 sealing, P4 event log, reorder note, kept as P3, section 8 heading; plus two negative checks confirming Approvers required and kept as P4 are gone.

🤖 Generated with Claude Code

…921a76

The previous commit's message and PR #454 described three changes to this file
that were not actually in the committed content: the P3/P4 reorder, the section 7
tier-table refresh, and the section 8 rewrite. Each edit reported success and then
was not present on disk at commit time, so the commit recorded intent rather than
substance. Something else is writing this repo concurrently (STATUS.md changed
the same way).

Re-applied and verified present by grep before committing:
- header no longer says awaiting approval from three reviewers
- section 7 row three states what ships, with the host-dependency and
  unsigned-measurement caveats
- section 5 P2 records the certify-twice decision
- P3 is sealing, P4 is the event log, with the reorder rationale
- the 'kept as P3' cross-reference matches the new numbering
- section 8 is decisions taken, not approvals requested

Refs #432, #439, #453
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant