Skip to main content

LuksError

Enum LuksError 

Source
#[non_exhaustive]
pub enum LuksError { NotLuks { found: [u8; 6], }, UnsupportedVersion { version: u16, }, Unsupported { what: &'static str, value: String, }, UnlockBudgetExceeded { slots_tried: usize, budget_secs: u64, }, DerivationBudgetExceeded { iterations: u32, projected_secs: u64, budget_secs: u64, }, ImplausibleStripes { stripes: usize, max: usize, block_size: usize, }, DerivationMemoryExceeded { requested_kib: u32, max_kib: u32, }, KeyLengthExceeded { requested: usize, max: usize, }, MalformedHeader { what: &'static str, need: usize, got: usize, }, AuthenticationFailed, NoActiveKeyslot, Io(Error), }
Expand description

A LUKS parse or unlock failure. Every variant names the offending value so an investigator can act on it (never a bare “invalid”).

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

NotLuks

The LUKS\xba\xbe magic is absent — not a LUKS container.

Fields

§found: [u8; 6]

The first six bytes actually found.

§

UnsupportedVersion

The header version is neither 1 nor 2.

Fields

§version: u16

The version field value.

§

Unsupported

The cipher/mode/hash combination has no validated decrypt path.

Fields

§what: &'static str

Which axis is unsupported (cipher, mode, hash).

§value: String

The offending value verbatim.

§

UnlockBudgetExceeded

The keyslot demands more key-derivation work than the wall-clock budget allows. The iteration count comes from the header, so a crafted container can ask for billions of rounds; refusing is the only way the tool stays responsive on hostile input.

A refusal, never a silent reduction: deriving with fewer rounds than the header specifies produces a different key, which would report a wrong An unlock exhausted its TOTAL time budget across all keyslots.

Distinct from Self::DerivationBudgetExceeded, which bounds a single derivation. LUKS permits 8 keyslots and the header decides how many are active and what each costs, so a crafted header can stay under the per-derivation budget on every slot while the sum runs for hours. Each individual check passes; nothing owns the total. This variant is that total.

Fields

§slots_tried: usize

How many keyslots had been attempted when the budget ran out.

§budget_secs: u64

The total budget for the whole unlock.

§

DerivationBudgetExceeded

passphrase for a container that would in fact have opened.

Fields

§iterations: u32

The iteration count the header asked for, verbatim.

§projected_secs: u64

Projected cost on this machine, measured from a calibration run.

§budget_secs: u64

The budget that was exceeded.

§

ImplausibleStripes

The keyslot’s anti-forensic stripe count is not plausible.

stripes is a header field, so the container chooses it. It multiplies the key size to give the key-material length the caller then allocates, and it is the trip count of the AF merge loop — so an unbounded value is both an allocation and a spin, on the container’s say-so.

LUKS1 fixes the count at 4000 and cryptsetup writes the same for LUKS2, so the ceiling sits far above anything genuine.

Fields

§stripes: usize

The stripe count the header asked for, verbatim.

§max: usize

The ceiling that was exceeded.

§block_size: usize

The key size the count would have been multiplied by.

§

DerivationMemoryExceeded

The Argon2 keyslot demands more memory than the ceiling allows.

Separate from Self::DerivationBudgetExceeded because memory cannot be bounded the same way: a time cost can be measured and projected, but attempting an oversized allocation is itself the harm — the process is killed by the OS before any deadline could fire. argon2::Params caps m_cost at u32::MAX 1 KiB blocks (4 TiB) and the header chooses the value, so the ceiling has to be ours.

Fields

§requested_kib: u32

The memory cost the header asked for, verbatim, in KiB blocks.

§max_kib: u32

The ceiling that was exceeded, in KiB blocks.

§

KeyLengthExceeded

The header asks to derive a master key longer than the ceiling allows.

A third cost axis, independent of iterations and of Argon2 memory, and bounded for the same reason as the memory one: the derived-key length multiplies the work of every PBKDF2 iteration (ceil(dkLen / hLen) HMAC blocks each), and it sizes an allocation. Crucially it also sizes the CALIBRATION probe used to project the iteration cost, so leaving it unbounded makes the measurement itself the denial of service — the guard has to run before anything is measured or allocated.

Fields

§requested: usize

The master-key length the header asked for, verbatim, in bytes.

§max: usize

The ceiling that was exceeded, in bytes.

§

MalformedHeader

The header is structurally malformed (a field runs past the buffer).

Fields

§what: &'static str

What was being read.

§need: usize

Bytes needed.

§got: usize

Bytes available.

§

AuthenticationFailed

No keyslot could be unlocked with the supplied passphrase, or the derived master key failed the mk-digest check (wrong passphrase).

§

NoActiveKeyslot

The container carries no active (enabled) keyslot.

§

Io(Error)

An I/O error reading the container.

Trait Implementations§

Source§

impl Debug for LuksError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for LuksError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for LuksError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<Error> for LuksError

Source§

fn from(source: Error) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.