Coverage Report

Created: 2026-05-16 07:38

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