diff --git a/der/src/error.rs b/der/src/error.rs index 902863d49..0891b8da3 100644 --- a/der/src/error.rs +++ b/der/src/error.rs @@ -11,17 +11,24 @@ use crate::asn1::ObjectIdentifier; #[cfg(feature = "pem")] use crate::pem; +#[cfg(feature = "std")] +use alloc::boxed::Box; + /// Result type. pub type Result = core::result::Result; /// Error type. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Debug)] pub struct Error { /// Kind of error. kind: ErrorKind, /// Position inside of message where error occurred. position: Option, + + /// Source of the error. + #[cfg(feature = "std")] + source: Option>, } impl Error { @@ -30,6 +37,8 @@ impl Error { Error { kind, position: Some(position), + #[cfg(feature = "std")] + source: None, } } @@ -48,15 +57,27 @@ impl Error { } /// Get the [`ErrorKind`] which occurred. - pub fn kind(self) -> ErrorKind { + pub fn kind(&self) -> ErrorKind { self.kind } /// Get the position inside of the message where the error occurred. - pub fn position(self) -> Option { + pub fn position(&self) -> Option { self.position } + /// Set the source of this error. Useful for e.g. propagating an additional error with + /// [`ErrorKind::Value`]. + /// + /// Overwrites any previously set source. + #[cfg(feature = "std")] + pub fn set_source(&mut self, source: E) + where + E: std::error::Error + Send + Sync + 'static, + { + self.source = Some(Box::new(source)); + } + /// For errors occurring inside of a nested message, extend the position /// count by the location where the nested message occurs. pub(crate) fn nested(self, nested_position: Length) -> Self { @@ -66,13 +87,12 @@ impl Error { Self { kind: self.kind, position, + #[cfg(feature = "std")] + source: self.source, } } } -#[cfg(feature = "std")] -impl std::error::Error for Error {} - impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.kind)?; @@ -85,11 +105,20 @@ impl fmt::Display for Error { } } +impl Eq for Error {} +impl PartialEq for Error { + fn eq(&self, other: &Self) -> bool { + self.kind == other.kind && self.position == other.position + } +} + impl From for Error { fn from(kind: ErrorKind) -> Error { Error { kind, position: None, + #[cfg(feature = "std")] + source: None, } } } @@ -101,10 +130,12 @@ impl From for Error { } impl From for Error { - fn from(_: TryFromIntError) -> Error { + fn from(err: TryFromIntError) -> Error { Error { kind: ErrorKind::Overflow, position: None, + #[cfg(feature = "std")] + source: Some(Box::new(err)), } } } @@ -112,8 +143,10 @@ impl From for Error { impl From for Error { fn from(err: Utf8Error) -> Error { Error { - kind: ErrorKind::Utf8(err), + kind: ErrorKind::Utf8(err.clone()), position: None, + #[cfg(feature = "std")] + source: Some(Box::new(err)), } } } @@ -158,6 +191,15 @@ impl From for Error { } } +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.source + .as_ref() + .map(|source| source.as_ref() as &(dyn std::error::Error + 'static)) + } +} + /// Error type. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] diff --git a/pkcs1/src/error.rs b/pkcs1/src/error.rs index 135bcd7d9..8ea96ec8b 100644 --- a/pkcs1/src/error.rs +++ b/pkcs1/src/error.rs @@ -9,7 +9,7 @@ use der::pem; pub type Result = core::result::Result; /// Error type -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Debug, Eq, PartialEq)] #[non_exhaustive] pub enum Error { /// ASN.1 DER-related errors. @@ -92,4 +92,13 @@ impl From for Error { } #[cfg(feature = "std")] -impl std::error::Error for Error {} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Asn1(err) => Some(err), + #[cfg(feature = "pkcs8")] + Error::Pkcs8(err) => Some(err), + _ => None, + } + } +} diff --git a/pkcs5/Cargo.toml b/pkcs5/Cargo.toml index 31ca92803..40139eb51 100644 --- a/pkcs5/Cargo.toml +++ b/pkcs5/Cargo.toml @@ -33,6 +33,8 @@ hex-literal = "0.4" [features] alloc = [] +std = ["alloc"] + 3des = ["dep:des", "pbes2"] des-insecure = ["dep:des", "pbes2"] getrandom = ["rand_core/getrandom"] diff --git a/pkcs5/src/error.rs b/pkcs5/src/error.rs index 60571b3b7..c6d24e519 100644 --- a/pkcs5/src/error.rs +++ b/pkcs5/src/error.rs @@ -54,3 +54,6 @@ impl fmt::Display for Error { } } } + +#[cfg(feature = "std")] +impl std::error::Error for Error {} diff --git a/pkcs5/src/lib.rs b/pkcs5/src/lib.rs index 550cd0d5e..64287b01f 100644 --- a/pkcs5/src/lib.rs +++ b/pkcs5/src/lib.rs @@ -29,6 +29,9 @@ #[cfg(all(feature = "alloc", feature = "pbes2"))] extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + mod error; pub mod pbes1; diff --git a/pkcs8/Cargo.toml b/pkcs8/Cargo.toml index ce39f4f4f..c7e1450df 100644 --- a/pkcs8/Cargo.toml +++ b/pkcs8/Cargo.toml @@ -30,7 +30,7 @@ tempfile = "3" [features] alloc = ["der/alloc", "der/zeroize", "spki/alloc"] -std = ["alloc", "der/std", "spki/std"] +std = ["alloc", "der/std", "pkcs5?/std", "spki/std"] 3des = ["encryption", "pkcs5/3des"] des-insecure = ["encryption", "pkcs5/des-insecure"] diff --git a/pkcs8/src/error.rs b/pkcs8/src/error.rs index 70c60aedb..febacadac 100644 --- a/pkcs8/src/error.rs +++ b/pkcs8/src/error.rs @@ -9,7 +9,7 @@ use der::pem; pub type Result = core::result::Result; /// Error type -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Debug, Eq, PartialEq)] #[non_exhaustive] pub enum Error { /// ASN.1 DER-related errors. @@ -48,7 +48,17 @@ impl fmt::Display for Error { } #[cfg(feature = "std")] -impl std::error::Error for Error {} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Asn1(err) => Some(err), + #[cfg(feature = "pkcs5")] + Error::EncryptedPrivateKey(err) => Some(err), + Error::PublicKey(err) => Some(err), + _ => None, + } + } +} impl From for Error { fn from(err: der::Error) -> Error { diff --git a/pkcs8/tests/encrypted_private_key.rs b/pkcs8/tests/encrypted_private_key.rs index 9d601c749..51996b8f8 100644 --- a/pkcs8/tests/encrypted_private_key.rs +++ b/pkcs8/tests/encrypted_private_key.rs @@ -3,11 +3,14 @@ #![cfg(feature = "pkcs5")] use hex_literal::hex; -use pkcs8::{pkcs5::pbes2, EncryptedPrivateKeyInfo, PrivateKeyInfo}; +use pkcs8::{pkcs5::pbes2, EncryptedPrivateKeyInfo}; #[cfg(feature = "alloc")] use der::Encode; +#[cfg(feature = "encryption")] +use pkcs8::PrivateKeyInfo; + #[cfg(feature = "pem")] use der::EncodePem; diff --git a/sec1/src/error.rs b/sec1/src/error.rs index 0d8bc8b70..99cb0269a 100644 --- a/sec1/src/error.rs +++ b/sec1/src/error.rs @@ -9,7 +9,7 @@ use der::pem; pub type Result = core::result::Result; /// Error type -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Debug, Eq, PartialEq)] #[non_exhaustive] pub enum Error { /// ASN.1 DER-related errors. diff --git a/spki/src/error.rs b/spki/src/error.rs index 9d05990f3..c0156605e 100644 --- a/spki/src/error.rs +++ b/spki/src/error.rs @@ -10,7 +10,7 @@ pub type Result = core::result::Result; use der::pem; /// Error type -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Debug, Eq, PartialEq)] #[non_exhaustive] pub enum Error { /// Algorithm parameters are missing. @@ -65,4 +65,11 @@ impl From for Error { } #[cfg(feature = "std")] -impl std::error::Error for Error {} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Asn1(err) => Some(err), + _ => None, + } + } +}