filevault/error.rs
1//! Error type for the FileVault / CoreStorage decryptor.
2
3use thiserror::Error;
4
5/// Errors surfaced while parsing or decrypting a CoreStorage / FileVault volume.
6///
7/// Every failure is loud and named (Fail-loud): a bootstrap failure — a missing
8/// CoreStorage signature, an unreadable metadata block, a failed key unwrap — is
9/// an explicit error, never an empty/`Ok` degrade. A per-artifact miss inside a
10/// validated volume is the only place a silent skip is legitimate.
11#[derive(Debug, Error)]
12#[non_exhaustive]
13pub enum FileVaultError {
14 /// An I/O error reading the underlying image.
15 #[error("i/o error: {0}")]
16 Io(#[from] std::io::Error),
17
18 /// The physical volume header does not carry the CoreStorage `"CS"`
19 /// signature at offset 88 — this is not a CoreStorage volume. Carries the
20 /// bytes that WERE found (Show-the-unrecognized-value).
21 #[error("not a CoreStorage volume: signature at offset 88 was {found:#06x}, expected 0x5343 (\"CS\")")]
22 NotCoreStorage {
23 /// The 2 signature bytes actually found, little-endian.
24 found: u16,
25 },
26
27 /// The encryption method is not AES-XTS-128 (the only supported method).
28 #[error("unsupported encryption method {found}: only 2 (AES-XTS-128) is supported")]
29 UnsupportedEncryptionMethod {
30 /// The encryption-method code found in the header at offset 172.
31 found: u32,
32 },
33
34 /// A required metadata structure could not be located in the (decrypted)
35 /// metadata — the encryption context, a wrapped-key struct, or the family
36 /// UUID. Names which one so the investigator knows what was missing.
37 #[error("required metadata structure not found: {what}")]
38 MetadataStructureMissing {
39 /// Which structure was missing (e.g. "encryption context plist").
40 what: &'static str,
41 },
42
43 /// A base64 blob in the encryption context did not decode.
44 #[error("base64 decode failed for {what}")]
45 Base64 {
46 /// Which blob failed to decode.
47 what: &'static str,
48 },
49
50 /// An RFC 3394 AES key-unwrap failed (wrong password, or corrupt wrapped
51 /// key): the integrity check value did not match `0xA6A6A6A6A6A6A6A6`.
52 /// The password-derived unwrap failing is the "wrong password" signal.
53 #[error("key unwrap failed for {what}: wrong password or corrupt wrapped key")]
54 KeyUnwrap {
55 /// Which key failed to unwrap (KEK or VMK).
56 what: &'static str,
57 },
58
59 /// A length or count field taken from the image was out of range.
60 #[error("value out of range: {what}")]
61 OutOfRange {
62 /// What was out of range.
63 what: &'static str,
64 },
65}