Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use stronger LUKS Argon2id parameters (in installer and dist-upgrade) #8600

Open
no-usernames-left opened this issue Oct 12, 2023 · 4 comments
Labels
C: dist upgrade The code and tools that support upgrading in-place from one Qubes OS release to another C: installer cryptography This issue pertains to cryptography. P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality.

Comments

@no-usernames-left
Copy link

no-usernames-left commented Oct 12, 2023

The problem you're addressing (if any)

LUKS has default KDF parameters which allow it to be used on a wide spectrum of hardware. Qubes OS has very significant base system requirements, and Qubes users typically have a different risk model than the average computer user (which is why they're using Qubes in the first place); in fact, many are higher-value targets (with data of higher value to adversaries) than the average.

The solution you'd like

We should increase the default Argon2id parameters for LUKS to memory cost 1024 MiB, ops cost 4, parallelism 1.

This is based upon the recommendations of @soatok, a well-respected cryptographer:

If you’re deriving an encryption key from a password, use any of the following algorithms:

  • scrypt with N = 1048576, r = 8, p = 1 and a random salt at least 128 bits in length (256 preferred)
  • Argon2id with a memory cost of 1024 MiB, ops cost of 4, and parallelism of 1

The value to a user, and who that user might be

It would appear as though argon2i is less resistant to attack by sophisticated adversaries than initially thought (1,2).

This would benefit ~all Qubes OS users.

@no-usernames-left no-usernames-left added P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality. labels Oct 12, 2023
@no-usernames-left
Copy link
Author

no-usernames-left commented Oct 12, 2023

#8582 is related (for upgrades from 4.1 to 4.2).

@no-usernames-left no-usernames-left changed the title LUKS KDF: Increase Argon2id parameters from upstream LUKS KDF: Increase Argon2id parameters from upstream for new installs Oct 12, 2023
@andrewdavidwong andrewdavidwong changed the title LUKS KDF: Increase Argon2id parameters from upstream for new installs Use stronger LUKS Argon2id parameters (in installer and dist-upgrade) Oct 12, 2023
@andrewdavidwong andrewdavidwong added C: installer cryptography This issue pertains to cryptography. C: dist upgrade The code and tools that support upgrading in-place from one Qubes OS release to another labels Oct 12, 2023
@andrewdavidwong
Copy link
Member

andrewdavidwong commented Oct 12, 2023

Argon2id with a memory cost of 1024 MiB, ops cost of 4, and parallelism of 1

I know that Argon2id is the new LUKS default, but what are the default parameters? All I've been able to find so far is this:

https://man7.org/linux/man-pages/man8/cryptsetup-luksConvertKey.8.html

       MINIMAL AND MAXIMAL PBKDF COSTS: For PBKDF2, the minimum
       iteration count is 1000 and maximum is 4294967295 (maximum
       for 32bit unsigned integer). Memory and parallel costs are
       unused for PBKDF2. For Argon2i and Argon2id, minimum
       iteration count (CPU cost) is 4 and maximum is 4294967295
       (maximum for 32bit 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
       range from 64 MiB to 1 GiB. The parallel cost minimum is 1
       and maximum 4 (if enough CPUs cores are available, otherwise
       it is decreased).

Let's go through the three recommended parameters and compare the two quotations.

Memory cost

The recommendation is 1024 MiB, whereas the minimum is either 32 KiB (absolute min) or 64 MiB (when unspecified). If I understand correctly, however, LUKS will automatically choose a memory cost for each specific machine by effectively "benchmarking" that particular machine. So, in practice, I'm guessing that all Qubes machines will automatically have a higher memory cost than 64 MiB even with default LUKS settings, but I don't know whether it will be at least 1024 MiB.

The current minimum system requirements for Qubes OS require at least 6 GB or memory, and it looks like dom0 can go up to 4 GB while the system is running (e.g., after shutting down enough other VMs), so it looks like there might be room for a Qubes-specific default setting higher than 1024 MiB here, but I don't know whether this will have any unintended consequences elsewhere.

Ops cost

The recommendation says "ops cost of 4," but the man page says "minimum iteration count (CPU cost) is 4." Are these the same thing? If so, it sounds like the recommendation is already the minimum. I don't know what the LUKS default is, but it can't be lower than the minimum.

Parallelism

The recommendation says "parallelism of 1," and the man page says "the parallel cost minimum is 1." So, again, it sounds like the recommendation is already the minimum. Again, I don't know what the LUKS default is, but it can't be lower than the minimum.

The current minimum system requirements for Qubes OS require a 64-bit Intel or AMD processor with certain features, so maybe there's room here to choose a higher safe default, but I'm not sure.

Conclusion

It looks like the recommendation is pretty conservative and already coincides with the minimums for two out of three parameters. It also seems like there's a good chance that the memory cost used in practice with default settings already meets or exceeds the recommendation, but I don't know. I also don't know what the actual LUKS defaults are.

@UndeadDevel
Copy link

I'll give some feedback after experimenting and reading a bit about this:

The RFC recommendation for memory cost on argon2id setups is 6 GB for hard-drive encryption (albeit with a weak CPU), while the general recommendation for all settings is 2 GB if that much RAM is available; with Qubes, dom0 is usually limited to 4 GB RAM (with another 4 GB swap typically), and cryptsetup AFAIU still limits the memory parameter to 4 GB, but both 4 and 6 GB as the default would likely create problems with changing the passphrase within dom0. I do think it makes sense to use 2 GB as the default (instead of 1 GB), however, as that works without even using swap and the idea behind argon2id difficulty is primarily about memory and parallelism and only secondarily about iterations.

Regarding parallelism the max allowed by cryptsetup seems to be 4 and it will, just as with the memory cost, treat this parameter as a maximum; i.e. if there are less than 4 cores on the system, cryptsetup will choose a lower number despite the parameter being 4; 4 is also the default for argon2 in cryptsetup, so a specific Qubes default doesn't really seem to be necessary.

Finally, regarding iterations it is best not to mess with that parameter (also WARNING to anyone wanting to experiment: argon2 iteration envelopes are in a completely different realm from pbkdf2 iteration envelopes...if you are familiar with the latter from LUKS1 and use e.g. --pbkdf-force-iterations=800000 with argon2, prepare to go into disaster recovery after you realize that your system will now be generating a key for the next weeks / months / years depending on which other parameters you chose).
Instead, the best practice is to choose an iteration time (-i=milliseconds) with the default for LUKS2 being 2000 ms; here I suppose QubesOS, being a security focused operating system, may choose a bit higher a value, perhaps between 3000 and 5000 ms. Note that the reason cryptsetup makes 4 iterations the minimum is because there have been attacks demonstrated against argon2i (not argon2id), which make decryption easier if less than 4 (or, according to an improved version of the attack, less than 10) iterations are used, but the linked RFC seems to disagree and feels that 1 iteration is okay if spending more time is not desired, though they do state:

The best attack on Argon2id can be obtained by complementing the best attack on the 1-pass Argon2i with the best attack on a multi-pass Argon2d. Thus, the best trade-off attack on 1-pass Argon2id is the combined low-storage attack (for the first half of the memory) and the ranking attack (for the second half), which generate the factor of about 2.1. The best trade-off attack on t-pass Argon2id is the ranking trade-off attack, which reduces the time-area product by the factor of 1.33.

Thus choosing at least 2 iterations is probably desired nevertheless, so the cryptsetup minimum of 4 is probably a good thing.

In any case, one should not choose more iterations while decreasing memory or parallelism, so I think the biggest takeaway here should be that increasing default memory cost from 1 GB to 2 GB in the Qubes installer / upgrader should be seriously considered.

@no-usernames-left
Copy link
Author

the biggest takeaway here should be that increasing default memory cost from 1 GB to 2 GB in the Qubes installer / upgrader should be seriously considered.

Agreed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: dist upgrade The code and tools that support upgrading in-place from one Qubes OS release to another C: installer cryptography This issue pertains to cryptography. P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality.
Projects
None yet
Development

No branches or pull requests

3 participants