Mounting a LUKS-encrypted volume at boot time

Hi,

I successfully encrypted an USB-stick partition and I’m able to mount it. (An example howto can e.g. be found here)
Unfortunately mounting at boot time is not possible as cryptdisks_start does not work:

root@Router:~# cryptdisks_start crypt
-ash: cryptdisks_start: not found

Installed packages (for cryptsetup and mounting volumes): block-mount kmod-usb-storage-extras kmod-fs-ext4 e2fsprogs kmod-crypto-xts kmod-crypto-iv kmod-crypto-misc kmod-crypto-user cryptsetup

Did I miss a package or is this a bug?

(adressing the “does it make any sense to have a keyfile for encrypting a device stored to an unencrypted device”: I just don’t want anyone to be able to grab an USB-Stick and retrieve sensitive data - no more, no less. As there is no PCIe port left inside the device housing, I had to externally attach an USB-stick.)

I have a very similar situation, so I will pin to that question.

I think the topic might be changed to “Mounting an ?LUKS?-encrypted storage at boot time”. To make it a bit more general. Since the solution for this might be applied to internal mSATA drive as well as other possible options.

Sure, you’re welcome.

I am pretty certain that dm-crypt with password interaction is not working. LUKS with keys seems a different matter and could be working unless the crypt driver is not getting loaded during boot but only at hotplug level, perhaps something with the boot environment. Like mentioned here

you have to act at the level of hotplug, because the implementation of cryptosetup of openwrt not seem to support the /etc/crypttab (probably should be recompiled the boot image)

Have been looking at the subject far and wide and haven’t come across a solution for mounting encrypted (in/external) drives at boot time, be it dm-crypt with password or LUKS with keys.

Did you try the proposed solution in your linked thread?

Nope, because it covers only devices hotplugged once the system is fully booted but not password interaction at boot time for encrypted devices like it does on a linux system with crypttab support.

1 Like

This is a automated LUKS decrypting “quick fix” that I’m running at /etc/hotplug.d/block/99-lukscrypt:

#!/bin/bash
# Perform tasks when called by BLOCK hotplug (/etc/hotplug.d/block/99-lukscrypt)
# CC0: 21JUL18 by WaLLy3K, updated 09AUG18
[[ -z "${DEVNAME}" ]] && DEVNAME="${1##*/}"
msg() { logger -st "$(basename "${0%.*}")($DEVNAME)[$$]" -- "$@"; }

# Hotplug Vars: $ACTION (add/remove), $DEVICE (?), $DEVNAME (sdx)
BID_RAW="$(blkid "/dev/$DEVNAME" | awk -v RS=' ' '{gsub("[:\"]",""); print $0}')"
BID_UUID="$(awk -F= '/UUID/ {print $2}' <<< "$BID_RAW")"
BID_TYPE="$(awk -F= '/TYPE/ {print $2}' <<< "$BID_RAW")"

# Determine whether drive needs to be decrypted
[[ ! -r "/etc/crypttab" ]] && { msg "Unable to read file: /etc/crypttab"; exit 1; }
CT_RAW="$(grep "$BID_UUID" /etc/crypttab)"

if [[ -n "${CT_RAW:-}" ]]; then
  CT_LABEL="$(awk '{print $1}' <<< "$CT_RAW")"
  CT_KEYFILE="$(awk '{print $3}' <<< "$CT_RAW")"
  CT_TYPE="$(awk -F '[ ,]+' '{print $4}' <<< "$CT_RAW")"
  #CT_SCRIPT="$(awk -F "keyscript=" '{print $2}' <<< "$CT_RAW")"

  if [[ -e "/dev/mapper/${CT_LABEL,,}" ]]; then
    msg "Drive already decrypted: $CT_LABEL"
    exit 0
  fi

  # Error Handling
  if [[ ! -e "$CT_KEYFILE" ]]; then
    msg "Unable to view keyfile: '$CT_KEYFILE'"
    exit 1
  fi
  if [[ ! "${BID_TYPE,,}" == *"${CT_TYPE,,}"* ]]; then
    msg "Unable to decrypt format: $CT_TYPE"
    exit 1
  fi

  msg "Decrypting drive: $CT_LABEL (/dev/$DEVNAME)"
  cryptsetup luksOpen "/dev/$DEVNAME" "${CT_LABEL,,}" -d "$CT_KEYFILE"
  CS_EXIT="$?"
  case "$CS_EXIT" in
    0)  if test -e "/dev/mapper/${CT_LABEL,,}"; then
          msg "Drive decrypted: $CT_LABEL"
        else
          msg "Drive not found after decrypting: $CT_LABEL"
          exit 1
        fi;;
    5) msg "Device already exists: $CT_LABEL (Dmsetup stuck?)"; exit 1;;
    *) msg "Unable to decrypt drive: $CT_LABEL ($CS_EXIT)"; exit 1;;
  esac

  # Mount drive if specified in fstab (or LuCI > System > Mount Points)
  block mount
fi

Then in /etc/rc.local (Also editable via LuCI > System > Startup > Local Startup) for decrypting upon boot:

# Decrypt drives upon boot
for b in /dev/sd*; do
  /root/scripts/block-hotplug.sh "$b"
done

