Skip to main content

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}