Parse TDVF firmware metadata This function uses scale codec for clean, panic-free parsing. Correctness is verified by integration test in tests/tdvf_parse.rs which ensures identical measurements to the original implementation.
(fw: &'a [u8])
| 122 | /// Correctness is verified by integration test in tests/tdvf_parse.rs |
| 123 | /// which ensures identical measurements to the original implementation. |
| 124 | pub fn parse(fw: &'a [u8]) -> Result<Tdvf<'a>> { |
| 125 | const TDX_METADATA_OFFSET_GUID: &str = "e47a6535-984a-4798-865e-4685a7bf8ec2"; |
| 126 | const TABLE_FOOTER_GUID: &str = "96b582de-1fb2-45f7-baea-a366c55a082d"; |
| 127 | const BYTES_AFTER_TABLE_FOOTER: usize = 32; |
| 128 | |
| 129 | if fw.len() < BYTES_AFTER_TABLE_FOOTER { |
| 130 | bail!("TDVF firmware too small"); |
| 131 | } |
| 132 | let offset = fw.len() - BYTES_AFTER_TABLE_FOOTER; |
| 133 | let encoded_footer_guid = encode_guid(TABLE_FOOTER_GUID)?; |
| 134 | if offset < 16 { |
| 135 | bail!("TDVF firmware offset too small for GUID"); |
| 136 | } |
| 137 | let guid = &fw[offset - 16..offset]; |
| 138 | |
| 139 | if guid != encoded_footer_guid { |
| 140 | bail!("Failed to parse TDVF metadata: Invalid footer GUID"); |
| 141 | } |
| 142 | |
| 143 | if offset < 18 { |
| 144 | bail!("TDVF firmware offset too small for tables length"); |
| 145 | } |
| 146 | let tables_len = decode_le::<u16>(&fw[offset - 18..offset - 16], "tables length")? as usize; |
| 147 | if tables_len == 0 || tables_len > offset.saturating_sub(18) { |
| 148 | bail!("Failed to parse TDVF metadata: Invalid tables length"); |
| 149 | } |
| 150 | let table_start = offset.saturating_sub(18).saturating_sub(tables_len); |
| 151 | let tables = &fw[table_start..offset - 18]; |
| 152 | let mut offset = tables.len(); |
| 153 | |
| 154 | let mut data: Option<&[u8]> = None; |
| 155 | let encoded_guid = encode_guid(TDX_METADATA_OFFSET_GUID)?; |
| 156 | loop { |
| 157 | if offset < 18 { |
| 158 | break; |
| 159 | } |
| 160 | let guid = &tables[offset - 16..offset]; |
| 161 | let entry_len = read_le::<u16>(tables, offset - 18, "entry length")? as usize; |
| 162 | if entry_len > offset.saturating_sub(18) { |
| 163 | bail!("Failed to parse TDVF metadata: Invalid entry length"); |
| 164 | } |
| 165 | if guid == encoded_guid { |
| 166 | let entry_start = offset.saturating_sub(18).saturating_sub(entry_len); |
| 167 | data = Some(&tables[entry_start..offset - 18]); |
| 168 | break; |
| 169 | } |
| 170 | offset = offset.saturating_sub(entry_len); |
| 171 | } |
| 172 | |
| 173 | let data = data.context("Failed to parse TDVF metadata: Missing TDVF metadata")?; |
| 174 | |
| 175 | if data.len() < 4 { |
| 176 | bail!("TDVF metadata data too small"); |
| 177 | } |
| 178 | let tdvf_meta_offset_raw = |
| 179 | decode_le::<u32>(&data[data.len() - 4..], "TDVF metadata offset")? as usize; |
| 180 | if tdvf_meta_offset_raw > fw.len() { |
| 181 | bail!("TDVF metadata offset exceeds firmware size"); |
no test coverage detected