wiki:Linux/Ubuntu/HardyEncryptedLVM

Version 9 (modified by tj, 9 years ago) (diff)

--

Hardy Encrypted Logical Volume Management

This article shows how to use the Ubuntu Hardy Desktop Live CD to build and install to a secure encrypted Logical system that requires a key-file on an external USB memory stick in order to start. It is designed to secure portable PCs (netbooks, notebooks, laptops, etc.).

The existing organisation and usage of the laptop was preventing an upgrade from Gutsy to Hardy: sda6 (12.8GiB - the Gutsy / partition) was too full, and I had too many customisations I didn't want to lose. Most of the partitions were at or near capacity. I decided to backup all the data to other disks and do a clean install that allowed me to create an optimum configuration that included encryption and LVM.

Existing Layout

In my case the laptop PC was fully utilising the 200GB (186GiB) hard disk:

fdisk -ul /dev/sda

Disk /dev/sda: 200.0 GB, 200049647616 bytes
255 heads, 63 sectors/track, 24321 cylinders, total 390721968 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0xf7fc3a6e

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1            2048    19531775     9764864   27  Unknown
/dev/sda2   *    19531776    77008895    28738560    7  HPFS/NTFS
/dev/sda3        77008896    81008896     2000000+  82  Linux swap / Solaris
/dev/sda4        81015795   390716864   154850535    5  Extended
/dev/sda5        81015858    81497744      240943+  83  Linux
/dev/sda6        81497808   108406619    13454406   83  Linux
/dev/sda7       108406683   120551759     6072538+  83  Linux
/dev/sda8       120551823   390716864   135082521   83  Linux
  • sda1 9.3GiB Sony Recovery
  • sda2 27.4GiB Windows Vista
  • sda3 1.9GiB Linux Swap
  • sda5 235.3MiB /boot
  • sda6 12.8GiB / (Gutsy - primary OS)
  • sda7 5.8GiB / (Ubuntu+1 testing)
  • sda8 128.8GiB /home

Optimised Layout

Note: The Data Back-Up step was done before the partition-table changes detailed here were performed. However, it seemed more logical to keep the before and after partition layout sections together in this article.

I wanted to simplify the Linux organisation, drop the almost 10GB taken up by the Sony Recovery partition, and shuffle the Windows Vista partition closer to the start of the disk. I also needed the LVM flexibility to shrink, grow, remove and create volumes to help with advanced testing.

  • sda1 251.0MiB /boot
  • sda2 27.4GiB Windows Vista
  • sda3 4.0GiB Linux Swap
  • sda4 154.8GiB Linux (encrypted) + LVM VG + / (Hardy), /var, /home, / (Ubuntu+1) and spare

