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: BitString<'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 = inside.read_bit_string().field(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
362 }
363 #[must_use]
365 pub fn signed_bytes(&self) -> &'a [u8] {
366 self.tbs.bytes
367 }
368 #[must_use]
370 pub fn as_bytes(&self) -> &'a [u8] {
371 self.bytes
372 }
373 #[must_use]
375 pub fn span(&self) -> Span {
376 self.span
377 }
378}
379
380const FIELD: &str = "certificateList";
381const TBS: &str = "certificateList.tbsCertList";
382const ALGORITHM: &str = "certificateList.signatureAlgorithm";
383const SIGNATURE: &str = "certificateList.signature";
384const ISSUER: &str = "certificateList.tbsCertList.issuer";
385const THIS_UPDATE: &str = "certificateList.tbsCertList.thisUpdate";
386const NEXT_UPDATE: &str = "certificateList.tbsCertList.nextUpdate";
387const ENTRIES: &str = "certificateList.tbsCertList.revokedCertificates";
388const EXTENSIONS: &str = "certificateList.tbsCertList.crlExtensions";
389
390fn required<'a>(reader: &mut Reader<'a>, field: &'static str, at: u64) -> Result<Element<'a>> {
391 reader
392 .next_element()
393 .field(field)?
394 .ok_or_else(|| Error::new(ErrorCode::MissingField, field, at))
395}
396
397fn end(reader: &structured_asn1::ScopedReader<'_, '_>, field: &'static str, at: u64) -> Result<()> {
398 if reader.is_empty() {
399 return Ok(());
400 }
401 Err(Error::new(ErrorCode::TrailingData, field, at))
402}
403
404fn is_time(element: &Element<'_>) -> bool {
405 element.tag() == Tag::primitive(universal::UTC_TIME)
406 || element.tag() == Tag::primitive(universal::GENERALIZED_TIME)
407}
408
409fn read_tbs<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<TbsCertList<'a>> {
410 if element.tag() != Tag::constructed(universal::SEQUENCE) {
411 return Err(Error::new(
412 ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
413 TBS,
414 element.span().start,
415 ));
416 }
417 let mut inside = parent.enter(element).field(TBS)?;
418 let mut next = required(&mut inside, TBS, element.span().start)?;
419 let version = if next.tag() == Tag::primitive(universal::INTEGER) {
420 inside.charge(9).field(TBS)?;
423 if inside.integer(&next).field(TBS)?.as_u64() != Some(1) {
424 return Err(Error::new(
425 ErrorCode::UnsupportedVersion,
426 TBS,
427 next.span().start,
428 ));
429 }
430 next = required(&mut inside, TBS, element.span().start)?;
431 Version::V2
432 } else {
433 Version::V1
434 };
435 let signature = algorithm::read(&inside, &next, TBS)?;
436 let issuer_element = required(&mut inside, ISSUER, element.span().start)?;
437 let issuer = name::read(&inside, &issuer_element, ISSUER)?;
438 if issuer.is_empty() {
440 return Err(Error::new(
441 ErrorCode::EmptySequence,
442 ISSUER,
443 issuer_element.span().start,
444 ));
445 }
446 let this = required(&mut inside, THIS_UPDATE, element.span().start)?;
447 let this_update = time::read_in(&inside, &this, THIS_UPDATE)?;
448 let mut next = inside.next_element().field(TBS)?;
449 let next_update = match next {
450 Some(value) if is_time(&value) => {
451 let time = time::read_in(&inside, &value, NEXT_UPDATE)?;
452 next = inside.next_element().field(TBS)?;
453 Some(time)
454 }
455 _ => None,
456 };
457 let work = parent.execution();
458 let mut revoked = work.vector();
459 if let Some(sequence) =
460 next.filter(|value| value.tag() == Tag::constructed(universal::SEQUENCE))
461 {
462 let mut entries = inside.enter(&sequence).field(ENTRIES)?;
463 while let Some(entry) = entries.next_element().field(ENTRIES)? {
464 let value = read_entry(&entries, &entry, version)?;
465 revoked
466 .try_push(value)
467 .map_err(|reason| Error::resource(reason, ENTRIES, entry.span().start))?;
468 }
469 if revoked.is_empty() {
471 return Err(Error::new(
472 ErrorCode::EmptySequence,
473 ENTRIES,
474 sequence.span().start,
475 ));
476 }
477 next = inside.next_element().field(TBS)?;
478 }
479 let mut extensions = Extensions::empty(inside.memory());
480 if let Some(tagged) = next {
481 if tagged.tag() != Tag::context(true, 0) || version != Version::V2 {
482 return Err(Error::new(
483 ErrorCode::UnexpectedField,
484 EXTENSIONS,
485 tagged.span().start,
486 ));
487 }
488 let mut wrapper = inside.enter(&tagged).field(EXTENSIONS)?;
489 let sequence = required(&mut wrapper, EXTENSIONS, tagged.span().start)?;
490 extensions = extension::read(&wrapper, &sequence, EXTENSIONS)?;
491 end(&wrapper, EXTENSIONS, tagged.span().start)?;
492 }
493 end(&inside, TBS, element.span().start)?;
494 Ok(TbsCertList {
495 version,
496 signature,
497 issuer,
498 this_update,
499 next_update,
500 revoked: revoked.into_owned(),
501 extensions,
502 bytes: element.as_bytes(),
503 span: element.span(),
504 })
505}
506
507fn read_entry<'a>(
508 parent: &Reader<'a>,
509 element: &Element<'a>,
510 version: Version,
511) -> Result<RevokedCertificate<'a>> {
512 if element.tag() != Tag::constructed(universal::SEQUENCE) {
513 return Err(Error::new(
514 ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
515 ENTRIES,
516 element.span().start,
517 ));
518 }
519 let mut inside = parent.enter(element).field(ENTRIES)?;
520 let serial = inside.read_integer().field(ENTRIES)?;
521 let date = required(&mut inside, ENTRIES, element.span().start)?;
522 let revocation_date = time::read_in(&inside, &date, ENTRIES)?;
523 let extensions = match inside.next_element().field(ENTRIES)? {
524 Some(value) => {
525 if version != Version::V2 {
527 return Err(Error::new(
528 ErrorCode::UnexpectedField,
529 ENTRIES,
530 value.span().start,
531 ));
532 }
533 extension::read(&inside, &value, ENTRIES)?
534 }
535 None => Extensions::empty(inside.memory()),
536 };
537 end(&inside, ENTRIES, element.span().start)?;
538 Ok(RevokedCertificate {
539 serial,
540 revocation_date,
541 revocation_date_offset: date.span().start,
542 extensions,
543 span: element.span(),
544 })
545}