1- //! Pure-Rust TDX quote verification backend. Selected by the `tdx-dcap-rust`
2- //! feature.
1+ //! TDX quote verification backend that needs no external DCAP shared library.
2+ //! Selected by the `tdx-dcap-rust` feature.
33//!
44//! This backend removes the dependency on the Intel DCAP shared library
55//! (`libsgx_dcap_quoteverify`) and its dynamically loaded quote provider. The
66//! ECDSA quote signature, PCK certificate chain, TCB info and QE identity are
7- //! all verified in Rust via the [`dcap_qvl`] crate; verification collateral is
8- //! fetched over HTTPS from a PCCS using the verifier's own `reqwest` stack (we
7+ //! all verified via the [`dcap_qvl`] crate; verification collateral is fetched
8+ //! over HTTPS from a PCCS using the verifier's own `reqwest` stack (we
99//! deliberately do *not* enable `dcap-qvl`'s `report` feature, which would pull
1010//! in `reqwest` 0.13 / `aws-lc-sys`).
1111//!
12- //! Toolchain: `dcap-qvl`'s dependency tree requires a newer Rust toolchain
13- //! (>= 1.86) than the default (FFI) build. This does not affect the default
14- //! build: the `tdx-dcap-rust` feature is opt-in, and with it disabled Cargo
15- //! prunes this whole subtree.
12+ //! Crypto backend: `dcap-qvl` is used with its `ring` crypto backend. `ring`
13+ //! statically links its own crypto (no external shared library), and — unlike
14+ //! the RustCrypto stack — builds on Rust 1.76, so this backend has the same
15+ //! toolchain requirement as the default (FFI) build. With the feature disabled,
16+ //! Cargo prunes this whole subtree, so it has no effect on the default build.
17+ //!
18+ //! PCCS configuration: the collateral endpoint is resolved from, in order, the
19+ //! `PCCS_URL` environment variable, the `pccs_url` / `PCCS_URL` entry in
20+ //! `/etc/sgx_default_qcnl.conf` (the same file the DCAP quote provider reads, so
21+ //! both backends share one configuration), and finally a built-in default.
1622//!
1723//! Scope: the collateral fetch currently supports quotes whose certification
1824//! data embeds the PCK certificate chain (PCK cert type 5), which is what cloud
@@ -36,11 +42,14 @@ use x509_parser::prelude::*;
3642
3743use crate :: tdx:: quote:: { parse_tdx_quote, TcbVerificationResult } ;
3844
39- /// Default PCCS base URL. Matches the Alibaba Cloud PCCS the FFI backend's
40- /// quote provider is normally configured against (`/etc/sgx_default_qcnl.conf`).
41- /// Overridable at run time with the `PCCS_URL` environment variable.
45+ /// Default PCCS base URL, used only when neither `PCCS_URL` nor the QCNL config
46+ /// file provide one.
4247const DEFAULT_PCCS_URL : & str = "https://sgx-dcap-server.cn-beijing.aliyuncs.com" ;
4348
49+ /// QCNL config file read by the DCAP quote provider (FFI backend). We fall back
50+ /// to its `pccs_url` so both backends can share one PCCS configuration.
51+ const QCNL_CONF_PATH : & str = "/etc/sgx_default_qcnl.conf" ;
52+
4453/// TEE type for TDX, matching the value the FFI backend reports in
4554/// `TcbVerificationResult::tee_type`.
4655const TEE_TYPE_TDX : u32 = 0x0000_0081 ;
@@ -51,11 +60,56 @@ const OID_SGX_TCB: &[u64] = &[1, 2, 840, 113741, 1, 13, 1, 2];
5160const OID_SGX_PCESVN : & [ u64 ] = & [ 1 , 2 , 840 , 113741 , 1 , 13 , 1 , 2 , 17 ] ;
5261const OID_SGX_FMSPC : & [ u64 ] = & [ 1 , 2 , 840 , 113741 , 1 , 13 , 1 , 4 ] ;
5362
54- pub async fn ecdsa_quote_verification ( quote : & [ u8 ] ) -> Result < TcbVerificationResult > {
55- let pccs_url = std:: env:: var ( "PCCS_URL" )
63+ /// Resolve the PCCS base URL: `PCCS_URL` env var, then the QCNL config file,
64+ /// then the built-in default.
65+ fn resolve_pccs_url ( ) -> String {
66+ if let Ok ( v) = std:: env:: var ( "PCCS_URL" ) {
67+ if !v. is_empty ( ) {
68+ return v;
69+ }
70+ }
71+ if let Some ( v) = std:: fs:: read_to_string ( QCNL_CONF_PATH )
5672 . ok ( )
57- . filter ( |s| !s. is_empty ( ) )
58- . unwrap_or_else ( || DEFAULT_PCCS_URL . to_string ( ) ) ;
73+ . and_then ( |c| parse_qcnl_pccs_url ( & c) )
74+ {
75+ debug ! ( "dcap-qvl backend: using PCCS URL from {QCNL_CONF_PATH}" ) ;
76+ return v;
77+ }
78+ DEFAULT_PCCS_URL . to_string ( )
79+ }
80+
81+ /// Extract the PCCS URL from QCNL config file contents, supporting both the JSON
82+ /// form (`{"pccs_url": "https://..."}`, optionally with `//` comments) and the
83+ /// legacy INI form (`PCCS_URL=https://...`).
84+ fn parse_qcnl_pccs_url ( content : & str ) -> Option < String > {
85+ for raw in content. lines ( ) {
86+ let line = raw. trim ( ) ;
87+ if line. starts_with ( '#' ) || line. starts_with ( "//" ) {
88+ continue ;
89+ }
90+ let Some ( key_pos) = line. to_ascii_lowercase ( ) . find ( "pccs_url" ) else {
91+ continue ;
92+ } ;
93+ // After the key (INI `=` or JSON `":`), take the URL up to the next
94+ // quote / comma / whitespace. This covers both config styles.
95+ let after = & line[ key_pos + "pccs_url" . len ( ) ..] ;
96+ let Some ( http_pos) = after. find ( "http" ) else {
97+ continue ;
98+ } ;
99+ let url = & after[ http_pos..] ;
100+ let end = url
101+ . find ( |c : char | c == '"' || c == ',' || c. is_whitespace ( ) )
102+ . unwrap_or ( url. len ( ) ) ;
103+ let url = & url[ ..end] ;
104+ if !url. is_empty ( ) {
105+ return Some ( url. to_string ( ) ) ;
106+ }
107+ }
108+ None
109+ }
110+
111+ pub async fn ecdsa_quote_verification ( quote : & [ u8 ] ) -> Result < TcbVerificationResult > {
112+ let pccs_url = resolve_pccs_url ( ) ;
59113
60114 // The PCK certificate chain is embedded in the quote's certification data
61115 // (PCK cert type 5). Extract it and derive FMSPC / CA type for collateral.
@@ -548,3 +602,31 @@ fn find_sub(haystack: &[u8], needle: &[u8]) -> Option<usize> {
548602fn rfind_sub ( haystack : & [ u8 ] , needle : & [ u8 ] ) -> Option < usize > {
549603 haystack. windows ( needle. len ( ) ) . rposition ( |w| w == needle)
550604}
605+
606+ #[ cfg( test) ]
607+ mod tests {
608+ use super :: parse_qcnl_pccs_url;
609+
610+ #[ test]
611+ fn parse_qcnl_ini_form ( ) {
612+ let conf = "# comment\n PCCS_URL=https://sgx-dcap-server.cn-hangzhou.aliyuncs.com/sgx/certification/v4/\n USE_SECURE_CERT=false\n " ;
613+ assert_eq ! (
614+ parse_qcnl_pccs_url( conf) . as_deref( ) ,
615+ Some ( "https://sgx-dcap-server.cn-hangzhou.aliyuncs.com/sgx/certification/v4/" )
616+ ) ;
617+ }
618+
619+ #[ test]
620+ fn parse_qcnl_json_form ( ) {
621+ let conf = "{\n // Intel default style\n \" pccs_url\" : \" https://pccs.example.com/sgx/certification/v4/\" ,\n \" use_secure_cert\" : true\n }\n " ;
622+ assert_eq ! (
623+ parse_qcnl_pccs_url( conf) . as_deref( ) ,
624+ Some ( "https://pccs.example.com/sgx/certification/v4/" )
625+ ) ;
626+ }
627+
628+ #[ test]
629+ fn parse_qcnl_missing ( ) {
630+ assert_eq ! ( parse_qcnl_pccs_url( "USE_SECURE_CERT=false\n " ) , None ) ;
631+ }
632+ }
0 commit comments