Skip to content

Commit 5daff92

Browse files
committed
Address reviewer comments
1 parent c2ad654 commit 5daff92

File tree

4 files changed

+84
-107
lines changed

4 files changed

+84
-107
lines changed

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

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use lru_cache::LruCache;
1616
use num_enum::TryFromPrimitive;
1717
use pcs::{
1818
CpuSvn, DcapArtifactIssuer, EncPpid, Fmspc, PceId, PceIsvsvn, PckCert, PckCerts, PckCrl, PckID, QeId,
19-
QeIdentitySigned, TcbInfo, RawTcbEvaluationDataNumbers, Unverified,
19+
QeIdentitySigned, TcbComponent, TcbInfo, RawTcbEvaluationDataNumbers, Unverified,
2020
};
2121
#[cfg(feature = "reqwest")]
2222
use reqwest::blocking::{Client as ReqwestClient, Response as ReqwestResponse};
@@ -583,66 +583,65 @@ pub trait ProvisioningClient {
583583
///
584584
/// Note that PCK certs for some TCB levels may be missing.
585585
fn pckcerts_with_fallback(&self, pck_id: &PckID) -> Result<PckCerts, Error> {
586+
let get_and_collect = |collection: &mut BTreeMap<([u8; 16], u16), PckCert<Unverified>>, cpu_svn: &[u8; 16], pce_svn: u16| -> Result<PckCert<Unverified>, Error> {
587+
let pck_cert = self.pckcert(
588+
Some(&pck_id.enc_ppid),
589+
&pck_id.pce_id,
590+
cpu_svn,
591+
pce_svn,
592+
Some(&pck_id.qe_id),
593+
)?;
594+
595+
// Getting PCK cert using CPUSVN from PCKID
596+
let ptcb = pck_cert.platform_tcb()?;
597+
collection.insert((ptcb.cpusvn, ptcb.tcb_components.pce_svn()), pck_cert.clone());
598+
Ok(pck_cert)
599+
};
600+
586601
match self.pckcerts(&pck_id.enc_ppid, pck_id.pce_id) {
587602
Ok(pck_certs) => return Ok(pck_certs),
588603
Err(Error::RequestNotSupported) => {} // fallback below
589604
Err(e) => return Err(e),
590605
}
591606
// fallback:
592607

593-
// NOTE: at least with PCCS, any call to `pckcert()` will return the
594-
// "best available" PCK cert for the specified TCB level.
595-
let pck_cert = self.pckcert(
596-
Some(&pck_id.enc_ppid),
597-
&pck_id.pce_id,
598-
&pck_id.cpu_svn,
599-
pck_id.pce_isvsvn,
600-
Some(&pck_id.qe_id),
601-
)?;
602608
// Use BTreeMap to have an ordered PckCerts at the end
603609
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-
}
610+
611+
// 1. Use PCK ID to get best available PCK Cert
612+
let pck_cert = get_and_collect(&mut pckcerts_map, &pck_id.cpu_svn, pck_id.pce_isvsvn)?;
613+
614+
// 2. Getting PCK cert using CPUSVN all 1's
615+
let _ign_err = get_and_collect(&mut pckcerts_map, &[u8::MAX; 16], pck_id.pce_isvsvn);
616+
622617
let fmspc = pck_cert.sgx_extension()?.fmspc;
623618
let tcb_info = self.tcbinfo(&fmspc, None)?;
624619
let tcb_data = tcb_info.data()?;
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())
630-
{
631-
let p = match self.pckcert(
632-
Some(&pck_id.enc_ppid),
633-
&pck_id.pce_id,
634-
&cpu_svn,
635-
pce_isvsvn,
636-
Some(&pck_id.qe_id),
637-
) {
638-
Ok(cert) => cert,
639-
Err(Error::PCSError(StatusCode::NotFound, _)) |
640-
Err(Error::PCSError(StatusCode::NonStandard462, _)) => continue,
641-
Err(other) => return Err(other)
642-
};
643-
let ptcb = p.platform_tcb()?;
644-
pckcerts_map.insert((ptcb.cpusvn, ptcb.tcb_components.pce_svn()), p);
620+
for (cpu_svn, pce_isvsvn) in tcb_data.iter_tcb_components() {
621+
// 3. Get PCK based on TCB levels
622+
let _ = get_and_collect(&mut pckcerts_map, &cpu_svn, pce_isvsvn)?;
623+
624+
// 4. If late loaded microcode version is higher than early loaded microcode,
625+
// also try with highest microcode version of both components. We found cases where
626+
// fetching the PCK Cert that exactly matched the TCB level, did not result in a PCK
627+
// Cert for that level
628+
const EARLY_UCODE_IDX: usize = 0;
629+
const LATE_UCODE_IDX: usize = 1;
630+
// Unfortunately the TCB Info does not populate the component type (e.g., curl -v -X GET
631+
// "https://api.trustedservices.intel.com/sgx/certification/v4/tcb?fmspc=00906ED50000&tcbEvaluationDataNumber=20"
632+
// ). We pick a default as backup, and ensure errors fetching these PckCerts are
633+
// ignored.
634+
let eary_ucode_idx = tcb_data.tcb_component_index(TcbComponent::EarlyMicrocodeUpdate).unwrap_or(EARLY_UCODE_IDX);
635+
let late_ucode_idx = tcb_data.tcb_component_index(TcbComponent::LateMicrocodeUpdate).unwrap_or(LATE_UCODE_IDX);
636+
let early_ucode = cpu_svn[eary_ucode_idx];
637+
let late_ucode = cpu_svn[late_ucode_idx];
638+
if early_ucode < late_ucode {
639+
let mut cpu_svn = cpu_svn.clone();
640+
cpu_svn[eary_ucode_idx] = late_ucode;
641+
let _ign_err = get_and_collect(&mut pckcerts_map, &cpu_svn, pce_isvsvn);
642+
}
645643
}
644+
646645
// BTreeMap by default is Ascending
647646
let pck_certs: Vec<_> = pckcerts_map.into_iter().rev().map(|(_, v)| v).collect();
648647
pck_certs

intel-sgx/pcs/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use {
2929
};
3030

3131
pub use crate::pckcrl::PckCrl;
32-
pub use crate::pckcrt::{PckCert, PckCerts, SGXPCKCertificateExtension, SGXType};
32+
pub use crate::pckcrt::{PckCert, PckCerts, SGXPCKCertificateExtension, SGXType, TcbComponent};
3333
pub use crate::qe_identity::{EnclaveIdentity, QeIdentity, QeIdentitySigned};
3434
pub use crate::tcb_info::{AdvisoryID, Fmspc, TcbInfo, TcbData, TcbLevel};
3535
pub use crate::tcb_evaluation_data_numbers::{RawTcbEvaluationDataNumbers, TcbEvalNumber, TcbEvaluationDataNumbers, TcbPolicy};

intel-sgx/pcs/src/pckcrt.rs

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,26 @@ enum IntelSgxTcbComponents {
127127
#[serde(from = "IntelSgxTcbComponents")]
128128
pub struct TcbComponents(IntelSgxTcbComponentsV4);
129129

130+
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
131+
pub enum TcbComponent {
132+
EarlyMicrocodeUpdate,
133+
LateMicrocodeUpdate,
134+
}
135+
136+
impl TryFrom<&str> for TcbComponent {
137+
type Error = ();
138+
139+
fn try_from(s: &str) -> Result<Self, Self::Error> {
140+
if s == "Early Microcode Update" {
141+
Ok(TcbComponent::EarlyMicrocodeUpdate)
142+
} else if s == "SGX Late Microcode Update" {
143+
Ok(TcbComponent::LateMicrocodeUpdate)
144+
} else {
145+
Err(())
146+
}
147+
}
148+
}
149+
130150
impl TcbComponents {
131151
pub fn from_raw(raw_cpusvn: [u8; 16], pcesvn: u16) -> Self {
132152
TcbComponents(IntelSgxTcbComponentsV4 {
@@ -159,48 +179,11 @@ impl TcbComponents {
159179
out
160180
}
161181

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
182+
/// Returns the index of the TCB component
183+
pub fn tcb_component_index(&self, comp: TcbComponent) -> Option<usize> {
184+
self.0.sgxtcbcomponents
192185
.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
186+
.position(|c| TcbComponent::try_from(c.comp_type.as_str()) == Ok(comp))
204187
}
205188
}
206189

@@ -857,7 +840,7 @@ mod tests {
857840

858841
use super::*;
859842
#[cfg(not(target_env = "sgx"))]
860-
use crate::{TcbInfo, get_cert_subject, get_cert_subject_from_der};
843+
use crate::{get_cert_subject, get_cert_subject_from_der};
861844

862845
fn decode_tcb_item<'a, 'b>(reader: &mut BERReaderSeq<'a, 'b>) -> ASN1Result<(ObjectIdentifier, u8)> {
863846
let oid = reader.next().read_oid()?;

intel-sgx/pcs/src/tcb_info.rs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use {
1818
pkix::pem::PEM_CERTIFICATE, pkix::x509::GenericCertificate, pkix::FromBer, std::ops::Deref,
1919
};
2020

21-
use crate::pckcrt::TcbComponents;
21+
use crate::pckcrt::{TcbComponent, TcbComponents};
2222
use crate::{io, CpuSvn, Error, PceIsvsvn, Platform, TcbStatus, Unverified, VerificationType, Verified};
2323

2424
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -301,6 +301,16 @@ impl TcbData<Unverified> {
301301
}
302302
Ok(data)
303303
}
304+
305+
/// Returns the index of the TCB component
306+
pub fn tcb_component_index(&self, comp: TcbComponent) -> Option<usize> {
307+
if let Some(c) = self.tcb_levels.first() {
308+
c.components().tcb_component_index(comp)
309+
} else {
310+
None
311+
}
312+
}
313+
304314
}
305315

306316
impl<V: VerificationType> TcbData<V> {
@@ -326,21 +336,6 @@ impl<V: VerificationType> TcbData<V> {
326336
pub fn iter_tcb_components(&self) -> impl Iterator<Item = (CpuSvn, PceIsvsvn)> + '_ {
327337
self.tcb_levels.iter().map(|tcb_level| (tcb_level.tcb.cpu_svn(), tcb_level.tcb.pce_svn()))
328338
}
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-
}
344339
}
345340

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

0 commit comments

Comments
 (0)