Disk encryption with USB drive as the key

I’ve been playing around with dm-crypt and LUKS.

I’ve come up with a 10-step process to encrypt a couple of hard disks (not the boot drive) and use a USB key plugged in at boot time to unlock them – boot without the USB key in, and you boot fine, but the drives aren’t mounted or readable.

Initially I was going to try some UDEV rules to unlock+mount the drives whenever a USB key was plugged in, but in true UDEV style, it didn’t work – we got an endless loop of cryptsetup processes, also there’s a method for reading the keyfile from the USB drive from Grub, but that didn’t seem to work either, so I’m sticking with my method below.

1. Create a partition on each disk, optionally filling with random data first:

dd if=/dev/urandom of=/dev/sdb
dd if=/dev/urandom of=/dev/sdc
 
fdisk /dev/sdb
fdisk /dev/sdc

2. Format and encrypt in one command:

luksformat -t ext3 /dev/sdb1
luksformat -t ext3 /dev/sdc1

3. Fill keyfile with random data:

dd if=/dev/urandom of=secretkey bs=512 count=4

4. Add keyfile to LUKS volumes:

cryptsetup luksAddKey /dev/sdb1 secretkey
cryptsetup luksAddKey /dev/sdc1 secretkey

5. Fill USB key with random data, an old 64Mb disk took a few minutes:

dd if=/dev/urandom of=/dev/disk/by-id/usb-Mobile_Drive_7777777777777777-0\:0

6. Write keyfile to USB key’s MBR, note this will be invisible as its outside the partition table, and there’s no partitions defined, so it won’t mount the drive either:

dd if=secretkey of=/dev/disk/by-id/usb-Mobile_Drive_7777777777777777-0\:0  bs=512 seek=4

