Howto re-encrypt your disk
As I already wrote I re-encrypted my disk using a new encryption master key to get rid of the risk that the original master key that had been generated during installation of the harddrive at Purism already has been compromised at Purism, while shipping my Librem or while my Librem passed through our company.
I compiled the steps I took so that people who’d like to re-encrypt their devices, too, could hopefully follow them.
If re-encryption does not work as expected for you all of the data on your disk might get lost. Don’t try this without a backup.
During the process you’ll generate a sha256 checksum for the old and new master keys for the disk encryption. You can compare them and make sure that the masterkey for your disk encryption really changed.
Also, I’d like to ask you to publish the checksum of your old master key in this thread: If we’d find that different people received the Librems with the same checksum of their master keys (aka the same master keys) it could be easily explained by Purism putting disk images on the new Librems (which to my knowledge is the fastest way of installing a number of devices if you grow afterwards the device size to the final size).
If this would be true the encryption of these devices would be useless in any case, because there’d be a good chance that someone could get their hands on those master keys used multiple times and just try them on Librems.
Here’s a short overview of the steps I took:
- find boot and root devices
- show information about encryption
- boot rescue system
- mount unencrypted boot and encrypted root devices of PureOS
- save sha256 checksum of encryption master key
- umount root device of PureOS
- re-encrypt root device with new master key
- show information about (new) encryption
- mount encrypted root device
- show sha256 checksum of new encryption master key
- re-add crypto_keyfile.bin to LUKS keys
- umount devices in rescue system, reboot
find boot and root devices
To find the devices containing your root and your boot filesystem you can use the following commands:
root device:
root@grml:# grep -v '^#' /etc/fstab | col | egrep '[[:space:]]+\/[[:space:]]+'
/dev/nvme0n1p2
boot device:
root@grml:# grep -v '^#' /etc/fstab | col | egrep '[[:space:]]+\/[[:space:]]+'
/dev/nvme0n1p1
These commands are taken from a script by Kyle Rankin.
So my devices are:
/ (root) = /dev/nvme0n1p2
/boot = /dev/nvme0n1p1
If your system uses different devices you’ll have to substitute my devices with your devices in all of the commands shown below.
E.g.:
If I write
ls /dev/nvme0n1p2
and you found that your root device is /dev/sda2 then you need to change it to
ls /dev/sda2
to make it work on your system.
show information about encryption
Below is how you can look at the non-secret information in your encrypted device that describes how your device is encrypted.
root@grml:# cryptsetup luksDump /dev/nvme0n1p2
LUKS header information for /dev/nvme0n1p2
Version: 1
Cipher name: aes
Cipher mode: xts-plain64
Hash spec: sha256
Payload offset: 4096
MK bits: 512
MK digest: 89 3b b1 57 52 87 3a b7 5b a6 6c 26 84 2b ed 84 fa d0 47 1c
MK salt: 72 c4 af cb 2a 5b a6 5c 0f 24 b9 e4 22 54 fa 62
be f6 65 78 22 65 13 f1 d6 09 e5 23 f5 97 4a 25
MK iterations: 104356
UUID: 64e871c7-a683-6de5-9a8d-2f7828012db0
Key Slot 0: ENABLED
Iterations: 1624562
Salt: 91 c4 d6 80 25 6a 29 7c 5e 80 df 44 70 48 1d 81
ff 99 63 99 0b 64 b1 97 28 6d 02 be 66 32 3e 62
Key material offset: 185
AF stripes: 4000
Key Slot 1: ENABLED
Iterations: 1834526
Salt: e2 3a f5 72 d5 06 50 30 d5 68 d5 b1 5a 1e 54 e8
68 e3 d7 68 ac 18 fe 67 46 b5 b6 42 e7 c1 48 66
Key material offset: 512
AF stripes: 4000
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED
To find out more about cryptsetup and its functions you’ll need to read the man page of the program by typing
man cryptsetup
In my example above you can see that two key slots are used - each of it containing the same master key for that device, but encrypted with two different passwords. One of the passwords is the one I choose setting up my Librem the first time and the other can be decrypted with the content of the file /crpto_keyfile.bin .
To understand why is that you can read the explanation here.
You don’t need to take note of these informations. They are not needed for the following steps. It’s just to make you aware how things work and to understand later that after re-encryption one key slot less is used and we have to fill up the second one manually again.
boot rescue system
I used the boot image from https://grml.org/ and put it on an usb stick. Generally you can use any rescue image you like that contains the program cryptsetup-reencrypt and preferable is based on Debian Buster. I choose to use GRML, because it offers to choose my keyboard layout in its boot menu.
To put the rescue image on an usb stick I followed “2. install using dd” in GRMLs wiki.
mount unencrypted boot and encrypted root devices of PureOS
Create mountpoints:
root@grml:# mkdir /mnt/boot
root@grml:# mkdir /mnt/root
Mount boot device:
root@grml:# mount /dev/nvme0n1p1 /mnt/boot
unencrypt root device and make it available as /dev/mapper/root-dev:
root@grml:# cryptsetup luksOpen --readonly /dev/nvme0n1p2 root-dev
Enter passphrase for lukstest.img:
mount the newly created decrypted device:
root@grml:# mount -oro /dev/mapper/root-dev /mnt/root
check whether everything worked:
root@grml:# mount | grep mnt
/dev/nvme0n1p1 on /mnt/boot type ext3 (rw,relatime,data=ordered)
/dev/mapper/root-dev on /mnt/root type ext3 (ro,relatime,data=ordered)
root@grml:# ls /mnt/root/crypto_keyfile.bin
/mnt/root/crypto_keyfile.bin
You now can write things to /mnt/boot for further reference and you can read the crypto_keyfile.bin of your root device. The crypto_keyfile.bin contains a password to unlock one of the key slots of your luks device.
save sha256 checksum of encryption master key
Now we will use the password in crypto_keyfile.bin to dump the encryption master key. I chose to do it this way because I didn’t want anybody to print her/his master key without need in clear text to the screen. This way we can cut of the part of the output of cryptsetup containing the master key and put it through sha256sum which will print its checksum in a hopefully reproducible way.
Since it is extremly difficult to find all the inputs that would create the same hash and then find in all of these endless variations the only one that is your master key, in my opinion it is safe to print this hash to your screen and safe it for further reference into a file.
Furthermore hopefully the re-encryption of your device with a new master key will work and the hash of your now still active and then old master key will only serve to compare and make sure the master key really changed.
Also I’d like to ask you to publish the hash we’ll now write into /mnt/boot/old-masterkey.sha256.txt (which in your running PureOS will be /boot/old-masterkey.sha256.txt) in this thread. This helps to make sure that there are no Librems that have for any reason been delivered with the same master key (in which case I’d strongly suggest that the owners need to be informed personally).
root@grml:# cryptsetup luksDump -q --dump-master-key --key-file /mnt/root/crypto_keyfile.bin /dev/nvme0n1p2 | grep -A4 '^MK dump:' | sha256sum | tee /mnt/boot/old-masterkey.sha256.txt
a9f3b6bb0389747d9914b2635ab0285cc572e703aabfd02c116e8f115f12c94b -
umount root device of PureOS
For re-encryption of the device I closed and unmounted it. I’m not sure if this is necessary since the man page states:
root@grml:# umount /mnt/root
root@grml:# cryptsetup luksClose root-dev
re-encrypt root device with new master key
With the reencryption part I had a problem: Either I entered several times a bad password or the version of cryptsetup-reencrypt I used didn’t try all the key slots with the password I provided. I ended up giving a parameter to define which key slot should be used.
If you’ll need to do the same, here’s how to find the right key slot:
root@grml:# cryptsetup --verbose luksOpen --test-passphrase /dev/nvme0n1p2
Enter passphrase for /dev/nvme0n1p2:
Key slot 1 unlocked.
Command successful.
In my case the key slot I could decrypt with my password is key slot 1.
To re-encrypt the device we use the following command. The parameter -S1 defines that we want to use key slot 1. You could also try to run the command without the -Sx option - in theory cryptsetup-reencrypt should choose the right key slot.
Before running the re-encryption command make sure that you have a backup and that your notebook is connected to power and your battery is full. The manpage of cryptsetup-reencrypt states the following warning:
Here we go:
root@grml:# cryptsetup-reencrypt -S1 /dev/nvme0n1p2
Enter passphrase for key slot 1:
Finished, time 46:15:192, 469674 MiB written, speed 169,2 MiB/s
As you can see the re-encryption of my 500GB NVMe took about three quarters of an hour.
show information about (new) encryption
If you look now at the content of the luks header (like above):
root@grml:# cryptsetup luksDump /dev/nvme0n1p2
You’ll note that only one key slot is used: It contains the password you typed. We’ll re-add your crypto_keyfile.bin later.
mount encrypted root device
To do so we need to unlock and mount the device again:
root@grml:# cryptsetup luksOpen --readonly /dev/nvme0n1p2 root-dev
Enter passphrase for lukstest.img:
root@grml:# mount -oro /dev/mapper/root-dev /mnt/root
re-add crypto_keyfile.bin to LUKS keys
Now we can add the password in crypto_keyfile.bin again:
root@grml:# cryptsetup luksAddKey /dev/nvme0n1p2 /mnt/root/crypto_keyfile.bin
Enter any existing passphrase:
cryptsetup luksAddKey /dev/nvme0n1p2 /mnt/root/crypto_keyfile.bin 6,74s user 0,02s system 76% cpu 8,841 total
show sha256 checksum of new encryption master key
Let’s see whether we changed the master key for disk encryption successfully:
root@grml:# cryptsetup luksDump -q --dump-master-key --key-file /mnt/root/crypto_keyfile.bin /dev/nvme0n1p2 | grep -A4 '^MK dump:' | sha256sum; cat /mnt/boot/old-masterkey.sha256.txt
f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2 -
a9f3b6bb0389747d9914b2635ab0285cc572e703aabfd02c116e8f115f12c94b -
In my example the re-encryption worked and the sha256 checksum for the masterkey changed.
umount devices in rescue system, reboot
root@grml:# umount /mnt/*
root@grml:# cryptsetup luksClose root-dev
root@grml:# reboot
After you started your PureOS again (hopefully succesfull) you could do to us Librem and PureOS users two favors:
- Write a short reply that this howto worked for you / didn’t work for you / you didn’t understand some things to help us improve it
- If you’re feeling save with it include the content of your /boot/old-masterkey.sha256.txt to help to find out whether this possible security issue might be more severe than we thought until now