0

For instance, if we choose --pbkdf argon2id and --hash blake2b-512,

# printf 'YES' | cryptsetup luksFormat             \
    --type luks2     --key-file /tmp/keyfile       \
    --header /tmp/luks.header                      \
    --cipher serpent-xts-plain64  --key-size 512   \
    --use-random                                   \
    --hash blake2b-512  --pbkdf argon2id           \
    --pbkdf-force-iterations 4                     \
    --pbkdf-memory 32  --pbkdf-parallel 1          \
    /dev/loop0

From the header, argon2id goes to the keyslot. And blake2b-512 is the hash used for Digest.

What does digest do indeed? From the LUKS2 specification, it states digests are used to verify that keys decrypted from keyslots are correct. If I get it correctly, the digest is only used to verify our passphrase/keyfile, but it has nothing to do with generating the volume master key.

# cryptsetup luksDump /tmp/luks.header

LUKS header information
Version:        2
Epoch:          3
Metadata area:  16384 [bytes]
Keyslots area:  16744448 [bytes]
UUID:           fa2562ec-b396-43b7-8d81-e5f4ffb96bb0
Label:          (no label)
Subsystem:      (no subsystem)
Flags:          (no flags)

Data segments:
  0: crypt
        offset: 0 [bytes]
        length: (whole device)
        cipher: serpent-xts-plain64
        sector: 4096 [bytes]

Keyslots:
  0: luks2
        Key:        512 bits
        Priority:   normal
        Cipher:     serpent-xts-plain64
        Cipher key: 512 bits
        PBKDF:      argon2id
        Time cost:  4
        Memory:     32
        Threads:    1
        Salt:       ab bc 1b 5b d9 19 2b ce 04 59 1c 31 97 cc 03 d9 
                    13 5a 6f 54 6a 1b 81 b8 c6 93 0e 19 d1 a0 0c 15
        AF stripes: 4000
        AF hash:    blake2b-512
        Area offset:32768 [bytes]
        Area length:258048 [bytes]
        Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
        Hash:       blake2b-512
        Iterations: 1000
        Salt:       78 4e 17 12 70 f5 63 18 49 bf 79 24 9f 35 d2 7e     
                    b0 e3 3e b2 85 5e 0e 64 9a 2e 31 9e 76 13 4e 24     
        Digest:     bf 97 93 6b 6a 0c b6 58 bd c6 1e 3d 7b ec d3 d5 
                    52 4d f7 f2 b5 9d 19 69 7d dd 7f aa 0c 90 bc 7e     
                    4d 4c ad 2a 3a 4f dd 92 d7 d2 16 df ca 3b 57 8d 
                    85 99 76 48 f6 59 fa 6a e2 dc 64 80 5f bc cc 35

With luksDump --dump-master-key, we can view the 512 bits volume master key in plain hex.

# printf 'YES' | cryptsetup luksDump --dump-master-key --key-file /tmp/keyfile /tmp/luks.header

LUKS header information for /tmp/luks.header
Cipher name:    serpent
Cipher mode:    xts-plain64
Payload offset: 0
UUID:           fa2562ec-b396-43b7-8d81-e5f4ffb96bb0
MK bits:        512
MK dump:        84 c3 c7 1d 8b bd f8 cd 29 5d 5d ee 08 10 da 70 
                0c 8e 45 af 9f 58 80 3d 49 46 e4 4d fe 75 37 c0 
                89 30 d4 fe a8 27 76 71 16 0c f2 4e aa d8 27 b4 
                6e c2 e4 f0 c6 5a 86 cf fe 35 ff fd f0 df e6 62

I try to use the Argon2 program, with the known salt, to generate the volume master key. With the same settings in Argon (iteration count=4, memory cost=32, and parallel cost=1), I cannot get the same hash result.

# eval 'cat /tmp/keyfile | argon2 '$(printf "\xab\xbc\x1b\x5b\xd9\x19\x2b\xce\x04\x59\x1c\x31\x97\xcc\x03\xd9\x13\x5a\x6f\x54\x6a\x1b\x81\xb8\xc6\x93\x0e\x19\xd1\xa0\x0c\x15")' -id -t 4 -m 5 -p 1 -l 64'

Type:           Argon2id
Iterations:     4
Memory:         32 KiB
Parallelism:    1
Hash:           83ed8343d0539ba4f44fd79ac1becce1c7dd5001b7098f0cfb6a6cc7a07123890ccafb4cf8b7a8cb3ba1475e738f1268fb66eb89c42faf8460272878781cd952
Encoded:        $argon2id$v=19$m=32,t=4,p=1$q7wbW9kZK84EWRwxl8wD2RNab1RqG4G4xpMOGdGgDBU$g+2DQ9BTm6T0T9eawb7M4cfdUAG3CY8M+2psx6BxI4kMyvtM+LeoyzuhR15zjxJo+2bricQvr4RgJyh4eBzZUg
0.000 seconds
Verification ok

How does LUKS make use of our passphrase, processed by the Argon PBKDF with salt, then obtain the volume master key?

1 Answer 1

2

I try to use the Argon2 program, with the known salt, to generate the volume master key.

The key derived from your passphrase and salt is used to decrypt the volume key stored in the key slot (an anti-forensics splitter is also used, it is described in the LUKS1 specification, section 2.4). So you generated only the key to decrypt the master key, not the master key itself.

If I get it correctly, the digest is only used to verify our passphrase/keyfile, but it has nothing to do with generating the volume master key.

Yes. You take the key you decrypted from the key slot and use it to calculate the digest and then compare the calculated digest to the one stored in the header (which was generated when the key slot was initialized). If they match, the provided password is correct.

3
  • Thank you. From the LUKS1 spec, I find the reference implementation using SHA1 in C. After studying the section 2.4 and the C source code, I try to make use of the AF_split() function to generate the master key. Because the C source code uses SHA1 in stead of Argon2, I changed the PBDKF to cryptsetup luksFormat --type=luks2 --key-file keyfile --header luks.sha1.header --cipher serpent-xts-plain64 --key-size 512 --use-random --hash sha1 --pbkdf pbkdf2 --pbkdf-force-iterations 1000 disk which uses SHA1. Then I have problem of how to apply the salt to SHA1. Please kindly help.
    – midnite
    Jun 6 at 13:17
  • Dear Vojtech Trefny. I have skimmed through the source codes of LUKS. I found that the volume key is randomly generated. I might be wrong though. gitlab.com/cryptsetup/cryptsetup/-/blob/main/lib/…
    – midnite
    Jun 6 at 23:36
  • Yes, it is. The master key is generated during luksFormat and then saved to the key slot encrypted with the key derived from the passphrase. That doesn't change anything about retrieving the key. "Then I have problem of how to apply the salt to SHA1." -- salt is one of the inputs of pbkdf2, see for example the python implementation. Jun 7 at 5:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.