use crate::containers::Table;
use crate::error::Result;
use crate::io::ReadData;
use crate::vec::Vec;
use super::ParseSectionData;
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct CertificateDataDirectory {
pub certificates: Table<Certificate>,
}
impl ParseSectionData for CertificateDataDirectory {
fn parse(
section_data: &[u8],
_: &super::Sections,
_: &crate::pe::optional_header::OptionalHeader,
_: &crate::pe::coff::CoffFileHeader,
) -> Result<Self> {
let mut offset = 0;
let mut certificates = Table::new();
loop {
let cert = Certificate::read(&mut section_data[offset..].as_ref())?;
offset += cert.length as usize;
offset = (offset + 7) & !7;
certificates.push(cert);
if offset == section_data.len() {
break;
}
}
Ok(Self { certificates })
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u16)]
pub enum CertificateType {
X509 = 0x0001,
PkcsSignedData = 0x0002,
Reserved1 = 0x0003,
TsStackSigned = 0x0004,
Other(u16),
}
impl CertificateType {
pub fn from_u16(val: u16) -> Self {
match val {
0x0001 => Self::X509,
0x0002 => Self::PkcsSignedData,
0x0003 => Self::Reserved1,
0x0004 => Self::TsStackSigned,
other => Self::Other(other),
}
}
}
impl Default for CertificateType {
fn default() -> Self {
Self::Other(0)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u16)]
pub enum CertificateRevision {
Revision1_0 = 0x0100,
Revision2_0 = 0x0200,
Other(u16),
}
impl CertificateRevision {
pub fn from_u16(val: u16) -> Self {
match val {
0x0001 => Self::Revision1_0,
0x0002 => Self::Revision2_0,
other => Self::Other(other),
}
}
}
impl Default for CertificateRevision {
fn default() -> Self {
Self::Other(0)
}
}
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct Certificate {
pub length: u32,
pub revision: CertificateRevision,
pub certificate_type: CertificateType,
pub certificate: Vec<u8>,
}
impl ReadData for Certificate {
fn read(reader: &mut impl crate::io::Reader) -> crate::error::Result<Self> {
let length: u32 = reader.read()?;
let cert_data_len = length.saturating_sub(core::mem::size_of_val(&length) as u32) as usize;
let mut cert_data = reader.read_slice(cert_data_len)?;
Ok(Self {
length,
revision: CertificateRevision::from_u16(u16::read(&mut cert_data)?),
certificate_type: CertificateType::from_u16(u16::read(&mut cert_data)?),
certificate: Vec::from(cert_data),
})
}
}