use std::num::TryFromIntError;
use ed25519_dalek::SignatureError;
use snafu::{Backtrace, Snafu};
pub type Result<T, E = Error> = ::std::result::Result<T, E>;
pub const MPI_TOO_LONG: u32 = 1000;
pub use crate::pgp::parsing::{Error as ParsingError, RemainingError};
#[derive(Debug, Snafu)]
#[snafu(visibility(pub(crate)))]
#[non_exhaustive]
pub enum Error {
#[snafu(display("invalid input"))]
InvalidInput { backtrace: Option<Backtrace> },
#[snafu(display("invalid armor wrappers"))]
InvalidArmorWrappers,
#[snafu(display("invalid crc24 checksum"))]
InvalidChecksum,
#[snafu(transparent)]
Base64Decode {
source: base64::DecodeError,
backtrace: Option<Backtrace>,
},
#[snafu(display("requested data size is larger than the packet body"))]
RequestedSizeTooLarge,
#[snafu(display("no matching packet found"))]
NoMatchingPacket { backtrace: Option<Backtrace> },
#[snafu(display("more than one matching packet was found"))]
TooManyPackets,
#[snafu(display("packet contained more data than was parsable (trailing bytes {size})"))]
PacketTooLarge { size: u64 },
#[snafu(transparent)]
RSAError {
#[snafu(source(from(rsa::errors::Error, Box::new)))]
source: Box<rsa::errors::Error>,
backtrace: Option<Backtrace>,
},
#[snafu(transparent)]
EllipticCurve {
source: elliptic_curve::Error,
backtrace: Option<Backtrace>,
},
#[snafu(display("IO error: {}", source), context(false))]
IO {
source: std::io::Error,
backtrace: Option<Backtrace>,
},
#[snafu(display("invalid key length"))]
InvalidKeyLength,
#[snafu(display("block mode error"))]
BlockMode,
#[snafu(display("missing key"))]
MissingKey,
#[snafu(display("cfb: invalid key iv length"))]
CfbInvalidKeyIvLength,
#[snafu(display("Not yet implemented: {message}"))]
Unimplemented {
message: String,
backtrace: Option<Backtrace>,
},
#[snafu(display("Unsupported: {message}"))]
Unsupported {
message: String,
backtrace: Option<Backtrace>,
},
#[snafu(display("{message}"))]
Message {
message: String,
backtrace: Option<Backtrace>,
},
#[snafu(display("Invalid Packet {kind:?}"))]
PacketError { kind: nom::error::ErrorKind },
#[snafu(display("Unpadding failed"))]
UnpadError,
#[snafu(display("Padding failed"))]
PadError,
#[snafu(transparent)]
Utf8Error {
source: std::str::Utf8Error,
backtrace: Option<Backtrace>,
},
#[snafu(transparent)]
ParseIntError {
source: std::num::ParseIntError,
backtrace: Option<Backtrace>,
},
#[snafu(display("Invalid Packet Content {source:?}"))]
InvalidPacketContent { source: Box<Error> },
#[snafu(transparent)]
SignatureError { source: SignatureError },
#[snafu(display("Modification Detection Code error"))]
MdcError,
#[snafu(transparent)]
TryFromInt {
source: TryFromIntError,
backtrace: Option<Backtrace>,
},
#[snafu(display("AEAD {:?}", source), context(false))]
Aead { source: crate::pgp::crypto::aead::Error },
#[snafu(display("AES key wrap {:?}", source), context(false))]
AesKw {
source: crate::pgp::crypto::aes_kw::Error,
},
#[snafu(transparent)]
ChecksumMissmatch {
source: crate::pgp::crypto::checksum::ChecksumMismatch,
},
#[snafu(transparent)]
Sha1HashCollision {
source: crate::pgp::crypto::checksum::Sha1HashCollision,
},
#[snafu(transparent)]
AesKek { source: aes_kw::Error },
#[snafu(transparent)]
PacketParsing {
#[snafu(backtrace, source(from(ParsingError, Box::new)))]
source: Box<ParsingError>,
},
#[snafu(display("packet is incomplete"))]
PacketIncomplete {
#[snafu(backtrace)]
source: Box<ParsingError>,
},
#[snafu(transparent)]
Argon2 {
source: argon2::Error,
backtrace: Option<Backtrace>,
},
#[snafu(transparent)]
SigningError { source: cx448::SigningError },
}
impl From<crate::pgp::crypto::hash::Error> for Error {
fn from(err: crate::pgp::crypto::hash::Error) -> Self {
match err {
crate::pgp::crypto::hash::Error::Unsupported { alg } => UnsupportedSnafu {
message: format!("hash algorithm: {alg:?}"),
}
.build(),
crate::pgp::crypto::hash::Error::Sha1HashCollision { source } => source.into(),
}
}
}
impl<T> From<nom::error::Error<T>> for Error {
fn from(err: nom::error::Error<T>) -> Self {
Self::PacketError { kind: err.code }
}
}
impl From<cipher::InvalidLength> for Error {
fn from(_: cipher::InvalidLength) -> Error {
Error::CfbInvalidKeyIvLength
}
}
impl From<block_padding::UnpadError> for Error {
fn from(_: block_padding::UnpadError) -> Error {
Error::UnpadError
}
}
impl From<String> for Error {
fn from(err: String) -> Error {
Error::Message {
message: err,
backtrace: Some(snafu::GenerateImplicitData::generate()),
}
}
}
impl From<derive_builder::UninitializedFieldError> for Error {
fn from(err: derive_builder::UninitializedFieldError) -> Error {
Error::Message {
message: err.to_string(),
backtrace: Some(snafu::GenerateImplicitData::generate()),
}
}
}
macro_rules! unimplemented_err {
($e:expr) => {
return Err($crate::pgp::errors::UnimplementedSnafu { message: $e.to_string() }.build())
};
($fmt:expr, $($arg:tt)+) => {
return Err($crate::pgp::errors::UnimplementedSnafu { message: format!($fmt, $($arg)+)}.build())
};
}
macro_rules! unsupported_err {
($e:expr) => {
return Err($crate::pgp::errors::UnsupportedSnafu {
message: $e.to_string(),
}.build())
};
($fmt:expr, $($arg:tt)+) => {
return Err($crate::pgp::errors::UnsupportedSnafu {
message: format!($fmt, $($arg)+),
}.build())
};
}
macro_rules! bail {
($e:expr) => {
return Err($crate::pgp::errors::Error::Message {
message: $e.to_string(),
backtrace: ::snafu::GenerateImplicitData::generate(),
})
};
($fmt:expr, $($arg:tt)+) => {
return Err($crate::pgp::errors::Error::Message {
message: format!($fmt, $($arg)+),
backtrace: ::snafu::GenerateImplicitData::generate(),
})
};
}
macro_rules! format_err {
($e:expr) => {
$crate::pgp::errors::Error::Message {
message: $e.to_string(),
backtrace: ::snafu::GenerateImplicitData::generate(),
}
};
($fmt:expr, $($arg:tt)+) => {
$crate::pgp::errors::Error::Message {
message: format!($fmt, $($arg)+),
backtrace: ::snafu::GenerateImplicitData::generate(),
}
};
}
macro_rules! ensure {
($cond:expr, $e:expr) => {
if !($cond) {
$crate::pgp::errors::bail!($e);
}
};
($cond:expr, $fmt:expr, $($arg:tt)+) => {
if !($cond) {
$crate::pgp::errors::bail!($fmt, $($arg)+);
}
};
}
macro_rules! ensure_eq {
($left:expr, $right:expr) => ({
match (&$left, &$right) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
$crate::pgp::errors::bail!(r#"assertion failed: `(left == right)`
left: `{:?}`,
right: `{:?}`"#, left_val, right_val)
}
}
}
});
($left:expr, $right:expr,) => ({
$crate::pgp::errors::ensure_eq!($left, $right)
});
($left:expr, $right:expr, $($arg:tt)+) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
$crate::pgp::errors::bail!(r#"assertion failed: `(left == right)`
left: `{:?}`,
right: `{:?}`: {}"#, left_val, right_val,
format_args!($($arg)+))
}
}
}
});
}
macro_rules! err_opt {
($e:expr) => {
match $e {
Ok(v) => v,
Err(err) => return Some(Err(err)),
}
};
}
pub(crate) use bail;
pub(crate) use ensure;
pub(crate) use ensure_eq;
pub(crate) use err_opt;
pub(crate) use format_err;
pub(crate) use unimplemented_err;
pub(crate) use unsupported_err;
#[cfg(test)]
mod tests {
#[cfg(target_pointer_width = "64")]
#[test]
fn size_of_error() {
assert_eq!(core::mem::size_of::<super::Error>(), 80);
}
}