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