man: Try to explain PBKDF hardcoded limits.

This commit is contained in:
Milan Broz
2025-07-23 17:18:36 +02:00
parent e0a5fb2c25
commit 267de08586
2 changed files with 28 additions and 8 deletions

View File

@@ -736,13 +736,27 @@ This will override the values without benchmarking.
Note it can cause extremely long unlocking time or cause out-of-memory conditions with unconditional process termination.
Use only in specific cases, for example, if you know that the formatted device will be used on some small embedded system.
+
*MINIMAL AND MAXIMAL PBKDF COSTS:* For *PBKDF2*, the minimum iteration count is 1000 and maximum is 4294967295 (maximum for 32-bit unsigned integer).
Memory and parallel costs are unused for PBKDF2.
*MINIMAL AND MAXIMAL PBKDF COSTS:* For *PBKDF2*, the minimum iteration count is 1000 and the maximum is 4294967295 (maximum for 32-bit unsigned integer).
Memory and parallel costs are not supported for PBKDF2.
For *Argon2i* and *Argon2id*, the minimum iteration count (CPU cost) is 4, and the maximum is 4294967295 (maximum for a 32-bit unsigned integer).
Minimum memory cost is 32 KiB and maximum is 4 GiB.
(Limited by addressable memory on some CPU platforms.)
If the memory cost parameter is benchmarked (not specified by a parameter), it is always in the range from 64 MiB to 1 GiB.
The parallel cost minimum is 1 and maximum 4 (if enough CPU cores are available, otherwise it is decreased).
Memory cost above 1GiB (up to the 4GiB maximum) can be setup only by the --pbkdf-memory parameter.
The parallel cost minimum is 1 and maximum 4 (if enough CPU cores are available, otherwise it is decreased by the available CPU cores).
+
*WARNING:* Increasing PBKDF computational costs above the mentioned limits provides negligible additional security improvement.
While elevated costs significantly increase brute-force overhead, they offer negligible protection against dictionary attacks.
The marginal cost increase for processing an entire dictionary remains fundamentally insufficient.
+
The hardcoded PBKDF limits represent engineered trade-offs between cryptographic security and operational usability.
LUKS maintains portability and must be used within a reasonable time on resource-constrained systems.
+
Cryptsetup deliberately restricts maximum memory cost (4 GiB) and parallel cost (4) parameters due to architectural limitations (like embedded and legacy systems).
+
PBKDF memory cost mandates actual physical RAM allocation with intensive write operations that must remain in physical RAM.
Any swap usage results in unacceptable performance degradation.
Memory management often overcommits allocations beyond available physical memory, expecting most allocated memory to remain unused.
In such situations, as PBKDF always uses all allocated memory, it frequently causes out-of-memory failures that abort cryptsetup operations.
endif::[]
ifdef::ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_REENCRYPT[]

View File

@@ -98,7 +98,7 @@ For most purposes, both terms can be used interchangeably.
LUKS can manage multiple passphrases that can be individually revoked or changed.
Each passphrase uses an individual keyslot containing a volume key for data encryption.
Keyslots can be securely scrubbed from persistent media due to the use of anti-forensic stripes.
Passphrases are protected against brute-force and dictionary attacks by the Password-Based Key Derivation Function (PBKDF).
Passphrases are protected against brute-force attacks by the Password-Based Key Derivation Function (PBKDF).
A passphrase stored in a file is called a key file.
The only difference between a passphrase and a key file is that a key file can contain binary data.
Both are processed the same.
@@ -489,8 +489,6 @@ The maximum input size is defined by the same compiled-in default as the maximum
=== Passphrase processing for LUKS
LUKS uses PBKDF to protect against dictionary attacks and to give some protection to low-entropy passphrases (see cryptsetup FAQ).
*From a terminal*: The passphrase is read until the first newline and then processed by PBKDF2 without the newline character.
*From stdin*: LUKS will read passphrases from stdin up to the first newline character or the compiled-in maximum key file length.
@@ -500,7 +498,15 @@ If --keyfile-size is given, it is ignored.
Newline characters do not terminate the input.
The --keyfile-size option can be used to limit what is read.
*Passphrase processing*: Whenever a passphrase is added to a LUKS header (luksAddKey, luksFormat), the user may specify how much time the passphrase processing should consume.
LUKS uses *Password-Based Key Derivation Function* (PBKDF) to protect against brute-force attacks and to give some protection to low-entropy passphrases (see cryptsetup FAQ).
LUKS1 supports the PBKDF2 algorithm only, while LUKS2 also supports memory-hard Argon2.
PBKDFs are configured with costs: how long the iteration should run (CPU cost or iteration count), how much memory is used (memory cost), and how many parallel processes are used (parallel cost).
PBKDF2 supports only iteration count.
Cryptsetup uses PBKDF benchmarking to calculate optimal costs based on the computer where the new passphrase is being initialized.
If needed, these costs can also be overwritten.
Note that there are some hardcoded limits, for details see *MINIMAL AND MAXIMAL PBKDF COSTS* section in --pbkdf option description.
Whenever a passphrase is added to a LUKS header (luksAddKey, luksFormat), the user may specify how much time the passphrase processing should consume.
The time is used to determine the iteration count for PBKDF2, and higher times will offer better protection for low-entropy passphrases, but the open command will take longer to complete.
For passphrases that have entropy higher than the used key length, higher iteration times will not increase security.