LCOV - code coverage report
Current view: top level - src/pe/signature - content_info.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 64.2 % 109 70
Test Date: 2026-04-12: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::{into_optional, FromFFI};
       6              : use crate::pe::Algorithms;
       7              : use crate::to_slice;
       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          325 :     pub fn content_type(&self) -> String {
      19          325 :         self.ptr.content_type().to_string()
      20          325 :     }
      21              : 
      22          325 :     pub fn value(&self) -> Option<Content<'_>> {
      23          325 :         into_optional(self.ptr.value())
      24          325 :     }
      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          325 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      40          325 :         f.debug_struct("ContentInfo")
      41          325 :             .field("content_type", &self.content_type())
      42          325 :             .finish()
      43          325 :     }
      44              : }
      45              : 
      46              : impl<'a> FromFFI<ffi::PE_ContentInfo> for ContentInfo<'a> {
      47          650 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ContentInfo>) -> Self {
      48          650 :         ContentInfo {
      49          650 :             ptr,
      50          650 :             _owner: PhantomData,
      51          650 :         }
      52          650 :     }
      53              : }
      54              : 
      55          325 : #[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          325 :     fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_ContentInfo_Content>) -> Self {
      64          325 :         unsafe {
      65          325 :             let content_ref = ffi_entry.as_ref().unwrap();
      66          325 :             if ffi::PE_SpcIndirectData::classof(content_ref) {
      67          208 :                 let raw = {
      68          208 :                     type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
      69          208 :                     type To = cxx::UniquePtr<ffi::PE_SpcIndirectData>;
      70          208 :                     std::mem::transmute::<From, To>(ffi_entry)
      71          208 :                 };
      72          208 :                 Content::SpcIndirectData(SpcIndirectData::from_ffi(raw))
      73          117 :             } else if ffi::PE_PKCS9TSTInfo::classof(content_ref) {
      74          117 :                 let raw = {
      75          117 :                     type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
      76          117 :                     type To = cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>;
      77          117 :                     std::mem::transmute::<From, To>(ffi_entry)
      78          117 :                 };
      79          117 :                 Content::PKCS9TSTInfo(PKCS9TSTInfo::from_ffi(raw))
      80              :             } else {
      81            0 :                 let raw = {
      82            0 :                     type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
      83            0 :                     type To = cxx::UniquePtr<ffi::PE_GenericContent>;
      84            0 :                     std::mem::transmute::<From, To>(ffi_entry)
      85            0 :                 };
      86            0 :                 Content::Generic(Generic::from_ffi(raw))
      87              :             }
      88              :         }
      89          325 :     }
      90              : }
      91              : 
      92              : pub trait ContentTrait {
      93              :     #[doc(hidden)]
      94              :     fn as_generic(&self) -> &ffi::PE_ContentInfo_Content;
      95              : 
      96              :     /// Return the OID that describes this content info.
      97              :     /// In the case of the PE authenticode, it should return `SPC_INDIRECT_DATA_OBJID (1.3.6.1.4.1.311.2.1.4)`
      98            0 :     fn content_type(&self) -> String {
      99            0 :         self.as_generic().content_type().to_string()
     100            0 :     }
     101              : }
     102              : 
     103              : pub struct SpcIndirectData<'a> {
     104              :     ptr: cxx::UniquePtr<ffi::PE_SpcIndirectData>,
     105              :     _owner: PhantomData<&'a ffi::PE_ContentInfo>,
     106              : }
     107              : 
     108              : impl SpcIndirectData<'_> {
     109          416 :     pub fn file(&self) -> String {
     110          416 :         self.ptr.file().to_string()
     111          416 :     }
     112              : 
     113          416 :     pub fn url(&self) -> String {
     114          416 :         self.ptr.url().to_string()
     115          416 :     }
     116              : 
     117              :     /// PE's authentihash
     118              :     ///
     119              :     /// See: [`crate::pe::Binary::authentihash`]
     120          208 :     pub fn digest(&self) -> &[u8] {
     121          208 :         to_slice!(self.ptr.digest());
     122          208 :     }
     123              : 
     124              :     /// Digest used to hash the file
     125          416 :     pub fn digest_algorithm(&self) -> Algorithms {
     126          416 :         Algorithms::from(self.ptr.digest_algorithm())
     127          416 :     }
     128              : }
     129              : 
     130              : impl std::fmt::Debug for SpcIndirectData<'_> {
     131          416 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     132          416 :         f.debug_struct("SpcIndirectData")
     133          416 :             .field("file", &self.file())
     134          416 :             .field("url", &self.url())
     135          416 :             .field("digest_algorithm", &self.digest_algorithm())
     136          416 :             .finish()
     137          416 :     }
     138              : }
     139              : 
     140              : impl FromFFI<ffi::PE_SpcIndirectData> for SpcIndirectData<'_> {
     141          208 :     fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_SpcIndirectData>) -> Self {
     142          208 :         Self {
     143          208 :             ptr: cmd,
     144          208 :             _owner: PhantomData,
     145          208 :         }
     146          208 :     }
     147              : }
     148              : 
     149              : impl ContentTrait for SpcIndirectData<'_> {
     150            0 :     fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
     151            0 :         self.ptr.as_ref().unwrap().as_ref()
     152            0 :     }
     153              : }
     154              : 
     155              : pub struct PKCS9TSTInfo<'a> {
     156              :     ptr: cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>,
     157              :     _owner: PhantomData<&'a ffi::PE_ContentInfo>,
     158              : }
     159              : 
     160              : impl PKCS9TSTInfo<'_> {
     161              :     // TODO(romain): Add API
     162              : }
     163              : 
     164              : impl std::fmt::Debug for PKCS9TSTInfo<'_> {
     165          117 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     166          117 :         f.debug_struct("PKCS9TSTInfo").finish()
     167          117 :     }
     168              : }
     169              : 
     170              : impl FromFFI<ffi::PE_PKCS9TSTInfo> for PKCS9TSTInfo<'_> {
     171          117 :     fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>) -> Self {
     172          117 :         Self {
     173          117 :             ptr: cmd,
     174          117 :             _owner: PhantomData,
     175          117 :         }
     176          117 :     }
     177              : }
     178              : 
     179              : impl ContentTrait for PKCS9TSTInfo<'_> {
     180            0 :     fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
     181            0 :         self.ptr.as_ref().unwrap().as_ref()
     182            0 :     }
     183              : }
     184              : 
     185              : pub struct Generic<'a> {
     186              :     ptr: cxx::UniquePtr<ffi::PE_GenericContent>,
     187              :     _owner: PhantomData<&'a ffi::PE_ContentInfo>,
     188              : }
     189              : 
     190              : impl Generic<'_> {
     191            0 :     pub fn raw(&self) -> &[u8] {
     192            0 :         to_slice!(self.ptr.raw());
     193            0 :     }
     194              : 
     195            0 :     pub fn oid(&self) -> String {
     196            0 :         self.ptr.oid().to_string()
     197            0 :     }
     198              : }
     199              : 
     200              : impl std::fmt::Debug for Generic<'_> {
     201            0 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     202            0 :         f.debug_struct("Generic").finish()
     203            0 :     }
     204              : }
     205              : 
     206              : impl FromFFI<ffi::PE_GenericContent> for Generic<'_> {
     207            0 :     fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_GenericContent>) -> Self {
     208            0 :         Self {
     209            0 :             ptr: cmd,
     210            0 :             _owner: PhantomData,
     211            0 :         }
     212            0 :     }
     213              : }
     214              : 
     215              : impl ContentTrait for Generic<'_> {
     216            0 :     fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
     217            0 :         self.ptr.as_ref().unwrap().as_ref()
     218            0 :     }
     219              : }
        

Generated by: LCOV version 2.1-1