x509_parser/extensions/
mod.rs

1//! X.509 Extensions objects and types
2
3use crate::error::{X509Error, X509Result};
4use crate::time::ASN1Time;
5use crate::utils::format_serial;
6use crate::x509::{ReasonCode, RelativeDistinguishedName};
7
8use asn1_rs::FromDer;
9use der_parser::ber::parse_ber_bool;
10use der_parser::der::*;
11use der_parser::error::{BerError, BerResult};
12use der_parser::num_bigint::BigUint;
13use nom::combinator::{all_consuming, complete, cut, map, map_res, opt};
14use nom::multi::{many0, many1};
15use nom::{Err, IResult, Parser};
16use oid_registry::*;
17use std::collections::HashMap;
18use std::fmt::{self, LowerHex};
19
20mod generalname;
21mod keyusage;
22mod nameconstraints;
23mod policymappings;
24mod sct;
25
26pub use generalname::*;
27pub use keyusage::*;
28pub use nameconstraints::*;
29pub use policymappings::*;
30pub use sct::*;
31
32/// X.509 version 3 extension
33///
34/// X.509 extensions allow adding attributes to objects like certificates or revocation lists.
35///
36/// Each extension in a certificate is designated as either critical or non-critical.  A
37/// certificate using system MUST reject the certificate if it encounters a critical extension it
38/// does not recognize; however, a non-critical extension MAY be ignored if it is not recognized.
39///
40/// Each extension includes an OID and an ASN.1 structure.  When an extension appears in a
41/// certificate, the OID appears as the field extnID and the corresponding ASN.1 encoded structure
42/// is the value of the octet string extnValue.  A certificate MUST NOT include more than one
43/// instance of a particular extension.
44///
45/// When parsing an extension, the global extension structure (described above) is parsed,
46/// and the object is returned if it succeeds.
47/// During this step, it also attempts to parse the content of the extension, if known.
48/// The returned object has a
49/// [`X509Extension::parsed_extension()`] method. The returned
50/// enum is either a known extension, or the special value `ParsedExtension::UnsupportedExtension`.
51///
52/// # Example
53///
54/// ```rust
55/// use x509_parser::prelude::FromDer;
56/// use x509_parser::extensions::{X509Extension, ParsedExtension};
57///
58/// static DER: &[u8] = &[
59///    0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xA3, 0x05, 0x2F, 0x18,
60///    0x60, 0x50, 0xC2, 0x89, 0x0A, 0xDD, 0x2B, 0x21, 0x4F, 0xFF, 0x8E, 0x4E, 0xA8, 0x30, 0x31,
61///    0x36 ];
62///
63/// # fn main() {
64/// let res = X509Extension::from_der(DER);
65/// match res {
66///     Ok((_rem, ext)) => {
67///         println!("Extension OID: {}", ext.oid);
68///         println!("  Critical: {}", ext.critical);
69///         let parsed_ext = ext.parsed_extension();
70///         assert!(!parsed_ext.unsupported());
71///         assert!(parsed_ext.error().is_none());
72///         if let ParsedExtension::SubjectKeyIdentifier(key_id) = parsed_ext {
73///             assert!(key_id.0.len() > 0);
74///         } else {
75///             panic!("Extension has wrong type");
76///         }
77///     },
78///     _ => panic!("x509 extension parsing failed: {:?}", res),
79/// }
80/// # }
81/// ```
82#[derive(Clone, Debug, PartialEq)]
83pub struct X509Extension<'a> {
84    /// OID describing the extension content
85    pub oid: Oid<'a>,
86    /// Boolean value describing the 'critical' attribute of the extension
87    ///
88    /// An extension includes the boolean critical, with a default value of FALSE.
89    pub critical: bool,
90    /// Raw content of the extension
91    pub value: &'a [u8],
92    pub(crate) parsed_extension: ParsedExtension<'a>,
93}
94
95impl<'a> X509Extension<'a> {
96    /// Creates a new extension with the provided values.
97    #[inline]
98    pub const fn new(
99        oid: Oid<'a>,
100        critical: bool,
101        value: &'a [u8],
102        parsed_extension: ParsedExtension<'a>,
103    ) -> X509Extension<'a> {
104        X509Extension {
105            oid,
106            critical,
107            value,
108            parsed_extension,
109        }
110    }
111
112    /// Return the extension type or `UnsupportedExtension` if the extension is not implemented.
113    #[inline]
114    pub fn parsed_extension(&self) -> &ParsedExtension<'a> {
115        &self.parsed_extension
116    }
117}
118
119/// <pre>
120/// Extension  ::=  SEQUENCE  {
121///     extnID      OBJECT IDENTIFIER,
122///     critical    BOOLEAN DEFAULT FALSE,
123///     extnValue   OCTET STRING  }
124/// </pre>
125impl<'a> FromDer<'a, X509Error> for X509Extension<'a> {
126    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
127        X509ExtensionParser::new().parse(i)
128    }
129}
130
131/// `X509Extension` parser builder
132#[derive(Clone, Copy, Debug)]
133pub struct X509ExtensionParser {
134    deep_parse_extensions: bool,
135}
136
137impl X509ExtensionParser {
138    #[inline]
139    pub const fn new() -> Self {
140        X509ExtensionParser {
141            deep_parse_extensions: true,
142        }
143    }
144
145    #[inline]
146    pub const fn with_deep_parse_extensions(self, deep_parse_extensions: bool) -> Self {
147        X509ExtensionParser {
148            deep_parse_extensions,
149        }
150    }
151}
152
153impl Default for X509ExtensionParser {
154    fn default() -> Self {
155        X509ExtensionParser::new()
156    }
157}
158
159impl<'a> Parser<&'a [u8], X509Extension<'a>, X509Error> for X509ExtensionParser {
160    fn parse(&mut self, input: &'a [u8]) -> IResult<&'a [u8], X509Extension<'a>, X509Error> {
161        parse_der_sequence_defined_g(|i, _| {
162            let (i, oid) = Oid::from_der(i)?;
163            let (i, critical) = der_read_critical(i)?;
164            let (i, value) = <&[u8]>::from_der(i)?;
165            let (i, parsed_extension) = if self.deep_parse_extensions {
166                parser::parse_extension(i, value, &oid)?
167            } else {
168                (&[] as &[_], ParsedExtension::Unparsed)
169            };
170            let ext = X509Extension {
171                oid,
172                critical,
173                value,
174                parsed_extension,
175            };
176            Ok((i, ext))
177        })(input)
178        .map_err(|_| X509Error::InvalidExtensions.into())
179    }
180}
181
182#[derive(Clone, Debug, PartialEq)]
183pub enum ParsedExtension<'a> {
184    /// Crate parser does not support this extension (yet)
185    UnsupportedExtension {
186        oid: Oid<'a>,
187    },
188    ParseError {
189        error: Err<BerError>,
190    },
191    /// Section 4.2.1.1 of rfc 5280
192    AuthorityKeyIdentifier(AuthorityKeyIdentifier<'a>),
193    /// Section 4.2.1.2 of rfc 5280
194    SubjectKeyIdentifier(KeyIdentifier<'a>),
195    /// Section 4.2.1.3 of rfc 5280
196    KeyUsage(KeyUsage),
197    /// Section 4.2.1.4 of rfc 5280
198    CertificatePolicies(CertificatePolicies<'a>),
199    /// Section 4.2.1.5 of rfc 5280
200    PolicyMappings(PolicyMappings<'a>),
201    /// Section 4.2.1.6 of rfc 5280
202    SubjectAlternativeName(SubjectAlternativeName<'a>),
203    /// Section 4.2.1.7 of rfc 5280
204    IssuerAlternativeName(IssuerAlternativeName<'a>),
205    /// Section 4.2.1.9 of rfc 5280
206    BasicConstraints(BasicConstraints),
207    /// Section 4.2.1.10 of rfc 5280
208    NameConstraints(NameConstraints<'a>),
209    /// Section 4.2.1.11 of rfc 5280
210    PolicyConstraints(PolicyConstraints),
211    /// Section 4.2.1.12 of rfc 5280
212    ExtendedKeyUsage(ExtendedKeyUsage<'a>),
213    /// Section 4.2.1.13 of rfc 5280
214    CRLDistributionPoints(CRLDistributionPoints<'a>),
215    /// Section 4.2.1.14 of rfc 5280
216    InhibitAnyPolicy(InhibitAnyPolicy),
217    /// Section 4.2.2.1 of rfc 5280
218    AuthorityInfoAccess(AuthorityInfoAccess<'a>),
219    /// Section 4.2.2.2 of rfc 5280
220    SubjectInfoAccess(SubjectInfoAccess<'a>),
221    /// Netscape certificate type (subject is SSL client, an SSL server, or a CA)
222    NSCertType(NSCertType),
223    /// Netscape certificate comment
224    NsCertComment(&'a str),
225    /// Section 5.2.5 of rfc 5280
226    IssuingDistributionPoint(IssuingDistributionPoint<'a>),
227    /// Section 5.3.1 of rfc 5280
228    CRLNumber(BigUint),
229    /// Section 5.3.1 of rfc 5280
230    ReasonCode(ReasonCode),
231    /// Section 5.3.3 of rfc 5280
232    InvalidityDate(ASN1Time),
233    /// rfc 6962
234    SCT(Vec<SignedCertificateTimestamp<'a>>),
235    /// Unparsed extension (was not requested in parsing options)
236    Unparsed,
237}
238
239impl ParsedExtension<'_> {
240    /// Return `true` if the extension is unsupported
241    pub fn unsupported(&self) -> bool {
242        matches!(self, &ParsedExtension::UnsupportedExtension { .. })
243    }
244
245    /// Return a reference on the parsing error if the extension parsing failed
246    pub fn error(&self) -> Option<&Err<BerError>> {
247        match self {
248            ParsedExtension::ParseError { error } => Some(error),
249            _ => None,
250        }
251    }
252}
253
254#[derive(Clone, Debug, PartialEq)]
255pub struct AuthorityKeyIdentifier<'a> {
256    pub key_identifier: Option<KeyIdentifier<'a>>,
257    pub authority_cert_issuer: Option<Vec<GeneralName<'a>>>,
258    pub authority_cert_serial: Option<&'a [u8]>,
259}
260
261impl<'a> FromDer<'a, X509Error> for AuthorityKeyIdentifier<'a> {
262    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
263        parser::parse_authoritykeyidentifier(i).map_err(Err::convert)
264    }
265}
266
267pub type CertificatePolicies<'a> = Vec<PolicyInformation<'a>>;
268
269// impl<'a> FromDer<'a> for CertificatePolicies<'a> {
270//     fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
271//         parser::parse_certificatepolicies(i).map_err(Err::convert)
272//     }
273// }
274
275#[derive(Clone, Debug, PartialEq, Eq)]
276pub struct PolicyInformation<'a> {
277    pub policy_id: Oid<'a>,
278    pub policy_qualifiers: Option<Vec<PolicyQualifierInfo<'a>>>,
279}
280
281#[derive(Clone, Debug, PartialEq, Eq)]
282pub struct PolicyQualifierInfo<'a> {
283    pub policy_qualifier_id: Oid<'a>,
284    pub qualifier: &'a [u8],
285}
286
287/// Identifies whether the subject of the certificate is a CA, and the max validation depth.
288#[derive(Clone, Debug, PartialEq, Eq)]
289pub struct BasicConstraints {
290    pub ca: bool,
291    pub path_len_constraint: Option<u32>,
292}
293
294impl<'a> FromDer<'a, X509Error> for BasicConstraints {
295    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
296        parser::parse_basicconstraints(i).map_err(Err::convert)
297    }
298}
299
300#[derive(Clone, Debug, PartialEq, Eq)]
301pub struct KeyIdentifier<'a>(pub &'a [u8]);
302
303impl<'a> FromDer<'a, X509Error> for KeyIdentifier<'a> {
304    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
305        parser::parse_keyidentifier(i).map_err(Err::convert)
306    }
307}
308
309impl LowerHex for KeyIdentifier<'_> {
310    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311        let s = format_serial(self.0);
312        f.write_str(&s)
313    }
314}
315
316#[derive(Clone, Copy, Debug, PartialEq, Eq)]
317pub struct NSCertType(u8);
318
319// The value is a bit-string, where the individual bit positions are defined as:
320//
321//     bit-0 SSL client - this cert is certified for SSL client authentication use
322//     bit-1 SSL server - this cert is certified for SSL server authentication use
323//     bit-2 S/MIME - this cert is certified for use by clients (New in PR3)
324//     bit-3 Object Signing - this cert is certified for signing objects such as Java applets and plugins(New in PR3)
325//     bit-4 Reserved - this bit is reserved for future use
326//     bit-5 SSL CA - this cert is certified for issuing certs for SSL use
327//     bit-6 S/MIME CA - this cert is certified for issuing certs for S/MIME use (New in PR3)
328//     bit-7 Object Signing CA - this cert is certified for issuing certs for Object Signing (New in PR3)
329impl NSCertType {
330    pub fn ssl_client(&self) -> bool {
331        self.0 & 0x1 == 1
332    }
333    pub fn ssl_server(&self) -> bool {
334        (self.0 >> 1) & 1 == 1
335    }
336    pub fn smime(&self) -> bool {
337        (self.0 >> 2) & 1 == 1
338    }
339    pub fn object_signing(&self) -> bool {
340        (self.0 >> 3) & 1 == 1
341    }
342    pub fn ssl_ca(&self) -> bool {
343        (self.0 >> 5) & 1 == 1
344    }
345    pub fn smime_ca(&self) -> bool {
346        (self.0 >> 6) & 1 == 1
347    }
348    pub fn object_signing_ca(&self) -> bool {
349        (self.0 >> 7) & 1 == 1
350    }
351}
352
353const NS_CERT_TYPE_FLAGS: &[&str] = &[
354    "SSL CLient",
355    "SSL Server",
356    "S/MIME",
357    "Object Signing",
358    "Reserved",
359    "SSL CA",
360    "S/MIME CA",
361    "Object Signing CA",
362];
363
364impl fmt::Display for NSCertType {
365    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366        let mut s = String::new();
367        let mut acc = self.0;
368        for flag_text in NS_CERT_TYPE_FLAGS {
369            if acc & 1 != 0 {
370                s = s + flag_text + ", ";
371            }
372            acc >>= 1;
373        }
374        s.pop();
375        s.pop();
376        f.write_str(&s)
377    }
378}
379
380impl<'a> FromDer<'a, X509Error> for NSCertType {
381    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
382        parser::parse_nscerttype(i).map_err(Err::convert)
383    }
384}
385
386#[derive(Clone, Debug, PartialEq)]
387pub struct AuthorityInfoAccess<'a> {
388    pub accessdescs: Vec<AccessDescription<'a>>,
389}
390
391impl<'a> AuthorityInfoAccess<'a> {
392    /// Returns an iterator over the Access Descriptors
393    pub fn iter(&self) -> impl Iterator<Item = &AccessDescription<'a>> {
394        self.accessdescs.iter()
395    }
396
397    /// Returns a `HashMap` mapping `Oid` to the list of references to `GeneralNames`
398    ///
399    /// If several names match the same `Oid`, they are merged in the same entry.
400    pub fn as_hashmap(&self) -> HashMap<Oid<'a>, Vec<&GeneralName<'a>>> {
401        // create the hashmap and merge entries with same OID
402        let mut m: HashMap<Oid, Vec<&GeneralName>> = HashMap::new();
403        for desc in &self.accessdescs {
404            let AccessDescription {
405                access_method: oid,
406                access_location: gn,
407            } = desc;
408            if let Some(general_names) = m.get_mut(oid) {
409                general_names.push(gn);
410            } else {
411                m.insert(oid.clone(), vec![gn]);
412            }
413        }
414        m
415    }
416
417    /// Returns a `HashMap` mapping `Oid` to the list of `GeneralNames` (consuming the input)
418    ///
419    /// If several names match the same `Oid`, they are merged in the same entry.
420    pub fn into_hashmap(self) -> HashMap<Oid<'a>, Vec<GeneralName<'a>>> {
421        let mut aia_list = self.accessdescs;
422        // create the hashmap and merge entries with same OID
423        let mut m: HashMap<Oid, Vec<GeneralName>> = HashMap::new();
424        for desc in aia_list.drain(..) {
425            let AccessDescription {
426                access_method: oid,
427                access_location: gn,
428            } = desc;
429            if let Some(general_names) = m.get_mut(&oid) {
430                general_names.push(gn);
431            } else {
432                m.insert(oid, vec![gn]);
433            }
434        }
435        m
436    }
437}
438
439impl<'a> FromDer<'a, X509Error> for AuthorityInfoAccess<'a> {
440    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
441        parser::parse_authorityinfoaccess(i).map_err(Err::convert)
442    }
443}
444
445#[derive(Clone, Debug, PartialEq)]
446pub struct SubjectInfoAccess<'a> {
447    pub accessdescs: Vec<AccessDescription<'a>>,
448}
449
450impl<'a> SubjectInfoAccess<'a> {
451    /// Returns an iterator over the Access Descriptors
452    pub fn iter(&self) -> impl Iterator<Item = &AccessDescription<'a>> {
453        self.accessdescs.iter()
454    }
455
456    /// Returns a `HashMap` mapping `Oid` to the list of references to `GeneralNames`
457    ///
458    /// If several names match the same `Oid`, they are merged in the same entry.
459    pub fn as_hashmap(&self) -> HashMap<Oid<'a>, Vec<&GeneralName<'a>>> {
460        // create the hashmap and merge entries with same OID
461        let mut m: HashMap<Oid, Vec<&GeneralName>> = HashMap::new();
462        for desc in &self.accessdescs {
463            let AccessDescription {
464                access_method: oid,
465                access_location: gn,
466            } = desc;
467            if let Some(general_names) = m.get_mut(oid) {
468                general_names.push(gn);
469            } else {
470                m.insert(oid.clone(), vec![gn]);
471            }
472        }
473        m
474    }
475
476    /// Returns a `HashMap` mapping `Oid` to the list of `GeneralNames` (consuming the input)
477    ///
478    /// If several names match the same `Oid`, they are merged in the same entry.
479    pub fn into_hashmap(self) -> HashMap<Oid<'a>, Vec<GeneralName<'a>>> {
480        let mut aia_list = self.accessdescs;
481        // create the hashmap and merge entries with same OID
482        let mut m: HashMap<Oid, Vec<GeneralName>> = HashMap::new();
483        for desc in aia_list.drain(..) {
484            let AccessDescription {
485                access_method: oid,
486                access_location: gn,
487            } = desc;
488            if let Some(general_names) = m.get_mut(&oid) {
489                general_names.push(gn);
490            } else {
491                m.insert(oid, vec![gn]);
492            }
493        }
494        m
495    }
496}
497
498impl<'a> FromDer<'a, X509Error> for SubjectInfoAccess<'a> {
499    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
500        parser::parse_subjectinfoaccess(i).map_err(Err::convert)
501    }
502}
503
504/// AccessDescription  ::=  SEQUENCE {
505///     accessMethod          OBJECT IDENTIFIER,
506///     accessLocation        GeneralName  }
507#[derive(Clone, Debug, PartialEq)]
508pub struct AccessDescription<'a> {
509    pub access_method: Oid<'a>,
510    pub access_location: GeneralName<'a>,
511}
512
513impl<'a> AccessDescription<'a> {
514    pub const fn new(access_method: Oid<'a>, access_location: GeneralName<'a>) -> Self {
515        AccessDescription {
516            access_method,
517            access_location,
518        }
519    }
520}
521
522#[derive(Clone, Debug, PartialEq, Eq)]
523pub struct InhibitAnyPolicy {
524    pub skip_certs: u32,
525}
526
527impl<'a> FromDer<'a, X509Error> for InhibitAnyPolicy {
528    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
529        map(parse_der_u32, |skip_certs| InhibitAnyPolicy { skip_certs })(i).map_err(Err::convert)
530    }
531}
532
533#[derive(Clone, Debug, PartialEq, Eq)]
534pub struct PolicyConstraints {
535    pub require_explicit_policy: Option<u32>,
536    pub inhibit_policy_mapping: Option<u32>,
537}
538
539impl<'a> FromDer<'a, X509Error> for PolicyConstraints {
540    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
541        parser::parse_policyconstraints(i).map_err(Err::convert)
542    }
543}
544
545#[derive(Clone, Debug, PartialEq)]
546pub struct SubjectAlternativeName<'a> {
547    pub general_names: Vec<GeneralName<'a>>,
548}
549
550impl<'a> FromDer<'a, X509Error> for SubjectAlternativeName<'a> {
551    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
552        parse_der_sequence_defined_g(|input, _| {
553            let (i, general_names) =
554                all_consuming(many0(complete(cut(GeneralName::from_der))))(input)?;
555            Ok((i, SubjectAlternativeName { general_names }))
556        })(i)
557    }
558}
559
560#[derive(Clone, Debug, PartialEq)]
561pub struct IssuerAlternativeName<'a> {
562    pub general_names: Vec<GeneralName<'a>>,
563}
564
565impl<'a> FromDer<'a, X509Error> for IssuerAlternativeName<'a> {
566    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
567        parse_der_sequence_defined_g(|input, _| {
568            let (i, general_names) =
569                all_consuming(many0(complete(cut(GeneralName::from_der))))(input)?;
570            Ok((i, IssuerAlternativeName { general_names }))
571        })(i)
572    }
573}
574
575#[derive(Clone, Debug, PartialEq)]
576pub struct CRLDistributionPoints<'a> {
577    pub points: Vec<CRLDistributionPoint<'a>>,
578}
579
580impl<'a> std::ops::Deref for CRLDistributionPoints<'a> {
581    type Target = Vec<CRLDistributionPoint<'a>>;
582
583    fn deref(&self) -> &Self::Target {
584        &self.points
585    }
586}
587
588impl<'a> FromDer<'a, X509Error> for CRLDistributionPoints<'a> {
589    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
590        parser::parse_crldistributionpoints(i).map_err(Err::convert)
591    }
592}
593
594#[derive(Clone, Debug, PartialEq)]
595pub struct CRLDistributionPoint<'a> {
596    pub distribution_point: Option<DistributionPointName<'a>>,
597    pub reasons: Option<ReasonFlags>,
598    pub crl_issuer: Option<Vec<GeneralName<'a>>>,
599}
600
601#[derive(Clone, Debug, PartialEq)]
602pub enum DistributionPointName<'a> {
603    FullName(Vec<GeneralName<'a>>),
604    NameRelativeToCRLIssuer(RelativeDistinguishedName<'a>),
605}
606
607#[derive(Clone, Debug, PartialEq, Eq)]
608pub struct ReasonFlags {
609    pub flags: u16,
610}
611
612impl ReasonFlags {
613    pub fn key_compromise(&self) -> bool {
614        (self.flags >> 1) & 1 == 1
615    }
616    pub fn ca_compromise(&self) -> bool {
617        (self.flags >> 2) & 1 == 1
618    }
619    pub fn affilation_changed(&self) -> bool {
620        (self.flags >> 3) & 1 == 1
621    }
622    pub fn superseded(&self) -> bool {
623        (self.flags >> 4) & 1 == 1
624    }
625    pub fn cessation_of_operation(&self) -> bool {
626        (self.flags >> 5) & 1 == 1
627    }
628    pub fn certificate_hold(&self) -> bool {
629        (self.flags >> 6) & 1 == 1
630    }
631    pub fn privelege_withdrawn(&self) -> bool {
632        (self.flags >> 7) & 1 == 1
633    }
634    pub fn aa_compromise(&self) -> bool {
635        (self.flags >> 8) & 1 == 1
636    }
637}
638
639const REASON_FLAGS: &[&str] = &[
640    "Unused",
641    "Key Compromise",
642    "CA Compromise",
643    "Affiliation Changed",
644    "Superseded",
645    "Cessation Of Operation",
646    "Certificate Hold",
647    "Privilege Withdrawn",
648    "AA Compromise",
649];
650
651impl fmt::Display for ReasonFlags {
652    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
653        let mut s = String::new();
654        let mut acc = self.flags;
655        for flag_text in REASON_FLAGS {
656            if acc & 1 != 0 {
657                s = s + flag_text + ", ";
658            }
659            acc >>= 1;
660        }
661        s.pop();
662        s.pop();
663        f.write_str(&s)
664    }
665}
666
667#[derive(Clone, Debug, PartialEq)]
668pub struct IssuingDistributionPoint<'a> {
669    pub distribution_point: Option<DistributionPointName<'a>>,
670    pub only_contains_user_certs: bool,
671    pub only_contains_ca_certs: bool,
672    pub only_some_reasons: Option<ReasonFlags>,
673    pub indirect_crl: bool,
674    pub only_contains_attribute_certs: bool,
675}
676
677pub(crate) mod parser {
678    use crate::extensions::*;
679    use asn1_rs::{GeneralizedTime, ParseResult};
680    use der_parser::ber::BerObject;
681    use lazy_static::lazy_static;
682
683    type ExtParser = fn(&[u8]) -> IResult<&[u8], ParsedExtension, BerError>;
684
685    lazy_static! {
686        static ref EXTENSION_PARSERS: HashMap<Oid<'static>, ExtParser> = {
687            macro_rules! add {
688                ($m:ident, $oid:ident, $p:ident) => {
689                    $m.insert($oid, $p as ExtParser);
690                };
691            }
692
693            let mut m = HashMap::new();
694            add!(
695                m,
696                OID_X509_EXT_SUBJECT_KEY_IDENTIFIER,
697                parse_keyidentifier_ext
698            );
699            add!(m, OID_X509_EXT_KEY_USAGE, parse_keyusage_ext);
700            add!(
701                m,
702                OID_X509_EXT_SUBJECT_ALT_NAME,
703                parse_subjectalternativename_ext
704            );
705            add!(
706                m,
707                OID_X509_EXT_ISSUER_ALT_NAME,
708                parse_issueralternativename_ext
709            );
710            add!(
711                m,
712                OID_X509_EXT_BASIC_CONSTRAINTS,
713                parse_basicconstraints_ext
714            );
715            add!(m, OID_X509_EXT_NAME_CONSTRAINTS, parse_nameconstraints_ext);
716            add!(
717                m,
718                OID_X509_EXT_CERTIFICATE_POLICIES,
719                parse_certificatepolicies_ext
720            );
721            add!(m, OID_X509_EXT_POLICY_MAPPINGS, parse_policymappings_ext);
722            add!(
723                m,
724                OID_X509_EXT_POLICY_CONSTRAINTS,
725                parse_policyconstraints_ext
726            );
727            add!(
728                m,
729                OID_X509_EXT_EXTENDED_KEY_USAGE,
730                parse_extendedkeyusage_ext
731            );
732            add!(
733                m,
734                OID_X509_EXT_CRL_DISTRIBUTION_POINTS,
735                parse_crldistributionpoints_ext
736            );
737            add!(
738                m,
739                OID_X509_EXT_INHIBIT_ANY_POLICY,
740                parse_inhibitanypolicy_ext
741            );
742            add!(
743                m,
744                OID_PKIX_AUTHORITY_INFO_ACCESS,
745                parse_authorityinfoaccess_ext
746            );
747            add!(m, OID_PKIX_SUBJECT_INFO_ACCESS, parse_subjectinfoaccess_ext);
748            add!(
749                m,
750                OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER,
751                parse_authoritykeyidentifier_ext
752            );
753            add!(m, OID_CT_LIST_SCT, parse_sct_ext);
754            add!(m, OID_X509_EXT_CERT_TYPE, parse_nscerttype_ext);
755            add!(m, OID_X509_EXT_CERT_COMMENT, parse_nscomment_ext);
756            add!(m, OID_X509_EXT_CRL_NUMBER, parse_crl_number);
757            add!(m, OID_X509_EXT_REASON_CODE, parse_reason_code);
758            add!(m, OID_X509_EXT_INVALIDITY_DATE, parse_invalidity_date);
759            add!(
760                m,
761                OID_X509_EXT_ISSUER_DISTRIBUTION_POINT,
762                parse_issuingdistributionpoint_ext
763            );
764            m
765        };
766    }
767
768    // look into the parser map if the extension is known, and parse it
769    // otherwise, leave it as UnsupportedExtension
770    fn parse_extension0<'a>(
771        orig_i: &'a [u8],
772        i: &'a [u8],
773        oid: &Oid,
774    ) -> IResult<&'a [u8], ParsedExtension<'a>, BerError> {
775        if let Some(parser) = EXTENSION_PARSERS.get(oid) {
776            match parser(i) {
777                Ok((_, ext)) => Ok((orig_i, ext)),
778                Err(error) => Ok((orig_i, ParsedExtension::ParseError { error })),
779            }
780        } else {
781            Ok((
782                orig_i,
783                ParsedExtension::UnsupportedExtension {
784                    oid: oid.to_owned(),
785                },
786            ))
787        }
788    }
789
790    pub(crate) fn parse_extension<'a>(
791        orig_i: &'a [u8],
792        i: &'a [u8],
793        oid: &Oid,
794    ) -> IResult<&'a [u8], ParsedExtension<'a>, BerError> {
795        parse_extension0(orig_i, i, oid)
796    }
797
798    /// Parse a "Basic Constraints" extension
799    ///
800    /// <pre>
801    ///   id-ce-basicConstraints OBJECT IDENTIFIER ::=  { id-ce 19 }
802    ///   BasicConstraints ::= SEQUENCE {
803    ///        cA                      BOOLEAN DEFAULT FALSE,
804    ///        pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
805    /// </pre>
806    ///
807    /// Note the maximum length of the `pathLenConstraint` field is limited to the size of a 32-bits
808    /// unsigned integer, and parsing will fail if value if larger.
809    pub(super) fn parse_basicconstraints(i: &[u8]) -> IResult<&[u8], BasicConstraints, BerError> {
810        let (rem, obj) = parse_der_sequence(i)?;
811        if let Ok(seq) = obj.as_sequence() {
812            let (ca, path_len_constraint) = match seq.len() {
813                0 => (false, None),
814                1 => {
815                    if let Ok(b) = seq[0].as_bool() {
816                        (b, None)
817                    } else if let Ok(u) = seq[0].as_u32() {
818                        (false, Some(u))
819                    } else {
820                        return Err(Err::Error(BerError::InvalidTag));
821                    }
822                }
823                2 => {
824                    let ca = seq[0]
825                        .as_bool()
826                        .or(Err(Err::Error(BerError::InvalidLength)))?;
827                    let pl = seq[1]
828                        .as_u32()
829                        .or(Err(Err::Error(BerError::InvalidLength)))?;
830                    (ca, Some(pl))
831                }
832                _ => return Err(Err::Error(BerError::InvalidLength)),
833            };
834            Ok((
835                rem,
836                BasicConstraints {
837                    ca,
838                    path_len_constraint,
839                },
840            ))
841        } else {
842            Err(Err::Error(BerError::InvalidLength))
843        }
844    }
845
846    fn parse_basicconstraints_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
847        map(parse_basicconstraints, ParsedExtension::BasicConstraints)(i)
848    }
849
850    fn parse_nameconstraints_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
851        map(parse_nameconstraints, ParsedExtension::NameConstraints)(i)
852    }
853
854    pub(super) fn parse_subjectalternativename_ext(
855        i: &[u8],
856    ) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
857        parse_der_sequence_defined_g(|input, _| {
858            let (i, general_names) = all_consuming(many0(complete(cut(parse_generalname))))(input)?;
859            Ok((
860                i,
861                ParsedExtension::SubjectAlternativeName(SubjectAlternativeName { general_names }),
862            ))
863        })(i)
864    }
865
866    pub(super) fn parse_issueralternativename_ext(
867        i: &[u8],
868    ) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
869        parse_der_sequence_defined_g(|input, _| {
870            let (i, general_names) = all_consuming(many0(complete(cut(parse_generalname))))(input)?;
871            Ok((
872                i,
873                ParsedExtension::IssuerAlternativeName(IssuerAlternativeName { general_names }),
874            ))
875        })(i)
876    }
877
878    pub(super) fn parse_policyconstraints(i: &[u8]) -> IResult<&[u8], PolicyConstraints, BerError> {
879        parse_der_sequence_defined_g(|input, _| {
880            let (i, require_explicit_policy) = opt(complete(map_res(
881                parse_der_tagged_implicit(0, parse_der_content(Tag::Integer)),
882                |x| x.as_u32(),
883            )))(input)?;
884            let (i, inhibit_policy_mapping) = all_consuming(opt(complete(map_res(
885                parse_der_tagged_implicit(1, parse_der_content(Tag::Integer)),
886                |x| x.as_u32(),
887            ))))(i)?;
888            let policy_constraint = PolicyConstraints {
889                require_explicit_policy,
890                inhibit_policy_mapping,
891            };
892            Ok((i, policy_constraint))
893        })(i)
894    }
895
896    fn parse_policyconstraints_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
897        map(parse_policyconstraints, ParsedExtension::PolicyConstraints)(i)
898    }
899
900    fn parse_policymappings_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
901        map(parse_policymappings, ParsedExtension::PolicyMappings)(i)
902    }
903
904    fn parse_inhibitanypolicy_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
905        let (ret, skip_certs) = parse_der_u32(i)?;
906        Ok((
907            ret,
908            ParsedExtension::InhibitAnyPolicy(InhibitAnyPolicy { skip_certs }),
909        ))
910    }
911
912    fn parse_extendedkeyusage_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
913        map(parse_extendedkeyusage, ParsedExtension::ExtendedKeyUsage)(i)
914    }
915
916    // DistributionPointName ::= CHOICE {
917    //     fullName                [0]     GeneralNames,
918    //     nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
919    fn parse_distributionpointname(
920        i: &[u8],
921    ) -> IResult<&[u8], DistributionPointName<'_>, BerError> {
922        let (rem, header) = der_read_element_header(i)?;
923        match header.tag().0 {
924            0 => {
925                let (rem, names) = many1(complete(parse_generalname))(rem)?;
926                Ok((rem, DistributionPointName::FullName(names)))
927            }
928            1 => {
929                let (rem, rdn) = RelativeDistinguishedName::from_der(rem)
930                    .map_err(|_| BerError::BerValueError)?;
931                Ok((rem, DistributionPointName::NameRelativeToCRLIssuer(rdn)))
932            }
933            _ => Err(Err::Error(BerError::InvalidTag)),
934        }
935    }
936
937    fn parse_implicit_tagged_reasons(tag: u32) -> impl Fn(&[u8]) -> BerResult<ReasonFlags> {
938        move |i: &[u8]| {
939            let (rem, obj) = parse_der_tagged_implicit(tag, parse_der_content(Tag::BitString))(i)?;
940            parse_reasons(rem, obj)
941        }
942    }
943
944    // ReasonFlags ::= BIT STRING {
945    // unused                  (0),
946    // keyCompromise           (1),
947    // cACompromise            (2),
948    // affiliationChanged      (3),
949    // superseded              (4),
950    // cessationOfOperation    (5),
951    // certificateHold         (6),
952    // privilegeWithdrawn      (7),
953    // aACompromise            (8) }
954    fn parse_reasons<'a>(rem: &'a [u8], obj: BerObject<'a>) -> BerResult<'a, ReasonFlags> {
955        if let DerObjectContent::BitString(_, b) = obj.content {
956            let flags = b
957                .data
958                .iter()
959                .rev()
960                .fold(0, |acc, x| (acc << 8) | (x.reverse_bits() as u16));
961            Ok((rem, ReasonFlags { flags }))
962        } else {
963            Err(Err::Failure(BerError::InvalidTag))
964        }
965    }
966
967    fn parse_crlissuer_content(i: &[u8]) -> BerResult<'_, Vec<GeneralName<'_>>> {
968        many1(complete(parse_generalname))(i)
969    }
970
971    // DistributionPoint ::= SEQUENCE {
972    //     distributionPoint       [0]     DistributionPointName OPTIONAL,
973    //     reasons                 [1]     ReasonFlags OPTIONAL,
974    //     cRLIssuer               [2]     GeneralNames OPTIONAL }
975    pub(super) fn parse_crldistributionpoint(
976        i: &[u8],
977    ) -> IResult<&[u8], CRLDistributionPoint<'_>, BerError> {
978        parse_der_sequence_defined_g(|content, _| {
979            let (rem, distribution_point) =
980                opt(complete(parse_der_tagged_explicit_g(0, |b, _| {
981                    parse_distributionpointname(b)
982                })))(content)?;
983            let (rem, reasons) = opt(complete(parse_implicit_tagged_reasons(1)))(rem)?;
984            let (rem, crl_issuer) = opt(complete(parse_der_tagged_implicit_g(2, |i, _, _| {
985                parse_crlissuer_content(i)
986            })))(rem)?;
987            let crl_dp = CRLDistributionPoint {
988                distribution_point,
989                reasons,
990                crl_issuer,
991            };
992            Ok((rem, crl_dp))
993        })(i)
994    }
995
996    pub(super) fn parse_crldistributionpoints(
997        i: &[u8],
998    ) -> IResult<&[u8], CRLDistributionPoints<'_>, BerError> {
999        let (ret, crldps) = parse_der_sequence_of_v(parse_crldistributionpoint)(i)?;
1000        Ok((ret, CRLDistributionPoints { points: crldps }))
1001    }
1002
1003    fn parse_crldistributionpoints_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1004        map(
1005            parse_crldistributionpoints,
1006            ParsedExtension::CRLDistributionPoints,
1007        )(i)
1008    }
1009
1010    //  IssuingDistributionPoint ::= SEQUENCE {
1011    //         distributionPoint          [0] DistributionPointName OPTIONAL,
1012    //         onlyContainsUserCerts      [1] BOOLEAN DEFAULT FALSE,
1013    //         onlyContainsCACerts        [2] BOOLEAN DEFAULT FALSE,
1014    //         onlySomeReasons            [3] ReasonFlags OPTIONAL,
1015    //         indirectCRL                [4] BOOLEAN DEFAULT FALSE,
1016    //         onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
1017    pub(super) fn parse_issuingdistributionpoint(
1018        i: &[u8],
1019    ) -> IResult<&[u8], IssuingDistributionPoint<'_>, BerError> {
1020        parse_der_sequence_defined_g(|content, _| {
1021            let parse_tagged_bool = |tag: u32, rem| -> IResult<&[u8], bool, BerError> {
1022                let (rem, value) = opt(complete(|_| {
1023                    parse_der_implicit(rem, tag, parse_der_content(Tag::Boolean))
1024                        .map(|(res, ob)| (res, ob.as_bool().unwrap_or(false)))
1025                }))(rem)?;
1026                Ok((rem, value.unwrap_or_default()))
1027            };
1028
1029            let (rem, distribution_point) =
1030                opt(complete(parse_der_tagged_explicit_g(0, |b, _| {
1031                    parse_distributionpointname(b)
1032                })))(content)?;
1033
1034            let (rem, only_contains_user_certs) = parse_tagged_bool(1, rem)?;
1035            let (rem, only_contains_ca_certs) = parse_tagged_bool(2, rem)?;
1036            let (rem, only_some_reasons) = opt(complete(parse_implicit_tagged_reasons(3)))(rem)?;
1037            let (rem, indirect_crl) = parse_tagged_bool(4, rem)?;
1038            let (rem, only_contains_attribute_certs) = parse_tagged_bool(5, rem)?;
1039
1040            let crl_idp = IssuingDistributionPoint {
1041                distribution_point,
1042                only_contains_user_certs,
1043                only_contains_ca_certs,
1044                only_some_reasons,
1045                indirect_crl,
1046                only_contains_attribute_certs,
1047            };
1048            Ok((rem, crl_idp))
1049        })(i)
1050    }
1051
1052    fn parse_issuingdistributionpoint_ext(
1053        i: &[u8],
1054    ) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1055        map(
1056            parse_issuingdistributionpoint,
1057            ParsedExtension::IssuingDistributionPoint,
1058        )(i)
1059    }
1060
1061    // AuthorityInfoAccessSyntax  ::=
1062    //         SEQUENCE SIZE (1..MAX) OF AccessDescription
1063    //
1064    // AccessDescription  ::=  SEQUENCE {
1065    //         accessMethod          OBJECT IDENTIFIER,
1066    //         accessLocation        GeneralName  }
1067    pub(super) fn parse_authorityinfoaccess(
1068        i: &[u8],
1069    ) -> IResult<&[u8], AuthorityInfoAccess<'_>, BerError> {
1070        fn parse_aia(i: &[u8]) -> IResult<&[u8], AccessDescription<'_>, BerError> {
1071            parse_der_sequence_defined_g(|content, _| {
1072                // Read first element, an oid.
1073                let (gn, oid) = Oid::from_der(content)?;
1074                // Parse second element
1075                let (rest, gn) = parse_generalname(gn)?;
1076                Ok((rest, AccessDescription::new(oid, gn)))
1077            })(i)
1078        }
1079        let (ret, accessdescs) = parse_der_sequence_of_v(parse_aia)(i)?;
1080        Ok((ret, AuthorityInfoAccess { accessdescs }))
1081    }
1082
1083    fn parse_authorityinfoaccess_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1084        map(
1085            parse_authorityinfoaccess,
1086            ParsedExtension::AuthorityInfoAccess,
1087        )(i)
1088    }
1089
1090    // SubjectInfoAccessSyntax  ::=
1091    //         SEQUENCE SIZE (1..MAX) OF AccessDescription
1092    //
1093    // AccessDescription  ::=  SEQUENCE {
1094    //         accessMethod          OBJECT IDENTIFIER,
1095    //         accessLocation        GeneralName  }
1096    pub(super) fn parse_subjectinfoaccess(
1097        i: &[u8],
1098    ) -> IResult<&[u8], SubjectInfoAccess<'_>, BerError> {
1099        fn parse_sia(i: &[u8]) -> IResult<&[u8], AccessDescription<'_>, BerError> {
1100            parse_der_sequence_defined_g(|content, _| {
1101                // Read first element, an oid.
1102                let (gn, oid) = Oid::from_der(content)?;
1103                // Parse second element
1104                let (rest, gn) = parse_generalname(gn)?;
1105                Ok((rest, AccessDescription::new(oid, gn)))
1106            })(i)
1107        }
1108        let (ret, accessdescs) = parse_der_sequence_of_v(parse_sia)(i)?;
1109        Ok((ret, SubjectInfoAccess { accessdescs }))
1110    }
1111
1112    fn parse_subjectinfoaccess_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1113        map(parse_subjectinfoaccess, ParsedExtension::SubjectInfoAccess)(i)
1114    }
1115
1116    fn parse_aki_content<'a>(
1117        i: &'a [u8],
1118        _hdr: Header<'_>,
1119    ) -> IResult<&'a [u8], AuthorityKeyIdentifier<'a>, BerError> {
1120        let (i, key_identifier) = opt(complete(parse_der_tagged_implicit_g(0, |d, _, _| {
1121            Ok((&[], KeyIdentifier(d)))
1122        })))(i)?;
1123        let (i, authority_cert_issuer) =
1124            opt(complete(parse_der_tagged_implicit_g(1, |d, _, _| {
1125                many0(complete(parse_generalname))(d)
1126            })))(i)?;
1127        let (i, authority_cert_serial) = opt(complete(parse_der_tagged_implicit(
1128            2,
1129            parse_der_content(Tag::Integer),
1130        )))(i)?;
1131        let authority_cert_serial = authority_cert_serial.and_then(|o| o.as_slice().ok());
1132        let aki = AuthorityKeyIdentifier {
1133            key_identifier,
1134            authority_cert_issuer,
1135            authority_cert_serial,
1136        };
1137        Ok((i, aki))
1138    }
1139
1140    // RFC 5280 section 4.2.1.1: Authority Key Identifier
1141    pub(super) fn parse_authoritykeyidentifier(
1142        i: &[u8],
1143    ) -> IResult<&[u8], AuthorityKeyIdentifier<'_>, BerError> {
1144        let (rem, aki) = parse_der_sequence_defined_g(parse_aki_content)(i)?;
1145        Ok((rem, aki))
1146    }
1147
1148    fn parse_authoritykeyidentifier_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1149        map(
1150            parse_authoritykeyidentifier,
1151            ParsedExtension::AuthorityKeyIdentifier,
1152        )(i)
1153    }
1154
1155    pub(super) fn parse_keyidentifier(i: &[u8]) -> IResult<&[u8], KeyIdentifier<'_>, BerError> {
1156        let (rest, id) = <&[u8]>::from_der(i)?;
1157        let ki = KeyIdentifier(id);
1158        Ok((rest, ki))
1159    }
1160
1161    fn parse_keyidentifier_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1162        map(parse_keyidentifier, ParsedExtension::SubjectKeyIdentifier)(i)
1163    }
1164
1165    fn parse_keyusage_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1166        map(parse_keyusage, ParsedExtension::KeyUsage)(i)
1167    }
1168
1169    pub(super) fn parse_nscerttype(i: &[u8]) -> IResult<&[u8], NSCertType, BerError> {
1170        let (rest, obj) = parse_der_bitstring(i)?;
1171        let bitstring = obj
1172            .content
1173            .as_bitstring()
1174            .or(Err(Err::Error(BerError::BerTypeError)))?;
1175        // bitstring should be 1 byte long
1176        if bitstring.data.len() != 1 {
1177            return Err(Err::Error(BerError::BerValueError));
1178        }
1179        let flags = bitstring.data[0].reverse_bits();
1180        Ok((rest, NSCertType(flags)))
1181    }
1182
1183    fn parse_nscerttype_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1184        map(parse_nscerttype, ParsedExtension::NSCertType)(i)
1185    }
1186
1187    fn parse_nscomment_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1188        match parse_der_ia5string(i) {
1189            Ok((i, obj)) => {
1190                let s = obj.as_str()?;
1191                Ok((i, ParsedExtension::NsCertComment(s)))
1192            }
1193            Err(e) => {
1194                // Some implementations encode the comment directly, without
1195                // wrapping it in an IA5String
1196                if let Ok(s) = std::str::from_utf8(i) {
1197                    Ok((&[], ParsedExtension::NsCertComment(s)))
1198                } else {
1199                    Err(e)
1200                }
1201            }
1202        }
1203    }
1204
1205    // CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
1206    //
1207    // PolicyInformation ::= SEQUENCE {
1208    //      policyIdentifier   CertPolicyId,
1209    //      policyQualifiers   SEQUENCE SIZE (1..MAX) OF
1210    //              PolicyQualifierInfo OPTIONAL }
1211    //
1212    // CertPolicyId ::= OBJECT IDENTIFIER
1213    //
1214    // PolicyQualifierInfo ::= SEQUENCE {
1215    //      policyQualifierId  PolicyQualifierId,
1216    //      qualifier          ANY DEFINED BY policyQualifierId }
1217    //
1218    // -- Implementations that recognize additional policy qualifiers MUST
1219    // -- augment the following definition for PolicyQualifierId
1220    //
1221    // PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
1222    pub(super) fn parse_certificatepolicies(
1223        i: &[u8],
1224    ) -> IResult<&[u8], Vec<PolicyInformation<'_>>, BerError> {
1225        fn parse_policy_qualifier_info(
1226            i: &[u8],
1227        ) -> IResult<&[u8], PolicyQualifierInfo<'_>, BerError> {
1228            parse_der_sequence_defined_g(|content, _| {
1229                let (rem, policy_qualifier_id) = Oid::from_der(content)?;
1230                let info = PolicyQualifierInfo {
1231                    policy_qualifier_id,
1232                    qualifier: rem,
1233                };
1234                Ok((&[], info))
1235            })(i)
1236        }
1237        fn parse_policy_information(i: &[u8]) -> IResult<&[u8], PolicyInformation<'_>, BerError> {
1238            parse_der_sequence_defined_g(|content, _| {
1239                let (rem, policy_id) = Oid::from_der(content)?;
1240                let (rem, policy_qualifiers) =
1241                    opt(complete(parse_der_sequence_defined_g(|content, _| {
1242                        many1(complete(parse_policy_qualifier_info))(content)
1243                    })))(rem)?;
1244                let info = PolicyInformation {
1245                    policy_id,
1246                    policy_qualifiers,
1247                };
1248                Ok((rem, info))
1249            })(i)
1250        }
1251        parse_der_sequence_of_v(parse_policy_information)(i)
1252    }
1253
1254    fn parse_certificatepolicies_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1255        map(
1256            parse_certificatepolicies,
1257            ParsedExtension::CertificatePolicies,
1258        )(i)
1259    }
1260
1261    // CRLReason ::= ENUMERATED { ...
1262    fn parse_reason_code(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1263        let (rest, obj) = parse_der_enum(i)?;
1264        let code = obj
1265            .content
1266            .as_u32()
1267            .or(Err(Err::Error(BerError::BerValueError)))?;
1268        if code > 10 {
1269            return Err(Err::Error(BerError::BerValueError));
1270        }
1271        let ret = ParsedExtension::ReasonCode(ReasonCode(code as u8));
1272        Ok((rest, ret))
1273    }
1274
1275    // invalidityDate ::=  GeneralizedTime
1276    fn parse_invalidity_date(i: &[u8]) -> ParseResult<'_, ParsedExtension<'_>> {
1277        let (rest, t) = GeneralizedTime::from_der(i)?;
1278        let dt = t.utc_datetime()?;
1279        Ok((rest, ParsedExtension::InvalidityDate(ASN1Time::new(dt))))
1280    }
1281
1282    // CRLNumber ::= INTEGER (0..MAX)
1283    // Note from RFC 3280: "CRL verifiers MUST be able to handle CRLNumber values up to 20 octets."
1284    fn parse_crl_number(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1285        let (rest, num) = map_res(parse_der_integer, |obj| obj.as_biguint())(i)?;
1286        Ok((rest, ParsedExtension::CRLNumber(num)))
1287    }
1288
1289    fn parse_sct_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1290        map(
1291            parse_ct_signed_certificate_timestamp_list,
1292            ParsedExtension::SCT,
1293        )(i)
1294    }
1295}
1296
1297/// Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
1298pub(crate) fn parse_extension_sequence(i: &[u8]) -> X509Result<'_, Vec<X509Extension<'_>>> {
1299    parse_der_sequence_defined_g(|a, _| all_consuming(many0(complete(X509Extension::from_der)))(a))(
1300        i,
1301    )
1302}
1303
1304pub(crate) fn parse_extensions(
1305    i: &[u8],
1306    explicit_tag: Tag,
1307) -> X509Result<'_, Vec<X509Extension<'_>>> {
1308    if i.is_empty() {
1309        return Ok((i, Vec::new()));
1310    }
1311
1312    match der_read_element_header(i) {
1313        Ok((rem, hdr)) => {
1314            if hdr.tag() != explicit_tag {
1315                return Err(Err::Error(X509Error::InvalidExtensions));
1316            }
1317            all_consuming(parse_extension_sequence)(rem)
1318        }
1319        Err(_) => Err(X509Error::InvalidExtensions.into()),
1320    }
1321}
1322
1323/// Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
1324pub(crate) fn parse_extension_envelope_sequence(
1325    i: &[u8],
1326) -> X509Result<'_, Vec<X509Extension<'_>>> {
1327    let parser = X509ExtensionParser::new().with_deep_parse_extensions(false);
1328
1329    parse_der_sequence_defined_g(move |a, _| all_consuming(many0(complete(parser)))(a))(i)
1330}
1331
1332pub(crate) fn parse_extensions_envelope(
1333    i: &[u8],
1334    explicit_tag: Tag,
1335) -> X509Result<'_, Vec<X509Extension<'_>>> {
1336    if i.is_empty() {
1337        return Ok((i, Vec::new()));
1338    }
1339
1340    match der_read_element_header(i) {
1341        Ok((rem, hdr)) => {
1342            if hdr.tag() != explicit_tag {
1343                return Err(Err::Error(X509Error::InvalidExtensions));
1344            }
1345            all_consuming(parse_extension_envelope_sequence)(rem)
1346        }
1347        Err(_) => Err(X509Error::InvalidExtensions.into()),
1348    }
1349}
1350
1351fn der_read_critical(i: &[u8]) -> BerResult<'_, bool> {
1352    // Some certificates do not respect the DER BOOLEAN constraint (true must be encoded as 0xff)
1353    // so we attempt to parse as BER
1354    let (rem, obj) = opt(parse_ber_bool)(i)?;
1355    let value = obj
1356        .map(|o| o.as_bool().unwrap_or_default()) // unwrap cannot fail, we just read a bool
1357        .unwrap_or(false) // default critical value
1358        ;
1359    Ok((rem, value))
1360}
1361
1362#[cfg(test)]
1363mod tests {
1364    use super::*;
1365
1366    #[test]
1367    fn test_keyusage_flags() {
1368        let ku = KeyUsage { flags: 98 };
1369        assert!(!ku.digital_signature());
1370        assert!(ku.non_repudiation());
1371        assert!(!ku.key_encipherment());
1372        assert!(!ku.data_encipherment());
1373        assert!(!ku.key_agreement());
1374        assert!(ku.key_cert_sign());
1375        assert!(ku.crl_sign());
1376        assert!(!ku.encipher_only());
1377        assert!(!ku.decipher_only());
1378    }
1379
1380    #[test]
1381    fn test_extensions1() {
1382        use der_parser::oid;
1383        let crt = crate::parse_x509_certificate(include_bytes!("../../assets/extension1.der"))
1384            .unwrap()
1385            .1;
1386        let tbs = &crt.tbs_certificate;
1387        let bc = crt
1388            .basic_constraints()
1389            .expect("could not get basic constraints")
1390            .expect("no basic constraints found");
1391        assert_eq!(
1392            bc.value,
1393            &BasicConstraints {
1394                ca: true,
1395                path_len_constraint: Some(1)
1396            }
1397        );
1398        {
1399            let ku = tbs
1400                .key_usage()
1401                .expect("could not get key usage")
1402                .expect("no key usage found")
1403                .value;
1404            assert!(ku.digital_signature());
1405            assert!(!ku.non_repudiation());
1406            assert!(ku.key_encipherment());
1407            assert!(ku.data_encipherment());
1408            assert!(ku.key_agreement());
1409            assert!(!ku.key_cert_sign());
1410            assert!(!ku.crl_sign());
1411            assert!(ku.encipher_only());
1412            assert!(ku.decipher_only());
1413        }
1414        {
1415            let eku = tbs
1416                .extended_key_usage()
1417                .expect("could not get extended key usage")
1418                .expect("no extended key usage found")
1419                .value;
1420            assert!(!eku.any);
1421            assert!(eku.server_auth);
1422            assert!(!eku.client_auth);
1423            assert!(eku.code_signing);
1424            assert!(!eku.email_protection);
1425            assert!(eku.time_stamping);
1426            assert!(!eku.ocsp_signing);
1427            assert_eq!(eku.other, vec![oid!(1.2.3 .4 .0 .42)]);
1428        }
1429        assert_eq!(
1430            tbs.policy_constraints()
1431                .expect("could not get policy constraints")
1432                .expect("no policy constraints found")
1433                .value,
1434            &PolicyConstraints {
1435                require_explicit_policy: None,
1436                inhibit_policy_mapping: Some(10)
1437            }
1438        );
1439        let val = tbs
1440            .inhibit_anypolicy()
1441            .expect("could not get inhibit_anypolicy")
1442            .expect("no inhibit_anypolicy found")
1443            .value;
1444        assert_eq!(val, &InhibitAnyPolicy { skip_certs: 2 });
1445        {
1446            let alt_names = &tbs
1447                .subject_alternative_name()
1448                .expect("could not get subject alt names")
1449                .expect("no subject alt names found")
1450                .value
1451                .general_names;
1452            assert_eq!(alt_names[0], GeneralName::RFC822Name("foo@example.com"));
1453            assert_eq!(alt_names[1], GeneralName::URI("http://my.url.here/"));
1454            assert_eq!(
1455                alt_names[2],
1456                GeneralName::IPAddress([192, 168, 7, 1].as_ref())
1457            );
1458            assert_eq!(
1459                format!(
1460                    "{}",
1461                    match alt_names[3] {
1462                        GeneralName::DirectoryName(ref dn) => dn,
1463                        _ => unreachable!(),
1464                    }
1465                ),
1466                "C=UK, O=My Organization, OU=My Unit, CN=My Name"
1467            );
1468            assert_eq!(alt_names[4], GeneralName::DNSName("localhost"));
1469            assert_eq!(alt_names[5], GeneralName::RegisteredID(oid!(1.2.90 .0)));
1470            assert_eq!(
1471                alt_names[6],
1472                GeneralName::OtherName(oid!(1.2.3 .4), b"\xA0\x17\x0C\x15some other identifier")
1473            );
1474        }
1475
1476        {
1477            let name_constraints = &tbs
1478                .name_constraints()
1479                .expect("could not get name constraints")
1480                .expect("no name constraints found")
1481                .value;
1482            assert_eq!(name_constraints.permitted_subtrees, None);
1483            assert_eq!(
1484                name_constraints.excluded_subtrees,
1485                Some(vec![
1486                    GeneralSubtree {
1487                        base: GeneralName::IPAddress([192, 168, 0, 0, 255, 255, 0, 0].as_ref())
1488                    },
1489                    GeneralSubtree {
1490                        base: GeneralName::RFC822Name("foo.com")
1491                    },
1492                ])
1493            );
1494        }
1495    }
1496
1497    #[test]
1498    fn test_extensions2() {
1499        use der_parser::oid;
1500        let crt = crate::parse_x509_certificate(include_bytes!("../../assets/extension2.der"))
1501            .unwrap()
1502            .1;
1503        let tbs = crt.tbs_certificate;
1504        assert_eq!(
1505            tbs.policy_constraints()
1506                .expect("could not get policy constraints")
1507                .expect("no policy constraints found")
1508                .value,
1509            &PolicyConstraints {
1510                require_explicit_policy: Some(5000),
1511                inhibit_policy_mapping: None
1512            }
1513        );
1514        {
1515            let pm = tbs
1516                .policy_mappings()
1517                .expect("could not get policy_mappings")
1518                .expect("no policy_mappings found")
1519                .value
1520                .clone()
1521                .into_hashmap();
1522            let mut pm_ref = HashMap::new();
1523            pm_ref.insert(oid!(2.34.23), vec![oid!(2.2)]);
1524            pm_ref.insert(oid!(1.1), vec![oid!(0.0.4)]);
1525            pm_ref.insert(oid!(2.2), vec![oid!(2.2.1), oid!(2.2.3)]);
1526            assert_eq!(pm, pm_ref);
1527        }
1528    }
1529
1530    #[test]
1531    fn test_extensions_crl_distribution_points() {
1532        // Extension not present
1533        {
1534            let crt = crate::parse_x509_certificate(include_bytes!(
1535                "../../assets/crl-ext/crl-no-crl.der"
1536            ))
1537            .unwrap()
1538            .1;
1539            assert!(!crt
1540                .tbs_certificate
1541                .extensions_map()
1542                .unwrap()
1543                .contains_key(&OID_X509_EXT_CRL_DISTRIBUTION_POINTS));
1544        }
1545        // CRLDistributionPoints has 1 entry with 1 URI
1546        {
1547            let crt = crate::parse_x509_certificate(include_bytes!(
1548                "../../assets/crl-ext/crl-simple.der"
1549            ))
1550            .unwrap()
1551            .1;
1552            let crl = crt
1553                .tbs_certificate
1554                .extensions_map()
1555                .unwrap()
1556                .get(&OID_X509_EXT_CRL_DISTRIBUTION_POINTS)
1557                .unwrap()
1558                .parsed_extension();
1559            assert!(matches!(crl, ParsedExtension::CRLDistributionPoints(_)));
1560            if let ParsedExtension::CRLDistributionPoints(crl) = crl {
1561                assert_eq!(crl.len(), 1);
1562                assert!(crl[0].reasons.is_none());
1563                assert!(crl[0].crl_issuer.is_none());
1564                let distribution_point = crl[0].distribution_point.as_ref().unwrap();
1565                assert!(matches!(
1566                    distribution_point,
1567                    DistributionPointName::FullName(_)
1568                ));
1569                if let DistributionPointName::FullName(names) = distribution_point {
1570                    assert_eq!(names.len(), 1);
1571                    assert!(matches!(names[0], GeneralName::URI(_)));
1572                    if let GeneralName::URI(uri) = names[0] {
1573                        assert_eq!(uri, "http://example.com/myca.crl")
1574                    }
1575                }
1576            }
1577        }
1578        // CRLDistributionPoints has 2 entries
1579        {
1580            let crt = crate::parse_x509_certificate(include_bytes!(
1581                "../../assets/crl-ext/crl-complex.der"
1582            ))
1583            .unwrap()
1584            .1;
1585            let crl = crt
1586                .tbs_certificate
1587                .extensions_map()
1588                .unwrap()
1589                .get(&OID_X509_EXT_CRL_DISTRIBUTION_POINTS)
1590                .unwrap()
1591                .parsed_extension();
1592            assert!(matches!(crl, ParsedExtension::CRLDistributionPoints(_)));
1593            if let ParsedExtension::CRLDistributionPoints(crl) = crl {
1594                assert_eq!(crl.len(), 2);
1595                // First CRL Distribution point
1596                let reasons = crl[0].reasons.as_ref().unwrap();
1597                assert!(reasons.key_compromise());
1598                assert!(reasons.ca_compromise());
1599                assert!(!reasons.affilation_changed());
1600                assert!(!reasons.superseded());
1601                assert!(!reasons.cessation_of_operation());
1602                assert!(!reasons.certificate_hold());
1603                assert!(!reasons.privelege_withdrawn());
1604                assert!(reasons.aa_compromise());
1605                assert_eq!(
1606                    format!("{reasons}"),
1607                    "Key Compromise, CA Compromise, AA Compromise"
1608                );
1609                let issuers = crl[0].crl_issuer.as_ref().unwrap();
1610                assert_eq!(issuers.len(), 1);
1611                assert!(matches!(issuers[0], GeneralName::DirectoryName(_)));
1612                if let GeneralName::DirectoryName(name) = &issuers[0] {
1613                    assert_eq!(name.to_string(), "C=US, O=Organisation, CN=Some Name");
1614                }
1615                let distribution_point = crl[0].distribution_point.as_ref().unwrap();
1616                assert!(matches!(
1617                    distribution_point,
1618                    DistributionPointName::FullName(_)
1619                ));
1620                if let DistributionPointName::FullName(names) = distribution_point {
1621                    assert_eq!(names.len(), 1);
1622                    assert!(matches!(names[0], GeneralName::URI(_)));
1623                    if let GeneralName::URI(uri) = names[0] {
1624                        assert_eq!(uri, "http://example.com/myca.crl")
1625                    }
1626                }
1627                // Second CRL Distribution point
1628                let reasons = crl[1].reasons.as_ref().unwrap();
1629                assert!(reasons.key_compromise());
1630                assert!(reasons.ca_compromise());
1631                assert!(!reasons.affilation_changed());
1632                assert!(!reasons.superseded());
1633                assert!(!reasons.cessation_of_operation());
1634                assert!(!reasons.certificate_hold());
1635                assert!(!reasons.privelege_withdrawn());
1636                assert!(!reasons.aa_compromise());
1637                assert_eq!(format!("{reasons}"), "Key Compromise, CA Compromise");
1638                assert!(crl[1].crl_issuer.is_none());
1639                let distribution_point = crl[1].distribution_point.as_ref().unwrap();
1640                assert!(matches!(
1641                    distribution_point,
1642                    DistributionPointName::FullName(_)
1643                ));
1644                if let DistributionPointName::FullName(names) = distribution_point {
1645                    assert_eq!(names.len(), 1);
1646                    assert!(matches!(names[0], GeneralName::URI(_)));
1647                    if let GeneralName::URI(uri) = names[0] {
1648                        assert_eq!(uri, "http://example.com/myca2.crl")
1649                    }
1650                }
1651            }
1652        }
1653    }
1654
1655    // Test cases for:
1656    // - parsing SubjectAlternativeName
1657    // - parsing NameConstraints
1658}