Bug 261306 - Geli rc.d script does not support insertion of USB devices containing a keyfile.
Summary: Geli rc.d script does not support insertion of USB devices containing a keyfile.
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: conf (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-bugs (Nobody)
URL:
Keywords: feature, security
Depends on:
Blocks:
 
Reported: 2022-01-18 13:53 UTC by James Elstone
Modified: 2023-04-27 16:14 UTC (History)
3 users (show)

See Also:


Attachments
patch for /etc/rc.d/geli to enable waiting and very early mounting of a USB storage device (2.89 KB, patch)
2022-01-18 13:53 UTC, James Elstone
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description James Elstone 2022-01-18 13:53:14 UTC
Created attachment 231128 [details]
patch for /etc/rc.d/geli to enable waiting and very early mounting of a USB storage device

Outline -
==========

The script /etc/rc.d/geli does not support usb flash devices which either have a  hardware pin or are inserted during system boot process.

This will allow users to have a removable USB device with keyfiles on to be used by the _user-land_ geli service that is not stored in /boot/ or another fixed disk on the system. This would allow the security of key management to be increased.

The attached (git) patch provides a:

1) Pause for a defined number of seconds for the user to insert a predefined USB storage device.

2) Early mounting of an inserted USB device that contains a keyfile, but just for geli. This can then be used in the geli_*_flags rcvar as a referenced key file. The device is unmounted after Geli has used it, so not to impact later boot stages.


Detail -
========

This is a change to the /etc/rc.d/geli script, see attached diff.

Both the EFI loader and kernel boot process resets all USB devices as they are enumerated, as expected. If you are using a USB storage device that requires a manual pin to be entered before it is available (i.e. hardware pin entered on the USB storage device, e.g. iStorage DataShur) it is very difficult to get a consistent boot without it erroring and entering single user mode.

This change would also allow the late (prior to geli being called in the init process) insertion of any USB storage device for keyfile storage purposes. This would allow a practical end-user mechanism that would increase the system security as the keyfile is stored on an external and physically separate device of the users choice.

Each time the USB bus is enumerated the USB device is reset and in effect a pin based storage device is locked by this, as expected, but cannot be used due to the time it takes to enter a pin on the device. 


Example Usage -
===============

/etc/rc.conf:
  geli_secdevusb_device="/dev/gpt/security_key"
  geli_secdevusb_path="/security_key"
  geli_secdevusb_wait="120"
  geli_secdevusb_options=""

where:
- "/dev/gpt/security_key" is a gpart label for a UFS partition on a memory stick, or any other removable device that can be inserted and then mounted using mount(8).
- /security_keys is a directory that the USB device should be mounted on, and can be referenced in the geli_*_flags variables in rc.conf.


Setup for testing -
===================
da0 is a fixed disk being encrypted, and da1 is a removable usb storage device contianing the keyfile. Warning: These test instructions are destructive to the example devices, read first and adapt for your system; also make sure you have backed up any critical data encrypted or not for da0 and da1.

#create security key
mkdir /security_key
gpart create -s gpt /dev/da1
gpart add -a 1m -freebsd-ufs -l security_key /dev/da1
newfs /dev/da1p1
mount /dev/gpt/security_key /security_key
mkdir /security_key/geli
dd if=/dev/random of=/security_key/geli/DISK-ID0.key bs=64 count=1

#create encrypted volume with geli
gpart create -s gpt /dev/da0
gpart add -a 1m -freebsd-zfs -l DISK-ID0 /dev/da0
geli init -s 4096 -B none -K "/security_keys/DISK-ID0.key" "/dev/gpt/DISK-ID0"

#update rc.conf variables
sysrc geli_secdevusb_device="/dev/gpt/security_key"
sysrc geli_secdevusb_path="/security_key"
sysrc geli_secdevusb_wait="120"
sysrc geli_secdevusb_options=""
sysrc geli_gpt_DISK_ID0_flags="-k /security_key/geli/DISK-ID0.key"

#remove USB device that is da1 and reboot
reboot

#When prompted inset USB storage device that is da1 and enter the passphrase used with the geli init command above.


RC Vars -
=========
There are four new RC vars needed:
sysrc geli_secdevusb_device=""
sysrc geli_secdevusb_path=""
sysrc geli_secdevusb_wait=""
sysrc geli_secdevusb_options=""

The default rcvars should be as follows to prevent the code from operating unless the user requires:
geli_secdevusb_device=""
geli_secdevusb_path=""
geli_secdevusb_wait="0"
geli_secdevusb_options=""


Reasoning
=========

I maybe reinventing the wheel here, but have explored the /boot/loader.conf vars geli_*_name, and geli_*_flags in /etc/rc.conf, but does not cover this use case. Most of the examples online refer to putting the keys into /boot/ which is not a strong security practice IMO as you are storing the key and the encrypted data in the same machine.

I think this covers a use case not currently supported by FreeBSD, and is an improvement to have removable keyfiles on a usb device, and would like to help  other users to reduce their security footprint.
Comment 1 James Elstone 2022-01-18 14:12:12 UTC
Have tested this with FreeBSD 13-RELEASE and FreeBSD 13.0-RELEASE-p6, and is working as expected.
Comment 2 James Elstone 2022-01-18 17:32:42 UTC
Updatd instructions for creating a geli volume, one above had a typo.

#create encrypted volume with geli
gpart create -s gpt /dev/da0
gpart add -a 1m -freebsd-zfs -l DISK-ID0 /dev/da0
geli init -s 4096 -B none -K "/security_key/geli/DISK-ID0.key" "/dev/gpt/DISK-ID0"
Comment 3 James Elstone 2023-04-27 16:14:11 UTC
Is there any more I can do to help this progress please?