refactor(attestation)!: verify only attested evidence - #266
Merged
samlaf merged 1 commit intoAug 26, 2026
Merged
Conversation
Fixes SEI-396. The verifier returns Ok(None) for evidence that declares attestation_type: none when its policy names no attested platform. seismic-attestation passed that through as a reachable success: VerifiedSeismicAttestation::NoAttestation, verified measurements that measure nothing. Every Seismic relying party appraises a TEE node, so that outcome is never wanted, and modelling it cost an Option in the crate's own signatures. It was reachable only through verify_evidence_with_predicate, which builds its policy from the peer's own claimed type: a peer claiming `none` got a policy for `none`, and the verifier accepted. Both admission predicates happened to reject the variant, but nothing enforced it — a future predicate written to appraise measurements would have admitted an unattested peer, since NoAttestation carries none to fail on. verify_with_backend_policy now refuses a None result with AttestationError::Unattested before any predicate runs. That makes the rest unreachable, so it goes: the NoAttestation variant, the Option on from_backend, and AttestationError::MissingMeasurements. A test drives `none` evidence through the predicate path with an admit-everything predicate and asserts the refusal. The `none`-claiming joiner's refusal moves from the admission layer to the verification layer; its wire error stays RootKeyRefusal::RequesterEvidenceUnusable, now by an explicit Unattested arm in rpc_error pinned by test rather than by placement. The admission tests that used NoAttestation as their non-Azure case use DcapTdx, a type a predicate can actually receive. verify_evidence_with_policy also absorbs its _and_options twin and takes VerifyOptions directly. Running without TDX hardware stays the verifier's `mock` feature, which produces real DcapTdx evidence against a mock root.
samlaf
deleted the
sl/sei-396-refactorattestation-verify-only-attested-evidence
branch
August 26, 2026 17:00
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes SEI-396.
The verifier returns Ok(None) for evidence that declares attestation_type: none when its policy names no attested platform. seismic-attestation passed that through as a reachable success: VerifiedSeismicAttestation::NoAttestation, verified measurements that measure nothing. Every Seismic relying party appraises a TEE node, so that outcome is never wanted, and modelling it cost an Option in the crate's own signatures.
It was reachable only through verify_evidence_with_predicate, which builds its policy from the peer's own claimed type: a peer claiming
nonegot a policy fornone, and the verifier accepted. Both admission predicates happened to reject the variant, but nothing enforced it — a future predicate written to appraise measurements would have admitted an unattested peer, since NoAttestation carries none to fail on.verify_with_backend_policy now refuses a None result with AttestationError::Unattested before any predicate runs. That makes the rest unreachable, so it goes: the NoAttestation variant, the Option on from_backend, and AttestationError::MissingMeasurements. A test drives
noneevidence through the predicate path with an admit-everything predicate and asserts the refusal.The
none-claiming joiner's refusal moves from the admission layer to the verification layer; its wire error staysRootKeyRefusal::RequesterEvidenceUnusable, now by an explicit Unattested arm in rpc_error pinned by test rather than by placement. The admission tests that used NoAttestation as their non-Azure case use DcapTdx, a type a predicate can actually receive.
verify_evidence_with_policy also absorbs its _and_options twin and takes VerifyOptions directly. Running without TDX hardware stays the verifier's
mockfeature, which produces real DcapTdx evidence against a mock root.