Opening a LUKS container using a USB drive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I've been trying to set up an encrypted LUKS container, which could be opened only when a specific 
USB device was plugged into the USB port. I partially achieved what I wanted, but there's one thing 
I couldn't figure out.

When I boot the system, it waits till I plug the right USB device in. When I do so, then it 
processes the device and decrypts the root files system, and the system boots as usual.

It starts with:

	Begin: Running /scripts/local-top...
	Waiting for device...

After plugging the USB device, I can see the following messages:

	sd 0:0:0:0 [sda] No Caching mode page found
	sd 0:0:0:0 [sda] Assuming drive cache: write through
	8+0 records in
	8+0 records out

It hangs here for a while because it tries to open the LUKS container which is an SD card, and it 
succeeds. 

Then I can see the following errors:

	Nothing to read on input
	cryptsetup: ERROR rpi_crypt: cryptsetup failed, bad password or options?
	8+0 records in
	8+0 records out
	Device rpi_crypt already exists
	Nothing to read on input
	....
	cryptsetup: ERROR rpi_crypt: maximum number of tries exceeded
	done
	Begin: Running /scripts/local-premount ... done
	...
	
After the last cryptsetup error, the system continues to boot without any issue and it works well. 
So what's wrong with it?



Here's the full setup.

I created the LUKSv2 container in the following way:

	# cryptsetup luksFormat /dev/mmcblk0p2 \
	  --type luks2 \
	  --cipher aes-xts-plain64 \
	  --key-size 512 \
	  --hash sha512 \
	  --pbkdf argon2i \
	  --pbkdf-force-iterations 4 \
	  --pbkdf-memory 524288 \
	  --pbkdf-parallel 2 \
	  --label rpi \
	  --subsystem "" \
	  --use-random \
	  --verify-passphrase \
	  --verbose
	  
And then I created an EXT4 file system:

	# cryptsetup luksOpen /dev/mmcblk0p2 rpi_crypt

	# mke2fs \
		-t ext4 \
		-m 0 \
		-L rootfs \
		-J size=128 \
		-O 64bit,has_journal,extents,huge_file,flex_bg,metadata_csum,dir_nlink,extra_isize,^resize_inode,^uninit_bg \
		-E lazy_itable_init=0,lazy_journal_init=0 \
		/dev/mapper/rpi_crypt

The SD card looks like this:

	# lsblk -o "NAME,SIZE,FSTYPE,TYPE,LABEL,MOUNTPOINT,UUID,PARTUUID" /dev/mmcblk0
	NAME           SIZE FSTYPE      TYPE  LABEL  MOUNTPOINT UUID                                 PARTUUID
	mmcblk0       28.8G             disk
	├─mmcblk0p1    256M vfat        part  boot              B05C-D0C4                            0d03b705-01
	└─mmcblk0p2   28.6G crypto_LUKS part  rpi               0b9b66eb-d5ec-4371-80e3-f3a6ae92e0be 0d03b705-02
	  └─rpi_crypt 28.6G ext4        crypt rootfs /media/rpi 0ca2062b-142b-4826-bb74-d465ca89b554

This is the /etc/fstab entry:

	UUID=0ca2062b-142b-4826-bb74-d465ca89b554  /   ext4    defaults,lazytime,errors=remount-ro  0 1

This is the /etc/crypttab entry:

	rpi_crypt  UUID=0b9b66eb-d5ec-4371-80e3-f3a6ae92e0be   none  luks,keyscript=/usr/sbin/unlock-rpi,initramfs,keyslot=1

In the kernel cmdline I added luks.crypttab=no to disable the systemd cryptsetup generator as it 
doesn't support many crypttab options.

The LUKS container can be opened at boot without issues when the luks,initramfs options are 
specified in /etc/crypttab , but in this way I would have to enter the password manually each time I
boot the system, and my RPI doesn't have a keyboard connected. Instead I wanted to use a USB 
drive to open the LUKS container. I mean the device is used in this process and not a keyfile 
that sits inside of the device's file system. That's why I used keyscript=/usr/sbin/unlock-rpi in 
/etc/crypttab . Here's the content of the script:

	#!/bin/sh

	dd if=/dev/usbkey bs=512 skip=100 count=8 | \
	 cryptsetup luksOpen /dev/mmcblk0p2 rpi_crypt --key-file=-

