Skip to content

Commit f189110

Browse files
committed
test(snp): cover ovmf parser golden vector
1 parent ab89844 commit f189110

1 file changed

Lines changed: 85 additions & 0 deletions

File tree

dstack-mr/src/sev.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,91 @@ mod tests {
10321032
hex::encode(vec![byte; len])
10331033
}
10341034

1035+
fn ovmf_footer_entry(data: &[u8], guid: &[u8; 16]) -> Vec<u8> {
1036+
let mut entry = data.to_vec();
1037+
entry.extend_from_slice(&((data.len() + OVMF_FOOTER_ENTRY_SIZE) as u16).to_le_bytes());
1038+
entry.extend_from_slice(guid);
1039+
entry
1040+
}
1041+
1042+
fn synthetic_snp_ovmf() -> Vec<u8> {
1043+
let mut ovmf = vec![0u8; 4096];
1044+
let meta_start = 512usize;
1045+
ovmf[meta_start..meta_start + 4].copy_from_slice(b"ASEV");
1046+
write_u32_le_at(&mut ovmf, meta_start + 8, 1);
1047+
write_u32_le_at(&mut ovmf, meta_start + 12, 4);
1048+
let sections = [
1049+
(0x1000u32, 0x1000u32, 1u32),
1050+
(0x2000u32, 0x1000u32, 2u32),
1051+
(0x3000u32, 0x1000u32, 3u32),
1052+
(0x4000u32, 0x1000u32, 0x10u32),
1053+
];
1054+
for (i, (gpa, size, section_type)) in sections.into_iter().enumerate() {
1055+
let off = meta_start + 16 + i * 12;
1056+
write_u32_le_at(&mut ovmf, off, gpa);
1057+
write_u32_le_at(&mut ovmf, off + 4, size);
1058+
write_u32_le_at(&mut ovmf, off + 8, section_type);
1059+
}
1060+
1061+
let mut table = Vec::new();
1062+
table.extend(ovmf_footer_entry(
1063+
&0x4000u32.to_le_bytes(),
1064+
&GUID_SEV_HASH_TABLE_RV,
1065+
));
1066+
table.extend(ovmf_footer_entry(
1067+
&0xffff_fff0u32.to_le_bytes(),
1068+
&GUID_SEV_ES_RESET_BLK,
1069+
));
1070+
table.extend(ovmf_footer_entry(
1071+
&((ovmf.len() - meta_start) as u32).to_le_bytes(),
1072+
&GUID_SEV_META_DATA,
1073+
));
1074+
1075+
let footer_off = ovmf.len() - OVMF_RESET_VECTOR_TAIL_SIZE - OVMF_FOOTER_ENTRY_SIZE;
1076+
let table_start = footer_off - table.len();
1077+
ovmf[table_start..footer_off].copy_from_slice(&table);
1078+
write_u16_le_at(
1079+
&mut ovmf,
1080+
footer_off,
1081+
(table.len() + OVMF_FOOTER_ENTRY_SIZE) as u16,
1082+
);
1083+
ovmf[footer_off + 2..footer_off + OVMF_FOOTER_ENTRY_SIZE]
1084+
.copy_from_slice(&GUID_FOOTER_TABLE);
1085+
ovmf
1086+
}
1087+
1088+
#[test]
1089+
fn ovmf_parser_matches_synthetic_footer_metadata_vector() {
1090+
let ovmf = synthetic_snp_ovmf();
1091+
let info = OvmfInfo::parse(ovmf.clone()).expect("synthetic ovmf parses");
1092+
assert_eq!(info.gpa, FOUR_GIB - ovmf.len() as u64);
1093+
assert_eq!(info.sev_hashes_table_gpa, 0x4000);
1094+
assert_eq!(info.sev_es_reset_eip, 0xffff_fff0);
1095+
1096+
let sections: Vec<(u64, u64, SectionType)> = info
1097+
.sections
1098+
.iter()
1099+
.map(|s| (s.gpa, s.size, s.section_type))
1100+
.collect();
1101+
assert_eq!(
1102+
sections,
1103+
vec![
1104+
(0x1000, 0x1000, SectionType::SnpSecMemory),
1105+
(0x2000, 0x1000, SectionType::SnpSecrets),
1106+
(0x3000, 0x1000, SectionType::Cpuid),
1107+
(0x4000, 0x1000, SectionType::SnpKernelHashes),
1108+
]
1109+
);
1110+
1111+
let mut gctx = Gctx::new();
1112+
gctx.update_normal_pages(info.gpa, &info.data);
1113+
assert_eq!(
1114+
hex::encode(gctx.ld),
1115+
"7c0f80f0a8d0ab1ee23fe763b255b8b210bb71113febcda60d76c00e84512f0cc141ffaa61be7bd22164736e85ec52d3",
1116+
"synthetic OVMF launch digest vector should not drift"
1117+
);
1118+
}
1119+
10351120
fn valid_input() -> MeasurementInput {
10361121
let rootfs_hash = hex_of(0x33, 32);
10371122
MeasurementInput {

0 commit comments

Comments
 (0)