Coverage Report

Created: 2026-02-14 06:16

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