Skip to content

Commit

Permalink
Attestation Report versioning Update
Browse files Browse the repository at this point in the history
In spec 1.56 of the SEV firmware a new version of the attestation report
was introduced.

Here we are introducing a way to version the attestation report that
keeps security and backwards compatibility.

The main AttestationReport is now an enum that will contain the
different versions of the attestation report. There are 2 new structs
for the Attestation Report, one for each version. There is a new trait
called Attestable that all the attestation reports will implement, this
will allow users to attest their report regardless of the version.

The ReportRsp will now contain raw bytes, rather than the Attestation
Report Strucutre. The AttestationReport Enum has a TryFrom bytes that
will return the appropriate attestation report version according to the
first 4 bytes of the raw data.

Structs consumed by the attestation report that now have new fields
depending on the version, are now also versioned, and each report
will consume the appropriate version of that struct (look at PlatInfo).

Signed-off-by: DGonzalezVillal <[email protected]>
  • Loading branch information
DGonzalezVillal committed Dec 20, 2024
1 parent 18ed5c5 commit 6e34b22
Show file tree
Hide file tree
Showing 11 changed files with 453 additions and 57 deletions.
40 changes: 40 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,9 @@ pub enum UserApiError {
/// Invalid VMPL.
VmplError,

/// Attestation Report Error
AttestationReportError(AttestationError),

/// Unknown error
Unknown,
}
Expand All @@ -550,6 +553,7 @@ impl error::Error for UserApiError {
Self::VmmError(vmm_error) => Some(vmm_error),
Self::HashstickError(hashstick_error) => Some(hashstick_error),
Self::VmplError => None,
Self::AttestationReportError(attestation_error) => Some(attestation_error),
Self::Unknown => None,
}
}
Expand All @@ -565,6 +569,9 @@ impl std::fmt::Display for UserApiError {
Self::VmmError(error) => format!("VMM Error Encountered: {error}"),
Self::HashstickError(error) => format!("VLEK Hashstick Error Encountered: {error}"),
Self::VmplError => "Invalid VM Permission Level (VMPL)".to_string(),
Self::AttestationReportError(error) => {
format!("Attestation Report Error Encountered: {error}")
}
Self::Unknown => "Unknown Error Encountered!".to_string(),
};
write!(f, "{err_msg}")
Expand Down Expand Up @@ -619,6 +626,12 @@ impl std::convert::From<CertError> for UserApiError {
}
}

impl std::convert::From<AttestationError> for UserApiError {
fn from(attestation_error: AttestationError) -> Self {
Self::AttestationReportError(attestation_error)
}
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
/// Errors which may be encountered when handling Version Loaded Endorsement Keys
/// (VLEK) Hashsticks.
Expand Down Expand Up @@ -699,6 +712,33 @@ impl std::fmt::Display for CertError {

impl error::Error for CertError {}

#[derive(Debug)]
/// Errors which may be encountered when handling attestation reports
pub enum AttestationError {
/// Bincode Error Handling
BincodeError(bincode::ErrorKind),

/// Unsuported Attestation Report Version
UnsupportedReportVersion(u32),
}

impl std::fmt::Display for AttestationError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
AttestationError::BincodeError(e) => write!(f, "Bincode error encountered: {e}"),
AttestationError::UnsupportedReportVersion(version) => write!(f, "The encountered Attestation Report version {version} is not supported by the library yet."),
}
}
}

impl std::convert::From<bincode::ErrorKind> for AttestationError {
fn from(value: bincode::ErrorKind) -> Self {
Self::BincodeError(value)
}
}

impl error::Error for AttestationError {}

#[derive(Debug)]
/// Errors which may be encountered when building custom guest context.
pub enum GCTXError {
Expand Down
13 changes: 10 additions & 3 deletions src/firmware/guest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::firmware::{
},
};

use std::convert::TryFrom;
#[cfg(target_os = "linux")]
use std::fs::{File, OpenOptions};

Expand Down Expand Up @@ -107,7 +108,9 @@ impl Firmware {
Err(FirmwareError::from(response.status))?
}

Ok(response.report)
let raw_report = response.report.as_slice();

Ok(AttestationReport::try_from(raw_report.as_slice())?)
}

/// Request an extended attestation report from the AMD Secure Processor.
Expand Down Expand Up @@ -179,8 +182,12 @@ impl Firmware {
Err(FirmwareError::from(report_response.status))?
}

let raw_report = report_response.report.as_slice();

let report = AttestationReport::try_from(raw_report.as_slice())?;

if ext_report_request.certs_len == 0 {
return Ok((report_response.report, None));
return Ok((report, None));
}

let mut certificates: Vec<CertTableEntry>;
Expand All @@ -194,7 +201,7 @@ impl Firmware {
}

// Return both the Attestation Report, as well as the Cert Table.
Ok((report_response.report, Some(certificates)))
Ok((report, Some(certificates)))
}

/// Fetches a derived key from the AMD Secure Processor. The `message_version` will default to `1` if `None` is specified.
Expand Down
Loading

0 comments on commit 6e34b22

Please sign in to comment.