devolutions_crypto/
error.rs

1//! Possible errors in the library.
2use cbc::cipher::block_padding::UnpadError;
3
4#[cfg(feature = "wbindgen")]
5use wasm_bindgen::JsValue;
6
7use strum::IntoStaticStr;
8
9use hmac::digest::MacError;
10
11pub type Result<T> = std::result::Result<T, Error>;
12
13// Doesn't work because Result is a type alias, keeping the commented code just in case we revisit someday
14// impl<T, E> From<std::result::Result<T, E>> for Result<T>
15// where E: Into<Error> {
16//    fn from(value: std::result::Result<T, E>) -> Self {
17//         match value {
18//             Ok(t) => Ok(t),
19//             Err(e) => Err(e.into()),
20//         }
21//     }
22// }
23
24/// This crate's error type.
25#[derive(Debug, IntoStaticStr, thiserror::Error)]
26pub enum Error {
27    /// The provided data has an invalid length. Error code: -1
28    #[error("The provided data has an invalid length")]
29    InvalidLength,
30    /// The key length is invalid. Error code: -2
31    #[error("The key length is invalid.")]
32    InvalidKeyLength,
33    /// The length of the FFI output buffer is invalid. Error code: -3
34    #[error("The length of the FFI output buffer is invalid.")]
35    InvalidOutputLength,
36    /// The signature of the data blob does not match 0x0d0c. Error code: -11
37    #[error("The signature of the data blob does not match 0x0d0c.")]
38    InvalidSignature,
39    /// The MAC is invalid. Error code: -12
40    #[error("The MAC is invalid.")]
41    InvalidMac,
42    /// The operation cannot be done with this type. Error code: -13
43    #[error("The operation cannot be done with this type.")]
44    InvalidDataType,
45    /// The data type is unknown. Error code: -21
46    #[error("The data type is unknown.")]
47    UnknownType,
48    /// The data subtype is unknown. Error code: -22
49    #[error("The data subtype is unknown.")]
50    UnknownSubtype,
51    /// The data type version is unknown. Error code: -23
52    #[error("The data type version is unknown.")]
53    UnknownVersion,
54    /// The data is invalid. Error code: -24
55    #[error("The data is invalid.")]
56    InvalidData,
57    /// A null pointer has been passed to the FFI interface. Error code: -31
58    #[error("A null pointer has been passed to the FFI interface.")]
59    NullPointer,
60    /// A cryptographic error occurred. Error code: -32
61    #[error("A cryptographic error occurred.")]
62    CryptoError,
63    /// An error with the Random Number Generator occurred. Error code: -33
64    #[error("An error with the Random Number Generator occurred.")]
65    RandomError,
66    /// A generic IO error has occurred. Error code: -34
67    #[error("Generic IO error: {0}")]
68    IoError(#[from] std::io::Error),
69    /// There is not enough shares to regenerate a secret: -41
70    #[error("There wasn't enough share to regenerate the secret.")]
71    NotEnoughShares,
72    /// The version of the multiple data is inconsistent: -42
73    #[error("The version is not the same for all the data.")]
74    InconsistentVersion,
75    /// The length of the data to encrypt/decrypt during online encryption is not the same as the chunk size: -43
76    #[error("The length of the data to encrypt/decrypt during online encryption is not the same as the chunk size")]
77    InvalidChunkLength,
78    /// The mutex is poisoned and cannot be locked: -44
79    #[error("The mutex is poisoned and cannot be locked")]
80    PoisonedMutex,
81}
82
83impl Error {
84    /// Returns the error code associated with the error.
85    /// This is useful for passing the exception type across a language boundary.
86    pub fn error_code(&self) -> i64 {
87        match *self {
88            Error::InvalidLength => -1,
89            Error::InvalidKeyLength => -2,
90            Error::InvalidOutputLength => -3,
91            Error::InvalidSignature => -11,
92            Error::InvalidMac => -12,
93            Error::InvalidDataType => -13,
94            Error::UnknownType => -21,
95            Error::UnknownSubtype => -22,
96            Error::UnknownVersion => -23,
97            Error::InvalidData => -24,
98            Error::NullPointer => -31,
99            Error::CryptoError => -32,
100            Error::RandomError => -33,
101            Error::IoError(_) => -34,
102            Error::NotEnoughShares => -41,
103            Error::InconsistentVersion => -42,
104            Error::InvalidChunkLength => -43,
105            Error::PoisonedMutex => -44,
106        }
107    }
108}
109
110impl From<hmac::digest::InvalidLength> for Error {
111    fn from(_error: hmac::digest::InvalidLength) -> Error {
112        Error::InvalidKeyLength
113    }
114}
115
116impl From<MacError> for Error {
117    fn from(_error: MacError) -> Error {
118        Error::InvalidMac
119    }
120}
121
122impl From<UnpadError> for Error {
123    fn from(_error: UnpadError) -> Error {
124        Error::CryptoError
125    }
126}
127
128impl From<aead::Error> for Error {
129    fn from(_error: aead::Error) -> Error {
130        Error::InvalidMac
131    }
132}
133
134impl From<rand::Error> for Error {
135    fn from(_error: rand::Error) -> Error {
136        Error::RandomError
137    }
138}
139
140impl From<argon2::Error> for Error {
141    fn from(_error: argon2::Error) -> Self {
142        Error::CryptoError
143    }
144}
145
146#[cfg(feature = "wbindgen")]
147impl From<Error> for JsValue {
148    fn from(error: Error) -> JsValue {
149        let js_error = js_sys::Error::new(&error.to_string());
150
151        js_error.set_name(error.into());
152        js_error.into()
153    }
154}