Skip to main content

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;