Skip to main content

structured_pkix/
path.rs

1//! Certification paths: which sequences of certificates lead from a
2//! certificate to an anchor the caller trusts, and what that costs.
3//!
4//! One signature can have several valid paths, and a report shows them,
5//! because a cross-certified provider is recognized under one scheme by one
6//! path and under another by another. That is not the same as enumerating
7//! every path: a certificate set somebody else controls can hold a
8//! combinatorial number of them, and a browser asked for all of them stops
9//! answering. So the search is bounded in every direction it can grow, and
10//! when a bound is reached the answer says so. Silence about truncation
11//! would be a worse answer than the truncation.
12//!
13//! Where the bound is on how many paths are returned, which paths are kept
14//! is not the order they were found in. A second path to the same anchor
15//! naming the same policies tells a reader nothing the first did not; a path
16//! to another anchor, or one naming other policies, is the whole reason
17//! several paths are shown at all. So a path that differs in either is kept
18//! ahead of a repeat of one already held.
19//!
20//! An anchor is an input, never a discovery (RFC 5280 6.1): a self-signed
21//! certificate that happens to sit in the same pool is a certificate like
22//! any other, and a path that ends at one the caller did not name ends
23//! nowhere.
24
25mod error;
26mod name_space;
27mod policy;
28
29pub use error::{BuildError, BuildResult};
30
31use crate::algorithm::AlgorithmIdentifier;
32use crate::certificate::{Certificate, Validity};
33use crate::constraints::CertificateCount;
34use crate::error::{Result, gate};
35use crate::extension::Recognizer;
36use crate::general_name::GeneralName;
37use crate::key::PublicKeyInfo;
38use crate::name::Name;
39use name_space::{Admission, NameSpace};
40use structured_asn1::memory::{Memory, OwnedMap, OwnedVec};
41use structured_asn1::{BitString, Oid};
42
43/// What the caller trusts, as the trust context named it.
44///
45/// A name and a key, because that is what an anchor is: the certificate it
46/// was published in, where there is one, is kept for the report and is not
47/// what makes it an anchor. Two anchors with the same name and different
48/// keys are two anchors, and a path is built to each.
49#[derive(Debug, Clone, Copy)]
50pub struct Anchor<'a> {
51    name: &'a Name<'a>,
52    key: PublicKeyInfo<'a>,
53    certificate: Option<&'a Certificate<'a>>,
54}
55
56impl<'a> Anchor<'a> {
57    /// An anchor the trust context supplies as a name and a key.
58    #[must_use]
59    pub fn new(name: &'a Name<'a>, key: PublicKeyInfo<'a>) -> Self {
60        Self {
61            name,
62            key,
63            certificate: None,
64        }
65    }
66
67    /// An anchor the trust context supplies as a certificate, whose subject
68    /// and key it is. The certificate is not part of any path built to it
69    /// (RFC 5280 6.1), and is kept so a report can name where the anchor
70    /// came from and so that what it says about the names below it is
71    /// obeyed.
72    #[must_use]
73    pub fn from_certificate(certificate: &'a Certificate<'a>) -> Self {
74        Self {
75            name: certificate.tbs().subject(),
76            key: certificate.tbs().public_key(),
77            certificate: Some(certificate),
78        }
79    }
80
81    /// The name a certificate issued under this anchor carries as its issuer.
82    #[must_use]
83    pub fn name(&self) -> &'a Name<'a> {
84        self.name
85    }
86
87    /// The public key information, as encoded, which is what verifies the
88    /// signature of the certificate below it.
89    #[must_use]
90    pub fn key(&self) -> PublicKeyInfo<'a> {
91        self.key
92    }
93
94    /// The certificate the anchor was published in, where the trust context
95    /// had one.
96    #[must_use]
97    pub fn certificate(&self) -> Option<&'a Certificate<'a>> {
98        self.certificate
99    }
100
101    /// Whether two anchors are the same one: the same name and the same key,
102    /// which is what an anchor is.
103    fn same(self, other: Self, execution: &Memory) -> Result<bool> {
104        execution
105            .charge_work(self.key.as_bytes().len().max(other.key.as_bytes().len()) as u64)
106            .map_err(|reason| self.name.resource(reason))?;
107        if self.key.as_bytes() != other.key.as_bytes() {
108            return Ok(false);
109        }
110        self.name.matches(other.name, execution)
111    }
112}
113
114/// What a verifier says about one signature.
115///
116/// The third answer is the one that matters: an algorithm this build cannot
117/// verify is not a signature that passed. Collapsing it into a no would say
118/// the certificate is broken, and into a yes would say it is good; both are
119/// claims nobody made.
120#[derive(Debug, Clone, Copy, PartialEq, Eq)]
121#[non_exhaustive]
122pub enum Verified {
123    /// The signature is the issuer's over these bytes.
124    Yes,
125    /// The signature is not.
126    No,
127    /// This build cannot answer: the algorithm, the key or the parameters
128    /// are outside what it verifies.
129    Unsupported,
130}
131
132/// The key a certificate's signature is checked with, and the parameters
133/// that are in force for it.
134///
135/// "If the public key algorithm parameters are absent, the working public key
136/// parameters are inherited" from the certificate above (RFC 5280 6.1.2 (c)
137/// and 6.1.4 (c)). A key written without them is not a key anything can be
138/// checked with on its own: the curve or the group it belongs to is written
139/// once, in an authority above it, and every key below stands in that same
140/// one. A verifier handed the encoding alone would have to answer that it
141/// cannot say, and a valid path would go unreported.
142///
143/// Where the key carries its own parameters, those are the ones in force and
144/// nothing is inherited. This is the ordinary case: a named curve, an RSA
145/// modulus, an Edwards key.
146#[derive(Debug, Clone, Copy)]
147pub struct WorkingKey<'a> {
148    key: PublicKeyInfo<'a>,
149    /// The parameters carried down, and the algorithm they belong to: they
150    /// stand only for a key of that same algorithm.
151    inherited: Option<(Oid<'a>, &'a [u8])>,
152}
153
154impl<'a> WorkingKey<'a> {
155    /// A key that stands on its own, which is what a trust anchor's is: there
156    /// is nothing above it to inherit from.
157    #[must_use]
158    pub fn standing(key: PublicKeyInfo<'a>) -> Self {
159        Self {
160            key,
161            inherited: None,
162        }
163    }
164
165    /// The key itself, as the certificate wrote it.
166    #[must_use]
167    pub fn key(self) -> PublicKeyInfo<'a> {
168        self.key
169    }
170
171    /// The parameters in force: the key's own where it has them, and the ones
172    /// carried down from above where it does not and belongs to the same
173    /// algorithm.
174    ///
175    /// "If the certificate subjectPublicKey algorithm and the
176    /// `working_public_key_algorithm` are different, set the
177    /// `working_public_key_parameters` to null" (RFC 5280 6.1.4 (d)). Nothing
178    /// is carried across a change of algorithm: a curve is not a modulus,
179    /// and an authority on one algorithm certifying a key on another says
180    /// nothing about how that key is written. Handing them over anyway gives
181    /// a verifier a key described by parameters that are not its own, which
182    /// it can only refuse.
183    ///
184    /// A key that writes an explicit null inherits exactly as one that omits
185    /// its parameters does. The clause opens on "an algorithm field with
186    /// null parameters or parameters are omitted" and gives the two one
187    /// rule, so a key that writes a null and names the algorithm in force
188    /// stands in what is in force, whatever a given algorithm's own encoding
189    /// rules say about which of the two spellings it should have used. The
190    /// same tolerance is `AlgorithmIdentifier::same_as`, and reading a null
191    /// as a refusal here would refuse paths the profile builds.
192    ///
193    /// `None` says the algorithm takes none, which is not the same as a key
194    /// whose parameters were inherited.
195    #[must_use]
196    pub fn parameters(self) -> Option<&'a [u8]> {
197        if !self.key.algorithm().has_no_parameters() {
198            return self.key.algorithm().parameters();
199        }
200        let (algorithm, inherited) = self.inherited?;
201        (algorithm == self.key.algorithm().algorithm()).then_some(inherited)
202    }
203
204    /// The working key one certificate further down: this certificate's own
205    /// key, standing in the parameters in force where it wrote none.
206    ///
207    /// The algorithm those parameters belong to travels with them, since a
208    /// key further down inherits only from a key of its own algorithm.
209    #[must_use]
210    fn below(self, key: PublicKeyInfo<'a>) -> Self {
211        let algorithm = self.key.algorithm().algorithm();
212        Self {
213            key,
214            inherited: self.parameters().map(|held| (algorithm, held)),
215        }
216    }
217}
218
219/// Who checks a signature.
220///
221/// Which algorithms may verify what belongs to the algorithm registry rather
222/// than to this crate, so the check is asked for rather than performed here.
223/// A caller that supplies no verifier gets no path: nothing else in a path
224/// binds one certificate to the next.
225pub trait Verify {
226    /// The original policy, provider or resource failure of this implementation.
227    type Error;
228
229    /// Whether the signature over `signed` is the one the key in `key`
230    /// makes under `algorithm`.
231    ///
232    /// The key arrives with the parameters in force rather than as the
233    /// encoding alone, since a certificate may omit them and stand in the
234    /// ones an authority above it wrote.
235    ///
236    /// A key may also be offered before those are known: while a path is
237    /// being looked for, an authority is asked about with the key exactly as
238    /// its certificate wrote it, because what it stands in is above and
239    /// above has not been reached. An implementation that cannot judge a key
240    /// without parameters it was not given answers `Unsupported` rather than
241    /// `No`. The two are not interchangeable here: `No` prunes the branch,
242    /// and a key that merely could not be judged yet is asked about again
243    /// from the anchor down.
244    fn verify(
245        &self,
246        algorithm: &AlgorithmIdentifier<'_>,
247        key: WorkingKey<'_>,
248        signed: &[u8],
249        signature: BitString<'_>,
250        execution: &Memory,
251    ) -> core::result::Result<Verified, Self::Error>;
252}
253
254/// Nothing is verified, which is what a caller without a registry has.
255impl Verify for () {
256    type Error = core::convert::Infallible;
257    fn verify(
258        &self,
259        _algorithm: &AlgorithmIdentifier<'_>,
260        _key: WorkingKey<'_>,
261        _signed: &[u8],
262        _signature: BitString<'_>,
263        _execution: &Memory,
264    ) -> core::result::Result<Verified, Self::Error> {
265        Ok(Verified::Unsupported)
266    }
267}
268
269/// Whether the search has run out of time.
270///
271/// There is no clock here: this crate builds without an operating system, so
272/// wall time is something the caller watches and this asks about. The work
273/// bound below is the one that always applies, and this one narrows it where
274/// the caller can measure.
275pub trait Watch {
276    /// Whether the time the caller allowed has passed.
277    fn out_of_time(&self) -> bool;
278}
279
280/// No clock, so no deadline: the work bound is what stops the search.
281impl Watch for () {
282    fn out_of_time(&self) -> bool {
283        false
284    }
285}
286
287/// What charges work and says whether there is any left.
288///
289/// The search holds the meter, and the planes that work out policies and
290/// names are given it rather than a copy of what it counts: a plane with its
291/// own budget is a second bound the caller never set, and one with none
292/// spends whatever a list somebody else wrote asks for. One trait rather
293/// than the search itself, so those planes do not carry the verifier, the
294/// clock and the recognizer through their signatures to reach the counter.
295pub(crate) trait Meter {
296    /// Charges work, and says whether there is any budget left. Both the
297    /// work bound and the caller's clock are answered here, since running
298    /// out of either stops the same search.
299    fn spend(&mut self, work: u64) -> Result<bool>;
300}
301
302/// No meter, so no bound: for asking a plane what it works out rather than
303/// what it spends, which is what the tests of one plane are about.
304impl Meter for () {
305    fn spend(&mut self, _work: u64) -> Result<bool> {
306        Ok(true)
307    }
308}
309
310/// How far the search may go before it stops and says so.
311///
312/// Every direction a search can grow has a number here, because a
313/// certificate set somebody else controls grows in all of them: deeper
314/// chains, wider fan-out at each step, more paths that differ in one
315/// certificate, more policies in each certificate. The defaults are what a
316/// browser can spend on a document somebody sent, not what a server can
317/// spend on its own inventory.
318#[derive(Debug, Clone, Copy)]
319pub struct Bounds {
320    /// How many certificates a path may hold, the anchor aside.
321    pub depth: usize,
322    /// How many times a certificate may be entered at some depth.
323    pub visited: usize,
324    /// How many candidate issuers may be considered in total.
325    pub edges: usize,
326    /// How much work the checks along the way may cost.
327    pub work: u64,
328    /// How many paths may be returned.
329    pub paths: usize,
330    /// How many policies one path's working out may hold at once.
331    pub policies: usize,
332}
333
334impl Default for Bounds {
335    fn default() -> Self {
336        Self {
337            depth: 12,
338            visited: 4_096,
339            edges: 16_384,
340            work: 1_000_000,
341            paths: 8,
342            policies: 1_024,
343        }
344    }
345}
346
347/// Which bound stopped the search, where one did.
348///
349/// A report says which, because the answers differ: a search that ran out of
350/// paths has more to show, and a search that ran out of depth was looking in
351/// the wrong place.
352#[derive(Debug, Clone, Copy, PartialEq, Eq)]
353#[non_exhaustive]
354pub enum Truncation {
355    /// A path reached the depth bound and was not followed further.
356    Depth,
357    /// The count of entered certificates reached its bound.
358    Visited,
359    /// The count of considered candidates reached its bound.
360    Edges,
361    /// The checks along the way cost what the caller allowed.
362    Work,
363    /// The caller's clock ran out.
364    Time,
365    /// More paths were found than the caller asked for, and one that was
366    /// found is not among the ones returned.
367    Paths,
368    /// Working out what a path was issued under grew past what the caller
369    /// allowed it to hold, so that path was not settled.
370    Policies,
371}
372
373impl Truncation {
374    /// Whether reaching this bound ends the whole search rather than one
375    /// branch of it.
376    ///
377    /// The counts of work, time, entered certificates and considered
378    /// candidates are spent once for the whole search, so reaching one
379    /// leaves nothing further to look at. Depth, room for paths and the size
380    /// of a policy tree are reached by one branch or one path, and the
381    /// search goes on to the next.
382    fn halts(self) -> bool {
383        matches!(self, Self::Work | Self::Time | Self::Visited | Self::Edges)
384    }
385}
386
387/// One certification path: the certificates from the target up, the anchor
388/// they lead to, and what the authorities along it agreed the target was
389/// issued under.
390#[derive(Debug)]
391pub struct Path<'a> {
392    certificates: OwnedVec<&'a Certificate<'a>>,
393    anchor: Anchor<'a>,
394    policies: OwnedVec<Oid<'a>>,
395}
396
397impl<'a> Path<'a> {
398    /// The certificates, the target first and the one the anchor issued
399    /// last. The anchor's own certificate is not among them.
400    #[must_use]
401    pub fn certificates(&self) -> &[&'a Certificate<'a>] {
402        &self.certificates
403    }
404
405    /// The anchor this path ends at.
406    #[must_use]
407    pub fn anchor(&self) -> Anchor<'a> {
408        self.anchor
409    }
410
411    /// The policies every authority along the path agreed the target was
412    /// issued under, narrowed to the ones the caller asked about.
413    ///
414    /// Empty says the path names no policy the caller asked about, which is
415    /// a path only because nobody along it demanded that it name one.
416    ///
417    /// A set rather than a list, and returned in one order whatever order
418    /// the certificates wrote it in, so that two paths naming one set are
419    /// told apart by walking them once.
420    #[must_use]
421    pub fn policies(&self) -> &[Oid<'a>] {
422        &self.policies
423    }
424
425    /// How many certificates the path holds.
426    #[must_use]
427    pub fn len(&self) -> usize {
428        self.certificates.len()
429    }
430
431    /// Whether the path holds no certificates, which no path this builder
432    /// returns does.
433    #[must_use]
434    pub fn is_empty(&self) -> bool {
435        self.certificates.is_empty()
436    }
437
438    /// Whether two paths say the same thing: the same names carrying the
439    /// same keys, up to the same anchor.
440    ///
441    /// Serial numbers and validity are not part of it, so an authority that
442    /// re-issued its own certificate is one route rather than two. What
443    /// makes a second path worth showing is that it goes somewhere else or
444    /// says something else, and neither of those is a new serial number.
445    fn same_route(
446        &self,
447        chain: &[&'a Certificate<'a>],
448        anchor: Anchor<'a>,
449        execution: &Memory,
450    ) -> Result<bool> {
451        if self.certificates.len() != chain.len() || !self.anchor.same(anchor, execution)? {
452            return Ok(false);
453        }
454        for (ours, theirs) in self.certificates.iter().zip(chain) {
455            execution
456                .charge_work(
457                    ours.tbs()
458                        .public_key()
459                        .as_bytes()
460                        .len()
461                        .max(theirs.tbs().public_key().as_bytes().len()) as u64,
462                )
463                .map_err(|reason| ours.tbs().subject().resource(reason))?;
464            if ours.tbs().public_key().as_bytes() != theirs.tbs().public_key().as_bytes()
465                || !ours
466                    .tbs()
467                    .subject()
468                    .matches(theirs.tbs().subject(), execution)?
469            {
470                return Ok(false);
471            }
472        }
473        Ok(true)
474    }
475
476    /// Whether a path would tell a reader what this one already told them:
477    /// the same anchor, and the same policies. What is worth keeping when
478    /// there is room for fewer paths than were found is one of each of
479    /// these, not the first ones found.
480    /// Both sets arrive in one order, which is what makes this a walk down
481    /// the two rather than a search of one for each member of the other:
482    /// the second is the square of a count the caller's policy ceiling
483    /// allows, and it is repeated against every path being held.
484    fn same_meaning(
485        &self,
486        anchor: Anchor<'a>,
487        policies: &[Oid<'a>],
488        execution: &Memory,
489    ) -> Result<bool> {
490        if !self.anchor.same(anchor, execution)? || self.policies.len() != policies.len() {
491            return Ok(false);
492        }
493        for (ours, theirs) in self.policies.iter().zip(policies) {
494            execution
495                .charge_work(ours.as_bytes().len().max(theirs.as_bytes().len()) as u64)
496                .map_err(|reason| self.anchor.name.resource(reason))?;
497            if ours != theirs {
498                return Ok(false);
499            }
500        }
501        Ok(true)
502    }
503}
504
505/// What the search found, and what it did not get to.
506#[derive(Debug)]
507pub struct Outcome<'a> {
508    paths: OwnedVec<Path<'a>>,
509    truncated: Option<Truncation>,
510}
511
512impl<'a> Outcome<'a> {
513    fn empty(execution: &Memory) -> Self {
514        Self {
515            paths: execution.vector(),
516            truncated: None,
517        }
518    }
519
520    /// The paths, shortest first, and among paths of one length in the order
521    /// the caller's inputs put them in.
522    #[must_use]
523    pub fn paths(&self) -> &[Path<'a>] {
524        &self.paths
525    }
526
527    /// Which bound stopped the search, where one did. `None` says the search
528    /// finished: every path there is, is here.
529    #[must_use]
530    pub fn truncated(&self) -> Option<Truncation> {
531        self.truncated
532    }
533
534    /// Whether the search was stopped rather than finished, which a report
535    /// must say rather than claim it enumerated everything.
536    #[must_use]
537    pub fn is_truncated(&self) -> bool {
538        self.truncated.is_some()
539    }
540}
541
542/// The interval the path is built for, in seconds from the epoch.
543///
544/// A signature is placed in an interval rather than at an instant, because
545/// what a timestamp proves is an upper bound and the lower one is usually
546/// unknown. A certificate takes part in a path only where it was valid
547/// across the whole of it: resolving at one end would let a signature made
548/// before a certificate existed pass on the strength of a later moment.
549///
550/// Seconds rather than a `Time`, because a `Time` is how a certificate wrote
551/// a moment, and this interval is not something a certificate wrote.
552#[derive(Debug, Clone, Copy, PartialEq, Eq)]
553pub struct Interval {
554    from: i64,
555    to: i64,
556}
557
558impl Interval {
559    /// The interval between two moments, whichever way round the caller
560    /// hands them: an interval is a pair of bounds, not an ordering.
561    #[must_use]
562    pub fn between(first: i64, second: i64) -> Self {
563        Self {
564            from: first.min(second),
565            to: first.max(second),
566        }
567    }
568
569    /// The interval that is one moment, which is what a caller has when the
570    /// signing time is known exactly and nothing wider has to be covered.
571    #[must_use]
572    pub fn at(moment: i64) -> Self {
573        Self {
574            from: moment,
575            to: moment,
576        }
577    }
578
579    /// The earlier bound.
580    #[must_use]
581    pub fn from(self) -> i64 {
582        self.from
583    }
584
585    /// The later bound.
586    #[must_use]
587    pub fn to(self) -> i64 {
588        self.to
589    }
590
591    /// Whether a validity interval holds the whole of this one.
592    fn inside(self, validity: Validity) -> bool {
593        // These endpoints are ordinary POSIX labels. Zero nanoseconds always
594        // fits Instant; compare lossless labels so :60 cannot alias :59.
595        let from = crate::temporal::Instant::new(self.from, 0).expect("zero nanoseconds fits");
596        let to = crate::temporal::Instant::new(self.to, 0).expect("zero nanoseconds fits");
597        validity.not_before().instant() <= from && to <= validity.not_after().instant()
598    }
599}
600
601/// What the caller was asking about, before any certificate was read.
602///
603/// The defaults are a validator with no policy of its own: it asks what the
604/// authorities agreed on rather than whether they agreed on one thing, and
605/// reads what the certificates say rather than overriding it. A caller with
606/// a policy of its own says so here, and gets paths that satisfy it or none.
607#[derive(Debug, Clone, Copy)]
608pub struct Policy<'a> {
609    /// The policies the caller is asking about. Empty asks about all of
610    /// them, and a path then carries whatever its authorities agreed on.
611    pub wanted: &'a [Oid<'a>],
612    /// Whether every path must name a policy, rather than only those an
613    /// authority along the way demanded it of.
614    pub explicit: bool,
615    /// Whether a policy one authority maps to another's is honoured.
616    pub mapping: bool,
617    /// Whether the identifier standing for any policy is read as the
618    /// certificate meant it.
619    pub any: bool,
620}
621
622impl Default for Policy<'_> {
623    fn default() -> Self {
624        Self {
625            wanted: &[],
626            explicit: false,
627            mapping: true,
628            any: true,
629        }
630    }
631}
632
633/// What the search charges for the checks it runs, so that a pool somebody
634/// else controls cannot buy an unbounded amount of them. The numbers are
635/// relative to each other rather than to any clock: a signature check is
636/// what a path spends most of its budget on, and a name comparison is a
637/// walk over two names.
638mod cost {
639    /// Reading an extension of a certificate the search is considering.
640    pub(super) const EXTENSION: u64 = 8;
641    /// Reaching for two names to compare them, before what they hold.
642    pub(super) const NAME: u64 = 16;
643    /// How many bytes of the two names one unit of work buys where they are
644    /// compared. Comparing them reads both: the parts of a name holding
645    /// several attributes are ordered against each other, and values that
646    /// are not byte-identical are folded through to the end. What that
647    /// costs is the size of what a pool somebody else wrote put there, so
648    /// it is charged by that size rather than at a flat rate.
649    pub(super) const COMPARED: u64 = 16;
650    /// Asking the verifier about one signature.
651    pub(super) const SIGNATURE: u64 = 1_024;
652    /// Holding one certificate to the constraints above it.
653    pub(super) const CHECK: u64 = 32;
654    /// One node of a path's working out of what it was issued under.
655    pub(super) const POLICY: u64 = 4;
656    /// Looking at one entry of a list a document decides the length of: a
657    /// policy a certificate names, a mapping it declares, a region an
658    /// authority wrote, a node of the working out being indexed.
659    ///
660    /// Charged per entry rather than per list, because the length is what
661    /// somebody else chose. What the entry holds is charged where it is
662    /// read, which for most of these is a lookup in an index and nothing
663    /// more.
664    pub(super) const ENTRY: u64 = 4;
665    /// How many bytes of a certificate one unit of work buys where the whole
666    /// of it is read, which is where its identity is taken.
667    pub(super) const HASHED: u64 = 64;
668}
669
670/// Everything the search asks of the caller: what is trusted, when, how far
671/// to look, what is being asked about, and who answers the questions this
672/// crate does not.
673///
674/// One value rather than a row of arguments, because these travel together:
675/// a path built against other anchors, or for another interval, is another
676/// question rather than the same one asked differently.
677pub struct Context<'a, 'p, V: Verify, W: Watch, R: Recognizer> {
678    /// The current operation's shared execution and storage domain.
679    /// Retained certificate accounts never implicitly finance this search.
680    pub execution: &'p Memory,
681    /// The anchors a path may end at, in the order a report should prefer.
682    pub anchors: &'p [Anchor<'a>],
683    /// The interval the path is built for.
684    pub interval: Interval,
685    /// How far the search may go before it stops and says so.
686    pub bounds: Bounds,
687    /// What the caller is asking about the policies a path was issued under.
688    pub policy: Policy<'a>,
689    /// Who checks a signature.
690    pub verifier: &'p V,
691    /// Who says the time the caller allowed has passed.
692    pub watch: &'p W,
693    /// Which extensions a scheme understands beyond the ones this crate
694    /// reads, since a critical extension nobody understood is a certificate
695    /// no path goes through.
696    pub recognizer: &'p R,
697}
698
699/// The state a search carries, so the bounds are counted in one place.
700struct Search<'a, 'p, V: Verify, W: Watch, R: Recognizer> {
701    execution: &'p Memory,
702    /// The candidates as the caller supplied them, unread until a path
703    /// needs one.
704    supplied: &'p [&'a Certificate<'a>],
705    /// The certificate the question is about, which is not a candidate
706    /// issuer of itself.
707    target: &'a Certificate<'a>,
708    /// The candidates folded to one each, worked out the first time the
709    /// search looks for an issuer.
710    ///
711    /// Not before then: a target an anchor issued is settled by the anchors
712    /// alone, and reading a pool of certificates no path goes through would
713    /// spend the budget that answer needs before the answer is reached. A
714    /// document may carry any number of them, so that is a path a caller
715    /// holds the whole of being reported as left out.
716    pool: Option<OwnedVec<&'a Certificate<'a>>>,
717    anchors: &'p [Anchor<'a>],
718    interval: Interval,
719    bounds: Bounds,
720    policy: Policy<'a>,
721    verifier: &'p V,
722    watch: &'p W,
723    recognizer: &'p R,
724    visited: usize,
725    edges: usize,
726    spent: u64,
727    /// The bound that ended the search, where one did.
728    halted: Option<Truncation>,
729    /// What a bound left out without ending the search.
730    noted: Option<Truncation>,
731    found: OwnedVec<Path<'a>>,
732    /// What the verifier has already said, so that a subpath shared by many
733    /// paths costs one check rather than one per path. Two certificates
734    /// stand for one answer here by where their bytes are, since that is
735    /// what was handed to the verifier; a second copy of one certificate is
736    /// a second entry and not a wrong one.
737    signatures: OwnedMap<(usize, usize, usize), Verified>,
738    /// What each certificate says about itself, which does not depend on
739    /// where in a path it sits. A cross-certified pool reaches the same
740    /// certificate at many depths and on many chains, and reading its
741    /// extensions again each time would charge a caller once per visit for
742    /// an answer that cannot have changed.
743    properties: OwnedMap<usize, Properties>,
744}
745
746/// What one certificate says about itself, worked out once.
747#[derive(Debug, Clone, Copy)]
748struct Properties {
749    /// Whether it can stand in a path at all: valid across the interval, and
750    /// carrying no critical extension nobody understood.
751    usable: bool,
752    /// What it says about issuing certificates, or `None` where it says it
753    /// issues none.
754    issues: Option<crate::constraints::BasicConstraints>,
755    /// Whether it was issued to the name that issued it.
756    self_issued: bool,
757    /// Whether it is an anchor's own certificate: it carries the name and
758    /// key of one, and signs itself. Both, because a certificate carrying an
759    /// anchor's identity under somebody else's signature is a link to that
760    /// anchor rather than the anchor.
761    publishes_itself: bool,
762}
763
764impl<V: Verify, W: Watch, R: Recognizer> Meter for Search<'_, '_, V, W, R> {
765    fn spend(&mut self, work: u64) -> Result<bool> {
766        Self::spend(self, work)
767    }
768}
769
770impl<V: Verify, W: Watch, R: Recognizer> Search<'_, '_, V, W, R> {
771    /// Charges work, and says whether the search may go on.
772    fn spend(&mut self, work: u64) -> Result<bool> {
773        debug_assert!(self.spent <= self.bounds.work);
774        if work > self.bounds.work - self.spent {
775            self.stop(Truncation::Work);
776            return Ok(false);
777        }
778        self.execution
779            .charge_work(work)
780            .map_err(|reason| self.target.tbs().subject().resource(reason))?;
781        self.spent += work;
782        if self.watch.out_of_time() {
783            self.stop(Truncation::Time);
784            return Ok(false);
785        }
786        Ok(true)
787    }
788
789    /// Charges for comparing two names, by what comparing them reads.
790    ///
791    /// Before the comparison rather than after it: a bound that is charged
792    /// once the work is done is a bound the last comparison was never held
793    /// to, and a pool of long names is a set of last comparisons.
794    fn spend_names(&mut self, left: &Name<'_>, right: &Name<'_>) -> Result<bool> {
795        // Admit the metadata scan before finding the widest RDN. Both counts
796        // are bounded by their borrowed encodings; their sum fits u64.
797        let parts = left.parts().len() as u64 + right.parts().len() as u64;
798        if !self.spend(parts)? {
799            return Ok(false);
800        }
801        let bytes = left.as_bytes().len() as u64 + right.as_bytes().len() as u64;
802        let rounds = sorting_rounds(left).max(sorting_rounds(right));
803        let work = rounds
804            .checked_mul(bytes / cost::COMPARED)
805            .and_then(|work| work.checked_add(cost::NAME))
806            .ok_or_else(|| left.resource(structured_asn1::memory::MemoryError::WorkExceeded))?;
807        self.spend(work)
808    }
809
810    /// Local policy-tree bounds truncate; aggregate resource failures abort.
811    fn policy<T>(
812        &mut self,
813        result: core::result::Result<T, policy::Overflow>,
814    ) -> Result<Option<T>> {
815        match result {
816            Ok(value) => Ok(Some(value)),
817            Err(policy::Overflow::Limit) => {
818                self.stop(Truncation::Policies);
819                Ok(None)
820            }
821            Err(policy::Overflow::Resource(error)) => Err(error),
822        }
823    }
824
825    /// Records which bound stopped the search, keeping the first one: it is
826    /// the one that decided the answer.
827    fn stop(&mut self, at: Truncation) {
828        // Two kinds of bound, kept apart because they are two statements. A
829        // bound that ends the whole search decides the answer and is what
830        // the answer reports; one that ended a branch or left a path out is
831        // worth saying only where nothing ended the search. Keeping one
832        // field for both would let the first branch to run out of depth
833        // swallow the count of certificates that later stopped everything,
834        // and the search would carry on past a bound it had reached while
835        // naming the wrong reason for what it did not do.
836        let recorded = if at.halts() {
837            &mut self.halted
838        } else {
839            &mut self.noted
840        };
841        if recorded.is_none() {
842            *recorded = Some(at);
843        }
844    }
845
846    /// Whether a bound has ended the search.
847    ///
848    /// Running out of room for paths is not one of them: what is worth
849    /// keeping is decided when a path is settled rather than by which was
850    /// found first, so a search that has filled its room keeps looking for
851    /// something better to put in it, under the bounds that remain.
852    fn stopped(&self) -> bool {
853        self.halted.is_some()
854    }
855
856    /// What the answer says about being incomplete: the bound that ended the
857    /// search where one did, and otherwise what was left out along the way.
858    fn truncated(&self) -> Option<Truncation> {
859        self.halted.or(self.noted)
860    }
861
862    /// Asks the verifier about one signature, or repeats what it said about
863    /// the same one before. `None` says the budget ran out before it could
864    /// be asked, which is not an answer about the signature.
865    ///
866    /// The charge is here rather than at the call sites, and only where the
867    /// verifier is actually reached. Repeating what is already known costs a
868    /// lookup, and charging a cryptographic check for it would undo what
869    /// remembering the answer was for: a sub-path shared by many chains
870    /// would spend the budget once per chain that walks it, and the search
871    /// would stop before reaching paths it had already done the work for.
872    fn verified(
873        &mut self,
874        certificate: &Certificate<'_>,
875        key: WorkingKey<'_>,
876    ) -> BuildResult<Option<Verified>, V::Error, R::Error> {
877        // The parameters are part of what was asked, not only the key: one
878        // key standing in two different sets of inherited parameters is two
879        // questions, and answering the second from the first would carry an
880        // answer across paths that do not share what the key stands in.
881        let at = (
882            certificate.signed_bytes().as_ptr() as usize,
883            key.key().as_bytes().as_ptr() as usize,
884            key.parameters().map_or(0, |held| held.as_ptr() as usize),
885        );
886        if let Some(answer) = self
887            .signatures
888            .get(&at, self.execution)
889            .map_err(|reason| certificate.tbs().subject().resource(reason))?
890        {
891            return Ok(Some(*answer));
892        }
893        if !self.spend(cost::SIGNATURE)? {
894            return Ok(None);
895        }
896        // Admit the cache allocation before invoking the external verifier.
897        self.signatures
898            .try_insert(at, Verified::Unsupported)
899            .map_err(|reason| certificate.tbs().subject().resource(reason))?;
900        let answer = self
901            .verifier
902            .verify(
903                &certificate.signature_algorithm(),
904                key,
905                certificate.signed_bytes(),
906                certificate.signature(),
907                self.execution,
908            )
909            .map_err(BuildError::Verification)?;
910        *self
911            .signatures
912            .get_mut(&at, self.execution)
913            .map_err(|reason| certificate.tbs().subject().resource(reason))?
914            .expect("the admitted signature cache entry") = answer;
915        Ok(Some(answer))
916    }
917}
918
919/// Admits anchor-folding work before mutation in both local and aggregate budgets.
920fn spend_anchor(
921    context: &Context<'_, '_, impl Verify, impl Watch, impl Recognizer>,
922    spent: &mut u64,
923    halted: &mut Option<Truncation>,
924    origin: &Name<'_>,
925    work: u64,
926) -> Result<bool> {
927    debug_assert!(*spent <= context.bounds.work);
928    if work > context.bounds.work - *spent {
929        *halted = Some(Truncation::Work);
930        return Ok(false);
931    }
932    if context.watch.out_of_time() {
933        *halted = Some(Truncation::Time);
934        return Ok(false);
935    }
936    context
937        .execution
938        .charge_work(work)
939        .map_err(|reason| origin.resource(reason))?;
940    *spent += work;
941    Ok(true)
942}
943
944/// The anchors a search will look at, with the repeats among the caller's
945/// folded away, and what folding them spent.
946///
947/// Two anchors of one name and one key are one anchor, and the paths to them
948/// are one path. A trust context assembled from several stores hands the same
949/// root over more than once, and every copy would buy an edge and a name
950/// comparison to settle a path that was already settled, so a bound would
951/// report the answer as truncated over nothing that was left out.
952///
953/// Folded by what makes two anchors one, which is the same name and the same
954/// key however the name was written, and the same certificate or none behind
955/// both. Folding by the bytes of the name instead would leave one key under
956/// two spellings as two anchors, and placed in front of a key that does
957/// verify they can spend a tight bound before it is reached: the path that
958/// exists is then not returned, which is a lost answer rather than a charge.
959///
960/// The keys are grouped first, because they are compared as bytes and a trust
961/// store's are all different: an anchor is looked at once, and the comparison
962/// that reads two names runs only where a key was supplied twice, which is
963/// the case being folded. Comparing every pair would be the square of a count
964/// for the sake of the pairs that cannot match.
965fn fold_anchors<'a>(
966    context: &Context<'a, '_, impl Verify, impl Watch, impl Recognizer>,
967    spent: &mut u64,
968    halted: &mut Option<Truncation>,
969) -> Result<OwnedVec<Anchor<'a>>> {
970    let mut keyed: OwnedMap<&[u8], OwnedVec<usize>> = context.execution.map();
971    let mut anchors: OwnedVec<Anchor<'a>> = context.execution.vector();
972    'anchors: for anchor in context.anchors {
973        let key = anchor.key().as_bytes();
974        if !spend_anchor(
975            context,
976            spent,
977            halted,
978            anchor.name(),
979            cost::CHECK + key.len() as u64 / cost::HASHED,
980        )? {
981            break;
982        }
983
984        let fail = |reason| anchor.name().resource(reason);
985        if keyed.get(&key, context.execution).map_err(fail)?.is_none() {
986            keyed
987                .try_insert(key, context.execution.vector())
988                .map_err(fail)?;
989        }
990        let group = keyed
991            .get_mut(&key, context.execution)
992            .map_err(fail)?
993            .expect("the group was inserted before lookup");
994        for at in group.iter() {
995            let theirs: &Name<'_> = anchors[*at].name();
996            let bytes = (theirs.as_bytes().len() as u64)
997                .checked_add(anchor.name().as_bytes().len() as u64)
998                .ok_or_else(|| {
999                    anchor
1000                        .name()
1001                        .resource(structured_asn1::memory::MemoryError::WorkExceeded)
1002                })?;
1003            if !spend_anchor(
1004                context,
1005                spent,
1006                halted,
1007                anchor.name(),
1008                cost::NAME + bytes / cost::COMPARED,
1009            )? {
1010                break 'anchors;
1011            }
1012            if !theirs.matches(anchor.name(), context.execution)? {
1013                continue;
1014            }
1015
1016            // The names and the key agree, and one thing is left that tells
1017            // two such anchors apart: what each was published in. A trust
1018            // context that supplied the anchor as a constrained certificate
1019            // bound the names below it, and the same name and key supplied
1020            // without one bound nothing. They are two statements about one
1021            // key, and folding them would let the order of the caller's list
1022            // decide which constraint holds and so whether a path exists at
1023            // all.
1024            let held = anchors[*at].certificate();
1025            let bytes = published_bytes(held)
1026                .checked_add(published_bytes(anchor.certificate()))
1027                .ok_or_else(|| {
1028                    anchor
1029                        .name()
1030                        .resource(structured_asn1::memory::MemoryError::WorkExceeded)
1031                })?;
1032            if !spend_anchor(
1033                context,
1034                spent,
1035                halted,
1036                anchor.name(),
1037                cost::CHECK + bytes / cost::HASHED,
1038            )? {
1039                break 'anchors;
1040            }
1041            if published_alike(held, anchor.certificate(), context.execution)? {
1042                continue 'anchors;
1043            }
1044        }
1045        group.try_push(anchors.len()).map_err(fail)?;
1046        anchors.try_push(*anchor).map_err(fail)?;
1047    }
1048    Ok(anchors)
1049}
1050
1051/// The candidates of a pool, each of them once and the target not among
1052/// them.
1053///
1054/// A pool that holds one certificate twice holds one certificate, and folding
1055/// the copies before the search rather than at each step is what makes that
1056/// true of what the search spends as well as of what it finds. A pool
1057/// somebody else wrote may repeat a certificate leading nowhere as often as
1058/// it likes, and charging every copy would let the copies spend the search
1059/// before the issuer that does lead somewhere is reached.
1060///
1061/// The folding is itself charged, because it is itself work somebody else
1062/// decides the size of: the identity of a certificate is its bytes, and there
1063/// may be any number of certificates of any length.
1064fn fold_pool<'a, V: Verify, W: Watch, R: Recognizer>(
1065    search: &mut Search<'a, '_, V, W, R>,
1066    pool: &[&'a Certificate<'a>],
1067    target: &'a Certificate<'a>,
1068) -> BuildResult<OwnedVec<&'a Certificate<'a>>, V::Error, R::Error> {
1069    let mut named: OwnedMap<usize, ()> = search.execution.map();
1070    let mut seen: OwnedMap<&[u8], ()> = search.execution.map();
1071    let mut unique = search.execution.vector();
1072    for candidate in pool {
1073        let bytes = candidate.as_bytes();
1074
1075        // Looking at a candidate at all, which every one of them costs.
1076        if !search.spend(cost::CHECK)? {
1077            break;
1078        }
1079
1080        // A pool that names one certificate over and over names it once,
1081        // and recognising that costs a pointer. Reading the whole encoding
1082        // is what telling a separately written copy from it costs, and
1083        // charging that for every repeat lets the repeats spend the search
1084        // before the issuer that does lead somewhere is reached.
1085        if named
1086            .try_insert(bytes.as_ptr() as usize, ())
1087            .map_err(|reason| candidate.tbs().subject().resource(reason))?
1088            .is_some()
1089        {
1090            continue;
1091        }
1092        if !search.spend(bytes.len() as u64 / cost::HASHED)? {
1093            break;
1094        }
1095
1096        // The target is not a candidate issuer of itself, and a caller who
1097        // put it here was told that changes nothing. Leaving it among the
1098        // candidates makes that false of what the search spends: the cycle
1099        // check refuses it, but only after an edge and a name comparison
1100        // have been charged for it, so a bound tight enough to notice
1101        // reports the answer as truncated over a certificate that could
1102        // never have been followed.
1103        search
1104            .execution
1105            .charge_work(bytes.len().max(target.as_bytes().len()) as u64)
1106            .map_err(|reason| candidate.tbs().subject().resource(reason))?;
1107        if bytes != target.as_bytes()
1108            && seen
1109                .try_insert(bytes, ())
1110                .map_err(|reason| candidate.tbs().subject().resource(reason))?
1111                .is_none()
1112        {
1113            unique
1114                .try_push(*candidate)
1115                .map_err(|reason| candidate.tbs().subject().resource(reason))?;
1116        }
1117    }
1118    Ok(unique)
1119}
1120
1121/// Builds the paths from one certificate to the anchors the caller trusts.
1122///
1123/// The pool is where issuers are looked for, and holding the target itself
1124/// changes nothing: a certificate never appears twice in one path
1125/// (RFC 5280 6.1), so it cannot be its own issuer.
1126///
1127/// # Errors
1128///
1129/// A spent budget, which says this run gave up rather than that the
1130/// certificates are wrong.
1131pub fn build<'a, V: Verify, W: Watch, R: Recognizer>(
1132    target: &'a Certificate<'a>,
1133    pool: &[&'a Certificate<'a>],
1134    context: &Context<'a, '_, V, W, R>,
1135) -> BuildResult<Outcome<'a>, V::Error, R::Error> {
1136    // A path ends at an anchor, so a caller who named none has asked a
1137    // question whose complete answer is no paths. Reading the pool to find
1138    // that out spends a budget on work that cannot change the answer, and a
1139    // bound reached while doing it would report the one conclusive answer
1140    // there is as though something had been left out, which reads to a
1141    // caller as worth asking again.
1142    if context.anchors.is_empty() {
1143        return Ok(Outcome::empty(context.execution));
1144    }
1145
1146    // And a path is built for a moment. A target the caller's interval does
1147    // not hold is not one any path can end at, whatever the anchors and the
1148    // pool say, so folding them to find that out is the same spending on an
1149    // answer that cannot change. The question is asked again where every
1150    // certificate of a path is held to it, and asking it here first is what
1151    // keeps a bound from calling this conclusive answer a partial one.
1152    if !context.interval.inside(target.tbs().validity()) {
1153        return Ok(Outcome::empty(context.execution));
1154    }
1155
1156    let mut spent = 0u64;
1157    let mut halted = None;
1158    let anchors = fold_anchors(context, &mut spent, &mut halted)?;
1159    if halted.is_some() {
1160        return Ok(Outcome {
1161            paths: context.execution.vector(),
1162            truncated: halted,
1163        });
1164    }
1165
1166    let mut search = Search {
1167        execution: context.execution,
1168        supplied: pool,
1169        target,
1170        pool: None,
1171        anchors: &anchors,
1172        interval: context.interval,
1173        bounds: context.bounds,
1174        policy: context.policy,
1175        verifier: context.verifier,
1176        watch: context.watch,
1177        recognizer: context.recognizer,
1178        visited: 0,
1179        edges: 0,
1180        spent,
1181        halted,
1182        noted: None,
1183        found: context.execution.vector(),
1184        signatures: context.execution.map(),
1185        properties: context.execution.map(),
1186    };
1187
1188    // The certificate an anchor was published in is not a step on a path to
1189    // that anchor: "when the trust anchor is provided in the form of a
1190    // self-signed certificate, this self-signed certificate is not included
1191    // as part of the prospective certification path" (RFC 5280 6.1). That
1192    // holds of the first position as much as of the rest, and the rest
1193    // already keep it. Settling such a target reports the anchor as issued
1194    // by itself, which is the anchor named twice rather than a chain of
1195    // authority, and it is what a caller asking about a root would read as
1196    // the root having been certified by somebody.
1197    //
1198    // A self-signed certificate can chain nowhere else, since the only name
1199    // that issued it is its own, so there is nothing further to look for
1200    // and the empty answer is the whole of it.
1201    let known = properties(&mut search, target)?;
1202    let mut chain = context.execution.vector();
1203    if known.usable && !known.publishes_itself {
1204        walk(&mut search, target, &mut chain)?;
1205    }
1206
1207    // Shortest first: a longer path to the same place says the same thing
1208    // through more parties, and a reader reads the first one. Among paths
1209    // of one length the order is the one the caller's inputs put them in,
1210    // which is what makes the same inputs give the same answer twice.
1211    // Include the discovery position in the comparison so the allocation-free
1212    // heap sort preserves the documented order among equal-length paths.
1213    let mut ordered = context.execution.vector();
1214    let found = core::mem::replace(&mut search.found, context.execution.vector());
1215    for (position, path) in found.into_iter().enumerate() {
1216        ordered
1217            .try_push((position, path))
1218            .map_err(|reason| target.tbs().subject().resource(reason))?;
1219    }
1220    ordered
1221        .try_sort_unstable_by(|left, right| {
1222            Ok::<_, structured_asn1::memory::MemoryError>(
1223                (left.1.len(), left.0).cmp(&(right.1.len(), right.0)),
1224            )
1225        })
1226        .map_err(|error| target.tbs().subject().resource(error.into()))?;
1227    for (_, path) in ordered {
1228        search
1229            .found
1230            .try_push(path)
1231            .map_err(|reason| target.tbs().subject().resource(reason))?;
1232    }
1233    let truncated = search.truncated();
1234    Ok(Outcome {
1235        paths: search.found,
1236        truncated,
1237    })
1238}
1239
1240/// Follows one certificate up: to every anchor that could have issued it,
1241/// and to every certificate in the pool that could have.
1242fn walk<'a, V: Verify, W: Watch, R: Recognizer>(
1243    search: &mut Search<'a, '_, V, W, R>,
1244    certificate: &'a Certificate<'a>,
1245    chain: &mut OwnedVec<&'a Certificate<'a>>,
1246) -> BuildResult<(), V::Error, R::Error> {
1247    // One candidate cursor per active certificate replaces recursive DFS.
1248    // Both stacks are admitted by the request domain before their growth.
1249    let mut cursors = search.execution.vector();
1250    let mut entering = certificate;
1251    'enter: loop {
1252        if search.stopped() {
1253            break;
1254        }
1255        if search.visited >= search.bounds.visited {
1256            search.stop(Truncation::Visited);
1257            break;
1258        }
1259        search.visited += 1;
1260        if !search.spend(cost::CHECK)? {
1261            break;
1262        }
1263        if chain.len() >= search.bounds.depth {
1264            search.stop(Truncation::Depth);
1265            break;
1266        }
1267        chain
1268            .try_push(entering)
1269            .map_err(|reason| entering.tbs().subject().resource(reason))?;
1270        cursors
1271            .try_push(0usize)
1272            .map_err(|reason| entering.tbs().subject().resource(reason))?;
1273        settle(search, entering, chain)?;
1274
1275        loop {
1276            if search.stopped() {
1277                break 'enter;
1278            }
1279            let current = *chain.last().expect("the active DFS certificate");
1280            let cursor = cursors.last_mut().expect("its candidate cursor");
1281            if let Some(candidate) = next_issuer(
1282                search,
1283                current,
1284                chain,
1285                chain.len() >= search.bounds.depth,
1286                cursor,
1287            )? {
1288                entering = candidate;
1289                continue 'enter;
1290            }
1291            chain.pop();
1292            cursors.pop();
1293            if chain.is_empty() {
1294                break 'enter;
1295            }
1296        }
1297    }
1298    chain.clear();
1299    Ok(())
1300}
1301
1302/// Ends the chain at every anchor that issued the certificate on top of it,
1303/// which is where a path becomes one.
1304fn settle<'a, V: Verify, W: Watch, R: Recognizer>(
1305    search: &mut Search<'a, '_, V, W, R>,
1306    certificate: &'a Certificate<'a>,
1307    chain: &[&'a Certificate<'a>],
1308) -> BuildResult<(), V::Error, R::Error> {
1309    for at in 0..search.anchors.len() {
1310        let anchor = search.anchors[at];
1311        if search.stopped() {
1312            break;
1313        }
1314        if search.edges >= search.bounds.edges {
1315            search.stop(Truncation::Edges);
1316            break;
1317        }
1318        search.edges += 1;
1319        if !search.spend_names(certificate.tbs().issuer(), anchor.name())? {
1320            break;
1321        }
1322        if !certificate
1323            .tbs()
1324            .issuer()
1325            .matches(anchor.name(), search.execution)?
1326        {
1327            continue;
1328        }
1329        // The signature is checked where the path is walked from the anchor
1330        // down, since that is where the parameters a key may stand in are
1331        // known. Nothing is lost by not asking here: this is the last edge
1332        // of the path, so the check is one step away either way.
1333        let Some(policies) = validate(search, chain, anchor)? else {
1334            continue;
1335        };
1336        keep(search, chain, anchor, policies)?;
1337    }
1338    Ok(())
1339}
1340
1341/// Puts a settled path among the ones that will be returned, where there is
1342/// room for it or where what it says is not already there.
1343///
1344/// A repeat of a route already held is dropped and is not truncation: it is
1345/// the same path spelled through a re-issued certificate, and nothing was
1346/// lost by not showing it twice. Dropping a path that does say something
1347/// else is truncation, and so is making room for one by putting out a
1348/// repeat of something already shown.
1349/// The chain is held rather than copied until there is somewhere to put it:
1350/// a cross-certified pool settles the same route many times over, and a copy
1351/// made before the question is asked is a copy made for every one of them.
1352fn keep<'a, V: Verify, W: Watch, R: Recognizer>(
1353    search: &mut Search<'a, '_, V, W, R>,
1354    chain: &[&'a Certificate<'a>],
1355    anchor: Anchor<'a>,
1356    policies: OwnedVec<Oid<'a>>,
1357) -> BuildResult<(), V::Error, R::Error> {
1358    // Telling this path from the ones already held reads their names, the
1359    // keys under them and their policies again, once per path held, and how
1360    // long a name or a key encoding is is the pool's to decide. Both are
1361    // read from the front, so two of one length that part near the end are
1362    // read almost to the end. The charge is taken for the whole scan before
1363    // it runs.
1364    //
1365    // Obeyed where there is anything to compare against: a charge that the
1366    // budget cannot meet is the answer that this scan is not going to
1367    // happen, and running it anyway is the reading the charge exists to
1368    // stop. What is then not known is whether this route says what a held
1369    // one already says, so it is not shown, and the answer is marked
1370    // truncated by the charge that failed.
1371    //
1372    // Where nothing is held there is nothing to compare and no scan to
1373    // refuse. The first path a search settles is kept whatever the budget
1374    // says, since dropping it would lose an answer for work nobody was
1375    // going to do.
1376    let held = search.found.len() as u64;
1377    if held > 0 {
1378        if !search.spend(chain.len() as u64)? {
1379            return Ok(());
1380        }
1381        let overflow = || {
1382            anchor
1383                .name
1384                .resource(structured_asn1::memory::MemoryError::WorkExceeded)
1385        };
1386        let mut read = 0u64;
1387        for certificate in chain {
1388            let tbs = certificate.tbs();
1389            let bytes =
1390                tbs.subject().as_bytes().len() as u64 + tbs.public_key().as_bytes().len() as u64;
1391            read = read.checked_add(bytes).ok_or_else(overflow)?;
1392        }
1393        let each = (read / cost::COMPARED)
1394            .checked_add(cost::NAME)
1395            .and_then(|work| work.checked_add(policies.len() as u64))
1396            .ok_or_else(overflow)?;
1397        let work = each.checked_mul(held).ok_or_else(overflow)?;
1398        if !search.spend(work)? {
1399            return Ok(());
1400        }
1401    }
1402
1403    // The same route saying the same thing. A re-issued certificate is one
1404    // route spelled twice, but an authority that re-issued under another
1405    // policy said something else through it, and that is precisely the
1406    // distinct outcome several paths exist to preserve: dropping it as a
1407    // repeat would throw away the answer while reporting nothing missing.
1408    for held in &search.found {
1409        if held.same_route(chain, anchor, search.execution)?
1410            && held.same_meaning(anchor, &policies, search.execution)?
1411        {
1412            return Ok(());
1413        }
1414    }
1415    if search.found.len() < search.bounds.paths {
1416        let mut certificates = search.execution.vector();
1417        certificates
1418            .try_extend_from_slice(chain)
1419            .map_err(|reason| anchor.name.resource(reason))?;
1420        search
1421            .found
1422            .try_push(Path {
1423                certificates,
1424                anchor,
1425                policies,
1426            })
1427            .map_err(|reason| anchor.name.resource(reason))?;
1428        return Ok(());
1429    }
1430
1431    // No room. A path saying something none of the held ones say is worth
1432    // more than a second path saying what one of them already said, so it
1433    // takes the place of the last such repeat. Either way a path that was
1434    // found is not being returned, which the answer has to say.
1435    search.stop(Truncation::Paths);
1436    for held in &search.found {
1437        if held.same_meaning(anchor, &policies, search.execution)? {
1438            return Ok(());
1439        }
1440    }
1441    let mut repeat = None;
1442    for at in (0..search.found.len()).rev() {
1443        let candidate = &search.found[at];
1444        let mut count = 0;
1445        for held in &search.found {
1446            if held.same_meaning(candidate.anchor, &candidate.policies, search.execution)? {
1447                count += 1;
1448                if count > 1 {
1449                    break;
1450                }
1451            }
1452        }
1453        if count > 1 {
1454            repeat = Some(at);
1455            break;
1456        }
1457    }
1458    if let Some(at) = repeat {
1459        // The repeat is taken out and the new path put on the end, rather
1460        // than dropped into the slot the repeat held. Paths of one length
1461        // come back in the order the caller's inputs put them in, and the
1462        // sort that arranges them is by length alone: a path written into
1463        // an earlier slot would sit in front of paths found before it, and
1464        // nothing afterwards would move it back.
1465        let moves = core::mem::size_of_val(&search.found[at..]);
1466        search
1467            .execution
1468            .charge_work(moves as u64)
1469            .map_err(|reason| anchor.name.resource(reason))?;
1470        search.found[at..].rotate_left(1);
1471        search.found.pop();
1472        let mut certificates = search.execution.vector();
1473        certificates
1474            .try_extend_from_slice(chain)
1475            .map_err(|reason| anchor.name.resource(reason))?;
1476        search
1477            .found
1478            .try_push(Path {
1479                certificates,
1480                anchor,
1481                policies,
1482            })
1483            .map_err(|reason| anchor.name.resource(reason))?;
1484    }
1485    Ok(())
1486}
1487
1488/// Follows the chain further up: to every certificate in the pool that could
1489/// have issued the one on top of it.
1490///
1491/// `deepest` says the chain has reached the length the caller allowed, so
1492/// that a candidate found here is one the depth bound refuses to step into
1493/// rather than one to walk. It is what turns the bound into a report: the
1494/// answer says it was reached where a candidate was there to be refused,
1495/// and says nothing where the chain had nowhere to go regardless.
1496fn next_issuer<'a, V: Verify, W: Watch, R: Recognizer>(
1497    search: &mut Search<'a, '_, V, W, R>,
1498    certificate: &'a Certificate<'a>,
1499    chain: &[&'a Certificate<'a>],
1500    deepest: bool,
1501    at: &mut usize,
1502) -> BuildResult<Option<&'a Certificate<'a>>, V::Error, R::Error> {
1503    // The candidates, folded the first time one is looked for. Every later
1504    // position reads the same folded list.
1505    if search.pool.is_none() {
1506        let supplied = search.supplied;
1507        let target = search.target;
1508        search.pool = Some(fold_pool(search, supplied, target)?);
1509    }
1510    // By position rather than by iterator: what follows this borrows the
1511    // search to walk further up, and a candidate is one shared reference,
1512    // so reading it out ends the borrow the loop would otherwise hold.
1513    while let Some(candidate) = search.pool.as_ref().and_then(|pool| pool.get(*at)).copied() {
1514        *at += 1;
1515        if search.stopped() {
1516            break;
1517        }
1518        if search.edges >= search.bounds.edges {
1519            search.stop(Truncation::Edges);
1520            break;
1521        }
1522        search.edges += 1;
1523        if !search.spend_names(certificate.tbs().issuer(), candidate.tbs().subject())? {
1524            break;
1525        }
1526        // A certificate appears once in a path (RFC 5280 6.1), which is
1527        // also what keeps a cycle from being followed round.
1528        //
1529        // Asked of where the certificate is rather than of what it holds.
1530        // The pool was folded before the search so that no two candidates
1531        // carry the same bytes, and the target was taken out of it, so two
1532        // certificates of one chain hold the same bytes exactly when they
1533        // are the same one. Comparing the encodings would read both from
1534        // end to end for an answer their addresses already give, and a pool
1535        // of long re-issued certificates that part only near the end makes
1536        // that a full scan per candidate per position of the chain, where
1537        // the charge just taken covers two names. It is the identity the
1538        // rest of the search already works by: what a certificate says
1539        // about itself is remembered under the same address.
1540        let mut repeated = false;
1541        for held in chain {
1542            search
1543                .execution
1544                .charge_work(1)
1545                .map_err(|reason| certificate.tbs().subject().resource(reason))?;
1546            if core::ptr::eq(held.as_bytes(), candidate.as_bytes()) {
1547                repeated = true;
1548                break;
1549            }
1550        }
1551        if repeated {
1552            continue;
1553        }
1554        if !certificate
1555            .tbs()
1556            .issuer()
1557            .matches(candidate.tbs().subject(), search.execution)?
1558        {
1559            continue;
1560        }
1561        // Everything cheap first, and the signature last: a candidate that
1562        // could not have issued anything, or was not valid when it would
1563        // have had to be, is refused for what it says rather than for what
1564        // its key does, and the check that costs the most is the one a
1565        // hostile pool would most like to buy in quantity.
1566        //
1567        // The certificate an anchor was published in is not a link in a path
1568        // to that anchor: "when the trust anchor is provided in the form of
1569        // a self-signed certificate, this self-signed certificate is not
1570        // included as part of the prospective certification path"
1571        // (RFC 5280 6.1). Walking into it would produce the path that was
1572        // already found, spelled one certificate longer.
1573        //
1574        // Self-signed is the whole of that rule, and names are not enough to
1575        // establish it. A provider recognized under two schemes has its
1576        // identity certified by both, and an authority rolling its key over
1577        // certifies the new key with the old one: the first carries the
1578        // anchor's name and key under somebody else's signature, the second
1579        // carries one name on both sides under the old key's. Both are
1580        // ordinary links, and skipping either would lose a whole route while
1581        // saying nothing about having lost it.
1582        let known = properties(search, candidate)?;
1583        if known.publishes_itself || !known.usable || known.issues.is_none() {
1584            continue;
1585        }
1586        if deepest {
1587            // A candidate that names itself the issuer and can issue is a
1588            // branch the depth bound is refusing, and refusing it is what
1589            // the answer has to say. Whether its signature would have held
1590            // is exactly what the search does not get to find out, so the
1591            // check is not spent on a candidate it will not follow. Once
1592            // one is refused the rest say the same thing, and the search
1593            // has other branches to spend its budget on.
1594            search.stop(Truncation::Depth);
1595            break;
1596        }
1597        // The key is asked about here, where the answer prunes the branch: a
1598        // candidate that did not sign this certificate is not walked into,
1599        // and a pool of such candidates costs one check each rather than a
1600        // subtree each.
1601        //
1602        // It is asked as the certificate wrote it, since what a key standing
1603        // in parameters written above stands in is exactly what this search
1604        // has not found yet. So only a definite no prunes. A registry that
1605        // cannot judge a key on those terms says that it cannot rather than
1606        // saying no, and the branch is walked so the question can be put
1607        // again from the anchor down, where the parameters in force are
1608        // known. Refusing on anything short of a no would lose whole routes.
1609        //
1610        // Asking only where the key carries its own parameters would prune
1611        // almost nothing: an algorithm that takes none writes a null, which
1612        // is written the same way as omitting them, so a pool of ordinary
1613        // wrong-key authorities would be walked in full and could spend the
1614        // whole budget before the one that signed this certificate is
1615        // reached. What tells the two apart is the registry's answer, and
1616        // the registry is who this asks.
1617        let key = WorkingKey::standing(candidate.tbs().public_key());
1618        let Some(answer) = search.verified(certificate, key)? else {
1619            break;
1620        };
1621        if answer == Verified::No {
1622            continue;
1623        }
1624        return Ok(Some(candidate));
1625    }
1626    Ok(None)
1627}
1628
1629/// Whether two anchors were published the same way: in the same certificate,
1630/// or in none. It is the last thing that tells apart two anchors of one name
1631/// and one key, because the certificate an anchor was published in is what
1632/// says how the names below it are constrained.
1633fn published_alike(
1634    left: Option<&Certificate<'_>>,
1635    right: Option<&Certificate<'_>>,
1636    execution: &Memory,
1637) -> Result<bool> {
1638    match (left, right) {
1639        (None, None) => Ok(true),
1640        (Some(ours), Some(theirs)) => binds_alike(ours, theirs, execution),
1641        _ => Ok(false),
1642    }
1643}
1644
1645/// Whether two certificates of one name and one key say the same thing about
1646/// the names below them.
1647///
1648/// By what is read rather than by every byte. An anchor's certificate is not
1649/// a link in any path: the one thing the search takes from it is what it
1650/// says about the space below, which is the regions it names, and nothing
1651/// else about it is consulted anywhere. A trust store holding a root
1652/// re-issued with a new serial, a new validity or a new signature holds one
1653/// statement of trust written twice, and keeping both makes the search try
1654/// each of them at every position where an anchor could end a path: a tight
1655/// bound on edges is then spent on copies, and a path through the one that
1656/// matches is lost.
1657///
1658/// The one extension compared is therefore the one enforced. Basic
1659/// constraints were compared here while an anchor's regions were honoured
1660/// only under an asserted authority bit; they are not read of an anchor any
1661/// more, and comparing them would split anchors that behave identically.
1662fn binds_alike(
1663    ours: &Certificate<'_>,
1664    theirs: &Certificate<'_>,
1665    execution: &Memory,
1666) -> Result<bool> {
1667    if same(ours, theirs) {
1668        return Ok(true);
1669    }
1670    let ours = ours
1671        .tbs()
1672        .extensions()
1673        .get(crate::oid::NAME_CONSTRAINTS, execution)?;
1674    let theirs = theirs
1675        .tbs()
1676        .extensions()
1677        .get(crate::oid::NAME_CONSTRAINTS, execution)?;
1678    Ok(match (ours, theirs) {
1679        (None, None) => true,
1680        (Some(ours), Some(theirs)) => {
1681            ours.is_critical() == theirs.is_critical() && ours.value() == theirs.value()
1682        }
1683        _ => false,
1684    })
1685}
1686
1687/// How many times comparing a name may read it.
1688///
1689/// Once, where every part holds one attribute: the parts line up in the
1690/// order they were written and each pair is compared where it stands. A part
1691/// holding several is a set, whose order carries no meaning, so both sides
1692/// are put in order before they are lined up, and a sort of `n` reads its
1693/// input about `log2(n)` times over. The widest part decides it, since one
1694/// wide part is enough to pay for.
1695///
1696/// A document decides how many attributes a part holds, so this factor is
1697/// theirs to choose too: without it a name of one very wide part is charged
1698/// as though it were read straight through, and the sort runs to the end
1699/// with nothing left to stop it.
1700fn sorting_rounds(name: &Name<'_>) -> u64 {
1701    let widest = name
1702        .parts()
1703        .iter()
1704        .map(|part| part.attributes().len())
1705        .max()
1706        .unwrap_or(1)
1707        .max(1);
1708    u64::from(widest.ilog2()) + 1
1709}
1710
1711/// How many bytes comparing an anchor's published certificate reads on its
1712/// side, which is none where it was published as a name and a key.
1713fn published_bytes(certificate: Option<&Certificate<'_>>) -> u64 {
1714    certificate.map_or(0, |certificate| certificate.as_bytes().len() as u64)
1715}
1716
1717/// Whether two certificates are the same one: the bytes they arrived as. A
1718/// pool that holds one certificate twice holds one certificate.
1719fn same(left: &Certificate<'_>, right: &Certificate<'_>) -> bool {
1720    core::ptr::eq(left.as_bytes(), right.as_bytes()) || left.as_bytes() == right.as_bytes()
1721}
1722
1723/// Whether a certificate is one an anchor was published in: the same name
1724/// and the same key, however the trust context supplied the anchor itself.
1725fn publishes_anchor<V: Verify, W: Watch, R: Recognizer>(
1726    search: &mut Search<'_, '_, V, W, R>,
1727    certificate: &Certificate<'_>,
1728) -> BuildResult<bool, V::Error, R::Error> {
1729    let anchors = search.anchors;
1730    for anchor in anchors {
1731        if !search.spend_names(certificate.tbs().subject(), anchor.name())? {
1732            break;
1733        }
1734        if !certificate
1735            .tbs()
1736            .subject()
1737            .matches(anchor.name(), search.execution)?
1738        {
1739            continue;
1740        }
1741
1742        // The keys are compared byte for byte, and how long a key encoding
1743        // is is decided by whoever wrote the certificate. Two encodings of
1744        // one length that differ near the end are read to the end, and a
1745        // pool can hold a candidate for every anchor: charged at a flat
1746        // rate, one certificate and a handful of anchors buy the reading of
1747        // their product while the bound barely moves. The name comparison
1748        // above is charged by what it reads for the same reason, and this
1749        // is the other side of the same question.
1750        let key = certificate.tbs().public_key().as_bytes();
1751        let against = anchor.key().as_bytes();
1752        let read = (key.len() as u64 + against.len() as u64) / cost::COMPARED;
1753        if !search.spend(read)? {
1754            break;
1755        }
1756        if key == against {
1757            return Ok(true);
1758        }
1759    }
1760    Ok(false)
1761}
1762
1763/// What one certificate says about itself, read the first time it is seen
1764/// and repeated afterwards.
1765///
1766/// Every answer here is a property of the certificate and of the question
1767/// the caller asked, neither of which changes while a search runs, so the
1768/// second visit costs a lookup rather than the extensions again.
1769fn properties<'a, V: Verify, W: Watch, R: Recognizer>(
1770    search: &mut Search<'a, '_, V, W, R>,
1771    certificate: &'a Certificate<'a>,
1772) -> BuildResult<Properties, V::Error, R::Error> {
1773    let at = certificate.as_bytes().as_ptr() as usize;
1774    if let Some(known) = search
1775        .properties
1776        .get(&at, search.execution)
1777        .map_err(|reason| certificate.tbs().subject().resource(reason))?
1778    {
1779        return Ok(*known);
1780    }
1781    // Whether it names itself as its own issuer, which is two names of the
1782    // certificate compared, and comparing them reads both: a document
1783    // decides how long they are, so the charge is the size of what is read
1784    // and it is taken before the reading. Where there is nothing left to
1785    // spend the answer is no, which is safe for the same reason it is below:
1786    // a certificate not known to be self-issued is an ordinary link, and the
1787    // search that could not afford the question is one nothing will now be
1788    // built through.
1789    let self_issued = search
1790        .spend_names(certificate.tbs().subject(), certificate.tbs().issuer())?
1791        && self_issued(certificate, search.execution)?;
1792    let publishes_anchor = publishes_anchor(search, certificate)?;
1793    let issuing = issues(search, certificate)?;
1794    // "If the subject is a CA ... then the subject field MUST be populated
1795    // with a non-empty distinguished name matching the contents of the
1796    // issuer field ... in all certificates issued by the subject CA"
1797    // (RFC 5280 4.1.2.6). A certificate may carry its identity in the
1798    // alternative names and leave the subject empty, but not while claiming
1799    // to be an authority: there is then no name for anything below it to be
1800    // issued under, and nothing for a report to say a path leads to.
1801    //
1802    // On the asserted bit rather than on whether it may issue. Those are two
1803    // questions, and a certificate that asserts being an authority while
1804    // naming a key that may not sign certificates has still asserted it:
1805    // reading one from the other would let that spelling name nobody.
1806    //
1807    // Asked here rather than where a path holds each certificate to what it
1808    // says about issuing, because that is asked only of the certificates a
1809    // path is built through. The one the question is about is not among
1810    // them, since it need not be an authority at all, and this is a
1811    // certificate that says it is one.
1812    //
1813    // A certificate whose basic constraints did not read has not answered
1814    // whether it is one, so there is no answer for this to be held to and
1815    // the certificate stands nowhere.
1816    let named =
1817        issuing.is_some_and(|issuing| !issuing.asserted || !certificate.tbs().subject().is_empty());
1818    let usable = named && usable(search, certificate)?;
1819
1820    // Whether it signs itself, which is asked only of the certificates that
1821    // could be an anchor's own: it is the one question here that costs a
1822    // signature check, and the answer matters for nothing else.
1823    //
1824    // Asked last, and only of a certificate that could stand in a path at
1825    // all. A pool can put any number of expired copies of an anchor's own
1826    // certificate in front of the issuer that leads somewhere, and what
1827    // rules each of them out is what it says about itself, which costs
1828    // nothing to read. Asking the expensive question first would spend the
1829    // search on candidates already refused.
1830    //
1831    // Naming itself as its issuer is not the same as signing itself. An
1832    // authority rolling its key over certifies the new key with the old one,
1833    // and that certificate carries one name on both sides while being signed
1834    // by somebody else. It is the only route from the new key to the old
1835    // anchor, so reading the names alone would lose it.
1836    //
1837    // Charged like every other signature, because it is one: a pool can hold
1838    // any number of certificates that copy an anchor's name and key, and
1839    // asking the verifier about each of them for free would run the most
1840    // expensive check here as often as somebody else likes while the meter
1841    // recorded only the name comparisons. Where there is nothing left to
1842    // spend the answer is no, which is safe: the search has halted, and a
1843    // certificate not known to sign itself is treated as an ordinary link
1844    // that nothing will now be built through.
1845    let publishes_itself = usable
1846        && publishes_anchor
1847        && self_issued
1848        && search.verified(
1849            certificate,
1850            // Its own key and nothing above it: a certificate that signs
1851            // itself stands in whatever it wrote, and a key that omits its
1852            // parameters has nowhere to inherit them from here.
1853            WorkingKey::standing(certificate.tbs().public_key()),
1854        )? == Some(Verified::Yes);
1855
1856    let known = Properties {
1857        usable,
1858        issues: issuing.and_then(|issuing| issuing.constraints),
1859        self_issued,
1860        publishes_itself,
1861    };
1862    search
1863        .properties
1864        .try_insert(at, known)
1865        .map_err(|reason| certificate.tbs().subject().resource(reason))?;
1866    Ok(known)
1867}
1868
1869/// Whether a certificate can stand in a path at all: valid across the
1870/// interval, and carrying no critical extension nobody understood.
1871///
1872/// A malformed extension is not an error of this run, so the answer is no
1873/// rather than a refusal: another path may not go through this certificate.
1874fn usable<'a, V: Verify, W: Watch, R: Recognizer>(
1875    search: &mut Search<'a, '_, V, W, R>,
1876    certificate: &'a Certificate<'a>,
1877) -> BuildResult<bool, V::Error, R::Error> {
1878    if !search.spend(cost::CHECK)? {
1879        return Ok(false);
1880    }
1881    if !search.interval.inside(certificate.tbs().validity()) {
1882        return Ok(false);
1883    }
1884    // The critical extensions one at a time, charged before each is read
1885    // and stopping at the first demand nobody understood. Working out one
1886    // entry decodes its value, and how many entries there are and how much
1887    // each holds is a certificate's to decide: gathering them all first
1888    // reads the whole list at a fixed charge, and goes on reading it after
1889    // the answer is already no.
1890    //
1891    // The charge comes before the question, and the list is walked without
1892    // asking it, so that a budget already spent refuses the reading rather
1893    // than being told about it afterwards.
1894    let extensions = certificate.tbs().extensions();
1895    for demand in extensions.criticals(search.execution) {
1896        let demand = demand?;
1897        if !search.spend(cost::EXTENSION)? {
1898            return Ok(false);
1899        }
1900        if extensions.understands(demand, search.recognizer, search.execution)? {
1901            continue;
1902        }
1903        // One of those demands is this function's own subject. A critical
1904        // name-constraints extension counts as not understood where it
1905        // constrains a form nothing here matches names against, and that
1906        // reading is right for a reader that will not look at the names:
1907        // for one that will, the profile asks for the certificate to be
1908        // refused only where "an instance of that name form appears"
1909        // below it (RFC 5280 4.2.1.10), which is a question the search
1910        // answers per certificate rather than here. What it cannot do is
1911        // go on when the value did not parse at all, since then there is
1912        // no constraint to hold anything to.
1913        if demand.kind() == crate::oid::NAME_CONSTRAINTS {
1914            if !search.spend(cost::EXTENSION)? {
1915                return Ok(false);
1916            }
1917            if gate(crate::constraints::NameConstraints::read(
1918                demand,
1919                search.execution,
1920            ))?
1921            .is_some()
1922            {
1923                continue;
1924            }
1925        }
1926        return Ok(false);
1927    }
1928    Ok(true)
1929}
1930
1931/// What a certificate says about issuing certificates, both facts read from
1932/// the one extension.
1933///
1934/// The answer carries the constraints rather than a yes, because the same
1935/// extension holds how far below the authority a path may go and reading it
1936/// twice would charge a caller twice for one value.
1937#[derive(Debug, Clone, Copy, Default)]
1938struct Issuing {
1939    /// Whether the certificate asserts being an authority: the basic
1940    /// constraints are there and say so, whatever its key may be used for.
1941    ///
1942    /// Kept apart from the constraints below because the profile hangs a
1943    /// different rule on it. The requirement that an authority name
1944    /// somebody is tied to this bit (RFC 5280 4.1.2.6), and a certificate
1945    /// that asserts it while naming a key that may not sign certificates
1946    /// has still asserted it.
1947    asserted: bool,
1948    /// The constraints where the certificate may issue, and `None` where it
1949    /// says it does not, does not say, or names a key that is not for
1950    /// signing certificates (RFC 5280 6.1.4 (k) and (n)).
1951    constraints: Option<crate::constraints::BasicConstraints>,
1952}
1953
1954/// Reads both, charging the extensions once.
1955///
1956/// `None` where the certificate carries basic constraints this run could not
1957/// read: whether the subject is an authority is then unanswered, and the
1958/// requirement that an authority name somebody (RFC 5280 4.1.2.6) is hung on
1959/// that answer. Reading it as though the extension were absent answers no,
1960/// so a certificate with an empty subject passes a requirement its own
1961/// extension may have been asserting. The extension need not be critical for
1962/// this to matter, and a critical one is refused elsewhere, so this is where
1963/// the difference is kept.
1964fn issues<'a, V: Verify, W: Watch, R: Recognizer>(
1965    search: &mut Search<'a, '_, V, W, R>,
1966    certificate: &'a Certificate<'a>,
1967) -> BuildResult<Option<Issuing>, V::Error, R::Error> {
1968    let extensions = certificate.tbs().extensions();
1969    let Ok(carried) = read(search, |execution| extensions.basic_constraints(execution))?.enforced()
1970    else {
1971        return Ok(None);
1972    };
1973    let Some(basic) = carried else {
1974        return Ok(Some(Issuing::default()));
1975    };
1976    if !basic.is_authority() {
1977        return Ok(Some(Issuing::default()));
1978    }
1979    let asserted = Issuing {
1980        asserted: true,
1981        constraints: None,
1982    };
1983    if extensions
1984        .get(crate::oid::KEY_USAGE, search.execution)?
1985        .is_some()
1986    {
1987        let Some(usage) = read(search, |execution| extensions.key_usage(execution))?.value() else {
1988            return Ok(Some(asserted));
1989        };
1990        if !usage.key_cert_sign() {
1991            return Ok(Some(asserted));
1992        }
1993    }
1994    Ok(Some(Issuing {
1995        constraints: Some(basic),
1996        ..asserted
1997    }))
1998}
1999
2000/// Whether the chain, read down from the anchor, is a path: every
2001/// certificate within the names the ones above it allowed, under a policy
2002/// they agreed on, and inside the depth they permitted (RFC 5280 6.1.3 and
2003/// 6.1.4).
2004///
2005/// The answer carries what the path was issued under, because that is not a
2006/// property of any one certificate: it is what is left after every authority
2007/// along the path has narrowed it.
2008///
2009/// The chain is held with the target first, so it is read backwards: the
2010/// certificate the anchor issued is where the path starts.
2011fn validate<'a, V: Verify, W: Watch, R: Recognizer>(
2012    search: &mut Search<'a, '_, V, W, R>,
2013    chain: &[&'a Certificate<'a>],
2014    anchor: Anchor<'a>,
2015) -> BuildResult<Option<OwnedVec<Oid<'a>>>, V::Error, R::Error> {
2016    let length = chain.len();
2017    let mut space = NameSpace::new(search.execution);
2018    let Some(mut policies) = initial_policies(search, length)? else {
2019        // A caller who allowed the working out nothing at all has not asked
2020        // for a path settled without it.
2021        return Ok(None);
2022    };
2023
2024    // What the anchor says about the names below it. The anchor itself is
2025    // not a certificate of the path, but a trust context that published a
2026    // constrained root published the constraint with it, and a path that
2027    // ignored it would be a path the trust context did not allow.
2028    if let Some(certificate) = anchor.certificate()
2029        && !narrow_published(search, &mut space, certificate.tbs().extensions())?
2030    {
2031        return Ok(None);
2032    }
2033
2034    // "n", the number of certificates in the path (6.1.2 (k)): a path can
2035    // never spend more than it holds.
2036    let mut allowed = u32::try_from(length).unwrap_or(u32::MAX);
2037    let mut last_constraints = None;
2038
2039    // The key each certificate is checked with, carried down from the anchor
2040    // (RFC 5280 6.1.2 (c)). The anchor's own key stands on its own: there is
2041    // nothing above a trust anchor to inherit from.
2042    let mut working = WorkingKey::standing(anchor.key());
2043
2044    for (position, certificate) in chain.iter().rev().enumerate() {
2045        if !search.spend(cost::CHECK)? {
2046            return Ok(None);
2047        }
2048        let last = position + 1 == length;
2049
2050        // (6.1.3 (a) (1)) The certificate is the one the key above signed.
2051        // Asked here rather than where the edge was found, because a key
2052        // that omits its parameters is only usable once the path above it
2053        // is known, and here it is. A key that stands on its own was asked
2054        // about at the edge and the answer is remembered, so this costs a
2055        // lookup for it.
2056        let Some(answer) = search.verified(certificate, working)? else {
2057            return Ok(None);
2058        };
2059        if answer != Verified::Yes {
2060            return Ok(None);
2061        }
2062        working = working.below(certificate.tbs().public_key());
2063        let known = properties(search, certificate)?;
2064        let self_issued = known.self_issued;
2065        let extensions = certificate.tbs().extensions();
2066
2067        // (6.1.3 (b) and (c)) The names have to be where the authorities
2068        // above allowed them. A self-issued certificate that is not the one
2069        // at the end is a key rollover rather than a name being certified,
2070        // and is not held to the space it is itself narrowing.
2071        if !space.is_open() && (last || !self_issued) && !within(search, &space, certificate)? {
2072            return Ok(None);
2073        }
2074
2075        // (6.1.3 (d) to (f)) What this certificate says about policies. A
2076        // list that is present and does not read is not a certificate that
2077        // named no policy: that reading would carry the agreement past a
2078        // certificate whose part in it nobody could see.
2079        let Ok(named) = read(search, |execution| {
2080            extensions.certificate_policies(execution)
2081        })?
2082        .enforced() else {
2083            return Ok(None);
2084        };
2085        let presented = policies.present(named.as_ref(), self_issued, last, search);
2086        let Some(satisfied) = search.policy(presented)? else {
2087            return Ok(None);
2088        };
2089        if !satisfied {
2090            return Ok(None);
2091        }
2092
2093        // (6.1.4 (g)) What this certificate says about the names below it,
2094        // which is read before the path ends because the profile allows the
2095        // extension only in a certificate that issues others: one at the end
2096        // of a path carries it only where the path is to an authority.
2097        if !narrow(search, &mut space, extensions)? {
2098            return Ok(None);
2099        }
2100
2101        if last {
2102            // Nothing reads the mappings of the certificate at the end of a
2103            // path, and nothing should. The mapping step is 6.1.4, which
2104            // runs for certificates 1 to n-1; 6.1.5 defines no processing of
2105            // mappings for certificate n, because there is no certificate
2106            // below for a mapped policy to be named in.
2107            //
2108            // Nor is carrying them a reason to refuse it. The profile says
2109            // the extension "is used in CA certificates" (RFC 5280 4.2.1.5),
2110            // which is a description of where it belongs, not a prohibition:
2111            // where it does mean to forbid an extension outside a
2112            // certification authority it says so, as it does for the name
2113            // constraints that "MUST be used only in a CA certificate"
2114            // (4.2.1.10), and that one is enforced above. Reading the weaker
2115            // sentence as the stronger one would refuse a certificate over a
2116            // rule the profile does not state.
2117            let Ok(constraints) =
2118                read(search, |execution| extensions.policy_constraints(execution))?.enforced()
2119            else {
2120                return Ok(None);
2121            };
2122            last_constraints = constraints;
2123            break;
2124        }
2125
2126        // (6.1.4 (b) and (h) to (j)) What it says about the ones below it.
2127        let Some(restrictions) = restrictions(search, extensions)? else {
2128            return Ok(None);
2129        };
2130        let carried = policies.carry(
2131            restrictions.mappings.as_ref(),
2132            restrictions.constraints,
2133            restrictions.inhibit,
2134            self_issued,
2135            search,
2136        );
2137        if search.policy(carried)?.is_none() {
2138            return Ok(None);
2139        }
2140
2141        // (6.1.4 (k)) A certificate that issues certificates says so, and
2142        // (n) where it says what its key is for, signing certificates is
2143        // among it. Both were asked of this certificate before the search
2144        // walked into it, and both are asked again here because a path is
2145        // read on what it holds rather than on how it was found.
2146        let Some(basic) = known.issues else {
2147            return Ok(None);
2148        };
2149
2150        // (6.1.4 (l)) A certificate issued to somebody else spends one of
2151        // the certificates the path is allowed. One issued to the same name
2152        // spends nothing: a key rollover is not a longer chain of authority.
2153        if !self_issued {
2154            if allowed == 0 {
2155                return Ok(None);
2156            }
2157            allowed -= 1;
2158        }
2159
2160        // (6.1.4 (m)) And an authority may allow fewer than it was given. A
2161        // limit wider than the counter holds is no limit: the path this
2162        // browser will ever walk is shorter than that by every other bound.
2163        if let Some(limit) = basic.path_length().and_then(CertificateCount::certificates) {
2164            allowed = allowed.min(limit);
2165        }
2166    }
2167
2168    // (6.1.5) What is left is what the authorities agreed the target was
2169    // issued under.
2170    if !spend_policies(search, policies.nodes())? {
2171        return Ok(None);
2172    }
2173    let settled = policies.settle(last_constraints, search.policy.wanted, search);
2174    let Some(settled) = search.policy(settled)? else {
2175        return Ok(None);
2176    };
2177    if !settled.is_satisfied() {
2178        return Ok(None);
2179    }
2180    Ok(Some(settled.into_policies()))
2181}
2182
2183/// Admits the terminal tree pass before settlement performs it.
2184fn spend_policies(
2185    search: &mut Search<'_, '_, impl Verify, impl Watch, impl Recognizer>,
2186    nodes: usize,
2187) -> Result<bool> {
2188    let work = cost::POLICY.checked_mul(nodes as u64).ok_or_else(|| {
2189        search
2190            .target
2191            .tbs()
2192            .subject()
2193            .resource(structured_asn1::memory::MemoryError::WorkExceeded)
2194    })?;
2195    search.spend(work)
2196}
2197
2198/// Creates the accounted policy root at the original target's location.
2199fn initial_policies<'a, V: Verify, W: Watch, R: Recognizer>(
2200    search: &mut Search<'a, '_, V, W, R>,
2201    length: usize,
2202) -> Result<Option<policy::Processing<'a>>> {
2203    let origin = search
2204        .target
2205        .tbs()
2206        .subject()
2207        .resource(structured_asn1::memory::MemoryError::CapacityOverflow);
2208    let length = u32::try_from(length).map_err(|_| origin.clone())?;
2209    let initial = policy::Processing::new(
2210        length,
2211        policy::Initial {
2212            explicit_policy: search.policy.explicit,
2213            policy_mapping: search.policy.mapping,
2214            any_policy: search.policy.any,
2215        },
2216        search.bounds.policies,
2217        search.execution,
2218        origin.offset(),
2219    );
2220    search.policy(initial)
2221}
2222
2223/// Keeps the settled identifiers in the returned path's resource domain.
2224/// Narrows the name space by what one certificate says, answering whether
2225/// the certificate may be in a path at all.
2226///
2227/// Two ways it may not. A constraint this run could not read is one nothing
2228/// below can be shown to obey, and treating an unreadable one as absent
2229/// would let a certificate through the space its authority narrowed by
2230/// writing a value nobody can parse. And "the name constraints extension
2231/// ... MUST be used only in a CA certificate" (RFC 5280 4.2.1.10): carried
2232/// by a certificate that issues nothing, it constrains a space that does not
2233/// exist, and the profile says such a certificate is not one to build a path
2234/// through.
2235fn narrow<'a, V: Verify, W: Watch, R: Recognizer>(
2236    search: &mut Search<'a, '_, V, W, R>,
2237    space: &mut NameSpace<'a>,
2238    extensions: &'a crate::extension::Extensions<'a>,
2239) -> BuildResult<bool, V::Error, R::Error> {
2240    if extensions
2241        .get(crate::oid::NAME_CONSTRAINTS, search.execution)?
2242        .is_none()
2243    {
2244        return Ok(true);
2245    }
2246    let authority = read(search, |execution| extensions.basic_constraints(execution))?
2247        .value()
2248        .is_some_and(crate::constraints::BasicConstraints::is_authority);
2249    if !authority {
2250        return Ok(false);
2251    }
2252    narrowed(search, space, extensions)
2253}
2254
2255/// The same, for the certificate a trust context published an anchor in.
2256///
2257/// Without the question about issuing. That question is asked of a
2258/// certificate of the path, where the profile allows the extension "only
2259/// within a CA certificate" and one carrying it while claiming to be
2260/// anything else is refused. An anchor is not a certificate of the path
2261/// (RFC 5280 6.1), it is the statement of trust the caller made, and this
2262/// crate's way of making that statement carry regions is to hand over a
2263/// certificate holding them. Reading them only where it also asserts being
2264/// an authority would throw away a path the caller trusts, to a target
2265/// inside the very subtree the caller allowed, and report it as no path at
2266/// all.
2267///
2268/// What is not waived is reading them: regions that do not read are regions
2269/// nothing was held to, and that refuses here as everywhere.
2270fn narrow_published<'a, V: Verify, W: Watch, R: Recognizer>(
2271    search: &mut Search<'a, '_, V, W, R>,
2272    space: &mut NameSpace<'a>,
2273    extensions: &'a crate::extension::Extensions<'a>,
2274) -> BuildResult<bool, V::Error, R::Error> {
2275    if extensions
2276        .get(crate::oid::NAME_CONSTRAINTS, search.execution)?
2277        .is_none()
2278    {
2279        return Ok(true);
2280    }
2281    narrowed(search, space, extensions)
2282}
2283
2284/// Reads the regions and narrows the space by them, which is what both of
2285/// the above do once they have decided the extension is theirs to honour.
2286fn narrowed<'a, V: Verify, W: Watch, R: Recognizer>(
2287    search: &mut Search<'a, '_, V, W, R>,
2288    space: &mut NameSpace<'a>,
2289    extensions: &'a crate::extension::Extensions<'a>,
2290) -> BuildResult<bool, V::Error, R::Error> {
2291    let Some(constraints) =
2292        read(search, |execution| extensions.name_constraints(execution))?.value()
2293    else {
2294        return Ok(false);
2295    };
2296    let origin = extensions
2297        .get(crate::oid::NAME_CONSTRAINTS, search.execution)?
2298        .expect("the decoded name constraints extension")
2299        .span()
2300        .start;
2301    space
2302        .narrow(constraints)
2303        .map_err(|reason| crate::Error::resource(reason, "nameConstraints", origin))?;
2304    Ok(true)
2305}
2306
2307/// Whether the names one certificate carries are where the authorities above
2308/// it allowed them to be (RFC 5280 6.1.3 (b) and (c)).
2309///
2310/// Names this run could not read are names it cannot show to be where they
2311/// were allowed. A certificate carrying an alternative name extension that
2312/// does not parse is not a certificate with no alternative names: reading it
2313/// as one would hold a shorter list to the space than the certificate
2314/// carries.
2315fn within<'a, V: Verify, W: Watch, R: Recognizer>(
2316    search: &mut Search<'a, '_, V, W, R>,
2317    space: &NameSpace<'a>,
2318    certificate: &'a Certificate<'a>,
2319) -> BuildResult<bool, V::Error, R::Error> {
2320    // Through the same gate as every other extension, so that reading the
2321    // list happens after the charge. Reaching for it here rather than
2322    // handing it over is what keeps that true: an argument is worked out
2323    // before the call it is passed to, and how many names this holds is a
2324    // certificate's to decide.
2325    let subject = certificate.tbs().subject();
2326    let Ok(carried) = read(search, |execution| {
2327        certificate.tbs().extensions().subject_alt_name(execution)
2328    })?
2329    .enforced() else {
2330        return Ok(false);
2331    };
2332    // Absent subjectAltName has no names; borrow the optional collection rather
2333    // than fabricate a new account or an uncharged growable container.
2334    let alternatives = carried.as_deref().unwrap_or(&[]);
2335    if !charge_names(search, space, subject, alternatives)? {
2336        return Ok(false);
2337    }
2338    Ok(
2339        space.admits(subject, alternatives, search.recognizer, search.execution)?
2340            == Admission::Admitted,
2341    )
2342}
2343
2344/// Charges for holding one certificate's names to the space above it, before
2345/// the comparison runs: both the number of names and the number of regions
2346/// come from certificates somebody else wrote.
2347///
2348/// Every name that will be compared is counted, the legacy mailboxes among
2349/// them. A subject may carry as many of those as the parse budget allowed,
2350/// and each is held against every region: charging for one would let a
2351/// certificate buy the comparisons of thousands without the meter that
2352/// stops them ever moving.
2353fn charge_names<V: Verify, W: Watch, R: Recognizer>(
2354    search: &mut Search<'_, '_, V, W, R>,
2355    space: &NameSpace<'_>,
2356    subject: &Name<'_>,
2357    alternatives: &[GeneralName<'_>],
2358) -> Result<bool> {
2359    // What the space says it will compare, which is the pairs of a name and
2360    // a region of one form rather than every name against every region. A
2361    // comparison that does not part early reads the whole of the name: two
2362    // distinguished names are ordered and compared attribute by attribute,
2363    // a domain and a mailbox are folded to the end. How long the names are
2364    // and how many regions there are is decided by a certificate and an
2365    // extension somebody else wrote, so the charge is their product rather
2366    // than a fixed amount, which one long name and a handful of regions
2367    // would otherwise buy while the bound barely moved.
2368    //
2369    // Charged where it is counted rather than counted here and charged
2370    // afterwards: forming a name reads it, and a list priced in full before
2371    // the meter is consulted has been read in full whatever the budget
2372    // said.
2373    space.charge(subject, alternatives, search, search.execution)
2374}
2375
2376/// Whether a certificate was issued to the name that issued it, which is how
2377/// an authority rolls its key over without lengthening the chain of
2378/// authority under it (RFC 5280 6.1).
2379fn self_issued(certificate: &Certificate<'_>, execution: &Memory) -> Result<bool> {
2380    certificate
2381        .tbs()
2382        .subject()
2383        .matches(certificate.tbs().issuer(), execution)
2384}
2385
2386/// What one extension of a certificate turned out to be.
2387///
2388/// Absent and unreadable are kept apart, because they are different facts
2389/// and the difference decides a path. A certificate that does not carry a
2390/// restriction is not restricted; one that carries a restriction nothing
2391/// here could read is a certificate whose restriction was not enforced, and
2392/// reading the second as the first lets it into a path on the strength of a
2393/// value nobody understood. Only the extensions marked critical are refused
2394/// when they are read, so this is the whole of what protects the rest.
2395enum Read<T> {
2396    /// The certificate does not carry it.
2397    Absent,
2398    /// It carries it, and this is what it says.
2399    Value(T),
2400    /// It carries it, and this run could not read it.
2401    Unreadable,
2402}
2403
2404impl<T> Read<T> {
2405    /// What the extension says, where it says anything, with unreadable and
2406    /// absent alike answering nothing. For the extensions whose absence and
2407    /// whose unreadability lead to the same refusal anyway.
2408    fn value(self) -> Option<T> {
2409        match self {
2410            Self::Value(value) => Some(value),
2411            Self::Absent | Self::Unreadable => None,
2412        }
2413    }
2414
2415    /// What the extension says, for a restriction where absent and
2416    /// unreadable are different answers: a certificate that carries no
2417    /// restriction restricts nothing, and one carrying a restriction this
2418    /// run could not read is a certificate whose restriction was never
2419    /// enforced.
2420    fn enforced(self) -> core::result::Result<Option<T>, Unreadable> {
2421        match self {
2422            Self::Absent => Ok(None),
2423            Self::Value(value) => Ok(Some(value)),
2424            Self::Unreadable => Err(Unreadable),
2425        }
2426    }
2427}
2428
2429/// A restriction that is there and could not be read, which is not the same
2430/// as a restriction that is not there.
2431struct Unreadable;
2432
2433/// What one certificate says about how policies are processed below it.
2434struct Restrictions<'a> {
2435    mappings: Option<crate::policy::PolicyMappings<'a>>,
2436    constraints: Option<crate::constraints::PolicyConstraints>,
2437    inhibit: Option<crate::constraints::InhibitAnyPolicy>,
2438}
2439
2440/// Reads all three, or refuses where any of them is present and does not
2441/// read: each restricts what may be agreed below, and reading an unreadable
2442/// one as absent carries the agreement past a restriction nobody saw.
2443fn restrictions<'a, V: Verify, W: Watch, R: Recognizer>(
2444    search: &mut Search<'a, '_, V, W, R>,
2445    extensions: &'a crate::extension::Extensions<'a>,
2446) -> BuildResult<Option<Restrictions<'a>>, V::Error, R::Error> {
2447    let mappings = read(search, |execution| extensions.policy_mappings(execution))?.enforced();
2448    let constraints =
2449        read(search, |execution| extensions.policy_constraints(execution))?.enforced();
2450    let inhibit = read(search, |execution| extensions.inhibit_any_policy(execution))?.enforced();
2451    let (Ok(mappings), Ok(constraints), Ok(inhibit)) = (mappings, constraints, inhibit) else {
2452        return Ok(None);
2453    };
2454    Ok(Some(Restrictions {
2455        mappings,
2456        constraints,
2457        inhibit,
2458    }))
2459}
2460
2461/// One extension of a certificate the search is holding to its constraints,
2462/// with a spent budget kept as the error it is: that says this run gave up
2463/// rather than anything about the document.
2464///
2465/// The extension is reached for rather than handed over, so that reading its
2466/// value happens after the charge and not before it. An argument is worked
2467/// out before the call it is passed to, and reading an extension decodes
2468/// everything it holds, which is a document's to decide: handed over, the
2469/// whole of it is read even where the budget was already spent.
2470fn read<T>(
2471    search: &mut Search<'_, '_, impl Verify, impl Watch, impl Recognizer>,
2472    outcome: impl FnOnce(&Memory) -> Result<Option<T>>,
2473) -> Result<Read<T>> {
2474    if !search.spend(cost::EXTENSION)? {
2475        return Ok(Read::Unreadable);
2476    }
2477    match gate(outcome(search.execution))? {
2478        Some(Some(value)) => Ok(Read::Value(value)),
2479        Some(None) => Ok(Read::Absent),
2480        None => Ok(Read::Unreadable),
2481    }
2482}
2483
2484#[cfg(test)]
2485mod tests;