Encrypted HOME directory on a second disk with OpenBSD

Some time ago, I bought a used Thinkpad X250 as backup and travel laptop. After switching the internal HDD with one of my older SSDs and rebooting, I discovered that the previous owner already had a mSATA SSD module installed (Yes, I wasn't paying close attention when having the case open). So, I decided to install OpenBSD's base system on the smaller disk and use the SSD for my home directory. Since I want full disc encryption (FDE) for both disks I was stuck in a small dilemma here. Installing OpenBSD on the smaller disk with FDE is easy, however, the question remains how can the file system on the SSD be automatically encrypted and mounted to /home?

Upon boot the disk appear in dmesg as follows:

sd0 at scsibus1 targ 0 lun 0: <ATA, Crucial_CT525MX3, M0C> naa.500a03578bd35392
sd0: 500786MB, 512 bytes/sector, 1025610768 sectors, thin
sd1 at scsibus1 targ 1 lun 0: <ATA, TS120GMTS420S, Q112> naa.57c247816471b4d1
sd1: 114473MB, 512 bytes/sector, 234441648 sectors, thin

Let's start at the beginning. I installed a fresh copy of OpenBSD 6.6-current with FDE according to the excellent FAQ. After the first boot, I created a disklabel and a file system on the SSD for my home directory. Again, I followed the steps in the FAQ. However, instead of creating a FFS1 file system, I created a FFS2 file system. Since I set up the system shortly after the FFS2 boot change this seemed like the most logical choice.

Automount during Boot

To have my home partition automatically mounted during the boot process, I wrote a small shell script that is started every boot via /etc/rc.local. Tanks to everyone in the Fediverse who helped out, especially Pengouin(BSD|Pdt). The passphrase to decrypt the partition via bioctl(1) is stored a file in root's home directory. You might ask yourself, if it's secure to store the FDE passphrase in clear text in a file. Since the file is owned by root with mode 400, an attacker must have root access on my system. And if that's the case, I have a serious number of other problems besides having lost my FDE key. So I considered saving the key as described as acceptable for me. YMMV.

Here is the script I call from rc.local to mount the second disk. Note that I don't use devices names like sdX here to avoid getting problems with renamed disks if boot with an USB stick inserted. So if you intent to use the script change the DUID values to your local disk. You can get them by calling disklabel sdX:

#!/bin/sh

# Path to the key file.  One line with a long random password
KFILE=/root/discenc.key
# Modify to your needs
DUID_DISK=0811f47210dfbdb2
# Modify to your needs
DUID_CRYPT=9d5aa599b81dcab8

# Mountpoints
set -A MP -- /home /home/browser
# Corresponding disk slices.  Make sure the order matches the order
# of the mountpoints above
set -A SLICE -- a d

if [ ! -f $KFILE ]; then
    echo "$KFILE not found. Cannot mount $MP"
    exit 1
fi

sync

bioctl -c C -l ${DUID_DISK}.a -p $KFILE softraid0 || exit 1

i=0
for part in ${MP[@]}; do
    fsck -p ${DUID_CRYPT}.${SLICE[i]}
    if [ $? -gt 0 ]; then
        echo "fsck failed for ${part}.  Check manually"
        break
    fi
    mount -o noatime,softdep ${DUID_CRYPT}.${SLICE[i]} $part
    logger "Mounted $part"
    i=$((i+1))
done

And here is the script to umount the disks upon shutdown. It is called from /etc/rc.shutdown. Again, modify the mountpoints and if you have multiple make sure that you specify them in reverse order.

#!/bin/sh

# Modify to your needs
DUID_CRYPT=9d5aa599b81dcab8

# Mountpoints to unmount
set -A MP -- /home/browser /home

sync

for part in ${MP[@]}; do
    echo -n "Unmount $part "
    logger "Unmount $part"
    umount -f $part
    echo "done."
    sync
done

bioctl -d ${DUID_CRYPT}

If everything works as planned, your home directory will be mounted upon boot and umounted on shutdown. I should look similar to this (snippet from dmesg -s):

[...]
clearing /tmp
kern.securelevel: 0 -> 1
creating runtime link editor directory cache.
preserving editor files.
starting network daemons: smtpd sndiod.
softraid0: CRYPTO volume attached as sd3
/dev/sd3a (9d5aa599b81dcab8.a): file system is clean; not checking
/dev/sd3d (9d5aa599b81dcab8.d): file system is clean; not checking
starting local daemons: apmd cron xenodm.
[...]

Making sysupgrade(8) work

When setting all this up, I completely forget about sysupgrade. It stores the upgrade data sets in /home/_sysupgrade so directly in my mounted home partition. Since the bsd.rd kernel will not run /etc/rc.local the data set won't be available for the upgrade script. So I came up with the following:

With these two symlinks I can run sysupgrade as usual when logged in. After booting into bsd.upgrade the script can find the data sets since /var/_sysupgrade will be mounted in /mnt on the ramdisk.

$Id: enchome.md,v 1.2 2020/05/15 18:23:16 cvs Exp $