• caglararli@hotmail.com
  • 05386281520

LUKS – Too large detached header size when large offset

Çağlar Arlı      -    5 Views

LUKS – Too large detached header size when large offset

I find cryptsetup to have an inconsistent way of dealing with headers, I'm tempted to call it a bug
I would like to achieve a very large LUKS offset without resulting in a very bulky detached header
Here is what I've tried:

$ cryptsetup --version
cryptsetup 2.2.0

$ # First let's establish the default header size 
$ cryptsetup --header header_default luksFormat /dev/sdc
$ stat -c '%s' header_default
16777216
$ # it is exactly 16 MiB

$ # I try now with offset zero
$ cryptsetup --header header_0 --offset 0 luksFormat /dev/sdc
$ stat -c '%s' header_0
16777216
$ # very good, all needed data is still stored in a 16 MiB header

$ # Let's see what happens with a very small offset of 1 MiB
$ cryptsetup --header header_1MiB --offset $((2**11)) luksFormat /dev/sdc
WARNING: keyslots area (1015808 bytes) is very small, available LUKS2 keyslot count is very limited.
$ stat -c '%s' header_1MiB
1048576
$ # header size is very small, matching exactly with offset given, but I got a warning
$ # I wish I could set any offset I like without resulting in a detached header with limitations 

$ # Let's try again with a slightly larger offset of 4 MiB
$ cryptsetup --header header_4MiB --offset $((2**11*4)) luksFormat /dev/sdc
$ stat -c '%s' header_4MiB
4194304
$ # again header size matches exactly with offset given, cryptsetup exited with no error or warning
$ # it seems that a proper header can be achieved with a size smaller than the default one

$ # Now let's try with a very large offset
$ cryptsetup --header header_1GiB --offset $((2**21)) luksFormat /dev/sdc
$ stat -c '%s' header_1GiB
1073741824
$ # again header size matches exactly with offset given
$ # problem is the header file is too unreasonably bulky !

$ # Let's try something different
$ cryptsetup --header-backup-file header_1GiB_backup luksHeaderBackup header_1GiB
$ stat -c '%s' header_1GiB_backup
134250496
$ # header_1GiB_backup is slightly more than 128 MiB, precisely "$((2**15*4097))"

$ # Let's see what's the difference between header_1GiB and header_1GiB_backup
$ cmp header_1GiB header_1GiB_backup
cmp: EOF on header_1GiB_backup after byte 134250496, in line 523167
$ xxd -s $((134250496-16)) header_1GiB | head -n2
08007ff0: 9d3a e917 4327 f9e5 6dfb bdcb 3890 6168  .:..C'..m...8.ah
08008000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
$ xxd -p -s 134250496 header_1GiB | { grep '[^0]' || echo 'only null bytes found'; }
only null bytes found
$ # As I suspected:  header_1GiB  =  header_1GiB_backup padded with zeros
$ # I've tried to 'luksHeaderBackup' other large headers, the resulting size is always the same: 134250496 bytes

$ # Are other headers padded with zeros? Let's have a look
$ tail -c 32 header_* | cat --show-nonprinting
==> header_0 <==
M-NM-^WM-PM-0M-LM-`M-^^BM-;M-,JM-+M-dM-:g1UM-/`M-"^Con<jD^F[^SJM-#*
==> header_1GiB <==
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
==> header_1GiB_backup <==
QM-^HM-^CM-^XM-i^_M-*GM-x~KM-i'M-^NM-^G]M-^]:M-i^WC'M-yM-emM-{M-=M-K8M-^Pah
==> header_1MiB <==
sM-KM-&=`~^FM-^PM-'M-G(AM-jM-_M-&l~>WM-^ZM-a^_M-^^M-qhs^R)M-2M-TM-eS
==> header_4MiB <==
~^@KM--F^U^[M-dM-_M-<M-;^FM-/M-^MM-'M-^\M-m?M-\dM-"M-^DM-sM-fEM-C^WeM-GTM-\M-^[
==> header_default <==
UM-_V
M-^^+M-z3M-^M-\M-*pM-jM-\M-^@"M-}|^OM-0M-6M-FM-DM-NM-b^ZM-!M-IM-^KM-^MR[
$ # Only 'header_1GiB' is padded with zeros, all others I believe are padded with random bytes

Default header size is 16 MiB and it seems to be more than enough for the purpose
System setups with large offsets should be facilitated with default size detached header
A default sized detached header should be also given for any offset smaller than 16 MiB, as it is the case for zero offset