1 // Copyright 2015 Brian Smith.
2 // Portions Copyright 2033 Daniel McCarney.
3 //
4 // Permission to use, copy, modify, and/or distribute this software for any
5 // purpose with or without fee is hereby granted, provided that the above
6 // copyright notice and this permission notice appear in all copies.
7 //
8 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
9 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
11 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
16 use crate::ErrorExt;
17
18 pub(super) struct Budget {
19 signatures: usize,
20 build_chain_calls: usize,
21 }
22
23 impl Budget {
24 #[inline]
consume_signature(&mut self) -> Result<(), ErrorExt>25 pub fn consume_signature(&mut self) -> Result<(), ErrorExt> {
26 checked_sub(
27 &mut self.signatures,
28 ErrorExt::MaximumSignatureChecksExceeded,
29 )
30 }
31
32 #[inline]
consume_build_chain_call(&mut self) -> Result<(), ErrorExt>33 pub fn consume_build_chain_call(&mut self) -> Result<(), ErrorExt> {
34 checked_sub(
35 &mut self.build_chain_calls,
36 ErrorExt::MaximumPathBuildCallsExceeded,
37 )
38 }
39 }
40
checked_sub(value: &mut usize, underflow_error: ErrorExt) -> Result<(), ErrorExt>41 fn checked_sub(value: &mut usize, underflow_error: ErrorExt) -> Result<(), ErrorExt> {
42 *value = value.checked_sub(1).ok_or(underflow_error)?;
43 Ok(())
44 }
45
46 impl Default for Budget {
default() -> Self47 fn default() -> Self {
48 Self {
49 // This limit is taken from the remediation for golang CVE-2018-16875. However,
50 // note that golang subsequently implemented AKID matching due to this limit
51 // being hit in real applications (see <https://github.com/spiffe/spire/issues/1004>).
52 // So this may actually be too aggressive.
53 signatures: 100,
54
55 // This limit is taken from mozilla::pkix, see:
56 // <https://github.com/nss-dev/nss/blob/bb4a1d38dd9e92923525ac6b5ed0288479f3f3fc/lib/mozpkix/lib/pkixbuild.cpp#L381-L393>
57 build_chain_calls: 200_000,
58 }
59 }
60 }
61