Skip to content

Commit c2ad654

Browse files
committed
update fn pckcerts_with_fallback
New logic will get following PCK certs: - PCKID CPUSVN - CPUSVN all 1's - For every CPUSVN we try where the late microcode value is higher than the early microcode value, the CPUSVN where the early microcode value is set to the late microcode value.
1 parent f2a71fc commit c2ad654

File tree

3 files changed

+100
-13
lines changed

3 files changed

+100
-13
lines changed

intel-sgx/dcap-artifact-retrieval/src/provisioning_client/mod.rs

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
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;
99
use std::convert::{TryFrom, TryInto};
1010
use std::hash::{DefaultHasher, Hash, Hasher};
1111
use 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
}

intel-sgx/pcs/src/pckcrt.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,50 @@ impl TcbComponents {
158158
}
159159
out
160160
}
161+
162+
/// Returns the CPUSVN with the "Early Microcode Update" SVN overridden by the
163+
/// "SGX Late Microcode Update" SVN if the latter is higher.
164+
/// We assume there is only at most one component of either type.
165+
/// If there are multiple components of either type, only the first occurrence is used.
166+
///
167+
/// For example:
168+
/// ```json
169+
/// [
170+
/// ...
171+
/// {
172+
/// "svn": 7,
173+
/// "category": "BIOS",
174+
/// "type": "Early Microcode Update"
175+
/// },
176+
/// ...
177+
/// {
178+
/// "svn": 9,
179+
/// "category": "OS/VMM",
180+
/// "type": "SGX Late Microcode Update"
181+
/// },
182+
/// ...
183+
/// ]
184+
/// ```
185+
/// Here 7 will be set to 9. Note: order is random.
186+
pub fn cpu_svn_with_late_override_early(&self) -> CpuSvn {
187+
let mut out: CpuSvn = self.cpu_svn();
188+
let tcb_components = &self.0.sgxtcbcomponents;
189+
190+
// Find the first index of each relevant component type.
191+
let early_idx = tcb_components
192+
.iter()
193+
.position(|comp| comp.comp_type == "Early Microcode Update");
194+
let late_idx = tcb_components
195+
.iter()
196+
.position(|comp| comp.comp_type == "SGX Late Microcode Update");
197+
198+
if let (Some(early), Some(late)) = (early_idx, late_idx) {
199+
if out[early] < out[late] {
200+
out[early] = out[late];
201+
}
202+
}
203+
out
204+
}
161205
}
162206

163207
impl PartialOrd for TcbComponents {

intel-sgx/pcs/src/tcb_info.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,21 @@ impl<V: VerificationType> TcbData<V> {
326326
pub fn iter_tcb_components(&self) -> impl Iterator<Item = (CpuSvn, PceIsvsvn)> + '_ {
327327
self.tcb_levels.iter().map(|tcb_level| (tcb_level.tcb.cpu_svn(), tcb_level.tcb.pce_svn()))
328328
}
329+
330+
/// For every CPUSVN where the late microcode value is higher
331+
/// than the early microcode value, the CPUSVN where the early
332+
/// microcode value is set to the late microcode value
333+
pub fn iter_tcb_components_with_late_tcb_override_only(&self) -> impl Iterator<Item = (CpuSvn, PceIsvsvn)> + '_ {
334+
self.tcb_levels.iter().filter_map(|tcb_level| {
335+
let overridden_svn = tcb_level.tcb.cpu_svn_with_late_override_early();
336+
let cpu_svn = tcb_level.tcb.cpu_svn();
337+
if cpu_svn != overridden_svn {
338+
Some((overridden_svn, tcb_level.tcb.pce_svn()))
339+
} else {
340+
None
341+
}
342+
})
343+
}
329344
}
330345

331346
#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)]

0 commit comments

Comments
 (0)