Attestation: certificate validity and revocation checks differ per platform, and SEV-SNP has none
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Cần làm rõ
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- aws, gcp, rust
- Lĩnh vực
- cryptography, security
Hướng nghiên cứu
Bắt đầu bằng cách so sánh các entry point của verifier trong sev-snp-qvl/src/lib.rs, nsm-qvl/src/verify.rs, tpm-qvl/src/verify.rs và dstack-attest/src/attestation.rs, bao gồm cả test nitro_verify. Trước tiên, hãy xác định policy dự kiến cho từng nền tảng và hành vi của clock; được xem là hoàn thành khi policy đã được quyết định và ghi lại, các khoảng trống validation được chọn đã được xử lý nhất quán, và hành vi khi hết hạn hoặc bị thu hồi được bao phủ bởi các test xác định.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
Temporal validation of attestation collateral differs by platform, and one platform has none at all. An expired VCEK verifies on AMD SEV-SNP exactly as a fresh one does; a revoked AWS Nitro certificate is never checked against a CRL because the production call site disables collateral; GCP TPM checks revocation only if a CRL happened to download. Only Intel TDX is complete.
None of this is written down anywhere, so a reader of one platform's path reasonably assumes the others behave the same way.
What each platform actually does
| Platform | Cert notBefore/notAfter |
Collateral expiry | Clock injectable | CRL |
|---|---|---|---|---|
| Intel TDX / GCP TDX | yes | yes (TCBInfo + QEIdentity nextUpdate) |
yes (now_secs) |
yes, ExpirationPolicy::Enforce, UnknownStatusPolicy::Deny |
| GCP TPM | yes | only when a CRL was downloaded | no | fail-open if the list is empty |
| AWS Nitro Enclave | yes (+1h doc freshness) | guard exists, unreachable in prod | yes | disabled at call site |
| AWS NitroTPM | yes (+1h doc freshness) | guard exists, unreachable in prod | yes | disabled at call site |
| AMD SEV-SNP | no | no | no | no |
Detail
AMD SEV-SNP — no temporal validation anywhere. Both chain branches in sev-snp-qvl/src/lib.rs:540-553 are signature-only:
- external-root branch,
verify_x509_chain(lib.rs:572-595): checksis_ca(), issuer/subject linkage, three signatures. NoValidityaccess exists in the file. - default branch:
sev6.0.0'sVerifiableimpls bottom out atX509::verify(&key)(sev-6.0.0/src/certs/snp/cert.rs:81-100), which is a signature check.
QuoteVerifier::verify (lib.rs:118-133) takes no clock argument, so a caller cannot supply one either. AMD's /vcek/v1/{product}/crl is never fetched. Observed on real collateral: a VCEK is issued with a 7-year window (ASK/ARK run to 2045), so nothing expires soon — but nothing would be noticed if it did, and revocation is permanently invisible.
AWS Nitro Enclave and NitroTPM — revocation disabled by the caller, not by the library. nsm-qvl bails when a certificate has CRL distribution points but no CRL was supplied (nsm-qvl/src/verify.rs:196-202). That guard sits after the let Some(collateral) = collateral else { ... return Ok(()) } early return at verify.rs:184-195, and dstack passes None:
// dstack-attest/src/attestation.rs:2461
// CRL fetch is unreliable (e.g. 403 from S3), so keep it disabled here by default.
let verified_report = verifier
.aws_nitro_enclave
.verify(&nsm_quote.nsm_quote, None, now)
Same for NitroTPM at attestation.rs:1830-1832. The reason given is real — AWS's S3 CRL endpoint returns 403 — but the result is that a fail-closed guard reads as active while never running.
GCP TPM — fail-open on an empty CRL set. tpm-qvl/src/verify.rs:609 gates all revocation checking on if !collateral.crls.is_empty(), and the else branch verifies with None revocation options. Unlike nsm-qvl there is no bail when a chain advertises CRL distribution points but none were downloaded: collateral.rs:94-105 continues past certs without a CRL DP, and download_first_available_crl only fails when every URL for a cert fails. Certificate dates are checked (verify.rs:591-594, 640-667).
The now parameter is mostly decorative. AttestationV1::verify_with_time / DstackQuote::verify_with_time accept a now, but it reaches only nsm-qvl. TDX hardcodes SystemTime::now() inside verify_tdx_quote (attestation.rs:181-188); GCP TPM and SEV-SNP have no hook at all. Every production path passes None; the only non-None caller is dstack-attest/tests/nitro_verify.rs:47. Verifying a quote as-of a past instant is therefore impossible for three of five platforms, which also makes deterministic tests of expiry behaviour impossible to write.
Operator-supplied root CAs are not date-validated either. validate_x509_certificate (attestation.rs:205-222) parses the DER, rejects trailing bytes, and asserts is_ca(). Nothing looks at the validity window.
Why it is worth fixing
Individually each of these is arguably defensible — SNP's rollback protection comes from the TCB fields in the report rather than from certificate expiry, and AWS's CRL endpoint really is unreliable. Collectively they mean the answer to "does dstack reject stale or revoked attestation collateral?" is "depends which platform, and not in a way the code makes visible."
The gap also compounds with caching. Pointing [core.attestation.urls] amd_kds at a caching mirror is a reasonable way to survive a KDS outage, but because nothing checks dates or revocation on that path, an arbitrarily old cached VCEK is indistinguishable from a fresh one.
Suggested direction
Not a fix proposal, just what seems worth deciding:
- Decide and document the intended policy per platform, including where fail-open is deliberate. Today the intent is only inferable from what the code omits.
- Thread one clock through every verifier.
nowalready exists in the public API; making it reach all five platforms costs little and makes expiry testable. - Add certificate validity checks to
sev-snp-qvl, or record explicitly why the report's TCB fields make them redundant. - Re-examine the Nitro CRL call site. If S3 403s make CRLs impractical, a comment at the call site is weaker than a typed "revocation not checked" signal that surfaces in
VerifiedReport. - Consider surfacing what was checked in the verification result, so a caller can tell a fully-validated chain from a signature-only one.
Found while testing 0.6.0-rc0 on real TDX and SEV-SNP hardware. Happy to take any of these if there is a preferred direction.
- Ngôn ngữ chính
- Rust
- Star
- 551
- Fork
- 97
- Merge trung bình
- 1 ngày 8 giờ
- Pull request đã merge (30 ngày)
- 182
Chuẩn bị môi trường
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của Dstack-TEE/dstack
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
Dstack-TEE/dstack#1384 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 30/100
Dstack-TEE/dstack#1301 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 55/100
Dstack-TEE/dstack#1300 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
Dstack-TEE/dstack#1299 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
Dstack-TEE/dstack#1298 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của Dstack-TEE/dstack
Issue tương tự
-
area:casework bug criticality:p3 triage:needs-implementation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
registrystack/registry-stack#1623 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
leptos-rs/leptos#4885 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
longbridge/gpui-kit#3276 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
A-Migration Guides D-Straightforward S-Ready-For-Implementation X-Uncontroversial
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
bevyengine/bevy-website#2607 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày