Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vlek: Adding VLEK support #150

Merged
merged 1 commit into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 28 additions & 13 deletions src/certs/snp/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ pub struct Chain {
/// The Certificate Authority (CA) chain.
pub ca: ca::Chain,

/// The Versioned Chip Endorsement Key.
pub vcek: Certificate,
/// The Versioned Chip Endorsement Key or Versioned Loaded Endorsement Key.
pub vek: Certificate,
}

impl<'a> Verifiable for &'a Chain {
Expand All @@ -22,9 +22,9 @@ impl<'a> Verifiable for &'a Chain {
let ask = self.ca.verify()?;

// Verify that ASK signs VCEK.
(ask, &self.vcek).verify()?;
(ask, &self.vek).verify()?;

Ok(&self.vcek)
Ok(&self.vek)
}
}

Expand Down Expand Up @@ -56,6 +56,7 @@ impl Chain {
let mut ark: Option<Certificate> = None;
let mut ask: Option<Certificate> = None;
let mut vcek: Option<Certificate> = None;
let mut vlek: Option<Certificate> = None;

let other = ErrorKind::Other;

Expand Down Expand Up @@ -88,6 +89,13 @@ impl Chain {

vcek = Some(cert);
}
CertType::VLEK => {
if vlek.is_some() {
return Err(Error::new(other, "more than one VLEK certificate found"));
}

vlek = Some(cert);
}
_ => continue,
}
}
Expand All @@ -97,32 +105,39 @@ impl Chain {
return Err(Error::new(other, "ARK not found"));
} else if ask.is_none() {
return Err(Error::new(other, "ASK not found"));
} else if vcek.is_none() {
return Err(Error::new(other, "VCEK not found"));
} else if vcek.is_none() && vlek.is_none() {
return Err(Error::new(other, "VCEK/VLEK not found"));
}

// Use the VLEK whenever it is present, but use the VCEK when VLEK is missing.
let vek_val = match (vcek, vlek) {
(_, Some(vlek)) => vlek,
(Some(vcek), None) => vcek,
_ => unreachable!(),
};

Ok(Self {
ca: ca::Chain {
ark: ark.unwrap(),
ask: ask.unwrap(),
},
vcek: vcek.unwrap(),
vek: vek_val,
})
}

