Skip to content

Commit

Permalink
vlek: Adding VLEK support
Browse files Browse the repository at this point in the history
This addds support for handling Version Loaded Endorsement Keys

Signed-off-by: Larry Dewey <larry.dewey@amd.com>
  • Loading branch information
larrydewey committed Feb 7, 2024
1 parent 8ec07d4 commit aa7a96c
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 23 deletions.
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

0 comments on commit aa7a96c

Please sign in to comment.