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::declare_iterator;
7 : use crate::pe::Algorithms;
8 :
9 : use super::{RsaInfo, VerificationFlags};
10 :
11 : /// Structure for a x509 certificate
12 : pub struct X509<'a> {
13 : ptr: cxx::UniquePtr<ffi::PE_x509>,
14 : _owner: PhantomData<&'a ffi::PE_SignerInfo>,
15 : }
16 :
17 : impl std::fmt::Debug for X509<'_> {
18 552 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 552 : f.debug_struct("x509")
20 552 : .field("version", &self.version())
21 552 : .field("signature_algorithm", &self.signature_algorithm())
22 552 : .field("valid_from", &self.valid_from())
23 552 : .field("valid_to", &self.valid_to())
24 552 : .field("issuer", &self.issuer())
25 552 : .field("key_type", &self.key_type())
26 552 : .field("subject", &self.subject())
27 552 : .field("is_ca", &self.is_ca())
28 552 : .finish()
29 552 : }
30 : }
31 :
32 : impl<'a> FromFFI<ffi::PE_x509> for X509<'a> {
33 552 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_x509>) -> Self {
34 552 : X509 {
35 552 : ptr,
36 552 : _owner: PhantomData,
37 552 : }
38 552 : }
39 : }
40 :
41 : #[allow(non_camel_case_types)]
42 552 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
43 : /// Public key scheme
44 : pub enum KeyType {
45 : /// Unknown scheme
46 : NONE,
47 :
48 : /// RSA Scheme
49 : RSA,
50 :
51 : /// Elliptic-curve scheme
52 : ECKEY,
53 :
54 : /// Elliptic-curve Diffie-Hellman
55 : ECKEY_DH,
56 :
57 : /// Elliptic-curve Digital Signature Algorithm
58 : ECDSA,
59 :
60 : /// RSA scheme with an alternative implementation for signing and decrypting
61 : RSA_ALT,
62 :
63 : /// RSA Probabilistic signature scheme
64 : RSASSA_PSS,
65 : UNKNOWN(u32),
66 : }
67 :
68 : impl From<u32> for KeyType {
69 552 : fn from(value: u32) -> Self {
70 552 : match value {
71 0 : 0x00000000 => KeyType::NONE,
72 552 : 0x00000001 => KeyType::RSA,
73 0 : 0x00000002 => KeyType::ECKEY,
74 0 : 0x00000003 => KeyType::ECKEY_DH,
75 0 : 0x00000004 => KeyType::ECDSA,
76 0 : 0x00000005 => KeyType::RSA_ALT,
77 0 : 0x00000006 => KeyType::RSASSA_PSS,
78 0 : _ => KeyType::UNKNOWN(value),
79 : }
80 552 : }
81 : }
82 :
83 : impl X509<'_> {
84 : /// X.509 version. (1=v1, 2=v2, 3=v3)
85 552 : pub fn version(&self) -> u32 {
86 552 : self.ptr.version()
87 552 : }
88 :
89 : /// Unique id for certificate issued by a specific CA.
90 448 : pub fn serial_number(&self) -> Vec<u8> {
91 448 : Vec::from(self.ptr.serial_number().as_slice())
92 448 : }
93 :
94 : /// Signature algorithm (OID)
95 552 : pub fn signature_algorithm(&self) -> String {
96 552 : self.ptr.signature_algorithm().to_string()
97 552 : }
98 :
99 : /// Start time of certificate validity
100 552 : pub fn valid_from(&self) -> Vec<u64> {
101 552 : Vec::from(self.ptr.valid_from().as_slice())
102 552 : }
103 :
104 : /// End time of certificate validity
105 552 : pub fn valid_to(&self) -> Vec<u64> {
106 552 : Vec::from(self.ptr.valid_to().as_slice())
107 552 : }
108 :
109 : /// Issuer information
110 552 : pub fn issuer(&self) -> String {
111 552 : self.ptr.issuer().to_string()
112 552 : }
113 :
114 : /// Subject information
115 552 : pub fn subject(&self) -> String {
116 552 : self.ptr.subject().to_string()
117 552 : }
118 :
119 : /// The raw x509 bytes (DER encoded)
120 448 : pub fn raw(&self) -> Vec<u8> {
121 448 : Vec::from(self.ptr.raw().as_slice())
122 448 : }
123 :
124 : /// Return the underlying public-key scheme
125 552 : pub fn key_type(&self) -> KeyType {
126 552 : KeyType::from(self.ptr.key_type())
127 552 : }
128 552 : pub fn is_ca(&self) -> bool {
129 552 : self.ptr.is_ca()
130 552 : }
131 :
132 : /// The signature of the certificate
133 448 : pub fn signature(&self) -> Vec<u8> {
134 448 : Vec::from(self.ptr.signature().as_slice())
135 448 : }
136 :
137 : /// **If** the underlying public-key scheme is RSA, return the RSA information.
138 448 : pub fn rsa_info(&self) -> Option<RsaInfo> {
139 448 : into_optional(self.ptr.rsa_info())
140 448 : }
141 :
142 : /// Try to decrypt the given signature and check if it matches the given hash according to
143 : /// the hash algorithm provided
144 0 : pub fn check_signature(&self, hash: &[u8], signature: &[u8], digest: Algorithms) -> bool {
145 0 : unsafe {
146 0 : self.ptr.check_signature(
147 0 : hash.as_ptr(),
148 0 : hash.len(),
149 0 : signature.as_ptr(),
150 0 : signature.len(),
151 0 : digest.into(),
152 0 : )
153 0 : }
154 0 : }
155 :
156 : /// Verify that this certificate has been used **to trust** the given certificate
157 0 : pub fn verify(&self, ca: &X509) -> VerificationFlags {
158 0 : VerificationFlags::from(self.ptr.verify(ca.ptr.as_ref().unwrap()))
159 0 : }
160 : }
161 :
162 368 : declare_iterator!(
163 368 : Certificates,
164 368 : X509<'a>,
165 368 : ffi::PE_x509,
166 368 : ffi::PE_Signature,
167 368 : ffi::PE_Signature_it_certificates
168 368 : );
|