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