# Raspberry pi 4, Ubuntu 22.04, LUKS with fallback

**URL:** <https://community.zymbit.com/t/raspberry-pi-4-ubuntu-22-04-luks-with-fallback/1500>\
**Category:** Encrypting File System\
**Created:** [February 13, 2023, 6:45am UTC](https://community.zymbit.com/t/raspberry-pi-4-ubuntu-22-04-luks-with-fallback/1500 "2023-02-13T06:45:30Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![kontrasec](https://avatars.discourse-cdn.com/v4/letter/k/9de0a6/32.png) [@kontrasec](https://community.zymbit.com/u/kontrasec)\
**Post date:** [February 13, 2023, 6:45am UTC](https://community.zymbit.com/t/raspberry-pi-4-ubuntu-22-04-luks-with-fallback/1500/1 "2023-02-13T06:45:30Z")

</div>

Please find below steps for RPI4 full disk encryption (FDE) under Ubuntu 22.04 LTS using LUKS with fallbacks.

**Apply LUKS**

Apply to your sdcard Ubuntu Server or Desktop.

Borrowing from:

1. [raspberrypi - LUKS Disk Encryption on Raspberry Pi 4 and Ubuntu Desktop 20.10 - Ask Ubuntu](https://askubuntu.com/questions/1287837/luks-disk-encryption-on-raspberry-pi-4-and-ubuntu-desktop-20-10/1296450#1296450).
2. [LUKS on Raspberry Pi | LUKS-on-Raspberry-Pi](https://rr-developer.github.io/LUKS-on-Raspberry-Pi/)

Steps are repeated and translated below.

[Prepare your SD card](https://ubuntu.com/tutorials/how-to-install-ubuntu-on-your-raspberry-pi) but do not install into the RPI4 – keep it on your linux desktop.

You have to be booted into a linux PC or laptop for this procedure - ideally also a matching Ubuntu version. If you don’t have that, you can follow this guide using two sdcards:

1. Image Ubuntu onto the first sdcard, boot and log into it.
2. Use it to image your second sdcard (via USB sdcard reader), which will become your eventual encrypted disk.

Ensure the sdcard is unmounted.

```auto
ubuntu@ubuntu:~$ lsblk 
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS 
loop0 7:0 0 57.9M 1 loop /snap/core20/1590 
loop1 7:1 0 59.1M 1 loop /snap/core20/1826 
loop2 7:2 0 71.8M 1 loop /snap/lxd/22927 
loop3 7:3 0 109.6M 1 loop /snap/lxd/24326 
loop4 7:4 0 43.2M 1 loop /snap/snapd/17954 
sda 8:0 1 183.3G 0 disk 
├─sda1 8:1 1 256M 0 part 
└─sda2 8:2 1 183.1G 0 part 
mmcblk0 179:0 0 29.8G 0 disk 
├─mmcblk0p1 179:1 0 256M 0 part /boot/firmware 
└─mmcblk0p2 179:2 0 29.6G 0 part / 

```

Note in this case, `/dev/mmcblk0` is the temporary OS we’re booted into and `/dev/sda` is the target image we’ll encrypt. Store the device name (e.g. `sda`) in a variable to avoid accidents.

```auto
read TARGET_DEVICE
export TARGET_DEVICE 

```

Ensure partitions are unmounted.

```auto
sudo umount /dev/${TARGET_DEVICE}1 
sudo umount /dev/${TARGET_DEVICE}2 

```

Check the second partition for errors first.

```auto
sudo e2fsck -f /dev/${TARGET_DEVICE}2 

```

Let’s not add more write cycles onto the sdcard than necessary. Shrink the partition.

```auto
sudo resize2fs -M /dev/${TARGET_DEVICE}2 

```

LUKS encrypt the partition. Because these devices do not have AES intrinsics, use Adiantum (below). If you’re reading this from the future, check if an [ASCON](https://www.nist.gov/news-events/news/2023/02/nist-selects-lightweight-cryptography-algorithms-protect-small-devices) cipher is available.

Generate your password from a password manager application.

_NOTE: Don’t use a 99 character password, because you will timeout during the splash screen on cold boot while trying to type it all in. Ask me how I know 🤦‍♂️_

**Anyway, here’s wonderwall.**

```auto
sudo cryptsetup-reencrypt --new --reduce-device-size=16M --type=luks2 -c xchacha20,aes-adiantum-plain64 -s 256 --hash sha3-256 --iter-time=8000 --pbkdf argon2id /dev/${TARGET_DEVICE}2 

```

Decrypt the LUKS partition and then re-expand the inner (ext4) partition.

```auto
sudo cryptsetup luksOpen /dev/${TARGET_DEVICE}2 rootfs 
sudo resize2fs /dev/mapper/rootfs 

```

Mount the root partition so that we can work inside of it.

```auto
sudo mkdir mnt 
sudo mount /dev/mapper/rootfs mnt 

```

Connect up the crypttab.

```auto
sudoedit mnt/etc/crypttab 

```

Add:

```auto
rootfs /dev/mmcblk0p2 none luks 

```

Connect up the fstab.

```auto
sudoedit mnt/etc/fstab 

```

Update such that the first line reads:

```auto
/dev/mapper/rootfs / ext4 defaults,noatime 0 0 

```

**Sidebar: Partition Sizing**

By default, ubuntu will expand the root partition to take up the entire disk. You may wish to disable auto-expand the root partition on bootup. Small disks make for small backup images.

Connect up to the cloud config.

```auto
sudoedit mnt/etc/cloud/cloud.cfg 

```

Remove `growpart`.

If you do this, next manually extend the partition now to your desired size.  
**Don’t skip expanding the partition** ; it avoids `no-space-left-on-device-ing` upon the first `apt update && apt upgrade` in 22.04.

I use 12GB below.

```auto
sudo umount /dev/mapper/rootfs 
sudo cryptsetup luksClose rootfs 

sudo parted /dev/sda resizepart 2 12GB 

sudo cryptsetup luksOpen /dev/${TARGET_DEVICE}2 rootfs 
sudo cryptsetup resize rootfs 

```

**End of Sidebar: Partition Sizing**

Mount the boot partition so that we can work inside of it.

```auto
sudo mkdir boot 
sudo mount /dev/${TARGET_DEVICE}1 boot 

```

Connect up the boot cmdline.

```auto
sudoedit boot/cmdline.txt 

```

Update

```auto
root=LABEL=writable

```

to

```auto
root=/dev/mapper/rootfs

```

and add `cryptdevice=/dev/mmcblk0p2:sdcard` to the end of line.

Your cmdline.txt should look akin to:

```auto
console=serial0,115200 dwc_otg.lpm_enable=0 console=tty1 root=/dev/mapper/rootfs rootfstype=ext4 rootwait fixrtc quiet splash cryptdevice=/dev/mmcblk0p2:sdcard 

```

While you’re here, might as well enable USB data on the USB-C port.

Connect up the config.txt.

```auto
sudoedit boot/config.txt 

```

and place under `[pi4]`:

```auto
dtoverlay=dwc2,dr_mode=host 

```

Unmount all.

```auto
sudo umount /dev/${TARGET_DEVICE}1 
sudo umount /dev/mapper/rootfs 
sudo cryptsetup luksClose rootfs 
sync 

```

Shutdown, set aside your temporary OS sdcard if you used one, and install the newly encrypted sdcard into the RPI4.

Connect up monitor and keyboard if you haven’t already.

Now here comes some _jank_. We have to boot,

> WAIT ON THE BLINKING CURSOR SEVERAL MINUTES FOR FAILOVER  
> WAIT ON THE BLINKING CURSOR SEVERAL MINUTES FOR FAILOVER  
> WAIT ON THE BLINKING CURSOR SEVERAL MINUTES FOR FAILOVER

, before getting dropped into an initramfs prompt.

Once you are booted into initramfs:

```auto
(initramfs) cryptsetup luksOpen /dev/mmcblk0p2 rootfs 
(initramfs) exit 

```

Login with user `ubuntu` password `ubuntu`. You’ll be forced to change the password now.  
Update the `initramfs` so that we don’t hang at the blinking cursor anymore.

```auto
sudo update-initramfs -u 
sudo reboot 

```

You should now get the ubuntu boot password splash screen. Verify it works by giving it the LUKS password and observe the machine boot.

**Remote Unlock**

I recommend layering in dropbear for remote unlock, especially for headless machines.

Borrowing from [Ubuntu Server 22.04 LTS with Remote LUKS Unlock - Migrating to Cockpit (Part I)](https://blog.gradiian.io/migrating-to-cockpit-part-i/#:~:text=Unlocking%20LUKS%20remotely) ,

Bring the OS up to date and install dropbear.

```auto
sudo apt update 
sudo apt upgrade -y 
sudo apt install -y dropbear-initramfs  

```

Ignore this warning because we’re going to fix it next!

```auto
dropbear: WARNING: Invalid authorized_keys file, SSH login to initramfs won't work! 

```

Connect up to the dropbear configuration.

```auto
sudoedit /etc/dropbear/initramfs/dropbear.conf 

```

Uncomment and use:

```auto
DROPBEAR_OPTIONS="-I 300 -j -k -p 2222 -s"  

```

On your client machine,

```auto
ssh-keygen -t ed25519 -f ~/.ssh/unlock_dropbear 
cat ~/.ssh/unlock_dropbear.pub 

```

Place your public key on the RPI4:

```auto
echo "ssh-ed25519 AAAAC3...." | sudo tee /etc/dropbear/initramfs/authorized_keys 

```

Build the remote unlock key into the `initramfs` and reboot.

```auto
sudo update-initramfs -u 
sudo reboot 

```

Verify that your dropbear key works as well as unlocking the LUKS partition:

```auto
ssh -i ~/.ssh/unlock_dropbear -p2222 root@<IP_OF_RPI4> 

```

From inside the dropbear shell:

```auto
cryptroot-unlock 

```

Consider updating your client’s ssh config, too.

```auto
edit ~/.ssh/config

 
Host rpiname.dropbear 
    Hostname <IP_OF_RPI4> 
    User root
    Port 2222 
    IdentityFile ~/.ssh/unlock_dropbear 

```

If you happen to be using an [X715 multi-voltage input hat](https://wiki.geekworm.com/X715) like I am, use this updated variable-rate fan driver for ubuntu 22.04:

```auto
sudo apt install -y build-essential 
mkdir -p /tmp/fandriver 
pushd /tmp/fandriver 
git clone --depth 1 https://github.com/coricarson/X715.git 
pushd X715 
sudo make install 
popd 
popd 
rm -rf /tmp/fandriver 

```

**Take a backup**  
If this is the third or fourth time you’re reading this guide, it probably means something inevitably went wrong. Happens all the time. I’ve been through this enough times that I ended up writing this post.

Take a backup image from e.g. your temporary OS booted on the rpi4.

```auto
lsblk 
 
read TARGET_DEVICE #e.g. "sda" 
export TARGET_DEVICE 

sudo fdisk -l /dev/${TARGET_DEVICE} 
Disk /dev/sda: 119.25 GiB, 128043712512 bytes, 250085376 sectors 
Disk model: Storage Device 
Units: sectors of 1 * 512 = 512 bytes 
Sector size (logical/physical): 512 bytes / 512 bytes 
I/O size (minimum/optimal): 512 bytes / 512 bytes 
Disklabel type: dos 
Disk identifier: 0x61768bc1 
  
Device Boot Start End Sectors Size Id Type 
/dev/sda1 * 2048 526335 524288 256M c W95 FAT32 (LBA) 
/dev/sda2 526336 23437500 22911165 10.9G 83 Linux 

```

Grab the block size (512 expected for sdcard) and the **end of the second partition PLUS ONE** : 23437501.

```auto
sudo dd if=/dev/${TARGET_DEVICE} of=rpi4_project.2023.02.14.img bs=512 count=23437501 status=progress 

# Optional: consider creating parity files to mitigate bitrot
sudo apt install -y par2 
par2 c -r15 ./rpi4_project.2023.02.14.img 

```

**Zymkey 4i**  
This is a zymbit user forum is it not? Now, physically install your zymkey 4i: [Quickstart - ZYMKEY4 |](https://docs.zymbit.com/getting-started/zymkey4/quickstart/) .

The setup package supports jammy! Thanks Zymbit!

```auto
curl -G https://s3.amazonaws.com/zk-sw-repo/install_zk_sw.sh | sudo bash 

```

Let the rpi4 reboot.  
Unlock it manually at the terminal or via dropbear ssh, add a new key to the LUKS, and lock it with the zymkey 4i.

Borrowed from [Ubuntu 20.04 and TPM2 encrypted system disk - Running Systems](https://run.tournament.org.il/ubuntu-20-04-and-tpm2-encrypted-system-disk/) ,

```auto
sudo su -
pushd /root

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 64 > root.key

num_times=4
while [${num_times} -gt 0] 
do 
    zklockifs root.key > /var/lib/zymbit/key.bin.lock 

    err=$? 
    if [${err} -eq 0] 
    then 
        break 
    else 
        num_times=$((num_times-1)) 
        sleep 0.2 
    fi 
done 

cryptsetup luksAddKey /dev/mmcblk0p2 root.key

rm root.key

popd

```

Now, add new hooks for initramfs generation. Borrowed from Zymbit’s own `mk_encr_ext_rfs.sh` script:

```auto
sudo su -

# Copy /var/lib/zymbit and all standalone zymkey utilities to initramfs
cat > /etc/initramfs-tools/hooks/zymkey_cryptfs_cfg <<'EOF'
#!/bin/sh

PREREQ=""

prereqs() {
     echo "$PREREQ"
}

case "$1" in
    prereqs)
        prereqs
        exit 0
        ;;
esac

. /usr/share/initramfs-tools/hook-functions

mkdir -p ${DESTDIR}/var/lib/zymbit
cp -prf /var/lib/zymbit/* ${DESTDIR}/var/lib/zymbit
copy_exec /sbin/zkunlockifs /sbin

EOF
chmod +x /etc/initramfs-tools/hooks/zymkey_cryptfs_cfg

# Bring the i2c drivers into initramfs
grep -q "^i2c-dev" /etc/initramfs-tools/modules || echo "i2c-dev" >> /etc/initramfs-tools/modules
grep -q "^i2c-bcm2835" /etc/initramfs-tools/modules || echo "i2c-bcm2835" >> /etc/initramfs-tools/modules
grep -q "^i2c-bcm2708" /etc/initramfs-tools/modules || echo "i2c-bcm2708" >> /etc/initramfs-tools/modules
grep -q "^lan78xx" /etc/initramfs-tools/modules || echo "lan78xx" >> /etc/initramfs-tools/modules

```

From [Raspberry pi4 Ubuntu not booting - #10 by kontrasec](https://community.zymbit.com/t/raspberry-pi4-ubuntu-not-booting/1285/10) , the stock keyscript has no fallbacks in case the zymbit is missing, damaged, or the OS was updated.

Run below to replace it:

```auto
cat > /lib/cryptsetup/scripts/zk_get_key <<'EOF'
#!/bin/sh

# Wait for network, but timeout if we can't see it.
num_times=30
while [${num_times} -gt 0]
do
    ls /sys/class/net/eth* 1>/dev/null 2>&1
    eth=$?
    ls /sys/class/net/enx* 1>/dev/null 2>&1
    enx=$?

    if [${eth} -ne 0] && [${enx} -ne 0]
    then
        num_times=$((num_times-1))
        sleep 0.1
    else
        break
fi
done

# Wait for zymbit, but timeout if we can't see it.
num_times=30
while [${num_times} -gt 0]
do
    if [-d "/var/lib/zymbit"]
    then
        break
    else
        num_times=$((num_times-1))
        sleep 0.1
    fi
done

if [-e /var/lib/zymbit/zkenv.conf]
then
    export $(cat /var/lib/zymbit/zkenv.conf)
fi

num_times=4
while [${num_times} -gt 0]
do
    /sbin/zkunlockifs /var/lib/zymbit/key.bin.lock

    err=$?
    if [${err} -eq 0]
    then
        exit
    else
        num_times=$((num_times-1))
        sleep 0.2
    fi
done

/lib/cryptsetup/askpass "Zymkey 4i did not release LUKS key. Please unlock rootfs with manual key:"

EOF
chmod +x /lib/cryptsetup/scripts/zk_get_key

```

Connect up to the crypttab.

```auto
sudoedit /etc/crypttab 

```

And add the `keyscript=` to the end:

```auto
rootfs /dev/mmcblk0p2 none luks,keyscript=/lib/cryptsetup/scripts/zk_get_key 

```

Now, rebuild the initramfs, reboot.

```auto
update-initramfs -u -k all 
reboot  

```

You should now observe your rpi4 operating in three different modes:

1. With zymkey 4i attached, full disk encryption (FDE) with LUKS will auto-unlock on power on or reboot.
2. Upon failure or removal of Zymkey 4i, remote unlock over dropbear SSH.
3. Upon failure or removal of Zymkey 4i, local console unlock with monitor/keyboard.

Remember to take frequent backups.  
Happy deployments!

---

<div class="post-metadata">

**Author:** ![israeconesa](https://avatars.discourse-cdn.com/v4/letter/i/54ee81/32.png) [@israeconesa](https://community.zymbit.com/u/israeconesa)\
**Post date:** [August 29, 2023, 3:15pm UTC](https://community.zymbit.com/t/raspberry-pi-4-ubuntu-22-04-luks-with-fallback/1500/2 "2023-08-29T15:15:13Z")

</div>

Hi, thanks for the guide. Unfortunately, I must be doing something wrong in this dance of mounting/unmounting, reducing/increasing partitions because I keep getting the same error after rebooting and dropping in initramfs.

 ![1693321570784](https://canada1.discourse-cdn.com/flex027/uploads/zymbit/original/2X/b/b0bb0b61fbdef5893ab0b3e01c285e9e7e760ce7.jpeg)

Is there an apparent point of failure that might result on that from your experience?

Regards,

Israel.

---

<div class="post-metadata">

**Author:** ![kontrasec](https://avatars.discourse-cdn.com/v4/letter/k/9de0a6/32.png) [@kontrasec](https://community.zymbit.com/u/kontrasec)\
**Post date:** [August 29, 2023, 4:23pm UTC](https://community.zymbit.com/t/raspberry-pi-4-ubuntu-22-04-luks-with-fallback/1500/3 "2023-08-29T16:23:08Z")

</div>

You are missing `cryptsetup` in your initramfs. I’ve noticed that the server image tends to include it, and the desktop image does not.

Boot into the unencrypted image, apt install cryptsetup and make sure initramfs is updated (update-initramfs), then reboot.
