Tutorial: Full disk encryption on Librem5

If the output is still:
$ ./crypto.sh
“Coping Source Path to ‘_reencrypted’”
cp: cannot stat ‘“”’: No such file or directory
“”

Then it sounds like the path was not correct handed over to the script.
Else it should at least say something like:
“Coping Source Path to ‘xxx_reencrypted’”

If the path parameter was “xxx”.

You have to replace the utf-8 quotes “,” by the simple ascii " for the script to work. So if you copy the script from your browser you should run

sed ‘s/[“”]/"/g’ old.sh > new.sh

And all expressions with grey background have to be enclosed by backquotes: `

1 Like

Good hint! Seems that I am not good in using the forum. (I also had problems with some other characters).

May be I will find a way to upload the script to the forum as file in the next days.

Here ist Cc281080’s script in the right format: (as code block, see https://en.wikipedia.org/wiki/Bbcode)

source_path=$1
reencrypted_path="${source_path}_reencrypted"

if [[ -d "${reencrypted_path}" ]]; then
echo "Cleaning up path for reencrypted version: ‘${reencrypted_path}’"
rm -rf "${reencrypted_path}"
echo ""
fi
echo "Coping Source Path to ‘${reencrypted_path}’"
cp -a "${source_path}" "${reencrypted_path}"

echo ""
echo "Opening Source LUKS Container…"
source_loop_device=`losetup -P -f --show "${source_path}/librem5r4.img"`
cryptsetup luksOpen "${source_loop_device}p2" Librem5_Orig
cryptsetup status /dev/mapper/Librem5_Orig
UUID=`cryptsetup luksDump "${source_loop_device}p2" | grep UUID | sed -e 's/^UUID:\s*\(\S*\)$/\1/'`

echo ""
echo "Reencryptipng new LUKS Container…"
reencrypted_loop_device=`losetup -P -f --show "${reencrypted_path}/librem5r4.img"`
cryptsetup luksFormat --type luks1 --key-size 256 --uuid "${UUID}" -q "${reencrypted_loop_device}p2"

echo ""
echo "Opening Reencrypted LUKS Container…"
cryptsetup luksOpen "${reencrypted_loop_device}p2" Librem5_Reencrypted
cryptsetup status /dev/mapper/Librem5_Reencrypted

echo ""
echo "Transfering all data to the reencrypted LUKS Container…"
partclone.ext4 --dev-to-dev -s /dev/mapper/Librem5_Orig -o /dev/mapper/Librem5_Reencrypted

echo ""
echo "Unloading the crypt containers…"
cryptsetup luksClose /dev/mapper/Librem5_Reencrypted
cryptsetup luksClose /dev/mapper/Librem5_Orig
losetup -d "${reencrypted_loop_device}"
losetup -d "${source_loop_device}"

echo ""
echo "New Image created succesfully"
echo "Please put your Librem5 to flash mode"
echo "cd ‘${reencrypted_path}’"
echo "uuu flash_librem5r4.lst"
3 Likes

Brilliantly spotted @nretro! and indeed at the center of the problem.
now I can finally give it a go :smiley:

I tried to flash a new image, but the flash_script ./scripts/librem5-flash-image doesn’t exists anymore :frowning:

Hui, since 3 months …

Ok, got it …

Looks like they got moved to here: git clone https://source.puri.sm/Librem5/librem5-flash-image.git

Thanks, I used a combination of @Cc281080’s bash code (that was cleaned up by @nretro and me) and OP’s partition expansion steps to successfully reencrypt the LUKS partition of a fresh Byzantium image which I flashed to my Librem 5’s eMMC.

I suspected that simply adding --variant luks to the existing image flash procedure would simply download the same public image that other Librem 5 users would download when they ran librem5-flash-image. Not wanting the encryption key for my Librem 5 to be held by Purism and everyone who uses default settings, I am glad I found this procedure to generate my own encryption key locally by creating a new LUKS container and filling it with the public image’s data. I hope librem5-flash-image incorporates local generation of encryption keys in the future.

Parent.
Archive.

Thank you so much to @Cc281080, @nretro, and @baltakatei for doing all the heavy lifting on this. I can’t imagine running a Librem 5 as a daily driver without properly encrypting the device. I know factory Librem 5s come LUKS encrypted with full disk size from the factory now, but I like testing pmOS and Mobian from time to time and this is my way home.

For anyone else, I spent a few hours wrapping my head around this one. I wrote up my notes as a guide for myself and anyone else. https://github.com/williamtries/linuxmobileguides/wiki/12.-Starting-Fresh-with-a-Used-Librem-5-(with-LUKS-Encryption,-Expanded-File-System,-and-New-Encryption-Key)

5 Likes

I did not feel comfortable with “Delete” and “New” partition with cfdisk. So I used jumpdrive and gparted to “resize” the partition graphically. Choose the 29.12 GB drive, which was /dev/sdb in my case. Use “Resize/Move” option from right click menu when selecting the encrypted partition. Set free size after the partition to 0. Now click apply (the gree tick mark) to complete resizing.

Once resized, use “Open encryption” option from gparted which mapped the drive to /dev/dm-4 (check cat /proc/partitions before and after Open encryption).


Now run

sudo e2fsck -f /dev/dm-4
sudo resize2fs /dev/dm-4

Changing luks password can be done from the phone directly using GNOME Disks (it does not support resizing - likely because it is already mounted).

There are a couple of ways to reencrypt a device in place. The device to reencrypt can be a loop device of a freshly downloaded image, as in the OP, or it can be a jumpdrive straight to the eMMC, for a chance to continue using the device without losing data. ( Always have a backup; the usual DISCLAIMER. )

Here, I did it on a freshly downloaded image:

librem5-flash-image --variant luks --skip-cleanup --skip-flash --dir devkit_image
sudo losetup -P -f --show devkit_image/librem5r4.img

Note the output, which was /dev/loop0 in my case.

Alternative #1 – convert to LUKS2

This is the one I tried successfully. The downloaded image comes with LUKS1 encryption, but the boot partition is unencrypted, so no need to worry about GRUB with LUKS2.

sudo cryptsetup convert /dev/loop0p2 --type luks2
sudo cryptsetup reencrypt /dev/loop0p2

The second command requires the old password ( 123456 ).

Alternative #2 – stay with LUKS1

I haven’t tried this, but it seems pretty straightforward:

sudo cryptsetup-reencrypt /dev/loop0p2

Now give it a strong mount passphrase :

sudo cryptsetup luksChangeKey /dev/loop0p2

From here, continue as usual to boot the device. In the case of a downloaded image, remove the loop device and flash the image:

sudo losetup -d /dev/loop0
cd devkit_image/
uuu flash_librem5r4.lst

Once inside the freshly booted Librem 5, open the terminal application and expand the partition:

sudo parted /dev/mmcblk0 resizepart 2 100%
sudo cryptsetup resize crypt_root
sudo resize2fs /dev/mapper/crypt_root
5 Likes

I’ve followed all the instructions here to reflash device:
https://developer.puri.sm/Librem5/Development_Environment/Phone/Troubleshooting/Reflashing_the_Phone.html

but I’m getting error when running the script:

INFO Looking for librem5r4 luks byzantium image
ERROR No matching image found

nothing I’ve tried has worked sadly

That is because there are no Byzantium images from Jenkins at the moment, other than QEMU plain. I also mentioned this in a different thread.

https://arm01.puri.sm/job/Images/job/Image%20Build/

Another Librem 5 owner was able to reflash the Librem 5 using the argument “stable”, so use it for now until Jenkins builds images succcessfully again or the script itself is updated to default to stable.

./scripts/librem5-flash-image --stable

can you encrypt the drive with LUKS1 or LUKS2 once an unencrypted image has been flashed using jumpdrive?

Yes (cryptsetup reencrypt --encrypt) but …

  • you will definitely want to image (make backup of) the disk before doing this (just in case!)
  • you will need to tell it to make the device smaller by 32 MB to allow for the LUKS header (hence wouldn’t be possible if your existing unencrypted file system is very close to full)
  • avoid any power interruption or other interruption during the process
  • and anything else I haven’t thought of so … caveat emptor

Read man cryptsetup-reencrypt carefully, note warnings and note examples.

I think the right approach to the second bullet point is to shrink the file system before starting this exercise. That is, I don’t think the above procedure will itself shrink the file system.

Personally, I did not take the above approach, instead just taking a copy of important files, reflashing from the LUKS variant disk image, and then manually reconfiguring / restoring important files.

2 Likes

awesome thanks @irvinewade I will give it a try, this is just for testing so if something goes wrong no loss

One question i have on

Encrypt LUKS2 device (in-place). Make sure last 32 MiB on /dev/plaintext is unused (e.g.: does not contain filesystem data):

cryptsetup reencrypt --encrypt --type luks2 --reduce-device-size 32m /dev/plaintext_device

Does that mean that a new 32MB partition on the device has to be created that is free? Or just that there needs to be 32MB free on the partition you are going to encrypt in place? Also when formatting the 32MB free partition what format is ideal FAT? I guess the other question is if the command --reduce-device-size 32m automatically resizes existing partition by creating a new free partition, so you don’t have to manually do it?