Skip to content

Commit 374d825

Browse files
Attestation Report versioning Update
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. This will not only handle both of the Attestation reports, but it will also work as an interface. Users will be able to use the enum to get any desired field and display the report without having to manually unwrap the report themselves. 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). We also add the sealed module with the sealed trait. This allows us to seal traits we want people to be able to use, but not to be able to impl themselves. For example in this PR we are now sealing the new trait Attestable. The enums that handle different versions will no longer use Serde Serialization and Deserialization due to the way Serde tags the raw data with 4 extra bytes. We implemented manual serialization and a raw from bytes. There are helper functions meant to facilitate this. We also modified and added unit testing. Signed-off-by: DGonzalezVillal <[email protected]>
1 parent 8ec281d commit 374d825

File tree

12 files changed

+1367
-245
lines changed

12 files changed

+1367
-245
lines changed

src/error.rs

+44
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,9 @@ pub enum UserApiError {
536536
/// Invalid VMPL.
537537
VmplError,
538538

539+
/// Attestation Report Error
540+
AttestationReportError(AttestationReportError),
541+
539542
/// Unknown error
540543
Unknown,
541544
}
@@ -550,6 +553,7 @@ impl error::Error for UserApiError {
550553
Self::VmmError(vmm_error) => Some(vmm_error),
551554
Self::HashstickError(hashstick_error) => Some(hashstick_error),
552555
Self::VmplError => None,
556+
Self::AttestationReportError(attestation_error) => Some(attestation_error),
553557
Self::Unknown => None,
554558
}
555559
}
@@ -565,6 +569,9 @@ impl std::fmt::Display for UserApiError {
565569
Self::VmmError(error) => format!("VMM Error Encountered: {error}"),
566570
Self::HashstickError(error) => format!("VLEK Hashstick Error Encountered: {error}"),
567571
Self::VmplError => "Invalid VM Permission Level (VMPL)".to_string(),
572+
Self::AttestationReportError(error) => {
573+
format!("Attestation Report Error Encountered: {error}")
574+
}
568575
Self::Unknown => "Unknown Error Encountered!".to_string(),
569576
};
570577
write!(f, "{err_msg}")
@@ -619,6 +626,12 @@ impl std::convert::From<CertError> for UserApiError {
619626
}
620627
}
621628

629+
impl std::convert::From<AttestationReportError> for UserApiError {
630+
fn from(attestation_error: AttestationReportError) -> Self {
631+
Self::AttestationReportError(attestation_error)
632+
}
633+
}
634+
622635
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
623636
/// Errors which may be encountered when handling Version Loaded Endorsement Keys
624637
/// (VLEK) Hashsticks.
@@ -699,6 +712,37 @@ impl std::fmt::Display for CertError {
699712

700713
impl error::Error for CertError {}
701714

715+
#[derive(Debug)]
716+
/// Errors which may be encountered when handling attestation reports
717+
pub enum AttestationReportError {
718+
/// Bincode Error Handling
719+
BincodeError(bincode::ErrorKind),
720+
721+
/// Unsuported Attestation Report Version
722+
UnsupportedReportVersion(u32),
723+
724+
/// Field is not supported in the current version of the Attestation Report
725+
UnsupportedField(String),
726+
}
727+
728+
impl std::fmt::Display for AttestationReportError {
729+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
730+
match self {
731+
AttestationReportError::BincodeError(e) => write!(f, "Bincode error encountered: {e}"),
732+
AttestationReportError::UnsupportedReportVersion(version) => write!(f, "The encountered Attestation Report version {version} is not supported by the library yet."),
733+
AttestationReportError::UnsupportedField(field) => write!(f,"The field {field} is not supported in the provided Attestation Report version"),
734+
}
735+
}
736+
}
737+
738+
impl std::convert::From<bincode::ErrorKind> for AttestationReportError {
739+
fn from(value: bincode::ErrorKind) -> Self {
740+
Self::BincodeError(value)
741+
}
742+
}
743+
744+
impl error::Error for AttestationReportError {}
745+
702746
#[derive(Debug)]
703747
/// Errors which may be encountered when building custom guest context.
704748
pub enum GCTXError {

src/firmware/guest/mod.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::firmware::{
2121
},
2222
};
2323

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

@@ -107,7 +108,9 @@ impl Firmware {
107108
Err(FirmwareError::from(response.status))?
108109
}
109110

110-
Ok(response.report)
111+
let raw_report = response.report.as_array();
112+
113+
Ok(AttestationReport::try_from(raw_report.as_slice())?)
111114
}
112115

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

185+
let raw_report = report_response.report.as_array();
186+
187+
let report = AttestationReport::try_from(raw_report.as_slice())?;
188+
182189
if ext_report_request.certs_len == 0 {
183-
return Ok((report_response.report, None));
190+
return Ok((report, None));
184191
}
185192

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

196203
// Return both the Attestation Report, as well as the Cert Table.
197-
Ok((report_response.report, Some(certificates)))
204+
Ok((report, Some(certificates)))
198205
}
199206

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

0 commit comments

Comments
 (0)