use bitflags::bitflags;
use lief_ffi as ffi;
pub mod attributes;
pub mod content_info;
pub mod rsa_info;
pub mod signer_info;
pub mod x509;
#[doc(inline)]
pub use content_info::ContentInfo;
#[doc(inline)]
pub use rsa_info::RsaInfo;
#[doc(inline)]
pub use signer_info::{AttributeType, SignerInfo, Signers};
#[doc(inline)]
pub use x509::{Certificates, KeyUsage, VerificationFlags as CertVerificationFlags, X509};
use std::io::{Read, Seek};
use crate::common::FromFFI;
use crate::common::into_optional;
use crate::declare_iterator;
use crate::pe::Algorithms;
use crate::to_slice;
use std::marker::PhantomData;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VerificationFlags: u32 {
const OK = 0;
const INVALID_SIGNER = 1 << 0;
const UNSUPPORTED_ALGORITHM = 1 << 1;
const INCONSISTENT_DIGEST_ALGORITHM = 1 << 2;
const CERT_NOT_FOUND = 1 << 3;
const CORRUPTED_CONTENT_INFO = 1 << 4;
const CORRUPTED_AUTH_DATA = 1 << 5;
const MISSING_PKCS9_MESSAGE_DIGEST = 1 << 6;
const BAD_DIGEST = 1 << 7;
const BAD_SIGNATURE = 1 << 8;
const NO_SIGNATURE = 1 << 9;
const CERT_EXPIRED = 1 << 10;
const CERT_FUTURE = 1 << 11;
}
}
impl std::fmt::Display for VerificationFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
bitflags::parser::to_writer(self, f)
}
}
impl From<u32> for VerificationFlags {
fn from(value: u32) -> Self {
VerificationFlags::from_bits_truncate(value)
}
}
impl From<VerificationFlags> for u32 {
fn from(value: VerificationFlags) -> Self {
value.bits()
}
}
impl VerificationFlags {
pub fn is_ok(self) -> bool {
self == VerificationFlags::OK
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VerificationChecks: u32 {
const DEFAULT = 1 << 0;
const HASH_ONLY = 1 << 1;
const LIFETIME_SIGNING = 1 << 2;
const SKIP_CERT_TIME = 1 << 3;
}
}
impl From<u32> for VerificationChecks {
fn from(value: u32) -> Self {
VerificationChecks::from_bits_truncate(value)
}
}
impl From<VerificationChecks> for u32 {
fn from(value: VerificationChecks) -> Self {
value.bits()
}
}
pub struct Signature<'a> {
ptr: cxx::UniquePtr<ffi::PE_Signature>,
_owner: PhantomData<&'a ()>,
}
impl<'b, 'a: 'b> From<&'a Signature<'_>> for &'b ffi::PE_Signature {
fn from(value: &'a Signature<'_>) -> &'b ffi::PE_Signature {
value.ptr.as_ref().unwrap()
}
}
impl std::fmt::Debug for Signature<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Signature").finish()
}
}
impl FromFFI<ffi::PE_Signature> for Signature<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Signature>) -> Self {
Signature {
ptr,
_owner: PhantomData,
}
}
}
impl<'a> Signature<'a> {
pub fn from_file(path: &str) -> Option<Self> {
cxx::let_cxx_string!(__cxx_s = path);
let ffi = ffi::PE_Signature::parse(&__cxx_s);
if ffi.is_null() {
return None;
}
Some(Signature::from_ffi(ffi))
}
pub fn from<R: Read + Seek>(reader: &mut R) -> Option<Self> {
let mut buffer = std::vec::Vec::new();
if reader.read_to_end(&mut buffer).is_err() {
return None;
}
let ffi_stream = unsafe { ffi::PE_Signature::from_raw(buffer.as_mut_ptr(), buffer.len()) };
Some(Signature::from_ffi(ffi_stream))
}
pub fn version(&self) -> u32 {
self.ptr.version()
}
pub fn digest_algorithm(&self) -> Algorithms {
Algorithms::from(self.ptr.digest_algorithm())
}
pub fn content_info(&'a self) -> ContentInfo<'a> {
ContentInfo::from_ffi(self.ptr.content_info())
}
pub fn certificates(&'a self) -> Certificates<'a> {
Certificates::new(self.ptr.certificates())
}
pub fn signers(&'a self) -> Signers<'a> {
Signers::new(self.ptr.signers())
}
pub fn raw_der(&self) -> &[u8] {
to_slice!(self.ptr.raw_der());
}
pub fn crt_by_serial(&self, serial: &[u8]) -> Option<X509<'_>> {
unsafe { into_optional(self.ptr.find_crt_by_serial(serial.as_ptr(), serial.len())) }
}
pub fn crt_by_subject(&self, subject: &str) -> Option<X509<'_>> {
cxx::let_cxx_string!(__cxx_s = subject);
into_optional(self.ptr.find_crt_by_subject(&__cxx_s))
}
pub fn crt_by_subject_and_serial(&self, subject: &str, serial: &[u8]) -> Option<X509<'_>> {
cxx::let_cxx_string!(__cxx_s = subject);
unsafe {
into_optional(self.ptr.find_crt_by_subject_and_serial(
&__cxx_s,
serial.as_ptr(),
serial.len(),
))
}
}
pub fn crt_by_issuer(&self, issuer: &str) -> Option<X509<'_>> {
cxx::let_cxx_string!(__cxx_s = issuer);
into_optional(self.ptr.find_crt_by_issuer(&__cxx_s))
}
pub fn find_crt_by_issuer_and_serial(&self, issuer: &str, serial: &[u8]) -> Option<X509<'_>> {
cxx::let_cxx_string!(__cxx_s = issuer);
unsafe {
into_optional(self.ptr.find_crt_by_issuer_and_serial(
&__cxx_s,
serial.as_ptr(),
serial.len(),
))
}
}
pub fn check(&self, checks: VerificationChecks) -> VerificationFlags {
VerificationFlags::from(self.ptr.check(checks.into()))
}
}
declare_iterator!(
Signatures,
Signature<'a>,
ffi::PE_Signature,
ffi::PE_Binary,
ffi::PE_Binary_it_signatures
);