structured_pkix/extension.rs
1//! The extensions a certificate carries, kept whether or not they are
2//! understood.
3//!
4//! An extension marked critical says that a relying party which does not
5//! understand it must not use the certificate. That is a decision about a
6//! verdict, not about whether the bytes can be read, so an unknown critical
7//! extension is reported here rather than refused: the product has to be able
8//! to say what it found and why it stopped, and a parser that refused would
9//! leave nothing to say it with.
10//!
11//! Which identifiers count as understood is not fixed by this crate alone. A
12//! scheme knows extensions of its own, and says so by implementing
13//! [`Recognizer`]. What it supplies is a set of identifiers, never code and
14//! never a place to fetch anything from.
15
16use crate::access::{DistributionPoints, InfoAccess};
17use crate::constraints::{BasicConstraints, InhibitAnyPolicy, NameConstraints, PolicyConstraints};
18use crate::error::{CallbackError, CallbackResult, Error, ErrorCode, Located, Result, gate};
19use crate::general_name::{self, GeneralName};
20use crate::identifier::{AuthorityKeyIdentifier, SubjectKeyIdentifier};
21use crate::oid;
22use crate::policy::{CertificatePolicies, PolicyMappings};
23use crate::qualified::QcStatements;
24use crate::usage::{ExtendedKeyUsage, KeyUsage};
25use structured_asn1::memory::{Memory, MemoryError, OwnedVec, Work};
26use structured_asn1::{Element, Oid, Parser, Reader, ScopedReader, Span, Tag, universal};
27
28mod entry;
29pub use entry::{
30 ExtensionFields, ExtensionHeader, ExtensionValue, ScopedExtensionFields, open, read_with,
31};
32
33/// One extension: what it is, whether it must be understood, and its value.
34#[derive(Debug, Clone, Copy)]
35pub struct Extension<'a> {
36 kind: Oid<'a>,
37 critical: bool,
38 value: &'a [u8],
39 value_span: Span,
40 span: Span,
41 /// The parser the certificate was read with, kept so every later decode
42 /// of this value is charged to that one budget: a signature accepting an
43 /// unrelated parser would let repeated decodes reset the counters and
44 /// cost many times the caller's declared limit.
45 parser: &'a Parser,
46 /// Depth of the reader that produced extnValue; lazy decoding must not
47 /// reset the certificate's aggregate depth allowance.
48 outer: u32,
49}
50
51impl<'a> Extension<'a> {
52 /// Which extension this is.
53 #[must_use]
54 pub fn kind(self) -> Oid<'a> {
55 self.kind
56 }
57
58 /// Whether a relying party that does not understand this extension must
59 /// refuse the certificate.
60 #[must_use]
61 pub fn is_critical(self) -> bool {
62 self.critical
63 }
64
65 /// The value, still encoded: the contents of the octet string the
66 /// extension wraps it in, which is a structure of its own.
67 #[must_use]
68 pub fn value(self) -> &'a [u8] {
69 self.value
70 }
71
72 /// Where the extension sits in the document.
73 #[must_use]
74 pub fn span(self) -> Span {
75 self.span
76 }
77
78 /// A reader over the value using the current execution domain and the
79 /// original parser session's cumulative ceilings, offsets and depth.
80 ///
81 /// How a scheme reads an extension of its own. Sharing the budget is what
82 /// keeps a certificate carrying a hundred extensions from costing a
83 /// hundred times what the caller allowed, and the offsets a reader made
84 /// this way reports are offsets in the whole document. The wrapped value
85 /// sits below extnValue and retains the certificate's depth allowance.
86 pub fn reader<W: Work + 'a>(self, execution: &W) -> structured_asn1::Result<Reader<'a>> {
87 // Always DER: the value lives inside the certificate, which RFC 5280
88 // section 4.1 defines in DER, whatever encoding the envelope was
89 // read in. A caller that read a BER envelope must not have its
90 // leniency reach into the certificate's own structures.
91 execution.read_nested(
92 self.parser,
93 self.value,
94 self.value_span.start,
95 structured_asn1::Encoding::Der,
96 self.outer,
97 )
98 }
99
100 /// Opens original payload bytes under a shorter current operation. Parsed
101 /// input views keep their source lifetime, while only the cursor/scratch
102 /// borrows this execution. Depth, source and query admission are unchanged.
103 pub fn reader_scoped<'operation, W: Work>(
104 self,
105 execution: &'operation W,
106 ) -> structured_asn1::Result<ScopedReader<'a, 'operation>>
107 where
108 'a: 'operation,
109 {
110 execution.read_scoped_nested(
111 self.parser,
112 self.value,
113 self.value_span.start,
114 structured_asn1::Encoding::Der,
115 self.outer,
116 )
117 }
118
119 /// Original DER value under both origin and current query ceilings.
120 ///
121 /// The query may come from another source. Original parser identity,
122 /// offsets and inherited depth are preserved from creation; allocation,
123 /// traversal and scratch also obey the current operation's local budget
124 /// and aggregate account. Previously retained storage is not transferred.
125 pub fn reader_in<'work>(self, query: &Reader<'work>) -> structured_asn1::Result<Reader<'work>>
126 where
127 'a: 'work,
128 {
129 self.parser.read_nested_query_in(
130 query,
131 self.value,
132 self.value_span.start,
133 structured_asn1::Encoding::Der,
134 self.outer,
135 )
136 }
137
138 /// The parser the certificate was read with, whose budget every decode
139 /// of this extension shares.
140 #[must_use]
141 pub fn parser(self) -> &'a Parser {
142 self.parser
143 }
144}
145
146/// The extensions of one certificate, in the order it holds them.
147#[derive(Debug)]
148pub struct Extensions<'a> {
149 items: OwnedVec<Extension<'a>>,
150}
151
152impl<'a> Extensions<'a> {
153 /// Account retaining this collection's storage. Deferred decoding may
154 /// explicitly use a different current execution domain.
155 #[must_use]
156 pub fn memory(&self) -> &Memory {
157 self.items.memory()
158 }
159
160 pub(crate) fn empty(execution: &Memory) -> Self {
161 Self {
162 items: execution.vector(),
163 }
164 }
165 /// Every extension in order, funded by this query's current execution.
166 /// The constructor allocates/clones nothing. Each metadata step is paid
167 /// before advancing; a resource failure is yielded once, then traversal
168 /// stops. Empty/exhausted catalogues perform no additional charged work.
169 /// Recognition and payload parsing must fund their own data-dependent work.
170 pub fn iter<'r, 'e, W: Work + 'e>(
171 &'r self,
172 execution: &'e W,
173 ) -> impl Iterator<Item = Result<&'r Extension<'a>>> + 'e
174 where
175 'r: 'e,
176 {
177 let mut entries = self.items.iter();
178 let mut failed = false;
179 core::iter::from_fn(move || {
180 if failed || entries.as_slice().is_empty() {
181 return None;
182 }
183 if let Err(reason) = execution.charge_work(1) {
184 failed = true;
185 // Source metadata for the refusal; the traversal has not
186 // advanced or exposed this item as a successful reading.
187 let at = entries.as_slice()[0].span.start;
188 return Some(Err(Error::resource(reason, "extensions", at)));
189 }
190 entries.next().map(Ok)
191 })
192 }
193
194 /// How many there are.
195 #[must_use]
196 pub fn len(&self) -> usize {
197 self.items.len()
198 }
199
200 /// Whether there are none.
201 #[must_use]
202 pub fn is_empty(&self) -> bool {
203 self.items.is_empty()
204 }
205
206 /// One extension by identifier. There is at most one of each: a
207 /// certificate carrying two copies is refused when it is read, because
208 /// which of them applies would have no answer.
209 pub fn get<W: Work>(&self, kind: Oid<'_>, execution: &W) -> Result<Option<&Extension<'a>>> {
210 for item in &self.items {
211 let work = item.kind.as_bytes().len().max(kind.as_bytes().len()) as u64;
212 execution
213 .charge_work(1 + work)
214 .map_err(|reason| Error::resource(reason, "extensions", item.span.start))?;
215 if item.kind == kind {
216 return Ok(Some(item));
217 }
218 }
219 Ok(None)
220 }
221
222 /// The critical extensions this run did not understand: the ones nobody
223 /// knows, and the ones this crate knows by identifier but whose values do
224 /// not parse.
225 ///
226 /// A non-empty answer is what blocks a verdict. Knowing the identifier is
227 /// not understanding the extension: a critical key usage whose value
228 /// never parsed was never understood, and filtering it out by identifier
229 /// alone would leave a validator seeing no blocker for a demand the
230 /// certificate marked as one. Extensions a `recognizer` claims are that
231 /// scheme's to decode and are taken at its word.
232 ///
233 /// The answer is returned rather than acted on, because what to do about
234 /// it belongs to the policy layer and the report has to name them. An
235 /// error is a spent budget and only that: it says this run gave up before
236 /// the question was answered, which must not be reported as a demand
237 /// nobody understood.
238 pub fn unhandled_critical<'r, E, W: Work>(
239 &'r self,
240 recognizer: &impl Recognizer<W, Error = E>,
241 execution: &W,
242 ) -> CallbackResult<OwnedVec<&'r Extension<'a>>, E> {
243 let mut unhandled = execution.vector();
244 for item in self.criticals(execution) {
245 let item = item?;
246 if !self.understands(item, recognizer, execution)? {
247 unhandled
248 .try_push(item)
249 .map_err(|reason| Error::resource(reason, "extensions", item.span().start))?;
250 }
251 }
252 Ok(unhandled.into_owned())
253 }
254
255 /// The critical extensions, in the order the certificate wrote them and
256 /// without reading any of their values.
257 ///
258 /// Separate from [`Self::understands`] because working out whether one
259 /// was understood decodes its value, and how much that value holds is a
260 /// document's to decide. A caller holding a budget charges for an entry
261 /// and then asks: the two joined into one step would decode before the
262 /// charge could refuse it, since asking for the next entry is what would
263 /// do the decoding.
264 /// Each metadata entry is admitted before testing its critical flag,
265 /// including skipped entries and a complete miss. A resource error is
266 /// yielded once, then iteration permanently ends without further charges.
267 ///
268 /// # Examples
269 /// ```no_run
270 /// use structured_asn1::memory::Memory;
271 /// use structured_pkix::{Certificate, Result};
272 /// fn has_critical(certificate: &Certificate<'_>, execution: &Memory) -> Result<bool> {
273 /// match certificate.tbs().extensions().criticals(execution).next() {
274 /// Some(item) => { item?; Ok(true) }
275 /// None => Ok(false),
276 /// }
277 /// }
278 /// ```
279 pub fn criticals<'r, 'e, W: Work + 'e>(
280 &'r self,
281 execution: &'e W,
282 ) -> impl Iterator<Item = Result<&'r Extension<'a>>> + 'e
283 where
284 'r: 'e,
285 {
286 let mut entries = self.iter(execution);
287 core::iter::from_fn(move || {
288 for item in entries.by_ref() {
289 let item = match item {
290 Ok(item) => item,
291 Err(error) => return Some(Err(error)),
292 };
293 if item.critical {
294 return Some(Ok(item));
295 }
296 }
297 None
298 })
299 }
300
301 /// Whether this run understood one extension: this crate decodes it, or
302 /// a scheme claims it and it holds one complete value.
303 ///
304 /// Knowing the identifier is not understanding the extension: a critical
305 /// key usage whose value never parsed was never understood, and taking
306 /// it by identifier alone would leave a validator seeing no blocker for
307 /// a demand the certificate marked as one.
308 pub fn understands<E, W: Work>(
309 &self,
310 item: &Extension<'a>,
311 recognizer: &impl Recognizer<W, Error = E>,
312 execution: &W,
313 ) -> CallbackResult<bool, E> {
314 let work = (item.kind.as_bytes().len() as u64)
315 .checked_mul(64)
316 .ok_or_else(|| {
317 Error::resource(MemoryError::WorkExceeded, "extensions", item.span.start)
318 })?;
319 execution
320 .charge_work(work)
321 .map_err(|reason| Error::resource(reason, "extensions", item.span.start))?;
322 if is_known(item.kind) {
323 return Self::decodes(item, recognizer, execution);
324 }
325 Ok(recognizer
326 .recognizes(item.kind, execution)
327 .map_err(CallbackError::Callback)?
328 && Self::holds_one_value(item, execution)?)
329 }
330
331 /// Whether the value of an extension this crate does not decode is one
332 /// complete DER value, all the way down.
333 ///
334 /// A scheme says which identifiers are its to decode. It never sees the
335 /// bytes, so its claim cannot be a statement about them, and "the
336 /// corresponding ASN.1 DER encoded structure is the value of the octet
337 /// string extnValue" (RFC 5280 4.1.2.9) is the one thing that can be
338 /// asked here: one structure, nothing after it, and every element under
339 /// it written the way the encoding writes it. Without this a critical
340 /// demand carrying bytes that are a value of no type would clear the
341 /// gate on an identifier alone.
342 fn holds_one_value<W: Work>(item: &Extension<'a>, execution: &W) -> Result<bool> {
343 const FIELD: &str = "extensions";
344 let read = || -> Result<()> {
345 let at = |code| Error::new(code, FIELD, item.value_span.start);
346 let mut reader = item.reader_scoped(execution).field(FIELD)?;
347 let element = reader
348 .next_element()
349 .field(FIELD)?
350 .ok_or_else(|| at(ErrorCode::MissingField))?;
351 crate::name::walk_der(&reader, &element, FIELD, crate::name::Strings::Checked)?;
352 if reader.is_empty() {
353 Ok(())
354 } else {
355 Err(at(ErrorCode::TrailingData))
356 }
357 };
358 Ok(gate(read())?.is_some())
359 }
360
361 /// Whether a known extension's value actually parses. An error is a spent
362 /// budget, never a malformed value.
363 fn decodes<E, W: Work>(
364 item: &Extension<'a>,
365 recognizer: &impl Recognizer<W, Error = E>,
366 execution: &W,
367 ) -> CallbackResult<bool, E> {
368 let kind = item.kind;
369 Ok(if kind == oid::BASIC_CONSTRAINTS {
370 gate(BasicConstraints::read(item, execution))?.is_some()
371 } else if kind == oid::KEY_USAGE {
372 gate(KeyUsage::read(item, execution))?.is_some()
373 } else if kind == oid::EXT_KEY_USAGE {
374 gate(ExtendedKeyUsage::read(item, execution))?.is_some()
375 } else if kind == oid::SUBJECT_ALT_NAME || kind == oid::ISSUER_ALT_NAME {
376 // The names read for the report either way; understanding also
377 // asks that every other-name type be one somebody claims.
378 match gate(general_name::read_alternative(item, execution))? {
379 Some(names) => all(names.iter(), item, execution, |name| {
380 other_name_known(name, recognizer, execution)
381 })?,
382 None => false,
383 }
384 } else if kind == oid::SUBJECT_KEY_IDENTIFIER {
385 gate(SubjectKeyIdentifier::read(item, execution))?.is_some()
386 } else if kind == oid::AUTHORITY_KEY_IDENTIFIER {
387 // The issuer names inside are the identity the extension points
388 // at, so they answer the same other-name question.
389 match gate(AuthorityKeyIdentifier::read(item, execution))? {
390 Some(identifier) => all(identifier.issuer().iter(), item, execution, |name| {
391 other_name_known(name, recognizer, execution)
392 })?,
393 None => false,
394 }
395 } else if kind == oid::NAME_CONSTRAINTS {
396 match gate(NameConstraints::read(item, execution))? {
397 Some(constraints) => all(
398 constraints.permitted().iter().chain(constraints.excluded()),
399 item,
400 execution,
401 |subtree| {
402 // A constraint is understood only where a
403 // certificate's names can be matched against it. The
404 // X.400 and EDI forms are kept as opaque encoded
405 // bytes, and a registered identifier has no defined
406 // constraint-matching rule either, so a critical
407 // constraint built on any of them was not understood
408 // even though its structure parsed.
409 //
410 // An other-name is the same question asked of a
411 // scheme, and it is the constraint question and not
412 // the reading one: knowing what a name of that type
413 // says is not knowing which names sit inside a
414 // subtree of it.
415 Ok(match subtree.base() {
416 GeneralName::X400(_)
417 | GeneralName::EdiParty(_)
418 | GeneralName::RegisteredId(_) => false,
419 GeneralName::Other { type_id, .. } => recognizer
420 .recognizes_name_constraint(*type_id, execution)
421 .map_err(CallbackError::Callback)?,
422 _ => true,
423 })
424 },
425 )?,
426 None => false,
427 }
428 } else if kind == oid::CERTIFICATE_POLICIES {
429 // The list parsing keeps qualifiers encoded; understanding a
430 // critical policy extension includes interpreting them.
431 match gate(CertificatePolicies::read(item, execution))? {
432 Some(policies) => policies.understood(item.parser, execution)?,
433 None => false,
434 }
435 } else if kind == oid::POLICY_MAPPINGS {
436 gate(PolicyMappings::read(item, execution))?.is_some()
437 } else if kind == oid::POLICY_CONSTRAINTS {
438 gate(PolicyConstraints::read(item, execution))?.is_some()
439 } else if kind == oid::INHIBIT_ANY_POLICY {
440 gate(InhibitAnyPolicy::read(item, execution))?.is_some()
441 } else if kind == oid::AUTHORITY_INFO_ACCESS || kind == oid::SUBJECT_INFO_ACCESS {
442 // A description's meaning is its method identifier, and a known
443 // method does not vouch for its location: an other-name there
444 // whose type nobody claims is a location this run never
445 // interpreted, and a form outside the ones the method names is
446 // an endpoint it cannot use. Either way the accessor still
447 // reports it.
448 match gate(InfoAccess::read(item, execution))? {
449 Some(access) => all(
450 access.descriptions().iter(),
451 item,
452 execution,
453 |description| {
454 let method = description.method();
455 // Each extension defines its own methods: OCSP and the
456 // issuing certificates on the authority side (RFC 5280
457 // 4.2.2.1), the repository and the time-stamping service
458 // on the subject side (RFC 5280 4.2.2.2). A method
459 // carried by the other extension has no defined meaning
460 // there and was not understood.
461 let named = if kind == oid::AUTHORITY_INFO_ACCESS {
462 [oid::OCSP, oid::CA_ISSUERS].contains(&method)
463 } else {
464 [oid::TIME_STAMPING_ACCESS, oid::CA_REPOSITORY].contains(&method)
465 };
466 Ok((named
467 || recognizer
468 .recognizes_access_method(method, execution)
469 .map_err(CallbackError::Callback)?)
470 && other_name_known(description.location(), recognizer, execution)?
471 && (!named || method_location_fits(method, description.location())))
472 },
473 )?,
474 None => false,
475 }
476 } else if kind == oid::CRL_DISTRIBUTION_POINTS || kind == oid::FRESHEST_CRL {
477 // A point's names say where the revocation evidence is, and the
478 // issuer names who signs it: both answer the other-name question.
479 match gate(DistributionPoints::read(item, execution))? {
480 Some(points) => all(points.points().iter(), item, execution, |point| {
481 all(
482 point.full_name().iter().chain(point.issuer()),
483 item,
484 execution,
485 |name| other_name_known(name, recognizer, execution),
486 )
487 })?,
488 None => false,
489 }
490 } else if kind == oid::OCSP_NO_CHECK {
491 gate(crate::ocsp::read_no_check(item, execution))?.is_some()
492 } else if kind == oid::QC_STATEMENTS {
493 // The outer list parsing is not understanding: the statement
494 // payloads decode lazily, and a critical list whose statement
495 // carries garbage, or whose identifier nobody here knows, is a
496 // critical demand this run never understood, one level down from
497 // an unknown extension.
498 match gate(QcStatements::read(item, execution))? {
499 Some(statements) => statements.understood(recognizer, execution)?,
500 None => false,
501 }
502 } else {
503 // is_known and this list name the same identifiers; a mismatch is
504 // a bug, and claiming the value parsed would hide it.
505 false
506 })
507 }
508}
509
510/// Generates one typed accessor per extension: absent when the list does not
511/// carry the identifier, otherwise whatever the reader makes of the value.
512/// The table is the single place an accessor name, its identifier and its
513/// reader meet, so the three cannot drift apart.
514macro_rules! typed_accessors {
515 ($($(#[$doc:meta])* $name:ident, $oid:path => $reader:path, $result:ty;)+) => {
516 $(
517 $(#[$doc])*
518 pub fn $name<W: Work>(&self, execution: &W) -> Result<Option<$result>> {
519 match self.get($oid, execution)? {
520 Some(item) => $reader(item, execution).map(Some),
521 None => Ok(None),
522 }
523 }
524 )+
525 };
526}
527
528/// The extensions this crate reads into structures of their own.
529///
530/// Each is read when it is asked for rather than when the certificate is,
531/// because an extension that cannot be read is not a certificate that cannot
532/// be read. Lookup and decoding use the caller's current execution domain;
533/// the original parser's cumulative local ceilings still apply.
534impl<'a> Extensions<'a> {
535 /// Reads one original Extensions SEQUENCE with the certificate catalogue
536 /// invariants: nonempty, no duplicate OIDs, primitive extnValue, and the
537 /// producing encoding's DEFAULT rules. This does not recognize/trust values.
538 pub fn read_element(
539 parent: &ScopedReader<'a, '_>,
540 element: &Element<'a>,
541 field: &'static str,
542 ) -> Result<Self> {
543 read(parent, element, field)
544 }
545
546 /// Reads `[number] IMPLICIT Extensions` without changing original bytes.
547 /// The number is selected by the enclosing schema (RFC3161 §§2.4.1–2.4.2).
548 /// This strict catalogue is suitable for requests, not `TSTInfo` inspection
549 /// recovery; use [`read_with`] there before deciding duplicate/fault policy.
550 /// Original source/depth and producing local/current aggregate work survive.
551 /// <https://www.rfc-editor.org/rfc/rfc3161#section-2.4.1>
552 pub fn read_implicit(
553 parent: &ScopedReader<'a, '_>,
554 element: &Element<'a>,
555 number: u32,
556 field: &'static str,
557 ) -> Result<Self> {
558 read_tagged(parent, element, Tag::context(true, number), field)
559 }
560
561 typed_accessors! {
562 /// Whether this is a certification authority, and how deep a path
563 /// below it may go.
564 basic_constraints, oid::BASIC_CONSTRAINTS => BasicConstraints::read, BasicConstraints;
565 /// What the key may be used for.
566 key_usage, oid::KEY_USAGE => KeyUsage::read, KeyUsage<'a>;
567 /// The further purposes the key is named for.
568 extended_key_usage, oid::EXT_KEY_USAGE => ExtendedKeyUsage::read, ExtendedKeyUsage<'a>;
569 /// The further names for the subject.
570 subject_alt_name, oid::SUBJECT_ALT_NAME => general_name::read_alternative, OwnedVec<GeneralName<'a>>;
571 /// The further names for the issuer.
572 issuer_alt_name, oid::ISSUER_ALT_NAME => general_name::read_alternative, OwnedVec<GeneralName<'a>>;
573 /// The identifier for the key this certificate carries.
574 subject_key_identifier, oid::SUBJECT_KEY_IDENTIFIER => SubjectKeyIdentifier::read, SubjectKeyIdentifier<'a>;
575 /// The identifier for the key that signed it.
576 authority_key_identifier, oid::AUTHORITY_KEY_IDENTIFIER => AuthorityKeyIdentifier::read, AuthorityKeyIdentifier<'a>;
577 /// The name space this authority may certify within.
578 name_constraints, oid::NAME_CONSTRAINTS => NameConstraints::read, NameConstraints<'a>;
579 /// The policies the certificate was issued under.
580 certificate_policies, oid::CERTIFICATE_POLICIES => CertificatePolicies::read, CertificatePolicies<'a>;
581 /// The policies of one domain treated as equivalent to another's.
582 policy_mappings, oid::POLICY_MAPPINGS => PolicyMappings::read, PolicyMappings<'a>;
583 /// The limits on policy processing below this certificate.
584 policy_constraints, oid::POLICY_CONSTRAINTS => PolicyConstraints::read, PolicyConstraints;
585 /// After how many certificates the identifier standing for any policy
586 /// stops being accepted.
587 inhibit_any_policy, oid::INHIBIT_ANY_POLICY => InhibitAnyPolicy::read, InhibitAnyPolicy;
588 /// Where the issuer's certificate and status service are published.
589 authority_info_access, oid::AUTHORITY_INFO_ACCESS => InfoAccess::read, InfoAccess<'a>;
590 /// Where services belonging to the subject are published.
591 subject_info_access, oid::SUBJECT_INFO_ACCESS => InfoAccess::read, InfoAccess<'a>;
592 /// Where revocation lists covering this certificate are published.
593 crl_distribution_points, oid::CRL_DISTRIBUTION_POINTS => DistributionPoints::read, DistributionPoints<'a>;
594 /// Where the delta revocation list is published.
595 freshest_crl, oid::FRESHEST_CRL => DistributionPoints::read, DistributionPoints<'a>;
596 /// What the issuer claims about this being a qualified certificate.
597 qc_statements, oid::QC_STATEMENTS => QcStatements::read, QcStatements<'a>;
598 }
599}
600
601/// Whether a name is not an other-name, or is one whose type identifier a
602/// scheme claims. An other-name's value means what its type says, this crate
603/// names no such types itself, and a critical name extension carrying one
604/// nobody claims was not understood.
605/// Whether a location takes a form its access method names (RFC 5280
606/// 4.2.2.1 and 4.2.2.2): the status responder is reached by a URI; the
607/// issuing certificates and the repository publish over transfer protocols,
608/// a URI, or the directory, a directory name, and a mailbox names no
609/// publication location for them; the timestamping service adds the mailbox,
610/// host and address forms. A method a recognizer claims keeps its own forms.
611fn method_location_fits(method: Oid<'_>, location: &GeneralName<'_>) -> bool {
612 if method == oid::OCSP {
613 matches!(location, GeneralName::Uri(_))
614 } else if method == oid::CA_ISSUERS || method == oid::CA_REPOSITORY {
615 matches!(location, GeneralName::Uri(_) | GeneralName::Directory(_))
616 } else if method == oid::TIME_STAMPING_ACCESS {
617 matches!(
618 location,
619 GeneralName::Uri(_)
620 | GeneralName::Email(_)
621 | GeneralName::Dns(_)
622 | GeneralName::IpAddress(_)
623 )
624 } else {
625 true
626 }
627}
628
629pub(crate) fn other_name_known<E, W: Work>(
630 name: &GeneralName<'_>,
631 recognizer: &impl Recognizer<W, Error = E>,
632 execution: &W,
633) -> CallbackResult<bool, E> {
634 match name {
635 GeneralName::Other { type_id, .. } => recognizer
636 .recognizes_other_name(*type_id, execution)
637 .map_err(CallbackError::Callback),
638 _ => Ok(true),
639 }
640}
641
642fn all<T, E, W: Work>(
643 values: impl Iterator<Item = T>,
644 item: &Extension<'_>,
645 execution: &W,
646 mut understood: impl FnMut(T) -> CallbackResult<bool, E>,
647) -> CallbackResult<bool, E> {
648 for value in values {
649 execution
650 .charge_work(1)
651 .map_err(|reason| Error::resource(reason, "extensions", item.span.start))?;
652 if !understood(value)? {
653 return Ok(false);
654 }
655 }
656 Ok(true)
657}
658
659/// The identifiers a scheme understands, answered by the role an identifier
660/// plays: claiming an extension says nothing about interpreting an
661/// other-name or an access method that reuses the same identifier.
662///
663/// Data, not behaviour: an implementation answers whether an identifier is one
664/// it knows. It cannot decode anything, and nothing here gives it a way to
665/// reach the network. Each role defaults to no, the direction that blocks
666/// rather than vouches.
667pub trait Recognizer<W: Work = Memory> {
668 /// The original policy, provider or resource error of this implementation.
669 type Error;
670
671 /// Whether this scheme understands the extension.
672 fn recognizes(&self, kind: Oid<'_>, execution: &W) -> core::result::Result<bool, Self::Error>;
673
674 /// Whether this scheme can interpret an other-name of this type.
675 fn recognizes_other_name(
676 &self,
677 _type_id: Oid<'_>,
678 _execution: &W,
679 ) -> core::result::Result<bool, Self::Error> {
680 Ok(false)
681 }
682
683 /// Whether this scheme enforces a name constraint written over an
684 /// other-name of this type.
685 ///
686 /// A different question from reading one. Reading asks what a name of
687 /// this type says; a constraint asks whether a certificate's names fall
688 /// inside a subtree of it, which needs a containment rule the type's
689 /// reader never states. A scheme that reads the type and has no such
690 /// rule leaves the constraint enforced by nobody, so this role is
691 /// answered separately and defaults to no.
692 fn recognizes_name_constraint(
693 &self,
694 _type_id: Oid<'_>,
695 _execution: &W,
696 ) -> core::result::Result<bool, Self::Error> {
697 Ok(false)
698 }
699
700 /// Whether this scheme understands an information-access method, its
701 /// location forms included.
702 fn recognizes_access_method(
703 &self,
704 _method: Oid<'_>,
705 _execution: &W,
706 ) -> core::result::Result<bool, Self::Error> {
707 Ok(false)
708 }
709
710 /// Whether this scheme can interpret a qualified statement of this kind:
711 /// a national statement is knowledge a scheme carries, not this crate.
712 fn recognizes_statement(
713 &self,
714 _kind: Oid<'_>,
715 _execution: &W,
716 ) -> core::result::Result<bool, Self::Error> {
717 Ok(false)
718 }
719}
720
721/// Nothing beyond what this crate itself understands.
722impl<W: Work> Recognizer<W> for () {
723 type Error = core::convert::Infallible;
724 fn recognizes(
725 &self,
726 _kind: Oid<'_>,
727 _execution: &W,
728 ) -> core::result::Result<bool, Self::Error> {
729 Ok(false)
730 }
731}
732
733impl<W: Work> Recognizer<W> for [Oid<'_>] {
734 type Error = MemoryError;
735 fn recognizes(&self, kind: Oid<'_>, execution: &W) -> core::result::Result<bool, Self::Error> {
736 for candidate in self {
737 execution
738 .charge_work(1 + candidate.as_bytes().len().max(kind.as_bytes().len()) as u64)?;
739 if *candidate == kind {
740 return Ok(true);
741 }
742 }
743 Ok(false)
744 }
745}
746
747/// A scheme reached by reference answers exactly as it does directly.
748///
749/// Every role of the trait is forwarded, and a new role must be added here
750/// too: each default answers no, so a role left behind silently drops the
751/// scheme's knowledge for callers holding it behind a reference, which is
752/// how a generic wrapper and a `&dyn Recognizer` both arrive.
753impl<W: Work, T: Recognizer<W> + ?Sized> Recognizer<W> for &T {
754 type Error = T::Error;
755 fn recognizes(&self, kind: Oid<'_>, execution: &W) -> core::result::Result<bool, Self::Error> {
756 (*self).recognizes(kind, execution)
757 }
758
759 fn recognizes_other_name(
760 &self,
761 type_id: Oid<'_>,
762 execution: &W,
763 ) -> core::result::Result<bool, Self::Error> {
764 (*self).recognizes_other_name(type_id, execution)
765 }
766
767 fn recognizes_name_constraint(
768 &self,
769 type_id: Oid<'_>,
770 execution: &W,
771 ) -> core::result::Result<bool, Self::Error> {
772 (*self).recognizes_name_constraint(type_id, execution)
773 }
774
775 fn recognizes_access_method(
776 &self,
777 method: Oid<'_>,
778 execution: &W,
779 ) -> core::result::Result<bool, Self::Error> {
780 (*self).recognizes_access_method(method, execution)
781 }
782
783 fn recognizes_statement(
784 &self,
785 kind: Oid<'_>,
786 execution: &W,
787 ) -> core::result::Result<bool, Self::Error> {
788 (*self).recognizes_statement(kind, execution)
789 }
790}
791
792/// Whether this crate reads the extension into a structure of its own.
793#[must_use]
794pub fn is_known(kind: Oid<'_>) -> bool {
795 [
796 oid::BASIC_CONSTRAINTS,
797 oid::KEY_USAGE,
798 oid::EXT_KEY_USAGE,
799 oid::SUBJECT_ALT_NAME,
800 oid::ISSUER_ALT_NAME,
801 oid::SUBJECT_KEY_IDENTIFIER,
802 oid::AUTHORITY_KEY_IDENTIFIER,
803 oid::NAME_CONSTRAINTS,
804 oid::CERTIFICATE_POLICIES,
805 oid::POLICY_MAPPINGS,
806 oid::POLICY_CONSTRAINTS,
807 oid::INHIBIT_ANY_POLICY,
808 oid::AUTHORITY_INFO_ACCESS,
809 oid::SUBJECT_INFO_ACCESS,
810 oid::CRL_DISTRIBUTION_POINTS,
811 oid::FRESHEST_CRL,
812 oid::QC_STATEMENTS,
813 oid::OCSP_NO_CHECK,
814 ]
815 .contains(&kind)
816}
817
818/// A reader over the members of the one sequence an extension's value holds,
819/// which is the shape of most of them.
820pub(crate) fn sequence<'a: 'operation, 'operation, W: Work>(
821 extension: &Extension<'a>,
822 field: &'static str,
823 execution: &'operation W,
824) -> Result<ScopedReader<'a, 'operation>> {
825 sequence_reader(
826 extension.reader_scoped(execution).field(field)?,
827 field,
828 extension.span().start,
829 )
830}
831
832pub(crate) fn sequence_reader<'a: 'operation, 'operation>(
833 mut reader: ScopedReader<'a, 'operation>,
834 field: &'static str,
835 at: u64,
836) -> Result<ScopedReader<'a, 'operation>> {
837 let fail = |code| Error::new(code, field, at);
838 let element = reader
839 .next_element()
840 .field(field)?
841 .ok_or_else(|| fail(ErrorCode::MissingField))?;
842 if element.tag() != Tag::constructed(universal::SEQUENCE) {
843 return Err(fail(ErrorCode::Encoding(
844 structured_asn1::ErrorCode::UnexpectedTag,
845 )));
846 }
847 // A value holding a second structure after the first is two answers to
848 // what the extension says.
849 if !reader.is_empty() {
850 return Err(fail(ErrorCode::TrailingData));
851 }
852
853 reader.enter(&element).field(field)
854}
855
856/// The number and construction of a context-specific tag, and `None` for a
857/// tag of any other class.
858///
859/// The fields these schemas tag by position are context-specific, and a match
860/// on number and construction alone would read an APPLICATION or PRIVATE tag
861/// with the same number as the field it is not.
862pub(crate) fn context_of(tag: Tag) -> Option<(u32, bool)> {
863 // A number this reader does not name is not a field any schema wrote.
864 (tag.class() == structured_asn1::Class::ContextSpecific)
865 .then(|| tag.number().map(|number| (number, tag.is_constructed())))
866 .flatten()
867}
868
869/// Reads the extensions from the element the schema wraps them in. The
870/// parent reader's parser is kept with each extension, so every later decode
871/// of its value is charged to the budget the certificate was read with, and
872/// no other parser can be handed in beside the reader.
873pub(crate) fn read<'a>(
874 parent: &ScopedReader<'a, '_>,
875 element: &Element<'a>,
876 field: &'static str,
877) -> Result<Extensions<'a>> {
878 read_tagged(
879 parent,
880 element,
881 Tag::constructed(universal::SEQUENCE),
882 field,
883 )
884}
885
886fn read_tagged<'a>(
887 parent: &ScopedReader<'a, '_>,
888 element: &Element<'a>,
889 expected: Tag,
890 field: &'static str,
891) -> Result<Extensions<'a>> {
892 let parser = parent.parser();
893 let fail = |code| Error::new(code, field, element.span().start);
894
895 if element.tag() != expected {
896 return Err(fail(ErrorCode::Encoding(
897 structured_asn1::ErrorCode::UnexpectedTag,
898 )));
899 }
900
901 let mut sequence = parent.enter(element).field(field)?;
902 let mut items = parent.execution().vector();
903 // A set rather than a scan of what came before: a certificate can carry
904 // tens of thousands of extensions within the parse budget, and a per-item
905 // scan of the list would be quadratic work the budget never sees.
906 let mut kinds = parent.execution().map::<Oid<'a>, ()>();
907
908 while let Some(entry) = sequence.next_element().field(field)? {
909 let at = |code| Error::new(code, field, entry.span().start);
910
911 let fields = open(&sequence, &entry, field)?;
912 if fields.header().default_written() && fields.reader().encoding().is_der() {
913 let at = fields
914 .header()
915 .critical_span()
916 .expect("written flag has a span")
917 .start;
918 return Err(Error::new(ErrorCode::MalformedValue, field, at));
919 }
920 let decoded = fields
921 .read_with(|_header, inside, value| {
922 // RFC5280 §4.1 / X.690 §11.5: the strict certificate profile
923 // keeps its primitive-value and DER-default invariants. TSP
924 // inspection can instead retain the common structural metadata.
925 // https://www.rfc-editor.org/rfc/rfc5280#section-4.1
926 if value.tag() != Tag::primitive(universal::OCTET_STRING) {
927 return Err(Error::new(
928 ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
929 field,
930 value.span().start,
931 ));
932 }
933 if !inside.is_empty() {
934 return Err(at(ErrorCode::TrailingData));
935 }
936 Ok((value.contents(), value.contents_span(), inside.depth()))
937 })
938 .map_err(|error| match error {
939 CallbackError::Processing(error) | CallbackError::Callback(error) => error,
940 })?;
941 let header = decoded.header();
942 let kind = header.kind();
943 let critical = header.is_critical();
944 let (value, value_span, outer) = decoded.into_value();
945
946 // Two copies of one extension leave no answer to which applies, and a
947 // reader that took the first would disagree with one that took the
948 // last about what the certificate says.
949 if kinds
950 .try_insert(kind, ())
951 .map_err(|reason| Error::resource(reason, field, entry.span().start))?
952 .is_some()
953 {
954 return Err(at(ErrorCode::DuplicateExtension));
955 }
956
957 items
958 .try_push(Extension {
959 kind,
960 critical,
961 value,
962 value_span,
963 span: entry.span(),
964 parser,
965 outer,
966 })
967 .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
968 }
969
970 // The schema requires at least one, and an empty sequence is a structure
971 // that says nothing while claiming to.
972 if items.is_empty() {
973 return Err(fail(ErrorCode::EmptySequence));
974 }
975
976 Ok(Extensions {
977 items: items.into_owned(),
978 })
979}
980
981#[cfg(test)]
982mod tests;