User:Sakaki/Sakaki's EFI Install Guide/Migrating from Whirlpool Hash on LUKS

From Gentoo Wiki
Jump to: navigation, search

Previous versions of this install guide recommended the Whirlpool hash algorithm for use, when creating the LUKS partition on your system's hard drive.

Unfortunately, there is a bug in the implementation of Whirlpool in the library dev-libs/libgcrypt (versions < 1.6), which cryptsetup uses. As a result (per this Arch Linux bug report), if you update libgcrypt to version >= 1.6 (for example, by running genup after 1.6.2 has been stabilized), you will no longer be able to open the LUKS partition (since the correct implementation in the new version will not match the incorrect one used in the LUKS header).

The install guide has been modified to reflect this bug, and now recommends the use of SHA-512 hashing instead (which is correctly implemented in both version 1.5 and 1.6 of dev-libs/libgcrypt).

However, existing users will need to migrate their LUKS header to use a different hash. The below guide provides short form instructions for doing this (when using a GPG-encrypted keyfile, per the guide). It is patterned on the advice in this email from the dm-crypt archives.

This migration process should leave all your LUKS data and software intact. Also, although best done pre-emptively, even if you have already upgraded dev-libs/libgcrypt to >= 1.6, and thereby locked yourself out, you should still be able to use the instructions below to recover. However, proceed at your own risk!

Obviously, you need only do this if you have used the Whirlpool hash in your LUKS setup. If you used another hash (such as the SHA-512 now recommended), you should not carry out the procedure below.


To carry this out, you will need:

  1. your boot USB key (on which the file luks-key.gpg has been stored);
  2. the target PC, on which the LUKS partition (created using the buggy dev-libs/libgcrypt (< 1.6) implementation of Whirlpool) resides; and
  3. a second USB key (of at least 300MB capacity), which we'll use to hold a Gentoo minimal-install disk image (this will let us access your LUKS partition in its closed state); I'll refer to this as the ISO USB key in the below.

We'll be using tools downloaded from this GitHub repository to facilitate the migration. There are digital signatures there you can check if you wish to do so; I will omit that process in what follows, for brevity.


On an appropriate PC (as root), insert your ISO USB key, unmount any partitions of it that may have automounted (using umount), and then issue the following to download and write the appropriate Gentoo minimal install ISO:

root #dd if=install-amd64-minimal-20141113.iso of=/dev/sdX bs=8192k && sync
Substitute the correct path for the USB device for /dev/sdX in the above. Make sure you have the correct device path! As these are short-form instructions, I'm not going to repeat these warnings each time. The process is essentially similar to that describe in this chapter of the install guide, so please refer to that for hints, should any of the below be unclear.
You can use another ISO to boot your machine, but it needs to have all the correct library versions (including a buggy version of dev-libs/libgcrypt).

Remove the ISO USB key, and insert it into your (powered down) target PC. Make sure your boot USB key is not inserted at this point. Power up the target, enter the BIOS, set legacy / CSM boot (and ensure secure boot is off), and choose to boot from USB (essentially, exactly as per these instructions). Press Enter at the ISOLINUX boot prompt as usual, and set an appropriate keymap when asked. You should now be looking at the familiar livecd prompt.

Now bring networking up (as per these instructions). Once you have done this, download the (prebuilt) cryptsetup-reencrypt utility:

You're now ready to go. Insert your boot USB key (which has the luks-key.gpg encrypted keyfile on it), and determine its device path (you can use lsblk to help you do this). In what follows, I'm going to use:

  • /dev/sdY1 to refer to the first partition of the boot USB key (where luks-key.gpg resides, it will probably be something like /dev/sdb1), and
  • /dev/sdZn to refer to your LUKS partition (e.g. /dev/sda5).

Substitute appropriate values for your system in the following commands.

Begin by setting up GPG so that we can decrypt the keyfile. Issue:

livecd ~ #gpg-agent --daemon
  ... additional output suppressed ...
