1use 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 der_parser::oid::Oid;
14use nom::combinator::{all_consuming, complete, cut, map, map_res, opt};
15use nom::multi::{many0, many1};
16use nom::{Err, IResult, Parser};
17use oid_registry::*;
18use std::collections::HashMap;
19use std::fmt::{self, LowerHex};
20
21mod generalname;
22mod keyusage;
23mod nameconstraints;
24mod policymappings;
25mod sct;
26
27pub use generalname::*;
28pub use keyusage::*;
29pub use nameconstraints::*;
30pub use policymappings::*;
31pub use sct::*;
32
33#[derive(Clone, Debug, PartialEq)]
84pub struct X509Extension<'a> {
85 pub oid: Oid<'a>,
87 pub critical: bool,
91 pub value: &'a [u8],
93 pub(crate) parsed_extension: ParsedExtension<'a>,
94}
95
96impl<'a> X509Extension<'a> {
97 #[inline]
99 pub const fn new(
100 oid: Oid<'a>,
101 critical: bool,
102 value: &'a [u8],
103 parsed_extension: ParsedExtension<'a>,
104 ) -> X509Extension<'a> {
105 X509Extension {
106 oid,
107 critical,
108 value,
109 parsed_extension,
110 }
111 }
112
113 #[inline]
115 pub fn parsed_extension(&self) -> &ParsedExtension<'a> {
116 &self.parsed_extension
117 }
118}
119
120impl<'a> FromDer<'a, X509Error> for X509Extension<'a> {
127 fn from_der(i: &'a [u8]) -> X509Result<Self> {
128 X509ExtensionParser::new().parse(i)
129 }
130}
131
132#[derive(Clone, Copy, Debug)]
134pub struct X509ExtensionParser {
135 deep_parse_extensions: bool,
136}
137
138impl X509ExtensionParser {
139 #[inline]
140 pub const fn new() -> Self {
141 X509ExtensionParser {
142 deep_parse_extensions: true,
143 }
144 }
145
146 #[inline]
147 pub const fn with_deep_parse_extensions(self, deep_parse_extensions: bool) -> Self {
148 X509ExtensionParser {
149 deep_parse_extensions,
150 }
151 }
152}
153
154impl<'a> Parser<&'a [u8], X509Extension<'a>, X509Error> for X509ExtensionParser {
155 fn parse(&mut self, input: &'a [u8]) -> IResult<&'a [u8], X509Extension<'a>, X509Error> {
156 parse_der_sequence_defined_g(|i, _| {
157 let (i, oid) = Oid::from_der(i)?;
158 let (i, critical) = der_read_critical(i)?;
159 let (i, value) = <&[u8]>::from_der(i)?;
160 let (i, parsed_extension) = if self.deep_parse_extensions {
161 parser::parse_extension(i, value, &oid)?
162 } else {
163 (&[] as &[_], ParsedExtension::Unparsed)
164 };
165 let ext = X509Extension {
166 oid,
167 critical,
168 value,
169 parsed_extension,
170 };
171 Ok((i, ext))
172 })(input)
173 .map_err(|_| X509Error::InvalidExtensions.into())
174 }
175}
176
177#[derive(Clone, Debug, PartialEq)]
178pub enum ParsedExtension<'a> {
179 UnsupportedExtension {
181 oid: Oid<'a>,
182 },
183 ParseError {
184 error: Err<BerError>,
185 },
186 AuthorityKeyIdentifier(AuthorityKeyIdentifier<'a>),
188 SubjectKeyIdentifier(KeyIdentifier<'a>),
190 KeyUsage(KeyUsage),
192 CertificatePolicies(CertificatePolicies<'a>),
194 PolicyMappings(PolicyMappings<'a>),
196 SubjectAlternativeName(SubjectAlternativeName<'a>),
198 IssuerAlternativeName(IssuerAlternativeName<'a>),
200 BasicConstraints(BasicConstraints),
202 NameConstraints(NameConstraints<'a>),
204 PolicyConstraints(PolicyConstraints),
206 ExtendedKeyUsage(ExtendedKeyUsage<'a>),
208 CRLDistributionPoints(CRLDistributionPoints<'a>),
210 InhibitAnyPolicy(InhibitAnyPolicy),
212 AuthorityInfoAccess(AuthorityInfoAccess<'a>),
214 NSCertType(NSCertType),
216 NsCertComment(&'a str),
218 IssuingDistributionPoint(IssuingDistributionPoint<'a>),
220 CRLNumber(BigUint),
222 ReasonCode(ReasonCode),
224 InvalidityDate(ASN1Time),
226 SCT(Vec<SignedCertificateTimestamp<'a>>),
228 Unparsed,
230}
231
232impl<'a> ParsedExtension<'a> {
233 pub fn unsupported(&self) -> bool {
235 matches!(self, &ParsedExtension::UnsupportedExtension { .. })
236 }
237
238 pub fn error(&self) -> Option<&Err<BerError>> {
240 match self {
241 ParsedExtension::ParseError { error } => Some(error),
242 _ => None,
243 }
244 }
245}
246
247#[derive(Clone, Debug, PartialEq)]
248pub struct AuthorityKeyIdentifier<'a> {
249 pub key_identifier: Option<KeyIdentifier<'a>>,
250 pub authority_cert_issuer: Option<Vec<GeneralName<'a>>>,
251 pub authority_cert_serial: Option<&'a [u8]>,
252}
253
254impl<'a> FromDer<'a, X509Error> for AuthorityKeyIdentifier<'a> {
255 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
256 parser::parse_authoritykeyidentifier(i).map_err(Err::convert)
257 }
258}
259
260pub type CertificatePolicies<'a> = Vec<PolicyInformation<'a>>;
261
262#[derive(Clone, Debug, PartialEq, Eq)]
269pub struct PolicyInformation<'a> {
270 pub policy_id: Oid<'a>,
271 pub policy_qualifiers: Option<Vec<PolicyQualifierInfo<'a>>>,
272}
273
274#[derive(Clone, Debug, PartialEq, Eq)]
275pub struct PolicyQualifierInfo<'a> {
276 pub policy_qualifier_id: Oid<'a>,
277 pub qualifier: &'a [u8],
278}
279
280#[derive(Clone, Debug, PartialEq, Eq)]
282pub struct BasicConstraints {
283 pub ca: bool,
284 pub path_len_constraint: Option<u32>,
285}
286
287impl<'a> FromDer<'a, X509Error> for BasicConstraints {
288 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
289 parser::parse_basicconstraints(i).map_err(Err::convert)
290 }
291}
292
293#[derive(Clone, Debug, PartialEq, Eq)]
294pub struct KeyIdentifier<'a>(pub &'a [u8]);
295
296impl<'a> FromDer<'a, X509Error> for KeyIdentifier<'a> {
297 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
298 parser::parse_keyidentifier(i).map_err(Err::convert)
299 }
300}
301
302impl<'a> LowerHex for KeyIdentifier<'a> {
303 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
304 let s = format_serial(self.0);
305 f.write_str(&s)
306 }
307}
308
309#[derive(Clone, Copy, Debug, PartialEq, Eq)]
310pub struct NSCertType(u8);
311
312impl NSCertType {
323 pub fn ssl_client(&self) -> bool {
324 self.0 & 0x1 == 1
325 }
326 pub fn ssl_server(&self) -> bool {
327 (self.0 >> 1) & 1 == 1
328 }
329 pub fn smime(&self) -> bool {
330 (self.0 >> 2) & 1 == 1
331 }
332 pub fn object_signing(&self) -> bool {
333 (self.0 >> 3) & 1 == 1
334 }
335 pub fn ssl_ca(&self) -> bool {
336 (self.0 >> 5) & 1 == 1
337 }
338 pub fn smime_ca(&self) -> bool {
339 (self.0 >> 6) & 1 == 1
340 }
341 pub fn object_signing_ca(&self) -> bool {
342 (self.0 >> 7) & 1 == 1
343 }
344}
345
346const NS_CERT_TYPE_FLAGS: &[&str] = &[
347 "SSL CLient",
348 "SSL Server",
349 "S/MIME",
350 "Object Signing",
351 "Reserved",
352 "SSL CA",
353 "S/MIME CA",
354 "Object Signing CA",
355];
356
357impl fmt::Display for NSCertType {
358 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359 let mut s = String::new();
360 let mut acc = self.0;
361 for flag_text in NS_CERT_TYPE_FLAGS {
362 if acc & 1 != 0 {
363 s = s + flag_text + ", ";
364 }
365 acc >>= 1;
366 }
367 s.pop();
368 s.pop();
369 f.write_str(&s)
370 }
371}
372
373impl<'a> FromDer<'a, X509Error> for NSCertType {
374 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
375 parser::parse_nscerttype(i).map_err(Err::convert)
376 }
377}
378
379#[derive(Clone, Debug, PartialEq)]
380pub struct AuthorityInfoAccess<'a> {
381 pub accessdescs: Vec<AccessDescription<'a>>,
382}
383
384impl<'a> AuthorityInfoAccess<'a> {
385 pub fn iter(&self) -> impl Iterator<Item = &AccessDescription<'a>> {
387 self.accessdescs.iter()
388 }
389
390 pub fn as_hashmap(&self) -> HashMap<Oid<'a>, Vec<&GeneralName<'a>>> {
394 let mut m: HashMap<Oid, Vec<&GeneralName>> = HashMap::new();
396 for desc in &self.accessdescs {
397 let AccessDescription {
398 access_method: oid,
399 access_location: gn,
400 } = desc;
401 if let Some(general_names) = m.get_mut(oid) {
402 general_names.push(gn);
403 } else {
404 m.insert(oid.clone(), vec![gn]);
405 }
406 }
407 m
408 }
409
410 pub fn into_hashmap(self) -> HashMap<Oid<'a>, Vec<GeneralName<'a>>> {
414 let mut aia_list = self.accessdescs;
415 let mut m: HashMap<Oid, Vec<GeneralName>> = HashMap::new();
417 for desc in aia_list.drain(..) {
418 let AccessDescription {
419 access_method: oid,
420 access_location: gn,
421 } = desc;
422 if let Some(general_names) = m.get_mut(&oid) {
423 general_names.push(gn);
424 } else {
425 m.insert(oid, vec![gn]);
426 }
427 }
428 m
429 }
430}
431
432impl<'a> FromDer<'a, X509Error> for AuthorityInfoAccess<'a> {
433 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
434 parser::parse_authorityinfoaccess(i).map_err(Err::convert)
435 }
436}
437
438#[derive(Clone, Debug, PartialEq)]
439pub struct AccessDescription<'a> {
440 pub access_method: Oid<'a>,
441 pub access_location: GeneralName<'a>,
442}
443
444impl<'a> AccessDescription<'a> {
445 pub const fn new(access_method: Oid<'a>, access_location: GeneralName<'a>) -> Self {
446 AccessDescription {
447 access_method,
448 access_location,
449 }
450 }
451}
452
453#[derive(Clone, Debug, PartialEq, Eq)]
454pub struct InhibitAnyPolicy {
455 pub skip_certs: u32,
456}
457
458impl<'a> FromDer<'a, X509Error> for InhibitAnyPolicy {
459 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
460 map(parse_der_u32, |skip_certs| InhibitAnyPolicy { skip_certs })(i).map_err(Err::convert)
461 }
462}
463
464#[derive(Clone, Debug, PartialEq, Eq)]
465pub struct PolicyConstraints {
466 pub require_explicit_policy: Option<u32>,
467 pub inhibit_policy_mapping: Option<u32>,
468}
469
470impl<'a> FromDer<'a, X509Error> for PolicyConstraints {
471 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
472 parser::parse_policyconstraints(i).map_err(Err::convert)
473 }
474}
475
476#[derive(Clone, Debug, PartialEq)]
477pub struct SubjectAlternativeName<'a> {
478 pub general_names: Vec<GeneralName<'a>>,
479}
480
481impl<'a> FromDer<'a, X509Error> for SubjectAlternativeName<'a> {
482 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
483 parse_der_sequence_defined_g(|input, _| {
484 let (i, general_names) =
485 all_consuming(many0(complete(cut(GeneralName::from_der))))(input)?;
486 Ok((i, SubjectAlternativeName { general_names }))
487 })(i)
488 }
489}
490
491#[derive(Clone, Debug, PartialEq)]
492pub struct IssuerAlternativeName<'a> {
493 pub general_names: Vec<GeneralName<'a>>,
494}
495
496impl<'a> FromDer<'a, X509Error> for IssuerAlternativeName<'a> {
497 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
498 parse_der_sequence_defined_g(|input, _| {
499 let (i, general_names) =
500 all_consuming(many0(complete(cut(GeneralName::from_der))))(input)?;
501 Ok((i, IssuerAlternativeName { general_names }))
502 })(i)
503 }
504}
505
506#[derive(Clone, Debug, PartialEq)]
507pub struct CRLDistributionPoints<'a> {
508 pub points: Vec<CRLDistributionPoint<'a>>,
509}
510
511impl<'a> std::ops::Deref for CRLDistributionPoints<'a> {
512 type Target = Vec<CRLDistributionPoint<'a>>;
513
514 fn deref(&self) -> &Self::Target {
515 &self.points
516 }
517}
518
519impl<'a> FromDer<'a, X509Error> for CRLDistributionPoints<'a> {
520 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
521 parser::parse_crldistributionpoints(i).map_err(Err::convert)
522 }
523}
524
525#[derive(Clone, Debug, PartialEq)]
526pub struct CRLDistributionPoint<'a> {
527 pub distribution_point: Option<DistributionPointName<'a>>,
528 pub reasons: Option<ReasonFlags>,
529 pub crl_issuer: Option<Vec<GeneralName<'a>>>,
530}
531
532#[derive(Clone, Debug, PartialEq)]
533pub enum DistributionPointName<'a> {
534 FullName(Vec<GeneralName<'a>>),
535 NameRelativeToCRLIssuer(RelativeDistinguishedName<'a>),
536}
537
538#[derive(Clone, Debug, PartialEq, Eq)]
539pub struct ReasonFlags {
540 pub flags: u16,
541}
542
543impl ReasonFlags {
544 pub fn key_compromise(&self) -> bool {
545 (self.flags >> 1) & 1 == 1
546 }
547 pub fn ca_compromise(&self) -> bool {
548 (self.flags >> 2) & 1 == 1
549 }
550 pub fn affilation_changed(&self) -> bool {
551 (self.flags >> 3) & 1 == 1
552 }
553 pub fn superseded(&self) -> bool {
554 (self.flags >> 4) & 1 == 1
555 }
556 pub fn cessation_of_operation(&self) -> bool {
557 (self.flags >> 5) & 1 == 1
558 }
559 pub fn certificate_hold(&self) -> bool {
560 (self.flags >> 6) & 1 == 1
561 }
562 pub fn privelege_withdrawn(&self) -> bool {
563 (self.flags >> 7) & 1 == 1
564 }
565 pub fn aa_compromise(&self) -> bool {
566 (self.flags >> 8) & 1 == 1
567 }
568}
569
570const REASON_FLAGS: &[&str] = &[
571 "Unused",
572 "Key Compromise",
573 "CA Compromise",
574 "Affiliation Changed",
575 "Superseded",
576 "Cessation Of Operation",
577 "Certificate Hold",
578 "Privilege Withdrawn",
579 "AA Compromise",
580];
581
582impl fmt::Display for ReasonFlags {
583 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
584 let mut s = String::new();
585 let mut acc = self.flags;
586 for flag_text in REASON_FLAGS {
587 if acc & 1 != 0 {
588 s = s + flag_text + ", ";
589 }
590 acc >>= 1;
591 }
592 s.pop();
593 s.pop();
594 f.write_str(&s)
595 }
596}
597
598#[derive(Clone, Debug, PartialEq)]
599pub struct IssuingDistributionPoint<'a> {
600 pub distribution_point: Option<DistributionPointName<'a>>,
601 pub only_contains_user_certs: bool,
602 pub only_contains_ca_certs: bool,
603 pub only_some_reasons: Option<ReasonFlags>,
604 pub indirect_crl: bool,
605 pub only_contains_attribute_certs: bool,
606}
607
608pub(crate) mod parser {
609 use crate::extensions::*;
610 use crate::time::ASN1Time;
611 use asn1_rs::{GeneralizedTime, ParseResult};
612 use der_parser::ber::BerObject;
613 use der_parser::error::BerError;
614 use der_parser::{oid::Oid, *};
615 use lazy_static::lazy_static;
616 use nom::combinator::{cut, map};
617 use nom::{Err, IResult};
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 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 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(nom::Err::Error(BerError::InvalidTag));
756 }
757 }
758 2 => {
759 let ca = seq[0]
760 .as_bool()
761 .or(Err(nom::Err::Error(BerError::InvalidLength)))?;
762 let pl = seq[1]
763 .as_u32()
764 .or(Err(nom::Err::Error(BerError::InvalidLength)))?;
765 (ca, Some(pl))
766 }
767 _ => return Err(nom::Err::Error(BerError::InvalidLength)),
768 };
769 Ok((
770 rem,
771 BasicConstraints {
772 ca,
773 path_len_constraint,
774 },
775 ))
776 } else {
777 Err(nom::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 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 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(nom::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 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 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 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 let (gn, oid) = Oid::from_der(content)?;
1005 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 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 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 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 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 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 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 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
1200pub(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
1223pub(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 let (rem, obj) = opt(parse_ber_bool)(i)?;
1253 let value = obj
1254 .map(|o| o.as_bool().unwrap_or_default()) .unwrap_or(false) ;
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 {
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 .get(&OID_X509_EXT_CRL_DISTRIBUTION_POINTS)
1442 .is_none());
1443 }
1444 {
1446 let crt = crate::parse_x509_certificate(include_bytes!(
1447 "../../assets/crl-ext/crl-simple.der"
1448 ))
1449 .unwrap()
1450 .1;
1451 let crl = crt
1452 .tbs_certificate
1453 .extensions_map()
1454 .unwrap()
1455 .get(&OID_X509_EXT_CRL_DISTRIBUTION_POINTS)
1456 .unwrap()
1457 .parsed_extension();
1458 assert!(matches!(crl, ParsedExtension::CRLDistributionPoints(_)));
1459 if let ParsedExtension::CRLDistributionPoints(crl) = crl {
1460 assert_eq!(crl.len(), 1);
1461 assert!(crl[0].reasons.is_none());
1462 assert!(crl[0].crl_issuer.is_none());
1463 let distribution_point = crl[0].distribution_point.as_ref().unwrap();
1464 assert!(matches!(
1465 distribution_point,
1466 DistributionPointName::FullName(_)
1467 ));
1468 if let DistributionPointName::FullName(names) = distribution_point {
1469 assert_eq!(names.len(), 1);
1470 assert!(matches!(names[0], GeneralName::URI(_)));
1471 if let GeneralName::URI(uri) = names[0] {
1472 assert_eq!(uri, "http://example.com/myca.crl")
1473 }
1474 }
1475 }
1476 }
1477 {
1479 let crt = crate::parse_x509_certificate(include_bytes!(
1480 "../../assets/crl-ext/crl-complex.der"
1481 ))
1482 .unwrap()
1483 .1;
1484 let crl = crt
1485 .tbs_certificate
1486 .extensions_map()
1487 .unwrap()
1488 .get(&OID_X509_EXT_CRL_DISTRIBUTION_POINTS)
1489 .unwrap()
1490 .parsed_extension();
1491 assert!(matches!(crl, ParsedExtension::CRLDistributionPoints(_)));
1492 if let ParsedExtension::CRLDistributionPoints(crl) = crl {
1493 assert_eq!(crl.len(), 2);
1494 let reasons = crl[0].reasons.as_ref().unwrap();
1496 assert!(reasons.key_compromise());
1497 assert!(reasons.ca_compromise());
1498 assert!(!reasons.affilation_changed());
1499 assert!(!reasons.superseded());
1500 assert!(!reasons.cessation_of_operation());
1501 assert!(!reasons.certificate_hold());
1502 assert!(!reasons.privelege_withdrawn());
1503 assert!(reasons.aa_compromise());
1504 assert_eq!(
1505 format!("{}", reasons),
1506 "Key Compromise, CA Compromise, AA Compromise"
1507 );
1508 let issuers = crl[0].crl_issuer.as_ref().unwrap();
1509 assert_eq!(issuers.len(), 1);
1510 assert!(matches!(issuers[0], GeneralName::DirectoryName(_)));
1511 if let GeneralName::DirectoryName(name) = &issuers[0] {
1512 assert_eq!(name.to_string(), "C=US, O=Organisation, CN=Some Name");
1513 }
1514 let distribution_point = crl[0].distribution_point.as_ref().unwrap();
1515 assert!(matches!(
1516 distribution_point,
1517 DistributionPointName::FullName(_)
1518 ));
1519 if let DistributionPointName::FullName(names) = distribution_point {
1520 assert_eq!(names.len(), 1);
1521 assert!(matches!(names[0], GeneralName::URI(_)));
1522 if let GeneralName::URI(uri) = names[0] {
1523 assert_eq!(uri, "http://example.com/myca.crl")
1524 }
1525 }
1526 let reasons = crl[1].reasons.as_ref().unwrap();
1528 assert!(reasons.key_compromise());
1529 assert!(reasons.ca_compromise());
1530 assert!(!reasons.affilation_changed());
1531 assert!(!reasons.superseded());
1532 assert!(!reasons.cessation_of_operation());
1533 assert!(!reasons.certificate_hold());
1534 assert!(!reasons.privelege_withdrawn());
1535 assert!(!reasons.aa_compromise());
1536 assert_eq!(format!("{}", reasons), "Key Compromise, CA Compromise");
1537 assert!(crl[1].crl_issuer.is_none());
1538 let distribution_point = crl[1].distribution_point.as_ref().unwrap();
1539 assert!(matches!(
1540 distribution_point,
1541 DistributionPointName::FullName(_)
1542 ));
1543 if let DistributionPointName::FullName(names) = distribution_point {
1544 assert_eq!(names.len(), 1);
1545 assert!(matches!(names[0], GeneralName::URI(_)));
1546 if let GeneralName::URI(uri) = names[0] {
1547 assert_eq!(uri, "http://example.com/myca2.crl")
1548 }
1549 }
1550 }
1551 }
1552 }
1553
1554 }