11

Is it possible to convert LUKS2 to LUKS version 1, and by extension, change the use of features that would block such a conversion?

Fedora 30 uses LUKS2 by default, however I ran into a situation where I need to stick with LUKS version 1. Specifically, Relax-and-Recover (rear) does not support LUKS2 at the moment.

Documentation mentions that converting between LUKS2 and LUKS1 is possible under certain conditions:

  • In-place conversion form LUKS1

    To allow easy testing and transition to the new LUKS2 format, there is a new convert command that allows in-place conversion from the LUKS1 format and, if there are no incompatible options, also conversion back from LUKS2 to LUKS1 format.

    Note this command can be used only on some LUKS1 devices (some device header sizes are not supported). This command is dangerous, never run it without header backup! If something fails in the middle of conversion (IO error), the header is destroyed. (Note that conversion requires move of keyslot data area to a different offset.)

    To convert header in-place to LUKS2 format, use
    $ cryptsetup convert --type luks2

    To convert it back to LUKS1 format, use
    $ cryptsetup convert --type luks1

    You can verify LUKS version with luksDump command.
    $ cryptsetup luksDump

    Note that some LUKS2 features will make header incompatible with LUKS1 and conversion will be rejected (for example using new Argon2 PBKDF or integrity extensions). Some minor attributes can be lost in conversion.

That last point is a problem as it seems that feature is used by default at least on Fedora.

$ sudo cryptsetup convert /dev/sda3 --type luks1

WARNING!
========
This operation will convert /dev/sda3 to LUKS1 format.


Are you sure? (Type uppercase yes): YES
Cannot convert to LUKS1 format - keyslot 0 is not LUKS1 compatible.
$ sudo cryptsetup luksDump /dev/sda3
LUKS header information
Version:        2
Epoch:          3
Metadata area:  16384 [bytes]
Keyslots area:  16744448 [bytes]
UUID:           974b19f8-021a-46b6-a089-a46e06e6e746
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:  4
    Memory:     973984
    Threads:    4
    Salt:       af 33 7e 3b 6c bb 55 dc e3 dc 2b 07 c5 9e c3 6d 
                f2 c9 08 be 2f 1d 8b 78 8a 33 65 90 41 e3 05 10 
    AF stripes: 4000
    AF hash:    sha256
    Area offset:32768 [bytes]
    Area length:258048 [bytes]
    Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
    Hash:       sha256
    Iterations: 100361
    Salt:       d9 30 b6 7f 60 d0 e0 19 39 f6 a2 38 ae 22 88 43 
                1e 5c 74 75 e6 b5 dd db a9 e7 29 1a 74 64 9c 0f 
    Digest:     ae 06 29 5f 71 49 bd c8 75 de 53 e8 95 94 d3 38 
                57 43 5f 0e 1e ac 6d 59 fb 34 a3 97 e4 5a 94 0c 

1 Answer 1

10

Converting LUKS1 to LUKS2, then back to LUKS1 works just fine. It's starting out with LUKS2 then converting to LUKS1 that causes problems. Apparently, cryptsetup convert is unable to convert between LUKS2 argon2i keys and LUKS1 pbkdf2 keys.

Setup:

# truncate -s 100M luks1.img
# truncate -s 100M luks2.img
# cryptsetup luksFormat --type luks1 luks1.img
# cryptsetup luksFormat --type luks2 luks2.img

Test with originally luks1:

# cryptsetup convert luks1.img --type luks2
WARNING!
========
This operation will convert luks1.img to LUKS2 format.


Are you sure? (Type uppercase yes): YES

# cryptsetup convert luks1.img --type luks1

WARNING!
========
This operation will convert luks1.img to LUKS1 format.


Are you sure? (Type uppercase yes): YES

We've got LUKS1 -> LUKS2 -> LUKS1 working.

Test with originally luks2:

# cryptsetup convert luks2.img --type luks1

WARNING!
========
This operation will convert luks2.img to LUKS1 format.


Are you sure? (Type uppercase yes): YES
Cannot convert to LUKS1 format - keyslot 0 is not LUKS1 compatible.

Same story for the originally luks1.img, if you add another key while in LUKS2 format.

But since we're able to add argon2i keys to originally luks1, perhaps we can add pbkdf key to originally luks2? There were some weird issues with that, too, but after some trial and error, I ended up with:

# cryptsetup luksConvertKey --pbkdf=pbkdf2 luks2.img
Enter passphrase for keyslot to be converted: I have a sudden craving for butternut biscuits.

And then it works (provided that was the only key).

# cryptsetup convert luks2.img --type luks1 

WARNING!
========
This operation will convert luks2.img to LUKS1 format.


Are you sure? (Type uppercase yes): YES

But it's not quite the same as the originally LUKS1 header (in particular, Payload offset: 32768 stands out). Now, LUKS1 changed their data offset before (originally it was not MiB aligned) so third-party software should be able to handle unusual offsets, but you never know.

LUKS2 also has other features that make conversions impossible (without oldfashioned re-encrypting) so the method described here only covers the most simple case.

2
  • Thank you! I can confirm this solution worked on a test VM and it was still able to boot afterwards. I also noted the Payload offset: 32768.
    – adatum
    Commented Aug 12, 2019 at 5:19
  • Notably, there was a recent exploit uncovered affecting LUKS2 volumes, which do not affect LUKS1, making this post quite useful: seclists.org/oss-sec/2022/q1/34
    – galets
    Commented Jan 28, 2022 at 3:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .