• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::error::{X509Error, X509Result};
2 use crate::extensions::*;
3 use crate::time::ASN1Time;
4 use crate::traits::FromDer;
5 use crate::x509::{
6     parse_serial, parse_signature_value, AlgorithmIdentifier, ReasonCode, X509Name, X509Version,
7 };
8 
9 use der_parser::ber::{BerTag, BitStringObject};
10 use der_parser::der::*;
11 use der_parser::num_bigint::BigUint;
12 use der_parser::oid::Oid;
13 use nom::combinator::{all_consuming, complete, map, opt};
14 use nom::multi::many1;
15 use nom::Offset;
16 use oid_registry::*;
17 use std::collections::HashMap;
18 
19 /// An X.509 v2 Certificate Revocation List (CRL).
20 ///
21 /// X.509 v2 CRLs are defined in [RFC5280](https://tools.ietf.org/html/rfc5280).
22 ///
23 /// # Example
24 ///
25 /// To parse a CRL and print information about revoked certificates:
26 ///
27 /// ```rust
28 /// use x509_parser::revocation_list::CertificateRevocationList;
29 /// use x509_parser::traits::FromDer;
30 ///
31 /// # static DER: &'static [u8] = include_bytes!("../assets/example.crl");
32 /// #
33 /// # fn main() {
34 /// let res = CertificateRevocationList::from_der(DER);
35 /// match res {
36 ///     Ok((_rem, crl)) => {
37 ///         for revoked in crl.iter_revoked_certificates() {
38 ///             println!("Revoked certificate serial: {}", revoked.raw_serial_as_string());
39 ///             println!("  Reason: {}", revoked.reason_code().unwrap_or_default().1);
40 ///         }
41 ///     },
42 ///     _ => panic!("CRL parsing failed: {:?}", res),
43 /// }
44 /// # }
45 /// ```
46 #[derive(Clone, Debug)]
47 pub struct CertificateRevocationList<'a> {
48     pub tbs_cert_list: TbsCertList<'a>,
49     pub signature_algorithm: AlgorithmIdentifier<'a>,
50     pub signature_value: BitStringObject<'a>,
51 }
52 
53 impl<'a> CertificateRevocationList<'a> {
54     /// Get the version of the encoded certificate
version(&self) -> Option<X509Version>55     pub fn version(&self) -> Option<X509Version> {
56         self.tbs_cert_list.version
57     }
58 
59     /// Get the certificate issuer.
60     #[inline]
issuer(&self) -> &X509Name61     pub fn issuer(&self) -> &X509Name {
62         &self.tbs_cert_list.issuer
63     }
64 
65     /// Get the date and time of the last (this) update.
66     #[inline]
last_update(&self) -> ASN1Time67     pub fn last_update(&self) -> ASN1Time {
68         self.tbs_cert_list.this_update
69     }
70 
71     /// Get the date and time of the next update, if present.
72     #[inline]
next_update(&self) -> Option<ASN1Time>73     pub fn next_update(&self) -> Option<ASN1Time> {
74         self.tbs_cert_list.next_update
75     }
76 
77     /// Return an iterator over the `RevokedCertificate` objects
iter_revoked_certificates(&self) -> impl Iterator<Item = &RevokedCertificate<'a>>78     pub fn iter_revoked_certificates(&self) -> impl Iterator<Item = &RevokedCertificate<'a>> {
79         self.tbs_cert_list.revoked_certificates.iter()
80     }
81 
82     /// Get the CRL extensions.
83     #[inline]
extensions(&self) -> &[X509Extension]84     pub fn extensions(&self) -> &[X509Extension] {
85         &self.tbs_cert_list.extensions
86     }
87 
88     /// Get the CRL number, if present
89     ///
90     /// Note that the returned value is a `BigUint`, because of the following RFC specification:
91     /// <pre>
92     /// Given the requirements above, CRL numbers can be expected to contain long integers.  CRL
93     /// verifiers MUST be able to handle CRLNumber values up to 20 octets.  Conformant CRL issuers
94     /// MUST NOT use CRLNumber values longer than 20 octets.
95     /// </pre>
crl_number(&self) -> Option<&BigUint>96     pub fn crl_number(&self) -> Option<&BigUint> {
97         self.extensions()
98             .iter()
99             .find(|&ext| ext.oid == OID_X509_EXT_BASIC_CONSTRAINTS)
100             .and_then(|ext| match ext.parsed_extension {
101                 ParsedExtension::CRLNumber(ref num) => Some(num),
102                 _ => None,
103             })
104     }
105 }
106 
107 /// <pre>
108 /// CertificateList  ::=  SEQUENCE  {
109 ///      tbsCertList          TBSCertList,
110 ///      signatureAlgorithm   AlgorithmIdentifier,
111 ///      signatureValue       BIT STRING  }
112 /// </pre>
113 impl<'a> FromDer<'a> for CertificateRevocationList<'a> {
from_der(i: &'a [u8]) -> X509Result<Self>114     fn from_der(i: &'a [u8]) -> X509Result<Self> {
115         parse_der_sequence_defined_g(|i, _| {
116             let (i, tbs_cert_list) = TbsCertList::from_der(i)?;
117             let (i, signature_algorithm) = AlgorithmIdentifier::from_der(i)?;
118             let (i, signature_value) = parse_signature_value(i)?;
119             let crl = CertificateRevocationList {
120                 tbs_cert_list,
121                 signature_algorithm,
122                 signature_value,
123             };
124             Ok((i, crl))
125         })(i)
126     }
127 }
128 
129 /// The sequence TBSCertList contains information about the certificates that have
130 /// been revoked by the CA that issued the CRL.
131 ///
132 /// RFC5280 definition:
133 ///
134 /// <pre>
135 /// TBSCertList  ::=  SEQUENCE  {
136 ///         version                 Version OPTIONAL,
137 ///                                      -- if present, MUST be v2
138 ///         signature               AlgorithmIdentifier,
139 ///         issuer                  Name,
140 ///         thisUpdate              Time,
141 ///         nextUpdate              Time OPTIONAL,
142 ///         revokedCertificates     SEQUENCE OF SEQUENCE  {
143 ///             userCertificate         CertificateSerialNumber,
144 ///             revocationDate          Time,
145 ///             crlEntryExtensions      Extensions OPTIONAL
146 ///                                      -- if present, version MUST be v2
147 ///                                   } OPTIONAL,
148 ///         crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
149 ///                                      -- if present, version MUST be v2
150 ///                             }
151 /// </pre>
152 #[derive(Clone, Debug, PartialEq)]
153 pub struct TbsCertList<'a> {
154     pub version: Option<X509Version>,
155     pub signature: AlgorithmIdentifier<'a>,
156     pub issuer: X509Name<'a>,
157     pub this_update: ASN1Time,
158     pub next_update: Option<ASN1Time>,
159     pub revoked_certificates: Vec<RevokedCertificate<'a>>,
160     extensions: Vec<X509Extension<'a>>,
161     pub(crate) raw: &'a [u8],
162 }
163 
164 impl<'a> TbsCertList<'a> {
165     /// Returns the certificate extensions
166     #[inline]
extensions(&self) -> &[X509Extension]167     pub fn extensions(&self) -> &[X509Extension] {
168         &self.extensions
169     }
170 
171     /// Returns an iterator over the certificate extensions
172     #[inline]
iter_extensions(&self) -> impl Iterator<Item = &X509Extension>173     pub fn iter_extensions(&self) -> impl Iterator<Item = &X509Extension> {
174         self.extensions.iter()
175     }
176 
177     /// Searches for an extension with the given `Oid`.
178     ///
179     /// Note: if there are several extensions with the same `Oid`, the first one is returned.
find_extension(&self, oid: &Oid) -> Option<&X509Extension>180     pub fn find_extension(&self, oid: &Oid) -> Option<&X509Extension> {
181         self.extensions.iter().find(|&ext| ext.oid == *oid)
182     }
183 
184     /// Builds and returns a map of extensions.
185     ///
186     /// If an extension is present twice, this will fail and return `DuplicateExtensions`.
extensions_map(&self) -> Result<HashMap<Oid, &X509Extension>, X509Error>187     pub fn extensions_map(&self) -> Result<HashMap<Oid, &X509Extension>, X509Error> {
188         self.extensions
189             .iter()
190             .try_fold(HashMap::new(), |mut m, ext| {
191                 if m.contains_key(&ext.oid) {
192                     return Err(X509Error::DuplicateExtensions);
193                 }
194                 m.insert(ext.oid.clone(), ext);
195                 Ok(m)
196             })
197     }
198 }
199 
200 impl<'a> AsRef<[u8]> for TbsCertList<'a> {
as_ref(&self) -> &[u8]201     fn as_ref(&self) -> &[u8] {
202         self.raw
203     }
204 }
205 
206 impl<'a> FromDer<'a> for TbsCertList<'a> {
from_der(i: &'a [u8]) -> X509Result<Self>207     fn from_der(i: &'a [u8]) -> X509Result<Self> {
208         let start_i = i;
209         parse_der_sequence_defined_g(move |i, _| {
210             let (i, version) =
211                 opt(map(parse_der_u32, X509Version))(i).or(Err(X509Error::InvalidVersion))?;
212             let (i, signature) = AlgorithmIdentifier::from_der(i)?;
213             let (i, issuer) = X509Name::from_der(i)?;
214             let (i, this_update) = ASN1Time::from_der(i)?;
215             let (i, next_update) = ASN1Time::from_der_opt(i)?;
216             let (i, revoked_certificates) = opt(complete(parse_revoked_certificates))(i)?;
217             let (i, extensions) = parse_extensions(i, BerTag(0))?;
218             let len = start_i.offset(i);
219             let tbs = TbsCertList {
220                 version,
221                 signature,
222                 issuer,
223                 this_update,
224                 next_update,
225                 revoked_certificates: revoked_certificates.unwrap_or_default(),
226                 extensions,
227                 raw: &start_i[..len],
228             };
229             Ok((i, tbs))
230         })(i)
231     }
232 }
233 
234 #[derive(Clone, Debug, PartialEq)]
235 pub struct RevokedCertificate<'a> {
236     /// The Serial number of the revoked certificate
237     pub user_certificate: BigUint,
238     /// The date on which the revocation occurred is specified.
239     pub revocation_date: ASN1Time,
240     /// Additional information about revocation
241     extensions: Vec<X509Extension<'a>>,
242     pub(crate) raw_serial: &'a [u8],
243 }
244 
245 impl<'a> RevokedCertificate<'a> {
246     /// Return the serial number of the revoked certificate
serial(&self) -> &BigUint247     pub fn serial(&self) -> &BigUint {
248         &self.user_certificate
249     }
250 
251     /// Get the CRL entry extensions.
252     #[inline]
extensions(&self) -> &[X509Extension]253     pub fn extensions(&self) -> &[X509Extension] {
254         &self.extensions
255     }
256 
257     /// Returns an iterator over the CRL entry extensions
258     #[inline]
iter_extensions(&self) -> impl Iterator<Item = &X509Extension>259     pub fn iter_extensions(&self) -> impl Iterator<Item = &X509Extension> {
260         self.extensions.iter()
261     }
262 
263     /// Searches for a CRL entry extension with the given `Oid`.
264     ///
265     /// Note: if there are several extensions with the same `Oid`, the first one is returned.
find_extension(&self, oid: &Oid) -> Option<&X509Extension>266     pub fn find_extension(&self, oid: &Oid) -> Option<&X509Extension> {
267         self.extensions.iter().find(|&ext| ext.oid == *oid)
268     }
269 
270     /// Builds and returns a map of CRL entry extensions.
271     ///
272     /// If an extension is present twice, this will fail and return `DuplicateExtensions`.
extensions_map(&self) -> Result<HashMap<Oid, &X509Extension>, X509Error>273     pub fn extensions_map(&self) -> Result<HashMap<Oid, &X509Extension>, X509Error> {
274         self.extensions
275             .iter()
276             .try_fold(HashMap::new(), |mut m, ext| {
277                 if m.contains_key(&ext.oid) {
278                     return Err(X509Error::DuplicateExtensions);
279                 }
280                 m.insert(ext.oid.clone(), ext);
281                 Ok(m)
282             })
283     }
284 
285     /// Get the raw bytes of the certificate serial number
raw_serial(&self) -> &[u8]286     pub fn raw_serial(&self) -> &[u8] {
287         self.raw_serial
288     }
289 
290     /// Get a formatted string of the certificate serial number, separated by ':'
raw_serial_as_string(&self) -> String291     pub fn raw_serial_as_string(&self) -> String {
292         let mut s = self
293             .raw_serial
294             .iter()
295             .fold(String::with_capacity(3 * self.raw_serial.len()), |a, b| {
296                 a + &format!("{:02x}:", b)
297             });
298         s.pop();
299         s
300     }
301 
302     /// Get the code identifying the reason for the revocation, if present
reason_code(&self) -> Option<(bool, ReasonCode)>303     pub fn reason_code(&self) -> Option<(bool, ReasonCode)> {
304         self.find_extension(&OID_X509_EXT_REASON_CODE)
305             .and_then(|ext| match ext.parsed_extension {
306                 ParsedExtension::ReasonCode(code) => Some((ext.critical, code)),
307                 _ => None,
308             })
309     }
310 
311     /// Get the invalidity date, if present
312     ///
313     /// The invalidity date is the date on which it is known or suspected that the private
314     ///  key was compromised or that the certificate otherwise became invalid.
invalidity_date(&self) -> Option<(bool, ASN1Time)>315     pub fn invalidity_date(&self) -> Option<(bool, ASN1Time)> {
316         self.find_extension(&OID_X509_EXT_INVALIDITY_DATE)
317             .and_then(|ext| match ext.parsed_extension {
318                 ParsedExtension::InvalidityDate(date) => Some((ext.critical, date)),
319                 _ => None,
320             })
321     }
322 }
323 
324 // revokedCertificates     SEQUENCE OF SEQUENCE  {
325 //     userCertificate         CertificateSerialNumber,
326 //     revocationDate          Time,
327 //     crlEntryExtensions      Extensions OPTIONAL
328 //                                   -- if present, MUST be v2
329 //                          }  OPTIONAL,
330 impl<'a> FromDer<'a> for RevokedCertificate<'a> {
from_der(i: &'a [u8]) -> X509Result<Self>331     fn from_der(i: &'a [u8]) -> X509Result<Self> {
332         parse_der_sequence_defined_g(|i, _| {
333             let (i, (raw_serial, user_certificate)) = parse_serial(i)?;
334             let (i, revocation_date) = ASN1Time::from_der(i)?;
335             let (i, extensions) = opt(complete(parse_extension_sequence))(i)?;
336             let revoked = RevokedCertificate {
337                 user_certificate,
338                 revocation_date,
339                 extensions: extensions.unwrap_or_default(),
340                 raw_serial,
341             };
342             Ok((i, revoked))
343         })(i)
344     }
345 }
346 
parse_revoked_certificates(i: &[u8]) -> X509Result<Vec<RevokedCertificate>>347 fn parse_revoked_certificates(i: &[u8]) -> X509Result<Vec<RevokedCertificate>> {
348     parse_der_sequence_defined_g(|a, _| {
349         all_consuming(many1(complete(RevokedCertificate::from_der)))(a)
350     })(i)
351 }
352