certain_certificate/
certificate.rs

1use std::{
2    
3    fmt::{
4
5        Formatter as FmtFormatter,
6        Result as FmtResult,
7        Debug as FmtDebug,
8    },
9
10    time::{SystemTime},
11    net::{IpAddr},
12};
13
14use chrono::{
15    
16    NaiveDateTime,
17    DateTime, 
18    Utc,
19};
20
21use rustls_native_certs::{Certificate as TlsNativeCertificate};
22
23use rustls::{
24
25    server::{
26        AllowAnyAuthenticatedClient as TlsAllowAnyAuthenticatedClient, 
27        ClientCertVerifier as TlsClientCertVerifier,
28    },
29
30    OwnedTrustAnchor as TlsOwnedTrustAnchor,
31    RootCertStore as TlsRootCertStore,
32    Certificate as TlsCertificate,
33};
34
35use serde::{
36
37    Deserialize, 
38    Serialize,
39};
40
41use webpki_roots::{TLS_SERVER_ROOTS};
42
43use x509_parser::prelude::{
44
45    X509Certificate, 
46    TbsCertificate, 
47    GeneralName, 
48    FromDer,
49};
50
51#[derive(Clone, Copy, Debug)]
52#[derive(Serialize, Deserialize)]
53pub struct CertificateValidity {
54    begin: DateTime<Utc>,
55    end: DateTime<Utc>,
56}
57
58impl CertificateValidity {
59    pub(crate) fn from_timestamps(begin: i64, end: i64) -> CertificateValidity {
60        CertificateValidity { 
61            begin: DateTime::from_utc(NaiveDateTime::from_timestamp_opt(begin.min(end), 0)
62                .unwrap_or_default(), Utc), 
63            end: DateTime::from_utc(NaiveDateTime::from_timestamp_opt(end.max(begin), 0)
64                .unwrap_or_default(), Utc), 
65        }
66    }
67
68    pub fn is_within_valid_time(&self) -> bool {
69        let now = Utc::now();
70
71        if self.end > now {
72            if self.begin < now {
73                return true
74            }
75        }
76
77        false
78    }
79
80    pub fn timestamp_begin(&self) -> i64 {
81        self.begin.timestamp()
82    }
83
84    pub fn time_begin(&self) -> DateTime<Utc> {
85        self.begin.clone()
86    }
87
88    pub fn timestamp_end(&self) -> i64 {
89        self.end.timestamp()
90    }
91
92    pub fn time_end(&self) -> DateTime<Utc> {
93        self.end.clone()
94    }
95}
96
97#[derive(Clone, Debug)]
98#[derive(Serialize, Deserialize)]
99pub enum CertificateAlternateName {
100    Directory(String),
101    Hostname(String),
102    Address(String),
103    Email(String),
104    Uri(String),
105}
106
107impl<'a> CertificateAlternateName {
108    pub fn to_string(&'a self) -> String{
109        match self {
110            CertificateAlternateName::Directory(ref string) => string.clone(),
111            CertificateAlternateName::Hostname(ref string) => string.clone(),
112            CertificateAlternateName::Address(ref string) => string.clone(),
113            CertificateAlternateName::Email(ref string) => string.clone(),
114            CertificateAlternateName::Uri(ref string) => string.clone(),
115        }
116    }
117
118    pub fn as_str(&'a self) -> &'a str {
119        match self {
120            CertificateAlternateName::Directory(ref string) => string.as_str(),
121            CertificateAlternateName::Hostname(ref string) => string.as_str(),
122            CertificateAlternateName::Address(ref string) => string.as_str(),
123            CertificateAlternateName::Email(ref string) => string.as_str(),
124            CertificateAlternateName::Uri(ref string) => string.as_str(),
125        }
126    }
127}
128
129#[derive(Clone)]
130#[derive(Serialize, Deserialize)]
131pub struct CertificateData {
132    pub(crate) authority: bool,
133    pub(crate) issuer_name: Option<String>,
134    pub(crate) issuer_country:Option<String>,
135    pub(crate) issuer_state:Option<String>,
136    pub(crate) issuer_organization:Option<String>,
137    pub(crate) issuer_organizational_unit:Option<String>,
138    pub(crate) subject_name: Option<String>,
139    pub(crate) subject_alternate_names: Vec<CertificateAlternateName>,
140    pub(crate) subject_country:Option<String>,
141    pub(crate) subject_state:Option<String>,
142    pub(crate) subject_organization:Option<String>,
143    pub(crate) subject_organizational_unit:Option<String>,
144    pub(crate) validity: CertificateValidity,
145    pub(crate) serial: Vec<u8>,
146    pub(crate) raw_der_encoded: Vec<u8>,
147}
148
149impl CertificateData {
150    pub fn authority(&self) -> bool {
151        self.authority
152    }
153
154    pub fn issuer_name(&self) -> Option<&str> {
155        if let Some(ref issuer_name) = self.issuer_name {
156            return Some(issuer_name.as_str())
157        }
158
159        None
160    }
161
162    pub fn issuer_country(&self) -> Option<&str> {
163        if let Some(ref issuer_country) = self.issuer_country {
164            return Some(issuer_country.as_str())
165        }
166
167        None
168    }
169
170    pub fn issuer_state(&self) -> Option<&str> {
171        if let Some(ref issuer_state) = self.issuer_state {
172            return Some(issuer_state.as_str())
173        }
174
175        None
176    }
177
178    pub fn issuer_organization(&self) -> Option<&str> {
179        if let Some(ref issuer_organization) = self.issuer_organization {
180            return Some(issuer_organization.as_str())
181        }
182
183        None
184    }
185
186    pub fn issuer_organizational_unit(&self) -> Option<&str> {
187        if let Some(ref issuer_organizational_unit) = self.issuer_organizational_unit {
188            return Some(issuer_organizational_unit.as_str())
189        }
190
191        None
192    }
193
194    pub fn subject_name(&self) -> Option<&str> {
195        if let Some(ref subject_name) = self.subject_name {
196            return Some(subject_name.as_str())
197        }
198
199        None
200    }
201
202    pub fn subject_alternate_names(&self) -> &[CertificateAlternateName] {
203        self.subject_alternate_names.as_slice()
204    }
205
206    pub fn subject_country(&self) -> Option<&str> {
207        if let Some(ref subject_country) = self.subject_country {
208            return Some(subject_country.as_str())
209        }
210
211        None
212    }
213
214    pub fn subject_state(&self) -> Option<&str> {
215        if let Some(ref subject_state) = self.subject_state {
216            return Some(subject_state.as_str())
217        }
218
219        None
220    }
221
222    pub fn subject_organization(&self) -> Option<&str> {
223        if let Some(ref subject_organization) = self.subject_organization {
224            return Some(subject_organization.as_str())
225        }
226
227        None
228    }
229
230    pub fn subject_organizational_unit(&self) -> Option<&str> {
231        if let Some(ref subject_organizational_unit) = self.subject_organizational_unit {
232            return Some(subject_organizational_unit.as_str())
233        }
234
235        None
236    }
237
238    pub fn validity(&self) -> CertificateValidity {
239        self.validity
240    }
241
242    pub fn serial(&self) -> &[u8] {
243        self.serial.as_slice()
244    }
245
246    pub fn raw_der_encoded(&self) -> &[u8] {
247        self.raw_der_encoded.as_slice()
248    }
249}
250
251impl FmtDebug for CertificateData {
252    fn fmt(&self, formatter: &mut FmtFormatter<'_>) -> FmtResult {
253        formatter.debug_struct("Certificate")
254            .field("authority", &(self.authority()))
255            .field("issuer_name", &(self.issuer_name()))
256            .field("issuer_country", &(self.issuer_country()))
257            .field("issuer_state", &(self.issuer_state()))
258            .field("issuer_organization", &(self.issuer_organization()))
259            .field("issuer_organizational_unit", &(self.issuer_organizational_unit()))
260            .field("subject_name", &(self.subject_name()))
261            .field("subject_alternate_names", &(self.subject_alternate_names()))
262            .field("subject_country", &(self.subject_country()))
263            .field("subject_state", &(self.subject_state()))
264            .field("subject_organization", &(self.subject_organization()))
265            .field("subject_organizational_unit", &(self.subject_organizational_unit()))
266            .field("validity", &(self.validity()))
267            .finish()
268    }
269}
270
271#[derive(Clone, Debug)]
272#[derive(Serialize, Deserialize)]
273pub enum Certificate {
274    Signed(CertificateData),
275    Pending(CertificateData),
276}
277
278impl Certificate {
279    /// Parse a certificate from `DER` encoded data.
280    pub fn parse(data: &[u8]) -> Option<Certificate> {
281        let (pending, remaining, certificate) = if let Ok((remaining, certificate)) = X509Certificate::from_der(data) { 
282            (false, remaining, certificate.tbs_certificate) 
283        } 
284        
285        else {
286    
287            if let Ok((remaining, tbs_certificate)) = TbsCertificate::from_der(data) { 
288                (true, remaining, tbs_certificate) 
289            }
290            
291            else {
292                
293                return None
294            }
295        };
296
297        let authority = certificate.is_ca();
298
299        let issuer_name = certificate.issuer().iter_common_name()
300            .filter_map(|name| name.as_str().ok())
301            .next().and_then(|name| Some({
302                Some(name.to_owned())
303            })).unwrap_or(None);
304
305        let issuer_country = certificate.issuer().iter_country()
306            .filter_map(|name| name.as_str().ok())
307            .next().and_then(|name| Some({
308                Some(name.to_owned())
309            })).unwrap_or(None);
310
311        let issuer_state = certificate.issuer().iter_state_or_province()
312            .filter_map(|name| name.as_str().ok())
313            .next().and_then(|name| Some({
314                Some(name.to_owned())
315            })).unwrap_or(None);
316    
317        let issuer_organization = certificate.issuer().iter_organization()
318            .filter_map(|name| name.as_str().ok())
319            .next().and_then(|name| Some({
320                Some(name.to_owned())
321            })).unwrap_or(None);
322
323        let issuer_organizational_unit = certificate.issuer().iter_organizational_unit()
324            .filter_map(|name| name.as_str().ok())
325            .next().and_then(|name| Some({
326                Some(name.to_owned())
327            })).unwrap_or(None);
328        
329        let subject_name = certificate.subject().iter_common_name()
330            .filter_map(|name| name.as_str().ok())
331            .next().and_then(|name| Some({
332                Some(name.to_owned())
333            })).unwrap_or(None);
334
335        let subject_alternate = if let Ok(Some(extension)) = certificate.subject_alternative_name() {
336            extension.value.general_names.iter().filter_map(|name| match name {
337                GeneralName::DirectoryName(name) => Some({
338                    CertificateAlternateName::Directory(name.to_string())
339                }),
340                GeneralName::RFC822Name(name) => Some({
341                    CertificateAlternateName::Email(name.to_string())
342                }),
343                GeneralName::IPAddress(octets) => Some({
344                    CertificateAlternateName::Address(match octets {
345                        octets if octets.len() == 4 => {
346                            let mut array: [u8; 4] = Default::default();
347                            for i in 0..4 { array[i] = octets[i] }
348                            IpAddr::from(array).to_string()
349                        },
350                        octets if octets.len() == 16 => {
351                            let mut array: [u8; 16] = Default::default();
352                            for i in 0..16 { array[i] = octets[i] }
353                            IpAddr::from(array).to_string()
354                        },
355                        _ => return None
356                    })
357                }),
358                GeneralName::DNSName(name) => Some({
359                    CertificateAlternateName::Hostname(name.to_string())
360                }),
361                GeneralName::URI(name) => Some({
362                    CertificateAlternateName::Uri(name.to_string())
363                }),
364                _ => None,
365            }).filter_map(|alternate| match alternate.clone() {
366                CertificateAlternateName::Directory(ref item) |
367                CertificateAlternateName::Hostname(ref item) |
368                CertificateAlternateName::Address(ref item) |
369                CertificateAlternateName::Email(ref item) |
370                CertificateAlternateName::Uri(ref item) => {
371                    if let Some(ref subject) = subject_name {
372                        if item == subject.as_str() {
373                            return None
374                        }
375                    }
376    
377                    Some(alternate)
378                }
379            }).collect()
380        } else { Default::default() };
381
382        let subject_country = certificate.subject().iter_country()
383            .filter_map(|name| name.as_str().ok())
384            .next().and_then(|name| Some({
385                Some(name.to_owned())
386            })).unwrap_or(None);
387
388        let subject_state = certificate.subject().iter_state_or_province()
389            .filter_map(|name| name.as_str().ok())
390            .next().and_then(|name| Some({
391                Some(name.to_owned())
392            })).unwrap_or(None);
393
394        let subject_organization = certificate.subject().iter_organization()
395            .filter_map(|name| name.as_str().ok())
396            .next().and_then(|name| Some({
397                Some(name.to_owned())
398            })).unwrap_or(None);
399
400        let subject_organizational_unit = certificate.subject().iter_organizational_unit()
401            .filter_map(|name| name.as_str().ok())
402            .next().and_then(|name| Some({
403                Some(name.to_owned())
404            })).unwrap_or(None);
405    
406        let validity = {
407    
408            let begin = certificate.validity.not_before.timestamp();
409            let end = certificate.validity.not_after.timestamp();
410    
411            CertificateValidity::from_timestamps(begin, end)
412        };
413
414        let serial = certificate.serial.to_bytes_be();
415    
416        let raw_der_encoded = data[..(data.len() - remaining.len())].to_vec();
417    
418        let data = CertificateData {
419    
420            authority,
421            issuer_name,
422            issuer_country,
423            issuer_state,
424            issuer_organization,
425            issuer_organizational_unit,
426            subject_name,
427            subject_alternate_names: subject_alternate,
428            subject_country,
429            subject_state,
430            subject_organization,
431            subject_organizational_unit,
432            validity,
433            serial,
434            raw_der_encoded,
435        };
436    
437        if pending { Some(Certificate::Pending(data)) } 
438        else { Some(Certificate::Signed(data)) }
439    }
440
441    pub fn verify_trust_chain_web_roots(&self, chain: &[Certificate]) -> bool {
442        let mut trust_store = TlsRootCertStore::empty();
443
444        trust_store.add_server_trust_anchors(TLS_SERVER_ROOTS.0.iter().map(|anchor| {
445            TlsOwnedTrustAnchor::from_subject_spki_name_constraints(anchor.subject, anchor.spki, anchor.name_constraints)
446        }));
447
448        let ref certificate = TlsCertificate(self.raw_der_encoded().to_owned());
449        let chain: Vec<TlsCertificate> = chain.iter().map(|certificate| {
450            TlsCertificate(certificate.raw_der_encoded().to_vec())
451        }).collect();
452
453        TlsAllowAnyAuthenticatedClient::new(trust_store)
454            .verify_client_cert(certificate, chain.as_slice(), SystemTime::now())
455            .is_ok()
456    }
457
458    pub fn verify_trust_chain_system_roots(&self, chain: &[Certificate]) -> bool {
459        if let Ok(native) = rustls_native_certs::load_native_certs() {
460            let mut trust_store = TlsRootCertStore::empty();
461
462            for TlsNativeCertificate(data) in native.iter() {
463                let ref root = TlsCertificate(data.to_vec());
464                if let Err(..) = trust_store.add(root) {
465                    continue
466                }
467            }
468
469            let ref certificate = TlsCertificate(self.raw_der_encoded().to_owned());
470            let chain: Vec<TlsCertificate> = chain.iter().map(|certificate| {
471                TlsCertificate(certificate.raw_der_encoded().to_vec())
472            }).collect();
473
474            return TlsAllowAnyAuthenticatedClient::new(trust_store)
475                .verify_client_cert(certificate, chain.as_slice(), SystemTime::now())
476                .is_ok()
477        }
478
479        false
480    }
481
482    pub fn verify_trust_chain(&self, chain: &[Certificate], roots: &[Certificate]) -> bool {
483        let mut trust_store = TlsRootCertStore::empty();
484
485        for root in roots.iter() {
486            let ref certificate = TlsCertificate(root.raw_der_encoded().to_owned());
487            if let Err(..) = trust_store.add(certificate) {
488                return false
489            }
490        }
491
492        let ref certificate = TlsCertificate(self.raw_der_encoded().to_owned());
493        let chain: Vec<TlsCertificate> = chain.iter().map(|certificate| {
494            TlsCertificate(certificate.raw_der_encoded().to_vec())
495        }).collect();
496
497        TlsAllowAnyAuthenticatedClient::new(trust_store)
498            .verify_client_cert(certificate, chain.as_slice(), SystemTime::now())
499            .is_ok()
500    } 
501
502    pub fn authority(&self) -> bool {
503        match self {
504            Certificate::Signed(data) => data.authority(),
505            Certificate::Pending(data) => data.authority(),
506        }
507    }
508
509    pub fn issuer_name(&self) -> Option<&str> {
510        match self {
511            Certificate::Signed(data) => data.issuer_name(),
512            Certificate::Pending(data) => data.issuer_name(),
513        }
514    }
515
516    pub fn issuer_country(&self) -> Option<&str> {
517        match self {
518            Certificate::Signed(data) => data.issuer_country(),
519            Certificate::Pending(data) => data.issuer_country(),
520        }
521    }
522
523    pub fn issuer_state(&self) -> Option<&str> {
524        match self {
525            Certificate::Signed(data) => data.issuer_state(),
526            Certificate::Pending(data) => data.issuer_state(),
527        }
528    }
529
530    pub fn issuer_organization(&self) -> Option<&str> {
531        match self {
532            Certificate::Signed(data) => data.issuer_organization(),
533            Certificate::Pending(data) => data.issuer_organization(),
534        }
535    }
536
537    pub fn issuer_organizational_unit(&self) -> Option<&str> {
538        match self {
539            Certificate::Signed(data) => data.issuer_organizational_unit(),
540            Certificate::Pending(data) => data.issuer_organizational_unit(),
541        }
542    }
543
544    pub fn subject_name(&self) -> Option<&str> {
545        match self {
546            Certificate::Signed(data) => data.subject_name(),
547            Certificate::Pending(data) => data.subject_name(),
548        }
549    }
550
551    pub fn subject_alternate_names(&self) -> &[CertificateAlternateName] {
552        match self {
553            Certificate::Signed(data) => data.subject_alternate_names(),
554            Certificate::Pending(data) => data.subject_alternate_names(),
555        }
556    }
557
558    pub fn subject_country(&self) -> Option<&str> {
559        match self {
560            Certificate::Signed(data) => data.subject_country(),
561            Certificate::Pending(data) => data.subject_country(),
562        }
563    }
564
565    pub fn subject_state(&self) -> Option<&str> {
566        match self {
567            Certificate::Signed(data) => data.subject_state(),
568            Certificate::Pending(data) => data.subject_state(),
569        }
570    }
571
572    pub fn subject_organization(&self) -> Option<&str> {
573        match self {
574            Certificate::Signed(data) => data.subject_organization(),
575            Certificate::Pending(data) => data.subject_organization(),
576        }
577    }
578
579    pub fn subject_organizational_unit(&self) -> Option<&str> {
580        match self {
581            Certificate::Signed(data) => data.subject_organizational_unit(),
582            Certificate::Pending(data) => data.subject_organizational_unit(),
583        }
584    }
585
586    pub fn validity(&self) -> CertificateValidity {
587        match self {
588            Certificate::Signed(data) => data.validity(),
589            Certificate::Pending(data) => data.validity(),
590        }
591    }
592
593    pub fn serial(&self) -> &[u8] {
594        match self {
595            Certificate::Signed(data) => data.serial(),
596            Certificate::Pending(data) => data.serial(),
597        }
598    }
599
600    pub fn raw_der_encoded(&self) -> &[u8] {
601        match self {
602            Certificate::Signed(data) => data.raw_der_encoded(),
603            Certificate::Pending(data) => data.raw_der_encoded(),
604        }
605    }
606}