Coverage Report

Created: 2025-08-11 06:51

/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
}