1use crate::algorithm::{self, AlgorithmIdentifier};
8use crate::error::{Error, ErrorCode, Located, Result};
9use crate::extension::{self, Extensions};
10use crate::name::{self, Name};
11use crate::path::{Verified, Verify, WorkingKey};
12use crate::time::{self, Time};
13use structured_asn1::memory::{OwnedVec, Work};
14use structured_asn1::{BitString, Element, Integer, Parser, Reader, Span, Tag, universal};
15
16mod scope;
17use crate::revocation::{RevocationScheme, RevocationTarget, TargetKind};
18pub use scope::{CertificateKind, IssuingDistributionPoint, Reasons, ScopeFailure, ScopeOutcome};
19mod entry;
20pub use entry::EntryLookup;
21pub use entry::Reason;
22pub(crate) use entry::reason_element;
23mod delta;
24pub use delta::{
25 BoundDelta, CombinedEntry, DeltaBinding, DeltaFailure, EntryOrigin, MissingDeltaField,
26};
27mod freshness;
28pub use freshness::Freshness;
29pub(crate) use freshness::update_window;
30
31mod evidence;
32pub use evidence::{
33 AbsenceEvidence, CompleteEvidence, CompleteFacts, Coverage, CoverageAdmission, DeltaEvidence,
34 DeltaFacts, Evaluation, EvidenceSource, SourceOrigin,
35};
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum Version {
40 V1,
42 V2,
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub enum AuthenticationFailure {
49 KeyBinding,
51 IssuerName,
53 KeyUsage,
55 Signature,
57}
58
59#[derive(Debug, Clone, Copy)]
62pub struct Authenticated<'r, 'a> {
63 crl: &'r CertificateList<'a>,
64 issuer: &'r crate::Certificate<'a>,
65 key: WorkingKey<'a>,
66}
67
68impl<'r, 'a> Authenticated<'r, 'a> {
69 #[must_use]
71 pub fn crl(self) -> &'r CertificateList<'a> {
72 self.crl
73 }
74 #[must_use]
76 pub fn issuer(self) -> &'r crate::Certificate<'a> {
77 self.issuer
78 }
79 #[must_use]
81 pub fn key(self) -> WorkingKey<'a> {
82 self.key
83 }
84}
85
86#[derive(Debug)]
89pub enum Authentication<'r, 'a> {
90 Authenticated(Authenticated<'r, 'a>),
92 Rejected(AuthenticationFailure),
94 Unsupported,
96}
97
98#[derive(Debug)]
101pub struct RevokedCertificate<'a> {
102 serial: Integer<'a>,
103 revocation_date: Time,
104 revocation_date_offset: u64,
105 extensions: Extensions<'a>,
106 span: Span,
107}
108
109impl<'a> RevokedCertificate<'a> {
110 #[must_use]
112 pub fn serial(&self) -> Integer<'a> {
113 self.serial
114 }
115
116 #[must_use]
118 pub fn revocation_date(&self) -> Time {
119 self.revocation_date
120 }
121
122 pub fn time_relation<W: Work>(
126 &self,
127 now: crate::temporal::Reading,
128 utc: &crate::temporal::LeapTable<'_>,
129 execution: &W,
130 ) -> Result<crate::time::Relation> {
131 crate::time::relation_in(
132 self.revocation_date.instant(),
133 now,
134 utc,
135 execution,
136 (
137 "certificateList.revokedCertificates.revocationDate",
138 self.revocation_date_offset,
139 ),
140 )
141 }
142
143 #[must_use]
145 pub fn extensions(&self) -> &Extensions<'a> {
146 &self.extensions
147 }
148
149 #[must_use]
151 pub fn span(&self) -> Span {
152 self.span
153 }
154}
155
156#[derive(Debug)]
159pub struct TbsCertList<'a> {
160 version: Version,
161 signature: AlgorithmIdentifier<'a>,
162 issuer: Name<'a>,
163 this_update: Time,
164 next_update: Option<Time>,
165 revoked: OwnedVec<RevokedCertificate<'a>>,
166 extensions: Extensions<'a>,
167 bytes: &'a [u8],
168 span: Span,
169}
170
171impl<'a> TbsCertList<'a> {
172 #[must_use]
174 pub fn version(&self) -> Version {
175 self.version
176 }
177 #[must_use]
179 pub fn signature(&self) -> AlgorithmIdentifier<'a> {
180 self.signature
181 }
182 #[must_use]
184 pub fn issuer(&self) -> &Name<'a> {
185 &self.issuer
186 }
187 #[must_use]
189 pub fn this_update(&self) -> Time {
190 self.this_update
191 }
192 #[must_use]
195 pub fn next_update(&self) -> Option<Time> {
196 self.next_update
197 }
198 #[must_use]
200 pub fn revoked_certificates(&self) -> &[RevokedCertificate<'a>] {
201 &self.revoked
202 }
203 #[must_use]
205 pub fn extensions(&self) -> &Extensions<'a> {
206 &self.extensions
207 }
208 #[must_use]
210 pub fn as_bytes(&self) -> &'a [u8] {
211 self.bytes
212 }
213 #[must_use]
215 pub fn span(&self) -> Span {
216 self.span
217 }
218}
219
220#[derive(Debug)]
222pub struct CertificateList<'a> {
223 tbs: TbsCertList<'a>,
224 signature_algorithm: AlgorithmIdentifier<'a>,
225 signature: crate::signature::SignatureValue<'a>,
226 bytes: &'a [u8],
227 span: Span,
228}
229
230impl<'a> CertificateList<'a> {
231 pub fn authenticate<'r, V: Verify<E>, E: Work>(
240 &'r self,
241 issuer: &'r crate::Certificate<'a>,
242 key: WorkingKey<'a>,
243 verifier: &V,
244 execution: &E,
245 ) -> crate::error::CallbackResult<Authentication<'r, 'a>, V::Error> {
246 use crate::error::CallbackError;
247 let encoded_key = key.key().as_bytes();
248 let issuer_key = issuer.tbs().public_key().as_bytes();
249 let work = (encoded_key.len().max(issuer_key.len()) as u64)
250 .checked_mul(2)
251 .and_then(|n| n.checked_add(1))
252 .ok_or_else(|| {
253 Error::resource(
254 structured_asn1::memory::MemoryError::WorkExceeded,
255 FIELD,
256 self.span.start,
257 )
258 })?;
259 execution
260 .charge_work(work)
261 .map_err(|reason| Error::resource(reason, FIELD, self.span.start))?;
262 if encoded_key != issuer_key {
263 return Ok(Authentication::Rejected(AuthenticationFailure::KeyBinding));
264 }
265 if !self.tbs.issuer.matches(issuer.tbs().subject(), execution)? {
266 return Ok(Authentication::Rejected(AuthenticationFailure::IssuerName));
267 }
268 let usage = issuer.tbs().extensions().key_usage(execution)?;
269 if usage.is_some_and(|usage| !usage.crl_sign())
274 || (usage.is_none() && issuer.tbs().version() == crate::Version::V3)
275 {
276 return Ok(Authentication::Rejected(AuthenticationFailure::KeyUsage));
277 }
278 match verifier
279 .verify(
280 &self.tbs.signature,
281 key,
282 self.signed_bytes(),
283 self.signature,
284 execution,
285 )
286 .map_err(CallbackError::Callback)?
287 {
288 Verified::Yes => Ok(Authentication::Authenticated(Authenticated {
289 crl: self,
290 issuer,
291 key,
292 })),
293 Verified::No => Ok(Authentication::Rejected(AuthenticationFailure::Signature)),
294 Verified::Unsupported => Ok(Authentication::Unsupported),
295 }
296 }
297
298 pub fn read(parser: &'a Parser, bytes: &'a [u8], base: u64) -> Result<Self> {
300 let mut reader = parser.read(bytes, base).field(FIELD)?;
301 let element = required(&mut reader, FIELD, base)?;
302 let crl = Self::read_element(&reader, &element)?;
303 if !reader.is_empty() {
304 return Err(Error::new(
305 ErrorCode::TrailingData,
306 FIELD,
307 element.span().end(),
308 ));
309 }
310 Ok(crl)
311 }
312
313 pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
316 let mut outer = parent
319 .reread(element, structured_asn1::Encoding::Der)
320 .field(FIELD)?;
321 let root = outer
322 .expect(Tag::constructed(universal::SEQUENCE))
323 .field(FIELD)?;
324 let mut inside = outer.enter(&root).field(FIELD)?;
325 let tbs_element = required(&mut inside, TBS, root.span().start)?;
326 let tbs = read_tbs(&inside, &tbs_element)?;
327 let algorithm_element = required(&mut inside, ALGORITHM, root.span().start)?;
328 let signature_algorithm = algorithm::read(&inside, &algorithm_element, ALGORITHM)?;
329 let signature = crate::signature::SignatureValue::read(&mut inside, SIGNATURE)?;
330 end(&inside, FIELD, root.span().start)?;
331 if !signature_algorithm.matches_in(&tbs.signature, &inside)? {
334 return Err(Error::new(
335 ErrorCode::AlgorithmMismatch,
336 ALGORITHM,
337 algorithm_element.span().start,
338 ));
339 }
340 Ok(Self {
341 tbs,
342 signature_algorithm,
343 signature,
344 bytes: root.as_bytes(),
345 span: root.span(),
346 })
347 }
348
349 #[must_use]
351 pub fn tbs(&self) -> &TbsCertList<'a> {
352 &self.tbs
353 }
354 #[must_use]
356 pub fn signature_algorithm(&self) -> AlgorithmIdentifier<'a> {
357 self.signature_algorithm
358 }
359 #[must_use]
361 pub fn signature(&self) -> BitString<'a> {
362 self.signature.bit_string()
363 }
364 #[must_use]
366 pub fn signature_value(&self) -> crate::signature::SignatureValue<'a> {
367 self.signature
368 }
369 #[must_use]
371 pub fn signed_bytes(&self) -> &'a [u8] {
372 self.tbs.bytes
373 }
374 #[must_use]
376 pub fn as_bytes(&self) -> &'a [u8] {
377 self.bytes
378 }
379 #[must_use]
381 pub fn span(&self) -> Span {
382 self.span
383 }
384}
385
386const FIELD: &str = "certificateList";
387const TBS: &str = "certificateList.tbsCertList";
388const ALGORITHM: &str = "certificateList.signatureAlgorithm";
389const SIGNATURE: &str = "certificateList.signature";
390const ISSUER: &str = "certificateList.tbsCertList.issuer";
391const THIS_UPDATE: &str = "certificateList.tbsCertList.thisUpdate";
392const NEXT_UPDATE: &str = "certificateList.tbsCertList.nextUpdate";
393const ENTRIES: &str = "certificateList.tbsCertList.revokedCertificates";
394const EXTENSIONS: &str = "certificateList.tbsCertList.crlExtensions";
395
396fn required<'a>(reader: &mut Reader<'a>, field: &'static str, at: u64) -> Result<Element<'a>> {
397 reader
398 .next_element()
399 .field(field)?
400 .ok_or_else(|| Error::new(ErrorCode::MissingField, field, at))
401}
402
403fn end(reader: &structured_asn1::ScopedReader<'_, '_>, field: &'static str, at: u64) -> Result<()> {
404 if reader.is_empty() {
405 return Ok(());
406 }
407 Err(Error::new(ErrorCode::TrailingData, field, at))
408}
409
410fn is_time(element: &Element<'_>) -> bool {
411 element.tag() == Tag::primitive(universal::UTC_TIME)
412 || element.tag() == Tag::primitive(universal::GENERALIZED_TIME)
413}
414
415fn read_tbs<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<TbsCertList<'a>> {
416 if element.tag() != Tag::constructed(universal::SEQUENCE) {
417 return Err(Error::new(
418 ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
419 TBS,
420 element.span().start,
421 ));
422 }
423 let mut inside = parent.enter(element).field(TBS)?;
424 let mut next = required(&mut inside, TBS, element.span().start)?;
425 let version = if next.tag() == Tag::primitive(universal::INTEGER) {
426 inside.charge(9).field(TBS)?;
429 if inside.integer(&next).field(TBS)?.as_u64() != Some(1) {
430 return Err(Error::new(
431 ErrorCode::UnsupportedVersion,
432 TBS,
433 next.span().start,
434 ));
435 }
436 next = required(&mut inside, TBS, element.span().start)?;
437 Version::V2
438 } else {
439 Version::V1
440 };
441 let signature = algorithm::read(&inside, &next, TBS)?;
442 let issuer_element = required(&mut inside, ISSUER, element.span().start)?;
443 let issuer = name::read(&inside, &issuer_element, ISSUER)?;
444 if issuer.is_empty() {
446 return Err(Error::new(
447 ErrorCode::EmptySequence,
448 ISSUER,
449 issuer_element.span().start,
450 ));
451 }
452 let this = required(&mut inside, THIS_UPDATE, element.span().start)?;
453 let this_update = time::read_in(&inside, &this, THIS_UPDATE)?;
454 let mut next = inside.next_element().field(TBS)?;
455 let next_update = match next {
456 Some(value) if is_time(&value) => {
457 let time = time::read_in(&inside, &value, NEXT_UPDATE)?;
458 next = inside.next_element().field(TBS)?;
459 Some(time)
460 }
461 _ => None,
462 };
463 let work = parent.execution();
464 let mut revoked = work.vector();
465 if let Some(sequence) =
466 next.filter(|value| value.tag() == Tag::constructed(universal::SEQUENCE))
467 {
468 let mut entries = inside.enter(&sequence).field(ENTRIES)?;
469 while let Some(entry) = entries.next_element().field(ENTRIES)? {
470 let value = read_entry(&entries, &entry, version)?;
471 revoked
472 .try_push(value)
473 .map_err(|reason| Error::resource(reason, ENTRIES, entry.span().start))?;
474 }
475 if revoked.is_empty() {
477 return Err(Error::new(
478 ErrorCode::EmptySequence,
479 ENTRIES,
480 sequence.span().start,
481 ));
482 }
483 next = inside.next_element().field(TBS)?;
484 }
485 let mut extensions = Extensions::empty(inside.memory());
486 if let Some(tagged) = next {
487 if tagged.tag() != Tag::context(true, 0) || version != Version::V2 {
488 return Err(Error::new(
489 ErrorCode::UnexpectedField,
490 EXTENSIONS,
491 tagged.span().start,
492 ));
493 }
494 let mut wrapper = inside.enter(&tagged).field(EXTENSIONS)?;
495 let sequence = required(&mut wrapper, EXTENSIONS, tagged.span().start)?;
496 extensions = extension::read(&wrapper, &sequence, EXTENSIONS)?;
497 end(&wrapper, EXTENSIONS, tagged.span().start)?;
498 }
499 end(&inside, TBS, element.span().start)?;
500 Ok(TbsCertList {
501 version,
502 signature,
503 issuer,
504 this_update,
505 next_update,
506 revoked: revoked.into_owned(),
507 extensions,
508 bytes: element.as_bytes(),
509 span: element.span(),
510 })
511}
512
513fn read_entry<'a>(
514 parent: &Reader<'a>,
515 element: &Element<'a>,
516 version: Version,
517) -> Result<RevokedCertificate<'a>> {
518 if element.tag() != Tag::constructed(universal::SEQUENCE) {
519 return Err(Error::new(
520 ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
521 ENTRIES,
522 element.span().start,
523 ));
524 }
525 let mut inside = parent.enter(element).field(ENTRIES)?;
526 let serial = inside.read_integer().field(ENTRIES)?;
527 let date = required(&mut inside, ENTRIES, element.span().start)?;
528 let revocation_date = time::read_in(&inside, &date, ENTRIES)?;
529 let extensions = match inside.next_element().field(ENTRIES)? {
530 Some(value) => {
531 if version != Version::V2 {
533 return Err(Error::new(
534 ErrorCode::UnexpectedField,
535 ENTRIES,
536 value.span().start,
537 ));
538 }
539 extension::read(&inside, &value, ENTRIES)?
540 }
541 None => Extensions::empty(inside.memory()),
542 };
543 end(&inside, ENTRIES, element.span().start)?;
544 Ok(RevokedCertificate {
545 serial,
546 revocation_date,
547 revocation_date_offset: date.span().start,
548 extensions,
549 span: element.span(),
550 })
551}