1#[derive(thiserror::Error, Debug)]
4pub enum Error {
5 #[error("std::io::Error {0}")]
6 Io(#[from] std::io::Error),
7
8 #[error("DatabaseError::RecycleBinDisabled")]
9 RecycleBinDisabled,
10
11 #[error("DatabaseError::RecycleBinAlreadyExists")]
12 RecycleBinAlreadyExists,
13
14 #[error("DatabaseOpenError {0}")]
15 DatabaseOpenError(#[from] DatabaseOpenError),
16
17 #[error("DatabaseSaveError {0}")]
18 DatabaseSaveError(#[from] DatabaseSaveError),
19
20 #[cfg(feature = "totp")]
21 #[error("DbOtpError {0}")]
22 DbOtpError(#[from] crate::db::otp::TOTPError),
23
24 #[error("OuterCipherConfigError {0}")]
25 OuterCipherConfigError(#[from] OuterCipherConfigError),
26
27 #[error("InnerCipherConfigError {0}")]
28 InnerCipherConfigError(#[from] InnerCipherConfigError),
29
30 #[error("CompressionConfigError {0}")]
31 CompressionConfigError(#[from] CompressionConfigError),
32
33 #[error("KdfConfigError {0}")]
34 KdfConfigError(#[from] KdfConfigError),
35
36 #[error("CryptographyError {0}")]
37 CryptographyError(#[from] CryptographyError),
38
39 #[error("BlockStreamError {0}")]
40 BlockStreamError(#[from] BlockStreamError),
41
42 #[error("VariantDictionaryError {0}")]
43 VariantDictionaryError(#[from] VariantDictionaryError),
44
45 #[error("XmlParseError {0}")]
46 XmlParseError(#[from] XmlParseError),
47
48 #[error("ParseColorError {0}")]
49 ParseColorError(#[from] ParseColorError),
50
51 #[error("ParseIconIdError {}", icon_id)]
52 ParseIconIdError { icon_id: usize },
53
54 #[cfg(feature = "_merge")]
55 #[error("MergeError {0}")]
56 MergeError(#[from] crate::db::merge::MergeError),
57
58 #[error("String error: {0}")]
59 String(String),
60}
61
62impl From<&str> for Error {
63 fn from(s: &str) -> Self {
64 Error::String(s.to_string())
65 }
66}
67
68impl From<String> for Error {
69 fn from(s: String) -> Self {
70 Error::String(s)
71 }
72}
73
74impl From<&String> for Error {
75 fn from(s: &String) -> Self {
76 Error::String(s.clone())
77 }
78}
79
80pub type Result<T, E = Error> = std::result::Result<T, E>;
81
82pub type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
83
84#[derive(Debug, thiserror::Error)]
86pub enum DatabaseOpenError {
87 #[error(transparent)]
89 Io(#[from] std::io::Error),
90
91 #[error(transparent)]
93 Key(#[from] DatabaseKeyError),
94
95 #[error(transparent)]
97 DatabaseIntegrity(#[from] DatabaseIntegrityError),
98
99 #[error("Opening this database version is not supported")]
101 UnsupportedVersion,
102}
103
104#[derive(Debug, thiserror::Error)]
106pub enum DatabaseIntegrityError {
107 #[error("Invalid KDBX identifier")]
109 InvalidKDBXIdentifier,
110
111 #[error("Invalid KDBX version: {}.{}.{}", version, file_major_version, file_minor_version)]
113 InvalidKDBXVersion {
114 version: u32,
115 file_major_version: u32,
116 file_minor_version: u32,
117 },
118
119 #[error("Invalid header size: {}", size)]
121 InvalidFixedHeader { size: usize },
122
123 #[error("Invalid field length for type {}: {} (expected {})", field_type, field_size, expected_field_size)]
124 InvalidKDBFieldLength {
125 field_type: u16,
126 field_size: u32,
127 expected_field_size: u32,
128 },
129
130 #[error("Missing group level")]
131 MissingKDBGroupLevel,
132
133 #[error("Invalid KDBX header field ID: {}", field_id)]
134 InvalidKDBXHeaderFieldID { field_id: u8 },
135
136 #[error("Invalid group level {} (current level {})", group_level, current_level)]
137 InvalidKDBGroupLevel { group_level: u16, current_level: u16 },
138
139 #[error("Missing group ID")]
140 MissingKDBGroupId,
141
142 #[error("Invalid group ID {}", group_id)]
143 InvalidKDBGroupId { group_id: u32 },
144
145 #[error("Invalid group field type: {}", field_type)]
146 InvalidKDBGroupFieldType { field_type: u16 },
147
148 #[error("Invalid entry field type: {}", field_type)]
149 InvalidKDBEntryFieldType { field_type: u16 },
150
151 #[error("Incomplete group")]
152 IncompleteKDBGroup,
153
154 #[error("Incomplete entry")]
155 IncompleteKDBEntry,
156
157 #[error("Invalid fixed cipher ID: {}", cid)]
158 InvalidFixedCipherID { cid: u32 },
159
160 #[error("Header hash masmatch")]
161 HeaderHashMismatch,
162
163 #[error("Invalid outer header entry: {}", entry_type)]
164 InvalidOuterHeaderEntry { entry_type: u8 },
165
166 #[error("Incomplete outer header: Missing {}", missing_field)]
167 IncompleteOuterHeader { missing_field: String },
168
169 #[error("Invalid inner header entry: {}", entry_type)]
170 InvalidInnerHeaderEntry { entry_type: u8 },
171
172 #[error("Incomplete outer header: Missing {}", missing_field)]
173 IncompleteInnerHeader { missing_field: String },
174
175 #[error(transparent)]
176 Cryptography(#[from] CryptographyError),
177
178 #[error(transparent)]
179 Xml(#[from] XmlParseError),
180
181 #[error(transparent)]
182 OuterCipher(#[from] OuterCipherConfigError),
183
184 #[error(transparent)]
185 InnerCipher(#[from] InnerCipherConfigError),
186
187 #[error(transparent)]
188 Compression(#[from] CompressionConfigError),
189
190 #[error(transparent)]
191 BlockStream(#[from] BlockStreamError),
192
193 #[error(transparent)]
194 VariantDictionary(#[from] VariantDictionaryError),
195
196 #[error(transparent)]
197 KdfSettings(#[from] KdfConfigError),
198
199 #[error(transparent)]
200 Io(#[from] std::io::Error),
201}
202
203#[derive(Debug, thiserror::Error)]
205pub enum DatabaseSaveError {
206 #[error("Saving this database version is not supported")]
208 UnsupportedVersion,
209
210 #[error("Error while generating XML")]
212 Xml(#[from] xml::writer::Error),
213
214 #[error(transparent)]
216 Io(#[from] std::io::Error),
217
218 #[error(transparent)]
220 Key(#[from] DatabaseKeyError),
221
222 #[error(transparent)]
224 Cryptography(#[from] CryptographyError),
225
226 #[error(transparent)]
228 Random(#[from] getrandom::Error),
229}
230
231#[derive(Debug, thiserror::Error)]
233pub enum DatabaseKeyError {
234 #[error("Incorrect key")]
236 IncorrectKey,
237
238 #[error(transparent)]
240 Cryptography(#[from] CryptographyError),
241
242 #[error(transparent)]
244 Io(#[from] std::io::Error),
245
246 #[error(transparent)]
248 Xml(#[from] xml::reader::Error),
249
250 #[error("Could not obtain a key from the keyfile")]
252 InvalidKeyFile,
253
254 #[cfg(feature = "challenge_response")]
256 #[error("Error with the challenge-response key: {0}")]
257 ChallengeResponseKeyError(String),
258}
259
260#[derive(Debug, thiserror::Error)]
262pub enum OuterCipherConfigError {
263 #[error(transparent)]
264 Cryptography(#[from] CryptographyError),
265
266 #[error("Invalid outer cipher ID: {:?}", cid)]
267 InvalidOuterCipherID { cid: Vec<u8> },
268}
269
270#[derive(Debug, thiserror::Error)]
272pub enum InnerCipherConfigError {
273 #[error(transparent)]
274 Cryptography(#[from] CryptographyError),
275
276 #[error("Invalid inner cipher ID: {}", cid)]
277 InvalidInnerCipherID { cid: u32 },
278}
279
280#[derive(Debug, thiserror::Error)]
282pub enum CompressionConfigError {
283 #[error("Invalid compression algorithm: {}", cid)]
285 InvalidCompressionSuite { cid: u32 },
286}
287
288#[derive(Debug, thiserror::Error)]
290pub enum KdfConfigError {
291 #[error("Invalid KDF version: {}", version)]
292 InvalidKDFVersion { version: u32 },
293
294 #[error("Invalid KDF UUID: {:?}", uuid)]
295 InvalidKDFUUID { uuid: Vec<u8> },
296
297 #[error(transparent)]
298 VariantDictionary(#[from] VariantDictionaryError),
299}
300
301#[derive(Debug, thiserror::Error)]
303pub enum CryptographyError {
304 #[error(transparent)]
305 InvalidLength(#[from] cipher::InvalidLength),
306
307 #[error(transparent)]
308 Unpadding(#[from] cipher::block_padding::UnpadError),
309
310 #[error(transparent)]
311 Padding(#[from] cipher::inout::PadError),
312
313 #[error(transparent)]
314 Argon2(#[from] argon2::Error),
315}
316
317#[derive(Debug, thiserror::Error)]
319pub enum BlockStreamError {
320 #[error(transparent)]
321 Cryptography(#[from] CryptographyError),
322
323 #[error("Block hash mismatch for block {}", block_index)]
324 BlockHashMismatch { block_index: u64 },
325}
326
327#[derive(Debug, thiserror::Error)]
329pub enum VariantDictionaryError {
330 #[error("Invalid variant dictionary version: {}", version)]
331 InvalidVersion { version: u16 },
332
333 #[error("Invalid value type: {}", value_type)]
334 InvalidValueType { value_type: u8 },
335
336 #[error("Missing key: {}", key)]
337 MissingKey { key: String },
338
339 #[error("Mistyped value: {}", key)]
340 Mistyped { key: String },
341
342 #[error("VariantDictionary did not end with null byte, when it should")]
343 NotTerminated,
344}
345
346#[derive(Debug, thiserror::Error)]
348pub enum XmlParseError {
349 #[error(transparent)]
350 Xml(#[from] xml::reader::Error),
351
352 #[error(transparent)]
353 Base64(#[from] base64::DecodeError),
354
355 #[error(transparent)]
356 TimestampFormat(#[from] chrono::ParseError),
357
358 #[error(transparent)]
359 IntFormat(#[from] std::num::ParseIntError),
360
361 #[error(transparent)]
362 BoolFormat(#[from] std::str::ParseBoolError),
363
364 #[error(transparent)]
365 Uuid(#[from] uuid::Error),
366
367 #[error(transparent)]
368 Color(#[from] ParseColorError),
369
370 #[error(transparent)]
371 Cryptography(#[from] CryptographyError),
372
373 #[error("Decompression error: {}", _0)]
374 Compression(#[source] std::io::Error),
375
376 #[error("Bad XML event: expected {}, got {:?}", expected, event)]
379 BadEvent {
380 expected: &'static str,
381 event: crate::xml_db::parse::SimpleXmlEvent,
382 },
383
384 #[error("Unexpected end of XML document")]
386 Eof,
387}
388
389#[derive(Debug, thiserror::Error)]
391#[error("Cannot parse color: '{}'", _0)]
392pub struct ParseColorError(pub String);
393
394mod conversions {
396 use super::{
397 BlockStreamError, CompressionConfigError, CryptographyError, DatabaseIntegrityError, DatabaseOpenError, InnerCipherConfigError,
398 KdfConfigError, OuterCipherConfigError, VariantDictionaryError, XmlParseError,
399 };
400
401 impl From<CryptographyError> for DatabaseOpenError {
402 fn from(e: CryptographyError) -> Self {
403 DatabaseIntegrityError::from(e).into()
404 }
405 }
406
407 impl From<BlockStreamError> for DatabaseOpenError {
408 fn from(e: BlockStreamError) -> Self {
409 DatabaseIntegrityError::from(e).into()
410 }
411 }
412
413 impl From<XmlParseError> for DatabaseOpenError {
414 fn from(e: XmlParseError) -> Self {
415 DatabaseIntegrityError::from(e).into()
416 }
417 }
418
419 impl From<InnerCipherConfigError> for DatabaseOpenError {
420 fn from(e: InnerCipherConfigError) -> Self {
421 DatabaseIntegrityError::from(e).into()
422 }
423 }
424
425 impl From<OuterCipherConfigError> for DatabaseOpenError {
426 fn from(e: OuterCipherConfigError) -> Self {
427 DatabaseIntegrityError::from(e).into()
428 }
429 }
430
431 impl From<KdfConfigError> for DatabaseOpenError {
432 fn from(e: KdfConfigError) -> Self {
433 DatabaseIntegrityError::from(e).into()
434 }
435 }
436
437 impl From<VariantDictionaryError> for DatabaseOpenError {
438 fn from(e: VariantDictionaryError) -> Self {
439 DatabaseIntegrityError::from(e).into()
440 }
441 }
442
443 impl From<CompressionConfigError> for DatabaseOpenError {
444 fn from(e: CompressionConfigError) -> Self {
445 DatabaseIntegrityError::from(e).into()
446 }
447 }
448}