1use crate::error::{X509Error, X509Result};
2use crate::extensions::*;
3use crate::time::ASN1Time;
4use crate::utils::format_serial;
5use crate::x509::{
6 parse_serial, parse_signature_value, AlgorithmIdentifier, ReasonCode, X509Name, X509Version,
7};
8
9#[cfg(feature = "verify")]
10use crate::verify::verify_signature;
11#[cfg(feature = "verify")]
12use crate::x509::SubjectPublicKeyInfo;
13use asn1_rs::{BitString, FromDer};
14use der_parser::der::*;
15use der_parser::num_bigint::BigUint;
16use nom::combinator::{all_consuming, complete, map, opt};
17use nom::multi::many0;
18use nom::Offset;
19use oid_registry::*;
20use std::collections::HashMap;
21
22#[derive(Clone, Debug)]
50pub struct CertificateRevocationList<'a> {
51 pub tbs_cert_list: TbsCertList<'a>,
52 pub signature_algorithm: AlgorithmIdentifier<'a>,
53 pub signature_value: BitString<'a>,
54
55 pub(crate) raw: &'a [u8],
57}
58
59impl<'a> CertificateRevocationList<'a> {
60 pub fn version(&self) -> Option<X509Version> {
62 self.tbs_cert_list.version
63 }
64
65 #[inline]
67 pub fn issuer(&self) -> &X509Name<'_> {
68 &self.tbs_cert_list.issuer
69 }
70
71 #[inline]
73 pub fn last_update(&self) -> ASN1Time {
74 self.tbs_cert_list.this_update
75 }
76
77 #[inline]
79 pub fn next_update(&self) -> Option<ASN1Time> {
80 self.tbs_cert_list.next_update
81 }
82
83 pub fn iter_revoked_certificates(&self) -> impl Iterator<Item = &RevokedCertificate<'a>> {
85 self.tbs_cert_list.revoked_certificates.iter()
86 }
87
88 #[inline]
90 pub fn extensions(&self) -> &[X509Extension<'_>] {
91 &self.tbs_cert_list.extensions
92 }
93
94 pub fn crl_number(&self) -> Option<&BigUint> {
103 self.extensions()
104 .iter()
105 .find(|&ext| ext.oid == OID_X509_EXT_CRL_NUMBER)
106 .and_then(|ext| match ext.parsed_extension {
107 ParsedExtension::CRLNumber(ref num) => Some(num),
108 _ => None,
109 })
110 }
111
112 #[cfg(feature = "verify")]
118 #[cfg_attr(docsrs, doc(cfg(feature = "verify")))]
119 pub fn verify_signature(&self, public_key: &SubjectPublicKeyInfo) -> Result<(), X509Error> {
120 verify_signature(
121 public_key,
122 &self.signature_algorithm,
123 &self.signature_value,
124 self.tbs_cert_list.raw,
125 )
126 }
127
128 pub fn as_raw(&self) -> &'a [u8] {
136 self.raw
137 }
138}
139
140impl<'a> AsRef<[u8]> for CertificateRevocationList<'a> {
141 fn as_ref(&self) -> &[u8] {
142 self.as_raw()
143 }
144}
145
146impl<'a> FromDer<'a, X509Error> for CertificateRevocationList<'a> {
153 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
154 let start_i = i;
155 let (rem, mut crl) = parse_der_sequence_defined_g(|i, _| {
156 let (i, tbs_cert_list) = TbsCertList::from_der(i)?;
157 let (i, signature_algorithm) = AlgorithmIdentifier::from_der(i)?;
158 let (i, signature_value) = parse_signature_value(i)?;
159 let crl = CertificateRevocationList {
160 tbs_cert_list,
161 signature_algorithm,
162 signature_value,
163 raw: &[],
164 };
165 Ok((i, crl))
166 })(i)?;
167 let len = start_i.offset(rem);
168 crl.raw = &start_i[..len];
169 Ok((rem, crl))
170 }
171}
172
173#[derive(Clone, Debug, PartialEq)]
197pub struct TbsCertList<'a> {
198 pub version: Option<X509Version>,
199 pub signature: AlgorithmIdentifier<'a>,
200 pub issuer: X509Name<'a>,
201 pub this_update: ASN1Time,
202 pub next_update: Option<ASN1Time>,
203 pub revoked_certificates: Vec<RevokedCertificate<'a>>,
204 extensions: Vec<X509Extension<'a>>,
205 pub(crate) raw: &'a [u8],
206}
207
208impl TbsCertList<'_> {
209 #[inline]
211 pub fn extensions(&self) -> &[X509Extension<'_>] {
212 &self.extensions
213 }
214
215 #[inline]
217 pub fn iter_extensions(&self) -> impl Iterator<Item = &X509Extension<'_>> {
218 self.extensions.iter()
219 }
220
221 pub fn find_extension(&self, oid: &Oid) -> Option<&X509Extension<'_>> {
225 self.extensions.iter().find(|&ext| ext.oid == *oid)
226 }
227
228 pub fn extensions_map(&self) -> Result<HashMap<Oid<'_>, &X509Extension<'_>>, X509Error> {
232 self.extensions
233 .iter()
234 .try_fold(HashMap::new(), |mut m, ext| {
235 if m.contains_key(&ext.oid) {
236 return Err(X509Error::DuplicateExtensions);
237 }
238 m.insert(ext.oid.clone(), ext);
239 Ok(m)
240 })
241 }
242}
243
244impl AsRef<[u8]> for TbsCertList<'_> {
245 fn as_ref(&self) -> &[u8] {
246 self.raw
247 }
248}
249
250impl<'a> FromDer<'a, X509Error> for TbsCertList<'a> {
251 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
252 let start_i = i;
253 parse_der_sequence_defined_g(move |i, _| {
254 let (i, version) =
255 opt(map(parse_der_u32, X509Version))(i).or(Err(X509Error::InvalidVersion))?;
256 let (i, signature) = AlgorithmIdentifier::from_der(i)?;
257 let (i, issuer) = X509Name::from_der(i)?;
258 let (i, this_update) = ASN1Time::from_der(i)?;
259 let (i, next_update) = ASN1Time::from_der_opt(i)?;
260 let (i, revoked_certificates) = opt(complete(parse_revoked_certificates))(i)?;
261 let (i, extensions) = parse_extensions(i, Tag(0))?;
262 let len = start_i.offset(i);
263 let tbs = TbsCertList {
264 version,
265 signature,
266 issuer,
267 this_update,
268 next_update,
269 revoked_certificates: revoked_certificates.unwrap_or_default(),
270 extensions,
271 raw: &start_i[..len],
272 };
273 Ok((i, tbs))
274 })(i)
275 }
276}
277
278#[derive(Clone, Debug, PartialEq)]
279pub struct RevokedCertificate<'a> {
280 pub user_certificate: BigUint,
282 pub revocation_date: ASN1Time,
284 extensions: Vec<X509Extension<'a>>,
286 pub(crate) raw_serial: &'a [u8],
287}
288
289impl RevokedCertificate<'_> {
290 pub fn serial(&self) -> &BigUint {
292 &self.user_certificate
293 }
294
295 #[inline]
297 pub fn extensions(&self) -> &[X509Extension<'_>] {
298 &self.extensions
299 }
300
301 #[inline]
303 pub fn iter_extensions(&self) -> impl Iterator<Item = &X509Extension<'_>> {
304 self.extensions.iter()
305 }
306
307 pub fn find_extension(&self, oid: &Oid) -> Option<&X509Extension<'_>> {
311 self.extensions.iter().find(|&ext| ext.oid == *oid)
312 }
313
314 pub fn extensions_map(&self) -> Result<HashMap<Oid<'_>, &X509Extension<'_>>, X509Error> {
318 self.extensions
319 .iter()
320 .try_fold(HashMap::new(), |mut m, ext| {
321 if m.contains_key(&ext.oid) {
322 return Err(X509Error::DuplicateExtensions);
323 }
324 m.insert(ext.oid.clone(), ext);
325 Ok(m)
326 })
327 }
328
329 pub fn raw_serial(&self) -> &[u8] {
331 self.raw_serial
332 }
333
334 pub fn raw_serial_as_string(&self) -> String {
336 format_serial(self.raw_serial)
337 }
338
339 pub fn reason_code(&self) -> Option<(bool, ReasonCode)> {
341 self.find_extension(&OID_X509_EXT_REASON_CODE)
342 .and_then(|ext| match ext.parsed_extension {
343 ParsedExtension::ReasonCode(code) => Some((ext.critical, code)),
344 _ => None,
345 })
346 }
347
348 pub fn invalidity_date(&self) -> Option<(bool, ASN1Time)> {
353 self.find_extension(&OID_X509_EXT_INVALIDITY_DATE)
354 .and_then(|ext| match ext.parsed_extension {
355 ParsedExtension::InvalidityDate(date) => Some((ext.critical, date)),
356 _ => None,
357 })
358 }
359}
360
361impl<'a> FromDer<'a, X509Error> for RevokedCertificate<'a> {
368 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
369 parse_der_sequence_defined_g(|i, _| {
370 let (i, (raw_serial, user_certificate)) = parse_serial(i)?;
371 let (i, revocation_date) = ASN1Time::from_der(i)?;
372 let (i, extensions) = opt(complete(parse_extension_sequence))(i)?;
373 let revoked = RevokedCertificate {
374 user_certificate,
375 revocation_date,
376 extensions: extensions.unwrap_or_default(),
377 raw_serial,
378 };
379 Ok((i, revoked))
380 })(i)
381 }
382}
383
384fn parse_revoked_certificates(i: &[u8]) -> X509Result<'_, Vec<RevokedCertificate<'_>>> {
385 parse_der_sequence_defined_g(|a, _| {
386 all_consuming(many0(complete(RevokedCertificate::from_der)))(a)
387 })(i)
388}