feat(tee-verifier): stateless dcap_qvl::verify wrapper contract - #3237
Conversation
b3acde8 to
820497e
Compare
eb25314 to
7766451
Compare
820497e to
2e70aa9
Compare
7766451 to
43413b5
Compare
…-qvl Pure crate split, no behaviour change. Sets up the WASM-size win that the follow-up PR (mpc-contract Promise refactor) will land. What moves: - `app_compose`, `measurements`, `report_data`, `tcb_info` modules and their assets — none of these touched `dcap-qvl` to begin with. - The post-DCAP verification helpers (`verify_tcb_status`, `verify_report_data`, `verify_rtmr3`, `verify_app_compose`, `verify_any_measurements`, `verify_static_rtmrs`, `verify_key_provider_digest`, `verify_event_log_rtmr3`, `validate_app_compose_config`, `compare_hashes`, `compare_hex_hashes`, plus the `OrErr` and `GetSingleEvent` traits and `VerificationError`) — refactored from private methods on `DstackAttestation` to free functions in `attestation_types::verify_post_dcap`, taking the `tee_verifier_interface::VerifiedReport` mirror instead of the `dcap_qvl` type. What stays in `attestation`: - `DstackAttestation::verify` (the one and only `dcap_qvl::verify::verify` call site). It now converts the dcap-qvl-returned report to the Borsh mirror once and calls the free functions on it. - The `Collateral` newtype and `QuoteBytes` newtype. Their dedup with the `tee-verifier-interface` mirrors is deferred to a later PR. What this enables (next PR): - `mpc-contract` can depend on `attestation-types` alone (no `dcap-qvl`) and call the post-DCAP helpers from a Promise callback that receives the verifier-returned `VerifiedReport`. That is the actual WASM-size win for NEP-509. Drops the dead `TryFrom<dcap_qvl::verify::VerifiedReport> for Measurements` impl (no callers anywhere in the codebase). Re-exports the moved modules from `attestation::lib.rs` so existing consumers (`mpc-attestation`, `tee-authority`, `attestation-cli`, etc.) keep their import paths unchanged. Part of the verifier breakout from docs/design/attestation-verifier-contract.md (#3160). Stacked on #3237.
2e70aa9 to
dde7dd2
Compare
43413b5 to
5fae5d5
Compare
dcap_qvl::verify wrapper contract
d1e513b to
54fc11c
Compare
b731b70 to
c3f7c04
Compare
56f6430 to
d69203b
Compare
a288dbd to
b2ff62d
Compare
5edeb86 to
7f576f3
Compare
198b297 to
77b14bb
Compare
7f576f3 to
6d043fe
Compare
6d043fe to
cf72a5a
Compare
…n tests Matches the repo convention (and `conversions.rs` in this crate), so the attribute warns if the lint stops being triggered.
- Bump the NEP-330 reproducible-build image to 0.21.1-rust-1.93.0 to match
`rust-toolchain.toml` and `crates/contract` (was 0.17.0-rust-1.86.0).
- Convert the fixture timestamp with `u64::try_from(...).expect(...)` instead
of a silently-truncating `as u64` cast.
- Use `err.to_string()` instead of `format!("{err}")`.
barakeinav1
left a comment
There was a problem hiding this comment.
LGTM, aligned to the changes we agreed upon in #3235. verify_quote returning VerificationResult resolves the failure-distinguishability concern, conversions are field-for-field correct and pinned against dcap-qvl, and the negative-path tests are a good add. 👍
One nit inline.
The crate uses `borsh::` directly in the `conversions.rs` layout-pinning tests, so cargo-shear sees `borsh` as used — unlike the contract template this was copied from, which doesn't touch borsh. The ignore was redundant.
| fn make_collateral() -> Collateral { | ||
| // `test_utils::attestation::collateral()` returns a `serde_json::Value` | ||
| // matching `attestation::Collateral`'s JSON shape. We re-parse it | ||
| // into the interface crate's mirror type by extracting the same | ||
| // field names that `dcap_qvl::QuoteCollateralV3` uses. | ||
| let v = collateral_json(); | ||
| Collateral { | ||
| pck_crl_issuer_chain: v["pck_crl_issuer_chain"].as_str().unwrap().to_string(), | ||
| root_ca_crl: hex::decode(v["root_ca_crl"].as_str().unwrap()).unwrap(), | ||
| pck_crl: hex::decode(v["pck_crl"].as_str().unwrap()).unwrap(), | ||
| tcb_info_issuer_chain: v["tcb_info_issuer_chain"].as_str().unwrap().to_string(), | ||
| tcb_info: v["tcb_info"].as_str().unwrap().to_string(), | ||
| tcb_info_signature: hex::decode(v["tcb_info_signature"].as_str().unwrap()).unwrap(), | ||
| qe_identity_issuer_chain: v["qe_identity_issuer_chain"].as_str().unwrap().to_string(), | ||
| qe_identity: v["qe_identity"].as_str().unwrap().to_string(), | ||
| qe_identity_signature: hex::decode(v["qe_identity_signature"].as_str().unwrap()).unwrap(), | ||
| pck_certificate_chain: v | ||
| .get("pck_certificate_chain") | ||
| .and_then(|s| s.as_str()) | ||
| .map(str::to_string), | ||
| } | ||
| } |
There was a problem hiding this comment.
I am surprised we need such manual conversion here. I would expect we should have that conversion code somewhere already
There was a problem hiding this comment.
Yeah, looks like there are no existing conversions for this, but we can easily add one (see demo: #3521).
The issue is that we don’t want to add a dependency on MPC-specific crates to tee-verifier, since it’s supposed to stay MPC-agnostic and potentially be used by external teams too.
There was a problem hiding this comment.
yeah, maybe in a future refactor this will become easier, thank you for giving it a try
gilcu3
left a comment
There was a problem hiding this comment.
ups found a small blocker
…-contract Align the verifier contract's reproducible-build command with mpc-contract; it was missing the release-contract profile.
Closes #3266
Overview
Adds
tee-verifier: a stateless TEE attestation verifier contract.It wraps
dcap_qvl::verify::verifyin a singleverify_quotemethod. The contract holds no state and has no admin — verifier-internal policy (thedcap-qvlversion, Intel root certs, etc.) is bound to the deployed code hash. Per-team allowlists, report-data binding, and other post-DCAP checks live in the caller, not here.This moves the heavy
dcap-qvl/ring/webpki/x509-certclosure out of any contract that needs quote verification and into this one contract, reached over a cross-contract call using the DTOs from #3235.Builds on #3235 (PR #3235); part of the stack tracked by #3264. See
docs/design/attestation-verifier-contract.mdfor the design.