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