1use std::fmt;
16use std::io;
17use std::path::PathBuf;
18
19#[derive(Debug)]
21pub enum Error {
22 Io(io::Error),
24 InvalidKeyLength,
26 UnsupportedPkAlgo,
28 UnsupportedKdfAlgo,
30 FileTooShort,
32 FileTooLarge,
34 InvalidCommentHeader,
36 InvalidCommentUtf8,
38 PasswordMismatch,
40 PasswordReadFailed,
42 IncorrectPassphrase,
44 MissingPubKey,
46 KeyMismatch,
48 VerifyFailed,
50 AutolocateFailed(PathBuf, Box<Error>),
52 InvalidKeyName,
54 InvalidPath,
56 CheckFailed,
58 ChecksumMismatch(String),
60 ChecksumParseFailed(String),
62 UnsupportedHashAlgo(String),
64 Overflow,
66 Base64Decode(base64ct::Error),
68 Arg(lexopt::Error),
70 InvalidSignatureLength,
72 MissingGzipHeader,
74 MissingGzipSignature,
76 MissingSignatureNewline,
78 KeyringDisabled,
80 InvalidKeyId,
82 RequiredArg(&'static str),
84 MissingMode,
86 InvalidPasswordUtf8,
88 InvalidSignatureUtf8,
90 WeakPassword(Option<String>),
92 #[cfg(any(target_os = "linux", target_os = "android"))]
94 Keyring(linux_keyutils::KeyError),
95 Crypto(ed25519_compact::Error),
97 Rng(rand_core::OsError),
99 #[cfg(unix)]
100 Nix(nix::errno::Errno),
102 #[cfg(any(target_os = "linux", target_os = "android"))]
104 Landlock(landlock::RulesetError),
105 #[cfg(target_os = "freebsd")]
107 Capsicum(io::Error),
108 #[cfg(target_os = "openbsd")]
110 Pledge(pledge::Error),
111 #[cfg(target_os = "openbsd")]
113 Unveil(unveil::Error),
114}
115
116impl std::error::Error for Error {
117 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
118 match self {
119 Self::Io(err) => Some(err),
120 Self::Base64Decode(err) => Some(err),
121 Self::Arg(err) => Some(err),
122 #[cfg(unix)]
123 Self::Nix(err) => Some(err),
124 #[cfg(any(target_os = "linux", target_os = "android"))]
125 Self::Landlock(err) => Some(err),
126 #[cfg(target_os = "freebsd")]
127 Self::Capsicum(err) => Some(err),
128 #[cfg(target_os = "openbsd")]
129 Self::Pledge(err) => Some(err),
130 #[cfg(target_os = "openbsd")]
131 Self::Unveil(err) => Some(err),
132 _ => None,
133 }
134 }
135}
136
137impl fmt::Display for Error {
138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139 match self {
140 Self::Io(err) => write!(f, "IO error: {err}"),
141 Self::InvalidKeyLength => write!(f, "invalid key length"),
142 Self::UnsupportedPkAlgo => write!(f, "unsupported public key algorithm"),
143 Self::UnsupportedKdfAlgo => write!(f, "unsupported KDF algorithm"),
144 Self::FileTooShort => write!(f, "file too short"),
145 Self::FileTooLarge => write!(f, "file too large (memory limit exceeded)"),
146 Self::InvalidCommentHeader => write!(f, "invalid comment header"),
147 Self::InvalidCommentUtf8 => write!(f, "invalid comment (not utf8)"),
148 Self::InvalidPasswordUtf8 => write!(f, "invalid password (not utf8)"),
149 Self::InvalidSignatureUtf8 => write!(f, "invalid signature (base64 is not utf8)"),
150 Self::Base64Decode(err) => write!(f, "base64 decode error: {err}"),
151 Self::Arg(err) => write!(f, "argument error: {err}"),
152 Self::PasswordMismatch => write!(f, "password mismatch"),
153 Self::PasswordReadFailed => write!(f, "failed to read password"),
154 Self::IncorrectPassphrase => write!(f, "incorrect passphrase"),
155 Self::MissingPubKey => write!(f, "public key not found"),
156 Self::KeyMismatch => write!(f, "verification failed: checked against wrong key"),
157 Self::VerifyFailed => write!(f, "signature verification failed"),
158 Self::AutolocateFailed(path, err) => {
159 write!(f, "autolocate failed loading {}: {err}", path.display())
160 }
161 Self::InvalidKeyName => write!(f, "invalid key name"),
162 Self::InvalidPath => write!(f, "invalid path"),
163 Self::CheckFailed => write!(f, "checksum check failed"),
164 Self::ChecksumMismatch(file) => write!(f, "{file}: FAIL"),
165 Self::ChecksumParseFailed(line) => write!(f, "unable to parse: {line}"),
166 Self::UnsupportedHashAlgo(algo) => write!(f, "unsupported hash algorithm: {algo}"),
167 Self::Overflow => write!(f, "limit exceeded"),
168 Self::InvalidSignatureLength => write!(f, "invalid signature length"),
169 Self::MissingGzipHeader => write!(f, "missing gzip header"),
170 Self::MissingGzipSignature => write!(f, "missing signature in gzip comment"),
171 Self::MissingSignatureNewline => write!(f, "missing newline in signature"),
172 Self::KeyringDisabled => write!(f, "keyring support disabled"),
173 Self::InvalidKeyId => write!(f, "invalid key id"),
174 Self::RequiredArg(arg) => write!(f, "missing required argument: {arg}"),
175 Self::MissingMode => write!(f, "must specify mode"),
176 Self::WeakPassword(feedback) => {
177 if let Some(msg) = feedback {
178 write!(f, "password too weak: {msg}")
179 } else {
180 write!(f, "password too weak")
181 }
182 }
183 #[cfg(any(target_os = "linux", target_os = "android"))]
184 Self::Keyring(err) => write!(f, "keyring error: {err:?}"),
185 Self::Crypto(err) => write!(f, "crypto error: {err}"),
186 Self::Rng(err) => write!(f, "rng error: {err}"),
187 #[cfg(unix)]
188 Self::Nix(err) => write!(f, "UNIX error: {err}"),
189 #[cfg(any(target_os = "linux", target_os = "android"))]
190 Self::Landlock(err) => write!(f, "landlock error: {err}"),
191 #[cfg(target_os = "freebsd")]
192 Self::Capsicum(err) => write!(f, "capsicum error: {err}"),
193 #[cfg(target_os = "openbsd")]
194 Self::Pledge(err) => write!(f, "pledge error: {err}"),
195 #[cfg(target_os = "openbsd")]
196 Self::Unveil(err) => write!(f, "unveil error: {err}"),
197 }
198 }
199}
200
201impl From<ed25519_compact::Error> for Error {
202 fn from(err: ed25519_compact::Error) -> Self {
203 Self::Crypto(err)
204 }
205}
206
207#[cfg(unix)]
208impl From<nix::errno::Errno> for Error {
209 fn from(err: nix::errno::Errno) -> Self {
210 Self::Nix(err)
211 }
212}
213
214impl From<io::Error> for Error {
215 fn from(err: io::Error) -> Self {
216 Self::Io(err)
217 }
218}
219
220impl From<base64ct::Error> for Error {
221 fn from(err: base64ct::Error) -> Self {
222 Self::Base64Decode(err)
223 }
224}
225
226impl From<lexopt::Error> for Error {
227 fn from(err: lexopt::Error) -> Self {
228 Self::Arg(err)
229 }
230}
231
232#[cfg(any(target_os = "linux", target_os = "android"))]
233impl From<linux_keyutils::KeyError> for Error {
234 fn from(err: linux_keyutils::KeyError) -> Self {
235 Self::Keyring(err)
236 }
237}
238
239impl From<rand_core::OsError> for Error {
240 fn from(err: rand_core::OsError) -> Self {
241 Self::Rng(err)
242 }
243}
244
245#[cfg(target_os = "openbsd")]
246impl From<pledge::Error> for Error {
247 fn from(err: pledge::Error) -> Self {
248 Self::Pledge(err)
249 }
250}
251
252#[cfg(target_os = "openbsd")]
253impl From<unveil::Error> for Error {
254 fn from(err: unveil::Error) -> Self {
255 Self::Unveil(err)
256 }
257}
258
259#[cfg(any(target_os = "linux", target_os = "android"))]
260impl From<landlock::RulesetError> for Error {
261 fn from(err: landlock::RulesetError) -> Self {
262 Self::Landlock(err)
263 }
264}
265
266pub type Result<T> = std::result::Result<T, Error>;