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-02-23: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          250 :     pub fn content_type(&self) -> String {
      19          250 :         self.ptr.content_type().to_string()
      20          250 :     }
      21              : 
      22          250 :     pub fn value(&self) -> Option<Content<'_>> {
      23          250 :         into_optional(self.ptr.value())
      24          250 :     }
      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          250 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      40          250 :         f.debug_struct("ContentInfo")
      41          250 :             .field("content_type", &self.content_type())
      42          250 :             .finish()
      43          250 :     }
      44              : }
      45              : 
      46              : impl<'a> FromFFI<ffi::PE_ContentInfo> for ContentInfo<'a> {
      47          500 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ContentInfo>) -> Self {
      48          500 :         ContentInfo {
      49          500 :             ptr,
      50          500 :             _owner: PhantomData,
      51          500 :         }
      52          500 :     }
      53              : }
      54              : 
      55          250 : #[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          250 :     fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_ContentInfo_Content>) -> Self {
      64          250 :         unsafe {
      65          250 :             let content_ref = ffi_entry.as_ref().unwrap();
      66          250 :             if ffi::PE_SpcIndirectData::classof(content_ref) {
      67          160 :                 let raw = {
      68          160 :                     type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
      69          160 :                     type To = cxx::UniquePtr<ffi::PE_SpcIndirectData>;
      70          160 :                     std::mem::transmute::<From, To>(ffi_entry)
      71          160 :                 };
      72          160 :                 Content::SpcIndirectData(SpcIndirectData::from_ffi(raw))
      73              :             }
      74           90 :             else if ffi::PE_PKCS9TSTInfo::classof(content_ref) {
      75           90 :                 let raw = {
      76           90 :                     type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
      77           90 :                     type To = cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>;
      78           90 :                     std::mem::transmute::<From, To>(ffi_entry)
      79           90 :                 };
      80           90 :                 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          250 :     }
      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          320 :     pub fn file(&self) -> String {
     111          320 :         self.ptr.file().to_string()
     112          320 :     }
     113              : 
     114          320 :     pub fn url(&self) -> String {
     115          320 :         self.ptr.url().to_string()
     116          320 :     }
     117              : 
     118              :     /// PE's authentihash
     119              :     ///
     120              :     /// See: [`crate::pe::Binary::authentihash`]
     121          160 :     pub fn digest(&self) -> &[u8] {
     122          160 :         to_slice!(self.ptr.digest());
     123          160 :     }
     124              : 
     125              :     /// Digest used to hash the file
     126          320 :     pub fn digest_algorithm(&self) -> Algorithms {
     127          320 :         Algorithms::from(self.ptr.digest_algorithm())
     128          320 :     }
     129              : }
     130              : 
     131              : impl std::fmt::Debug for SpcIndirectData<'_> {
     132          320 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     133          320 :         f.debug_struct("SpcIndirectData")
     134          320 :             .field("file", &self.file())
     135          320 :             .field("url", &self.url())
     136          320 :             .field("digest_algorithm", &self.digest_algorithm())
     137          320 :             .finish()
     138          320 :     }
     139              : }
     140              : 
     141              : impl FromFFI<ffi::PE_SpcIndirectData> for SpcIndirectData<'_> {
     142          160 :     fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_SpcIndirectData>) -> Self {
     143          160 :         Self {
     144          160 :             ptr: cmd,
     145          160 :             _owner: PhantomData,
     146          160 :         }
     147          160 :     }
     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           90 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     167           90 :         f.debug_struct("PKCS9TSTInfo")
     168           90 :             .finish()
     169           90 :     }
     170              : }
     171              : 
     172              : impl FromFFI<ffi::PE_PKCS9TSTInfo> for PKCS9TSTInfo<'_> {
     173           90 :     fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>) -> Self {
     174           90 :         Self {
     175           90 :             ptr: cmd,
     176           90 :             _owner: PhantomData,
     177           90 :         }
     178           90 :     }
     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