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 // This is required for the implementation of `std::error::Error`.
80 impl core::fmt::Display for Unspecified {
fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result81     fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
82         f.write_str("ring::error::Unspecified")
83     }
84 }
85 
86 #[cfg(feature = "std")]
87 impl std::error::Error for Unspecified {}
88 
89 impl From<untrusted::EndOfInput> for Unspecified {
from(_: untrusted::EndOfInput) -> Self90     fn from(_: untrusted::EndOfInput) -> Self {
91         Self
92     }
93 }
94 
95 impl From<core::array::TryFromSliceError> for Unspecified {
from(_: core::array::TryFromSliceError) -> Self96     fn from(_: core::array::TryFromSliceError) -> Self {
97         Self
98     }
99 }
100 
101 /// An error parsing or validating a key.
102 ///
103 /// The `Display` implementation will return a string that will help you better
104 /// understand why a key was rejected change which errors are reported in which
105 /// situations while minimizing the likelihood that any applications will be
106 /// broken.
107 ///
108 /// Here is an incomplete list of reasons a key may be unsupported:
109 ///
110 /// * Invalid or Inconsistent Components: A component of the key has an invalid
111 ///   value, or the mathematical relationship between two (or more) components
112 ///   required for a valid key does not hold.
113 ///
114 /// * The encoding of the key is invalid. Perhaps the key isn't in the correct
115 ///   format; e.g. it may be Base64 ("PEM") encoded, in which case   the Base64
116 ///   encoding needs to be undone first.
117 ///
118 /// * The encoding includes a versioning mechanism and that mechanism indicates
119 ///   that the key is encoded in a version of the encoding that isn't supported.
120 ///   This might happen for multi-prime RSA keys (keys with more than two
121 ///   private   prime factors), which aren't supported, for example.
122 ///
123 /// * Too small or too Large: One of the primary components of the key is too
124 ///   small or two large. Too-small keys are rejected for security reasons. Some
125 ///   unnecessarily large keys are rejected for performance reasons.
126 ///
127 ///  * Wrong algorithm: The key is not valid for the algorithm in which it was
128 ///    being used.
129 ///
130 ///  * Unexpected errors: Report this as a bug.
131 #[derive(Copy, Clone, Debug)]
132 pub struct KeyRejected(&'static str);
133 
134 impl KeyRejected {
inconsistent_components() -> Self135     pub(crate) fn inconsistent_components() -> Self {
136         Self("InconsistentComponents")
137     }
138 
invalid_component() -> Self139     pub(crate) fn invalid_component() -> Self {
140         Self("InvalidComponent")
141     }
142 
143     #[inline]
invalid_encoding() -> Self144     pub(crate) fn invalid_encoding() -> Self {
145         Self("InvalidEncoding")
146     }
147 
148     // XXX: See the comment at the call site.
rng_failed() -> Self149     pub(crate) fn rng_failed() -> Self {
150         Self("RNG failed")
151     }
152 
public_key_is_missing() -> Self153     pub(crate) fn public_key_is_missing() -> Self {
154         Self("PublicKeyIsMissing")
155     }
156 
157     #[cfg(feature = "alloc")]
too_small() -> Self158     pub(crate) fn too_small() -> Self {
159         Self("TooSmall")
160     }
161 
162     #[cfg(feature = "alloc")]
too_large() -> Self163     pub(crate) fn too_large() -> Self {
164         Self("TooLarge")
165     }
166 
version_not_supported() -> Self167     pub(crate) fn version_not_supported() -> Self {
168         Self("VersionNotSupported")
169     }
170 
wrong_algorithm() -> Self171     pub(crate) fn wrong_algorithm() -> Self {
172         Self("WrongAlgorithm")
173     }
174 
175     #[cfg(feature = "alloc")]
private_modulus_len_not_multiple_of_512_bits() -> Self176     pub(crate) fn private_modulus_len_not_multiple_of_512_bits() -> Self {
177         Self("PrivateModulusLenNotMultipleOf512Bits")
178     }
179 
unexpected_error() -> Self180     pub(crate) fn unexpected_error() -> Self {
181         Self("UnexpectedError")
182     }
183 }
184 
185 #[cfg(feature = "std")]
186 impl std::error::Error for KeyRejected {}
187 
188 impl core::fmt::Display for KeyRejected {
fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result189     fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
190         f.write_str(self.0)
191     }
192 }
193 
194 impl From<KeyRejected> for Unspecified {
from(_: KeyRejected) -> Self195     fn from(_: KeyRejected) -> Self {
196         Self
197     }
198 }
199