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 #[must_use]
234 pub fn execution_in<'operation, W: Work>(
235 &self,
236 work: &'operation W,
237 ) -> structured_asn1::memory::Execution<'operation>
238 where
239 'a: 'operation,
240 {
241 self.signature_algorithm.query_in(work)
242 }
243
244 pub fn authenticate<'r, V: Verify<E>, E: Work>(
253 &'r self,
254 issuer: &'r crate::Certificate<'a>,
255 key: WorkingKey<'a>,
256 verifier: &V,
257 execution: &E,
258 ) -> crate::error::CallbackResult<Authentication<'r, 'a>, V::Error> {
259 use crate::error::CallbackError;
260 let encoded_key = key.key().as_bytes();
261 let issuer_key = issuer.tbs().public_key().as_bytes();
262 let work = (encoded_key.len().max(issuer_key.len()) as u64)
263 .checked_mul(2)
264 .and_then(|n| n.checked_add(1))
265 .ok_or_else(|| {
266 Error::resource(
267 structured_asn1::memory::MemoryError::WorkExceeded,
268 FIELD,
269 self.span.start,
270 )
271 })?;
272 execution
273 .charge_work(work)
274 .map_err(|reason| Error::resource(reason, FIELD, self.span.start))?;
275 if encoded_key != issuer_key {
276 return Ok(Authentication::Rejected(AuthenticationFailure::KeyBinding));
277 }
278 if !self.tbs.issuer.matches(issuer.tbs().subject(), execution)? {
279 return Ok(Authentication::Rejected(AuthenticationFailure::IssuerName));
280 }
281 let usage = issuer.tbs().extensions().key_usage(execution)?;
282 if usage.is_some_and(|usage| !usage.crl_sign())
287 || (usage.is_none() && issuer.tbs().version() == crate::Version::V3)
288 {
289 return Ok(Authentication::Rejected(AuthenticationFailure::KeyUsage));
290 }
291 match verifier
292 .verify(
293 &self.tbs.signature,
294 key,
295 self.signed_bytes(),
296 self.signature,
297 execution,
298 )
299 .map_err(CallbackError::Callback)?
300 {
301 Verified::Yes => Ok(Authentication::Authenticated(Authenticated {
302 crl: self,
303 issuer,
304 key,
305 })),
306 Verified::No => Ok(Authentication::Rejected(AuthenticationFailure::Signature)),
307 Verified::Unsupported => Ok(Authentication::Unsupported),
308 }
309 }
310
311 pub fn read(parser: &'a Parser, bytes: &'a [u8], base: u64) -> Result<Self> {
313 let mut reader = parser.read(bytes, base).field(FIELD)?;
314 let element = required(&mut reader, FIELD, base)?;
315 let crl = Self::read_element(&reader, &element)?;
316 if !reader.is_empty() {
317 return Err(Error::new(
318 ErrorCode::TrailingData,
319 FIELD,
320 element.span().end(),
321 ));
322 }
323 Ok(crl)
324 }
325
326 pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
329 let mut outer = parent
332 .reread(element, structured_asn1::Encoding::Der)
333 .field(FIELD)?;
334 let root = outer
335 .expect(Tag::constructed(universal::SEQUENCE))
336 .field(FIELD)?;
337 let mut inside = outer.enter(&root).field(FIELD)?;
338 let tbs_element = required(&mut inside, TBS, root.span().start)?;
339 let tbs = read_tbs(&inside, &tbs_element)?;
340 let algorithm_element = required(&mut inside, ALGORITHM, root.span().start)?;
341 let signature_algorithm = algorithm::read(&inside, &algorithm_element, ALGORITHM)?;
342 let signature = crate::signature::SignatureValue::read(&mut inside, SIGNATURE)?;
343 end(&inside, FIELD, root.span().start)?;
344 if !signature_algorithm.matches_in(&tbs.signature, &inside)? {
347 return Err(Error::new(
348 ErrorCode::AlgorithmMismatch,
349 ALGORITHM,
350 algorithm_element.span().start,
351 ));
352 }
353 Ok(Self {
354 tbs,
355 signature_algorithm,
356 signature,
357 bytes: root.as_bytes(),
358 span: root.span(),
359 })
360 }
361
362 #[must_use]
364 pub fn tbs(&self) -> &TbsCertList<'a> {
365 &self.tbs
366 }
367 #[must_use]
369 pub fn signature_algorithm(&self) -> AlgorithmIdentifier<'a> {
370 self.signature_algorithm
371 }
372 #[must_use]
374 pub fn signature(&self) -> BitString<'a> {
375 self.signature.bit_string()
376 }
377 #[must_use]
379 pub fn signature_value(&self) -> crate::signature::SignatureValue<'a> {
380 self.signature
381 }
382 #[must_use]
384 pub fn signed_bytes(&self) -> &'a [u8] {
385 self.tbs.bytes
386 }
387 #[must_use]
389 pub fn as_bytes(&self) -> &'a [u8] {
390 self.bytes
391 }
392 #[must_use]
394 pub fn span(&self) -> Span {
395 self.span
396 }
397}
398
399const FIELD: &str = "certificateList";
400const TBS: &str = "certificateList.tbsCertList";
401const ALGORITHM: &str = "certificateList.signatureAlgorithm";
402const SIGNATURE: &str = "certificateList.signature";
403const ISSUER: &str = "certificateList.tbsCertList.issuer";
404const THIS_UPDATE: &str = "certificateList.tbsCertList.thisUpdate";
405const NEXT_UPDATE: &str = "certificateList.tbsCertList.nextUpdate";
406const ENTRIES: &str = "certificateList.tbsCertList.revokedCertificates";
407const EXTENSIONS: &str = "certificateList.tbsCertList.crlExtensions";
408
409fn required<'a>(reader: &mut Reader<'a>, field: &'static str, at: u64) -> Result<Element<'a>> {
410 reader
411 .next_element()
412 .field(field)?
413 .ok_or_else(|| Error::new(ErrorCode::MissingField, field, at))
414}
415
416fn end(reader: &structured_asn1::ScopedReader<'_, '_>, field: &'static str, at: u64) -> Result<()> {
417 if reader.is_empty() {
418 return Ok(());
419 }
420 Err(Error::new(ErrorCode::TrailingData, field, at))
421}
422
423fn is_time(element: &Element<'_>) -> bool {
424 element.tag() == Tag::primitive(universal::UTC_TIME)
425 || element.tag() == Tag::primitive(universal::GENERALIZED_TIME)
426}
427
428fn read_tbs<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<TbsCertList<'a>> {
429 if element.tag() != Tag::constructed(universal::SEQUENCE) {
430 return Err(Error::new(
431 ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
432 TBS,
433 element.span().start,
434 ));
435 }
436 let mut inside = parent.enter(element).field(TBS)?;
437 let mut next = required(&mut inside, TBS, element.span().start)?;
438 let version = if next.tag() == Tag::primitive(universal::INTEGER) {
439 inside.charge(9).field(TBS)?;
442 if inside.integer(&next).field(TBS)?.as_u64() != Some(1) {
443 return Err(Error::new(
444 ErrorCode::UnsupportedVersion,
445 TBS,
446 next.span().start,
447 ));
448 }
449 next = required(&mut inside, TBS, element.span().start)?;
450 Version::V2
451 } else {
452 Version::V1
453 };
454 let signature = algorithm::read(&inside, &next, TBS)?;
455 let issuer_element = required(&mut inside, ISSUER, element.span().start)?;
456 let issuer = name::read(&inside, &issuer_element, ISSUER)?;
457 if issuer.is_empty() {
459 return Err(Error::new(
460 ErrorCode::EmptySequence,
461 ISSUER,
462 issuer_element.span().start,
463 ));
464 }
465 let this = required(&mut inside, THIS_UPDATE, element.span().start)?;
466 let this_update = time::read_in(&inside, &this, THIS_UPDATE)?;
467 let mut next = inside.next_element().field(TBS)?;
468 let next_update = match next {
469 Some(value) if is_time(&value) => {
470 let time = time::read_in(&inside, &value, NEXT_UPDATE)?;
471 next = inside.next_element().field(TBS)?;
472 Some(time)
473 }
474 _ => None,
475 };
476 let work = parent.execution();
477 let mut revoked = work.vector();
478 if let Some(sequence) =
479 next.filter(|value| value.tag() == Tag::constructed(universal::SEQUENCE))
480 {
481 let mut entries = inside.enter(&sequence).field(ENTRIES)?;
482 while let Some(entry) = entries.next_element().field(ENTRIES)? {
483 let value = read_entry(&entries, &entry, version)?;
484 revoked
485 .try_push(value)
486 .map_err(|reason| Error::resource(reason, ENTRIES, entry.span().start))?;
487 }
488 if revoked.is_empty() {
490 return Err(Error::new(
491 ErrorCode::EmptySequence,
492 ENTRIES,
493 sequence.span().start,
494 ));
495 }
496 next = inside.next_element().field(TBS)?;
497 }
498 let mut extensions = Extensions::empty(inside.memory());
499 if let Some(tagged) = next {
500 if tagged.tag() != Tag::context(true, 0) || version != Version::V2 {
501 return Err(Error::new(
502 ErrorCode::UnexpectedField,
503 EXTENSIONS,
504 tagged.span().start,
505 ));
506 }
507 let mut wrapper = inside.enter(&tagged).field(EXTENSIONS)?;
508 let sequence = required(&mut wrapper, EXTENSIONS, tagged.span().start)?;
509 extensions = extension::read(&wrapper, &sequence, EXTENSIONS)?;
510 end(&wrapper, EXTENSIONS, tagged.span().start)?;
511 }
512 end(&inside, TBS, element.span().start)?;
513 Ok(TbsCertList {
514 version,
515 signature,
516 issuer,
517 this_update,
518 next_update,
519 revoked: revoked.into_owned(),
520 extensions,
521 bytes: element.as_bytes(),
522 span: element.span(),
523 })
524}
525
526fn read_entry<'a>(
527 parent: &Reader<'a>,
528 element: &Element<'a>,
529 version: Version,
530) -> Result<RevokedCertificate<'a>> {
531 if element.tag() != Tag::constructed(universal::SEQUENCE) {
532 return Err(Error::new(
533 ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
534 ENTRIES,
535 element.span().start,
536 ));
537 }
538 let mut inside = parent.enter(element).field(ENTRIES)?;
539 let serial = inside.read_integer().field(ENTRIES)?;
540 let date = required(&mut inside, ENTRIES, element.span().start)?;
541 let revocation_date = time::read_in(&inside, &date, ENTRIES)?;
542 let extensions = match inside.next_element().field(ENTRIES)? {
543 Some(value) => {
544 if version != Version::V2 {
546 return Err(Error::new(
547 ErrorCode::UnexpectedField,
548 ENTRIES,
549 value.span().start,
550 ));
551 }
552 extension::read(&inside, &value, ENTRIES)?
553 }
554 None => Extensions::empty(inside.memory()),
555 };
556 end(&inside, ENTRIES, element.span().start)?;
557 Ok(RevokedCertificate {
558 serial,
559 revocation_date,
560 revocation_date_offset: date.span().start,
561 extensions,
562 span: element.span(),
563 })
564}