Skip to main content

dcap_qvl/
lib.rs

1//! # dcap-qvl
2//!
3//! Verify Intel SGX and TDX (DCAP — Data Center Attestation Primitives)
4//! attestation quotes, in pure Rust. Supports both SGX (Software Guard
5//! Extensions) and TDX (Trust Domain Extensions).
6//!
7//! # What it does
8//! - Verify SGX and TDX quotes against Intel's trust chain
9//! - Fetch collateral from a PCCS or Intel PCS, or verify fully offline
10//! - Extract report fields (measurements, report data, TCB status) from a quote
11//!
12//! By default the collateral client uses Phala Network's PCCS
13//! (`https://pccs.phala.network`).
14//!
15//! Native bindings for Python, JavaScript, Go, Kotlin, and Swift are published
16//! from the same core — see the [project README][readme].
17//!
18//! [readme]: https://github.com/Phala-Network/dcap-qvl
19//!
20//! # Example
21//!
22//! ```no_run
23//! use dcap_qvl::collateral::CollateralClient;
24//! use dcap_qvl::verify::verify;
25//! use dcap_qvl::PHALA_PCCS_URL;
26//!
27//! #[tokio::main]
28//! async fn main() {
29//!     let quote = std::fs::read("quote").expect("quote file not found");
30//!
31//!     // Use default Phala PCCS, or override with custom URL
32//!     let pccs_url = std::env::var("PCCS_URL").unwrap_or_else(|_| PHALA_PCCS_URL.to_string());
33//!     let collateral = CollateralClient::with_default_http(pccs_url)
34//!         .expect("failed to build HTTP client")
35//!         .fetch(&quote)
36//!         .await
37//!         .expect("failed to get collateral");
38//!
39//!     let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs();
40//!     let report = verify(&quote, &collateral, now).expect("failed to verify quote");
41//!     println!("{report:?}");
42//! }
43//! ```
44//!
45//! # Crypto backends
46//!
47//! Two backends are available: **ring** (optimized, uses assembly) and
48//! **rustcrypto** (pure Rust). Both are enabled by default and `ring` takes
49//! priority. For predictable behavior, call an explicit backend module:
50//!
51//! ```ignore
52//! use dcap_qvl::verify::ring::verify;        // always ring
53//! use dcap_qvl::verify::rustcrypto::verify;  // always rustcrypto
54//! ```
55//!
56//! The top-level [`verify::verify`] selects the backend from enabled features:
57//! `ring` wins when both are on, `rustcrypto` is used when only it is enabled,
58//! and enabling neither is a compile error. Because Cargo features are additive,
59//! any crate in your dependency tree that enables `ring` makes the top-level
60//! `verify()` use ring — reach for the explicit modules to avoid surprises.
61//!
62//! # Feature flags
63//!
64//! ```toml
65//! # Default: both backends, std, the PCCS collateral client, and x509 parsing.
66//! dcap-qvl = "0.5"
67//!
68//! # Minimal verifier for WASM / on-chain (smaller, ring only, no_std-friendly):
69//! dcap-qvl = { version = "0.5", default-features = false, features = ["std", "ring"] }
70//! ```
71//!
72//! `no_std` builds are supported by disabling default features. The `report`
73//! feature pulls in the async PCCS collateral client (`reqwest` + `tokio`); drop
74//! it for offline verification on size-constrained targets.
75
76#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
77
78#[macro_use]
79extern crate alloc;
80
81use scale::{Decode, Encode};
82use serde::{Deserialize, Serialize};
83
84#[cfg(feature = "borsh_schema")]
85use borsh::BorshSchema;
86#[cfg(feature = "borsh")]
87use borsh::{BorshDeserialize, BorshSerialize};
88
89#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
90#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
91#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
92pub struct QuoteCollateralV3 {
93    pub pck_crl_issuer_chain: String,
94    #[serde(with = "serde_bytes")]
95    pub root_ca_crl: Vec<u8>,
96    #[serde(with = "serde_bytes")]
97    pub pck_crl: Vec<u8>,
98    pub tcb_info_issuer_chain: String,
99    pub tcb_info: String,
100    #[serde(with = "serde_bytes")]
101    pub tcb_info_signature: Vec<u8>,
102    pub qe_identity_issuer_chain: String,
103    pub qe_identity: String,
104    #[serde(with = "serde_bytes")]
105    pub qe_identity_signature: Vec<u8>,
106    /// PCK certificate chain (PEM format).
107    /// For cert_type 5: extracted from quote during collateral fetch.
108    /// For cert_type 3: fetched from PCCS using encrypted PPID.
109    /// Used by verify() for offline verification.
110    #[serde(default, skip_serializing_if = "Option::is_none")]
111    pub pck_certificate_chain: Option<String>,
112}
113
114impl From<&QuoteCollateralV3> for QuoteCollateralV3 {
115    fn from(value: &QuoteCollateralV3) -> Self {
116        value.clone()
117    }
118}
119
120#[cfg(feature = "report")]
121pub mod collateral;
122
123#[cfg(feature = "report")]
124pub use collateral::PHALA_PCCS_URL;
125
126#[cfg(feature = "report")]
127pub mod http;
128
129pub mod config;
130#[cfg(feature = "default-x509")]
131pub mod configs;
132pub mod crypto;
133pub mod oids;
134#[cfg(feature = "default-x509")]
135pub mod signature;
136#[cfg(feature = "default-x509")]
137pub mod x509;
138
139mod constants;
140pub mod intel;
141pub mod policy;
142pub mod qe_identity;
143pub mod tcb_info;
144mod utils;
145
146pub use constants::{CpuSvn, Fmspc, MrEnclave, MrSigner, Svn, INTEL_QE_VENDOR_ID};
147pub use policy::{
148    PckCertFlag, PckIdentity, PlatformInfo, Policy, QeInfo, QuoteClaims, QuotePolicy,
149    QuotePolicyConfig, TcbVerdict,
150};
151pub use qe_identity::{QeIdentity, QeTcb, QeTcbLevel};
152pub use tcb_info::{Tcb, TcbComponents, TcbInfo, TcbLevel, TcbStatus, TcbStatusWithAdvisory};
153
154pub mod quote;
155pub mod verify;
156
157#[cfg(feature = "python")]
158pub mod python;
159
160#[cfg(feature = "go")]
161mod ffi;
162
163#[cfg(feature = "python")]
164use pyo3::prelude::*;
165
166#[cfg(feature = "python")]
167#[pymodule]
168fn _dcap_qvl(m: &Bound<'_, PyModule>) -> PyResult<()> {
169    python::register_module(m)
170}