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