Skip to content

feat(attestation)!: pin verification to archived collateral with VerifyMode - #3

Open
samlaf wants to merge 1 commit into
sei-208/pr1-report-verified-collateralfrom
sei-208/pr2-verify-mode
Open

feat(attestation)!: pin verification to archived collateral with VerifyMode#3
samlaf wants to merge 1 commit into
sei-208/pr1-report-verified-collateralfrom
sei-208/pr2-verify-mode

Conversation

@samlaf

@samlaf samlaf commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Closes flashbots#84
Second of two changes for flashbots#84, stacked on flashbots#85.

Reporting the collateral a verification consumed is half of provenance. The other half is running the same verification again later, against that bundle, and getting the same answer. Nothing exposed that: the public entry points always fetched, and the only way to supply a bundle was through test-only variants that also took a bare timestamp.

Verification now takes a VerifyMode. Live fetches collateral and reads the wall clock. Archived carries the bundle and the instant it was collected, so the two can never be supplied apart - a pinned bundle evaluated at the wrong instant is the mistake the old (Option, now) pair permitted. Azure holds its AK certificate chain to the instant the DCAP leg reported, so both legs evaluate at one time in either mode.

The Azure TCB override leaves the public DCAP entry points. Only the Azure verifier has a reason to relax TCB checks, so it reaches the override through a crate-private variant; verify_dcap_attestation always verifies at full strictness. The mock verifier likewise becomes its own function rather than a cfg switch inside the production one, so verify_dcap_attestation means Intel-rooted in every build and the fixture tests replay real captures against it. AttestationVerifier is the one place that picks between them.

BREAKING CHANGE

verify_attestation and verify_attestation_sync take a VerifyMode; the DCAP and Azure entry points take mode before pccs and the DCAP ones drop override_azure_outdated_tcb; the *_with_given_timestamp variants are gone, replaced by VerifyMode::Archived.

GCP checks and Archived mode

The GCP host provenance check from flashbots#54 stays live in either mode, as does the firmware fetch for the quote's MRTD. Neither rests on signed material a replay could re-verify: the provenance document is an unsigned JSON object whose trust is the TLS connection to Google's bucket, so archiving it would not make a replay stronger. The docs on VerifyMode::Archived and verify_attestation state the carve-out. Whether Archived should skip the provenance lookup instead is left open.

@linear-code

linear-code Bot commented Aug 25, 2026

Copy link
Copy Markdown

SEI-208

…fyMode

Second of two changes for flashbots#84, stacked on
flashbots#85.

Reporting the collateral a verification consumed is half of provenance.
The other half is running the same verification again later, against
that bundle, and getting the same answer. Nothing exposed that: the
public entry points always fetched, and the only way to supply a bundle
was through test-only variants that also took a bare timestamp.

Verification now takes a VerifyMode. Live fetches collateral and reads
the wall clock. Archived carries the bundle and the instant it was
collected, so the two can never be supplied apart - a pinned bundle
evaluated at the wrong instant is the mistake the old
(Option<collateral>, now) pair permitted. Azure holds its AK certificate
chain to the instant the DCAP leg reported, so both legs evaluate at one
time in either mode.

The Azure TCB override leaves the public DCAP entry points. Only the
Azure verifier has a reason to relax TCB checks, so it reaches the
override through a crate-private variant; verify_dcap_attestation always
verifies at full strictness. The mock verifier likewise becomes its own
function rather than a cfg switch inside the production one, so
verify_dcap_attestation means Intel-rooted in every build and the
fixture tests replay real captures against it. AttestationVerifier is
the one place that picks between them.

BREAKING CHANGE: verify_attestation and verify_attestation_sync take a
VerifyMode; the DCAP and Azure entry points take mode before pccs and
the DCAP ones drop override_azure_outdated_tcb; the
*_with_given_timestamp variants are gone, replaced by
VerifyMode::Archived.

GCP checks and Archived mode
----------------------------

The GCP host provenance check from flashbots#54 stays live
in either mode, as does the firmware fetch for the quote's MRTD. Neither
rests on signed material a replay could re-verify: the provenance
document is an unsigned JSON object whose trust is the TLS connection to
Google's bucket, so archiving it would not make a replay stronger. The
docs on VerifyMode::Archived and verify_attestation state the carve-out.
Whether Archived should skip the provenance lookup instead is left open.

Closes flashbots#84
@samlaf
samlaf force-pushed the sei-208/pr2-verify-mode branch from f3b9a66 to 3fc3640 Compare August 25, 2026 20:52
samlaf added a commit to SeismicSystems/enclave that referenced this pull request Aug 26, 2026
…gainst (#268)

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.
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