LCOV - code coverage report
Current view: top level - src/pe/signature - x509.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 37.9 % 174 66
Test Date: 2026-04-12:00:00:00 Functions: 37.8 % 45 17

            Line data    Source code
       1              : use std::marker::PhantomData;
       2              : 
       3              : use bitflags::bitflags;
       4              : use lief_ffi as ffi;
       5              : 
       6              : use crate::common::{into_optional, FromFFI};
       7              : use crate::declare_iterator;
       8              : use crate::pe::Algorithms;
       9              : 
      10              : use super::RsaInfo;
      11              : 
      12              : /// Structure for a x509 certificate
      13              : pub struct X509<'a> {
      14              :     ptr: cxx::UniquePtr<ffi::PE_x509>,
      15              :     _owner: PhantomData<&'a ffi::PE_SignerInfo>,
      16              : }
      17              : 
      18              : impl std::fmt::Debug for X509<'_> {
      19         1092 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      20         1092 :         f.debug_struct("x509")
      21         1092 :             .field("version", &self.version())
      22         1092 :             .field("signature_algorithm", &self.signature_algorithm())
      23         1092 :             .field("valid_from", &self.valid_from())
      24         1092 :             .field("valid_to", &self.valid_to())
      25         1092 :             .field("issuer", &self.issuer())
      26         1092 :             .field("key_type", &self.key_type())
      27         1092 :             .field("subject", &self.subject())
      28         1092 :             .field("is_ca", &self.is_ca())
      29         1092 :             .finish()
      30         1092 :     }
      31              : }
      32              : 
      33              : impl<'a> FromFFI<ffi::PE_x509> for X509<'a> {
      34         1092 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_x509>) -> Self {
      35         1092 :         X509 {
      36         1092 :             ptr,
      37         1092 :             _owner: PhantomData,
      38         1092 :         }
      39         1092 :     }
      40              : }
      41              : 
      42              : #[allow(non_camel_case_types)]
      43         1092 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
      44              : /// Public key scheme
      45              : pub enum KeyType {
      46              :     /// Unknown scheme
      47              :     NONE,
      48              : 
      49              :     /// RSA Scheme
      50              :     RSA,
      51              : 
      52              :     /// Elliptic-curve scheme
      53              :     ECKEY,
      54              : 
      55              :     /// Elliptic-curve Diffie-Hellman
      56              :     ECKEY_DH,
      57              : 
      58              :     /// Elliptic-curve Digital Signature Algorithm
      59              :     ECDSA,
      60              : 
      61              :     /// RSA scheme with an alternative implementation for signing and decrypting
      62              :     RSA_ALT,
      63              : 
      64              :     /// RSA Probabilistic signature scheme
      65              :     RSASSA_PSS,
      66              :     UNKNOWN(u32),
      67              : }
      68              : 
      69              : impl From<u32> for KeyType {
      70         1092 :     fn from(value: u32) -> Self {
      71         1092 :         match value {
      72            0 :             0x00000000 => KeyType::NONE,
      73         1092 :             0x00000001 => KeyType::RSA,
      74            0 :             0x00000002 => KeyType::ECKEY,
      75            0 :             0x00000003 => KeyType::ECKEY_DH,
      76            0 :             0x00000004 => KeyType::ECDSA,
      77            0 :             0x00000005 => KeyType::RSA_ALT,
      78            0 :             0x00000006 => KeyType::RSASSA_PSS,
      79            0 :             _ => KeyType::UNKNOWN(value),
      80              :         }
      81         1092 :     }
      82              : }
      83              : 
      84              : /// Key usage as defined in RFC #5280 - section-4.2.1.3
      85              : #[allow(non_camel_case_types)]
      86            0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
      87              : pub enum KeyUsage {
      88              :     /// The key is used for digital signature
      89              :     DIGITAL_SIGNATURE,
      90              :     /// The key is used for digital signature and to protect against falsely denying some action
      91              :     NON_REPUDIATION,
      92              :     /// The key is used for enciphering private or secret keys
      93              :     KEY_ENCIPHERMENT,
      94              :     /// The key is used for directly enciphering raw user data without an intermediate symmetric cipher
      95              :     DATA_ENCIPHERMENT,
      96              :     /// The key is used for key agreement (e.g. with Diffie-Hellman)
      97              :     KEY_AGREEMENT,
      98              :     /// The key is used for verifying signatures on public key certificates
      99              :     KEY_CERT_SIGN,
     100              :     /// The key is used for verifying signatures on certificate revocation lists
     101              :     CRL_SIGN,
     102              :     /// In association with KEY_AGREEMENT, the key is only used for enciphering data
     103              :     ENCIPHER_ONLY,
     104              :     /// In association with KEY_AGREEMENT, the key is only used for deciphering data
     105              :     DECIPHER_ONLY,
     106              :     UNKNOWN(u32),
     107              : }
     108              : 
     109              : impl From<u32> for KeyUsage {
     110            0 :     fn from(value: u32) -> Self {
     111            0 :         match value {
     112            0 :             0x00000000 => KeyUsage::DIGITAL_SIGNATURE,
     113            0 :             0x00000001 => KeyUsage::NON_REPUDIATION,
     114            0 :             0x00000002 => KeyUsage::KEY_ENCIPHERMENT,
     115            0 :             0x00000003 => KeyUsage::DATA_ENCIPHERMENT,
     116            0 :             0x00000004 => KeyUsage::KEY_AGREEMENT,
     117            0 :             0x00000005 => KeyUsage::KEY_CERT_SIGN,
     118            0 :             0x00000006 => KeyUsage::CRL_SIGN,
     119            0 :             0x00000007 => KeyUsage::ENCIPHER_ONLY,
     120            0 :             0x00000008 => KeyUsage::DECIPHER_ONLY,
     121            0 :             _ => KeyUsage::UNKNOWN(value),
     122              :         }
     123            0 :     }
     124              : }
     125              : 
     126              : impl From<KeyUsage> for u32 {
     127            0 :     fn from(value: KeyUsage) -> u32 {
     128            0 :         match value {
     129            0 :             KeyUsage::DIGITAL_SIGNATURE => 0x00000000,
     130            0 :             KeyUsage::NON_REPUDIATION => 0x00000001,
     131            0 :             KeyUsage::KEY_ENCIPHERMENT => 0x00000002,
     132            0 :             KeyUsage::DATA_ENCIPHERMENT => 0x00000003,
     133            0 :             KeyUsage::KEY_AGREEMENT => 0x00000004,
     134            0 :             KeyUsage::KEY_CERT_SIGN => 0x00000005,
     135            0 :             KeyUsage::CRL_SIGN => 0x00000006,
     136            0 :             KeyUsage::ENCIPHER_ONLY => 0x00000007,
     137            0 :             KeyUsage::DECIPHER_ONLY => 0x00000008,
     138            0 :             KeyUsage::UNKNOWN(v) => v,
     139              :         }
     140            0 :     }
     141              : }
     142              : 
     143            0 : bitflags! {
     144            0 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     145            0 :     /// Mirror of mbedtls X509 verification flags for certificate verification
     146            0 :     pub struct VerificationFlags: u32 {
     147            0 :         const OK = 0;
     148            0 :         const BADCERT_EXPIRED = 1 << 0;
     149            0 :         const BADCERT_REVOKED = 1 << 1;
     150            0 :         const BADCERT_CN_MISMATCH = 1 << 2;
     151            0 :         const BADCERT_NOT_TRUSTED = 1 << 3;
     152            0 :         const BADCRL_NOT_TRUSTED = 1 << 4;
     153            0 :         const BADCRL_EXPIRED = 1 << 5;
     154            0 :         const BADCERT_MISSING = 1 << 6;
     155            0 :         const BADCERT_SKIP_VERIFY = 1 << 7;
     156            0 :         const BADCERT_OTHER = 1 << 8;
     157            0 :         const BADCERT_FUTURE = 1 << 9;
     158            0 :         const BADCRL_FUTURE = 1 << 10;
     159            0 :         const BADCERT_KEY_USAGE = 1 << 11;
     160            0 :         const BADCERT_EXT_KEY_USAGE = 1 << 12;
     161            0 :         const BADCERT_NS_CERT_TYPE = 1 << 13;
     162            0 :         const BADCERT_BAD_MD = 1 << 14;
     163            0 :         const BADCERT_BAD_PK = 1 << 15;
     164            0 :         const BADCERT_BAD_KEY = 1 << 16;
     165            0 :         const BADCRL_BAD_MD = 1 << 17;
     166            0 :         const BADCRL_BAD_PK = 1 << 18;
     167            0 :         const BADCRL_BAD_KEY = 1 << 19;
     168            0 :     }
     169            0 : }
     170              : 
     171              : impl std::fmt::Display for VerificationFlags {
     172            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
     173            0 :         bitflags::parser::to_writer(self, f)
     174            0 :     }
     175              : }
     176              : 
     177              : impl From<u32> for VerificationFlags {
     178            0 :     fn from(value: u32) -> Self {
     179            0 :         VerificationFlags::from_bits_truncate(value)
     180            0 :     }
     181              : }
     182              : 
     183              : impl From<VerificationFlags> for u32 {
     184            0 :     fn from(value: VerificationFlags) -> Self {
     185            0 :         value.bits()
     186            0 :     }
     187              : }
     188              : 
     189              : impl VerificationFlags {
     190            0 :     pub fn is_ok(self) -> bool {
     191            0 :         self == VerificationFlags::OK
     192            0 :     }
     193              : }
     194              : 
     195              : impl X509<'_> {
     196              :     /// X.509 version. (1=v1, 2=v2, 3=v3)
     197         1092 :     pub fn version(&self) -> u32 {
     198         1092 :         self.ptr.version()
     199         1092 :     }
     200              : 
     201              :     /// Unique id for certificate issued by a specific CA.
     202          884 :     pub fn serial_number(&self) -> Vec<u8> {
     203          884 :         Vec::from(self.ptr.serial_number().as_slice())
     204          884 :     }
     205              : 
     206              :     /// Signature algorithm (OID)
     207         1092 :     pub fn signature_algorithm(&self) -> String {
     208         1092 :         self.ptr.signature_algorithm().to_string()
     209         1092 :     }
     210              : 
     211              :     /// Start time of certificate validity
     212         1092 :     pub fn valid_from(&self) -> Vec<u64> {
     213         1092 :         Vec::from(self.ptr.valid_from().as_slice())
     214         1092 :     }
     215              : 
     216              :     /// End time of certificate validity
     217         1092 :     pub fn valid_to(&self) -> Vec<u64> {
     218         1092 :         Vec::from(self.ptr.valid_to().as_slice())
     219         1092 :     }
     220              : 
     221              :     /// Issuer information
     222         1092 :     pub fn issuer(&self) -> String {
     223         1092 :         self.ptr.issuer().to_string()
     224         1092 :     }
     225              : 
     226              :     /// Subject information
     227         1092 :     pub fn subject(&self) -> String {
     228         1092 :         self.ptr.subject().to_string()
     229         1092 :     }
     230              : 
     231              :     /// The raw x509 bytes (DER encoded)
     232          884 :     pub fn raw(&self) -> Vec<u8> {
     233          884 :         Vec::from(self.ptr.raw().as_slice())
     234          884 :     }
     235              : 
     236              :     /// Return the underlying public-key scheme
     237         1092 :     pub fn key_type(&self) -> KeyType {
     238         1092 :         KeyType::from(self.ptr.key_type())
     239         1092 :     }
     240         1092 :     pub fn is_ca(&self) -> bool {
     241         1092 :         self.ptr.is_ca()
     242         1092 :     }
     243              : 
     244              :     /// The signature of the certificate
     245          884 :     pub fn signature(&self) -> Vec<u8> {
     246          884 :         Vec::from(self.ptr.signature().as_slice())
     247          884 :     }
     248              : 
     249              :     /// **If** the underlying public-key scheme is RSA, return the RSA information.
     250          884 :     pub fn rsa_info(&self) -> Option<RsaInfo<'_>> {
     251          884 :         into_optional(self.ptr.rsa_info())
     252          884 :     }
     253              : 
     254              :     /// Try to decrypt the given signature and check if it matches the given hash according to
     255              :     /// the hash algorithm provided
     256            0 :     pub fn check_signature(&self, hash: &[u8], signature: &[u8], digest: Algorithms) -> bool {
     257            0 :         unsafe {
     258            0 :             self.ptr.check_signature(
     259            0 :                 hash.as_ptr(),
     260            0 :                 hash.len(),
     261            0 :                 signature.as_ptr(),
     262            0 :                 signature.len(),
     263            0 :                 digest.into(),
     264            0 :             )
     265            0 :         }
     266            0 :     }
     267              : 
     268              :     /// Verify that this certificate has been used **to trust** the given certificate
     269            0 :     pub fn verify(&self, ca: &X509) -> VerificationFlags {
     270            0 :         VerificationFlags::from(self.ptr.verify(ca.ptr.as_ref().unwrap()))
     271            0 :     }
     272              : 
     273              :     /// Return the key usage extensions of this certificate
     274            0 :     pub fn key_usage(&self) -> Vec<KeyUsage> {
     275            0 :         self.ptr
     276            0 :             .key_usage()
     277            0 :             .into_iter()
     278            0 :             .map(|e| KeyUsage::from(*e))
     279            0 :             .collect()
     280            0 :     }
     281              : 
     282              :     /// Return the extended key usage OIDs of this certificate
     283            0 :     pub fn ext_key_usage(&self) -> Vec<String> {
     284            0 :         self.ptr
     285            0 :             .ext_key_usage()
     286            0 :             .into_iter()
     287            0 :             .map(|e| e.to_string())
     288            0 :             .collect()
     289            0 :     }
     290              : 
     291              :     /// Return the certificate policies OIDs of this certificate
     292            0 :     pub fn certificate_policies(&self) -> Vec<String> {
     293            0 :         self.ptr
     294            0 :             .certificate_policies()
     295            0 :             .into_iter()
     296            0 :             .map(|e| e.to_string())
     297            0 :             .collect()
     298            0 :     }
     299              : }
     300              : 
     301          676 : declare_iterator!(
     302          676 :     Certificates,
     303          676 :     X509<'a>,
     304          676 :     ffi::PE_x509,
     305          676 :     ffi::PE_Signature,
     306          676 :     ffi::PE_Signature_it_certificates
     307          676 : );
        

Generated by: LCOV version 2.1-1