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 nom::combinator::{all_consuming, complete, cut, map, map_res, opt};
14use nom::multi::{many0, many1};
15use nom::{Err, IResult, Parser};
16use oid_registry::*;
17use std::collections::HashMap;
18use std::fmt::{self, LowerHex};
19
20mod generalname;
21mod keyusage;
22mod nameconstraints;
23mod policymappings;
24mod sct;
25
26pub use generalname::*;
27pub use keyusage::*;
28pub use nameconstraints::*;
29pub use policymappings::*;
30pub use sct::*;
31
32#[derive(Clone, Debug, PartialEq)]
83pub struct X509Extension<'a> {
84 pub oid: Oid<'a>,
86 pub critical: bool,
90 pub value: &'a [u8],
92 pub(crate) parsed_extension: ParsedExtension<'a>,
93}
94
95impl<'a> X509Extension<'a> {
96 #[inline]
98 pub const fn new(
99 oid: Oid<'a>,
100 critical: bool,
101 value: &'a [u8],
102 parsed_extension: ParsedExtension<'a>,
103 ) -> X509Extension<'a> {
104 X509Extension {
105 oid,
106 critical,
107 value,
108 parsed_extension,
109 }
110 }
111
112 #[inline]
114 pub fn parsed_extension(&self) -> &ParsedExtension<'a> {
115 &self.parsed_extension
116 }
117}
118
119impl<'a> FromDer<'a, X509Error> for X509Extension<'a> {
126 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
127 X509ExtensionParser::new().parse(i)
128 }
129}
130
131#[derive(Clone, Copy, Debug)]
133pub struct X509ExtensionParser {
134 deep_parse_extensions: bool,
135}
136
137impl X509ExtensionParser {
138 #[inline]
139 pub const fn new() -> Self {
140 X509ExtensionParser {
141 deep_parse_extensions: true,
142 }
143 }
144
145 #[inline]
146 pub const fn with_deep_parse_extensions(self, deep_parse_extensions: bool) -> Self {
147 X509ExtensionParser {
148 deep_parse_extensions,
149 }
150 }
151}
152
153impl Default for X509ExtensionParser {
154 fn default() -> Self {
155 X509ExtensionParser::new()
156 }
157}
158
159impl<'a> Parser<&'a [u8], X509Extension<'a>, X509Error> for X509ExtensionParser {
160 fn parse(&mut self, input: &'a [u8]) -> IResult<&'a [u8], X509Extension<'a>, X509Error> {
161 parse_der_sequence_defined_g(|i, _| {
162 let (i, oid) = Oid::from_der(i)?;
163 let (i, critical) = der_read_critical(i)?;
164 let (i, value) = <&[u8]>::from_der(i)?;
165 let (i, parsed_extension) = if self.deep_parse_extensions {
166 parser::parse_extension(i, value, &oid)?
167 } else {
168 (&[] as &[_], ParsedExtension::Unparsed)
169 };
170 let ext = X509Extension {
171 oid,
172 critical,
173 value,
174 parsed_extension,
175 };
176 Ok((i, ext))
177 })(input)
178 .map_err(|_| X509Error::InvalidExtensions.into())
179 }
180}
181
182#[derive(Clone, Debug, PartialEq)]
183pub enum ParsedExtension<'a> {
184 UnsupportedExtension {
186 oid: Oid<'a>,
187 },
188 ParseError {
189 error: Err<BerError>,
190 },
191 AuthorityKeyIdentifier(AuthorityKeyIdentifier<'a>),
193 SubjectKeyIdentifier(KeyIdentifier<'a>),
195 KeyUsage(KeyUsage),
197 CertificatePolicies(CertificatePolicies<'a>),
199 PolicyMappings(PolicyMappings<'a>),
201 SubjectAlternativeName(SubjectAlternativeName<'a>),
203 IssuerAlternativeName(IssuerAlternativeName<'a>),
205 BasicConstraints(BasicConstraints),
207 NameConstraints(NameConstraints<'a>),
209 PolicyConstraints(PolicyConstraints),
211 ExtendedKeyUsage(ExtendedKeyUsage<'a>),
213 CRLDistributionPoints(CRLDistributionPoints<'a>),
215 InhibitAnyPolicy(InhibitAnyPolicy),
217 AuthorityInfoAccess(AuthorityInfoAccess<'a>),
219 SubjectInfoAccess(SubjectInfoAccess<'a>),
221 NSCertType(NSCertType),
223 NsCertComment(&'a str),
225 IssuingDistributionPoint(IssuingDistributionPoint<'a>),
227 CRLNumber(BigUint),
229 ReasonCode(ReasonCode),
231 InvalidityDate(ASN1Time),
233 SCT(Vec<SignedCertificateTimestamp<'a>>),
235 Unparsed,
237}
238
239impl ParsedExtension<'_> {
240 pub fn unsupported(&self) -> bool {
242 matches!(self, &ParsedExtension::UnsupportedExtension { .. })
243 }
244
245 pub fn error(&self) -> Option<&Err<BerError>> {
247 match self {
248 ParsedExtension::ParseError { error } => Some(error),
249 _ => None,
250 }
251 }
252}
253
254#[derive(Clone, Debug, PartialEq)]
255pub struct AuthorityKeyIdentifier<'a> {
256 pub key_identifier: Option<KeyIdentifier<'a>>,
257 pub authority_cert_issuer: Option<Vec<GeneralName<'a>>>,
258 pub authority_cert_serial: Option<&'a [u8]>,
259}
260
261impl<'a> FromDer<'a, X509Error> for AuthorityKeyIdentifier<'a> {
262 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
263 parser::parse_authoritykeyidentifier(i).map_err(Err::convert)
264 }
265}
266
267pub type CertificatePolicies<'a> = Vec<PolicyInformation<'a>>;
268
269#[derive(Clone, Debug, PartialEq, Eq)]
276pub struct PolicyInformation<'a> {
277 pub policy_id: Oid<'a>,
278 pub policy_qualifiers: Option<Vec<PolicyQualifierInfo<'a>>>,
279}
280
281#[derive(Clone, Debug, PartialEq, Eq)]
282pub struct PolicyQualifierInfo<'a> {
283 pub policy_qualifier_id: Oid<'a>,
284 pub qualifier: &'a [u8],
285}
286
287#[derive(Clone, Debug, PartialEq, Eq)]
289pub struct BasicConstraints {
290 pub ca: bool,
291 pub path_len_constraint: Option<u32>,
292}
293
294impl<'a> FromDer<'a, X509Error> for BasicConstraints {
295 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
296 parser::parse_basicconstraints(i).map_err(Err::convert)
297 }
298}
299
300#[derive(Clone, Debug, PartialEq, Eq)]
301pub struct KeyIdentifier<'a>(pub &'a [u8]);
302
303impl<'a> FromDer<'a, X509Error> for KeyIdentifier<'a> {
304 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
305 parser::parse_keyidentifier(i).map_err(Err::convert)
306 }
307}
308
309impl LowerHex for KeyIdentifier<'_> {
310 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311 let s = format_serial(self.0);
312 f.write_str(&s)
313 }
314}
315
316#[derive(Clone, Copy, Debug, PartialEq, Eq)]
317pub struct NSCertType(u8);
318
319impl NSCertType {
330 pub fn ssl_client(&self) -> bool {
331 self.0 & 0x1 == 1
332 }
333 pub fn ssl_server(&self) -> bool {
334 (self.0 >> 1) & 1 == 1
335 }
336 pub fn smime(&self) -> bool {
337 (self.0 >> 2) & 1 == 1
338 }
339 pub fn object_signing(&self) -> bool {
340 (self.0 >> 3) & 1 == 1
341 }
342 pub fn ssl_ca(&self) -> bool {
343 (self.0 >> 5) & 1 == 1
344 }
345 pub fn smime_ca(&self) -> bool {
346 (self.0 >> 6) & 1 == 1
347 }
348 pub fn object_signing_ca(&self) -> bool {
349 (self.0 >> 7) & 1 == 1
350 }
351}
352
353const NS_CERT_TYPE_FLAGS: &[&str] = &[
354 "SSL CLient",
355 "SSL Server",
356 "S/MIME",
357 "Object Signing",
358 "Reserved",
359 "SSL CA",
360 "S/MIME CA",
361 "Object Signing CA",
362];
363
364impl fmt::Display for NSCertType {
365 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366 let mut s = String::new();
367 let mut acc = self.0;
368 for flag_text in NS_CERT_TYPE_FLAGS {
369 if acc & 1 != 0 {
370 s = s + flag_text + ", ";
371 }
372 acc >>= 1;
373 }
374 s.pop();
375 s.pop();
376 f.write_str(&s)
377 }
378}
379
380impl<'a> FromDer<'a, X509Error> for NSCertType {
381 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
382 parser::parse_nscerttype(i).map_err(Err::convert)
383 }
384}
385
386#[derive(Clone, Debug, PartialEq)]
387pub struct AuthorityInfoAccess<'a> {
388 pub accessdescs: Vec<AccessDescription<'a>>,
389}
390
391impl<'a> AuthorityInfoAccess<'a> {
392 pub fn iter(&self) -> impl Iterator<Item = &AccessDescription<'a>> {
394 self.accessdescs.iter()
395 }
396
397 pub fn as_hashmap(&self) -> HashMap<Oid<'a>, Vec<&GeneralName<'a>>> {
401 let mut m: HashMap<Oid, Vec<&GeneralName>> = HashMap::new();
403 for desc in &self.accessdescs {
404 let AccessDescription {
405 access_method: oid,
406 access_location: gn,
407 } = desc;
408 if let Some(general_names) = m.get_mut(oid) {
409 general_names.push(gn);
410 } else {
411 m.insert(oid.clone(), vec![gn]);
412 }
413 }
414 m
415 }
416
417 pub fn into_hashmap(self) -> HashMap<Oid<'a>, Vec<GeneralName<'a>>> {
421 let mut aia_list = self.accessdescs;
422 let mut m: HashMap<Oid, Vec<GeneralName>> = HashMap::new();
424 for desc in aia_list.drain(..) {
425 let AccessDescription {
426 access_method: oid,
427 access_location: gn,
428 } = desc;
429 if let Some(general_names) = m.get_mut(&oid) {
430 general_names.push(gn);
431 } else {
432 m.insert(oid, vec![gn]);
433 }
434 }
435 m
436 }
437}
438
439impl<'a> FromDer<'a, X509Error> for AuthorityInfoAccess<'a> {
440 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
441 parser::parse_authorityinfoaccess(i).map_err(Err::convert)
442 }
443}
444
445#[derive(Clone, Debug, PartialEq)]
446pub struct SubjectInfoAccess<'a> {
447 pub accessdescs: Vec<AccessDescription<'a>>,
448}
449
450impl<'a> SubjectInfoAccess<'a> {
451 pub fn iter(&self) -> impl Iterator<Item = &AccessDescription<'a>> {
453 self.accessdescs.iter()
454 }
455
456 pub fn as_hashmap(&self) -> HashMap<Oid<'a>, Vec<&GeneralName<'a>>> {
460 let mut m: HashMap<Oid, Vec<&GeneralName>> = HashMap::new();
462 for desc in &self.accessdescs {
463 let AccessDescription {
464 access_method: oid,
465 access_location: gn,
466 } = desc;
467 if let Some(general_names) = m.get_mut(oid) {
468 general_names.push(gn);
469 } else {
470 m.insert(oid.clone(), vec![gn]);
471 }
472 }
473 m
474 }
475
476 pub fn into_hashmap(self) -> HashMap<Oid<'a>, Vec<GeneralName<'a>>> {
480 let mut aia_list = self.accessdescs;
481 let mut m: HashMap<Oid, Vec<GeneralName>> = HashMap::new();
483 for desc in aia_list.drain(..) {
484 let AccessDescription {
485 access_method: oid,
486 access_location: gn,
487 } = desc;
488 if let Some(general_names) = m.get_mut(&oid) {
489 general_names.push(gn);
490 } else {
491 m.insert(oid, vec![gn]);
492 }
493 }
494 m
495 }
496}
497
498impl<'a> FromDer<'a, X509Error> for SubjectInfoAccess<'a> {
499 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
500 parser::parse_subjectinfoaccess(i).map_err(Err::convert)
501 }
502}
503
504#[derive(Clone, Debug, PartialEq)]
508pub struct AccessDescription<'a> {
509 pub access_method: Oid<'a>,
510 pub access_location: GeneralName<'a>,
511}
512
513impl<'a> AccessDescription<'a> {
514 pub const fn new(access_method: Oid<'a>, access_location: GeneralName<'a>) -> Self {
515 AccessDescription {
516 access_method,
517 access_location,
518 }
519 }
520}
521
522#[derive(Clone, Debug, PartialEq, Eq)]
523pub struct InhibitAnyPolicy {
524 pub skip_certs: u32,
525}
526
527impl<'a> FromDer<'a, X509Error> for InhibitAnyPolicy {
528 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
529 map(parse_der_u32, |skip_certs| InhibitAnyPolicy { skip_certs })(i).map_err(Err::convert)
530 }
531}
532
533#[derive(Clone, Debug, PartialEq, Eq)]
534pub struct PolicyConstraints {
535 pub require_explicit_policy: Option<u32>,
536 pub inhibit_policy_mapping: Option<u32>,
537}
538
539impl<'a> FromDer<'a, X509Error> for PolicyConstraints {
540 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
541 parser::parse_policyconstraints(i).map_err(Err::convert)
542 }
543}
544
545#[derive(Clone, Debug, PartialEq)]
546pub struct SubjectAlternativeName<'a> {
547 pub general_names: Vec<GeneralName<'a>>,
548}
549
550impl<'a> FromDer<'a, X509Error> for SubjectAlternativeName<'a> {
551 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
552 parse_der_sequence_defined_g(|input, _| {
553 let (i, general_names) =
554 all_consuming(many0(complete(cut(GeneralName::from_der))))(input)?;
555 Ok((i, SubjectAlternativeName { general_names }))
556 })(i)
557 }
558}
559
560#[derive(Clone, Debug, PartialEq)]
561pub struct IssuerAlternativeName<'a> {
562 pub general_names: Vec<GeneralName<'a>>,
563}
564
565impl<'a> FromDer<'a, X509Error> for IssuerAlternativeName<'a> {
566 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
567 parse_der_sequence_defined_g(|input, _| {
568 let (i, general_names) =
569 all_consuming(many0(complete(cut(GeneralName::from_der))))(input)?;
570 Ok((i, IssuerAlternativeName { general_names }))
571 })(i)
572 }
573}
574
575#[derive(Clone, Debug, PartialEq)]
576pub struct CRLDistributionPoints<'a> {
577 pub points: Vec<CRLDistributionPoint<'a>>,
578}
579
580impl<'a> std::ops::Deref for CRLDistributionPoints<'a> {
581 type Target = Vec<CRLDistributionPoint<'a>>;
582
583 fn deref(&self) -> &Self::Target {
584 &self.points
585 }
586}
587
588impl<'a> FromDer<'a, X509Error> for CRLDistributionPoints<'a> {
589 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
590 parser::parse_crldistributionpoints(i).map_err(Err::convert)
591 }
592}
593
594#[derive(Clone, Debug, PartialEq)]
595pub struct CRLDistributionPoint<'a> {
596 pub distribution_point: Option<DistributionPointName<'a>>,
597 pub reasons: Option<ReasonFlags>,
598 pub crl_issuer: Option<Vec<GeneralName<'a>>>,
599}
600
601#[derive(Clone, Debug, PartialEq)]
602pub enum DistributionPointName<'a> {
603 FullName(Vec<GeneralName<'a>>),
604 NameRelativeToCRLIssuer(RelativeDistinguishedName<'a>),
605}
606
607#[derive(Clone, Debug, PartialEq, Eq)]
608pub struct ReasonFlags {
609 pub flags: u16,
610}
611
612impl ReasonFlags {
613 pub fn key_compromise(&self) -> bool {
614 (self.flags >> 1) & 1 == 1
615 }
616 pub fn ca_compromise(&self) -> bool {
617 (self.flags >> 2) & 1 == 1
618 }
619 pub fn affilation_changed(&self) -> bool {
620 (self.flags >> 3) & 1 == 1
621 }
622 pub fn superseded(&self) -> bool {
623 (self.flags >> 4) & 1 == 1
624 }
625 pub fn cessation_of_operation(&self) -> bool {
626 (self.flags >> 5) & 1 == 1
627 }
628 pub fn certificate_hold(&self) -> bool {
629 (self.flags >> 6) & 1 == 1
630 }
631 pub fn privelege_withdrawn(&self) -> bool {
632 (self.flags >> 7) & 1 == 1
633 }
634 pub fn aa_compromise(&self) -> bool {
635 (self.flags >> 8) & 1 == 1
636 }
637}
638
639const REASON_FLAGS: &[&str] = &[
640 "Unused",
641 "Key Compromise",
642 "CA Compromise",
643 "Affiliation Changed",
644 "Superseded",
645 "Cessation Of Operation",
646 "Certificate Hold",
647 "Privilege Withdrawn",
648 "AA Compromise",
649];
650
651impl fmt::Display for ReasonFlags {
652 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
653 let mut s = String::new();
654 let mut acc = self.flags;
655 for flag_text in REASON_FLAGS {
656 if acc & 1 != 0 {
657 s = s + flag_text + ", ";
658 }
659 acc >>= 1;
660 }
661 s.pop();
662 s.pop();
663 f.write_str(&s)
664 }
665}
666
667#[derive(Clone, Debug, PartialEq)]
668pub struct IssuingDistributionPoint<'a> {
669 pub distribution_point: Option<DistributionPointName<'a>>,
670 pub only_contains_user_certs: bool,
671 pub only_contains_ca_certs: bool,
672 pub only_some_reasons: Option<ReasonFlags>,
673 pub indirect_crl: bool,
674 pub only_contains_attribute_certs: bool,
675}
676
677pub(crate) mod parser {
678 use crate::extensions::*;
679 use asn1_rs::{GeneralizedTime, ParseResult};
680 use der_parser::ber::BerObject;
681 use lazy_static::lazy_static;
682
683 type ExtParser = fn(&[u8]) -> IResult<&[u8], ParsedExtension, BerError>;
684
685 lazy_static! {
686 static ref EXTENSION_PARSERS: HashMap<Oid<'static>, ExtParser> = {
687 macro_rules! add {
688 ($m:ident, $oid:ident, $p:ident) => {
689 $m.insert($oid, $p as ExtParser);
690 };
691 }
692
693 let mut m = HashMap::new();
694 add!(
695 m,
696 OID_X509_EXT_SUBJECT_KEY_IDENTIFIER,
697 parse_keyidentifier_ext
698 );
699 add!(m, OID_X509_EXT_KEY_USAGE, parse_keyusage_ext);
700 add!(
701 m,
702 OID_X509_EXT_SUBJECT_ALT_NAME,
703 parse_subjectalternativename_ext
704 );
705 add!(
706 m,
707 OID_X509_EXT_ISSUER_ALT_NAME,
708 parse_issueralternativename_ext
709 );
710 add!(
711 m,
712 OID_X509_EXT_BASIC_CONSTRAINTS,
713 parse_basicconstraints_ext
714 );
715 add!(m, OID_X509_EXT_NAME_CONSTRAINTS, parse_nameconstraints_ext);
716 add!(
717 m,
718 OID_X509_EXT_CERTIFICATE_POLICIES,
719 parse_certificatepolicies_ext
720 );
721 add!(m, OID_X509_EXT_POLICY_MAPPINGS, parse_policymappings_ext);
722 add!(
723 m,
724 OID_X509_EXT_POLICY_CONSTRAINTS,
725 parse_policyconstraints_ext
726 );
727 add!(
728 m,
729 OID_X509_EXT_EXTENDED_KEY_USAGE,
730 parse_extendedkeyusage_ext
731 );
732 add!(
733 m,
734 OID_X509_EXT_CRL_DISTRIBUTION_POINTS,
735 parse_crldistributionpoints_ext
736 );
737 add!(
738 m,
739 OID_X509_EXT_INHIBIT_ANY_POLICY,
740 parse_inhibitanypolicy_ext
741 );
742 add!(
743 m,
744 OID_PKIX_AUTHORITY_INFO_ACCESS,
745 parse_authorityinfoaccess_ext
746 );
747 add!(m, OID_PKIX_SUBJECT_INFO_ACCESS, parse_subjectinfoaccess_ext);
748 add!(
749 m,
750 OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER,
751 parse_authoritykeyidentifier_ext
752 );
753 add!(m, OID_CT_LIST_SCT, parse_sct_ext);
754 add!(m, OID_X509_EXT_CERT_TYPE, parse_nscerttype_ext);
755 add!(m, OID_X509_EXT_CERT_COMMENT, parse_nscomment_ext);
756 add!(m, OID_X509_EXT_CRL_NUMBER, parse_crl_number);
757 add!(m, OID_X509_EXT_REASON_CODE, parse_reason_code);
758 add!(m, OID_X509_EXT_INVALIDITY_DATE, parse_invalidity_date);
759 add!(
760 m,
761 OID_X509_EXT_ISSUER_DISTRIBUTION_POINT,
762 parse_issuingdistributionpoint_ext
763 );
764 m
765 };
766 }
767
768 fn parse_extension0<'a>(
771 orig_i: &'a [u8],
772 i: &'a [u8],
773 oid: &Oid,
774 ) -> IResult<&'a [u8], ParsedExtension<'a>, BerError> {
775 if let Some(parser) = EXTENSION_PARSERS.get(oid) {
776 match parser(i) {
777 Ok((_, ext)) => Ok((orig_i, ext)),
778 Err(error) => Ok((orig_i, ParsedExtension::ParseError { error })),
779 }
780 } else {
781 Ok((
782 orig_i,
783 ParsedExtension::UnsupportedExtension {
784 oid: oid.to_owned(),
785 },
786 ))
787 }
788 }
789
790 pub(crate) fn parse_extension<'a>(
791 orig_i: &'a [u8],
792 i: &'a [u8],
793 oid: &Oid,
794 ) -> IResult<&'a [u8], ParsedExtension<'a>, BerError> {
795 parse_extension0(orig_i, i, oid)
796 }
797
798 pub(super) fn parse_basicconstraints(i: &[u8]) -> IResult<&[u8], BasicConstraints, BerError> {
810 let (rem, obj) = parse_der_sequence(i)?;
811 if let Ok(seq) = obj.as_sequence() {
812 let (ca, path_len_constraint) = match seq.len() {
813 0 => (false, None),
814 1 => {
815 if let Ok(b) = seq[0].as_bool() {
816 (b, None)
817 } else if let Ok(u) = seq[0].as_u32() {
818 (false, Some(u))
819 } else {
820 return Err(Err::Error(BerError::InvalidTag));
821 }
822 }
823 2 => {
824 let ca = seq[0]
825 .as_bool()
826 .or(Err(Err::Error(BerError::InvalidLength)))?;
827 let pl = seq[1]
828 .as_u32()
829 .or(Err(Err::Error(BerError::InvalidLength)))?;
830 (ca, Some(pl))
831 }
832 _ => return Err(Err::Error(BerError::InvalidLength)),
833 };
834 Ok((
835 rem,
836 BasicConstraints {
837 ca,
838 path_len_constraint,
839 },
840 ))
841 } else {
842 Err(Err::Error(BerError::InvalidLength))
843 }
844 }
845
846 fn parse_basicconstraints_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
847 map(parse_basicconstraints, ParsedExtension::BasicConstraints)(i)
848 }
849
850 fn parse_nameconstraints_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
851 map(parse_nameconstraints, ParsedExtension::NameConstraints)(i)
852 }
853
854 pub(super) fn parse_subjectalternativename_ext(
855 i: &[u8],
856 ) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
857 parse_der_sequence_defined_g(|input, _| {
858 let (i, general_names) = all_consuming(many0(complete(cut(parse_generalname))))(input)?;
859 Ok((
860 i,
861 ParsedExtension::SubjectAlternativeName(SubjectAlternativeName { general_names }),
862 ))
863 })(i)
864 }
865
866 pub(super) fn parse_issueralternativename_ext(
867 i: &[u8],
868 ) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
869 parse_der_sequence_defined_g(|input, _| {
870 let (i, general_names) = all_consuming(many0(complete(cut(parse_generalname))))(input)?;
871 Ok((
872 i,
873 ParsedExtension::IssuerAlternativeName(IssuerAlternativeName { general_names }),
874 ))
875 })(i)
876 }
877
878 pub(super) fn parse_policyconstraints(i: &[u8]) -> IResult<&[u8], PolicyConstraints, BerError> {
879 parse_der_sequence_defined_g(|input, _| {
880 let (i, require_explicit_policy) = opt(complete(map_res(
881 parse_der_tagged_implicit(0, parse_der_content(Tag::Integer)),
882 |x| x.as_u32(),
883 )))(input)?;
884 let (i, inhibit_policy_mapping) = all_consuming(opt(complete(map_res(
885 parse_der_tagged_implicit(1, parse_der_content(Tag::Integer)),
886 |x| x.as_u32(),
887 ))))(i)?;
888 let policy_constraint = PolicyConstraints {
889 require_explicit_policy,
890 inhibit_policy_mapping,
891 };
892 Ok((i, policy_constraint))
893 })(i)
894 }
895
896 fn parse_policyconstraints_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
897 map(parse_policyconstraints, ParsedExtension::PolicyConstraints)(i)
898 }
899
900 fn parse_policymappings_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
901 map(parse_policymappings, ParsedExtension::PolicyMappings)(i)
902 }
903
904 fn parse_inhibitanypolicy_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
905 let (ret, skip_certs) = parse_der_u32(i)?;
906 Ok((
907 ret,
908 ParsedExtension::InhibitAnyPolicy(InhibitAnyPolicy { skip_certs }),
909 ))
910 }
911
912 fn parse_extendedkeyusage_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
913 map(parse_extendedkeyusage, ParsedExtension::ExtendedKeyUsage)(i)
914 }
915
916 fn parse_distributionpointname(
920 i: &[u8],
921 ) -> IResult<&[u8], DistributionPointName<'_>, BerError> {
922 let (rem, header) = der_read_element_header(i)?;
923 match header.tag().0 {
924 0 => {
925 let (rem, names) = many1(complete(parse_generalname))(rem)?;
926 Ok((rem, DistributionPointName::FullName(names)))
927 }
928 1 => {
929 let (rem, rdn) = RelativeDistinguishedName::from_der(rem)
930 .map_err(|_| BerError::BerValueError)?;
931 Ok((rem, DistributionPointName::NameRelativeToCRLIssuer(rdn)))
932 }
933 _ => Err(Err::Error(BerError::InvalidTag)),
934 }
935 }
936
937 fn parse_implicit_tagged_reasons(tag: u32) -> impl Fn(&[u8]) -> BerResult<ReasonFlags> {
938 move |i: &[u8]| {
939 let (rem, obj) = parse_der_tagged_implicit(tag, parse_der_content(Tag::BitString))(i)?;
940 parse_reasons(rem, obj)
941 }
942 }
943
944 fn parse_reasons<'a>(rem: &'a [u8], obj: BerObject<'a>) -> BerResult<'a, ReasonFlags> {
955 if let DerObjectContent::BitString(_, b) = obj.content {
956 let flags = b
957 .data
958 .iter()
959 .rev()
960 .fold(0, |acc, x| (acc << 8) | (x.reverse_bits() as u16));
961 Ok((rem, ReasonFlags { flags }))
962 } else {
963 Err(Err::Failure(BerError::InvalidTag))
964 }
965 }
966
967 fn parse_crlissuer_content(i: &[u8]) -> BerResult<'_, Vec<GeneralName<'_>>> {
968 many1(complete(parse_generalname))(i)
969 }
970
971 pub(super) fn parse_crldistributionpoint(
976 i: &[u8],
977 ) -> IResult<&[u8], CRLDistributionPoint<'_>, BerError> {
978 parse_der_sequence_defined_g(|content, _| {
979 let (rem, distribution_point) =
980 opt(complete(parse_der_tagged_explicit_g(0, |b, _| {
981 parse_distributionpointname(b)
982 })))(content)?;
983 let (rem, reasons) = opt(complete(parse_implicit_tagged_reasons(1)))(rem)?;
984 let (rem, crl_issuer) = opt(complete(parse_der_tagged_implicit_g(2, |i, _, _| {
985 parse_crlissuer_content(i)
986 })))(rem)?;
987 let crl_dp = CRLDistributionPoint {
988 distribution_point,
989 reasons,
990 crl_issuer,
991 };
992 Ok((rem, crl_dp))
993 })(i)
994 }
995
996 pub(super) fn parse_crldistributionpoints(
997 i: &[u8],
998 ) -> IResult<&[u8], CRLDistributionPoints<'_>, BerError> {
999 let (ret, crldps) = parse_der_sequence_of_v(parse_crldistributionpoint)(i)?;
1000 Ok((ret, CRLDistributionPoints { points: crldps }))
1001 }
1002
1003 fn parse_crldistributionpoints_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1004 map(
1005 parse_crldistributionpoints,
1006 ParsedExtension::CRLDistributionPoints,
1007 )(i)
1008 }
1009
1010 pub(super) fn parse_issuingdistributionpoint(
1018 i: &[u8],
1019 ) -> IResult<&[u8], IssuingDistributionPoint<'_>, BerError> {
1020 parse_der_sequence_defined_g(|content, _| {
1021 let parse_tagged_bool = |tag: u32, rem| -> IResult<&[u8], bool, BerError> {
1022 let (rem, value) = opt(complete(|_| {
1023 parse_der_implicit(rem, tag, parse_der_content(Tag::Boolean))
1024 .map(|(res, ob)| (res, ob.as_bool().unwrap_or(false)))
1025 }))(rem)?;
1026 Ok((rem, value.unwrap_or_default()))
1027 };
1028
1029 let (rem, distribution_point) =
1030 opt(complete(parse_der_tagged_explicit_g(0, |b, _| {
1031 parse_distributionpointname(b)
1032 })))(content)?;
1033
1034 let (rem, only_contains_user_certs) = parse_tagged_bool(1, rem)?;
1035 let (rem, only_contains_ca_certs) = parse_tagged_bool(2, rem)?;
1036 let (rem, only_some_reasons) = opt(complete(parse_implicit_tagged_reasons(3)))(rem)?;
1037 let (rem, indirect_crl) = parse_tagged_bool(4, rem)?;
1038 let (rem, only_contains_attribute_certs) = parse_tagged_bool(5, rem)?;
1039
1040 let crl_idp = IssuingDistributionPoint {
1041 distribution_point,
1042 only_contains_user_certs,
1043 only_contains_ca_certs,
1044 only_some_reasons,
1045 indirect_crl,
1046 only_contains_attribute_certs,
1047 };
1048 Ok((rem, crl_idp))
1049 })(i)
1050 }
1051
1052 fn parse_issuingdistributionpoint_ext(
1053 i: &[u8],
1054 ) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1055 map(
1056 parse_issuingdistributionpoint,
1057 ParsedExtension::IssuingDistributionPoint,
1058 )(i)
1059 }
1060
1061 pub(super) fn parse_authorityinfoaccess(
1068 i: &[u8],
1069 ) -> IResult<&[u8], AuthorityInfoAccess<'_>, BerError> {
1070 fn parse_aia(i: &[u8]) -> IResult<&[u8], AccessDescription<'_>, BerError> {
1071 parse_der_sequence_defined_g(|content, _| {
1072 let (gn, oid) = Oid::from_der(content)?;
1074 let (rest, gn) = parse_generalname(gn)?;
1076 Ok((rest, AccessDescription::new(oid, gn)))
1077 })(i)
1078 }
1079 let (ret, accessdescs) = parse_der_sequence_of_v(parse_aia)(i)?;
1080 Ok((ret, AuthorityInfoAccess { accessdescs }))
1081 }
1082
1083 fn parse_authorityinfoaccess_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1084 map(
1085 parse_authorityinfoaccess,
1086 ParsedExtension::AuthorityInfoAccess,
1087 )(i)
1088 }
1089
1090 pub(super) fn parse_subjectinfoaccess(
1097 i: &[u8],
1098 ) -> IResult<&[u8], SubjectInfoAccess<'_>, BerError> {
1099 fn parse_sia(i: &[u8]) -> IResult<&[u8], AccessDescription<'_>, BerError> {
1100 parse_der_sequence_defined_g(|content, _| {
1101 let (gn, oid) = Oid::from_der(content)?;
1103 let (rest, gn) = parse_generalname(gn)?;
1105 Ok((rest, AccessDescription::new(oid, gn)))
1106 })(i)
1107 }
1108 let (ret, accessdescs) = parse_der_sequence_of_v(parse_sia)(i)?;
1109 Ok((ret, SubjectInfoAccess { accessdescs }))
1110 }
1111
1112 fn parse_subjectinfoaccess_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1113 map(parse_subjectinfoaccess, ParsedExtension::SubjectInfoAccess)(i)
1114 }
1115
1116 fn parse_aki_content<'a>(
1117 i: &'a [u8],
1118 _hdr: Header<'_>,
1119 ) -> IResult<&'a [u8], AuthorityKeyIdentifier<'a>, BerError> {
1120 let (i, key_identifier) = opt(complete(parse_der_tagged_implicit_g(0, |d, _, _| {
1121 Ok((&[], KeyIdentifier(d)))
1122 })))(i)?;
1123 let (i, authority_cert_issuer) =
1124 opt(complete(parse_der_tagged_implicit_g(1, |d, _, _| {
1125 many0(complete(parse_generalname))(d)
1126 })))(i)?;
1127 let (i, authority_cert_serial) = opt(complete(parse_der_tagged_implicit(
1128 2,
1129 parse_der_content(Tag::Integer),
1130 )))(i)?;
1131 let authority_cert_serial = authority_cert_serial.and_then(|o| o.as_slice().ok());
1132 let aki = AuthorityKeyIdentifier {
1133 key_identifier,
1134 authority_cert_issuer,
1135 authority_cert_serial,
1136 };
1137 Ok((i, aki))
1138 }
1139
1140 pub(super) fn parse_authoritykeyidentifier(
1142 i: &[u8],
1143 ) -> IResult<&[u8], AuthorityKeyIdentifier<'_>, BerError> {
1144 let (rem, aki) = parse_der_sequence_defined_g(parse_aki_content)(i)?;
1145 Ok((rem, aki))
1146 }
1147
1148 fn parse_authoritykeyidentifier_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1149 map(
1150 parse_authoritykeyidentifier,
1151 ParsedExtension::AuthorityKeyIdentifier,
1152 )(i)
1153 }
1154
1155 pub(super) fn parse_keyidentifier(i: &[u8]) -> IResult<&[u8], KeyIdentifier<'_>, BerError> {
1156 let (rest, id) = <&[u8]>::from_der(i)?;
1157 let ki = KeyIdentifier(id);
1158 Ok((rest, ki))
1159 }
1160
1161 fn parse_keyidentifier_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1162 map(parse_keyidentifier, ParsedExtension::SubjectKeyIdentifier)(i)
1163 }
1164
1165 fn parse_keyusage_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1166 map(parse_keyusage, ParsedExtension::KeyUsage)(i)
1167 }
1168
1169 pub(super) fn parse_nscerttype(i: &[u8]) -> IResult<&[u8], NSCertType, BerError> {
1170 let (rest, obj) = parse_der_bitstring(i)?;
1171 let bitstring = obj
1172 .content
1173 .as_bitstring()
1174 .or(Err(Err::Error(BerError::BerTypeError)))?;
1175 if bitstring.data.len() != 1 {
1177 return Err(Err::Error(BerError::BerValueError));
1178 }
1179 let flags = bitstring.data[0].reverse_bits();
1180 Ok((rest, NSCertType(flags)))
1181 }
1182
1183 fn parse_nscerttype_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1184 map(parse_nscerttype, ParsedExtension::NSCertType)(i)
1185 }
1186
1187 fn parse_nscomment_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1188 match parse_der_ia5string(i) {
1189 Ok((i, obj)) => {
1190 let s = obj.as_str()?;
1191 Ok((i, ParsedExtension::NsCertComment(s)))
1192 }
1193 Err(e) => {
1194 if let Ok(s) = std::str::from_utf8(i) {
1197 Ok((&[], ParsedExtension::NsCertComment(s)))
1198 } else {
1199 Err(e)
1200 }
1201 }
1202 }
1203 }
1204
1205 pub(super) fn parse_certificatepolicies(
1223 i: &[u8],
1224 ) -> IResult<&[u8], Vec<PolicyInformation<'_>>, BerError> {
1225 fn parse_policy_qualifier_info(
1226 i: &[u8],
1227 ) -> IResult<&[u8], PolicyQualifierInfo<'_>, BerError> {
1228 parse_der_sequence_defined_g(|content, _| {
1229 let (rem, policy_qualifier_id) = Oid::from_der(content)?;
1230 let info = PolicyQualifierInfo {
1231 policy_qualifier_id,
1232 qualifier: rem,
1233 };
1234 Ok((&[], info))
1235 })(i)
1236 }
1237 fn parse_policy_information(i: &[u8]) -> IResult<&[u8], PolicyInformation<'_>, BerError> {
1238 parse_der_sequence_defined_g(|content, _| {
1239 let (rem, policy_id) = Oid::from_der(content)?;
1240 let (rem, policy_qualifiers) =
1241 opt(complete(parse_der_sequence_defined_g(|content, _| {
1242 many1(complete(parse_policy_qualifier_info))(content)
1243 })))(rem)?;
1244 let info = PolicyInformation {
1245 policy_id,
1246 policy_qualifiers,
1247 };
1248 Ok((rem, info))
1249 })(i)
1250 }
1251 parse_der_sequence_of_v(parse_policy_information)(i)
1252 }
1253
1254 fn parse_certificatepolicies_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1255 map(
1256 parse_certificatepolicies,
1257 ParsedExtension::CertificatePolicies,
1258 )(i)
1259 }
1260
1261 fn parse_reason_code(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1263 let (rest, obj) = parse_der_enum(i)?;
1264 let code = obj
1265 .content
1266 .as_u32()
1267 .or(Err(Err::Error(BerError::BerValueError)))?;
1268 if code > 10 {
1269 return Err(Err::Error(BerError::BerValueError));
1270 }
1271 let ret = ParsedExtension::ReasonCode(ReasonCode(code as u8));
1272 Ok((rest, ret))
1273 }
1274
1275 fn parse_invalidity_date(i: &[u8]) -> ParseResult<'_, ParsedExtension<'_>> {
1277 let (rest, t) = GeneralizedTime::from_der(i)?;
1278 let dt = t.utc_datetime()?;
1279 Ok((rest, ParsedExtension::InvalidityDate(ASN1Time::new(dt))))
1280 }
1281
1282 fn parse_crl_number(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1285 let (rest, num) = map_res(parse_der_integer, |obj| obj.as_biguint())(i)?;
1286 Ok((rest, ParsedExtension::CRLNumber(num)))
1287 }
1288
1289 fn parse_sct_ext(i: &[u8]) -> IResult<&[u8], ParsedExtension<'_>, BerError> {
1290 map(
1291 parse_ct_signed_certificate_timestamp_list,
1292 ParsedExtension::SCT,
1293 )(i)
1294 }
1295}
1296
1297pub(crate) fn parse_extension_sequence(i: &[u8]) -> X509Result<'_, Vec<X509Extension<'_>>> {
1299 parse_der_sequence_defined_g(|a, _| all_consuming(many0(complete(X509Extension::from_der)))(a))(
1300 i,
1301 )
1302}
1303
1304pub(crate) fn parse_extensions(
1305 i: &[u8],
1306 explicit_tag: Tag,
1307) -> X509Result<'_, Vec<X509Extension<'_>>> {
1308 if i.is_empty() {
1309 return Ok((i, Vec::new()));
1310 }
1311
1312 match der_read_element_header(i) {
1313 Ok((rem, hdr)) => {
1314 if hdr.tag() != explicit_tag {
1315 return Err(Err::Error(X509Error::InvalidExtensions));
1316 }
1317 all_consuming(parse_extension_sequence)(rem)
1318 }
1319 Err(_) => Err(X509Error::InvalidExtensions.into()),
1320 }
1321}
1322
1323pub(crate) fn parse_extension_envelope_sequence(
1325 i: &[u8],
1326) -> X509Result<'_, Vec<X509Extension<'_>>> {
1327 let parser = X509ExtensionParser::new().with_deep_parse_extensions(false);
1328
1329 parse_der_sequence_defined_g(move |a, _| all_consuming(many0(complete(parser)))(a))(i)
1330}
1331
1332pub(crate) fn parse_extensions_envelope(
1333 i: &[u8],
1334 explicit_tag: Tag,
1335) -> X509Result<'_, Vec<X509Extension<'_>>> {
1336 if i.is_empty() {
1337 return Ok((i, Vec::new()));
1338 }
1339
1340 match der_read_element_header(i) {
1341 Ok((rem, hdr)) => {
1342 if hdr.tag() != explicit_tag {
1343 return Err(Err::Error(X509Error::InvalidExtensions));
1344 }
1345 all_consuming(parse_extension_envelope_sequence)(rem)
1346 }
1347 Err(_) => Err(X509Error::InvalidExtensions.into()),
1348 }
1349}
1350
1351fn der_read_critical(i: &[u8]) -> BerResult<'_, bool> {
1352 let (rem, obj) = opt(parse_ber_bool)(i)?;
1355 let value = obj
1356 .map(|o| o.as_bool().unwrap_or_default()) .unwrap_or(false) ;
1359 Ok((rem, value))
1360}
1361
1362#[cfg(test)]
1363mod tests {
1364 use super::*;
1365
1366 #[test]
1367 fn test_keyusage_flags() {
1368 let ku = KeyUsage { flags: 98 };
1369 assert!(!ku.digital_signature());
1370 assert!(ku.non_repudiation());
1371 assert!(!ku.key_encipherment());
1372 assert!(!ku.data_encipherment());
1373 assert!(!ku.key_agreement());
1374 assert!(ku.key_cert_sign());
1375 assert!(ku.crl_sign());
1376 assert!(!ku.encipher_only());
1377 assert!(!ku.decipher_only());
1378 }
1379
1380 #[test]
1381 fn test_extensions1() {
1382 use der_parser::oid;
1383 let crt = crate::parse_x509_certificate(include_bytes!("../../assets/extension1.der"))
1384 .unwrap()
1385 .1;
1386 let tbs = &crt.tbs_certificate;
1387 let bc = crt
1388 .basic_constraints()
1389 .expect("could not get basic constraints")
1390 .expect("no basic constraints found");
1391 assert_eq!(
1392 bc.value,
1393 &BasicConstraints {
1394 ca: true,
1395 path_len_constraint: Some(1)
1396 }
1397 );
1398 {
1399 let ku = tbs
1400 .key_usage()
1401 .expect("could not get key usage")
1402 .expect("no key usage found")
1403 .value;
1404 assert!(ku.digital_signature());
1405 assert!(!ku.non_repudiation());
1406 assert!(ku.key_encipherment());
1407 assert!(ku.data_encipherment());
1408 assert!(ku.key_agreement());
1409 assert!(!ku.key_cert_sign());
1410 assert!(!ku.crl_sign());
1411 assert!(ku.encipher_only());
1412 assert!(ku.decipher_only());
1413 }
1414 {
1415 let eku = tbs
1416 .extended_key_usage()
1417 .expect("could not get extended key usage")
1418 .expect("no extended key usage found")
1419 .value;
1420 assert!(!eku.any);
1421 assert!(eku.server_auth);
1422 assert!(!eku.client_auth);
1423 assert!(eku.code_signing);
1424 assert!(!eku.email_protection);
1425 assert!(eku.time_stamping);
1426 assert!(!eku.ocsp_signing);
1427 assert_eq!(eku.other, vec![oid!(1.2.3 .4 .0 .42)]);
1428 }
1429 assert_eq!(
1430 tbs.policy_constraints()
1431 .expect("could not get policy constraints")
1432 .expect("no policy constraints found")
1433 .value,
1434 &PolicyConstraints {
1435 require_explicit_policy: None,
1436 inhibit_policy_mapping: Some(10)
1437 }
1438 );
1439 let val = tbs
1440 .inhibit_anypolicy()
1441 .expect("could not get inhibit_anypolicy")
1442 .expect("no inhibit_anypolicy found")
1443 .value;
1444 assert_eq!(val, &InhibitAnyPolicy { skip_certs: 2 });
1445 {
1446 let alt_names = &tbs
1447 .subject_alternative_name()
1448 .expect("could not get subject alt names")
1449 .expect("no subject alt names found")
1450 .value
1451 .general_names;
1452 assert_eq!(alt_names[0], GeneralName::RFC822Name("foo@example.com"));
1453 assert_eq!(alt_names[1], GeneralName::URI("http://my.url.here/"));
1454 assert_eq!(
1455 alt_names[2],
1456 GeneralName::IPAddress([192, 168, 7, 1].as_ref())
1457 );
1458 assert_eq!(
1459 format!(
1460 "{}",
1461 match alt_names[3] {
1462 GeneralName::DirectoryName(ref dn) => dn,
1463 _ => unreachable!(),
1464 }
1465 ),
1466 "C=UK, O=My Organization, OU=My Unit, CN=My Name"
1467 );
1468 assert_eq!(alt_names[4], GeneralName::DNSName("localhost"));
1469 assert_eq!(alt_names[5], GeneralName::RegisteredID(oid!(1.2.90 .0)));
1470 assert_eq!(
1471 alt_names[6],
1472 GeneralName::OtherName(oid!(1.2.3 .4), b"\xA0\x17\x0C\x15some other identifier")
1473 );
1474 }
1475
1476 {
1477 let name_constraints = &tbs
1478 .name_constraints()
1479 .expect("could not get name constraints")
1480 .expect("no name constraints found")
1481 .value;
1482 assert_eq!(name_constraints.permitted_subtrees, None);
1483 assert_eq!(
1484 name_constraints.excluded_subtrees,
1485 Some(vec![
1486 GeneralSubtree {
1487 base: GeneralName::IPAddress([192, 168, 0, 0, 255, 255, 0, 0].as_ref())
1488 },
1489 GeneralSubtree {
1490 base: GeneralName::RFC822Name("foo.com")
1491 },
1492 ])
1493 );
1494 }
1495 }
1496
1497 #[test]
1498 fn test_extensions2() {
1499 use der_parser::oid;
1500 let crt = crate::parse_x509_certificate(include_bytes!("../../assets/extension2.der"))
1501 .unwrap()
1502 .1;
1503 let tbs = crt.tbs_certificate;
1504 assert_eq!(
1505 tbs.policy_constraints()
1506 .expect("could not get policy constraints")
1507 .expect("no policy constraints found")
1508 .value,
1509 &PolicyConstraints {
1510 require_explicit_policy: Some(5000),
1511 inhibit_policy_mapping: None
1512 }
1513 );
1514 {
1515 let pm = tbs
1516 .policy_mappings()
1517 .expect("could not get policy_mappings")
1518 .expect("no policy_mappings found")
1519 .value
1520 .clone()
1521 .into_hashmap();
1522 let mut pm_ref = HashMap::new();
1523 pm_ref.insert(oid!(2.34.23), vec![oid!(2.2)]);
1524 pm_ref.insert(oid!(1.1), vec![oid!(0.0.4)]);
1525 pm_ref.insert(oid!(2.2), vec![oid!(2.2.1), oid!(2.2.3)]);
1526 assert_eq!(pm, pm_ref);
1527 }
1528 }
1529
1530 #[test]
1531 fn test_extensions_crl_distribution_points() {
1532 {
1534 let crt = crate::parse_x509_certificate(include_bytes!(
1535 "../../assets/crl-ext/crl-no-crl.der"
1536 ))
1537 .unwrap()
1538 .1;
1539 assert!(!crt
1540 .tbs_certificate
1541 .extensions_map()
1542 .unwrap()
1543 .contains_key(&OID_X509_EXT_CRL_DISTRIBUTION_POINTS));
1544 }
1545 {
1547 let crt = crate::parse_x509_certificate(include_bytes!(
1548 "../../assets/crl-ext/crl-simple.der"
1549 ))
1550 .unwrap()
1551 .1;
1552 let crl = crt
1553 .tbs_certificate
1554 .extensions_map()
1555 .unwrap()
1556 .get(&OID_X509_EXT_CRL_DISTRIBUTION_POINTS)
1557 .unwrap()
1558 .parsed_extension();
1559 assert!(matches!(crl, ParsedExtension::CRLDistributionPoints(_)));
1560 if let ParsedExtension::CRLDistributionPoints(crl) = crl {
1561 assert_eq!(crl.len(), 1);
1562 assert!(crl[0].reasons.is_none());
1563 assert!(crl[0].crl_issuer.is_none());
1564 let distribution_point = crl[0].distribution_point.as_ref().unwrap();
1565 assert!(matches!(
1566 distribution_point,
1567 DistributionPointName::FullName(_)
1568 ));
1569 if let DistributionPointName::FullName(names) = distribution_point {
1570 assert_eq!(names.len(), 1);
1571 assert!(matches!(names[0], GeneralName::URI(_)));
1572 if let GeneralName::URI(uri) = names[0] {
1573 assert_eq!(uri, "http://example.com/myca.crl")
1574 }
1575 }
1576 }
1577 }
1578 {
1580 let crt = crate::parse_x509_certificate(include_bytes!(
1581 "../../assets/crl-ext/crl-complex.der"
1582 ))
1583 .unwrap()
1584 .1;
1585 let crl = crt
1586 .tbs_certificate
1587 .extensions_map()
1588 .unwrap()
1589 .get(&OID_X509_EXT_CRL_DISTRIBUTION_POINTS)
1590 .unwrap()
1591 .parsed_extension();
1592 assert!(matches!(crl, ParsedExtension::CRLDistributionPoints(_)));
1593 if let ParsedExtension::CRLDistributionPoints(crl) = crl {
1594 assert_eq!(crl.len(), 2);
1595 let reasons = crl[0].reasons.as_ref().unwrap();
1597 assert!(reasons.key_compromise());
1598 assert!(reasons.ca_compromise());
1599 assert!(!reasons.affilation_changed());
1600 assert!(!reasons.superseded());
1601 assert!(!reasons.cessation_of_operation());
1602 assert!(!reasons.certificate_hold());
1603 assert!(!reasons.privelege_withdrawn());
1604 assert!(reasons.aa_compromise());
1605 assert_eq!(
1606 format!("{reasons}"),
1607 "Key Compromise, CA Compromise, AA Compromise"
1608 );
1609 let issuers = crl[0].crl_issuer.as_ref().unwrap();
1610 assert_eq!(issuers.len(), 1);
1611 assert!(matches!(issuers[0], GeneralName::DirectoryName(_)));
1612 if let GeneralName::DirectoryName(name) = &issuers[0] {
1613 assert_eq!(name.to_string(), "C=US, O=Organisation, CN=Some Name");
1614 }
1615 let distribution_point = crl[0].distribution_point.as_ref().unwrap();
1616 assert!(matches!(
1617 distribution_point,
1618 DistributionPointName::FullName(_)
1619 ));
1620 if let DistributionPointName::FullName(names) = distribution_point {
1621 assert_eq!(names.len(), 1);
1622 assert!(matches!(names[0], GeneralName::URI(_)));
1623 if let GeneralName::URI(uri) = names[0] {
1624 assert_eq!(uri, "http://example.com/myca.crl")
1625 }
1626 }
1627 let reasons = crl[1].reasons.as_ref().unwrap();
1629 assert!(reasons.key_compromise());
1630 assert!(reasons.ca_compromise());
1631 assert!(!reasons.affilation_changed());
1632 assert!(!reasons.superseded());
1633 assert!(!reasons.cessation_of_operation());
1634 assert!(!reasons.certificate_hold());
1635 assert!(!reasons.privelege_withdrawn());
1636 assert!(!reasons.aa_compromise());
1637 assert_eq!(format!("{reasons}"), "Key Compromise, CA Compromise");
1638 assert!(crl[1].crl_issuer.is_none());
1639 let distribution_point = crl[1].distribution_point.as_ref().unwrap();
1640 assert!(matches!(
1641 distribution_point,
1642 DistributionPointName::FullName(_)
1643 ));
1644 if let DistributionPointName::FullName(names) = distribution_point {
1645 assert_eq!(names.len(), 1);
1646 assert!(matches!(names[0], GeneralName::URI(_)));
1647 if let GeneralName::URI(uri) = names[0] {
1648 assert_eq!(uri, "http://example.com/myca2.crl")
1649 }
1650 }
1651 }
1652 }
1653 }
1654
1655 }