cryptsetup.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* To make LUKS detached header even more secure?
@ 2022-06-07  2:41 midnite zandiro
  2022-06-07  6:36 ` Michael Kjörling
  0 siblings, 1 reply; 4+ messages in thread
From: midnite zandiro @ 2022-06-07  2:41 UTC (permalink / raw)
  To: cryptsetup

Dear LUKS Creators,

First of all, thank you very much for creating the powerful LUKS
program. Please accept  my deepest gratitude for your great works.

I have an enquiry about the volume master key and the keyslot digest.
And also a security aspect discussion on a detached header setup.

1. How are the volume master key and the keyslot digest generated?

I have skimmed through the source code. Please correct me if I am
wrong. I thought the volume masker key was generated from the
passphrase/the keyfile. But I found out that the volume master key is
actually generated by random, at /lib/volumekey.c line 141 in
crypt_generate_volume_key() -
https://gitlab.com/cryptsetup/cryptsetup/-/blob/main/lib/volumekey.c#L141
. This makes sense because LUKS enables us to specify the
--master-key-file directly. If MK is not generated independent to the
passphrase, we have to work reversely from MK and passphrase to obtain
the keyslot digest.

For the keyslot digest, I guess it is generated at
/lib/luks2/luks2_digest.c line 85 from LUKS2_digest_find_free() -
https://gitlab.com/cryptsetup/cryptsetup/-/blob/main/lib/luks2/luks2_digest.c#L85
. But I cannot trace any further as I cannot find the function body of
json_object_object_get_ex().

2. To achieve an even more secure design than the LUKS2 detached header?

With the header detached onto the USB Key, and volume locked with an
user passphrase, it is so-called a two-factor authentication setup.
However I find a weakness scenario in this setup. An attacker who
gains a clone of the USB Key can start his attack, without the need to
wait for an acquisition of encrypted disk. This weakness is mainly
because, with solely the header, we can verify if our passphrase is
correct.

IF the volume master key is generated from the user passphrase, please
consider another setup. Stored in the USB Key are the hashing options
(like PBKDF=argon2id, iteration cost=19, memory cost=4G, thread
cost=4) and also the salt. This is basically the LUKS2 header without
the digest. Using the passphrase, the salt, and the PBKDF options, we
can generate the volume master key as usual. However, there is no way
for the attacker to verify if the passphrase is correct. Until the
attacker obtains both the USB Key and the encrypted disk, he can
verify if the guessed volume master key reveals meaningful bytes (e.g.
by file system signatures) from the disk.

My suggested setup has its drawbacks. It cannot support multiple keys
obviously. If we store two sets of hashing options and salts in the
USB Key, the attacker will be able to verify if his guesses of the
volume master keys match.

However it is possible to change the user passphrase without
re-encryption. The setup needs to be tweaked a bit. Similarly we use
the user passphrase, hashing options, and the salt to generate a MK1.
With this MK1, we generate a series of random bits (MK). This series
of random bits is actually the volume master key (MK). MK will never
be stored plainly on the USB Key. Instead, the encrypted version,
encrypt(MK1, MK), is stored on the USB Key. Upon passphrase change, we
generate MK2 with the new passphrase, new hashing options, and new
salt. With MK1 also unlocked, we simply copy the MK to the new MK2's
container. Then another encrypted version, encrypt(MK2, MK), is stored
on the USB Key. This is very similar to the LUKS keyslot digests.
However, with only one set of hashing options and salt present in the
USB Key, the attacker is still impossible to verify his guesses of the
MK.

I would like to point out that this suggested setup is stronger than
using LUKS plain mode. It is because it inherits the same passphrase
hashing, with salting, and also AF diffusion. It performs everything
as what LUKS2 does. It intentionally drops the ability to store
multiple keys. In return, an attacker who gets only the USB Key (i.e.
the header) will not be able to start passphrase hacking.

In fact LUKS is already very secure, in addition to very convenient.
IF we can disable passphrase checking in the LUKS header, we can
tighten the security of a detached header setup even further.

Thank you very much for your time. Hope you are doing well everyday.

Best wishes,
midnite

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: To make LUKS detached header even more secure?
  2022-06-07  2:41 To make LUKS detached header even more secure? midnite zandiro
@ 2022-06-07  6:36 ` Michael Kjörling
  2022-06-08  0:05   ` midnite zandiro
  0 siblings, 1 reply; 4+ messages in thread
From: Michael Kjörling @ 2022-06-07  6:36 UTC (permalink / raw)
  To: cryptsetup

On 7 Jun 2022 10:41 +0800, from midnite.hk@gmail.com (midnite zandiro):
> 1. How are the volume master key and the keyslot digest generated?
> 
> I have skimmed through the source code. Please correct me if I am
> wrong. I thought the volume masker key was generated from the
> passphrase/the keyfile. But I found out that the volume master key is
> actually generated by random, at /lib/volumekey.c line 141 in
> crypt_generate_volume_key() -
> https://gitlab.com/cryptsetup/cryptsetup/-/blob/main/lib/volumekey.c#L141
> . This makes sense because LUKS enables us to specify the
> --master-key-file directly. If MK is not generated independent to the
> passphrase, we have to work reversely from MK and passphrase to obtain
> the keyslot digest.

There is an even bigger reason for generating the master key
independently of the passphrase: it preserves security when changing
the passphrase without requiring a full reencryption, which on large
media can take _days_. (A read/write pass over 8 TB at an average of
100 MB/s works out to about 1.8 days.) There's also the fact that LUKS
supports more than one passphrase, any one of which can be used to
unlock a container.


> 2. To achieve an even more secure design than the LUKS2 detached header?
> 
> With the header detached onto the USB Key, and volume locked with an
> user passphrase, it is so-called a two-factor authentication setup.

No, that is not proper 2FA. As is clearly demonstrated by your
argument about how the second storage device can be copied (and
relatively easily, at that), both are "something you know".

> However I find a weakness scenario in this setup. An attacker who
> gains a clone of the USB Key

There you have it.

> can start his attack, without the need to
> wait for an acquisition of encrypted disk. This weakness is mainly
> because, with solely the header, we can verify if our passphrase is
> correct.
> 
> IF the volume master key is generated from the user passphrase,

Well, since it isn't, the remainder of that paragraph becomes moot.


> However it is possible to change the user passphrase without
> re-encryption. The setup needs to be tweaked a bit. Similarly we use
> the user passphrase, hashing options, and the salt to generate a MK1.
> With this MK1, we generate a series of random bits (MK). This series
> of random bits is actually the volume master key (MK). MK will never
> be stored plainly on the USB Key. Instead, the encrypted version,
> encrypt(MK1, MK), is stored on the USB Key. Upon passphrase change, we
> generate MK2 with the new passphrase, new hashing options, and new
> salt. With MK1 also unlocked, we simply copy the MK to the new MK2's
> container. Then another encrypted version, encrypt(MK2, MK), is stored
> on the USB Key. This is very similar to the LUKS keyslot digests.
> However, with only one set of hashing options and salt present in the
> USB Key, the attacker is still impossible to verify his guesses of the
> MK.

So, if I understand correctly, what you are proposing is basically a
_split_ header, with part of the data stored in one location and part
of the data stored in another location, and one (but not both) of
those partial headers possibly detached from the container?

This requires storing some header data separate from the detached
header, which either requires some kind of "two detached headers"
setup (at which point we're back to your original threat model about
being able to copy both, since we're already assuming an attacker who
has access to the detached header) or causes a detached-header LUKS
container to no longer be length-preserving.

I'm struggling to see what the benefit of this would be in practice.
You claim increased resistance to passphrase guessing by an attacker
who has access to the detached header but not the encrypted (locked)
container itself, but there's already a simple way to do that:
increase iteration count, passphrase length, or both. Take as an
example a seven-word standard Diceware passphrase, which is hardly
onerous; that already gives you about 90 bits' worth of security,
which on its own is _almost_ sufficient. Throw in a few extra seconds'
worth of key derivation iteration, and that's likely very much
sufficient against a _cryptographic_ attack even by a highly
determined, powerful adversary. (The master key can be assumed to be
sufficiently secure against a cryptographic attack, because if it
wasn't, then the attacker would just go for that and not bother with
the passphrase at all.) Since this would be aimed only or primarily at
users who use a detached header stored on a separate device, who seem
likely to already care more about security than the average user, I
don't think either is an unreasonable assumption. At that point
something simple like a key logger or rubber hose cryptanalysis
appears a more likely threat.

https://xkcd.com/538/ applies.

None of this is to say that the security of LUKS couldn't _possibly_
be improved upon somehow (such a claim would be naiive), but there's
ample reason already to not add complexity based on what appears at
least to me to be a rather contrived threat model.

Some form of TPM integration, possibly coupled with secure
attestation, seems a more reasonable approach to guard against the
kind of attack against a detached header that you postulate.


> I would like to point out that this suggested setup is stronger than
> using LUKS plain mode.

There is no "LUKS plain mode". Sticking to what's reasonably available
in present-day-supported implementations, there's plain dm-crypt
(which is a straight one-to-one mapping between blocks; encryption
metadata is retained elsewhere, such as in /etc/crypttab or on a piece
of paper kept in the user's wallet), there's LUKS 1, and there's LUKS
2; the latter two with integrated or detached headers, for a total of
five combinations.

-- 
Michael Kjörling • https://michael.kjorling.se • michael@kjorling.se
 “Remember when, on the Internet, nobody cared that you were a dog?”


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: To make LUKS detached header even more secure?
@ 2022-06-08  0:05   ` midnite zandiro
  2022-06-08  6:13     ` Michael Kjörling
  0 siblings, 1 reply; 4+ messages in thread
From: midnite zandiro @ 2022-06-08  0:05 UTC (permalink / raw)
  To: michael; +Cc: cryptsetup

Dear Michael Kjörling,

Thank you very much for your prompt reply. You have given me a better
insight of LUKS.

> So, if I understand correctly, what you are proposing is basically a
> _split_ header, with part of the data stored in one location and part
> of the data stored in another location, and one (but not both) of
> those partial headers possibly detached from the container?

My apologies that I did not present my suggested setups clearly. Let
me explain by the pseudo code which I copied from the LUKS1
specification.
https://mirrors.edge.kernel.org/pub/linux/utils/cryptsetup/LUKS_docs/on-disk-format.pdf

In the partition header, during creation:

(C1) phdr.mk−digest =
PBKDF2( masterKey , phdr.mk−digest−salt , phdr.mk−digest−iter ,
LUKS_DIGESTSIZE )

In each keyslot, during creation:

(C2) pwd−PBKDF2ed =
PBKDF2( password , ks.salt , ks.iteration−count , masterKeyLength )

(C3) splitKey =
AFsplit( masterKey , masterKeyLength , ks.stripes )

(C4) encryptedKey =
encrypt( phdr.cipherSpec , pwd−PBKDF2ed , splitKey , splitKeyLength )

In each keyslot, during decryption:

(D2) pwd−PBKDF2ed =
PBKDF2( password , ks.salt , ks.iteration−count , masterKeyLength )

(D4) splitKey =
decrypt( phdr.cipherSpec , pwd−PBKDF2ed , encryptedKey , encryptedKeyLength )

(D3) masterKeyCandidate =
AFmerge( splitKey , masterkeyLength , ks.stripes )

During decryption, check against the MK digest:

(D1) MKCandidate−PBKDF2ed =
PBKDF2( masterKeyCandidate , phdr.mk−digest−salt , phdr.mk−digest−iter
, LUKS_DIGESTSIZE )

As I am far from a professional in cryptography, I aim to replicate
the algorithms of LUKS, hoping to achieve the same level of
cryptographic strength. From the above, the phdr.mk−digest (C1), hence
the first (C1) and the last operations (D1), are unnecessary for the
MK encryption and the MK decryption. My proposed design is just DO NOT
STORE phdr.mk−digest in the header. This leads to a problem that we
cannot verify the masterKeyCandidate (D3). But it can avoid hacking
solely on the header.

> (Detached header) No, that is not proper 2FA. As is clearly demonstrated by your
> argument about how the second storage device can be copied (and
> relatively easily, at that), both are "something you know".

I would like to point out that, even if the detached header is in the
hand of another person who does not know the passphrase, an attacker
who acquired the detached header is sufficient to start the cracking.
It is identical to the non-detached header scenario. The attacker is
just yet to obtain the actual data. Given that (as far as I can find)
no security advice on the Internet which encourages re-encryption of
the entire volume on a regular basis, the data is at plain risk until
the hard disk dies. In which, a patient attacker can have 3 to 5 more
years to work on cracking.

P.S. I do re-encryption regularly.

> You claim increased resistance to passphrase guessing by an attacker
> who has access to the detached header but not the encrypted (locked)
> container itself, but there's already a simple way to do that:
> increase iteration count, passphrase length, or both.

I do agree that the current LUKS, with the contemporary hashes, is
already very strong. But the strengths of encryption algorithms depend
mostly on the speed of processing power. It is strong today. It may be
breakable next year.

In my proposed design, an attacker can do nothing if he gets the
header. If an attacker gets the encrypted disk, he can hack on the MK,
the tough way. Only when an attacker gets BOTH the header and the
encrypted disk, then he can start a normal cryptographic attack.

One more point to note in real life scenarios, users tend to have
multiple copies (the need of backups) of the header USB Keys carrying
around, to the office, to the cafe, etc. It is a lot easier to get a
clone of the header without the users' awareness. On the contrary,
cloning the encrypted disks usually involve breaking into premises and
take longer times.

> Since this would be aimed only or primarily at
> users who use a detached header stored on a separate device, who seem
> likely to already care more about security than the average user, I
> don't think either is an unreasonable assumption.
> ...
> None of this is to say that the security of LUKS couldn't _possibly_
> be improved upon somehow (such a claim would be naiive), but there's
> ample reason already to not add complexity based on what appears at
> least to me to be a rather contrived threat model.

I do agree that there is not an urge to update the current LUKS. I do
like a quote from the FAQ, " It is better to have less protection
against low-entropy passphrases and ***people actually use LUKS, than
having them do without encryption altogether.*** ". Convenience plays
an important role in the real world too.

Thank you again for your informative reply. It is my pleasure to
discuss the concepts with you. In the future, I will fork the project
for a few paranoids like me.

Best regards,
midnite

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: To make LUKS detached header even more secure?
  2022-06-08  0:05   ` midnite zandiro
