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::ber::Tag;
15use der_parser::der::*;
16use der_parser::num_bigint::BigUint;
17use der_parser::oid::Oid;
18use nom::combinator::{all_consuming, complete, map, opt};
19use nom::multi::many0;
20use nom::Offset;
21use oid_registry::*;
22use std::collections::HashMap;
23
24#[derive(Clone, Debug)]
52pub struct CertificateRevocationList<'a> {
53 pub tbs_cert_list: TbsCertList<'a>,
54 pub signature_algorithm: AlgorithmIdentifier<'a>,
55 pub signature_value: BitString<'a>,
56}
57
58impl<'a> CertificateRevocationList<'a> {
59 pub fn version(&self) -> Option<X509Version> {
61 self.tbs_cert_list.version
62 }
63
64 #[inline]
66 pub fn issuer(&self) -> &X509Name {
67 &self.tbs_cert_list.issuer
68 }
69
70 #[inline]
72 pub fn last_update(&self) -> ASN1Time {
73 self.tbs_cert_list.this_update
74 }
75
76 #[inline]
78 pub fn next_update(&self) -> Option<ASN1Time> {
79 self.tbs_cert_list.next_update
80 }
81
82 pub fn iter_revoked_certificates(&self) -> impl Iterator<Item = &RevokedCertificate<'a>> {
84 self.tbs_cert_list.revoked_certificates.iter()
85 }
86
87 #[inline]
89 pub fn extensions(&self) -> &[X509Extension] {
90 &self.tbs_cert_list.extensions
91 }
92
93 pub fn crl_number(&self) -> Option<&BigUint> {
102 self.extensions()
103 .iter()
104 .find(|&ext| ext.oid == OID_X509_EXT_CRL_NUMBER)
105 .and_then(|ext| match ext.parsed_extension {
106 ParsedExtension::CRLNumber(ref num) => Some(num),
107 _ => None,
108 })
109 }
110
111 #[cfg(feature = "verify")]
117 #[cfg_attr(docsrs, doc(cfg(feature = "verify")))]
118 pub fn verify_signature(&self, public_key: &SubjectPublicKeyInfo) -> Result<(), X509Error> {
119 verify_signature(
120 public_key,
121 &self.signature_algorithm,
122 &self.signature_value,
123 self.tbs_cert_list.raw,
124 )
125 }
126}
127
128impl<'a> FromDer<'a, X509Error> for CertificateRevocationList<'a> {
135 fn from_der(i: &'a [u8]) -> X509Result<Self> {
136 parse_der_sequence_defined_g(|i, _| {
137 let (i, tbs_cert_list) = TbsCertList::from_der(i)?;
138 let (i, signature_algorithm) = AlgorithmIdentifier::from_der(i)?;
139 let (i, signature_value) = parse_signature_value(i)?;
140 let crl = CertificateRevocationList {
141 tbs_cert_list,
142 signature_algorithm,
143 signature_value,
144 };
145 Ok((i, crl))
146 })(i)
147 }
148}
149
150#[derive(Clone, Debug, PartialEq)]
174pub struct TbsCertList<'a> {
175 pub version: Option<X509Version>,
176 pub signature: AlgorithmIdentifier<'a>,
177 pub issuer: X509Name<'a>,
178 pub this_update: ASN1Time,
179 pub next_update: Option<ASN1Time>,
180 pub revoked_certificates: Vec<RevokedCertificate<'a>>,
181 extensions: Vec<X509Extension<'a>>,
182 pub(crate) raw: &'a [u8],
183}
184
185impl<'a> TbsCertList<'a> {
186 #[inline]
188 pub fn extensions(&self) -> &[X509Extension] {
189 &self.extensions
190 }
191
192 #[inline]
194 pub fn iter_extensions(&self) -> impl Iterator<Item = &X509Extension> {
195 self.extensions.iter()
196 }
197
198 pub fn find_extension(&self, oid: &Oid) -> Option<&X509Extension> {
202 self.extensions.iter().find(|&ext| ext.oid == *oid)
203 }
204
205 pub fn extensions_map(&self) -> Result<HashMap<Oid, &X509Extension>, X509Error> {
209 self.extensions
210 .iter()
211 .try_fold(HashMap::new(), |mut m, ext| {
212 if m.contains_key(&ext.oid) {
213 return Err(X509Error::DuplicateExtensions);
214 }
215 m.insert(ext.oid.clone(), ext);
216 Ok(m)
217 })
218 }
219}
220
221impl<'a> AsRef<[u8]> for TbsCertList<'a> {
222 fn as_ref(&self) -> &[u8] {
223 self.raw
224 }
225}
226
227impl<'a> FromDer<'a, X509Error> for TbsCertList<'a> {
228 fn from_der(i: &'a [u8]) -> X509Result<Self> {
229 let start_i = i;
230 parse_der_sequence_defined_g(move |i, _| {
231 let (i, version) =
232 opt(map(parse_der_u32, X509Version))(i).or(Err(X509Error::InvalidVersion))?;
233 let (i, signature) = AlgorithmIdentifier::from_der(i)?;
234 let (i, issuer) = X509Name::from_der(i)?;
235 let (i, this_update) = ASN1Time::from_der(i)?;
236 let (i, next_update) = ASN1Time::from_der_opt(i)?;
237 let (i, revoked_certificates) = opt(complete(parse_revoked_certificates))(i)?;
238 let (i, extensions) = parse_extensions(i, Tag(0))?;
239 let len = start_i.offset(i);
240 let tbs = TbsCertList {
241 version,
242 signature,
243 issuer,
244 this_update,
245 next_update,
246 revoked_certificates: revoked_certificates.unwrap_or_default(),
247 extensions,
248 raw: &start_i[..len],
249 };
250 Ok((i, tbs))
251 })(i)
252 }
253}
254
255#[derive(Clone, Debug, PartialEq)]
256pub struct RevokedCertificate<'a> {
257 pub user_certificate: BigUint,
259 pub revocation_date: ASN1Time,
261 extensions: Vec<X509Extension<'a>>,
263 pub(crate) raw_serial: &'a [u8],
264}
265
266impl<'a> RevokedCertificate<'a> {
267 pub fn serial(&self) -> &BigUint {
269 &self.user_certificate
270 }
271
272 #[inline]
274 pub fn extensions(&self) -> &[X509Extension] {
275 &self.extensions
276 }
277
278 #[inline]
280 pub fn iter_extensions(&self) -> impl Iterator<Item = &X509Extension> {
281 self.extensions.iter()
282 }
283
284 pub fn find_extension(&self, oid: &Oid) -> Option<&X509Extension> {
288 self.extensions.iter().find(|&ext| ext.oid == *oid)
289 }
290
291 pub fn extensions_map(&self) -> Result<HashMap<Oid, &X509Extension>, X509Error> {
295 self.extensions
296 .iter()
297 .try_fold(HashMap::new(), |mut m, ext| {
298 if m.contains_key(&ext.oid) {
299 return Err(X509Error::DuplicateExtensions);
300 }
301 m.insert(ext.oid.clone(), ext);
302 Ok(m)
303 })
304 }
305
306 pub fn raw_serial(&self) -> &[u8] {
308 self.raw_serial
309 }
310
311 pub fn raw_serial_as_string(&self) -> String {
313 format_serial(self.raw_serial)
314 }
315
316 pub fn reason_code(&self) -> Option<(bool, ReasonCode)> {
318 self.find_extension(&OID_X509_EXT_REASON_CODE)
319 .and_then(|ext| match ext.parsed_extension {
320 ParsedExtension::ReasonCode(code) => Some((ext.critical, code)),
321 _ => None,
322 })
323 }
324
325 pub fn invalidity_date(&self) -> Option<(bool, ASN1Time)> {
330 self.find_extension(&OID_X509_EXT_INVALIDITY_DATE)
331 .and_then(|ext| match ext.parsed_extension {
332 ParsedExtension::InvalidityDate(date) => Some((ext.critical, date)),
333 _ => None,
334 })
335 }
336}
337
338impl<'a> FromDer<'a, X509Error> for RevokedCertificate<'a> {
345 fn from_der(i: &'a [u8]) -> X509Result<Self> {
346 parse_der_sequence_defined_g(|i, _| {
347 let (i, (raw_serial, user_certificate)) = parse_serial(i)?;
348 let (i, revocation_date) = ASN1Time::from_der(i)?;
349 let (i, extensions) = opt(complete(parse_extension_sequence))(i)?;
350 let revoked = RevokedCertificate {
351 user_certificate,
352 revocation_date,
353 extensions: extensions.unwrap_or_default(),
354 raw_serial,
355 };
356 Ok((i, revoked))
357 })(i)
358 }
359}
360
361fn parse_revoked_certificates(i: &[u8]) -> X509Result<Vec<RevokedCertificate>> {
362 parse_der_sequence_defined_g(|a, _| {
363 all_consuming(many0(complete(RevokedCertificate::from_der)))(a)
364 })(i)
365}