To get the /dev/usbkey device, I have the following UDEV rule:

	ACTION=="add", KERNEL=="sd?", \
	 ENV{ID_SERIAL_SHORT}=="0019E06B9C8ABE41C7A2C3EC", \
	 SYMLINK+="usbkey%n"
	 
So the script reads the 4096 bytes starting at certain point of the pendrive, then it hands the 
data to cryptsetup and the device can be unlocked.

Both of the files are included in the initramfs/initrd image.

The keyfile was added to the LUKS header in the following way:

	# dd if=/dev/random of=/tmp-ram/keyfile bs=1 count=4096
	# cryptsetup luksAddKey /dev/mmcblk0p2 /tmp-ram/keyfile --hash sha512
	# cryptsetup luksDump /dev/mmcblk0p2
	LUKS header information
	...
	  1: luks2
		Key:        512 bits
		Priority:   normal
		Cipher:     aes-xts-plain64
		Cipher key: 512 bits
		PBKDF:      argon2i
		Time cost:  4
		Memory:     185496
		Threads:    4
		Salt:       79 04 9f 36 26 2f da 5d 1c c0 a1 be 8a 73 6f c5 
					d8 c7 55 97 a0 cf ee 5c ec ae 20 11 06 d0 27 62 
		AF stripes: 4000
		AF hash:    sha512
		Area offset:290816 [bytes]
		Area length:258048 [bytes]
		Digest ID:  0
	...

Since the keyfile was added to the keyslot number 1, I used also the keyslot=1 option in 
/etc/crypttab.

The keyfile was also burned to the pendrive using the following commands:

	# dd if=/dev/urandom of=/dev/sda bs=512 count=2047 seek=1
	# dd if=/tmp-ram/keyfile of=/dev/sda bs=512 seek=100

To make all this work, I had to add two things to the initramfs/initrd image: 1) a hook, 2) a 
script:

Here's the /etc/initramfs-tools/hooks/unlock-rpi hook, which copies the keyscript to the image:

	#!/bin/sh

	set -e

	PREREQ=""
	prereqs()
	{
	   echo "$PREREQ"
	}

	case $1 in
	prereqs)
	   prereqs
	   exit 0
	   ;;
	esac

	[ -r /usr/share/initramfs-tools/hook-functions ] || exit 0
	. /usr/share/initramfs-tools/hook-functions

	copy_exec /usr/local/bin/unlock-rpi /usr/sbin/
	chmod +x  /usr/sbin/unlock-rpi

And here's the /etc/initramfs-tools/scripts/local-top/delay-decrypt' script, which delays the boot 
process till the right USB device is plugged in (since I created a link to the block device, I had 
to check for link and not for the block device):

	#!/bin/sh

	PREREQ="udev"
	prereqs()
	{
	   echo "$PREREQ"
	}

	case $1 in
	prereqs)
	   prereqs
	   exit 0
	   ;;
	esac

	# source for log_*_msg() functions, see LP: #272301
	. /scripts/functions

	# Default PATH differs between shells, and is not automatically exported
	# by klibc dash.  Make it consistent.
	export PATH=/sbin:/usr/sbin:/bin:/usr/bin

	DEVICE=/dev/usbkey
	if [ ! -L "$DEVICE" ]; then
		echo -e "\nWaiting for device..." >&2
		until [ -L "$DEVICE" ]; do
			sleep 1
		done
	fi

	exit 0

So what's wrong with this setup, and why it tries to open the LUKS container multiple times even 
when it succeeds for the very first time after the USB device was plugged in?
_______________________________________________
dm-crypt mailing list -- dm-crypt@xxxxxxxx
To unsubscribe send an email to dm-crypt-leave@xxxxxxxx




[Index of Archives]     [Device Mapper Devel]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]     [Fedora Docs]

  Powered by Linux