1use crate::Algorithm;
4use core::fmt;
5
6#[cfg(feature = "alloc")]
7use crate::certificate;
8
9#[cfg(feature = "ppk")]
10use crate::ppk::PpkParseError;
11
12#[cfg(doc)]
13use crate::HashAlg;
14
15pub type Result<T> = core::result::Result<T, Error>;
17
18#[derive(Clone, Debug, Eq, PartialEq)]
20#[non_exhaustive]
21pub enum Error {
22 AlgorithmUnknown,
26
27 AlgorithmUnsupported {
35 algorithm: Algorithm,
37 },
38
39 #[cfg(feature = "alloc")]
41 CertificateFieldInvalid(certificate::Field),
42
43 CertificateValidation,
45
46 Crypto,
48
49 Decrypted,
51
52 #[cfg(feature = "ecdsa")]
54 Ecdsa(sec1::Error),
55
56 Encoding(encoding::Error),
58
59 Encrypted,
61
62 FormatEncoding,
64
65 HashSize,
67
68 #[cfg(feature = "std")]
70 Io(std::io::ErrorKind),
71
72 Namespace,
74
75 PublicKey,
77
78 #[cfg(feature = "ppk")]
80 Ppk(PpkParseError),
81
82 #[cfg(feature = "rand_core")]
84 RngFailure,
85
86 Signature,
88
89 Time,
91
92 TrailingData {
94 remaining: usize,
96 },
97
98 Version {
100 number: u32,
102 },
103}
104
105impl fmt::Display for Error {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 match self {
108 Error::AlgorithmUnknown => write!(f, "unknown algorithm"),
109 Error::AlgorithmUnsupported { algorithm } => {
110 write!(f, "unsupported algorithm: {algorithm}")
111 }
112 #[cfg(feature = "alloc")]
113 Error::CertificateFieldInvalid(field) => {
114 write!(f, "certificate field invalid: {field}")
115 }
116 Error::CertificateValidation => write!(f, "certificate validation failed"),
117 Error::Crypto => write!(f, "cryptographic error"),
118 Error::Decrypted => write!(f, "private key is already decrypted"),
119 #[cfg(feature = "ecdsa")]
120 Error::Ecdsa(err) => write!(f, "ECDSA encoding error: {err}"),
121 Error::Encoding(err) => write!(f, "{err}"),
122 Error::Encrypted => write!(f, "private key is encrypted"),
123 Error::FormatEncoding => write!(f, "format encoding error"),
124 Error::HashSize => write!(f, "hash is the wrong size for the given algorithm"),
125 #[cfg(feature = "std")]
126 Error::Io(err) => write!(f, "I/O error: {}", std::io::Error::from(*err)),
127 Error::Namespace => write!(f, "namespace invalid"),
128 #[cfg(feature = "ppk")]
129 Error::Ppk(err) => write!(f, "PPK parsing error: {err}"),
130 Error::PublicKey => write!(f, "public key is incorrect"),
131 #[cfg(feature = "rand_core")]
132 Error::RngFailure => write!(f, "random number generator failure"),
133 Error::Signature => write!(f, "signature error"),
134 Error::Time => write!(f, "invalid time"),
135 Error::TrailingData { remaining } => write!(
136 f,
137 "unexpected trailing data at end of message ({remaining} bytes)",
138 ),
139 Error::Version { number: version } => write!(f, "version unsupported: {version}"),
140 }
141 }
142}
143
144impl core::error::Error for Error {
145 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
146 match self {
147 #[cfg(feature = "ecdsa")]
148 Self::Ecdsa(err) => Some(err),
149 Self::Encoding(err) => Some(err),
150 _ => None,
151 }
152 }
153}
154
155impl From<cipher::Error> for Error {
156 fn from(_: cipher::Error) -> Error {
157 Error::Crypto
158 }
159}
160
161impl From<core::array::TryFromSliceError> for Error {
162 fn from(_: core::array::TryFromSliceError) -> Error {
163 Error::Encoding(encoding::Error::Length)
164 }
165}
166
167impl From<core::str::Utf8Error> for Error {
168 fn from(err: core::str::Utf8Error) -> Error {
169 Error::Encoding(err.into())
170 }
171}
172
173impl From<encoding::Error> for Error {
174 fn from(err: encoding::Error) -> Error {
175 Error::Encoding(err)
176 }
177}
178
179impl From<encoding::LabelError> for Error {
180 fn from(err: encoding::LabelError) -> Error {
181 Error::Encoding(err.into())
182 }
183}
184
185impl From<encoding::base64::Error> for Error {
186 fn from(err: encoding::base64::Error) -> Error {
187 Error::Encoding(err.into())
188 }
189}
190
191impl From<encoding::pem::Error> for Error {
192 fn from(err: encoding::pem::Error) -> Error {
193 Error::Encoding(err.into())
194 }
195}
196
197#[cfg(not(feature = "alloc"))]
198impl From<signature::Error> for Error {
199 fn from(_: signature::Error) -> Error {
200 Error::Signature
201 }
202}
203
204#[cfg(feature = "alloc")]
205impl From<signature::Error> for Error {
206 fn from(err: signature::Error) -> Error {
207 use core::error::Error as _;
208
209 err.source()
210 .and_then(|source| source.downcast_ref().cloned())
211 .unwrap_or(Error::Signature)
212 }
213}
214
215#[cfg(not(feature = "alloc"))]
216impl From<Error> for signature::Error {
217 fn from(_: Error) -> signature::Error {
218 signature::Error::new()
219 }
220}
221
222#[cfg(feature = "alloc")]
223impl From<Error> for signature::Error {
224 fn from(err: Error) -> signature::Error {
225 signature::Error::from_source(err)
226 }
227}
228
229#[cfg(feature = "alloc")]
230impl From<alloc::string::FromUtf8Error> for Error {
231 fn from(err: alloc::string::FromUtf8Error) -> Error {
232 Error::Encoding(err.into())
233 }
234}
235
236#[cfg(feature = "ecdsa")]
237impl From<sec1::Error> for Error {
238 fn from(err: sec1::Error) -> Error {
239 Error::Ecdsa(err)
240 }
241}
242
243#[cfg(any(feature = "dsa", feature = "rsa"))]
244impl From<encoding::bigint::DecodeError> for Error {
245 fn from(err: encoding::bigint::DecodeError) -> Error {
246 encoding::Error::from(err).into()
247 }
248}
249
250#[cfg(feature = "rsa")]
251impl From<rsa::errors::Error> for Error {
252 fn from(_: rsa::errors::Error) -> Error {
253 Error::Crypto
254 }
255}
256
257#[cfg(feature = "std")]
258impl From<std::io::Error> for Error {
259 fn from(err: std::io::Error) -> Error {
260 Error::Io(err.kind())
261 }
262}
263
264#[cfg(feature = "std")]
265impl From<std::time::SystemTimeError> for Error {
266 fn from(_: std::time::SystemTimeError) -> Error {
267 Error::Time
268 }
269}