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;