55 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
66 */
77
8- use std:: collections:: HashMap ;
8+ use std:: collections:: BTreeMap ;
99use std:: convert:: { TryFrom , TryInto } ;
1010use std:: hash:: { DefaultHasher , Hash , Hasher } ;
1111use std:: io:: Read ;
@@ -570,10 +570,17 @@ pub trait ProvisioningClient {
570570
571571 /// Retrieve PCK certificates using `pckcerts()` and fallback to the
572572 /// following method if that's not supported:
573- /// - Call `pckcert()` to find the FMSPC.
574- /// - Using the FMSPC value, call `tcbinfo()` to get TCB info.
575- /// - For each TCB level in the result of previous call:
576- /// - Call `pckcert()` to get the best available PCK cert for that TCB level.
573+ /// 1. Call `pckcert()` with PCK ID to get best available PCK cert.
574+ /// 2. Try to call `pckcert()` with PCK ID but with CPUSVN all 1's.
575+ /// 3. Using the FMSPC value from PCK cert in step 1, call `tcbinfo()` to
576+ /// get TCB info.
577+ /// 4. For each TCB level in the result of previous call:
578+ /// - Call `pckcert()` to get the best available PCK cert for that TCB
579+ /// level.
580+ /// - When late microcode value is higher than the early microcode
581+ /// value, also try to get PCK cert with TCB level where the early
582+ /// microcode value is set to the late microcode value.
583+ ///
577584 /// Note that PCK certs for some TCB levels may be missing.
578585 fn pckcerts_with_fallback ( & self , pck_id : & PckID ) -> Result < PckCerts , Error > {
579586 match self . pckcerts ( & pck_id. enc_ppid , pck_id. pce_id ) {
@@ -592,15 +599,35 @@ pub trait ProvisioningClient {
592599 pck_id. pce_isvsvn ,
593600 Some ( & pck_id. qe_id ) ,
594601 ) ?;
602+ // Use BTreeMap to have an ordered PckCerts at the end
603+ let mut pckcerts_map = BTreeMap :: new ( ) ;
604+ // Getting PCK cert using CPUSVN from PCKID
605+ {
606+ let ptcb = pck_cert. platform_tcb ( ) ?;
607+ pckcerts_map. insert ( ( ptcb. cpusvn , ptcb. tcb_components . pce_svn ( ) ) , pck_cert. clone ( ) ) ;
608+ }
609+ // Getting PCK cert using CPUSVN all 1's
610+ {
611+ if let Ok ( pck_cert) = self . pckcert (
612+ Some ( & pck_id. enc_ppid ) ,
613+ & pck_id. pce_id ,
614+ & [ u8:: MAX ; 16 ] ,
615+ pck_id. pce_isvsvn ,
616+ Some ( & pck_id. qe_id ) ,
617+ ) {
618+ let ptcb = pck_cert. platform_tcb ( ) ?;
619+ pckcerts_map. insert ( ( ptcb. cpusvn , ptcb. tcb_components . pce_svn ( ) ) , pck_cert) ;
620+ }
621+ }
595622 let fmspc = pck_cert. sgx_extension ( ) ?. fmspc ;
596623 let tcb_info = self . tcbinfo ( & fmspc, None ) ?;
597624 let tcb_data = tcb_info. data ( ) ?;
598- let mut pcks = HashMap :: new ( ) ;
625+ // For every CPUSVN we also try where the late microcode value is higher
626+ // than the early microcode value, the CPUSVN where the early
627+ // microcode value is set to the late microcode value
628+ for ( cpu_svn, pce_isvsvn) in tcb_data. iter_tcb_components ( )
629+ . chain ( tcb_data. iter_tcb_components_with_late_tcb_override_only ( ) )
599630 {
600- let ptcb = pck_cert. platform_tcb ( ) ?;
601- pcks. insert ( ( ptcb. cpusvn , ptcb. tcb_components . pce_svn ( ) ) , pck_cert) ;
602- }
603- for ( cpu_svn, pce_isvsvn) in tcb_data. iter_tcb_components ( ) {
604631 let p = match self . pckcert (
605632 Some ( & pck_id. enc_ppid ) ,
606633 & pck_id. pce_id ,
@@ -614,10 +641,11 @@ pub trait ProvisioningClient {
614641 Err ( other) => return Err ( other)
615642 } ;
616643 let ptcb = p. platform_tcb ( ) ?;
617- pcks . insert ( ( ptcb. cpusvn , ptcb. tcb_components . pce_svn ( ) ) , p) ;
644+ pckcerts_map . insert ( ( ptcb. cpusvn , ptcb. tcb_components . pce_svn ( ) ) , p) ;
618645 }
619- let pcks: Vec < _ > = pcks. into_iter ( ) . map ( |( _, v) | v) . collect ( ) ;
620- pcks
646+ // BTreeMap by default is Ascending
647+ let pck_certs: Vec < _ > = pckcerts_map. into_iter ( ) . rev ( ) . map ( |( _, v) | v) . collect ( ) ;
648+ pck_certs
621649 . try_into ( )
622650 . map_err ( |e| Error :: PCSDecodeError ( format ! ( "{}" , e) . into ( ) ) )
623651 }
0 commit comments