Two-factor LUKS using Ubuntu

Ubuntu 10.04 LTS “Lucid Lynx” supports LUKS quite well per default. This is a nice feature if you’re seeking for some extra security. But what if you want a real two-factor based solution?

In the office we have been using OpenPGP cards for quite some time now to secure data. It seemed a good idea to use the newly released USB version of the OpenPGP card combined with LUKS. Very easy to use since you only need to rember your PIN code and very secure as well (even more if you use 2048 or even 3072 bits keys).

Let’s assume you already own an OpenPGP card (smartcard or USB version) and are familiar with GnuPG. Nice, but what about the rest?

Ubuntu 10.04 Live DVD


Boot your system using an Ubuntu Live CD or Live DVD and choose the Try Ubuntu without installing option. When the system is booted, open a new Terminal and create new partitions on your hard drive (or SSD…).

$ sudo cfdisk -z

For example, create a 250 MiB partition for /boot and assign the rest of the available space to encrypt using LUKS:

$ sudo fdisk -l

Disk /dev/sda: 251.0 GB, 250999144448 bytes
64 heads, 32 sectors/track, 239371 cylinders
Units = cylinders of 2048 * 512 = 1048576 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00092b99

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1         238      243696   83  Linux
/dev/sda2             239      239371   244872192   da  Non-FS data

Install needed packages for LUKS and LVM:

$ sudo apt-get --force-yes --yes install cryptsetup lvm2
Reading package lists... Done
Building dependency tree
Reading state information... Done
cryptsetup is already the newest version.
The following extra packages will be installed:
  libdevmapper-event1.02.1 watershed
The following NEW packages will be installed:
  libdevmapper-event1.02.1 lvm2 watershed
0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
Need to get 0B/463kB of archives.
After this operation, 1,266kB of additional disk space will be used.
Selecting previously deselected package libdevmapper-event1.02.1.
(Reading database ... 165628 files and directories currently installed.)
Unpacking libdevmapper-event1.02.1 (from .../libdevmapper-event1.02.1_1.02.39-1ubuntu4_amd64.deb) ...
Selecting previously deselected package watershed.
Unpacking watershed (from .../watershed_5_amd64.deb) ...
Selecting previously deselected package lvm2.
Unpacking lvm2 (from .../lvm2_2.02.54-1ubuntu4_amd64.deb) ...
Processing triggers for man-db ...
Setting up libdevmapper-event1.02.1 (2:1.02.39-1ubuntu4) ...

Setting up watershed (5) ...
update-initramfs is disabled since running on read-only media

Setting up lvm2 (2.02.54-1ubuntu4) ...
update-initramfs is disabled since running on read-only media

Processing triggers for libc-bin ...
ldconfig deferred processing now taking place

Load needed kernel modules for LUKS, AES and XTS:

$ sudo modprobe dm-crypt aes xts

Generate a new key to protect the LUKS volume:

$ dd if=/dev/urandom | tr -d '\n' | dd bs=1 count=64 of=/dev/shm/luks-key.txt
64+0 records in
64+0 records out
64 bytes (64 B) copied, 0.000253039 s, 253 kB/s

Create a new LUKS volume:

$ sudo cryptsetup -c aes-xts-plain -s 512 luksFormat /dev/sda2 /dev/shm/luks-key.txt

WARNING!
========
This will overwrite data on /dev/sda2 irrevocably.

Are you sure? (Type uppercase yes): YES

Start the newly created LUKS volume:

$ sudo cryptsetup luksOpen -d /dev/shm/luks-key.txt /dev/sda2 crypto
Key slot 0 unlocked.

Create an LVM physical volume, volume group and some logical volumes:

$ sudo pvcreate /dev/mapper/crypto
  Physical volume "/dev/mapper/crypto" successfully created

$ sudo vgcreate vg /dev/mapper/crypto
  Volume group "vg" successfully created

$ sudo lvcreate -L 4G -n vg/swap
  Logical volume "swap" created

$ sudo lvcreate -L 40G -n vg/root
  Logical volume "root" created

$ sudo lvs
  LV   VG   Attr   LSize  Origin Snap%  Move Log Copy%  Convert
  root vg   -wi-a- 40.00g
  swap vg   -wi-a-  4.00g

