This is an old revision of the document!


Work in progress!!!

Disclaimer: I only tried this with the LIME2 hardware

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)

Introduction

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 summary of the steps I followed will be 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.

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)

  • howto/unlock_cryptroot_usb.1486509647.txt.gz
  • Last modified: 2018/12/08 22:28
  • (external edit)