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