///|
/// The certificate table (data-directory slot 4).
///
/// This is the one directory whose `VirtualAddress` is a **file offset**, not an
/// RVA — a documented PE quirk that a naive reader gets wrong. Each entry is a
/// `WIN_CERTIFICATE`: length, revision and type, padded to eight bytes.
///
/// The certificate bytes are not verified here; that would require a full
/// Authenticode implementation. Reading the table answers "is a signature
/// embedded, and what kind".
///|
pub(all) struct Certificate {
length : Int32
revision : Int32
kind : Int32
} derive(@debug.Debug)
///|
/// Walk the certificate table.
pub fn Pe::certificates(self : Pe) -> Array[Certificate] raise PeError {
let out : Array[Certificate] = []
let directory = match self.directory(4) {
None => return out
Some(directory) => directory
}
if directory.size == 0 || directory.virtual_address == 0 {
return out
}
// Slot 4 stores a file offset in the address field.
let mut offset = directory.virtual_address
let end = offset + directory.size
if end > self.bytes.length() {
raise PeError::Malformed(
"certificate table extends past the end of the file", offset,
)
}
let mut count = 0
while offset + 8 <= end && count < 1024 {
let reader = Reader::at(self.bytes, offset)
let length = reader.u32()
let revision = reader.u16()
let kind = reader.u16()
if length < 8 {
break
}
out.push({ length, revision, kind, })
let advance = (length + 7) / 8 * 8
offset = offset + advance
count = count + 1
}
out
}