I used cfdisk to create the revised layout (I initially used fdisk to ensure the Windows partition was exactly the same size as previously but cfdisk reported "FATAL ERROR: Bad primary partition 3: Partition ends in the final partial cylinder" so, since cfdisk's reputation is so good, I let it do the work. The result is that the Windows Vista partition is slightly bigger than the NTFS file-system image that was backed up, but Vista's Disk Management tool can expand the NTFS live file-system to ensure the slack space will be used.

fdisk -ul /dev/sda

Disk /dev/sda: 200.0 GB, 200049647616 bytes
255 heads, 63 sectors/track, 24321 cylinders, total 390721968 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0x4abc0f4b

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1              63      498014      248976   83  Linux
/dev/sda2   *      498015    57994649    28748317+   7  HPFS/NTFS
/dev/sda3        57994650    65995019     4000185   82  Linux swap / Solaris
/dev/sda4        65995020   390716864   162360922+  83  Linux

Data Back-Up

I copied a large amount of non-core data directories (Source-code repositories, audio-book libraries, camcorder library, etc.) to an external USB2 160GB drive. It already had a lot of data on it so I then used rsync to copy all of /, /boot, /home, and the Vista partition image to a RAID-5 server over a 100Mbps ethernet link.

Total data moved over ethernet was 30GiB + 10GiB + 27.4GiB and it took about 3.5 hours.

I started the laptop with the Hardy Desktop Live CD, installed the sshfs package from the universe repository, and mounted the network server in the Live CD environment:

sudo su
sed -i 's/^# \(deb .*universe\)/\1/' /etc/apt/sources.list
apt-get update
apt-get install sshfs
mkdir /mnt/remote
sshfs tj@10.254.251.72: /mnt/remote

I mounted the local hard drive partitions into the Live CD environment:

mkdir /mnt/rootfs
mkdir /mnt/home
mount /dev/sda6 /mnt/rootfs
mount /dev/sda5 /mnt/rootfs/boot
mount /dev/sda8 /mnt/home

I kept /home on a separate mount-point so I could rsync the root file-system and home separately. These operations took several hours:

rsync -ae ssh --delete /mnt/home/ tj@10.254.251.72:Backups/home/
rsync -ae ssh --delete /mnt/rootfs/ tj@10.254.251.72:Backups/rootfs/

I copied an image of the Windows Vista partition (27.4GiB) to the network server:

dd if=/dev/sda2 bs=512000 of=/mnt/remote/Backups/sda2-Vista.img

I copied an image of the Sony Recovery partition (10GB) to the external USB2 hard disk:

dd if=/dev/sda1 bs=512000 of=/media/disk/Backups/sda1-SonyRecovery.img

Finally, I made a backup of the master boot record (MBR) sector and a textual log from fdisk:

dd if=/dev/sda bs=512 count=1 of=/mnt/remote/Backups/mbr-sector.bin
fdisk -ul /dev/sda > /mnt/remote/Backups/sda-fdisk.txt

Encryption

First, install the cryptography package:

apt-get install cryptsetup

Load the kernel module:

modprobe dm-crypt

Randomise the disk surface

By ensuring every sector of the disk partition is written with random data, a potential attacker will have great difficulty locating encrypted data that they might want to try to decrypt. If the surface of the disk was written with zeros (using if=/dev/zero) or some other predictable values encrypted data would be easy to identify if the disk were to fall into hostile hands.

Option 1: The Long Way

This is likely to take a long time - possibly 24 hours or more:

dd if=/dev/urandom of=/dev/sda4

Check the progress by sending the USR1 signal to the dd process from another terminal window:

ps -ef | sed -n 's/[a-z ]*\([0-9]*\).* dd.*/\1/p' | while read PID; do kill -USR1 $PID; done

The dd terminal will report its statistics:

6243380+0 records in
6243379+0 records out
3196610048 bytes (3.2 GB) copied, 559.041 s, 5.7 MB/s

Wait until dd finishes.

Option 2: The Short Cut

We can achieve most of the benefits with a short-cut. As always, evaluate the method based on your priorities. In this, a small (I chose 500MB) temporary file is created and then repeated written to the disk. It is much faster since the pseudo-random number generator only runs for a fraction of the time. The size of the temporary file (which is kept in RAM since this is the Live CD environment) is determined by the amount of system RAM. Here, the laptop has 2GB RAM so 500MB is reasonable:

SIZE=500000000
TOTAL=$( echo "1024 * $(fdisk -ul /dev/sda4 | sed -n ',^/dev/sda4 *[-09]* * [0-9]* *\([0-9]*\).*,\1,p')" | bc)
SEEK=0
dd if=/dev/urandom of=/tmp/urandom.dat bs=$SIZE count=1
while [ $TOTAL -gt 0 ]; do
 echo "Seek=$SEEK Total=$TOTAL"
 dd if=/tmp/urandom.dat of=/dev/sda4 bs=$SIZE count=1 seek=$SEEK
 SEEK=$((SEEK + 1))
 TOTAL=$((TOTAL - SIZE))
done
rm /tmp/urandom.dat

Choosing a Key-File

The key-file is kept on an external USB memory stick. There are various ways to create and store the key-file. Many guides recommend generating a random key from /dev/random but in my opinion anyone that managed to get access to the memory stick could easily locate the key-file because of its totally random contents, unless many 'fake' keys were also on the memory stick.

My preferred method now is to use a real file. Install the  Hardy Desktop Live image on the USB memory stick so it is bootable on any system. Because the installation has a persistent /home/ I can copy some music and image files onto it and use one of those as the key-file. The reason I choose music and images is that most MP3 and PNG or JPG files are highly compressed and their data can have a high degree of variability, and is hard to predict. An attacker would need to know the name of the key-file to determine which of the thousands of files was the key-file. To do that, they'd need access to the encrypted system itself.

For the purposes of this guide let us assume we're using a self-created music file called theme-song.mp3 (Being self-created no-one else will have the same file - in other words, don't use a commonly shared file).

