Open LUKS2 encrypted volume on a low memory device.

There are those rare situations when you cannot open LUKS encrypted volume on a low memory device.

$ sudo cryptsetup luksOpen /dev/sda1 decrypted_sda1
Enter passphrase for /dev/sda1: 
Killed

The process is killed by the OOM killer.

$ dmesg -T | tail
[Tue May  4 20:18:51 2021] [   2688]    33  2688     1779      207    14336      149             0 nginx
[Tue May  4 20:18:51 2021] [   2689]    33  2689     1779      207    14336      149             0 nginx
[Tue May  4 20:18:51 2021] [   2690]    33  2690     1779      207    12288      149             0 nginx
[Tue May  4 20:18:51 2021] [   2700]     0  2700     1294      494    14336       60             0 cron
[Tue May  4 20:18:51 2021] [   2883]   107  2883   181125        0   176128    16069             0 mysqld
[Tue May  4 20:18:51 2021] [   3030]     0  3030     1650      495    16384       81             0 sudo
[Tue May  4 20:18:51 2021] [   3031]     0  3031   264642   232106   935936        0             0 cryptsetup
[Tue May  4 20:18:51 2021] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/,task=cryptsetup,pid=3031,uid=0
[Tue May  4 20:18:51 2021] Out of memory: Killed process 3031 (cryptsetup) total-vm:1058568kB, anon-rss:920420kB, file-rss:8004kB, shmem-rss:0kB, UID:0 pgtables:914kB oom_score_adj:0
[Tue May  4 20:18:51 2021] oom_reaper: reaped process 3031 (cryptsetup), now anon-rss:920428kB, file-rss:7992kB, shmem-rss:0kB

You will likely encounter this issue when using LUKS2 as LUKS1 uses PBKDF2 as key derivation function (only time cost), but LUKS2 uses Argon2i/Argon2id (time, memory, and parallel cost).

Sample LUKS2 header version 2.

$ sudo cryptsetup luksDump /dev/sda1
LUKS header information
Version:        2                                    
Epoch:          5                                    
Metadata area:  16384 [bytes]      
Keyslots area:  16744448 [bytes]
UUID:           0e17b44c-a9af-4da1-8f98-062552e1df7a
Label:          (no label)                           
Subsystem:      (no subsystem)
Flags:          (no flags)                                                                                
                                                                                                          
Data segments:          
  0: crypt                                           
        offset: 16777216 [bytes]  
        length: (whole device)    
        cipher: aes-xts-plain64
        sector: 512 [bytes]
                          
Keyslots:  
  0: luks2                                           
        Key:        512 bits
        Priority:   normal                                                                                
        Cipher:     aes-xts-plain64                                                                       
        Cipher key: 512 bits                                                                              
        PBKDF:      argon2i                                                                               
        Time cost:  5
        Memory:     1048576
        Threads:    4
        Salt:       af b0 98 7d a1 07 a4 17 d9 78 d6 13 c2 61 14 36 
                    e7 51 ea 90 21 cb 29 62 d8 9b 45 78 90 02 b5 c0 
        AF stripes: 4000
        AF hash:    sha256 
        Area offset:32768 [bytes]
        Area length:258048 [bytes]
        Digest ID:  0
  6: luks2
        Key:        512 bits
        Priority:   normal 
        Cipher:     aes-xts-plain64
        Cipher key: 512 bits
        PBKDF:      pbkdf2 
        Hash:       sha256 
        Iterations: 1836384
        Salt:       6d 99 0b f4 eb 5e 81 12 2b 13 a5 67 0d 47 10 88 
                    f5 66 da 00 bd 33 9b f6 cf 29 ee ab fe a7 14 c9 
        AF stripes: 4000
        AF hash:    sha256 
        Area offset:290816 [bytes]
        Area length:258048 [bytes]
        Digest ID:  0
  7: luks2
        Key:        512 bits
        Priority:   normal 
        Cipher:     aes-xts-plain64
        Cipher key: 512 bits
        PBKDF:      pbkdf2 
        Hash:       sha256 
        Iterations: 1859176
        Salt:       25 de 5c 85 7d a2 39 77 f9 f9 74 89 ea 4d 22 ce 
                    36 16 2c 98 24 86 fb 9e a1 fc a1 17 cd 6b 72 ac 
        AF stripes: 4000
        AF hash:    sha256 
        Area offset:548864 [bytes]
        Area length:258048 [bytes]
        Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
        Hash:       sha256 
        Iterations: 116819 
        Salt:       ce 39 26 63 7c 48 10 3f 16 ee a1 c2 7b 0c 94 b0 
                    ee d3 f1 38 bc da 9e 78 9d 68 59 53 3c 04 1a bb 
        Digest:     db 65 ad 6a 80 fc 5f 42 ad 9c 1e ee 39 5a 8d 33 
                    b4 ad 6e 50 c9 fc 99 45 27 75 91 95 96 c8 9e c9 

Sample LUKS2 header version 1.

$ sudo cryptsetup luksDump /dev/sdd1
LUKS header information for /dev/sdd1

Version:        1
Cipher name:    aes
Cipher mode:    xts-plain64
Hash spec:      sha256
Payload offset: 4096
MK bits:        512
MK digest:      5c ae 6f 4e 12 15 59 70 24 bf c9 84 82 c6 01 f1 f7 9a d4 77 
MK salt:        65 56 a3 83 7e 52 eb 7f ae b0 cb 40 2b 65 79 b7 
                81 eb 80 3b 13 fa b6 28 8e 29 7d 33 ca 66 0b b5 
MK iterations:  107436
UUID:           a0bad006-a567-4f5f-83c2-5c86ba50e5df

Key Slot 0: ENABLED
        Iterations:             1771242
        Salt:                   9d f7 31 82 eb 41 f9 cc 0f 53 42 46 9e 30 d7 0b 
                                6e 7b e6 f8 bd a1 bb 41 98 d4 41 17 78 4c 84 8e 
        Key material offset:    8
        AF stripes:             4000
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

There are multiple solutions as you can convert keyslot to new pbkdf parameters, convert LUKS header version 2 to LUKS header version 1, and add new key using PBKDF2 as a key derivation function.

The easiest solution is to add a new key or password. Do it on a slightly more powerful machine.

Create a new key.

$ dd if=/dev/urandom of=secret.key bs=512 count=1
1+0 records in
1+0 records out
512 bytes copied, 0,000272616 s, 1,9 MB/s

Add it to the unused keyslot.

$ sudo cryptsetup luksAddKey --key-slot 7 --pbkdf pbkdf2  /dev/sda1 secret.key
Enter any existing passphrase: **********

Now you can use this key to open the LUKS device in low memory conditions.

$ sudo cryptsetup luksOpen /dev/sda1 --key-slot 7 --key-file ~/.secret.key decrypted_sda1

It works!