ssh_key/
error.rs

1//! Error types
2
3use crate::pem;
4use core::fmt;
5
6#[cfg(feature = "alloc")]
7use crate::certificate;
8
9/// Result type with `ssh-key`'s [`Error`] as the error type.
10pub type Result<T> = core::result::Result<T, Error>;
11
12/// Error type.
13#[derive(Copy, Clone, Debug, Eq, PartialEq)]
14#[non_exhaustive]
15pub enum Error {
16    /// Algorithm-related errors.
17    Algorithm,
18
19    /// Base64-related errors.
20    Base64(base64ct::Error),
21
22    /// Certificate field is invalid or already set.
23    #[cfg(feature = "alloc")]
24    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
25    CertificateFieldInvalid(certificate::Field),
26
27    /// Certificate validation failed.
28    CertificateValidation,
29
30    /// Character encoding-related errors.
31    CharacterEncoding,
32
33    /// Cryptographic errors.
34    Crypto,
35
36    /// Cannot perform operation on decrypted private key.
37    Decrypted,
38
39    /// ECDSA key encoding errors.
40    #[cfg(feature = "ecdsa")]
41    #[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
42    Ecdsa(sec1::Error),
43
44    /// Cannot perform operation on encrypted private key.
45    Encrypted,
46
47    /// Other format encoding errors.
48    FormatEncoding,
49
50    /// Input/output errors.
51    #[cfg(feature = "std")]
52    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
53    Io(std::io::ErrorKind),
54
55    /// Invalid length.
56    Length,
57
58    /// Overflow errors.
59    Overflow,
60
61    /// PEM encoding errors.
62    Pem(pem::Error),
63
64    /// Public key does not match private key.
65    PublicKey,
66
67    /// Invalid timestamp (e.g. in a certificate)
68    Time,
69
70    /// Unexpected trailing data at end of message.
71    TrailingData {
72        /// Number of bytes of remaining data at end of message.
73        remaining: usize,
74    },
75}
76
77impl fmt::Display for Error {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        match self {
80            Error::Algorithm => write!(f, "unknown or unsupported algorithm"),
81            Error::Base64(err) => write!(f, "Base64 encoding error: {}", err),
82            #[cfg(feature = "alloc")]
83            Error::CertificateFieldInvalid(field) => {
84                write!(f, "certificate field invalid: {}", field)
85            }
86            Error::CertificateValidation => write!(f, "certificate validation failed"),
87            Error::CharacterEncoding => write!(f, "character encoding invalid"),
88            Error::Crypto => write!(f, "cryptographic error"),
89            Error::Decrypted => write!(f, "private key is already decrypted"),
90            #[cfg(feature = "ecdsa")]
91            Error::Ecdsa(err) => write!(f, "ECDSA encoding error: {}", err),
92            Error::Encrypted => write!(f, "private key is encrypted"),
93            Error::FormatEncoding => write!(f, "format encoding error"),
94            #[cfg(feature = "std")]
95            Error::Io(err) => write!(f, "I/O error: {}", std::io::Error::from(*err)),
96            Error::Length => write!(f, "length invalid"),
97            Error::Overflow => write!(f, "internal overflow error"),
98            Error::Pem(err) => write!(f, "{}", err),
99            Error::PublicKey => write!(f, "public key is incorrect"),
100            Error::Time => write!(f, "invalid time"),
101            Error::TrailingData { remaining } => write!(
102                f,
103                "unexpected trailing data at end of message ({} bytes)",
104                remaining
105            ),
106        }
107    }
108}
109
110impl From<base64ct::Error> for Error {
111    fn from(err: base64ct::Error) -> Error {
112        Error::Base64(err)
113    }
114}
115
116impl From<base64ct::InvalidLengthError> for Error {
117    fn from(_: base64ct::InvalidLengthError) -> Error {
118        Error::Length
119    }
120}
121
122impl From<core::array::TryFromSliceError> for Error {
123    fn from(_: core::array::TryFromSliceError) -> Error {
124        Error::Length
125    }
126}
127
128impl From<core::num::TryFromIntError> for Error {
129    fn from(_: core::num::TryFromIntError) -> Error {
130        Error::Overflow
131    }
132}
133
134impl From<core::str::Utf8Error> for Error {
135    fn from(_: core::str::Utf8Error) -> Error {
136        Error::CharacterEncoding
137    }
138}
139
140impl From<pem_rfc7468::Error> for Error {
141    fn from(err: pem_rfc7468::Error) -> Error {
142        Error::Pem(err)
143    }
144}
145
146#[cfg(feature = "alloc")]
147#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
148impl From<alloc::string::FromUtf8Error> for Error {
149    fn from(_: alloc::string::FromUtf8Error) -> Error {
150        Error::CharacterEncoding
151    }
152}
153
154#[cfg(feature = "ecdsa")]
155#[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
156impl From<sec1::Error> for Error {
157    fn from(err: sec1::Error) -> Error {
158        Error::Ecdsa(err)
159    }
160}
161
162#[cfg(feature = "rsa")]
163#[cfg_attr(docsrs, doc(cfg(feature = "rsa")))]
164impl From<rsa::errors::Error> for Error {
165    fn from(_: rsa::errors::Error) -> Error {
166        Error::Crypto
167    }
168}
169
170#[cfg(feature = "signature")]
171#[cfg_attr(docsrs, doc(cfg(feature = "signature")))]
172impl From<signature::Error> for Error {
173    fn from(_: signature::Error) -> Error {
174        Error::Crypto
175    }
176}
177
178#[cfg(feature = "signature")]
179#[cfg_attr(docsrs, doc(cfg(feature = "signature")))]
180impl From<Error> for signature::Error {
181    fn from(_: Error) -> signature::Error {
182        signature::Error::new()
183    }
184}
185
186#[cfg(feature = "std")]
187#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
188impl From<std::io::Error> for Error {
189    fn from(err: std::io::Error) -> Error {
190        Error::Io(err.kind())
191    }
192}
193
194#[cfg(feature = "std")]
195impl From<std::time::SystemTimeError> for Error {
196    fn from(_: std::time::SystemTimeError) -> Error {
197        Error::Time
198    }
199}
200
201#[cfg(feature = "std")]
202impl std::error::Error for Error {}