How can I programmatically determine the exact start byte and exact end byte of a LUKS header on a block storage device?
I use Linux Unified Key Setup (LUKS) for Full Disk Encryption (FDE), so all of the data on my drive is encrypted using a strong master key that's not derived from my passpharse, and I'm working on a script that will securely wipe the drive in an panic/emergency shutdown situation (ie: someone is physically stealing your laptop).
Let's say I have a 1000T drive and time is too short (~30 seconds) in my emergency scenario to actually fill the drive with random bytes. Instead, I'd just like to overwrite the header because all of the data on the drive is worthless if the header (containing the keyslots with the master key and salts) is lost--even if the passphrase were recovered via rubber-hose cryptanalysis.
How can I programmatically safely determine the start byte and end byte of the LUKS header so I know what to overwrite?
Note: The solution provided must be valid for both LUKS1 (released in 2014) and LUKS2 (released in 2018).
In LUKS1, I've found that the start is 0 and the end is determined by multiplying the payload-offset
field from the container's binary header by 512. For example
root@disp4117:~# hexdump -Cs 6 -n 2 luksVol1
00000006 00 01 |..|
00000008
root@disp4117:~# hexdump -Cs 104 -n 4 luksVol1
00000068 00 00 10 00 |....|
0000006c
root@disp4117:~#
In this case, the LUKS1 header ends at byte 4096 * 512
= 2097152
.
In LUKS2, it's much trickier as it requires parsing the JSON metadata object in the LUKS header.