pewter/pe/sections/
certificate.rs

1//! The Attribute Certificate Table (Image Only)
2use crate::containers::Table;
3use crate::error::Result;
4use crate::io::ReadData;
5use crate::vec::Vec;
6
7use super::ParseSectionData;
8
9/// Attribute certificates can be associated with an image by adding an attribute certificate table.
10/// The attribute certificate table is composed of a set of contiguous, quadword-aligned attribute
11/// certificate entries. Zero padding is inserted between the original end of the file and the beginning
12/// of the attribute certificate table to achieve this alignment.
13#[derive(Default, Clone, Debug, PartialEq, Eq)]
14pub struct CertificateDataDirectory {
15    pub certificates: Table<Certificate>,
16}
17
18impl ParseSectionData for CertificateDataDirectory {
19    fn parse(
20        section_data: &[u8],
21        _: &super::Sections,
22        _: &crate::pe::optional_header::OptionalHeader,
23        _: &crate::pe::coff::CoffFileHeader,
24    ) -> Result<Self> {
25        let mut offset = 0;
26        let mut certificates = Table::new();
27        loop {
28            let cert = Certificate::read(&mut section_data[offset..].as_ref())?;
29            offset += cert.length as usize;
30            offset = (offset + 7) & !7;
31            certificates.push(cert);
32            if offset == section_data.len() {
33                break;
34            }
35        }
36        Ok(Self { certificates })
37    }
38}
39
40#[derive(Copy, Clone, Debug, PartialEq, Eq)]
41#[repr(u16)]
42pub enum CertificateType {
43    X509 = 0x0001,
44    PkcsSignedData = 0x0002,
45    Reserved1 = 0x0003,
46    TsStackSigned = 0x0004,
47    Other(u16),
48}
49
50impl CertificateType {
51    pub fn from_u16(val: u16) -> Self {
52        match val {
53            0x0001 => Self::X509,
54            0x0002 => Self::PkcsSignedData,
55            0x0003 => Self::Reserved1,
56            0x0004 => Self::TsStackSigned,
57            other => Self::Other(other),
58        }
59    }
60}
61
62impl Default for CertificateType {
63    fn default() -> Self {
64        Self::Other(0)
65    }
66}
67
68#[derive(Copy, Clone, Debug, PartialEq, Eq)]
69#[repr(u16)]
70pub enum CertificateRevision {
71    Revision1_0 = 0x0100,
72    Revision2_0 = 0x0200,
73    Other(u16),
74}
75
76impl CertificateRevision {
77    pub fn from_u16(val: u16) -> Self {
78        match val {
79            0x0001 => Self::Revision1_0,
80            0x0002 => Self::Revision2_0,
81            other => Self::Other(other),
82        }
83    }
84}
85
86impl Default for CertificateRevision {
87    fn default() -> Self {
88        Self::Other(0)
89    }
90}
91
92#[derive(Default, Clone, Debug, PartialEq, Eq)]
93pub struct Certificate {
94    /// Specifies the length of the attribute certificate entry.
95    pub length: u32,
96    /// Contains the certificate version number.
97    pub revision: CertificateRevision,
98    /// Specifies the type of content in `certificate`.
99    pub certificate_type: CertificateType,
100    /// Contains a certificate, such as an Authenticode signature.
101    /// For details, see the following text.
102    pub certificate: Vec<u8>,
103}
104
105impl ReadData for Certificate {
106    fn read(reader: &mut impl crate::io::Reader) -> crate::error::Result<Self> {
107        let length: u32 = reader.read()?;
108        let cert_data_len = length.saturating_sub(core::mem::size_of_val(&length) as u32) as usize;
109
110        let mut cert_data = reader.read_slice(cert_data_len)?;
111        Ok(Self {
112            length,
113            revision: CertificateRevision::from_u16(u16::read(&mut cert_data)?),
114            certificate_type: CertificateType::from_u16(u16::read(&mut cert_data)?),
115            certificate: Vec::from(cert_data),
116        })
117    }
118}