Skip to content

feat(verify-quote)!: archive the DCAP collateral a harvest verified against - #268

Merged
samlaf merged 1 commit into
seismicfrom
sei-208-feat-archive-dcap-collateral-with-each-harvested-founding
Aug 26, 2026
Merged

feat(verify-quote)!: archive the DCAP collateral a harvest verified against#268
samlaf merged 1 commit into
seismicfrom
sei-208-feat-archive-dcap-collateral-with-each-harvested-founding

Conversation

@samlaf

@samlaf samlaf commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

A founding harvest record verifies only for as long as the collateral its verification consumed is still what Intel serves. TCB Info, QE Identity and both CRLs carry nextUpdate on a roughly 30-day cadence, so a month after the founding the archived quote stops verifying against live collateral, and founding TEE-ness becomes something the operator vouches for rather than something a reader can check.

The verifier is the only component that knows which bundle it used, so it is the one that hands it over. seismic-attestation follows the attested-tls fork onto SeismicSystems/attested-tls#3 and #4: verify_evidence_with_policy returns VerifiedEvidence, the verdict plus the CollateralSnapshot (bundle and the instant every freshness check was held to), and VerifyOptions::mode chooses between a live fetch at the wall clock and an archived snapshot at its own instant.

verify-quote harvest grows the two ends of the archive:

  • --dump-collateral PATH writes the snapshot the verification consumed, once the quote has verified and never before, so a burned harvest leaves nothing a later reader mistakes for provenance. The document is a versioned JSON envelope in the archive's own serialization: the instant, the record's harvest_nonce, and the bundle with Intel's signed bodies and PEM chains as-is and the DER components base64. Parsing is strict and probes the version first. The rendered bytes are parsed back before they leave the process.
  • --collateral PATH verifies the record against that snapshot, at that instant, reaching no collateral service; it excludes --dump-collateral and --pccs-url. The snapshot names its record by nonce, so one filed beside another box's record is refused rather than replayed at the wrong instant against the wrong bundle.

deploy is unchanged in behaviour: a live challenge is judged against live collateral and archives nothing.

BREAKING: verify_evidence_with_policy returns VerifiedEvidence; VerifyOptions gains mode and no longer derives Default mechanically.

…gainst

A founding harvest record verifies only for as long as the collateral
its verification consumed is still what Intel serves. TCB Info, QE
Identity and both CRLs carry nextUpdate on a roughly 30-day cadence, so
a month after the founding the archived quote stops verifying against
live collateral, and founding TEE-ness becomes something the operator
vouches for rather than something a reader can check.

The verifier is the only component that knows which bundle it used, so
it is the one that hands it over. `seismic-attestation` follows the
attested-tls fork onto SeismicSystems/attested-tls#3 and #4:
`verify_evidence_with_policy` returns `VerifiedEvidence`, the verdict
plus the `CollateralSnapshot` (bundle and the instant every freshness
check was held to), and `VerifyOptions::mode` chooses between a live
fetch at the wall clock and an archived snapshot at its own instant.

`verify-quote harvest` grows the two ends of the archive:

- `--dump-collateral PATH` writes the snapshot the verification
  consumed, once the quote has verified and never before, so a burned
  harvest leaves nothing a later reader mistakes for provenance. The
  document is a versioned JSON envelope in the archive's own
  serialization: the instant, the record's `harvest_nonce`, and the
  bundle with Intel's signed bodies and PEM chains as-is and the DER
  components base64. Parsing is strict and probes the version first.
  The rendered bytes are parsed back before they leave the process.
- `--collateral PATH` verifies the record against that snapshot, at
  that instant, reaching no collateral service; it excludes
  `--dump-collateral` and `--pccs-url`. The snapshot names its record
  by nonce, so one filed beside another box's record is refused rather
  than replayed at the wrong instant against the wrong bundle.

`deploy` is unchanged in behaviour: a live challenge is judged against
live collateral and archives nothing.

BREAKING: `verify_evidence_with_policy` returns `VerifiedEvidence`;
`VerifyOptions` gains `mode` and no longer derives `Default`
mechanically.
@samlaf
samlaf requested a review from cdrappi as a code owner August 26, 2026 19:40
@linear-code

linear-code Bot commented Aug 26, 2026

Copy link
Copy Markdown

SEI-208

@samlaf
samlaf merged commit f596766 into seismic Aug 26, 2026
5 checks passed
@samlaf
samlaf deleted the sei-208-feat-archive-dcap-collateral-with-each-harvested-founding branch August 26, 2026 19:45
samlaf added a commit that referenced this pull request Aug 27, 2026
…270)

Every offline test here has run on fabricated collateral, which
exercises the plumbing but has never held the archive to a bundle Intel
actually served. The property the archive exists for — a founding quote
that still verifies once its collateral has aged out — has therefore
been argued rather than demonstrated.

Commit one real founding and re-verify it in `cargo test`. The fixtures
are node 1 of a two-box Azure TDX cohort (`tmp-devnet-1`, image
seismic-dev_2026-08-27.5c012e.vhd), harvested 2026-08-27T20:20:55Z and
torn down the same day: the harvest record, the collateral snapshot its
verification consumed, and the promoted policy it was verified against.
Those three files are a complete offline input, and nothing regenerates
them — the cohort's keys existed only in its boxes' RAM. The pubkeys are
a destroyed throwaway network's, so the archive discloses nothing.

Two tests, and the pair is the point:

- the founding verifies against its own snapshot, at the instant that
snapshot pins, reaching no collateral service;
- the same record and the same bundle stop verifying once that instant
moves past the bundle's nextUpdate.

Without the second, a verification that quietly fell back to the wall
clock would leave the first passing while proving nothing. For the same
reason the first asserts that every register the policy pins comes back
with the value it demanded: a policy whose measurements map were empty
accepts any quote, and the comparison loop iterates the policy's keys.

Neither test needs a network, TDX hardware, or the wall clock — an
archived verification takes its instant from the envelope — so both run
in ordinary CI on any platform.

The bundle's nextUpdate is 2026-09-26T19:23:26Z. From then on a live
verification of this record fails while the archived path keeps passing,
which is the property itself, directly observable.

Last phase of SEI-208. The capture and replay ends of the archive are
already merged, here in #268 and in
SeismicSystems/deploy#110.
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