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::Error),
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 #[error("unexpected end of file")]
327 Eof,
328}
329
330#[derive(Debug, thiserror::Error)]
332pub enum VariantDictionaryError {
333 #[error("Invalid variant dictionary version: {}", version)]
334 InvalidVersion { version: u16 },
335
336 #[error("Invalid value type: {}", value_type)]
337 InvalidValueType { value_type: u8 },
338
339 #[error("Missing key: {}", key)]
340 MissingKey { key: String },
341
342 #[error("Mistyped value: {}", key)]
343 Mistyped { key: String },
344
345 #[error("VariantDictionary did not end with null byte, when it should")]
346 NotTerminated,
347}
348
349#[derive(Debug, thiserror::Error)]
351pub enum XmlParseError {
352 #[error(transparent)]
353 Xml(#[from] xml::reader::Error),
354
355 #[error(transparent)]
356 Base64(#[from] base64::DecodeError),
357
358 #[error(transparent)]
359 TimestampFormat(#[from] chrono::ParseError),
360
361 #[error(transparent)]
362 IntFormat(#[from] std::num::ParseIntError),
363
364 #[error(transparent)]
365 BoolFormat(#[from] std::str::ParseBoolError),
366
367 #[error(transparent)]
368 Uuid(#[from] uuid::Error),
369
370 #[error(transparent)]
371 Color(#[from] ParseColorError),
372
373 #[error(transparent)]
374 Cryptography(#[from] CryptographyError),
375
376 #[error("Decompression error: {}", _0)]
377 Compression(#[source] std::io::Error),
378
379 #[error("Bad XML event: expected {}, got {:?}", expected, event)]
382 BadEvent {
383 expected: &'static str,
384 event: crate::format::xml_db::parse::SimpleXmlEvent,
385 },
386
387 #[error("Unexpected end of XML document")]
389 Eof,
390}
391
392#[derive(Debug, thiserror::Error)]
394#[error("Cannot parse color: '{}'", _0)]
395pub struct ParseColorError(pub String);
396
397mod conversions {
399 use super::{
400 BlockStreamError, CompressionConfigError, CryptographyError, DatabaseIntegrityError, DatabaseOpenError, InnerCipherConfigError,
401 KdfConfigError, OuterCipherConfigError, VariantDictionaryError, XmlParseError,
402 };
403
404 impl From<CryptographyError> for DatabaseOpenError {
405 fn from(e: CryptographyError) -> Self {
406 DatabaseIntegrityError::from(e).into()
407 }
408 }
409
410 impl From<BlockStreamError> for DatabaseOpenError {
411 fn from(e: BlockStreamError) -> Self {
412 DatabaseIntegrityError::from(e).into()
413 }
414 }
415
416 impl From<XmlParseError> for DatabaseOpenError {
417 fn from(e: XmlParseError) -> Self {
418 DatabaseIntegrityError::from(e).into()
419 }
420 }
421
422 impl From<InnerCipherConfigError> for DatabaseOpenError {
423 fn from(e: InnerCipherConfigError) -> Self {
424 DatabaseIntegrityError::from(e).into()
425 }
426 }
427
428 impl From<OuterCipherConfigError> for DatabaseOpenError {
429 fn from(e: OuterCipherConfigError) -> Self {
430 DatabaseIntegrityError::from(e).into()
431 }
432 }
433
434 impl From<KdfConfigError> for DatabaseOpenError {
435 fn from(e: KdfConfigError) -> Self {
436 DatabaseIntegrityError::from(e).into()
437 }
438 }
439
440 impl From<VariantDictionaryError> for DatabaseOpenError {
441 fn from(e: VariantDictionaryError) -> Self {
442 DatabaseIntegrityError::from(e).into()
443 }
444 }
445
446 impl From<CompressionConfigError> for DatabaseOpenError {
447 fn from(e: CompressionConfigError) -> Self {
448 DatabaseIntegrityError::from(e).into()
449 }
450 }
451}