@ 2022-06-08  6:13     ` Michael Kjörling
  0 siblings, 0 replies; 4+ messages in thread
From: Michael Kjörling @ 2022-06-08  6:13 UTC (permalink / raw)
  To: cryptsetup

On 8 Jun 2022 08:05 +0800, from midnite.hk@gmail.com (midnite zandiro):
> As I am far from a professional in cryptography, I aim to replicate
> the algorithms of LUKS, hoping to achieve the same level of
> cryptographic strength.

If you aren't well-versed in cryptography, I strongly urge you to not
fiddle with cryptography, but to rather use what's available and
already thoroughly vetted. Even tiny details can matter A LOT, and
even experts get things wrong from time to time. For the vast, vast,
VAST majority of people, to use a widely reviewed, well-vetted design
and implementation of similarly well-vetted algorithms is the best way
to avoid such traps.

I get it. It's fun to try to improve on things, but the odds are good
that one subtly breaks something in the process, which in turn makes
an attack easier; sometimes _much_ easier.


>> (Detached header) No, that is not proper 2FA. As is clearly demonstrated by your
>> argument about how the second storage device can be copied (and
>> relatively easily, at that), both are "something you know".

You misrepresent the intention of what I wrote. My statement about 2FA
was about the combination of a detached header and a keyslot
passphrase, or alternatively having two detached-header parts and a
keyslot passphrase. Not least since the detached header is trivial to
copy, it remains "something you know"; the physical storage device
itself may be "something you have", but that's immaterial since the
storage device itself (as opposed to what's stored on it) has no
significant bearing on the overall system security.

> I would like to point out that, even if the detached header is in the
> hand of another person who does not know the passphrase, an attacker
> who acquired the detached header is sufficient to start the cracking.
> It is identical to the non-detached header scenario.

This much I agree with.

> The attacker is
> just yet to obtain the actual data. Given that (as far as I can find)
> no security advice on the Internet which encourages re-encryption of
> the entire volume on a regular basis, the data is at plain risk until
> the hard disk dies. In which, a patient attacker can have 3 to 5 more
> years to work on cracking.

As I see it, the value of reencryption for these purposes basically
requires three things to be true:

(a) the attacker has access to the LUKS header
(b) the attacker will, at some future point in time, have access to
the locked container, but does not have such access now
(c) the attacker does not and will not have access to the legitimately
unlocked container

If the attacker has access to the unlocked volume, then LUKS provides
no additional security, hence (c); that is the nature of full-disk
encryption.

The combination of (a) and (b) pretty much means that this only
applies for detached header containers.

Overall, this is a pretty narrow use case. There are also downsides to
reencryption, not least that in LUKS 1, reencryption is a potentially
catastrophic operation; if the process is interrupted for some reason,
it can lead to significant data loss. (Restartable reencryption in
LUKS 2 solves that.) It's also a long-running, write-heavy operation;
for any media with write endurance limits, such as SSDs and some
rotational HDDs, that can be a consideration. (I'm not in the "you
must worry about SSD write endurance" camp, but there's a difference
between not worrying and doing unnecessary full-disk writes
repeatedly.)


>> You claim increased resistance to passphrase guessing by an attacker
>> who has access to the detached header but not the encrypted (locked)
>> container itself, but there's already a simple way to do that:
>> increase iteration count, passphrase length, or both.
> 
> I do agree that the current LUKS, with the contemporary hashes, is
> already very strong. But the strengths of encryption algorithms depend
> mostly on the speed of processing power. It is strong today. It may be
> breakable next year.

Your claim that "the strengths of encryption algorithms depend mostly
on the speed of processing power" is incorrect. Take a 256-bit
symmetric key as an example, such as with AES-256 without XTS. (I'm
not quite sure myself how XTS plays into this, but it doesn't make it
easier for an attacker.) There are _physical_ limitations with
anything that even resembles a classical computer that pretty much
guarantee that even _counting_ through all the values up to 2^256
would take more energy than the total energy output of the Sun for the
remainder of its life, and that's before you even _do_ anything with
the counted value. If you assume a useful quantum computer running
Grover's algorithm, that reduces to 2^128 operations, but for an
attack on, say, AES, those operations still might be complex and
certainly in public we're nowhere near a quantum computer that can
actually do that (just look at quantum computer error rates and how
they scale with increasing numbers of qubits for one aspect of this).

The slightly less unlikely _cryptographic_ attack is that someone
finds a flaw that allows them to shave more than fractions of bits
work factor off an attack against, say, AES, but at this point AES
certainly looks robust enough that this possibility appears very
remote. We don't even really have that against DES, it's just that
computational ability caught up with its relatively short key length.
Wikipedia still puts the current best attack against full AES-256,
which is what we would be talking about here, still at a 2^254.6 work
factor; that's cryptographically interesting, but meaningless for a
practical attack.

The _far more plausible_ scenario is that, as in the XKCD cartoon I
pointed out in my previous reply, someone drugs, physically abuses the
user (or someone the user cares about), or otherwise coerces the user,
until the user reveals the passphrase or other material required to
unlock the container, which is _hardly_ a covert attack; or goes after
some other part of the overall security system through for example an
evil maid attack, in which case the problem isn't the cryptographic
design or implementation in the first place.

Again, I'm assuming that the user has a strong passphrase (and
possibly an increased key derivation function iteration count), and
believe that for a scenario in which something like what you propose
might be used this is a reasonable assumption. This means that
attacking the passphrase will also come at a significant cost,
potentially comparable to an attack on the cryptographic key material
directly.


> One more point to note in real life scenarios, users tend to have
> multiple copies (the need of backups) of the header USB Keys carrying
> around, to the office, to the cafe, etc.

Backups don't need to be stored unencrypted and readily readable or
usable themselves. By their very nature, backups are rarely read
(which is not to say that they shouldn't occasionally be confirmed to
be readable and usable).

-- 
Michael Kjörling • https://michael.kjorling.se • michael@kjorling.se
 “Remember when, on the Internet, nobody cared that you were a dog?”


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-06-08  6:13 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-07  2:41 To make LUKS detached header even more secure? midnite zandiro
2022-06-07  6:36 ` Michael Kjörling
2022-06-08  0:05   ` midnite zandiro
2022-06-08  6:13     ` Michael Kjörling

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).