1 // Copyright 2016 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 //! Error reporting.
16 
17 #[cfg(feature = "std")]
18 extern crate std;
19 
20 /// An error with absolutely no details.
21 ///
22 /// *ring* uses this unit type as the error type in most of its results
23 /// because (a) usually the specific reasons for a failure are obvious or are
24 /// not useful to know, and/or (b) providing more details about a failure might
25 /// provide a dangerous side channel, and/or (c) it greatly simplifies the
26 /// error handling logic.
27 ///
28 /// `Result<T, ring::error::Unspecified>` is mostly equivalent to
29 /// `Result<T, ()>`. However, `ring::error::Unspecified` implements
30 /// [`std::error::Error`] and users of *ring* can implement
31 /// `From<ring::error::Unspecified>` to map this to their own error types, as
32 /// described in [“Error Handling” in the Rust Book]:
33 ///
34 /// ```
35 /// use ring::rand::{self, SecureRandom};
36 ///
37 /// enum Error {
38 ///     CryptoError,
39 ///
40 /// #  #[cfg(feature = "alloc")]
41 ///     IOError(std::io::Error),
42 ///     // [...]
43 /// }
44 ///
45 /// impl From<ring::error::Unspecified> for Error {
46 ///     fn from(_: ring::error::Unspecified) -> Self { Error::CryptoError }
47 /// }
48 ///
49 /// fn eight_random_bytes() -> Result<[u8; 8], Error> {
50 ///     let rng = rand::SystemRandom::new();
51 ///     let mut bytes = [0; 8];
52 ///
53 ///     // The `From<ring::error::Unspecified>` implementation above makes this
54 ///     // equivalent to
55 ///     // `rng.fill(&mut bytes).map_err(|_| Error::CryptoError)?`.
56 ///     rng.fill(&mut bytes)?;
57 ///
58 ///     Ok(bytes)
59 /// }
60 ///
61 /// assert!(eight_random_bytes().is_ok());
62 /// ```
63 ///
64 /// Experience with using and implementing other crypto libraries like has
65 /// shown that sophisticated error reporting facilities often cause significant
66 /// bugs themselves, both within the crypto library and within users of the
67 /// crypto library. This approach attempts to minimize complexity in the hopes
68 /// of avoiding such problems. In some cases, this approach may be too extreme,
69 /// and it may be important for an operation to provide some details about the
70 /// cause of a failure. Users of *ring* are encouraged to report such cases so
71 /// that they can be addressed individually.
72 ///
73 /// [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html
74 /// [“Error Handling” in the Rust Book]:
75 ///     https://doc.rust-lang.org/book/first-edition/error-handling.html#the-from-trait
76 #[derive(Clone, Copy, Debug, PartialEq)]
77 pub struct Unspecified;
78 
79 impl Unspecified {
description_() -> &'static str80     fn description_() -> &'static str {
81         "ring::error::Unspecified"
82     }
83 }
84 
85 // This is required for the implementation of `std::error::Error`.
86 impl core::fmt::Display for Unspecified {
fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result87     fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
88         f.write_str(Self::description_())
89     }
90 }
91 
92 #[cfg(feature = "std")]
93 impl std::error::Error for Unspecified {
94     #[inline]
cause(&self) -> Option<&dyn std::error::Error>95     fn cause(&self) -> Option<&dyn std::error::Error> {
96         None
97     }
98 
description(&self) -> &str99     fn description(&self) -> &str {
100         Self::description_()
101     }
102 }
103 
104 impl From<untrusted::EndOfInput> for Unspecified {
from(_: untrusted::EndOfInput) -> Self105     fn from(_: untrusted::EndOfInput) -> Self {
106         Unspecified
107     }
108 }
109 
110 impl From<core::array::TryFromSliceError> for Unspecified {
from(_: core::array::TryFromSliceError) -> Self111     fn from(_: core::array::TryFromSliceError) -> Self {
112         Unspecified
113     }
114 }
115 
116 /// An error parsing or validating a key.
117 ///
118 /// The `Display` implementation and `<KeyRejected as Error>::description()`
119 /// will return a string that will help you better understand why a key was
120 /// rejected change which errors are reported in which situations while
121 /// minimizing the likelihood that any applications will be broken.
122 ///
123 /// Here is an incomplete list of reasons a key may be unsupported:
124 ///
125 /// * Invalid or Inconsistent Components: A component of the key has an invalid
126 ///   value, or the mathematical relationship between two (or more) components
127 ///   required for a valid key does not hold.
128 ///
129 /// * The encoding of the key is invalid. Perhaps the key isn't in the correct
130 ///   format; e.g. it may be Base64 ("PEM") encoded, in which case   the Base64
131 ///   encoding needs to be undone first.
132 ///
133 /// * The encoding includes a versioning mechanism and that mechanism indicates
134 ///   that the key is encoded in a version of the encoding that isn't supported.
135 ///   This might happen for multi-prime RSA keys (keys with more than two
136 ///   private   prime factors), which aren't supported, for example.
137 ///
138 /// * Too small or too Large: One of the primary components of the key is too
139 ///   small or two large. Too-small keys are rejected for security reasons. Some
140 ///   unnecessarily large keys are rejected for performance reasons.
141 ///
142 ///  * Wrong algorithm: The key is not valid for the algorithm in which it was
143 ///    being used.
144 ///
145 ///  * Unexpected errors: Report this as a bug.
146 #[derive(Copy, Clone, Debug)]
147 pub struct KeyRejected(&'static str);
148 
149 impl KeyRejected {
150     /// The value returned from <Self as std::error::Error>::description()
description_(&self) -> &'static str151     pub fn description_(&self) -> &'static str {
152         self.0
153     }
154 
inconsistent_components() -> Self155     pub(crate) fn inconsistent_components() -> Self {
156         KeyRejected("InconsistentComponents")
157     }
158 
invalid_component() -> Self159     pub(crate) fn invalid_component() -> Self {
160         KeyRejected("InvalidComponent")
161     }
162 
163     #[inline]
invalid_encoding() -> Self164     pub(crate) fn invalid_encoding() -> Self {
165         KeyRejected("InvalidEncoding")
166     }
167 
168     // XXX: See the comment at the call site.
rng_failed() -> Self169     pub(crate) fn rng_failed() -> Self {
170         KeyRejected("RNG failed")
171     }
172 
public_key_is_missing() -> Self173     pub(crate) fn public_key_is_missing() -> Self {
174         KeyRejected("PublicKeyIsMissing")
175     }
176 
177     #[cfg(feature = "alloc")]
too_small() -> Self178     pub(crate) fn too_small() -> Self {
179         KeyRejected("TooSmall")
180     }
181 
182     #[cfg(feature = "alloc")]
too_large() -> Self183     pub(crate) fn too_large() -> Self {
184         KeyRejected("TooLarge")
185     }
186 
version_not_supported() -> Self187     pub(crate) fn version_not_supported() -> Self {
188         KeyRejected("VersionNotSupported")
189     }
190 
wrong_algorithm() -> Self191     pub(crate) fn wrong_algorithm() -> Self {
192         KeyRejected("WrongAlgorithm")
193     }
194 
195     #[cfg(feature = "alloc")]
private_modulus_len_not_multiple_of_512_bits() -> Self196     pub(crate) fn private_modulus_len_not_multiple_of_512_bits() -> Self {
197         KeyRejected("PrivateModulusLenNotMultipleOf512Bits")
198     }
199 
unexpected_error() -> Self200     pub(crate) fn unexpected_error() -> Self {
201         KeyRejected("UnexpectedError")
202     }
203 }
204 
205 #[cfg(feature = "std")]
206 impl std::error::Error for KeyRejected {
cause(&self) -> Option<&dyn std::error::Error>207     fn cause(&self) -> Option<&dyn std::error::Error> {
208         None
209     }
210 
description(&self) -> &str211     fn description(&self) -> &str {
212         self.description_()
213     }
214 }
215 
216 impl core::fmt::Display for KeyRejected {
fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result217     fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
218         f.write_str(self.description_())
219     }
220 }
221 
222 impl From<KeyRejected> for Unspecified {
from(_: KeyRejected) -> Self223     fn from(_: KeyRejected) -> Self {
224         Unspecified
225     }
226 }
227