The Ubuntu default installer gets a little confused if you don’t preformat the new logical volumes:

$ sudo mkswap -f /dev/vg/swap
Setting up swapspace version 1, size = 4194300 KiB
no label, UUID=ac1c5001-428b-49d3-9c1e-ce213a4b8b9e

$ sudo mkfs.ext3 /dev/vg/root
mke2fs 1.41.11 (14-Mar-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
2621440 inodes, 10485760 blocks
524288 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
320 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624

Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 23 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

Start the default installation:

Ubuntu installation icon

The installation works just like normal:

Ubuntu installation

Choose a language and timezone:

Ubuntu installation

Choose the correct keyboard layout:

Ubuntu installation

Choose for manual partitioning:

Ubuntu installation

Mind to use the correct logical volumes and /boot:

Ubuntu installation

Enter your personal data:

Ubuntu installation

Click Advanced… for a final check:

Ubuntu installation

CAUTON! When the installation has finished, do not close the window:

Ubuntu installation

Open a new Terminal and execute:

$ sudo mount -o bind /proc /target/proc
$ sudo mount -o bind /dev /target/dev
$ sudo mount -o bind /dev/pts /target/dev/pts
$ sudo mount -o bind /sys /target/sys

Store your pubring.gpg and secring.gpg somewhere and encrypt /dev/shm/luks-key.txt. Keep the resulting /dev/shm/luks-key.txt.gpg.

Fetch decrypt_luks.sh and gpg_luks and store these files as well. Copy the files to their correct locations:

$ sudo mkdir /target/etc/gpg_luks
$ sudo cp decrypt_luks.sh /target/usr/local/sbin
$ sudo cp gpg_luks /target/etc/initramfs-tools/hooks
$ sudo cp pubring.gpg /target/etc/gpg_luks
$ sudo cp secring.gpg /target/etc/gpg_luks
$ sudo cp /dev/shm/luks-key.txt.gpg /target/etc/gpg_luks

And fix the permissions:

$ sudo chmod 700 /target/etc/gpg_luks
$ sudo chmod 700 /target/usr/local/sbin/decrypt_luks.sh
$ sudo chmod 755 /target/etc/initramfs-tools/hooks/gpg_luks
$ sudo chmod 600 /target/etc/gpg_luks/pubring.gpg
$ sudo chmod 600 /target/etc/gpg_luks/secring.gpg
$ sudo chmod 600 /target/etc/gpg_luks/luks-key.txt.gpg

Create a crypttab file as follows:

$ cat /target/etc/crypttab
# <target name> <source device>         <key file>      <options>
crypto /dev/sda2 none luks,keyscript=/usr/local/sbin/decrypt_luks.sh

Install some needed packages:

$ sudo chroot /target su -
# apt-get install --force-yes --yes cryptsetup lvm2
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  libdevmapper-event1.02.1 watershed
The following NEW packages will be installed:
  cryptsetup libdevmapper-event1.02.1 lvm2 watershed
0 upgraded, 4 newly installed, 0 to remove and 242 not upgraded.
Need to get 606kB of archives.
After this operation, 1,831kB of additional disk space will be used.
Get:1 http://nl.archive.ubuntu.com/ubuntu/ lucid/main cryptsetup 2:1.1.0~rc2-1ubuntu13 [143kB]
Get:2 http://nl.archive.ubuntu.com/ubuntu/ lucid/main libdevmapper-event1.02.1 2:1.02.39-1ubuntu4 [28.5kB]
Get:3 http://nl.archive.ubuntu.com/ubuntu/ lucid/main watershed 5 [11.5kB]
Get:4 http://nl.archive.ubuntu.com/ubuntu/ lucid/main lvm2 2.02.54-1ubuntu4 [423kB]
Fetched 606kB in 1s (591kB/s)
Selecting previously deselected package cryptsetup.
(Reading database ... 124603 files and directories currently installed.)
Unpacking cryptsetup (from .../cryptsetup_2%3a1.1.0~rc2-1ubuntu13_amd64.deb) ...
Selecting previously deselected package libdevmapper-event1.02.1.
Unpacking libdevmapper-event1.02.1 (from .../libdevmapper-event1.02.1_2%3a1.02.39-1ubuntu4_amd64.deb) ...
Selecting previously deselected package watershed.
Unpacking watershed (from .../archives/watershed_5_amd64.deb) ...
Selecting previously deselected package lvm2.
Unpacking lvm2 (from .../lvm2_2.02.54-1ubuntu4_amd64.deb) ...
Processing triggers for ureadahead ...
Processing triggers for man-db ...
Setting up cryptsetup (2:1.1.0~rc2-1ubuntu13) ...
update-initramfs: deferring update (trigger activated)

Setting up libdevmapper-event1.02.1 (2:1.02.39-1ubuntu4) ...

Setting up watershed (5) ...
update-initramfs: deferring update (trigger activated)

Setting up lvm2 (2.02.54-1ubuntu4) ...
update-initramfs: deferring update (trigger activated)
Processing triggers for initramfs-tools ...
update-initramfs: Generating /boot/initrd.img-2.6.32-21-generic
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place

Make sure your system is bootable:

# update-initramfs -c -k all
update-initramfs: Generating /boot/initrd.img-2.6.32-21-generic
# update-grub2
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-2.6.32-21-generic
Found initrd image: /boot/initrd.img-2.6.32-21-generic
Found memtest86+ image: /memtest86+.bin
done

You can close the Terminal now and click Restart Now:

Ubuntu installation

At boot time, your system will ask for your OpenPGP card PIN code. Of course you’ll need your OpenPGP card as well. Real two-factor security!

Don’t worry about storing your secring.pgp somewhere in /boot. Only references to your OpenPGP card are stored in this file.

For reference: http://lfde.org/wiki/index.php/Ubuntu_Lucid_Lynx_10.04_Full_Disk_Encryption_with_USB_Key_Authentication

Tags: , , , , , , , , , , , , , ,


9 Responses to “Two-factor LUKS using Ubuntu”

  1. harningt says:

    Got this setup, awesome 🙂
    However, I had to make some modifications since creating a tty is breaks things in Ubuntu 13.10

    I edited the decrypt_luks.sh file and added –no-tty and dropped the tty setup code. And things work great 🙂

    One fix though, to avoid a warning printing out on the console, I edited the gpg_luks hook to update the permissions.

  2. harningt says:

    Awesome, will have to give this a try soon.
    Is there any guidance on setting up a backup option in case your token is broken?
    I’d guess you’d use the capability of cryptsetup to add another key to the drive, but I’m not too sure how the automatic input would work… I suppose you could edit the script so that it took an option to select between PIN for device or your alternate really long written down passphrase (perhaps with a bit you have to enter at the beginning or end so that even if you managed to lose the paper nobody could use it directly to login).

  3. Jan says:

    When executing
    “sudo cryptsetup -c aes-xts-plain -s 512 luksFormat /dev/sda2 /dev/shm/luks-key.txt”
    it failed with the error “Can’t wipe header /dev/sda2”. To fix it I had to run the following command first: “dd if=/dev/zero of=/dev/sda2 bs=1M count=8”

  4. Richard says:

    Hooray, it works!
    The remaining problem was indeed the empty secring.gpg.
    I read somewhere that it’s populated on first use.
    So, I decrypted the luks-key.txt.gpg file once on the live system, and then used the newly populated secring.gpg file from there. Might be obvious to people who are familiar with the stuff…

    Thanks again for the great tutorial.
    Richard

  5. Richard says:

    Sorry to bother again.

    Looks like what was missing is this:
    sudo mount /dev/sda1 /target/boot
    before the chroot

    Now it asks for my pin and says :
    cryptsetup failed, bad password or options?

  6. Richard says:

    Thanks for the comprehensive tutorial.

    I tried it with Mint 13.
    Installation went smooth. But when trying to boot, I get the following:

    Gave up waiting for root device.
    ALERT! /dev/mapper/vg-root does not exist. Dropping to a shell!

    I’m very new to this whole stuff. Is it normal, that the secring.gpg file has 0 bytes?

    Rgds
    Richard

Kumina designs, builds, operates and supports Kubernetes solutions that help companies thrive online. As Certified Kubernetes Service Partner, we know how to build real solutions.