It should be able to read /etc/crypttab lines like the following: DEVICELABEL UUID=0000-0000-0000-0000-0000 /path/to/keyfile luks, but doesn’t support password input.

This may not work for you “as-is”, but can hopefully get anyone reading this started in the right direction.

2 Likes

Thanks for sharing indeed.

Suppose you are using random content key files then and not passphrase protected keyfiles?

The issue with random key files to decrypt the LUKS volume is though that anyone with access to random keyfile(s) can decrypt the LUKS volume without the need for a password.
So perhaps random key file(s) is (are) should not be stored on the same hard drive as the LUKS volume is on but on another drive that then needs to be present at the time of decrypting the LUKS volume.

I wish there would a be way that provides for password interaction for decrypting volumes like it is common on a standard linux system.

Indeed. My threat model for LUKS essentially involves direct theft of an external hard drive, and better security is a bit limited when you’re having to script your own solution “acting at the level of hotplug”! :frowning:

So you keep the random content keyfile(s) on another hard drive than the one the LUKS volume is hosted on, if I understand correctly? Which would mean to revove that drive with the keyfiles on after each reboot, for the obvious security reason, and store it in a safe place and plug it back into the router for each reboot?

Opened a feaure request https://gitlab.labs.nic.cz/turris/turris-os-packages/issues/208

Perhaps anyone interested could vote up on it or even contribute patches.

That’s exactly my threat model, too.
In my case I store the file directly on the Omnia’s emmc.
But: if there was the possibility to enter PW at boot time, I’d gladly use that solution :blush:

And if the router gets snatched/taken together with the encrypted external hd? Suppose that mounting the router on a surface can make a petty theft of the router less likely.

You’re right, I just added the last sentence.
I would encrypt complete storage of TO, if that was possible - with having a USV attached and schnapps (snapshots would for sure need to be encrypted, too) availability, I don’t find it inconvenient to enter pw at boot time.

I do the same setup as @ssdnvv - I suppose it’d be possible to create a script that creates a valid keyfile on boot if correct network conditions are met (e.g: hashed PPPoE login details match what’s stored in uci, and a valid IP address), but I haven’t really looked into it :slight_smile:

Edit: If someone were to swipe the router and the external hard drive, they wouldn’t be able to access it anyway unless you have some unauthenticated means of accessing the content (e.g: Guest Samba/FTP).

Just another concept:

  • Point location of keyfile to an unencrypted device (e.g. eMMC)
  • Store keyfile permanently on the encrypted device + safely at a location not connected to your TO (backup-keyfile)
  • Create a Bash-Script with a trap on Exit. If the Bash Script gets killed during normal shutdown or reboot the trap on Exit calls a function that copies keyfile from encrypted device to the unencrypted device

Result:

  • If TO was shut down or rebooted normally the encrypted device can be mounted automatically with the keyfile on the unencrypted device
  • If TO was just disconnected from powersource (e.g. because it gets robbed) the robber has no access to the keyfile and can‘t decrypt your encrypted device

Requirements:

  • For this to work the keyfile has to be deleted SAFELY after every automatic mount of the encrypted device

And:

  • If the TO gets turned off because of an powerfailure you can either mount the encrypted device manually with your backup-keyfile or protect your TO against power failure using an UPS that shuts down TO gracefully before its battery gets low
1 Like

Before testing your solution I’d need to find a solution for a strange problem that arose after updating to 3.10.4/5:
I’m no more able to mount my encrypted volume.
Normal steps that worked before:

cryptsetup luksFormat /dev/sda1
cryptsetup open /dev/sda1 crypt
mkfs.ext4 /dev/mapper/crypt
mount /dev/mapper/crypt /srv

But when now running the last command I get the following in return:
mount: mounting /dev/mapper/crypt on /srv failed: Invalid argument

Even stranger: When on my second TO I [just today a few hours earlier] set up another encrypted USB-Stick it worked without any problem (maybe little bit different approach - as I set it up after updating to TOS 3.10.5).
Tried with different USB-Stick and different folders but getting always the same error-message… :frowning:

edit: I get the same mystake when trying to mount not encrypted volume (directly formating as ext4).

This is most probably because of missmatch between modules and kernel version. Try to reboot router to run updated version of kernel.

If it won’t help then try to compare installed packages (specially ones with mkmod- prefix) between those two routers. You might be missing some software or kernel module.

TO1 = first router in apartment 1. Mounting volumes (normal or encrypted) works fine.
TO2 = second router in separat building. Mounting volumes (normal or encrypted) does not work, I get the error-message mount: mounting /dev/mapper/crypt on /srv failed: Invalid argument, but worked on TO version <3.10.3. Rebooted 3 times.

Kernel version seems to be ok for both TO2 and TO1 for all kmod-packages. TO1 has all and even several more kmod-(usb-)packages installed compared to TO2.

If TO1 was not my main router for my apartment, I’d set it up from scratch again to solve that issue - that’s what I did with TO2 when I acquired it this May. But as I don’t want to work 2 days nightshift (WAF of resetting a router at daylight=0) resetting is not an option at the moment…

Any more suggestions, @cynerd ?

that is awesome, it works for me!
just one small fix

should probably point to the newly created script:

for b in /dev/sd*; do
   /etc/hotplug.d/block/99-lukscrypt "$b"
done