/// Deserialize a PEM-encoded ARK, ASK, and VCEK to a SEV-SNP chain.
pub fn from_pem(ark: &[u8], ask: &[u8], vcek: &[u8]) -> Result<Self> {
/// Deserialize a PEM-encoded ARK, ASK, and VEK to a SEV-SNP chain.
pub fn from_pem(ark: &[u8], ask: &[u8], vek: &[u8]) -> Result<Self> {
Ok(Self {
ca: ca::Chain::from_pem(ark, ask)?,
vcek: Certificate::from_pem(vcek)?,
vek: Certificate::from_pem(vek)?,
})
}

/// Deserialize a DER-encoded ARK, ASK, and VCEK to a SEV-SNP chain.
pub fn from_der(ark: &[u8], ask: &[u8], vcek: &[u8]) -> Result<Self> {
/// Deserialize a DER-encoded ARK, ASK, and VEK to a SEV-SNP chain.
pub fn from_der(ark: &[u8], ask: &[u8], vek: &[u8]) -> Result<Self> {
Ok(Self {
ca: ca::Chain::from_der(ark, ask)?,
vcek: Certificate::from_der(vcek)?,
vek: Certificate::from_der(vek)?,
})
}
}
24 changes: 18 additions & 6 deletions src/firmware/host/types/snp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ bitflags::bitflags! {
#[repr(C)]
/// Certificates which are accepted for [`CertTableEntry`](self::CertTableEntry)
pub enum CertType {
/// Empty or closing entry for the CertTable
Empty,

/// AMD Root Signing Key (ARK) certificate
ARK,

Expand All @@ -41,20 +44,25 @@ pub enum CertType {
/// Versioned Chip Endorsement Key (VCEK) certificate
VCEK,

/// Versioned Loaded Endorsement Key (VLEK) certificate
VLEK,

/// Certificate Revocation List (CRLs) certificate(s)
CRL,

/// Other (Specify GUID)
OTHER(uuid::Uuid),

/// Empty or closing entry for the CertTable
Empty,
}

impl ToString for CertType {
fn to_string(&self) -> String {
match self {
CertType::Empty => "00000000-0000-0000-0000-000000000000".to_string(),
CertType::ARK => "c0b406a4-a803-4952-9743-3fb6014cd0ae".to_string(),
CertType::ASK => "4ab7b379-bbac-4fe4-a02f-05aef327c782".to_string(),
CertType::VCEK => "63da758d-e664-4564-adc5-f4b93be8accd".to_string(),
CertType::Empty => "00000000-0000-0000-0000-000000000000".to_string(),
CertType::VLEK => "a8074bc2-a25a-483e-aae6-39c045a0b8a1".to_string(),
CertType::CRL => "92f81bc3-5811-4d3d-97ff-d19f88dc67ea".to_string(),
CertType::OTHER(guid) => guid.to_string(),
}
}
Expand All @@ -64,10 +72,12 @@ impl TryFrom<CertType> for uuid::Uuid {
type Error = uuid::Error;
fn try_from(value: CertType) -> Result<Self, Self::Error> {
match value {
CertType::Empty => uuid::Uuid::parse_str(&CertType::Empty.to_string()),
CertType::ARK => uuid::Uuid::parse_str(&CertType::ARK.to_string()),
CertType::ASK => uuid::Uuid::parse_str(&CertType::ASK.to_string()),
CertType::VCEK => uuid::Uuid::parse_str(&CertType::VCEK.to_string()),
CertType::Empty => uuid::Uuid::parse_str(&CertType::Empty.to_string()),
CertType::VLEK => uuid::Uuid::parse_str(&CertType::VLEK.to_string()),
CertType::CRL => uuid::Uuid::parse_str(&CertType::CRL.to_string()),
CertType::OTHER(guid) => Ok(guid),
}
}
Expand All @@ -78,10 +88,12 @@ impl TryFrom<&uuid::Uuid> for CertType {

fn try_from(value: &uuid::Uuid) -> Result<Self, Self::Error> {
Ok(match value.to_string().as_str() {
"00000000-0000-0000-0000-000000000000" => CertType::Empty,
"c0b406a4-a803-4952-9743-3fb6014cd0ae" => CertType::ARK,
"4ab7b379-bbac-4fe4-a02f-05aef327c782" => CertType::ASK,
"63da758d-e664-4564-adc5-f4b93be8accd" => CertType::VCEK,
"00000000-0000-0000-0000-000000000000" => CertType::Empty,
"a8074bc2-a25a-483e-aae6-39c045a0b8a1" => CertType::VLEK,
"92f81bc3-5811-4d3d-97ff-d19f88dc67ea" => CertType::CRL,
_ => CertType::OTHER(*value),
})
}
Expand Down
8 changes: 4 additions & 4 deletions tests/certs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ mod snp {

let chain = Chain {
ca,
vcek: vcek.clone(),
vek: vcek.clone(),
};

assert_eq!(chain.verify().ok(), Some(&vcek));
Expand All @@ -58,7 +58,7 @@ mod snp {

let ca = ca::Chain { ark, ask };

let chain = Chain { ca, vcek };
let chain = Chain { ca, vek: vcek };

assert_eq!(chain.verify().ok(), None);
}
Expand All @@ -73,7 +73,7 @@ mod snp {

let ca = ca::Chain { ark, ask };

let chain = Chain { ca, vcek };
let chain = Chain { ca, vek: vcek };

let report_bytes = hex::decode(TEST_MILAN_ATTESTATION_REPORT).unwrap();
let report: AttestationReport =
Expand All @@ -92,7 +92,7 @@ mod snp {

let ca = ca::Chain { ark, ask };

let chain = Chain { ca, vcek };
let chain = Chain { ca, vek: vcek };

let mut report_bytes = hex::decode(TEST_MILAN_ATTESTATION_REPORT).unwrap();
report_bytes[0] ^= 0x80;
Expand Down
Loading