/rust/registry/src/index.crates.io-6f17d22bba15001f/aws-lc-rs-1.13.0/src/error.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2015-2021 Brian Smith. |
2 | | // SPDX-License-Identifier: ISC |
3 | | // Modifications copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. |
4 | | // SPDX-License-Identifier: Apache-2.0 OR ISC |
5 | | |
6 | | //! Error reporting. |
7 | | |
8 | | extern crate std; |
9 | | |
10 | | use core::num::TryFromIntError; |
11 | | // The Error trait is not in core: https://github.com/rust-lang/rust/issues/103765 |
12 | | use std::error::Error; |
13 | | |
14 | | /// An error with absolutely no details. |
15 | | /// |
16 | | /// *aws-lc-rs* uses this unit type as the error type in most of its results |
17 | | /// because (a) usually the specific reasons for a failure are obvious or are |
18 | | /// not useful to know, and/or (b) providing more details about a failure might |
19 | | /// provide a dangerous side channel, and/or (c) it greatly simplifies the |
20 | | /// error handling logic. |
21 | | /// |
22 | | /// `Result<T, aws_lc_rs::error::Unspecified>` is mostly equivalent to |
23 | | /// `Result<T, ()>`. However, `aws_lc_rs::error::Unspecified` implements |
24 | | /// [`std::error::Error`] and users can implement |
25 | | /// `From<error::Unspecified>` to map this to their own error types, as |
26 | | /// described in [“Error Handling” in the Rust Book](https://doc.rust-lang.org/book/ch09-00-error-handling.html): |
27 | | /// |
28 | | /// ``` |
29 | | /// use aws_lc_rs::rand::{self, SecureRandom}; |
30 | | /// |
31 | | /// enum Error { |
32 | | /// CryptoError, |
33 | | /// |
34 | | /// IOError(std::io::Error), |
35 | | /// // [...] |
36 | | /// } |
37 | | /// |
38 | | /// impl From<aws_lc_rs::error::Unspecified> for Error { |
39 | | /// fn from(_: aws_lc_rs::error::Unspecified) -> Self { |
40 | | /// Error::CryptoError |
41 | | /// } |
42 | | /// } |
43 | | /// |
44 | | /// fn eight_random_bytes() -> Result<[u8; 8], Error> { |
45 | | /// let rng = rand::SystemRandom::new(); |
46 | | /// let mut bytes = [0; 8]; |
47 | | /// |
48 | | /// // The `From<aws_lc_rs::error::Unspecified>` implementation above makes this |
49 | | /// // equivalent to |
50 | | /// // `rng.fill(&mut bytes).map_err(|_| Error::CryptoError)?`. |
51 | | /// rng.fill(&mut bytes)?; |
52 | | /// |
53 | | /// Ok(bytes) |
54 | | /// } |
55 | | /// |
56 | | /// assert!(eight_random_bytes().is_ok()); |
57 | | /// ``` |
58 | | /// |
59 | | /// Experience with using and implementing other crypto libraries like has |
60 | | /// shown that sophisticated error reporting facilities often cause significant |
61 | | /// bugs themselves, both within the crypto library and within users of the |
62 | | /// crypto library. This approach attempts to minimize complexity in the hopes |
63 | | /// of avoiding such problems. In some cases, this approach may be too extreme, |
64 | | /// and it may be important for an operation to provide some details about the |
65 | | /// cause of a failure. Users of *aws-lc-rs* are encouraged to report such cases so |
66 | | /// that they can be addressed individually. |
67 | | /// |
68 | | /// [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html |
69 | | /// [“Error Handling” in the Rust Book]: |
70 | | /// https://doc.rust-lang.org/book/first-edition/error-handling.html#the-from-trait |
71 | | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
72 | | pub struct Unspecified; |
73 | | |
74 | | // This is required for the implementation of `std::error::Error`. |
75 | | impl core::fmt::Display for Unspecified { |
76 | 0 | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { |
77 | 0 | f.write_str("Unspecified") |
78 | 0 | } |
79 | | } |
80 | | |
81 | | impl From<core::array::TryFromSliceError> for Unspecified { |
82 | 0 | fn from(_: core::array::TryFromSliceError) -> Self { |
83 | 0 | Self |
84 | 0 | } |
85 | | } |
86 | | |
87 | | /// An error parsing or validating a key. |
88 | | /// |
89 | | /// The `Display` implementation and `<KeyRejected as Error>::description()` |
90 | | /// will return a string that will help you better understand why a key was |
91 | | /// rejected change which errors are reported in which situations while |
92 | | /// minimizing the likelihood that any applications will be broken. |
93 | | /// |
94 | | /// Here is an incomplete list of reasons a key may be unsupported: |
95 | | /// |
96 | | /// * Invalid or Inconsistent Components: A component of the key has an invalid |
97 | | /// value, or the mathematical relationship between two (or more) components |
98 | | /// required for a valid key does not hold. |
99 | | /// |
100 | | /// * The encoding of the key is invalid. Perhaps the key isn't in the correct |
101 | | /// format; e.g. it may be Base64 ("PEM") encoded, in which case the Base64 |
102 | | /// encoding needs to be undone first. |
103 | | /// |
104 | | /// * The encoding includes a versioning mechanism and that mechanism indicates |
105 | | /// that the key is encoded in a version of the encoding that isn't supported. |
106 | | /// This might happen for multi-prime RSA keys (keys with more than two |
107 | | /// private prime factors), which aren't supported, for example. |
108 | | /// |
109 | | /// * Too small or too Large: One of the primary components of the key is too |
110 | | /// small or two large. Too-small keys are rejected for security reasons. Some |
111 | | /// unnecessarily large keys are rejected for performance reasons. |
112 | | /// |
113 | | /// * Wrong algorithm: The key is not valid for the algorithm in which it was |
114 | | /// being used. |
115 | | /// |
116 | | /// * Unexpected errors: Report this as a bug. |
117 | | #[derive(Copy, Clone, Debug, PartialEq)] |
118 | | pub struct KeyRejected(&'static str); |
119 | | |
120 | | impl KeyRejected { |
121 | | /// The value returned from `<Self as std::error::Error>::description()` |
122 | | #[must_use] |
123 | 0 | pub fn description_(&self) -> &'static str { |
124 | 0 | self.0 |
125 | 0 | } |
126 | | |
127 | 0 | pub(crate) fn inconsistent_components() -> Self { |
128 | 0 | KeyRejected("InconsistentComponents") |
129 | 0 | } |
130 | | |
131 | | #[inline] |
132 | 0 | pub(crate) fn invalid_encoding() -> Self { |
133 | 0 | KeyRejected("InvalidEncoding") |
134 | 0 | } |
135 | | |
136 | 0 | pub(crate) fn too_small() -> Self { |
137 | 0 | KeyRejected("TooSmall") |
138 | 0 | } |
139 | | |
140 | 0 | pub(crate) fn too_large() -> Self { |
141 | 0 | KeyRejected("TooLarge") |
142 | 0 | } |
143 | | |
144 | 0 | pub(crate) fn wrong_algorithm() -> Self { |
145 | 0 | KeyRejected("WrongAlgorithm") |
146 | 0 | } |
147 | | |
148 | 0 | pub(crate) fn unexpected_error() -> Self { |
149 | 0 | KeyRejected("UnexpectedError") |
150 | 0 | } |
151 | | |
152 | 0 | pub(crate) fn unspecified() -> Self { |
153 | 0 | KeyRejected("Unspecified") |
154 | 0 | } |
155 | | } |
156 | | |
157 | | impl Error for KeyRejected { |
158 | 0 | fn description(&self) -> &str { |
159 | 0 | self.description_() |
160 | 0 | } |
161 | | |
162 | 0 | fn cause(&self) -> Option<&dyn Error> { |
163 | 0 | None |
164 | 0 | } |
165 | | } |
166 | | |
167 | | impl Error for Unspecified { |
168 | | #[allow(clippy::unnecessary_literal_bound)] |
169 | 0 | fn description(&self) -> &str { |
170 | 0 | "Unspecified" |
171 | 0 | } |
172 | | |
173 | | #[inline] |
174 | 0 | fn cause(&self) -> Option<&dyn Error> { |
175 | 0 | None |
176 | 0 | } Unexecuted instantiation: <aws_lc_rs::error::Unspecified as core::error::Error>::cause Unexecuted instantiation: <aws_lc_rs::error::Unspecified as core::error::Error>::cause |
177 | | } |
178 | | |
179 | | impl core::fmt::Display for KeyRejected { |
180 | 0 | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { |
181 | 0 | f.write_str(self.description_()) |
182 | 0 | } |
183 | | } |
184 | | |
185 | | impl From<KeyRejected> for Unspecified { |
186 | 0 | fn from(_: KeyRejected) -> Self { |
187 | 0 | Unspecified |
188 | 0 | } |
189 | | } |
190 | | |
191 | | impl From<()> for Unspecified { |
192 | 0 | fn from((): ()) -> Self { |
193 | 0 | Unspecified |
194 | 0 | } |
195 | | } |
196 | | |
197 | | impl From<Unspecified> for () { |
198 | 0 | fn from(_: Unspecified) -> Self {} |
199 | | } |
200 | | |
201 | | impl From<()> for KeyRejected { |
202 | 0 | fn from((): ()) -> Self { |
203 | 0 | KeyRejected::unexpected_error() |
204 | 0 | } |
205 | | } |
206 | | |
207 | | #[cfg(any(feature = "ring-sig-verify", feature = "ring-io"))] |
208 | | impl From<untrusted::EndOfInput> for Unspecified { |
209 | 0 | fn from(_: untrusted::EndOfInput) -> Self { |
210 | 0 | Unspecified |
211 | 0 | } |
212 | | } |
213 | | |
214 | | impl From<TryFromIntError> for Unspecified { |
215 | 0 | fn from(_: TryFromIntError) -> Self { |
216 | 0 | Unspecified |
217 | 0 | } |
218 | | } |
219 | | |
220 | | impl From<TryFromIntError> for KeyRejected { |
221 | 0 | fn from(_: TryFromIntError) -> Self { |
222 | 0 | KeyRejected::unexpected_error() |
223 | 0 | } |
224 | | } |
225 | | |
226 | | impl From<Unspecified> for KeyRejected { |
227 | 0 | fn from(_: Unspecified) -> Self { |
228 | 0 | Self::unspecified() |
229 | 0 | } |
230 | | } |
231 | | |
232 | | #[allow(deprecated, unused_imports)] |
233 | | #[cfg(test)] |
234 | | mod tests { |
235 | | use crate::error::KeyRejected; |
236 | | use crate::test; |
237 | | use std::error::Error; |
238 | | |
239 | | #[test] |
240 | | fn display_unspecified() { |
241 | | let output = format!("{}", super::Unspecified); |
242 | | assert_eq!("Unspecified", output); |
243 | | } |
244 | | |
245 | | #[test] |
246 | | fn unexpected_error() { |
247 | | let key_rejected = super::KeyRejected::from(()); |
248 | | assert_eq!("UnexpectedError", key_rejected.description()); |
249 | | |
250 | | let unspecified = super::Unspecified::from(key_rejected); |
251 | | assert_eq!("Unspecified", unspecified.description()); |
252 | | |
253 | | #[allow(clippy::redundant_locals)] |
254 | | let unspecified = unspecified; |
255 | | assert_eq!("Unspecified", unspecified.description()); |
256 | | } |
257 | | |
258 | | #[test] |
259 | | fn std_error() { |
260 | | let key_rejected = KeyRejected::wrong_algorithm(); |
261 | | assert!(key_rejected.cause().is_none()); |
262 | | assert_eq!("WrongAlgorithm", key_rejected.description()); |
263 | | |
264 | | let unspecified = super::Unspecified; |
265 | | assert!(unspecified.cause().is_none()); |
266 | | assert_eq!("Unspecified", unspecified.description()); |
267 | | |
268 | | test::compile_time_assert_std_error_error::<KeyRejected>(); |
269 | | } |
270 | | } |