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