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::QC_STATEMENTS {
432            // The outer list parsing is not understanding: the statement
433            // payloads decode lazily, and a critical list whose statement
434            // carries garbage, or whose identifier nobody here knows, is a
435            // critical demand this run never understood, one level down from
436            // an unknown extension.
437            match gate(QcStatements::read(item, execution))? {
438                Some(statements) => statements.understood(recognizer, execution)?,
439                None => false,
440            }
441        } else {
442            // is_known and this list name the same identifiers; a mismatch is
443            // a bug, and claiming the value parsed would hide it.
444            false
445        })
446    }
447}
448
449/// Generates one typed accessor per extension: absent when the list does not
450/// carry the identifier, otherwise whatever the reader makes of the value.
451/// The table is the single place an accessor name, its identifier and its
452/// reader meet, so the three cannot drift apart.
453macro_rules! typed_accessors {
454    ($($(#[$doc:meta])* $name:ident, $oid:path => $reader:path, $result:ty;)+) => {
455        $(
456            $(#[$doc])*
457            pub fn $name(&self, execution: &Memory) -> Result<Option<$result>> {
458                match self.get($oid, execution)? {
459                    Some(item) => $reader(item, execution).map(Some),
460                    None => Ok(None),
461                }
462            }
463        )+
464    };
465}
466
467/// The extensions this crate reads into structures of their own.
468///
469/// Each is read when it is asked for rather than when the certificate is,
470/// because an extension that cannot be read is not a certificate that cannot
471/// be read. Lookup and decoding use the caller's current execution domain;
472/// the original parser's cumulative local ceilings still apply.
473impl<'a> Extensions<'a> {
474    typed_accessors! {
475        /// Whether this is a certification authority, and how deep a path
476        /// below it may go.
477        basic_constraints, oid::BASIC_CONSTRAINTS => BasicConstraints::read, BasicConstraints;
478        /// What the key may be used for.
479        key_usage, oid::KEY_USAGE => KeyUsage::read, KeyUsage<'a>;
480        /// The further purposes the key is named for.
481        extended_key_usage, oid::EXT_KEY_USAGE => ExtendedKeyUsage::read, ExtendedKeyUsage<'a>;
482        /// The further names for the subject.
483        subject_alt_name, oid::SUBJECT_ALT_NAME => general_name::read_alternative, OwnedVec<GeneralName<'a>>;
484        /// The further names for the issuer.
485        issuer_alt_name, oid::ISSUER_ALT_NAME => general_name::read_alternative, OwnedVec<GeneralName<'a>>;
486        /// The identifier for the key this certificate carries.
487        subject_key_identifier, oid::SUBJECT_KEY_IDENTIFIER => SubjectKeyIdentifier::read, SubjectKeyIdentifier<'a>;
488        /// The identifier for the key that signed it.
489        authority_key_identifier, oid::AUTHORITY_KEY_IDENTIFIER => AuthorityKeyIdentifier::read, AuthorityKeyIdentifier<'a>;
490        /// The name space this authority may certify within.
491        name_constraints, oid::NAME_CONSTRAINTS => NameConstraints::read, NameConstraints<'a>;
492        /// The policies the certificate was issued under.
493        certificate_policies, oid::CERTIFICATE_POLICIES => CertificatePolicies::read, CertificatePolicies<'a>;
494        /// The policies of one domain treated as equivalent to another's.
495        policy_mappings, oid::POLICY_MAPPINGS => PolicyMappings::read, PolicyMappings<'a>;
496        /// The limits on policy processing below this certificate.
497        policy_constraints, oid::POLICY_CONSTRAINTS => PolicyConstraints::read, PolicyConstraints;
498        /// After how many certificates the identifier standing for any policy
499        /// stops being accepted.
500        inhibit_any_policy, oid::INHIBIT_ANY_POLICY => InhibitAnyPolicy::read, InhibitAnyPolicy;
501        /// Where the issuer's certificate and status service are published.
502        authority_info_access, oid::AUTHORITY_INFO_ACCESS => InfoAccess::read, InfoAccess<'a>;
503        /// Where services belonging to the subject are published.
504        subject_info_access, oid::SUBJECT_INFO_ACCESS => InfoAccess::read, InfoAccess<'a>;
505        /// Where revocation lists covering this certificate are published.
506        crl_distribution_points, oid::CRL_DISTRIBUTION_POINTS => DistributionPoints::read, DistributionPoints<'a>;
507        /// Where the delta revocation list is published.
508        freshest_crl, oid::FRESHEST_CRL => DistributionPoints::read, DistributionPoints<'a>;
509        /// What the issuer claims about this being a qualified certificate.
510        qc_statements, oid::QC_STATEMENTS => QcStatements::read, QcStatements<'a>;
511    }
512}
513
514/// Whether a name is not an other-name, or is one whose type identifier a
515/// scheme claims. An other-name's value means what its type says, this crate
516/// names no such types itself, and a critical name extension carrying one
517/// nobody claims was not understood.
518/// Whether a location takes a form its access method names (RFC 5280
519/// 4.2.2.1 and 4.2.2.2): the status responder is reached by a URI; the
520/// issuing certificates and the repository publish over transfer protocols,
521/// a URI, or the directory, a directory name, and a mailbox names no
522/// publication location for them; the timestamping service adds the mailbox,
523/// host and address forms. A method a recognizer claims keeps its own forms.
524fn method_location_fits(method: Oid<'_>, location: &GeneralName<'_>) -> bool {
525    if method == oid::OCSP {
526        matches!(location, GeneralName::Uri(_))
527    } else if method == oid::CA_ISSUERS || method == oid::CA_REPOSITORY {
528        matches!(location, GeneralName::Uri(_) | GeneralName::Directory(_))
529    } else if method == oid::TIME_STAMPING_ACCESS {
530        matches!(
531            location,
532            GeneralName::Uri(_)
533                | GeneralName::Email(_)
534                | GeneralName::Dns(_)
535                | GeneralName::IpAddress(_)
536        )
537    } else {
538        true
539    }
540}
541
542pub(crate) fn other_name_known<E>(
543    name: &GeneralName<'_>,
544    recognizer: &impl Recognizer<Error = E>,
545    execution: &Memory,
546) -> CallbackResult<bool, E> {
547    match name {
548        GeneralName::Other { type_id, .. } => recognizer
549            .recognizes_other_name(*type_id, execution)
550            .map_err(CallbackError::Callback),
551        _ => Ok(true),
552    }
553}
554
555fn all<T, E>(
556    values: impl Iterator<Item = T>,
557    item: &Extension<'_>,
558    execution: &Memory,
559    mut understood: impl FnMut(T) -> CallbackResult<bool, E>,
560) -> CallbackResult<bool, E> {
561    for value in values {
562        execution
563            .charge_work(1)
564            .map_err(|reason| Error::resource(reason, "extensions", item.span.start))?;
565        if !understood(value)? {
566            return Ok(false);
567        }
568    }
569    Ok(true)
570}
571
572/// The identifiers a scheme understands, answered by the role an identifier
573/// plays: claiming an extension says nothing about interpreting an
574/// other-name or an access method that reuses the same identifier.
575///
576/// Data, not behaviour: an implementation answers whether an identifier is one
577/// it knows. It cannot decode anything, and nothing here gives it a way to
578/// reach the network. Each role defaults to no, the direction that blocks
579/// rather than vouches.
580pub trait Recognizer {
581    /// The original policy, provider or resource error of this implementation.
582    type Error;
583
584    /// Whether this scheme understands the extension.
585    fn recognizes(
586        &self,
587        kind: Oid<'_>,
588        execution: &Memory,
589    ) -> core::result::Result<bool, Self::Error>;
590
591    /// Whether this scheme can interpret an other-name of this type.
592    fn recognizes_other_name(
593        &self,
594        _type_id: Oid<'_>,
595        _execution: &Memory,
596    ) -> core::result::Result<bool, Self::Error> {
597        Ok(false)
598    }
599
600    /// Whether this scheme enforces a name constraint written over an
601    /// other-name of this type.
602    ///
603    /// A different question from reading one. Reading asks what a name of
604    /// this type says; a constraint asks whether a certificate's names fall
605    /// inside a subtree of it, which needs a containment rule the type's
606    /// reader never states. A scheme that reads the type and has no such
607    /// rule leaves the constraint enforced by nobody, so this role is
608    /// answered separately and defaults to no.
609    fn recognizes_name_constraint(
610        &self,
611        _type_id: Oid<'_>,
612        _execution: &Memory,
613    ) -> core::result::Result<bool, Self::Error> {
614        Ok(false)
615    }
616
617    /// Whether this scheme understands an information-access method, its
618    /// location forms included.
619    fn recognizes_access_method(
620        &self,
621        _method: Oid<'_>,
622        _execution: &Memory,
623    ) -> core::result::Result<bool, Self::Error> {
624        Ok(false)
625    }
626
627    /// Whether this scheme can interpret a qualified statement of this kind:
628    /// a national statement is knowledge a scheme carries, not this crate.
629    fn recognizes_statement(
630        &self,
631        _kind: Oid<'_>,
632        _execution: &Memory,
633    ) -> core::result::Result<bool, Self::Error> {
634        Ok(false)
635    }
636}
637
638/// Nothing beyond what this crate itself understands.
639impl Recognizer for () {
640    type Error = core::convert::Infallible;
641    fn recognizes(
642        &self,
643        _kind: Oid<'_>,
644        _execution: &Memory,
645    ) -> core::result::Result<bool, Self::Error> {
646        Ok(false)
647    }
648}
649
650impl Recognizer for [Oid<'_>] {
651    type Error = MemoryError;
652    fn recognizes(
653        &self,
654        kind: Oid<'_>,
655        execution: &Memory,
656    ) -> core::result::Result<bool, Self::Error> {
657        for candidate in self {
658            execution
659                .charge_work(1 + candidate.as_bytes().len().max(kind.as_bytes().len()) as u64)?;
660            if *candidate == kind {
661                return Ok(true);
662            }
663        }
664        Ok(false)
665    }
666}
667
668/// A scheme reached by reference answers exactly as it does directly.
669///
670/// Every role of the trait is forwarded, and a new role must be added here
671/// too: each default answers no, so a role left behind silently drops the
672/// scheme's knowledge for callers holding it behind a reference, which is
673/// how a generic wrapper and a `&dyn Recognizer` both arrive.
674impl<T: Recognizer + ?Sized> Recognizer for &T {
675    type Error = T::Error;
676    fn recognizes(
677        &self,
678        kind: Oid<'_>,
679        execution: &Memory,
680    ) -> core::result::Result<bool, Self::Error> {
681        (*self).recognizes(kind, execution)
682    }
683
684    fn recognizes_other_name(
685        &self,
686        type_id: Oid<'_>,
687        execution: &Memory,
688    ) -> core::result::Result<bool, Self::Error> {
689        (*self).recognizes_other_name(type_id, execution)
690    }
691
692    fn recognizes_name_constraint(
693        &self,
694        type_id: Oid<'_>,
695        execution: &Memory,
696    ) -> core::result::Result<bool, Self::Error> {
697        (*self).recognizes_name_constraint(type_id, execution)
698    }
699
700    fn recognizes_access_method(
701        &self,
702        method: Oid<'_>,
703        execution: &Memory,
704    ) -> core::result::Result<bool, Self::Error> {
705        (*self).recognizes_access_method(method, execution)
706    }
707
708    fn recognizes_statement(
709        &self,
710        kind: Oid<'_>,
711        execution: &Memory,
712    ) -> core::result::Result<bool, Self::Error> {
713        (*self).recognizes_statement(kind, execution)
714    }
715}
716
717/// Whether this crate reads the extension into a structure of its own.
718#[must_use]
719pub fn is_known(kind: Oid<'_>) -> bool {
720    [
721        oid::BASIC_CONSTRAINTS,
722        oid::KEY_USAGE,
723        oid::EXT_KEY_USAGE,
724        oid::SUBJECT_ALT_NAME,
725        oid::ISSUER_ALT_NAME,
726        oid::SUBJECT_KEY_IDENTIFIER,
727        oid::AUTHORITY_KEY_IDENTIFIER,
728        oid::NAME_CONSTRAINTS,
729        oid::CERTIFICATE_POLICIES,
730        oid::POLICY_MAPPINGS,
731        oid::POLICY_CONSTRAINTS,
732        oid::INHIBIT_ANY_POLICY,
733        oid::AUTHORITY_INFO_ACCESS,
734        oid::SUBJECT_INFO_ACCESS,
735        oid::CRL_DISTRIBUTION_POINTS,
736        oid::FRESHEST_CRL,
737        oid::QC_STATEMENTS,
738    ]
739    .contains(&kind)
740}
741
742/// A reader over the members of the one sequence an extension's value holds,
743/// which is the shape of most of them.
744pub(crate) fn sequence<'a>(
745    extension: &Extension<'a>,
746    field: &'static str,
747    execution: &Memory,
748) -> Result<Reader<'a>> {
749    let fail = |code| Error::new(code, field, extension.span().start);
750
751    let mut reader = extension.reader(execution).field(field)?;
752    let element = reader
753        .next_element()
754        .field(field)?
755        .ok_or_else(|| fail(ErrorCode::MissingField))?;
756    if element.tag() != Tag::constructed(universal::SEQUENCE) {
757        return Err(fail(ErrorCode::Encoding(
758            structured_asn1::ErrorCode::UnexpectedTag,
759        )));
760    }
761    // A value holding a second structure after the first is two answers to
762    // what the extension says.
763    if !reader.is_empty() {
764        return Err(fail(ErrorCode::TrailingData));
765    }
766
767    reader.enter(&element).field(field)
768}
769
770/// The number and construction of a context-specific tag, and `None` for a
771/// tag of any other class.
772///
773/// The fields these schemas tag by position are context-specific, and a match
774/// on number and construction alone would read an APPLICATION or PRIVATE tag
775/// with the same number as the field it is not.
776pub(crate) fn context_of(tag: Tag) -> Option<(u32, bool)> {
777    // A number this reader does not name is not a field any schema wrote.
778    (tag.class() == structured_asn1::Class::ContextSpecific)
779        .then(|| tag.number().map(|number| (number, tag.is_constructed())))
780        .flatten()
781}
782
783/// Reads the extensions from the element the schema wraps them in. The
784/// parent reader's parser is kept with each extension, so every later decode
785/// of its value is charged to the budget the certificate was read with, and
786/// no other parser can be handed in beside the reader.
787pub(crate) fn read<'a>(
788    parent: &Reader<'a>,
789    element: &Element<'a>,
790    field: &'static str,
791) -> Result<Extensions<'a>> {
792    let parser = parent.parser();
793    let fail = |code| Error::new(code, field, element.span().start);
794
795    if element.tag() != Tag::constructed(universal::SEQUENCE) {
796        return Err(fail(ErrorCode::Encoding(
797            structured_asn1::ErrorCode::UnexpectedTag,
798        )));
799    }
800
801    let mut sequence = parent.enter(element).field(field)?;
802    let mut items = parent.memory().vector();
803    // A set rather than a scan of what came before: a certificate can carry
804    // tens of thousands of extensions within the parse budget, and a per-item
805    // scan of the list would be quadratic work the budget never sees.
806    let mut kinds = parent.memory().map::<Oid<'a>, ()>();
807
808    while let Some(entry) = sequence.next_element().field(field)? {
809        let at = |code| Error::new(code, field, entry.span().start);
810
811        if entry.tag() != Tag::constructed(universal::SEQUENCE) {
812            return Err(at(ErrorCode::Encoding(
813                structured_asn1::ErrorCode::UnexpectedTag,
814            )));
815        }
816
817        let mut inside = sequence.enter(&entry).field(field)?;
818        let kind = inside.read_oid().field(field)?;
819
820        let mut next = inside.next_element().field(field)?;
821        let critical = match next {
822            Some(flag) if flag.tag() == Tag::primitive(universal::BOOLEAN) => {
823                let value = inside.boolean(&flag).field(field)?;
824                // The flag defaults to false, and DER requires a default to
825                // be omitted: writing it out is a second spelling of the
826                // absent flag, and two spellings of one value is what DER
827                // exists to refuse. BER has no such rule, and issuers write
828                // it, so there the spelled-out default reads as itself.
829                if !value && inside.encoding().is_der() {
830                    return Err(Error::new(
831                        ErrorCode::MalformedValue,
832                        field,
833                        flag.span().start,
834                    ));
835                }
836                next = inside.next_element().field(field)?;
837                value
838            }
839            // Absent means false, which is what most extensions leave it at.
840            _ => false,
841        };
842
843        let value = next.ok_or_else(|| at(ErrorCode::MissingField))?;
844        if value.tag() != Tag::primitive(universal::OCTET_STRING) {
845            return Err(Error::new(
846                ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
847                field,
848                value.span().start,
849            ));
850        }
851        if !inside.is_empty() {
852            return Err(at(ErrorCode::TrailingData));
853        }
854
855        // Two copies of one extension leave no answer to which applies, and a
856        // reader that took the first would disagree with one that took the
857        // last about what the certificate says.
858        if kinds
859            .try_insert(kind, ())
860            .map_err(|reason| Error::resource(reason, field, entry.span().start))?
861            .is_some()
862        {
863            return Err(at(ErrorCode::DuplicateExtension));
864        }
865
866        items
867            .try_push(Extension {
868                kind,
869                critical,
870                value: value.contents(),
871                value_span: value.contents_span(),
872                span: entry.span(),
873                parser,
874                outer: inside.depth(),
875            })
876            .map_err(|reason| Error::resource(reason, field, entry.span().start))?;
877    }
878
879    // The schema requires at least one, and an empty sequence is a structure
880    // that says nothing while claiming to.
881    if items.is_empty() {
882        return Err(fail(ErrorCode::EmptySequence));
883    }
884
885    Ok(Extensions { items })
886}
887
888#[cfg(test)]
889mod tests;