1- use crate :: dcap_utils:: DCAPRemoteAttestationResult ;
1+ use crate :: dcap_utils:: { CollateralService , DCAPRemoteAttestationResult } ;
22use crate :: errors:: Error ;
33use attestation_report:: QEType ;
44use crypto:: Address ;
5- use dcap_quote_verifier:: cert:: { get_x509_subject_cn, parse_certchain} ;
6- use dcap_quote_verifier:: sgx_extensions:: extract_sgx_extensions;
5+ use dcap_quote_verifier:: quotes:: version_3:: verify_quote_v3;
76use dcap_quote_verifier:: types:: quotes:: version_3:: QuoteV3 ;
8- use dcap_quote_verifier:: types:: utils:: parse_pem;
9- use dcap_quote_verifier:: { collaterals:: IntelCollateral , quotes:: version_3:: verify_quote_v3} ;
107use keymanager:: EnclaveKeyManager ;
118use lcp_types:: Time ;
129use log:: * ;
@@ -27,18 +24,14 @@ pub const INTEL_ROOT_CA_HASH: [u8; 32] = [
2724pub fn run_dcap_ra (
2825 key_manager : & EnclaveKeyManager ,
2926 target_enclave_key : Address ,
30- pccs_url : & str ,
31- certs_service_url : & str ,
32- is_early_update : bool ,
27+ collateral_service : CollateralService ,
3328) -> Result < ( ) , Error > {
3429 let current_time = Time :: now ( ) ;
3530 let result = dcap_ra (
3631 key_manager,
3732 target_enclave_key,
3833 current_time,
39- pccs_url,
40- certs_service_url,
41- is_early_update,
34+ collateral_service,
4235 ) ?;
4336
4437 key_manager
@@ -53,9 +46,7 @@ pub(crate) fn dcap_ra(
5346 key_manager : & EnclaveKeyManager ,
5447 target_enclave_key : Address ,
5548 current_time : Time ,
56- pccs_url : & str ,
57- certs_service_url : & str ,
58- is_early_update : bool ,
49+ collateral_service : CollateralService ,
5950) -> Result < DCAPRemoteAttestationResult , Error > {
6051 let ek_info = key_manager. load ( target_enclave_key) . map_err ( |e| {
6152 Error :: key_manager (
@@ -74,7 +65,7 @@ pub(crate) fn dcap_ra(
7465
7566 let quote = QuoteV3 :: from_bytes ( & raw_quote) . map_err ( Error :: dcap_quote_verifier) ?;
7667
77- let collateral = get_collateral ( pccs_url , certs_service_url , is_early_update , & quote) ?;
68+ let collateral = collateral_service . get_collateral ( & quote. signature . qe_cert_data ) ?;
7869 let output = verify_quote_v3 ( & quote, & collateral, current_time. as_unix_timestamp_secs ( ) )
7970 . map_err ( Error :: dcap_quote_verifier) ?;
8071
@@ -107,104 +98,6 @@ fn rsgx_qe_get_quote(app_report: &sgx_report_t) -> Result<Vec<u8>, sgx_quote3_er
10798 }
10899}
109100
110- fn get_collateral (
111- pccs_url : & str ,
112- certs_service_url : & str ,
113- is_early_update : bool ,
114- quote : & QuoteV3 ,
115- ) -> Result < IntelCollateral , Error > {
116- let pccs_url = pccs_url. trim_end_matches ( '/' ) ;
117- let certs_service_url = certs_service_url. trim_end_matches ( '/' ) ;
118- let base_url = format ! ( "{pccs_url}/sgx/certification/v4" ) ;
119- if quote. signature . qe_cert_data . cert_data_type != 5 {
120- return Err ( Error :: collateral ( "QE Cert Type must be 5" . to_string ( ) ) ) ;
121- }
122- let certchain_pems = parse_pem ( & quote. signature . qe_cert_data . cert_data )
123- . map_err ( |e| Error :: collateral ( format ! ( "cannot parse QE cert chain: {}" , e) ) ) ?;
124-
125- let certchain = parse_certchain ( & certchain_pems) . map_err ( Error :: dcap_quote_verifier) ?;
126- if certchain. len ( ) != 3 {
127- return Err ( Error :: collateral (
128- "QE Cert chain must have 3 certs" . to_string ( ) ,
129- ) ) ;
130- }
131-
132- let update_policy = if is_early_update { "early" } else { "standard" } ;
133-
134- // get the pck certificate
135- let pck_cert = & certchain[ 0 ] ;
136- let pck_cert_issuer = & certchain[ 1 ] ;
137-
138- // get the SGX extension
139- let sgx_extensions = extract_sgx_extensions ( pck_cert) . map_err ( Error :: dcap_quote_verifier) ?;
140- let ( tcbinfo_bytes, sgx_tcb_signing_der) = {
141- let fmspc = hex:: encode_upper ( sgx_extensions. fmspc ) ;
142- let res = http_get ( format ! (
143- "{base_url}/tcb?fmspc={fmspc}&update={update_policy}"
144- ) ) ?;
145- let issuer_chain =
146- extract_raw_certs ( get_header ( & res, "TCB-Info-Issuer-Chain" ) ?. as_bytes ( ) ) ?;
147- ( res. bytes ( ) ?. to_vec ( ) , issuer_chain[ 0 ] . clone ( ) )
148- } ;
149-
150- let qeidentity_bytes = http_get ( format ! ( "{base_url}/qe/identity?update={update_policy}" ) ) ?
151- . bytes ( ) ?
152- . to_vec ( ) ;
153- let sgx_intel_root_ca_crl_der = http_get ( format ! ( "{certs_service_url}/IntelSGXRootCA.der" ) ) ?
154- . bytes ( ) ?
155- . to_vec ( ) ;
156-
157- let pck_crl_url = match get_x509_subject_cn ( pck_cert_issuer) . as_str ( ) {
158- "Intel SGX PCK Platform CA" => format ! ( "{base_url}/pckcrl?ca=platform&encoding=der" ) ,
159- "Intel SGX PCK Processor CA" => format ! ( "{base_url}/pckcrl?ca=processor&encoding=der" ) ,
160- cn => {
161- return Err ( Error :: collateral ( format ! (
162- "Unknown PCK Cert Subject CN: {}" ,
163- cn
164- ) ) ) ;
165- }
166- } ;
167- let sgx_pck_crl_der = http_get ( pck_crl_url) ?. bytes ( ) ?. to_vec ( ) ;
168-
169- Ok ( IntelCollateral {
170- tcbinfo_bytes,
171- qeidentity_bytes,
172- sgx_intel_root_ca_der : INTEL_ROOT_CA . to_vec ( ) ,
173- sgx_tcb_signing_der,
174- sgx_intel_root_ca_crl_der,
175- sgx_pck_crl_der,
176- } )
177- }
178-
179- fn get_header ( res : & reqwest:: blocking:: Response , name : & str ) -> Result < String , Error > {
180- let value = res
181- . headers ( )
182- . get ( name)
183- . ok_or_else ( || Error :: collateral ( format ! ( "missing header {}" , name) ) ) ?
184- . to_str ( )
185- . map_err ( |e| Error :: collateral ( format ! ( "invalid header value: {}" , e) ) ) ?;
186- let value = urlencoding:: decode ( value)
187- . map_err ( |e| Error :: collateral ( format ! ( "invalid header value: {}" , e) ) ) ?;
188- Ok ( value. into_owned ( ) )
189- }
190-
191- fn extract_raw_certs ( cert_chain : & [ u8 ] ) -> Result < Vec < Vec < u8 > > , Error > {
192- Ok ( pem:: parse_many ( cert_chain)
193- . map_err ( Error :: pem) ?
194- . iter ( )
195- . map ( |i| i. contents ( ) . to_vec ( ) )
196- . collect ( ) )
197- }
198-
199- fn http_get ( url : String ) -> Result < reqwest:: blocking:: Response , Error > {
200- info ! ( "get collateral from {}" , url) ;
201- let res = reqwest:: blocking:: get ( & url) . map_err ( Error :: reqwest_get) ?;
202- if !res. status ( ) . is_success ( ) {
203- return Err ( Error :: invalid_http_status ( url, res. status ( ) ) ) ;
204- }
205- Ok ( res)
206- }
207-
208101#[ cfg( test) ]
209102mod tests {
210103 use super :: * ;
@@ -219,13 +112,14 @@ mod tests {
219112 fn test_dcap_collateral ( ) {
220113 let quote = get_test_quote ( ) ;
221114 let quote = QuoteV3 :: from_bytes ( & quote) . unwrap ( ) ;
222- let collateral = get_collateral (
115+ let service = CollateralService :: new (
223116 "https://api.trustedservices.intel.com/" ,
224117 "https://certificates.trustedservices.intel.com/" ,
225118 false ,
226- & quote,
227- )
228- . unwrap ( ) ;
119+ ) ;
120+ let collateral = service
121+ . get_collateral ( & quote. signature . qe_cert_data )
122+ . unwrap ( ) ;
229123 let res = verify_quote_v3 ( & quote, & collateral, Time :: now ( ) . as_unix_timestamp_secs ( ) ) ;
230124 assert ! ( res. is_ok( ) , "{:?}" , res) ;
231125 let output = res. unwrap ( ) ;
0 commit comments