GPG_AGENT_INFO=/tmp/gpg-ESgBbB/S.gpg-agent:11818:1; export GPG_AGENT_INFO;

Your output will differ from the above, but whatever is shown, copy and paste it at the command prompt, and press Enter:

livecd ~ #GPG_AGENT_INFO=/tmp/gpg-ESgBbB/S.gpg-agent:11818:1; export GPG_AGENT_INFO;

Mount the boot USB key, so we can use the keyfile:

livecd ~ #mkdir bootusb
livecd ~ #mount /dev/sdY1 bootusb

Now check that you can indeed open your existing LUKS partition:

livecd ~ #gpg --decrypt bootusb/luks-key.gpg | cryptsetup luksOpen --key-file - /dev/sdZn gentoo
  ... enter your GPG passphrase when prompted ...
The necessary passphrase is the one you set up here in the tutorial. If you have problems, double-check you set the keymap correctly when booting the ISO.
Don't worry about any output of the form:
device-mapper: remove ioctl on temporary-cryptsetup-xxxxx failed: Device or resource busy
such warnings can safely be ignored (for our purposes) both here, and if they occur subsequently during the process.

Look at the device mapper, to verify that our gentoo LUKS device is now present:

livecd ~ #ls /dev/mapper
control gentoo

If you see something similar to the above, you should be good to go. Close the LUKS partition again:

livecd ~ #cryptsetup luksClose gentoo

One last preliminary: let's make a header backup of your LUKS partition, so we can get it back if something should go wrong:

livecd ~ #cryptsetup luksHeaderBackup /dev/sdZn --header-backup-file bootusb/prevluks.bak

Right, let's do the migration!

livecd ~ #gpg --decrypt bootusb/luks-key.gpg | ./cryptsetup-reencrypt --keep-key --key-file - --key-slot 0 --hash sha512 /dev/sdZn
Don't miss out that --keep-key, or you'll actually re-encrypt the whole LUKS partition, not just re-write the header. Also, note that when using a keyfile in this way, only one slot can be used, so if you have set up a fallback LUKS passphrase, you'll have to redo that (which is easiest when booted back in your main system, so you can safely leave it until then - you can add passphrases to an open LUKS partition).
Don't be surprised if you aren't prompted for your keyfile passphrase here or subsequently, as gpg-agent will have temporarily cached it (however, if you are, type it in again, of course).

When that returns, check that the hash is now reported as sha512; issue:

livecd ~ #cryptsetup luksDump /dev/sdZn

If good, check that you can still open the LUKS partition:

livecd ~ #gpg --decrypt bootusb/luks-key.gpg | cryptsetup luksOpen --key-file - /dev/sdZn gentoo
livecd ~ #ls /dev/mapper
control gentoo

Assuming that worked, congratulations, you have migrated your LUKS hash successfully! Close the LUKS partition again, and unmount your boot USB key:

livecd ~ #cryptsetup luksClose gentoo
livecd ~ #sync
livecd ~ #umount /dev/sdY1

That's it! Reboot:

livecd ~ #reboot

Enter the BIOS, and reset (if you have got to the appropriate stage in the tutorial) EFI and secure boot. Remove the ISO USB key, it can be reformatted now if you like. Select (in the BIOS) the EFI boot key as the boot device, and restart.

On some BIOSes, the EFI boot list may be reset when you switch out and then back into EFI boot in this manner. In this case, and if you are using the /EFI/Boot/gentoo.efi (rather than /EFI/Boot/bootx64.efi) pathname for your kernel, you may need to temporarily rename it (to /EFI/Boot/bootx64.efi), so that the boot can proceed. Once logged back into Gentoo, simply get root and run buildkernel (with the boot USB key inserted) to bring the EFI boot list back into sync again.

You should now be able to unlock the disk as usual (entering your GPG passphrase), and then log in.

Final Steps

If you added >=dev-libs/libgcrypt-1.6 (or similar) to /etc/portage/package.mask, you can safely remove that now - your LUKS system will work even with updated (>=1.6) versions of dev-libs/libgcrypt.