Building kernel modules
To build the kernel modules we first need to install the kernel sources matching the latest kernel. So first we download and install the required packages:
linux # apt install linux-source build-essential flex bison openssl libssl-dev dkms libelf-dev libudev-dev libudev-dev libiberty-dev autoconf libcap-dev
linux # ls /usr/src/linux-source-5.4.0 -l
total 131396
drwxr-xr-x 1 root root 460 Sep 7 09:47 debian
drwxr-xr-x 1 root root 240 Sep 7 09:47 debian.master
-rw-r--r-- 1 root root 134549352 Aug 26 15:15 linux-source-5.4.0.tar.bz2
And now prepare a kernel source tree for compilation:
linux # tar xjf /usr/src/linux-source-5.4.0.tar.bz2
linux # cd linux-source-5.4.0/
linux # rsync -avx /usr/src/linux-source-5.4.0/debian/ debian/
linux # rsync -avx /usr/src/linux-source-5.4.0/debian.master/ debian.master/
linux # mkdir debian/stamps
Now we should have the very same source tree that build our currently running kernel (well at least we will have it as soon as the debian/rules magic happened). Time to get and apply the patches. We also need to make some minor change to the kernels defconfig: The dm-crypt module is activated by default, so we only need to activate the building of the new module xtsproxy.
linux # wget -O - https://raw.githubusercontent.com/cloudflare/linux/12a61de6dd06408f4f3c27f8019beb66366e98e3/patches/0024-Add-xtsproxy-Crypto-API-module.patch | patch -p1
linux # wget -O - https://raw.githubusercontent.com/cloudflare/linux/12a61de6dd06408f4f3c27f8019beb66366e98e3/patches/0023-Add-DM_CRYPT_FORCE_INLINE-flag-to-dm-crypt-target.patch | patch -p1
linux # echo "CONFIG_CRYPTO_XTS_AES_SYNC=m" >> debian.master/config/config.common.ubuntu
Update: The current github release is rebased for latest stable kernel version 5.10. As the dm-crypt inline code was already merged here, there’s only a patch for xtsproxy available there. So for older kernel versions (like the Ubuntu Focal one: 5.4.0) make sure to get the older patches.
That’s all the preparation it needs. Now let’s build the new kernel/modules.
Update: Found a faster way to only compile the required modules:
linux # make -C /lib/modules/5.4.0-45-generic/build/ M=$PWD/drivers/md/ dm-crypt.ko
linux # make -C /lib/modules/5.4.0-45-generic/build/ M=$PWD/crypto/ CONFIG_CRYPTO_XTS_AES_SYNC=m xtsproxy.ko
linux # find . -name "*.ko"
./drivers/md/dm-crypt.ko
./crypto/xtsproxy.ko
Or you could rebuild most of the Ubuntu kernel packages: But this will take quite some time – get ready to get some coffee:
linux # fakeroot debian/rules clean
linux # fakeroot debian/rules binary-headers binary-generic binary-perarch
The new kernel modules will be located here:
linux # find debian/linux-modules-$(uname -r)/ -name dm-crypt.ko
debian/linux-modules-5.4.0-45-generic/lib/modules/5.4.0-45-generic/kernel/drivers/md/dm-crypt.ko
linux # find debian/linux-modules-$(uname -r)/ -name xtsproxy.ko
debian/linux-modules-5.4.0-45-generic/lib/modules/5.4.0-45-generic/kernel/crypto/xtsproxy.ko
As we now have two dm-crypt modules available, it’s important to know which one (if any) is currently loaded. To achieve that we’ll rely on the included srcversion:
# Shipped version:
linux # modinfo -F srcversion /lib/modules/$(uname -r)/kernel/drivers/md/dm-crypt.ko
8AD69BB5F232A7003E7AA85
# New version:
linux # modinfo -F srcversion debian/linux-modules-$(uname -r)/lib/modules/$(uname -r)/kernel/drivers/md/dm-crypt.ko
2E560E90F5A0578161F9F18
# Load module:
linux # modprobe dm-crypt
# Check loaded version:
linux # cat /sys/module/dm_crypt/srcversion
8AD69BB5F232A7003E7AA85
Make changes permanent
In order to permanently use the improvements we’ll need to install the generated modules into the kernel modules path and run depmod:
linux # mkdir /lib/modules/$(uname -r)/updates
linux # cp debian/linux-modules-5.4.0-45-generic/lib/modules/5.4.0-45-generic/kernel/crypto/xtsproxy.ko /lib/modules/$(uname -r)/updates/
linux # cp debian/linux-modules-5.4.0-45-generic/lib/modules/5.4.0-45-generic/kernel/drivers/md/dm-crypt.ko /lib/modules/$(uname -r)/updates/
linux # depmod -a
Make sure to use both modules at the same time: Though I didn’t notice a performance impact when xtsproxy wasn’t loaded one of my test maschines crashed regularly with kernel dumps.
But that’s not all that we need to do in order to activate the changes.
Activating changes
First of all we need to load the new modules:
linux # modprobe dm-crypt
linux # modprobe xtsproxy
Make sure the new version of dm-crypt got loaded (s. above).
Now we need to apply the changes to our existing LUKS devices. In order to apply the changes, there are however some pre-requirements: First of all LUKS devices created using the kernel keyring (like systemd does) can currently not be used as we required direct access to the key.
What we need to do is to modify a dmsetup table from this
linux # dmsetup table crypted_dev --showkeys
0 115433472 crypt xts-aes-plain64 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0 253:3 32768 1 sector_size:4096
to this
linux # dmsetup table crypted_dev --showkeys
0 115433472 crypt capi:xts-aes-xtsproxy-plain64 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0 253:3 32768 2 force_inline sector_size:4096
For security reasons the above output is the one without option –showkeys. If you run the above commands you should see a long line of (non-zero) numbers instead – that’s your encryption key.
So what we need to do is basically read the old config (using dmsetup table), modify the output to activate the new crypto functions and finally apply the modified settings to our device (using dmsetup reload).
More information about the dmsetup crypt table can be found here.
You can use the following script to activate the required settings:
#!/bin/bash
CRYPTDEV="$1"
if [ $# -ne 1 ]; then
echo "Syntax: $(basename $0) cryptodev"
exit 1
fi
if ! dmsetup table "$CRYPTDEV" >& /dev/null; then
echo "Cryptodev \"$CRYPTDEV\" not available"
exit 2
fi
OPTIONS=$(dmsetup table "$CRYPTDEV" --showkeys)
modprobe xtsproxy
if lsmod | grep -q xtsproxy; then
echo "Changing crypto variant"
OPTIONS=$(echo "$OPTIONS" | sed 's/aes-xts-plain64/capi:xts-aes-xtsproxy-plain64/')
else
echo "Module xtproxy not detected - aborting"
exit 3
fi
BASEOPTIONS=$(echo "$OPTIONS" | cut -d' ' -f1-8)
NUMOPTIONS=$(echo "$OPTIONS" | cut -d' ' -f9)
MOREOPTIONS=$(echo "$OPTIONS" | cut -d' ' -f10-)
if [ -n "$NUMOPTIONS" ]; then
NUMOPTIONS=$[ $NUMOPTIONS + 1 ]
MOREOPTIONS="$MOREOPTIONS force_inline"
else
NUMOPTIONS="1"
MOREOPTIONS="force_inline"
fi
echo "$BASEOPTIONS $NUMOPTIONS $MOREOPTIONS" | dmsetup reload "$CRYPTDEV"
dmsetup suspend "$CRYPTDEV"
dmsetup resume "$CRYPTDEV"