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
56impl<'a> CertificateRevocationList<'a> {
57 pub fn version(&self) -> Option<X509Version> {
59 self.tbs_cert_list.version
60 }
61
62 #[inline]
64 pub fn issuer(&self) -> &X509Name {
65 &self.tbs_cert_list.issuer
66 }
67
68 #[inline]
70 pub fn last_update(&self) -> ASN1Time {
71 self.tbs_cert_list.this_update
72 }
73
74 #[inline]
76 pub fn next_update(&self) -> Option<ASN1Time> {
77 self.tbs_cert_list.next_update
78 }
79
80 pub fn iter_revoked_certificates(&self) -> impl Iterator<Item = &RevokedCertificate<'a>> {
82 self.tbs_cert_list.revoked_certificates.iter()
83 }
84
85 #[inline]
87 pub fn extensions(&self) -> &[X509Extension] {
88 &self.tbs_cert_list.extensions
89 }
90
91 pub fn crl_number(&self) -> Option<&BigUint> {
100 self.extensions()
101 .iter()
102 .find(|&ext| ext.oid == OID_X509_EXT_CRL_NUMBER)
103 .and_then(|ext| match ext.parsed_extension {
104 ParsedExtension::CRLNumber(ref num) => Some(num),
105 _ => None,
106 })
107 }
108
109 #[cfg(feature = "verify")]
115 #[cfg_attr(docsrs, doc(cfg(feature = "verify")))]
116 pub fn verify_signature(&self, public_key: &SubjectPublicKeyInfo) -> Result<(), X509Error> {
117 verify_signature(
118 public_key,
119 &self.signature_algorithm,
120 &self.signature_value,
121 self.tbs_cert_list.raw,
122 )
123 }
124}
125
126impl<'a> FromDer<'a, X509Error> for CertificateRevocationList<'a> {
133 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
134 parse_der_sequence_defined_g(|i, _| {
135 let (i, tbs_cert_list) = TbsCertList::from_der(i)?;
136 let (i, signature_algorithm) = AlgorithmIdentifier::from_der(i)?;
137 let (i, signature_value) = parse_signature_value(i)?;
138 let crl = CertificateRevocationList {
139 tbs_cert_list,
140 signature_algorithm,
141 signature_value,
142 };
143 Ok((i, crl))
144 })(i)
145 }
146}
147
148#[derive(Clone, Debug, PartialEq)]
172pub struct TbsCertList<'a> {
173 pub version: Option<X509Version>,
174 pub signature: AlgorithmIdentifier<'a>,
175 pub issuer: X509Name<'a>,
176 pub this_update: ASN1Time,
177 pub next_update: Option<ASN1Time>,
178 pub revoked_certificates: Vec<RevokedCertificate<'a>>,
179 extensions: Vec<X509Extension<'a>>,
180 pub(crate) raw: &'a [u8],
181}
182
183impl TbsCertList<'_> {
184 #[inline]
186 pub fn extensions(&self) -> &[X509Extension] {
187 &self.extensions
188 }
189
190 #[inline]
192 pub fn iter_extensions(&self) -> impl Iterator<Item = &X509Extension> {
193 self.extensions.iter()
194 }
195
196 pub fn find_extension(&self, oid: &Oid) -> Option<&X509Extension> {
200 self.extensions.iter().find(|&ext| ext.oid == *oid)
201 }
202
203 pub fn extensions_map(&self) -> Result<HashMap<Oid, &X509Extension>, X509Error> {
207 self.extensions
208 .iter()
209 .try_fold(HashMap::new(), |mut m, ext| {
210 if m.contains_key(&ext.oid) {
211 return Err(X509Error::DuplicateExtensions);
212 }
213 m.insert(ext.oid.clone(), ext);
214 Ok(m)
215 })
216 }
217}
218
219impl AsRef<[u8]> for TbsCertList<'_> {
220 fn as_ref(&self) -> &[u8] {
221 self.raw
222 }
223}
224
225impl<'a> FromDer<'a, X509Error> for TbsCertList<'a> {
226 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
227 let start_i = i;
228 parse_der_sequence_defined_g(move |i, _| {
229 let (i, version) =
230 opt(map(parse_der_u32, X509Version))(i).or(Err(X509Error::InvalidVersion))?;
231 let (i, signature) = AlgorithmIdentifier::from_der(i)?;
232 let (i, issuer) = X509Name::from_der(i)?;
233 let (i, this_update) = ASN1Time::from_der(i)?;
234 let (i, next_update) = ASN1Time::from_der_opt(i)?;
235 let (i, revoked_certificates) = opt(complete(parse_revoked_certificates))(i)?;
236 let (i, extensions) = parse_extensions(i, Tag(0))?;
237 let len = start_i.offset(i);
238 let tbs = TbsCertList {
239 version,
240 signature,
241 issuer,
242 this_update,
243 next_update,
244 revoked_certificates: revoked_certificates.unwrap_or_default(),
245 extensions,
246 raw: &start_i[..len],
247 };
248 Ok((i, tbs))
249 })(i)
250 }
251}
252
253#[derive(Clone, Debug, PartialEq)]
254pub struct RevokedCertificate<'a> {
255 pub user_certificate: BigUint,
257 pub revocation_date: ASN1Time,
259 extensions: Vec<X509Extension<'a>>,
261 pub(crate) raw_serial: &'a [u8],
262}
263
264impl RevokedCertificate<'_> {
265 pub fn serial(&self) -> &BigUint {
267 &self.user_certificate
268 }
269
270 #[inline]
272 pub fn extensions(&self) -> &[X509Extension] {
273 &self.extensions
274 }
275
276 #[inline]
278 pub fn iter_extensions(&self) -> impl Iterator<Item = &X509Extension> {
279 self.extensions.iter()
280 }
281
282 pub fn find_extension(&self, oid: &Oid) -> Option<&X509Extension> {
286 self.extensions.iter().find(|&ext| ext.oid == *oid)
287 }
288
289 pub fn extensions_map(&self) -> Result<HashMap<Oid, &X509Extension>, X509Error> {
293 self.extensions
294 .iter()
295 .try_fold(HashMap::new(), |mut m, ext| {
296 if m.contains_key(&ext.oid) {
297 return Err(X509Error::DuplicateExtensions);
298 }
299 m.insert(ext.oid.clone(), ext);
300 Ok(m)
301 })
302 }
303
304 pub fn raw_serial(&self) -> &[u8] {
306 self.raw_serial
307 }
308
309 pub fn raw_serial_as_string(&self) -> String {
311 format_serial(self.raw_serial)
312 }
313
314 pub fn reason_code(&self) -> Option<(bool, ReasonCode)> {
316 self.find_extension(&OID_X509_EXT_REASON_CODE)
317 .and_then(|ext| match ext.parsed_extension {
318 ParsedExtension::ReasonCode(code) => Some((ext.critical, code)),
319 _ => None,
320 })
321 }
322
323 pub fn invalidity_date(&self) -> Option<(bool, ASN1Time)> {
328 self.find_extension(&OID_X509_EXT_INVALIDITY_DATE)
329 .and_then(|ext| match ext.parsed_extension {
330 ParsedExtension::InvalidityDate(date) => Some((ext.critical, date)),
331 _ => None,
332 })
333 }
334}
335
336impl<'a> FromDer<'a, X509Error> for RevokedCertificate<'a> {
343 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
344 parse_der_sequence_defined_g(|i, _| {
345 let (i, (raw_serial, user_certificate)) = parse_serial(i)?;
346 let (i, revocation_date) = ASN1Time::from_der(i)?;
347 let (i, extensions) = opt(complete(parse_extension_sequence))(i)?;
348 let revoked = RevokedCertificate {
349 user_certificate,
350 revocation_date,
351 extensions: extensions.unwrap_or_default(),
352 raw_serial,
353 };
354 Ok((i, revoked))
355 })(i)
356 }
357}
358
359fn parse_revoked_certificates(i: &[u8]) -> X509Result<Vec<RevokedCertificate>> {
360 parse_der_sequence_defined_g(|a, _| {
361 all_consuming(many0(complete(RevokedCertificate::from_der)))(a)
362 })(i)
363}