diff --git a/src/error.rs b/src/error.rs index 4465e267..735603d2 100644 --- a/src/error.rs +++ b/src/error.rs @@ -834,6 +834,9 @@ pub enum IdBlockError { /// Bincode Error Handling BincodeError(bincode::ErrorKind), + /// TryFrom Slice Error handling + FromSliceError(TryFromSliceError), + /// Error from when handling SEV Curve algorithm SevCurveError(), @@ -849,6 +852,7 @@ impl std::fmt::Display for IdBlockError { IdBlockError::LargeArrayError(e) => write!(f, "{e}"), IdBlockError::FileError(e) => write!(f, "Failed handling file: {e}"), IdBlockError::BincodeError(e) => write!(f, "Bincode error encountered: {e}"), + IdBlockError::FromSliceError(e) => write!(f, "Error converting slice: {e}"), IdBlockError::SevCurveError() => { write!(f, "Wrong curve used in the provided private key") } @@ -879,12 +883,19 @@ impl std::convert::From for IdBlockError { Self::FileError(value) } } + impl std::convert::From for IdBlockError { fn from(value: bincode::ErrorKind) -> Self { Self::BincodeError(value) } } +impl std::convert::From for IdBlockError { + fn from(value: TryFromSliceError) -> Self { + Self::FromSliceError(value) + } +} + /// Errors which may be encountered when calculating the guest measurement. #[derive(Debug)] pub enum MeasurementError { @@ -915,9 +926,15 @@ pub enum MeasurementError { /// Id Block Error Handling IdBlockError(IdBlockError), + /// Large Array Error handling + LargeArrayError(LargeArrayError), + /// Invalid VCPU provided InvalidVcpuTypeError(String), + /// Invalid VCPU Signature provided + InvalidVcpuSignatureError(String), + /// Invalid VMM Provided InvalidVmmError(String), @@ -943,9 +960,15 @@ impl std::fmt::Display for MeasurementError { MeasurementError::OVMFError(e) => write!(f, "OVMF Error Encountered: {e}"), MeasurementError::SevHashError(e) => write!(f, "Sev hash Error Encountered: {e}"), MeasurementError::IdBlockError(e) => write!(f, "Id Block Error Encountered: {e}"), + MeasurementError::LargeArrayError(e) => { + write!(f, "Error when handling Large arrays: {e}") + } MeasurementError::InvalidVcpuTypeError(value) => { write!(f, "Invalid VCPU type value provided: {value}") } + MeasurementError::InvalidVcpuSignatureError(value) => { + write!(f, "Invalid VCPU signature provided: {value}") + } MeasurementError::InvalidVmmError(value) => { write!(f, "Invalid VMM type provided: {value}") } @@ -1013,3 +1036,15 @@ impl std::convert::From for MeasurementError { Self::SevHashError(value) } } + +impl std::convert::From for MeasurementError { + fn from(value: IdBlockError) -> Self { + Self::IdBlockError(value) + } +} + +impl std::convert::From for MeasurementError { + fn from(value: LargeArrayError) -> Self { + Self::LargeArrayError(value) + } +} diff --git a/src/measurement/gctx.rs b/src/measurement/gctx.rs index 96f017cc..2abddea2 100644 --- a/src/measurement/gctx.rs +++ b/src/measurement/gctx.rs @@ -7,18 +7,18 @@ use openssl::sha::sha384; use crate::error::*; #[cfg(target_os = "linux")] -use crate::launch::snp::PageType; - -// Launch digest size in bytes -pub(crate) const LD_SIZE: usize = 384 / 8; +use crate::{ + launch::snp::PageType, + measurement::snp::{SnpLaunchDigest, LD_BYTES}, +}; // VMSA page is recorded in the RMP table with GPA (u64)(-1). // However, the address is page-aligned, and also all the bits above // 51 are cleared. pub(crate) const VMSA_GPA: u64 = 0xFFFFFFFFF000; -// Launch digest intialized in all zeros -const ZEROS: [u8; LD_SIZE] = [0; LD_SIZE]; +// Launch digest sized array with all zeros +const ZEROS: [u8; LD_BYTES] = [0; LD_BYTES]; fn validate_block_size(length: usize) -> Result<(), GCTXError> { if (length % 4096) != 0 { @@ -33,8 +33,9 @@ pub(crate) struct Completed; /// Guest context field structure pub struct Gctx { - /// Launch Digest, 48 bytes long - ld: [u8; LD_SIZE], + /// 48 byte Launch Digest + ld: SnpLaunchDigest, + /// Current GCTX state _state: T, } @@ -42,7 +43,7 @@ pub struct Gctx { impl Default for Gctx { fn default() -> Self { Self { - ld: ZEROS, + ld: SnpLaunchDigest::default(), _state: Updating, } } @@ -58,14 +59,14 @@ impl Gctx { } /// Will update guest context launch digest with provided data from page - fn update(&mut self, page_type: u8, gpa: u64, contents: &[u8]) -> Result<(), GCTXError> { + fn update(&mut self, page_type: u8, gpa: u64, contents: &[u8]) -> Result<(), MeasurementError> { let page_info_len: u16 = 0x70; let is_imi: u8 = 0; let vmpl3_perms: u8 = 0; let vmpl2_perms: u8 = 0; let vmpl1_perms: u8 = 0; - let mut page_info: Vec = self.ld.to_vec(); + let mut page_info: Vec = self.ld.try_into()?; page_info.extend_from_slice(contents); page_info.extend_from_slice(&page_info_len.to_le_bytes()); @@ -80,17 +81,14 @@ impl Gctx { page_info.extend_from_slice(&gpa.to_le_bytes()); if page_info.len() != (page_info_len as usize) { - return Err(GCTXError::InvalidPageSize( - page_info.len(), - page_info_len as usize, - )); + return Err(GCTXError::InvalidPageSize(page_info.len(), page_info_len as usize).into()); } - self.ld = sha384(&page_info); + self.ld = sha384(&page_info).as_slice().try_into()?; Ok(()) } - /// Update Lanunch digest type accprding to page type and guest physical address. + /// Update Lanunch digest type according to page type and guest physical address. /// Some Page types don't require data. Some page types just require size of the page. #[cfg(target_os = "linux")] pub fn update_page( @@ -99,7 +97,7 @@ impl Gctx { gpa: u64, contents: Option<&[u8]>, length_bytes: Option, - ) -> Result<(), GCTXError> { + ) -> Result<(), MeasurementError> { match page_type { PageType::Normal => { if let Some(data) = contents { @@ -116,7 +114,7 @@ impl Gctx { } Ok(()) } else { - Err(GCTXError::MissingData) + Err(GCTXError::MissingData.into()) } } @@ -126,7 +124,7 @@ impl Gctx { self.update(page_type as u8, VMSA_GPA, sha384(data).as_slice())?; Ok(()) } else { - Err(GCTXError::MissingData) + Err(GCTXError::MissingData.into()) } } @@ -140,7 +138,7 @@ impl Gctx { } Ok(()) } else { - Err(GCTXError::MissingBlockSize) + Err(GCTXError::MissingBlockSize.into()) } } @@ -161,7 +159,7 @@ impl Gctx { } } - /// Update is done and now we switch to a completed state + /// Change State to Completed pub(crate) fn finished(&self) -> Gctx { Gctx { ld: self.ld, @@ -172,7 +170,7 @@ impl Gctx { impl Gctx { /// Get the launch digest bytes - pub(crate) fn ld(&self) -> &[u8; LD_SIZE] { - &self.ld + pub(crate) fn ld(&self) -> SnpLaunchDigest { + self.ld } } diff --git a/src/measurement/idblock.rs b/src/measurement/idblock.rs index 124c056d..9a91f655 100644 --- a/src/measurement/idblock.rs +++ b/src/measurement/idblock.rs @@ -13,9 +13,13 @@ use std::{ use crate::{ error::IdBlockError, - measurement::idblock_types::{ - FamilyId, IdAuth, IdBlock, IdBlockLaunchDigest, IdMeasurements, ImageId, SevEcdsaPubKey, - SevEcdsaSig, CURVE_P384_NID, + firmware::guest::GuestPolicy, + measurement::{ + idblock_types::{ + FamilyId, IdAuth, IdBlock, IdMeasurements, ImageId, SevEcdsaPubKey, SevEcdsaSig, + CURVE_P384_NID, + }, + snp::SnpLaunchDigest, }, }; @@ -99,13 +103,13 @@ pub fn load_priv_key(path: PathBuf) -> Result, IdBlockError> { Ok(pkey) } -/// Generate the sha384 digest of the provided pem key -pub fn generate_key_digest(key_path: PathBuf) -> Result { +/// Generate the sha384 digest of the provided pem key (same sized digest as SNP Launch Digest) +pub fn generate_key_digest(key_path: PathBuf) -> Result { let ec_key = load_priv_key(key_path)?; let pub_key = SevEcdsaPubKey::try_from(&ec_key)?; - Ok(IdBlockLaunchDigest::new( + Ok(SnpLaunchDigest::new( sha384( bincode::serialize(&pub_key) .map_err(|e| IdBlockError::BincodeError(*e))? @@ -118,11 +122,11 @@ pub fn generate_key_digest(key_path: PathBuf) -> Result, + ld: Option, family_id: Option, image_id: Option, svn: Option, - policy: Option, + policy: Option, id_key_file: PathBuf, auth_key_file: PathBuf, ) -> Result { diff --git a/src/measurement/idblock_types.rs b/src/measurement/idblock_types.rs index 282852d4..25187421 100644 --- a/src/measurement/idblock_types.rs +++ b/src/measurement/idblock_types.rs @@ -14,18 +14,19 @@ use openssl::{ use serde::{Deserialize, Serialize}; use std::convert::{TryFrom, TryInto}; -use crate::{error::IdBlockError, measurement::large_array::LargeArray}; +use crate::{ + error::IdBlockError, + firmware::guest::GuestPolicy, + measurement::{large_array::LargeArray, snp::SnpLaunchDigest}, +}; pub(crate) const DEFAULT_ID_VERSION: u32 = 1; -pub(crate) const DEFAULT_ID_POLICY: u64 = 0x300000; +pub(crate) const DEFAULT_ID_POLICY: u64 = 0x30000; pub(crate) const CURVE_P384_NID: Nid = openssl::nid::Nid::SECP384R1; pub(crate) const DEFAULT_KEY_ALGO: u32 = 1; pub(crate) const CURVE_P384: u32 = 2; -pub(crate) const ID_BLK_DIGEST_BITS: usize = 384; -pub(crate) const ID_BLK_DIGEST_BYTES: usize = ID_BLK_DIGEST_BITS / 8; - pub(crate) const ID_BLK_ID_BITS: usize = 128; pub(crate) const ID_BLK_ID_BYTES: usize = ID_BLK_ID_BITS / 8; @@ -39,45 +40,30 @@ pub(crate) const ECDSA_POINT_SIZE_BYTES: usize = ECDSA_POINT_SIZE_BITS / 8; pub(crate) const ECDSA_PUBKEY_RESERVED: usize = 0x403 - 0x94 + 1; pub(crate) const ECDSA_SIG_RESERVED: usize = 0x1ff - 0x90 + 1; -/// The expected launch digest of the guest +/// Family-Id of the guest, provided by the guest owner and uninterpreted by the firmware. #[repr(C)] #[derive(Default, Serialize, Deserialize, Clone, Copy)] -pub struct IdBlockLaunchDigest(LargeArray); - -impl TryFrom<&[u8]> for IdBlockLaunchDigest { - type Error = IdBlockError; +pub struct FamilyId([u8; ID_BLK_ID_BYTES]); - fn try_from(bytes: &[u8]) -> Result { - Ok(IdBlockLaunchDigest(bytes.try_into()?)) +impl FamilyId { + /// Create a new Family Id with the provided data + pub fn new(data: [u8; ID_BLK_ID_BYTES]) -> Self { + Self(data) } } -impl TryInto> for IdBlockLaunchDigest { - type Error = &'static str; - - fn try_into(self) -> Result, Self::Error> { - let array = self.0.as_array(); - let vec: Vec = array.to_vec(); // Convert the array into a Vec - Ok(vec) - } -} +// Try from slice for Family Id +impl TryFrom<&[u8]> for FamilyId { + type Error = IdBlockError; -impl IdBlockLaunchDigest { - /// Create Launch Digest from large array - pub fn new(data: LargeArray) -> Self { - Self(data) + fn try_from(bytes: &[u8]) -> Result { + Ok(FamilyId(bytes.try_into()?)) } } -/// Family ID of the guest, provided by the guest owner and uninterpreted by the firmware. -#[repr(C)] -#[derive(Default, Serialize, Deserialize, Clone, Copy)] -pub struct FamilyId([u8; ID_BLK_ID_BYTES]); - -/// Image ID to be provided to the ID-BLOCK -#[repr(C)] -#[derive(Default, Serialize, Deserialize, Clone, Copy)] -pub struct ImageId([u8; ID_BLK_ID_BYTES]); +/// Family-Id of the guest, provided by the guest owner and uninterpreted by the firmware. +/// Esentially the same structure as Family Id. +pub type ImageId = FamilyId; /// The way the ECDSA SEV signature is strucutred. Need it in this format to calculate the AUTH-ID. #[repr(C)] @@ -208,12 +194,12 @@ impl TryFrom<&EcKey> for SevEcdsaPubKey { } } -/// SEV ID-BLOCK +/// SEV-SNP ID-BLOCK #[repr(C)] #[derive(Serialize, Deserialize, Clone, Copy)] pub struct IdBlock { /// The expected launch digest of the guest (aka measurement) - pub launch_digest: IdBlockLaunchDigest, + pub launch_digest: SnpLaunchDigest, /// Family ID of the guest, provided by the guest owner and uninterpreted by the firmware. pub family_id: FamilyId, /// Image ID of the guest, provided by the guest owner and uninterpreted by the firmware. @@ -223,7 +209,7 @@ pub struct IdBlock { /// SVN of the guest. pub guest_svn: u32, ///The policy of the guest. - pub policy: u64, + pub policy: GuestPolicy, } impl Default for IdBlock { @@ -234,19 +220,19 @@ impl Default for IdBlock { image_id: Default::default(), version: DEFAULT_ID_VERSION, guest_svn: Default::default(), - policy: DEFAULT_ID_POLICY, + policy: GuestPolicy(DEFAULT_ID_POLICY), } } } impl IdBlock { - /// Function to create a new ID-BLOCK with provided parameters. + /// Create a new ID-BLOCK with provided parameters. pub fn new( - ld: Option, + ld: Option, family_id: Option, image_id: Option, svn: Option, - policy: Option, + policy: Option, ) -> Result { let mut id_block = IdBlock::default(); @@ -348,14 +334,14 @@ impl Default for IdAuth { } #[derive(Default)] -/// All the measurments that can be used for pre-attestation +/// All the calculated pieces needed for ID verfication pub struct IdMeasurements { /// ID-BLOCK pub id_block: IdBlock, /// ID-AUTH-BLOCK pub id_auth: IdAuth, /// ID-KEY DIGEST - pub id_key_digest: IdBlockLaunchDigest, + pub id_key_digest: SnpLaunchDigest, /// AUTH-KEY DIGEST - pub auth_key_digest: IdBlockLaunchDigest, + pub auth_key_digest: SnpLaunchDigest, } diff --git a/src/measurement/ovmf.rs b/src/measurement/ovmf.rs index 2a9e3d2a..6c097ff1 100644 --- a/src/measurement/ovmf.rs +++ b/src/measurement/ovmf.rs @@ -23,7 +23,7 @@ pub fn guid_le_to_slice(guid: &str) -> Result<[u8; 16], MeasurementError> { Ok(guid.try_into()?) } -/// Types of sections declared by OVMF SEV Metadata, as appears in: https://github.com/tianocore/edk2/blob/edk2-stable202205/OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm +/// Types of sections declared by OVMF SEV Metadata, as appears in: https://github.com/tianocore/edk2/blob/edk2-stable202405/OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm #[derive(Debug, Clone, Copy, PartialEq, Deserialize)] #[serde(into = "u8", try_from = "u8")] pub enum SectionType { @@ -32,7 +32,9 @@ pub enum SectionType { /// SNP secret SnpSecrets = 2, /// CPUID - CPUID = 3, + Cpuid = 3, + /// SVSM_CAA + SvsmCaa = 4, /// SNP kernel hashes SnpKernelHashes = 0x10, } @@ -50,7 +52,8 @@ impl TryFrom for SectionType { match value { 1 => Ok(SectionType::SnpSecMemory), 2 => Ok(SectionType::SnpSecrets), - 3 => Ok(SectionType::CPUID), + 3 => Ok(SectionType::Cpuid), + 4 => Ok(SectionType::SvsmCaa), 0x10 => Ok(SectionType::SnpKernelHashes), _ => Err(OVMFError::InvalidSectionType), } diff --git a/src/measurement/snp.rs b/src/measurement/snp.rs index 1ca6b944..654fa828 100644 --- a/src/measurement/snp.rs +++ b/src/measurement/snp.rs @@ -2,27 +2,63 @@ //! Operations to calculate guest measurement for different SEV modes use crate::{ + error::*, launch::snp::PageType, measurement::{ gctx::{Gctx, Updating, VMSA_GPA}, + large_array::LargeArray, ovmf::{OvmfSevMetadataSectionDesc, SectionType, OVMF}, sev_hashes::SevHashes, vcpu_types::CpuType, - vmsa::{VMMType, VMSA}, + vmsa::{GuestFeatures, VMMType, VMSA}, }, }; use hex::FromHex; +use serde::{Deserialize, Serialize}; +use std::convert::{TryFrom, TryInto}; use std::path::PathBuf; -use crate::error::*; +const _PAGE_MASK: u64 = 0xfff; -use super::{gctx::LD_SIZE, vmsa::GuestFeatures}; +/// Launch Digest sizes +pub(crate) const LD_BITS: usize = 384; +pub(crate) const LD_BYTES: usize = LD_BITS / 8; -const _PAGE_MASK: u64 = 0xfff; +/// The expected launch digest of the guest +#[repr(C)] +#[derive(Debug, Default, Serialize, Deserialize, Clone, Copy)] +pub struct SnpLaunchDigest(LargeArray); + +// Try from slice +impl TryFrom<&[u8]> for SnpLaunchDigest { + type Error = MeasurementError; + + fn try_from(bytes: &[u8]) -> Result { + Ok(SnpLaunchDigest(bytes.try_into()?)) + } +} + +/// Vecotrize Launch Digest +impl TryInto> for SnpLaunchDigest { + type Error = MeasurementError; + + fn try_into(self) -> Result, MeasurementError> { + let array = self.0.as_array(); + let vec: Vec = array.to_vec(); // Convert the array into a Vec + Ok(vec) + } +} + +impl SnpLaunchDigest { + /// Create Launch Digest from large array + pub fn new(data: LargeArray) -> Self { + Self(data) + } -/// Get the launch digest as a hex string -pub fn get_hex_ld(ld: Vec) -> String { - hex::encode(ld) + /// Get the launch digest as a hex string + pub fn get_hex_ld(self) -> String { + hex::encode::<&[u8]>(self.0.as_slice()) + } } /// Update launch digest with SEV kernel hashes @@ -70,7 +106,7 @@ fn snp_update_section( SectionType::SnpSecrets => { gctx.update_page(PageType::Secrets, desc.gpa.into(), None, None)? } - SectionType::CPUID => { + SectionType::Cpuid => { if vmm_type != VMMType::EC2 { gctx.update_page(PageType::Cpuid, desc.gpa.into(), None, None)? } @@ -78,6 +114,12 @@ fn snp_update_section( SectionType::SnpKernelHashes => { snp_update_kernel_hashes(gctx, ovmf, sev_hashes, desc.gpa.into(), desc.size as usize)? } + SectionType::SvsmCaa => gctx.update_page( + PageType::Zero, + desc.gpa.into(), + None, + Some(desc.size as usize), + )?, } Ok(()) @@ -96,7 +138,7 @@ fn snp_update_metadata_pages( if vmm_type == VMMType::EC2 { for desc in ovmf.metadata_items() { - if desc.section_type == SectionType::CPUID { + if desc.section_type == SectionType::Cpuid { gctx.update_page(PageType::Cpuid, desc.gpa.into(), None, None)? } } @@ -111,7 +153,7 @@ fn snp_update_metadata_pages( } /// Calculate the OVMF hash from OVMF file -pub fn calc_snp_ovmf_hash(ovmf_file: PathBuf) -> Result<[u8; LD_SIZE], MeasurementError> { +pub fn calc_snp_ovmf_hash(ovmf_file: PathBuf) -> Result { let ovmf = OVMF::new(ovmf_file)?; let mut gctx = Gctx::default(); @@ -119,7 +161,7 @@ pub fn calc_snp_ovmf_hash(ovmf_file: PathBuf) -> Result<[u8; LD_SIZE], Measureme let gctx = gctx.finished(); - Ok(*gctx.ld()) + Ok(gctx.ld()) } /// Arguments required to calculate the SNP measurement @@ -147,7 +189,7 @@ pub struct SnpMeasurementArgs<'a> { /// Calulate an SEV-SNP launch digest pub fn snp_calc_launch_digest( snp_measurement: SnpMeasurementArgs, -) -> Result<[u8; LD_SIZE], MeasurementError> { +) -> Result { let ovmf = OVMF::new(snp_measurement.ovmf_file)?; let mut gctx: Gctx = match snp_measurement.ovmf_hash_str { @@ -194,5 +236,5 @@ pub fn snp_calc_launch_digest( let gctx = gctx.finished(); - Ok(*gctx.ld()) + Ok(gctx.ld()) } diff --git a/src/measurement/vcpu_types.rs b/src/measurement/vcpu_types.rs index 43397c51..4864080b 100644 --- a/src/measurement/vcpu_types.rs +++ b/src/measurement/vcpu_types.rs @@ -64,6 +64,22 @@ impl TryFrom for CpuType { } } +impl TryFrom for CpuType { + type Error = MeasurementError; + + fn try_from(value: i32) -> Result { + match value { + sig if sig == cpu_sig(23, 1, 2) => Ok(CpuType::Epyc), + sig if sig == cpu_sig(23, 49, 0) => Ok(CpuType::EpycRome), + sig if sig == cpu_sig(25, 1, 1) => Ok(CpuType::EpycMilan), + sig if sig == cpu_sig(25, 17, 0) => Ok(CpuType::EpycGenoa), + _ => Err(MeasurementError::InvalidVcpuSignatureError( + value.to_string(), + )), + } + } +} + impl CpuType { /// Matching CPU-Type with its CPU signature pub fn sig(&self) -> i32 { diff --git a/src/measurement/vmsa.rs b/src/measurement/vmsa.rs index 5ad0b162..c0968842 100644 --- a/src/measurement/vmsa.rs +++ b/src/measurement/vmsa.rs @@ -57,6 +57,19 @@ impl TryFrom for VMMType { } } +impl FromStr for VMMType { + type Err = MeasurementError; + + fn from_str(value: &str) -> Result { + match value.to_lowercase().as_str() { + "qemu" => Ok(VMMType::QEMU), + "ec2" => Ok(VMMType::EC2), + "krun" => Ok(VMMType::KRUN), + _ => Err(MeasurementError::InvalidVcpuTypeError(value.to_string())), + } + } +} + impl fmt::Debug for VMMType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/tests/id-block.rs b/tests/id-block.rs index 48707623..9a2e0af9 100644 --- a/tests/id-block.rs +++ b/tests/id-block.rs @@ -14,14 +14,15 @@ use hex::{self, FromHex}; use sev::measurement::{ idblock::{load_priv_key, snp_calculate_id}, - idblock_types::{IdAuth, IdBlockLaunchDigest, SevEcdsaPubKey, SevEcdsaSig}, + idblock_types::{IdAuth, SevEcdsaPubKey, SevEcdsaSig}, + snp::SnpLaunchDigest, }; // Testing that the appropriate id-block and key digests are being generated. #[test] fn test_id_block_and_key_digests() { // Expected ID-BLOCk, ID-KEY digest and AUTH-KEY digest - let expected_id_block = "oU1jg0HlZ0Yo/h4C++3r5eWrT68d1y2JZgaOYVu5nv0T0hSzXCMXFbOOJj3GBZdFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAMAAAAAAA".to_string(); + let expected_id_block = "oU1jg0HlZ0Yo/h4C++3r5eWrT68d1y2JZgaOYVu5nv0T0hSzXCMXFbOOJj3GBZdFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAwAAAAAA".to_string(); let expected_id_key_digest = "WfssaG36T+9J84M5qndckAUcKNVzg93DuvO160sUlt87DbvcuuX+J2d6ZEggdz/i".to_string(); let expected_auth_key_digest = @@ -29,8 +30,7 @@ fn test_id_block_and_key_digests() { // Pre-generated launch digest let launch_digest = Vec::from_hex("a14d638341e5674628fe1e02fbedebe5e5ab4faf1dd72d8966068e615bb99efd13d214b35c231715b38e263dc6059745").unwrap(); - let id_launch_digest: IdBlockLaunchDigest = - IdBlockLaunchDigest::new(launch_digest.try_into().unwrap()); + let id_launch_digest: SnpLaunchDigest = SnpLaunchDigest::new(launch_digest.try_into().unwrap()); // Generating ID-block and key digests let block_calculations = snp_calculate_id( diff --git a/tests/measurement.rs b/tests/measurement.rs index 7712658d..0d1cd3ec 100644 --- a/tests/measurement.rs +++ b/tests/measurement.rs @@ -13,7 +13,7 @@ mod snp_tests { // Test if we can compute a full LD from a pre generated hash using snp only kernel #[test] fn test_snp_ovmf_hash_gen_snp_only() { - let ovmf_hash = "cab7e085874b3acfdbe2d96dcaa3125111f00c35c6fc9708464c2ae74bfdb048a198cb9a9ccae0b3e5e1a33f5f249819"; + let ovmf_hash = "086e2e9149ebf45abdc3445fba5b2da8270bdbb04094d7a2c37faaa4b24af3aa16aff8c374c2a55c467a50da6d466b74"; let arguments = SnpMeasurementArgs { vcpus: 1, @@ -29,17 +29,15 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "3c018b826531c5f625f10004d51ee51ab5dbfaf1fdd79998ab649cff11b4afbdb2f50941d2a23b5d77fe00cf988242e7"; + let exp_result = "ddc5224521617a536ee7ce9dd6224d1b58a8d4fda1c741f3ac99fc4bfa04ba6e9fc98646d4a07a9079397fa3852819b5"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test if we can compute a full LD from a pre generated hash using the default kernel setting #[test] fn test_snp_ovmf_hash_gen_default() { - let ovmf_hash = "cab7e085874b3acfdbe2d96dcaa3125111f00c35c6fc9708464c2ae74bfdb048a198cb9a9ccae0b3e5e1a33f5f249819"; + let ovmf_hash = "086e2e9149ebf45abdc3445fba5b2da8270bdbb04094d7a2c37faaa4b24af3aa16aff8c374c2a55c467a50da6d466b74"; let arguments = SnpMeasurementArgs { vcpus: 1, @@ -55,21 +53,19 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "aa6f24465c304e3ad553a18069510996fc92a84f48ae2140cb95dfbd422cdb14087588fb6eec89ef0a65e6d376d9a300"; + let exp_result = "329c8ce0972ae52343b64d34a434a86f245dfd74f5ed7aae15d22efc78fb9683632b9b50e4e1d7fa41179ef98a7ef198"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test if we can compute a full LD from the OVMF hash usin snp only kernel #[test] fn test_snp_ovmf_hash_full_snp_only() { - let ovmf_hash = hex::encode( - calc_snp_ovmf_hash("./tests/measurement/ovmf_AmdSev_suffix.bin".into()).unwrap(), - ); + let ovmf_hash = calc_snp_ovmf_hash("./tests/measurement/ovmf_AmdSev_suffix.bin".into()) + .unwrap() + .get_hex_ld(); - let exp_hash = "edcf6d1c57ce868a167c990f58c8667c698269ef9e0803246419eea914186343054d557e1f17acd93b032c106bc70d25"; + let exp_hash = "086e2e9149ebf45abdc3445fba5b2da8270bdbb04094d7a2c37faaa4b24af3aa16aff8c374c2a55c467a50da6d466b74"; assert_eq!(ovmf_hash.as_str(), exp_hash); @@ -87,21 +83,19 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "72b3f3c1ed0df9e5279eb2317a9861be3b878537e8513b318b49c1e184f6228e3ff367d133a8688f430e412ba66f558f"; + let exp_result = "6d287813eb5222d770f75005c664e34c204f385ce832cc2ce7d0d6f354454362f390ef83a92046c042e706363b4b08fa"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test if we can compute a full LD from the OVMF hash using default kernel #[test] fn test_snp_ovmf_hash_full_default() { - let ovmf_hash = hex::encode( - calc_snp_ovmf_hash("./tests/measurement/ovmf_AmdSev_suffix.bin".into()).unwrap(), - ); + let ovmf_hash = calc_snp_ovmf_hash("./tests/measurement/ovmf_AmdSev_suffix.bin".into()) + .unwrap() + .get_hex_ld(); - let exp_hash = "edcf6d1c57ce868a167c990f58c8667c698269ef9e0803246419eea914186343054d557e1f17acd93b032c106bc70d25"; + let exp_hash = "086e2e9149ebf45abdc3445fba5b2da8270bdbb04094d7a2c37faaa4b24af3aa16aff8c374c2a55c467a50da6d466b74"; assert_eq!(ovmf_hash.as_str(), exp_hash); @@ -119,11 +113,9 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "2b9ca4d24c46845280fdca6f0ca0edf0f704bf179243e5c1b139acf3668ce7bc040e12d16b2ee8738aeaa39faddc8912"; + let exp_result = "803f691094946e42068aaa3a8f9e26a5c89f36f7b73ecfb28c653360fe4b3aba7e534442e7e1e17895dfe778d0228977"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test EC2 vmm type with SNP only kernel @@ -143,11 +135,9 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "760b6e51039d2d6c1fc6d38ca5c387967d158e0294883e4522c36f89bd61bfc9cdb975cd1ceedffbe1b23b1daf4e3f42"; + let exp_result = "7d3756157c805bf6adf617064c8552e8c1688fa1c8756f11cbf56ba5d25c9270fb69c0505c1cbe1c5c66c0e34c6ed3be"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test EC2 vmm type with default kernel @@ -167,16 +157,14 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "cd4a4690a1f679ac8f3d6e446aab8d0061d535cc94615d98c7d7dbe4b16dbceeaf7fc7944e7874b202e27041f179e7e6"; + let exp_result = "6ae80856486b1396af8c82a40351d6ed76a20c785e9c7fa4ffa27c22d5d6313b4b3b458cd3c9968e6f89fb5d8450d7a6"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test a regular snp type with snp only kernel #[test] - fn test_snp_snp_only() { + fn test_sev_snp_only() { let arguments = SnpMeasurementArgs { vcpus: 1, vcpu_type: CpuType::EpycV4, @@ -191,11 +179,9 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "72b3f3c1ed0df9e5279eb2317a9861be3b878537e8513b318b49c1e184f6228e3ff367d133a8688f430e412ba66f558f"; + let exp_result = "6d287813eb5222d770f75005c664e34c204f385ce832cc2ce7d0d6f354454362f390ef83a92046c042e706363b4b08fa"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test a regular snp type with default kernel @@ -215,11 +201,9 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "2b9ca4d24c46845280fdca6f0ca0edf0f704bf179243e5c1b139acf3668ce7bc040e12d16b2ee8738aeaa39faddc8912"; + let exp_result = "803f691094946e42068aaa3a8f9e26a5c89f36f7b73ecfb28c653360fe4b3aba7e534442e7e1e17895dfe778d0228977"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test a regular snp without specified kernel using an snp only guest kernel @@ -239,11 +223,9 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "c4ee889e2ca38dc7137f5a448c56960a1eb5c08919fd2107a1249eb899afda42be9ba11e417530938cfa8d62a5890557"; + let exp_result = "19358ba9a7615534a9a1e2f0dfc29384dcd4dcb7062ff9c6013b26869a5fc6ecabe033c48dd6f6db5d6d76e7c5df632d"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test a regular snp without specified kernel using a default guest kernel @@ -263,11 +245,9 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "d35ca073e73701aa476d9d1b2feeee9efd935b7ec9dc43a0105857f506addb48ba3a1d443e5c10db430ad1a436ac5b2c"; + let exp_result = "e1e1ca029dd7973ab9513295be68198472dcd4fc834bd9af9b63f6e8a1674dbf281a9278a4a2ebe0eed9f22adbcd0e2b"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test snp with multiple cpus with an snp only guest kernel @@ -287,11 +267,9 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "74b2f532253c8214df9998ba8df305aa98eb1733c0010014c5ed728b8d1a9fa83df0a0caf047e9cee14087cc79bbc7c9"; + let exp_result = "5061fffb019493a903613d56d54b94912a1a2f9e4502385f5c194616753720a92441310ba6c4933de877c36e23046ad5"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test snp with multiple cpus with a default guest kernel @@ -311,11 +289,9 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); - - let exp_result = "6258fc4d3c60d6964de64811587a903f309b9391efdccd448bb8bc39b78c1d153378077ca37e32d06d6ead319a5c7bce"; + let exp_result = "4953b1fb416fa874980e8442b3706d345926d5f38879134e00813c5d7abcbe78eafe7b422907be0b4698e2414a631942"; - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test snp with with ovmf64 and no kernel using a snp only guest kernel @@ -335,11 +311,9 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); + let exp_result = "da0296de8193586a5512078dcd719eccecbd87e2b825ad4148c44f665dc87df21e5b49e21523a9ad993afdb6a30b4005"; - let exp_result = "6ea57de00ffc6f159c6b799f9c053cd165a021efed1614678b1a0ae24c6b0374387f52ace64e0fbc08d1129a857a0b0c"; - - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test snp with with ovmf64 and no kernel using a default guest kernel @@ -359,11 +333,9 @@ mod snp_tests { let ld = snp_calc_launch_digest(arguments).unwrap(); - let ld_hex = hex::encode(ld); + let exp_result = "28797ae0afaba4005a81e629acebfb59e6687949d6be44007cd5506823b0dd66f146aaae26ff291eed7b493d8a64c385"; - let exp_result = "7b30bdd3f3124ccfceaa882f4b3ab2ff3641bb421bb9bc6df6b9be0d8ecde33e6fba86505808ab5257e3e620a2006e53"; - - assert_eq!(ld_hex.as_str(), exp_result); + assert_eq!(ld.get_hex_ld().as_str(), exp_result); } // Test non-SNP OVMF and SNP measure should fail @@ -411,7 +383,7 @@ mod sev_tests { let ld_hex = hex::encode(ld); - let exp_result = "c9c378be09902e3d5927a93b73ed383620eea5387e1d16416807cfc949b7f834"; + let exp_result = "13810ae661ea11e2bb205621f582fee268f0367c8f97bc297b7fadef3e12002c"; assert_eq!(ld_hex.as_str(), exp_result); } @@ -433,7 +405,7 @@ mod sev_tests { let ld_hex = hex::encode(ld); - let exp_result = "2806971adf7a9d5bdef59d007f0200af685dec6721781fe1d6efa9236b3361f1"; + let exp_result = "0dccbcaba8e90b261bd0d2e1863a2f9da714768b7b2a19363cd6ae35aa90de91"; assert_eq!(ld_hex.as_str(), exp_result); } @@ -474,7 +446,7 @@ mod sev_tests { let ld_hex = hex::encode(ld); - let exp_result = "f0d92a1fda00249e008820bd40def6abbed2ee65fea8a8bc47e532863ca0cc6a"; + let exp_result = "82a3ee5d537c3620628270c292ae30cb40c3c878666a7890ee7ef2a08fb535ff"; assert_eq!(ld_hex.as_str(), exp_result); } @@ -493,7 +465,7 @@ mod sev_tests { let ld_hex = hex::encode(ld); - let exp_result = "7332f6ef294f79919b46302e4541900a2dfc96714e2b7b4b5ccdc1899b78a195"; + let exp_result = "77f613d7bbcdf12a73782ea9e88b0172aeda50d1a54201cb903594ff52846898"; assert_eq!(ld_hex.as_str(), exp_result); } @@ -512,7 +484,7 @@ mod sev_tests { let ld_hex = hex::encode(ld); - let exp_result = "af9d6c674b1ff04937084c98c99ca106b25c37b2c9541ac313e6e0c54426314f"; + let exp_result = "b4c021e085fb83ceffe6571a3d357b4a98773c83c474e47f76c876708fe316da"; assert_eq!(ld_hex.as_str(), exp_result); } diff --git a/tests/measurement/ovmf_AmdSev_suffix.bin b/tests/measurement/ovmf_AmdSev_suffix.bin index 4ecfc95a..0095249c 100644 Binary files a/tests/measurement/ovmf_AmdSev_suffix.bin and b/tests/measurement/ovmf_AmdSev_suffix.bin differ diff --git a/tests/measurement/ovmf_OvmfX64_suffix.bin b/tests/measurement/ovmf_OvmfX64_suffix.bin index 43a56981..ea76d285 100644 Binary files a/tests/measurement/ovmf_OvmfX64_suffix.bin and b/tests/measurement/ovmf_OvmfX64_suffix.bin differ