Here I want to report on an article https://mjg59.dreamwidth.org/#entry-66429 I read on Matthew Garrett’s blog https://mjg59.dreamwidth.org
In his post, he is telling the story of a French activist who was arrested and his laptop seized. The man thought he was safe because his data were LUKS2 encrypted, with a very strong passphrase - the kind that no ordinary people could ever remember: it was 20+ characters with a mix of cases, numbers, and punctuation.
But surprisingly so, the police was able to decrypt the FDE partition and could use the plaintext as evidence against him.
So, how could this have happened, considering that:
- the guy never disclosed his password willingly or under threat
- he was not “physically brute-forced” to do so (French don’t do this)
- it doesn’t seem like there was any op-sec failure (e.g. his password written somewhere on a piece of paper or inside a smartphone, a keylogger, Evil Maid, stealth filming, password recycling, suspend-to-ram…)
Considering those facts, Garrett came up with a startling conclusion: the remaining possibility is that his high entropy passphrase was successfully brute-forced!
Now, if the French authorities can do this, we have to assume that just about any State actor can also do it (not that they would be considered particularly bad at cracking ciphers, but the implication is that this is now only a matter of shelling out millions $$ to buy loads of high-end GPUs.) If this is indeed the case, I would also suspect that very well resourced agencies have been able to do it for years.
To understand the problem, we have to look at how LUKS works: the final masterkey (AES) used to encrypt/decrypt the block device on-the-fly is encrypted via an intermediate key. This secondary key protecting the AES masterkey is itself the result (the output) of a computation called a Key Derivation Function (KDF) which takes a passphrase or a keyfile as an input. This scheme is so designed that when you want to change your passphrase (e.g. if you suspect it was breached), you can do so without having to re-encrypt the whole partition; same thing if you want to add another password or keyfile. Each password resides in a different key slot of the LUKS header, but the masterkey always remains the same.
When LUKS was first devised, it supported only one such KDF algorithm: PBKDF2, which is extremely “computationally expensive”. At the time, it was thought that brute-forcing it was realistically impractical. The technology just wasn’t there given the enormous number crunching involved. However later on with the LUKS2 specification, the designers took into account that ultimately sometime in the future this would become feasible; so they provided additional KDF algorithms that would be expensive not purely in computation but in other ways. One such new algorithm is argon2id - it is “memory expensive”.
To explain the concept, I am quoting Matthew Garrett who put it so clearly:
<<If the KDF algorithm requires a significant amount of RAM, the degree to which it can be performed in parallel on a GPU is massively reduced. A Geforce 4090 may have 16,384 execution units, but if each password attempt requires 1GB of RAM and the card only has 24GB on board, the attacker is restricted to running 24 attempts in parallel.>>
Looks like it may be time to switch to such safer KDF as argon2id. Unfortunately, it is not the default KDF when a LUKS2 container is first created - most likely all your active keyslots are still pbkdf2. In his article, Garrett then goes on explaining how to proceed. Be warned, though, that this is not for everyone to attempt if you don’t clearly understand what those cryptsetup cli do: it could quickly end up in a disaster, loss of partition or unbootable system.
I have tried his procedure on a Qubes laptop and this was easily done. There was no need to convert from LUKS to LUKS2, and only one keyslot was active (it was pbkdf2 although I had clean-installed v4.1)
It’s a different story for PureOS: there could be as many as 3 active keyslots, depending whether you ran the smartcard-key-luks script or not. I found it much trickier, because all keyslots have to be converted to argon2id or killed; and it is not obvious to determine which keyslot is what (in my case, slot0 could be killed - it was created at install time for purpose of having separate encrypted /home or other partitions; slot1 was the main passphrase and slot2 was the smartcard-key-luks unlock scheme)
Special care should be taken if you use GRUB2 as a bootloader (e.g. coreboot/seabios) and you have an encrypted /boot: it seems that GRUB2 is not [yet] able to handle argon2id - resulting in an unbootable system.