td_shim_interface/
loader.rs

1// Copyright (c) 2022 Intel Corporation
2//
3// SPDX-License-Identifier: BSD-2-Clause-Patent
4extern crate alloc;
5
6use crate::metadata::{
7    self, TdxMetadataDescriptor, TdxMetadataGuid, TdxMetadataSection, TDX_METADATA_DESCRIPTOR_LEN,
8    TDX_METADATA_GUID_LEN, TDX_METADATA_OFFSET, TDX_METADATA_SECTION_LEN,
9};
10use alloc::vec::Vec;
11use core::convert::TryInto;
12use log::error;
13use scroll::Pread;
14
15pub struct TdShimLoader;
16
17impl TdShimLoader {
18    /// generate TdxMetadata elements tupple from input file
19    ///
20    /// # Arguments
21    ///
22    /// * `filename` - The td-shim binary which contains TdxMetadata
23    pub fn parse(binary_file: &[u8]) -> Option<(TdxMetadataDescriptor, Vec<TdxMetadataSection>)> {
24        let file_size = binary_file.len();
25        // Then read 4 bytes at the pos of [file_len - 0x20]
26        // This is the offset of TdxMetadata
27        let metadata_offset_addr = file_size - TDX_METADATA_OFFSET as usize;
28        let buffer = &binary_file[metadata_offset_addr..metadata_offset_addr + 4];
29        let mut metadata_offset = ((buffer[3] as u32) << 24)
30            | ((buffer[2] as u32) << 16)
31            | ((buffer[1] as u32) << 8)
32            | (buffer[0] as u32);
33        if metadata_offset > file_size as u32 - TDX_METADATA_OFFSET - TDX_METADATA_DESCRIPTOR_LEN {
34            error!("The metadata offset is invalid. {}", metadata_offset);
35            error!("{:X?}", buffer);
36            return None;
37        }
38
39        // Then read the guid
40        metadata_offset -= TDX_METADATA_GUID_LEN;
41        let buffer = &binary_file
42            [metadata_offset as usize..(metadata_offset + TDX_METADATA_GUID_LEN) as usize]
43            .try_into()
44            .unwrap();
45        let metadata_guid = TdxMetadataGuid::from_bytes(buffer);
46        if metadata_guid.is_none() {
47            error!("Invalid TdxMetadataGuid");
48            error!("{:X?}", &buffer);
49            return None;
50        }
51
52        // Then the descriptor
53        metadata_offset += TDX_METADATA_GUID_LEN;
54        let buffer = &binary_file
55            [metadata_offset as usize..(metadata_offset + TDX_METADATA_DESCRIPTOR_LEN) as usize];
56        let metadata_descriptor: TdxMetadataDescriptor =
57            buffer.pread::<TdxMetadataDescriptor>(0).unwrap();
58        if !metadata_descriptor.is_valid() {
59            error!("Invalid TdxMetadata Descriptor: {:?}", metadata_descriptor);
60            return None;
61        }
62
63        // check if the metadata length exceeds the file size
64        let metadata_len = metadata_descriptor.number_of_section_entry * TDX_METADATA_SECTION_LEN
65            + TDX_METADATA_GUID_LEN
66            + TDX_METADATA_DESCRIPTOR_LEN;
67        if metadata_offset + metadata_len + TDX_METADATA_GUID_LEN + TDX_METADATA_DESCRIPTOR_LEN
68            > file_size as u32
69        {
70            error!("Invalid TdxMetadata length {}", metadata_len);
71            return None;
72        }
73
74        // after that extract the sections one by one
75        let mut metadata_sections: Vec<TdxMetadataSection> = Vec::new();
76        let mut i = 0;
77        metadata_offset += TDX_METADATA_DESCRIPTOR_LEN;
78
79        loop {
80            let buffer = &binary_file
81                [metadata_offset as usize..(metadata_offset + TDX_METADATA_SECTION_LEN) as usize];
82
83            let section = buffer.pread::<TdxMetadataSection>(0).unwrap();
84            metadata_sections.push(section);
85
86            i += 1;
87            if i == metadata_descriptor.number_of_section_entry {
88                break;
89            }
90            metadata_offset += TDX_METADATA_SECTION_LEN;
91        }
92
93        if i != metadata_descriptor.number_of_section_entry {
94            error!("Invalid number of sections.");
95            return None;
96        }
97
98        // check the validness of the sections
99        if metadata::validate_sections(&metadata_sections).is_err() {
100            error!("Invalid metadata sections.");
101            return None;
102        }
103
104        Some((metadata_descriptor, metadata_sections))
105    }
106}