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