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::{Memory, OwnedVec};
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;
29mod uri;
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(
126 &self,
127 now: crate::temporal::Reading,
128 utc: &crate::temporal::LeapTable<'_>,
129 execution: &Memory,
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: BitString<'a>,
226 bytes: &'a [u8],
227 span: Span,
228}
229
230impl<'a> CertificateList<'a> {
231 pub fn authenticate<'r, V: Verify>(
240 &'r self,
241 issuer: &'r crate::Certificate<'a>,
242 key: WorkingKey<'a>,
243 verifier: &V,
244 execution: &Memory,
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 = inside.read_bit_string().field(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
363 }
364 #[must_use]
366 pub fn signed_bytes(&self) -> &'a [u8] {
367 self.tbs.bytes
368 }
369 #[must_use]
371 pub fn as_bytes(&self) -> &'a [u8] {
372 self.bytes
373 }
374 #[must_use]
376 pub fn span(&self) -> Span {
377 self.span
378 }
379}
380
381const FIELD: &str = "certificateList";
382const TBS: &str = "certificateList.tbsCertList";
383const ALGORITHM: &str = "certificateList.signatureAlgorithm";
384const SIGNATURE: &str = "certificateList.signature";
385const ISSUER: &str = "certificateList.tbsCertList.issuer";
386const THIS_UPDATE: &str = "certificateList.tbsCertList.thisUpdate";
387const NEXT_UPDATE: &str = "certificateList.tbsCertList.nextUpdate";
388const ENTRIES: &str = "certificateList.tbsCertList.revokedCertificates";
389const EXTENSIONS: &str = "certificateList.tbsCertList.crlExtensions";
390
391fn required<'a>(reader: &mut Reader<'a>, field: &'static str, at: u64) -> Result<Element<'a>> {
392 reader
393 .next_element()
394 .field(field)?
395 .ok_or_else(|| Error::new(ErrorCode::MissingField, field, at))
396}
397
398fn end(reader: &Reader<'_>, field: &'static str, at: u64) -> Result<()> {
399 if reader.is_empty() {
400 return Ok(());
401 }
402 Err(Error::new(ErrorCode::TrailingData, field, at))
403}
404
405fn is_time(element: &Element<'_>) -> bool {
406 element.tag() == Tag::primitive(universal::UTC_TIME)
407 || element.tag() == Tag::primitive(universal::GENERALIZED_TIME)
408}
409
410fn read_tbs<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<TbsCertList<'a>> {
411 if element.tag() != Tag::constructed(universal::SEQUENCE) {
412 return Err(Error::new(
413 ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
414 TBS,
415 element.span().start,
416 ));
417 }
418 let mut inside = parent.enter(element).field(TBS)?;
419 let mut next = required(&mut inside, TBS, element.span().start)?;
420 let version = if next.tag() == Tag::primitive(universal::INTEGER) {
421 inside.charge(9).field(TBS)?;
424 if inside.integer(&next).field(TBS)?.as_u64() != Some(1) {
425 return Err(Error::new(
426 ErrorCode::UnsupportedVersion,
427 TBS,
428 next.span().start,
429 ));
430 }
431 next = required(&mut inside, TBS, element.span().start)?;
432 Version::V2
433 } else {
434 Version::V1
435 };
436 let signature = algorithm::read(&inside, &next, TBS)?;
437 let issuer_element = required(&mut inside, ISSUER, element.span().start)?;
438 let issuer = name::read(&inside, &issuer_element, ISSUER)?;
439 if issuer.is_empty() {
441 return Err(Error::new(
442 ErrorCode::EmptySequence,
443 ISSUER,
444 issuer_element.span().start,
445 ));
446 }
447 let this = required(&mut inside, THIS_UPDATE, element.span().start)?;
448 let this_update = time::read_in(&inside, &this, THIS_UPDATE)?;
449 let mut next = inside.next_element().field(TBS)?;
450 let next_update = match next {
451 Some(value) if is_time(&value) => {
452 let time = time::read_in(&inside, &value, NEXT_UPDATE)?;
453 next = inside.next_element().field(TBS)?;
454 Some(time)
455 }
456 _ => None,
457 };
458 let mut revoked = inside.memory().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,
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}