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?
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:
The installation works just like normal:
Choose a language and timezone:
Choose the correct keyboard layout:
Choose for manual partitioning:
Mind to use the correct logical volumes and /boot:
Enter your personal data:
Click Advanced… for a final check:
CAUTON! When the installation has finished, do not close the window:
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:
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: AES, disk partitioning, encryption, gnupg, LUKS, OpenPGP, PGP, PIN-code, security, smartcard, SSD, token, two-factor, Ubuntu, XTS
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.
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).
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”
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
Hi Richard,
Glad you found the solution! Sorry for not responding earlier :S
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?
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