Put the file on the USB memory stick and then plug it into the new system. Ensure it is mounted. In this example the USB key has two volumes on it (ubuntu & casper-rw) and the persistent files are in the casper-rw volume which usually is auto-mounted at /media/casper-rw (see  Installing Ubuntu on USB pendrive using Linux.

Encrypting the Disk

Now encrypt the large sda4 partition that will eventually use LVM:

cryptsetup --hash sha512 --key-size 256 --cipher aes-cbc-essiv:sha256 \
 luksFormat /dev/sda4 /media/casper-rw/home/tj/Media/theme-song.mp3

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

Are you sure (Type uppercase yes): YES
Command successful

Open the encrypted device, giving it the name sda4encrypted:

cryptsetup --key-file /media/casper-rw/home/tj/Media/theme-song.mp3 luksOpen /dev/sda4 sda4encrypted
key slot 0 unlocked.
Command successful.

There will now be a new device:

ls -1 /dev/mapper
control
sda4encrypted

Configure Logical Volume Management (LVM)

First install the LVM package:

apt-get install lvm2

LVM Tools Confuse Megabytes with Mebibytes

The LVM tool reports can be confusing because they use the wrong size suffixes (such as MB and GB). The problem is, a gigabyte (GB) is 1,000MB, a megabyte (MB) is 1,000 kilobytes, and a kilobyte (KB) is 1,000 bytes. However, LVM uses binary-based calculations, not the decimal, with KB = 1,024, MB = 1,024KB, and GB = 1,024MB. LVM should use  MiB and  GiB suffixes to indicate binary-based measurements.

The result is, if you use fdisk to create (for example) a 3,256MB partition (3.256 x 1000 x 1000 x 1000 = 3256000000 bytes) on a physical device and then create an LVM physical volume with it, the reports from pvdisplay and vgdisplay will show the size as 3.04GB. (3.04 x 1024 x 1024 x 1024 = 3264175144.96). In fact, 3,256MB = 3.256GB = 3.032386303 GiB so the lvm tools have rounded-up to the next tenth.

It looks as if you've miscalculated or lost disk space somewhere, but in fact LVM tools are causing confusion.

Determine the Number and Size of Logical Extents in Logical Volumes

Logical volume size is defined as the number of logical extents (LE), the size of which is the same for all logical volumes in a volume group and is the same as the physical extent (PE) size. Use vgdisplay to find out:

vgdisplay VGraid5

  --- Volume group ---
  VG Name               VGraid5
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  4
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                3
  Open LV               3
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               163.39 GB
  PE Size               4.00 MB
  Total PE              41829
  Alloc PE / Size       33040 / 129.06 GB
  Free  PE / Size       8789 / 34.33 GB
  VG UUID               V0kRhd-oFLa-hq21-9eCs-kAnm-e1BW-xK7GPT

The PE Size (physical extent size) for this volume group is 4.00MB. The Total PE (number of extents) is 43,794.

So, in fact, the PE Size is 4.00MiB (4.00 x 1024 x 1024 = 4,194,304 bytes), or 4.194304MB (4.194304 x 1000 x 1000 = 4,194,304 bytes).

To make later calculations easier set up some definitions:

export GB=1000000000
export MB=1000000
export GiB=1073741824
export MiB=1048576

Encrypted Volume

Create the physical volume and volume group:

pvcreate /dev/mapper/sda4encrypted
  Physical volume "/dev/mapper/sda4encrypted" successfully created

vgcreate -v VGencrypted /dev/mapper/sda4encrypted
    Adding physical volume '/dev/mapper/sda4encrypted' to volume group 'VGencrypted'
    Creating directory "/etc/lvm/archive"
    Archiving volume group "VGencrypted" metadata (seqno 0).
    Creating directory "/etc/lvm/backup"
    Creating volume group backup "/etc/lvm/backup/VGencrypted" (seqno 1).
  Volume group "VGencrypted" successfully created

Create the logical volume 'root' using 15GB in the volume group 'VGencrypted':

export PES_BYTES=$(echo "$(vgdisplay VGencrypted | sed -n 's/.*PE Size *\([0-9\.]*\) .*/\1/p') * $MiB" | bc)
EXTENTS=$(echo "15 * $GB / $PES_BYTES" | bc); echo $EXTENTS
4291
lvcreate -l $EXTENTS -n root VGencrypted
  Logical volume "root" created

Repeat for /var/ (5GB) and /home/ (75% of remaining free space):

EXTENTS=$(echo "5 * $GB / $PES_BYTES" | bc); echo $EXTENTS
2384

lvcreate -l $EXTENTS -n var VGencrypted
  Logical volume "var" created

lvcreate -l 75%FREE -n home VGencrypted
  Logical volume "home" created

Using vgdisplay you can see this will leave ~34GB of free space. If or when one of the existing logical volumes reaches capacity simply use lvextend to allocate more extents from the volume group - no need to shuffle data or partitions around. I shall be using some of this space for the Ubuntu+1 testing file-system.

vgdisplay VGencrypted | grep 'Free  PE'
  Free  PE / Size       8789 / 34.33 GB

Check the devices are available:

ls -1 /dev/mapper
control
sda4encrypted
VGencrypted-home
VGencrypted-root
VGencrypted-var

Write Windows image

To ensure when Ubuntu installs it writes a suitable GRUB menu that provides for booting to Windows, copy the Windows image from the back-up and into its target partition. This assumes the remote system is still mounted:

dd if=/mnt/remote/Backups/sda2-Vista.img of=/dev/sda2

Check the image consistency:

ntfsresize --info --no-action /dev/sda2

ntfsresize v2.0.0 (libntfs 10:0:0)
Device name        : /dev/sda2
NTFS volume version: 3.1
Cluster size       : 4096 bytes
Current volume size: 29428277760 bytes (29429 MB)
Current device size: 29428285440 bytes (29429 MB)
Checking filesystem consistency ...
100.00 percent completed
Accounting clusters ...
Space in use       : 19489 MB (66.2%)
Collecting resizing constraints ...
You might resize at 19488083968 bytes or 19489 MB (freeing 9940 MB).
Please make a test run using both the -n and -s options before real resizing!

No errors or warnings during the consistency scan so the system is ready for Ubuntu.

Install Ubuntu

Now the system has all the devices ready for formatting with file-systems and Windows in place, so installation of the operating system can begin.

Configuring

Run the Ubuntu installer by double-clicking the Install icon on the Live CD desktop. Select the language, time-zone and keyboard layout.

In the partitioner (Prepare disk space dialog) choose Manual, then press the Forward button.

After it has scanned the disks it will present a list of devices. As well as the physical devices (/dev/sda, /dev/sdb, etc.) there will be the logical devices just created with names beginning /dev/mapper/. The choice of device names should make it straight-forward to identify the intended purpose of each.

Let's begin.

The device list will show all the devices in the system.

Select /dev/sda1. Press the Edit partition button. Change Use as to Ext3. Tick the Format check-box. Set the mount point to /boot.

Select /dev/sda3. Press the Edit partition button. Change Use as to swap area. .

Select /dev/mapper/VGencrypted-home. Press the New partition table button. Select the free space. Press the New partition button. Choose Primary partition, use all the space (accept the default value for partition size), location at Beginning. Use as Ext3. Set the mount point to /home.

Select /dev/mapper/VGencrypted-root. Press the New partition table button. Select the free space. Press the New partition button. Choose Primary partition, use all the space (accept the default value for partition size), location at Beginning. Use as Ext3. Set the mount point to / (root).

Select /dev/mapper/VGencrypted-var. Press the New partition table button. Select the free space. Press the New partition button. Choose Primary partition, use all the space (accept the default value for partition size), location at Beginning. Use as Ext3. Set the mount point to /var.

Review the list to ensure it is correct, then press the Forward button to commit the changes.

Continue the installation process, answering the Who are you? questions.

On the Ready to install page, review the choices.

Finally, when you're happy with all the choices, press the Install button and wait whilst the installer runs.

When it finishes DO NOT restart the system - some additional configuration is required before the system is restarted so it will boot successfully.

Post-Installation configuration

Now a series of additional steps is required to ensure the new system can successfully boot.

Mount the Target System

Prepare the installation for access using chroot:

mkdir /mnt/target
mount /dev/mapper/VGencrypted-root /mnt/target
mount /dev/mapper/VGencrypted-var /mnt/target/var
mount /dev/mapper/VGencrypted-home /mnt/target/home
mount /dev/sda1 /mnt/target/boot
mount -o bind /proc /mnt/target/proc
mount -o bind /dev /mnt/target/dev

Install cryptsetup and lvm2

The installer didn't install the packages needed for the system to understand the disk configuration, so install them manually:

chroot /mnt/target /bin/bash -c "apt-get install cryptsetup lvm2"

Encrypted Disk Configuration

Write the configuration of /dev/mapper/sda4encrypted so the system knows how to open it. It will use a shell script that is executed early in the boot process from the initrd image:

echo "sda4encrypted /dev/disk/by-uuid/$(vol_id --uuid /dev/sda4) /home/tj/Media/theme-song.mp3 luks,keyscript=/usr/local/sbin/crypto-usb-key.sh" >> /mnt/target/etc/crypttab

There are several suitable shell scripts already existing. I chose to modify one written by Wejn and Rodolfo Garcia published at  How to setup passwordless disk encryption in Debian Etch. It is attached to my article on encrypted RAID-5 LVM ready for downloading.

My modifications enable the script to report progress via usplash or console, detect USB block devices, scan all partitions on the device (the original script only checked the first partition), auto-detect and load the file-system type driver, and output more informative messages.

Copy it into the new system (ensure the path and name match that specified in /mnt/target/etc/crypttab):

wget http://tjworld.net/raw-attachment/wiki/Linux/UbuntuHardyRAID5EncryptedLVM/crypto-usb-key.sh \
 -O /mnt/target/usr/local/sbin/crypto-usb-key.sh
chroot /mnt/target /bin/bash -c "chmod a+x /usr/local/sbin/crypto-usb-key.sh"

Update Initial RAM Disk (initrd)

chroot /mnt/target /bin/bash -c "update-initramfs -u all"
update-initramfs: Generating /boot/initrd.img-2.6.24-19-generic

Restart System and Test

With everything written to the disks it is time to restart:

shutdown -r now

Remove the installation CD from the drive when prompted.

When the system starts ensure the BIOS isn't configured to try booting from a USB device before the hard disk.

Insert the stick into a USB port and let the system start.

If using usplash you should see a message similar to "Success loading key-file from sdb1 (casper-rw)" early in the boot process when crypto-usb-key.sh locates the key-file. If it fails you'll see "FAILED to find suitable USB key-file ..." followed by "Try to enter the LUKS password:". At this point, if the device has a pass-phrase as well as a key-file you can type it instead of using the key-file.

Debugging crypt-usb-key.sh

If that fails you'll need to enable debugging within the script by changing:

DEBUG=$FALSE

to

DEBUG=$TRUE

To do this the initial RAM disk image needs updating. That means the encrypted volume must be opened and mounted and the chroot environment recreated from the Live CD.

Because that involves a lot of steps I put all the commands into a script. The script is attached to this article as update-liveCD-encryptedLVM.sh. It will install the packages, configure and unlock the devices, recreate the chroot environment, download and install the latest version of crypto-usb-key.sh, then update the initial RAM disk image.

Restart the system using the Live CD and open a terminal, then:

sudo su
wget http://tjworld.net/raw-attachment/wiki/Linux/Ubuntu/HardyEncryptedLVM/update-liveCD-encryptedLVM.sh
chmod a+x update-liveCD-encryptedLVM.sh

The script requires the key-file name be assigned to the environmental variable KEYFILE:

KEYFILE="/home/tj/Media/theme-song.mp3"
./update-liveCD-encryptedLVM.sh

Now make the changes and update the initial RAM disk image:

sed -i 's/^\(DEBUG=\)$FALSE/\1$TRUE/' /mnt/target/usr/local/sbin/update-usb-key.sh
update-initramfs -u all

You might also want to remove the "splash" option from the kernel command-line in the GRUB configuration (either in the file /boot/grub/menu.lst or by pressing Escape when GRUB is starting after a reboot to edit the menu directly). This will ensure that the large number of debug messages from the script are easily readable on the console, rather than scrolling up too fast in usplash.

Now the system can be restarted and hopefully the messages will help identify the cause of the problem, and suggest a solution.

Once the problem is fixed don't forget to change the debug setting back to $FALSE and update the initial RAM disk image.

References

 Installing Ubuntu on USB pendrive using Linux
 Ubuntu hard drive encryption with external key
 Installing Ubuntu 7.04 on an Encrypted LVM Partition For Root, Swap, and Home
 How to setup passwordless disk encryption in Debian Etch
 Encrypted Storage with LUKS, RAID and LVM2

Attachments