Table of Contents

Disclaimer: I only tried this with the LIME2 hardware

Disclaimer2: It can be really easy to get locked out of the system if anything goes wrong (like a mistake in the helper script), so backup your important data (and the functional initramfs) and consider the necessity of physical intervention (through the serial port or simply by accessing the Cube's SD card from your PC)

Introduction

The goal of this howto is to be able to unlock the rootfs of the encrypted version of the Internet Cube by using a USB key, as an alternative to providing the passphrase (in my case, because I can't unlock the rootfs through the network).

Note that it doesn't replace the traditional authentication mecanism with the passphrase, it only adds another authentication mecanism through the presence of a USB key.

There are different ways of unlocking a LUKS partition, for example with a passfile on a USB stick.

I decided to use a USB key, a devoted USB stick filled with random data containing the content of the keyfile, already documented on the internet (for example here). The steps I followed are pretty much the same, except for the last issue I faced which was more specific to the Internet Cube.

I started from an already working instance of the Cube (encrypted image of course).

Why would you do that

Note also that, as in any security system, the overall security boils down to the security of the weaker point. For example, if you keep the USB stick plugged all the time, it would be the same as if you didn't have any encryption on the disk.

Keep also in mind that if you want to protect the data from physical stealing (by stealing the hardware), you should avoid to keep the Cube and the key in the same place (two different places in the same room, with no apparent link between the USB stick and the Cube, like a “Cube decryption key” sticker or equivalent, is IMHO a bare minimum).

Preparation of the USB key

I filled a (small) USB stick with random data:

dd if=/dev/random of=/dev/sda

where sda is the device corresponding to the USB stick

Note: I didn't create any partition on it, it is just plain random data.

Preparation of the LUKS disk

First we need to extract the content of the passfile from the USB stick:

dd if=/dev/sda of=keyfile bs=1 count=4096 skip=67543

Note that the skip parameter is optional, it just allows to use the data from the middle of the stick and not the first bytes.

Then we add this keyfile into one of the slots of the LUKS partition (mmcblk0p2 on my system):

cryptsetup luksAddKey /dev/mmcblk0p2 keyfile

Note that you will be asked the passphrase to unlock the LUKS header

Last, we delete the keyfile:

shred --remove --zero keyfile

Configuration of the boot system

Now that our disk is ready, we have to update the boot configuration. In order to get the data from the stick, we will use the script system provided by the cryptsetup package through the crypttab file.

First we need to know the id of our USB stick:

ls -l /dev/disk/by-id | grep sda

On my system it returns

lrwxrwxrwx 1 root root  9 Jan  1 01:01 usb-USB_2.0_Flash_Disk_04032200B5073301-0:0 -> ../../sda

We will use the id label to identify the stick from where to get the data, even in the case that something else is plugged in a USB port.

We then edit the /etc/crypttab file:

# <target name> <source device>         <key file>      <options>
# This is the previous line, which I commented
#root    /dev/mmcblk0p2  none    luks
# We replace it with this line
root    /dev/mmcblk0p2  usb-USB_2.0_Flash_Disk_04032200B5073301-0:0 luks,keyscript=/usr/local/bin/crypto-usb-key.sh

We replaced the 3rd field with the id of our USB stick, and added the option keyscript, which allows us to use an external helper script to read the key:

#!/bin/sh

# we wait a bit to detect the USB stick
echo "Trying to get the key from USB keychain ..." >&2
sleep 5

if [ "x$1" = "x" -o "x$1" = "xnone" ]; then
    echo "Error: no argument received... exiting"
    exit 1
else
    # this is where we use the USB stick id
    diskid=$1
    usbkey=/dev/disk/by-id/${diskid}
fi
if [ -e ${usbkey} ]; then
    # if the USB stick is detected, we extract the data for unlocking 
    # /!\ be sure to use the same skip parameter as in the previous step /!\
    ask_passphrase=0
    echo "USB Key detected - unlocking partition $device ..." >&2
    dd if=${usbkey} bs=1 count=4096 skip=67543
    
else
    # if we don't find the USB stick, we ask for the passphrase
    echo "FAILED to find suitable USB keychain ..." >&2
    /lib/cryptsetup/askpass "Try to enter your password: " 
fi

We need then to add the necessary usb modules in the file /etc/initramfs-tools/module:

# List of modules that you want to include in your initramfs.
# They will be loaded at boot time in the order below.
#
# Syntax:  module_name [args ...]
#
# You must run update-initramfs(8) to effect this change.
#
# Examples:
#
# raid1
# sd_mod
[...]
ehci_hcd
ohci_hcd
ehci_platform
ohci_platform
usb_storage

Another important step is to edit the /etc/default/flash-kernel file, which contains the default arguments passed to the kernel and flashed to the bootloader. By default, it contains the cryptopts arguments, which has priority over the crypttab parameters, so we get rid of it:

#LINUX_KERNEL_CMDLINE="console=ttyS1 hdmi.audio=EDID:0 disp.screen0_output_mode=EDID:1280x720p60 root=/dev/mapper/root cryptopts=target=root,source=/dev/mmcblk0p2,cipher=aes-xts-plain64,size=256,hash=sha1 rootwait sunxi_ve_mem_reserve=0 sunxi_g2d_mem_reserve=0 sunxi_no_mali_mem_reserve sunxi_fb_mem_reserve=0 panic=10 loglevel=6 consoleblank=0"
LINUX_KERNEL_CMDLINE="console=ttyS1 hdmi.audio=EDID:0 disp.screen0_output_mode=EEDID:1280x720p60 root=/dev/mapper/root rootwait sunxi_ve_mem_reserve=0 sunxi_g2d__mem_reserve=0 sunxi_no_mali_mem_reserve sunxi_fb_mem_reserve=0 panic=10 loglevel=6 consoleblank=0"

Now it's time to update the initramfs, before rebooting:

update-initramfs -u

Reboot

Now, you should be able to unlock your root partition with the USB key you prepared, your Internet Cube should be up without having to enter any passphrase!

/!\ Don't forget to unplug the USB key after boot and store it in a safe place /!\

Note also that I was doing all these manipulations through the serial port of the Internet Cube (I am using the Bus Pirate device), so I had direct access to enter the passphrase if anything went wrong (actually I couldn't enter it through the network, so I don't know it this would still work in that case, if someone could try it, I'm curious to know about it)