bitlocker/error.rs
1//! Error type for the BitLocker reader/decryptor.
2//!
3//! The reader never panics on malformed input: out-of-range reads yield safe
4//! defaults through the bounds-checked helpers. Genuine failures — a non-BitLocker
5//! image, an unsupported cipher, a wrong password (CCM tag mismatch), or missing
6//! key material — surface as loud, specific errors that carry the offending value,
7//! never a silent empty result.
8
9/// An error decoding or unlocking a BitLocker (BDE) volume.
10#[derive(Debug, thiserror::Error)]
11pub enum BdeError {
12 /// An I/O error reading the underlying volume.
13 #[error("i/o error reading BitLocker volume: {0}")]
14 Io(#[from] std::io::Error),
15
16 /// The volume header carries neither a BitLocker `-FVE-FS-` signature nor a
17 /// BitLocker To Go `MSWIN4.1` signature. The offending bytes at offset 3 are
18 /// included so the caller can identify what was actually there.
19 #[error("not a BitLocker volume: signature at offset 3 is {signature:02x?} (expected \"-FVE-FS-\" or \"MSWIN4.1\")")]
20 NotBitLocker {
21 /// The 8 bytes found at offset 3 of the volume header.
22 signature: [u8; 8],
23 },
24
25 /// No FVE metadata block carried a valid `-FVE-FS-` block-header signature at
26 /// any of the three candidate offsets read from the volume header.
27 #[error("no valid FVE metadata block found at candidate offsets {offsets:?}")]
28 NoValidMetadata {
29 /// The three candidate byte offsets tried.
30 offsets: [u64; 3],
31 },
32
33 /// The volume's encryption method is not one this build decrypts. The raw
34 /// method value is included.
35 #[error("unsupported encryption method 0x{method:04x} (this build decrypts 0x8000 AES-128-CBC + Elephant Diffuser)")]
36 UnsupportedEncryptionMethod {
37 /// The raw 16-bit encryption-method value from the metadata header.
38 method: u16,
39 },
40
41 /// The metadata carries no password-protected VMK (protection type 0x2000),
42 /// so `unlock_with_password` cannot proceed. The protector types that *were*
43 /// present are listed to guide the examiner toward the right unlock path.
44 #[error("no password protector (type 0x2000) present; protectors found: {found:?}")]
45 NoPasswordProtector {
46 /// The key-protection types that were present.
47 found: Vec<u16>,
48 },
49
50 /// The password-protected VMK is missing its stretch key or AES-CCM key
51 /// entry, so the VMK cannot be derived. Names which part is absent.
52 #[error("password protector is malformed: missing {what}")]
53 MissingKeyMaterial {
54 /// Which required sub-entry was absent (e.g. "stretch key", "AES-CCM key").
55 what: &'static str,
56 },
57
58 /// The AES-CCM authentication tag did not verify — for a password unlock this
59 /// means the supplied password is wrong; for FVEK it means the VMK is wrong.
60 #[error(
61 "AES-CCM authentication failed unwrapping the {what} (wrong password or corrupt metadata)"
62 )]
63 AuthenticationFailed {
64 /// Which key was being unwrapped ("volume master key" or "FVEK").
65 what: &'static str,
66 },
67
68 /// A decrypted key container was shorter than the fixed layout requires, or a
69 /// key field ran past the end of the plaintext.
70 #[error("decrypted {what} key container is malformed (got {got} bytes, need at least {need})")]
71 MalformedKeyContainer {
72 /// Which container ("volume master key" or "FVEK").
73 what: &'static str,
74 /// Bytes actually present.
75 got: usize,
76 /// Minimum bytes the layout requires.
77 need: usize,
78 },
79}
80
81/// Convenience alias for reader results.
82pub type Result<T> = std::result::Result<T, BdeError>;