7. Secure delete the keyfile from hard disk – note you still have the passphrase (created in #2) to unlock the volumes if things go wrong:

shred --remove --zero secretkey

8. Update /etc/crypttab (chown root:root, chmod 600):

data1 /dev/sdb1 /dev/disk/by-id/usb-Mobile_Drive_7777777777777777-0\:0 luks,keyscript=/usr/local/bin/unlock-luks
data2 /dev/sdc1 /dev/disk/by-id/usb-Mobile_Drive_7777777777777777-0\:0 luks,keyscript=/usr/local/bin/unlock-luks

9. Create /usr/local/bin/unlock-luks (chown root:root, chmod 700):

#!/bin/sh
 
if [ -e $1 ]
then
dd if=$1 bs=512 skip=4 count=4
fi

10. Mount the encrypted volume at boot.

We do this in /etc/rc.local (chown root:root, chmod 700) as its the last part of the boot process – testing to see if LUKS managed to map the volumes first:

#!/bin/sh -e
 
if [ -e /dev/mapper/data1 -a -e /dev/mapper/data2 ] 
then
mount /dev/mapper/data1 /export/data1
mount /dev/mapper/data2 /export/data2
fi
 
exit 0

VirtualBox 2

Sun have updated xVM to v2.0, so I thought I’d have another crack at it – this time on my CentOS 5.2 box. I got dynamic bridging setup so that its more like VMWare – i.e. the physical eth0 is bridged to br0, and tap interface is created when you start a guest and removed when you stop the guest. You can access the LAN and internet. The setup is something like the following…..

1. Create /etc/sysconfig/network-scripts/ifcfg-br0, this is the permanent bridge interface, and effectively replaces your physical eth0

DEVICE=br0
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.0.6
NETMASK=255.255.255.0
NETWORK=192.168.0.0
BROADCAST=192.168.0.255
GATEWAY=192.168.0.1

2. Remove IP config for the physical interface /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0
BOOTPROTO=static
HWADDR=DE:AD:DE:AD:DE:AD
ONBOOT=yes
BRIDGE=br0

3. As I can never get UDEV changes to work on CentOS 5.2, I added this to /etc/security/console.perms.d/50-default.perms so that anyone in the vboxusers group can write to /dev/net/tun. This is similar to my previous post about the scanner.

<tunnel>=/dev/net/tun
<console> 0660
<tunnel> 0660 root.vboxusers

4. Added my user to vboxusers group, this doesn’t appear to be neccessary, contrary to the user guide….

usermod -a -G vboxusers myusername

5. Setup /etc/sudoers to not require a password for the startup/teardown scripts (below), also comment out the requirement for a TTY – this is the problem that stops you running sudo as part of the startup command for host networking as its running from a QT GUI, not a TTY.

#Defaults     requiretty
myusername   ALL = NOPASSWD: /usr/local/vbox/setuptap.sh, /usr/local/vbox/cleanuptap.sh

6. Create /usr/local/vbox/cleanuptap.sh, this is based on the script in the userguide.pdf – chmod a+x it to make it executable.

#!/bin/bash
/usr/sbin/brctl delif br0 $2
/usr/bin/VBoxTunctl -d $2

7. Create /usr/local/vbox/setuptap.sh

#!/bin/bash
interface=`/usr/bin/VBoxTunctl -b -u myusername`
if [ -z "$interface" ]; then
    exit 1
fi
echo $interface
/sbin/ifconfig $interface up
/usr/sbin/brctl addif br0 $interface

Then call “/usr/sbin/sudo /usr/local/vbox/setuptap.sh” as the startup, and cleanuptap.sh as the shutdown script in the network settings dialog (no interface name required).

8. Enable IP forwarding in /etc/sysctl.conf

net.ipv4.ip_forward = 1

9. Allow forwarding from the br0 interface in /etc/sysconfig/iptables

-A FORWARD -i br0 -j ACCEPT

I also checked for config files where I had bound to the eth0 interface – such as iptables, samba etc; and either set them to bind to br0 or to all interfaces (0.0.0.0:*)

I’m not particularly happy with the security implications of this method – you’ve got to lower permissions on the tunnel device, enable IP forwarding in the kernel, drop the firewall level, lower the security of sudo….. VMWare still does it much better; but this has better performance (I’m running Vista in 512Mb on an AthlonXP 2.4GHz) and is opensource and crossplatform, something that VMWare Server 2.0 most certainly isn’t.

Update: works for Fedora 9 and 10 too.

10. To enable USB support create a “usb” group (I guess you could use vboxusers created already) and add yourself to it:

groupadd -g 502 usb
usermod -a -G usb myusername

And add the following to /etc/fstab:

none /sys/bus/usb/drivers usbfs devgid=502,devmode=664 0 0

Update 2: it would seem that there is yet another permission problem with VirtualBox – if you want to be able to access the optical drives, you have to add yourself to the “disk” group. So that’s fudging with permission on tunnels, USB devices and CD drives now! I guess you could just assign all three to the vboxusers group and just add yourself to that, but this really is getting ridiculous now, people are going to give in and just run VirtualBox as root if you’re not careful.

Scanner Problems

I’ve wasted most of today trying to get my Epson RX425 scanner to work as a non-root user on CentOS 5.2

It worked fine before, so I think a kernel upgrade has broken udev, as I ended up having to edit /etc/security/console.perms.d/50-default-perms to allow less strict permissions on scanners than root-only.

It seems that doing it the proper way via /etc/udev/rules.d/60-iscan.rules no longer works – in fact you can put anything you like in the udev rules files and bugger all seems to change even after a reboot!

I seem to have been on pointless phonecalls all day today, and doing boring admin work like sorting out receipts and arranging a copy invoice for insurance claims etc.

I specced up a PC similar to the one I built for Kev the other day, and prices have gone up from about 500ukp to about 600ukp+ and specs have hardly gone up. So I’m going to wait for Nehalem aka Intel Core I7 before I build a new PC. I’ll rebuild and upgrade Solo a bit when Fedora10 comes out – replace the FX5200 with FX6200 graphics card and swap an old 200Gb for a new 250Gb hard disk.

Last night I decided I was going to look into scripting a load of DVD-to-DivX transcodes using mencoder. I basically took the commandline output from CloneDVD Mobile and put the same into mencoder on Linux. It all seemed to work quite well after some experimentation – for example specifying the audio language, threading and using the DVD:// virtual device instead of catting all the VOB’s together.

One odd thing is that some of the bitrates that work OK under CDVDm cause a segfault under mencoder for Linux, so I standardised on 1242kbps. When I got up in the morning I had four ripped DVD’s waiting for me!

mencoder dvd:// -dvd-device TRANSPORTER2 -ffourcc DIVX -af volume=10 \
-aspect 16:9 -of avi -noodml -oac mp3lame -ovc lavc \
-lavcopts vcodec=mpeg4:vbitrate=1242:abitrate=128:threads=2 \
-audio-preload 0.8 -delay 0.1 -lameopts cbr:br=128 -vf scale=640:360,harddup \
-info name="TRANSPORTER2" -ofps 24000/1001 -o /data4/video/transporter2.avi

Of course using the mencoder commandline on Linux rather than a GUI on Windows means that you can get to the other options – such as trimming the black bars and setting start and end points – features that CDVDm should really incorporate.