1use std::num::TryFromIntError;
2
3use ed25519_dalek::SignatureError;
4use snafu::{Backtrace, Snafu};
5
6pub type Result<T, E = Error> = ::std::result::Result<T, E>;
7
8pub const MPI_TOO_LONG: u32 = 1000;
10
11pub use crate::parsing::{Error as ParsingError, RemainingError};
12
13#[derive(Debug, Snafu)]
15#[snafu(visibility(pub(crate)))]
16#[non_exhaustive]
17pub enum Error {
18 #[snafu(display("invalid input"))]
19 InvalidInput { backtrace: Option<Backtrace> },
20 #[snafu(display("invalid armor wrappers"))]
21 InvalidArmorWrappers,
22 #[snafu(display("invalid crc24 checksum"))]
23 InvalidChecksum,
24 #[snafu(transparent)]
25 Base64Decode {
26 source: base64::DecodeError,
27 backtrace: Option<Backtrace>,
28 },
29 #[snafu(display("requested data size is larger than the packet body"))]
30 RequestedSizeTooLarge,
31 #[snafu(display("no matching packet found"))]
32 NoMatchingPacket { backtrace: Option<Backtrace> },
33 #[snafu(display("more than one matching packet was found"))]
34 TooManyPackets,
35 #[snafu(display("packet contained more data than was parsable (trailing bytes {size})"))]
36 PacketTooLarge { size: u64 },
37 #[snafu(transparent)]
38 RSAError {
39 #[snafu(source(from(rsa::errors::Error, Box::new)))]
40 source: Box<rsa::errors::Error>,
41 backtrace: Option<Backtrace>,
42 },
43 #[snafu(transparent)]
44 EllipticCurve {
45 source: elliptic_curve::Error,
46 backtrace: Option<Backtrace>,
47 },
48 #[snafu(display("IO error: {}", source), context(false))]
49 IO {
50 source: std::io::Error,
51 backtrace: Option<Backtrace>,
52 },
53 #[snafu(display("invalid key length"))]
54 InvalidKeyLength,
55 #[snafu(display("block mode error"))]
56 BlockMode,
57 #[snafu(display("missing key"))]
58 MissingKey,
59 #[snafu(display("cfb: invalid key iv length"))]
60 CfbInvalidKeyIvLength,
61 #[snafu(display("Not yet implemented: {message}"))]
62 Unimplemented {
63 message: String,
64 backtrace: Option<Backtrace>,
65 },
66 #[snafu(display("Unsupported: {message}"))]
68 Unsupported {
69 message: String,
70 backtrace: Option<Backtrace>,
71 },
72 #[snafu(display("{message}"))]
73 Message {
74 message: String,
75 backtrace: Option<Backtrace>,
76 },
77 #[snafu(display("Invalid Packet {kind:?}"))]
78 PacketError { kind: nom::error::ErrorKind },
79 #[snafu(display("Unpadding failed"))]
80 UnpadError,
81 #[snafu(display("Padding failed"))]
82 PadError,
83 #[snafu(transparent)]
84 Utf8Error {
85 source: std::str::Utf8Error,
86 backtrace: Option<Backtrace>,
87 },
88 #[snafu(transparent)]
89 ParseIntError {
90 source: std::num::ParseIntError,
91 backtrace: Option<Backtrace>,
92 },
93 #[snafu(display("Invalid Packet Content {source:?}"))]
94 InvalidPacketContent { source: Box<Error> },
95 #[snafu(transparent)]
96 SignatureError { source: SignatureError },
97 #[snafu(display("Modification Detection Code error"))]
98 MdcError,
99 #[snafu(transparent)]
100 TryFromInt {
101 source: TryFromIntError,
102 backtrace: Option<Backtrace>,
103 },
104 #[snafu(display("AEAD {:?}", source), context(false))]
105 Aead { source: crate::crypto::aead::Error },
106 #[snafu(display("AES key wrap {:?}", source), context(false))]
107 AesKw {
108 source: crate::crypto::aes_kw::Error,
109 },
110 #[snafu(transparent)]
111 ChecksumMissmatch {
112 source: crate::crypto::checksum::ChecksumMismatch,
113 },
114 #[snafu(transparent)]
115 Sha1HashCollision {
116 source: crate::crypto::checksum::Sha1HashCollision,
117 },
118 #[snafu(transparent)]
119 AesKek { source: aes_kw::Error },
120 #[snafu(transparent)]
121 PacketParsing {
122 #[snafu(backtrace, source(from(ParsingError, Box::new)))]
123 source: Box<ParsingError>,
124 },
125 #[snafu(display("packet is incomplete"))]
126 PacketIncomplete {
127 #[snafu(backtrace)]
128 source: Box<ParsingError>,
129 },
130 #[snafu(transparent)]
131 Argon2 {
132 source: argon2::Error,
133 backtrace: Option<Backtrace>,
134 },
135 #[snafu(transparent)]
136 SigningError { source: cx448::SigningError },
137}
138
139impl From<crate::crypto::hash::Error> for Error {
140 fn from(err: crate::crypto::hash::Error) -> Self {
141 match err {
142 crate::crypto::hash::Error::Unsupported { alg } => UnsupportedSnafu {
143 message: format!("hash algorithm: {:?}", alg),
144 }
145 .build(),
146 crate::crypto::hash::Error::Sha1HashCollision { source } => source.into(),
147 }
148 }
149}
150
151impl<T> From<nom::error::Error<T>> for Error {
152 fn from(err: nom::error::Error<T>) -> Self {
153 Self::PacketError { kind: err.code }
154 }
155}
156
157impl From<cipher::InvalidLength> for Error {
158 fn from(_: cipher::InvalidLength) -> Error {
159 Error::CfbInvalidKeyIvLength
160 }
161}
162
163impl From<block_padding::UnpadError> for Error {
164 fn from(_: block_padding::UnpadError) -> Error {
165 Error::UnpadError
166 }
167}
168
169impl From<String> for Error {
170 fn from(err: String) -> Error {
171 Error::Message {
172 message: err,
173 backtrace: Some(snafu::GenerateImplicitData::generate()),
174 }
175 }
176}
177
178impl From<derive_builder::UninitializedFieldError> for Error {
179 fn from(err: derive_builder::UninitializedFieldError) -> Error {
180 Error::Message {
181 message: err.to_string(),
182 backtrace: Some(snafu::GenerateImplicitData::generate()),
183 }
184 }
185}
186
187macro_rules! unimplemented_err {
188 ($e:expr) => {
189 return Err($crate::errors::UnimplementedSnafu { message: $e.to_string() }.build())
190 };
191 ($fmt:expr, $($arg:tt)+) => {
192 return Err($crate::errors::UnimplementedSnafu { message: format!($fmt, $($arg)+)}.build())
193 };
194}
195
196macro_rules! unsupported_err {
197 ($e:expr) => {
198 return Err($crate::errors::UnsupportedSnafu {
199 message: $e.to_string(),
200 }.build())
201 };
202 ($fmt:expr, $($arg:tt)+) => {
203 return Err($crate::errors::UnsupportedSnafu {
204 message: format!($fmt, $($arg)+),
205 }.build())
206 };
207}
208
209macro_rules! bail {
210 ($e:expr) => {
211 return Err($crate::errors::Error::Message {
212 message: $e.to_string(),
213 backtrace: ::snafu::GenerateImplicitData::generate(),
214 })
215 };
216 ($fmt:expr, $($arg:tt)+) => {
217 return Err($crate::errors::Error::Message {
218 message: format!($fmt, $($arg)+),
219 backtrace: ::snafu::GenerateImplicitData::generate(),
220 })
221 };
222}
223
224macro_rules! format_err {
225 ($e:expr) => {
226 $crate::errors::Error::Message {
227 message: $e.to_string(),
228 backtrace: ::snafu::GenerateImplicitData::generate(),
229 }
230 };
231 ($fmt:expr, $($arg:tt)+) => {
232 $crate::errors::Error::Message {
233 message: format!($fmt, $($arg)+),
234 backtrace: ::snafu::GenerateImplicitData::generate(),
235 }
236 };
237}
238
239macro_rules! ensure {
240 ($cond:expr, $e:expr) => {
241 if !($cond) {
242 $crate::errors::bail!($e);
243 }
244 };
245 ($cond:expr, $fmt:expr, $($arg:tt)+) => {
246 if !($cond) {
247 $crate::errors::bail!($fmt, $($arg)+);
248 }
249 };
250}
251
252macro_rules! ensure_eq {
253 ($left:expr, $right:expr) => ({
254 match (&$left, &$right) {
255 (left_val, right_val) => {
256 if !(*left_val == *right_val) {
257 $crate::errors::bail!(r#"assertion failed: `(left == right)`
258 left: `{:?}`,
259 right: `{:?}`"#, left_val, right_val)
260 }
261 }
262 }
263 });
264 ($left:expr, $right:expr,) => ({
265 $crate::errors::ensure_eq!($left, $right)
266 });
267 ($left:expr, $right:expr, $($arg:tt)+) => ({
268 match (&($left), &($right)) {
269 (left_val, right_val) => {
270 if !(*left_val == *right_val) {
271 $crate::errors::bail!(r#"assertion failed: `(left == right)`
272 left: `{:?}`,
273 right: `{:?}`: {}"#, left_val, right_val,
274 format_args!($($arg)+))
275 }
276 }
277 }
278 });
279}
280
281macro_rules! err_opt {
282 ($e:expr) => {
283 match $e {
284 Ok(v) => v,
285 Err(err) => return Some(Err(err)),
286 }
287 };
288}
289
290pub(crate) use bail;
291pub(crate) use ensure;
292pub(crate) use ensure_eq;
293pub(crate) use err_opt;
294pub(crate) use format_err;
295pub(crate) use unimplemented_err;
296pub(crate) use unsupported_err;
297
298#[cfg(test)]
299mod tests {
300 #[cfg(target_pointer_width = "64")]
310 #[test]
311 fn size_of_error() {
312 assert_eq!(core::mem::size_of::<super::Error>(), 80);
313 }
314}