cmail_rpgp/
errors.rs

1use std::num::TryFromIntError;
2
3use ed25519_dalek::SignatureError;
4use nom::{
5    error::{FromExternalError, ParseError},
6    ErrorConvert,
7};
8
9pub type Result<T, E = Error> = ::std::result::Result<T, E>;
10
11// custom nom error types
12pub const MPI_TOO_LONG: u32 = 1000;
13
14/// Error types
15#[derive(Debug, thiserror::Error)]
16pub enum Error {
17    #[error("failed to parse {0:?}")]
18    ParsingError(nom::error::ErrorKind),
19    #[error("invalid input")]
20    InvalidInput,
21    #[error("incomplete input: {0:?}")]
22    Incomplete(nom::Needed),
23    #[error("invalid armor wrappers")]
24    InvalidArmorWrappers,
25    #[error("invalid crc24 checksum")]
26    InvalidChecksum,
27    #[error("failed to decode base64 {0:?}")]
28    Base64DecodeError(#[from] base64::DecodeError),
29    #[error("requested data size is larger than the packet body")]
30    RequestedSizeTooLarge,
31    #[error("no matching packet found")]
32    NoMatchingPacket,
33    #[error("more than one matching packet was found")]
34    TooManyPackets,
35    #[error("rsa error: {0:?}")]
36    RSAError(rsa::errors::Error),
37    #[error("elliptic error: {0:?}")]
38    EllipticCurve(#[from] elliptic_curve::Error),
39    #[error("io error: {source:?}")]
40    IOError {
41        #[from]
42        source: std::io::Error,
43        #[cfg(feature = "nightly")]
44        backtrace: std::backtrace::Backtrace,
45    },
46    #[error("missing packets")]
47    MissingPackets,
48    #[error("invalid key length")]
49    InvalidKeyLength,
50    #[error("block mode error")]
51    BlockMode,
52    #[error("missing key")]
53    MissingKey,
54    #[error("cfb: invalid key iv length")]
55    CfbInvalidKeyIvLength,
56    #[error("Not yet implemented: {0:?}")]
57    Unimplemented(String),
58    #[error("Unsupported: {0:?}")]
59    Unsupported(String), // Signals packet versions and parameters we don't support, but can safely ignore
60    #[error("{0:?}")]
61    Message(String),
62    #[error("Invalid Packet {0:?}")]
63    PacketError(nom::error::ErrorKind),
64    #[error("Incomplete Packet")]
65    PacketIncomplete,
66    #[error("Unpadding failed")]
67    UnpadError,
68    #[error("Padding failed")]
69    PadError,
70    #[error("Utf8 {0:?}")]
71    Utf8Error(#[from] std::str::Utf8Error),
72    #[error("ParseInt {0:?}")]
73    ParseIntError(#[from] std::num::ParseIntError),
74    #[error("Invalid Packet Content {0:?}")]
75    InvalidPacketContent(Box<Error>),
76    #[error("Signature {0:?}")]
77    SignatureError(#[from] SignatureError),
78    #[error("Modification Detection Code error")]
79    MdcError,
80    #[error("Invalid size conversion {0}")]
81    TryFromInt(#[from] TryFromIntError),
82    #[error("GCM")]
83    Gcm,
84    #[error("EAX")]
85    Eax,
86    #[error("OCB")]
87    Ocb,
88    #[error("SHA1 hash collision detected")]
89    Sha1HashCollision,
90    #[error("AES Key Wrap error {0}")]
91    AesKek(#[from] aes_kw::Error),
92    #[error("MKV128 Key Wrap error {0}")]
93    Mkv128Kek(#[from] mkv128_kw::Error),
94}
95
96impl Error {
97    pub fn as_code(&self) -> u32 {
98        match self {
99            Error::ParsingError(_) => 0,
100            Error::InvalidInput => 1,
101            Error::Incomplete(_) => 2,
102            Error::InvalidArmorWrappers => 3,
103            Error::InvalidChecksum => 4,
104            Error::Base64DecodeError(_) => 5,
105            Error::RequestedSizeTooLarge => 6,
106            Error::NoMatchingPacket => 7,
107            Error::TooManyPackets => 8,
108            Error::RSAError(_) => 9,
109            Error::IOError { .. } => 10,
110            Error::MissingPackets => 11,
111            Error::InvalidKeyLength => 12,
112            Error::BlockMode => 13,
113            Error::MissingKey => 14,
114            Error::CfbInvalidKeyIvLength => 15,
115            Error::Unimplemented(_) => 16,
116            Error::Unsupported(_) => 17,
117            Error::Message(_) => 18,
118            Error::PacketError(_) => 19,
119            Error::PacketIncomplete => 20,
120            Error::UnpadError => 21,
121            Error::PadError => 22,
122            Error::Utf8Error(_) => 23,
123            Error::ParseIntError(_) => 24,
124            Error::InvalidPacketContent(_) => 25,
125            Error::SignatureError(_) => 26,
126            Error::MdcError => 27,
127            Error::TryFromInt(_) => 28,
128            Error::EllipticCurve(_) => 29,
129            Error::Gcm => 30,
130            Error::Eax => 31,
131            Error::Ocb => 32,
132            Error::Sha1HashCollision => 33,
133            Error::AesKek(_) => 34,
134            Error::Mkv128Kek(_) => 35,
135        }
136    }
137}
138
139pub(crate) type IResult<I, O, E = Error> = nom::IResult<I, O, E>;
140
141impl<T> From<nom::error::Error<T>> for Error {
142    fn from(err: nom::error::Error<T>) -> Self {
143        Self::PacketError(err.code)
144    }
145}
146
147impl<I> ParseError<I> for Error {
148    fn from_error_kind(_input: I, kind: nom::error::ErrorKind) -> Self {
149        Self::ParsingError(kind)
150    }
151
152    fn append(_input: I, _kind: nom::error::ErrorKind, other: Self) -> Self {
153        other
154    }
155}
156
157impl<I, E> FromExternalError<I, E> for Error {
158    fn from_external_error(input: I, kind: nom::error::ErrorKind, e: E) -> Self {
159        nom::error::Error::from_external_error(input, kind, e).into()
160    }
161}
162
163impl From<Error> for nom::Err<Error> {
164    fn from(err: Error) -> Self {
165        Self::Error(err)
166    }
167}
168
169impl ErrorConvert<Self> for Error {
170    fn convert(self) -> Self {
171        self
172    }
173}
174
175impl From<nom::Err<Error>> for Error {
176    fn from(err: nom::Err<Error>) -> Self {
177        match err {
178            nom::Err::Incomplete(err) => Self::Incomplete(err),
179            nom::Err::Error(err) | nom::Err::Failure(err) => err,
180        }
181    }
182}
183
184impl<T> From<nom::Err<nom::error::Error<T>>> for Error {
185    fn from(err: nom::Err<nom::error::Error<T>>) -> Error {
186        match err {
187            nom::Err::Incomplete(err) => Self::Incomplete(err),
188            nom::Err::Error(err) | nom::Err::Failure(err) => Self::ParsingError(err.code),
189        }
190    }
191}
192
193impl From<rsa::errors::Error> for Error {
194    fn from(err: rsa::errors::Error) -> Error {
195        Error::RSAError(err)
196    }
197}
198
199impl From<cipher::InvalidLength> for Error {
200    fn from(_: cipher::InvalidLength) -> Error {
201        Error::CfbInvalidKeyIvLength
202    }
203}
204
205impl From<block_padding::UnpadError> for Error {
206    fn from(_: block_padding::UnpadError) -> Error {
207        Error::UnpadError
208    }
209}
210
211impl From<String> for Error {
212    fn from(err: String) -> Error {
213        Error::Message(err)
214    }
215}
216
217impl From<derive_builder::UninitializedFieldError> for Error {
218    fn from(err: derive_builder::UninitializedFieldError) -> Error {
219        Error::Message(err.to_string())
220    }
221}
222
223#[macro_export]
224macro_rules! unimplemented_err {
225    ($e:expr) => {
226        return Err($crate::errors::Error::Unimplemented($e.to_string()))
227    };
228    ($fmt:expr, $($arg:tt)+) => {
229        return Err($crate::errors::Error::Unimplemented(format!($fmt, $($arg)+)))
230    };
231}
232
233#[macro_export]
234macro_rules! unsupported_err {
235    ($e:expr) => {
236        return Err($crate::errors::Error::Unsupported($e.to_string()))
237    };
238    ($fmt:expr, $($arg:tt)+) => {
239        return Err($crate::errors::Error::Unsupported(format!($fmt, $($arg)+)))
240    };
241}
242
243#[macro_export]
244macro_rules! bail {
245    ($e:expr) => {
246        return Err($crate::errors::Error::Message($e.to_string()))
247    };
248    ($fmt:expr, $($arg:tt)+) => {
249        return Err($crate::errors::Error::Message(format!($fmt, $($arg)+)))
250    };
251}
252
253#[macro_export]
254macro_rules! format_err {
255    ($e:expr) => {
256        $crate::errors::Error::Message($e.to_string())
257    };
258    ($fmt:expr, $($arg:tt)+) => {
259        $crate::errors::Error::Message(format!($fmt, $($arg)+))
260    };
261}
262
263#[macro_export(local_inner_macros)]
264macro_rules! ensure {
265    ($cond:expr, $e:expr) => {
266        if !($cond) {
267            bail!($e);
268        }
269    };
270    ($cond:expr, $fmt:expr, $($arg:tt)+) => {
271        if !($cond) {
272            bail!($fmt, $($arg)+);
273        }
274    };
275}
276
277#[macro_export]
278macro_rules! ensure_eq {
279    ($left:expr, $right:expr) => ({
280        match (&$left, &$right) {
281            (left_val, right_val) => {
282                if !(*left_val == *right_val) {
283                    bail!(r#"assertion failed: `(left == right)`
284  left: `{:?}`,
285 right: `{:?}`"#, left_val, right_val)
286                }
287            }
288        }
289    });
290    ($left:expr, $right:expr,) => ({
291        ensure_eq!($left, $right)
292    });
293    ($left:expr, $right:expr, $($arg:tt)+) => ({
294        match (&($left), &($right)) {
295            (left_val, right_val) => {
296                if !(*left_val == *right_val) {
297                    bail!(r#"assertion failed: `(left == right)`
298  left: `{:?}`,
299 right: `{:?}`: {}"#, left_val, right_val,
300                           format_args!($($arg)+))
301                }
302            }
303        }
304    });
305}
306
307#[macro_export]
308macro_rules! err_opt {
309    ($e:expr) => {
310        match $e {
311            Ok(v) => v,
312            Err(err) => return Some(Err(err)),
313        }
314    };
315}