LCOV - code coverage report
Current view: top level - src/pe/signature - content_info.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 64.5 % 110 71
Test Date: 2025-06-24:00:00:00 Functions: 58.3 % 24 14

            Line data    Source code
       1              : use std::marker::PhantomData;
       2              : 
       3              : use lief_ffi as ffi;
       4              : 
       5              : use crate::common::{FromFFI, into_optional};
       6              : use crate::to_slice;
       7              : use crate::pe::Algorithms;
       8              : 
       9              : pub struct ContentInfo<'a> {
      10              :     ptr: cxx::UniquePtr<ffi::PE_ContentInfo>,
      11              :     _owner: PhantomData<&'a ffi::PE_Signature>,
      12              : }
      13              : 
      14              : /// ContentInfo as described in the RFC2315 <https://tools.ietf.org/html/rfc2315#section-7>
      15              : impl ContentInfo<'_> {
      16              :     /// Return the OID that describes the content wrapped by this object.
      17              :     /// It should match `SPC_INDIRECT_DATA_OBJID` (`1.3.6.1.4.1.311.2.1.4`)
      18          300 :     pub fn content_type(&self) -> String {
      19          300 :         self.ptr.content_type().to_string()
      20          300 :     }
      21              : 
      22          300 :     pub fn value(&self) -> Option<Content<'_>> {
      23          300 :         into_optional(self.ptr.value())
      24          300 :     }
      25              : 
      26              :     /// Return the digest (authentihash) if the underlying content type is `SPC_INDIRECT_DATA_OBJID`
      27              :     /// Otherwise, return an empty vector
      28            0 :     pub fn digest(&self) -> Vec<u8> {
      29            0 :         Vec::from(self.ptr.digest().as_slice())
      30            0 :     }
      31              : 
      32              :     /// Return the digest used to hash the file
      33            0 :     pub fn digest_algorithm(&self) -> Algorithms {
      34            0 :         Algorithms::from(self.ptr.digest_algorithm())
      35            0 :     }
      36              : }
      37              : 
      38              : impl std::fmt::Debug for ContentInfo<'_> {
      39          300 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      40          300 :         f.debug_struct("ContentInfo")
      41          300 :             .field("content_type", &self.content_type())
      42          300 :             .finish()
      43          300 :     }
      44              : }
      45              : 
      46              : impl<'a> FromFFI<ffi::PE_ContentInfo> for ContentInfo<'a> {
      47          600 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ContentInfo>) -> Self {
      48          600 :         ContentInfo {
      49          600 :             ptr,
      50          600 :             _owner: PhantomData,
      51          600 :         }
      52          600 :     }
      53              : }
      54              : 
      55          300 : #[derive(Debug)]
      56              : pub enum Content<'a> {
      57              :     SpcIndirectData(SpcIndirectData<'a>),
      58              :     PKCS9TSTInfo(PKCS9TSTInfo<'a>),
      59              :     Generic(Generic<'a>),
      60              : }
      61              : 
      62              : impl<'a> FromFFI<ffi::PE_ContentInfo_Content> for Content<'a> {
      63          300 :     fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_ContentInfo_Content>) -> Self {
      64          300 :         unsafe {
      65          300 :             let content_ref = ffi_entry.as_ref().unwrap();
      66          300 :             if ffi::PE_SpcIndirectData::classof(content_ref) {
      67          192 :                 let raw = {
      68          192 :                     type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
      69          192 :                     type To = cxx::UniquePtr<ffi::PE_SpcIndirectData>;
      70          192 :                     std::mem::transmute::<From, To>(ffi_entry)
      71          192 :                 };
      72          192 :                 Content::SpcIndirectData(SpcIndirectData::from_ffi(raw))
      73              :             }
      74          108 :             else if ffi::PE_PKCS9TSTInfo::classof(content_ref) {
      75          108 :                 let raw = {
      76          108 :                     type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
      77          108 :                     type To = cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>;
      78          108 :                     std::mem::transmute::<From, To>(ffi_entry)
      79          108 :                 };
      80          108 :                 Content::PKCS9TSTInfo(PKCS9TSTInfo::from_ffi(raw))
      81              :             } else {
      82            0 :                 let raw = {
      83            0 :                     type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
      84            0 :                     type To = cxx::UniquePtr<ffi::PE_GenericContent>;
      85            0 :                     std::mem::transmute::<From, To>(ffi_entry)
      86            0 :                 };
      87            0 :                 Content::Generic(Generic::from_ffi(raw))
      88              :             }
      89              :         }
      90          300 :     }
      91              : }
      92              : 
      93              : pub trait ContentTrait {
      94              :     #[doc(hidden)]
      95              :     fn as_generic(&self) -> &ffi::PE_ContentInfo_Content;
      96              : 
      97              :     /// Return the OID that describes this content info.
      98              :     /// In the case of the PE authenticode, it should return `SPC_INDIRECT_DATA_OBJID (1.3.6.1.4.1.311.2.1.4)`
      99            0 :     fn content_type(&self) -> String {
     100            0 :         self.as_generic().content_type().to_string()
     101            0 :     }
     102              : }
     103              : 
     104              : pub struct SpcIndirectData<'a> {
     105              :     ptr: cxx::UniquePtr<ffi::PE_SpcIndirectData>,
     106              :     _owner: PhantomData<&'a ffi::PE_ContentInfo>,
     107              : }
     108              : 
     109              : impl SpcIndirectData<'_> {
     110          384 :     pub fn file(&self) -> String {
     111          384 :         self.ptr.file().to_string()
     112          384 :     }
     113              : 
     114          384 :     pub fn url(&self) -> String {
     115          384 :         self.ptr.url().to_string()
     116          384 :     }
     117              : 
     118              :     /// PE's authentihash
     119              :     ///
     120              :     /// See: [`crate::pe::Binary::authentihash`]
     121          192 :     pub fn digest(&self) -> &[u8] {
     122          192 :         to_slice!(self.ptr.digest());
     123          192 :     }
     124              : 
     125              :     /// Digest used to hash the file
     126          384 :     pub fn digest_algorithm(&self) -> Algorithms {
     127          384 :         Algorithms::from(self.ptr.digest_algorithm())
     128          384 :     }
     129              : }
     130              : 
     131              : impl std::fmt::Debug for SpcIndirectData<'_> {
     132          384 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     133          384 :         f.debug_struct("SpcIndirectData")
     134          384 :             .field("file", &self.file())
     135          384 :             .field("url", &self.url())
     136          384 :             .field("digest_algorithm", &self.digest_algorithm())
     137          384 :             .finish()
     138          384 :     }
     139              : }
     140              : 
     141              : impl FromFFI<ffi::PE_SpcIndirectData> for SpcIndirectData<'_> {
     142          192 :     fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_SpcIndirectData>) -> Self {
     143          192 :         Self {
     144          192 :             ptr: cmd,
     145          192 :             _owner: PhantomData,
     146          192 :         }
     147          192 :     }
     148              : }
     149              : 
     150              : impl ContentTrait for SpcIndirectData<'_> {
     151            0 :     fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
     152            0 :         self.ptr.as_ref().unwrap().as_ref()
     153            0 :     }
     154              : }
     155              : 
     156              : pub struct PKCS9TSTInfo<'a> {
     157              :     ptr: cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>,
     158              :     _owner: PhantomData<&'a ffi::PE_ContentInfo>,
     159              : }
     160              : 
     161              : impl PKCS9TSTInfo<'_> {
     162              :     // TODO(romain): Add API
     163              : }
     164              : 
     165              : impl std::fmt::Debug for PKCS9TSTInfo<'_> {
     166          108 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     167          108 :         f.debug_struct("PKCS9TSTInfo")
     168          108 :             .finish()
     169          108 :     }
     170              : }
     171              : 
     172              : impl FromFFI<ffi::PE_PKCS9TSTInfo> for PKCS9TSTInfo<'_> {
     173          108 :     fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>) -> Self {
     174          108 :         Self {
     175          108 :             ptr: cmd,
     176          108 :             _owner: PhantomData,
     177          108 :         }
     178          108 :     }
     179              : }
     180              : 
     181              : impl ContentTrait for PKCS9TSTInfo<'_> {
     182            0 :     fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
     183            0 :         self.ptr.as_ref().unwrap().as_ref()
     184            0 :     }
     185              : }
     186              : 
     187              : 
     188              : pub struct Generic<'a> {
     189              :     ptr: cxx::UniquePtr<ffi::PE_GenericContent>,
     190              :     _owner: PhantomData<&'a ffi::PE_ContentInfo>,
     191              : }
     192              : 
     193              : impl Generic<'_> {
     194            0 :     pub fn raw(&self) -> &[u8] {
     195            0 :         to_slice!(self.ptr.raw());
     196            0 :     }
     197              : 
     198            0 :     pub fn oid(&self) -> String {
     199            0 :         self.ptr.oid().to_string()
     200            0 :     }
     201              : 
     202              : }
     203              : 
     204              : impl std::fmt::Debug for Generic<'_> {
     205            0 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     206            0 :         f.debug_struct("Generic").finish()
     207            0 :     }
     208              : }
     209              : 
     210              : impl FromFFI<ffi::PE_GenericContent> for Generic<'_> {
     211            0 :     fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_GenericContent>) -> Self {
     212            0 :         Self {
     213            0 :             ptr: cmd,
     214            0 :             _owner: PhantomData,
     215            0 :         }
     216            0 :     }
     217              : }
     218              : 
     219              : impl ContentTrait for Generic<'_> {
     220            0 :     fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
     221            0 :         self.ptr.as_ref().unwrap().as_ref()
     222            0 :     }
     223              : }
     224              : 
        

Generated by: LCOV version 2.1-1