# full disk encryption on Gentoo

## kaazoo

Hello all,

I wanted to have RAID1 storage on my 2 new Samsung 1TB harddrives along with full disk encryption (including swap).

Here is what I did:

1) basic partitions

- one mirrored boot partition and one mirrored partition for encrypted data

```

/dev/sda1   *           1          25      200781   fd  Linux raid autodetect

/dev/sda2              26      121601   976559220   fd  Linux raid autodetect

/dev/sdb1   *           1          25      200781   fd  Linux raid autodetect

/dev/sdb2              26      121601   976559220   fd  Linux raid autodetect

md1 : active raid1 sdb2[1] sda2[0]

      976559104 blocks [2/2] [UU]

      

md0 : active raid1 sdb1[1] sda1[0]

      200704 blocks [2/2] [UU]

```

2) encrypted MDRAID device

- LUKS device created with crypsetup

```

cryptsetup -y -c aes-xts-essiv:sha256 -s 256 luksFormat /dev/md1

cryptsetup status vol_disk

/dev/mapper/vol_disk is active:

  cipher:  aes-xts-essiv:sha256

  keysize: 256 bits

  device:  /dev/md1

  offset:  2056 sectors

  size:    1953116152 sectors

  mode:    read/write

```

3) LVM on top

- encrypted LUKS partition formatted as physical LVM volume

```

  PV /dev/dm-0   VG vg0   lvm2 [931,32 GB / 0    free]

  Total: 1 [931,32 GB] / in use: 1 [931,32 GB] / in no VG: 0 [0   ]

  Reading all physical volumes.  This may take a while...

  Found volume group "vg0" using metadata type lvm2

  ACTIVE            '/dev/vg0/vol_swap' [8,00 GB] inherit

  ACTIVE            '/dev/vg0/vol_root' [923,32 GB] inherit

```

Of course, I had some problems getting my system to boot properly. I've found an interesting article from IBM (http://www.ibm.com/developerworks/linux/library/l-initrd.html) from which I got a script for generating an initrd without using Gentoo's genkernel.

Here is my modified version which includes cryptsetup and LVM:

```

#!/bin/bash

# Housekeeping...

rm -f /tmp/ramdisk.img

rm -f /tmp/ramdisk.img.gz

rm -rf /mnt/initrd/*

# Ramdisk Constants

RDSIZE=8000

BLKSIZE=1024

# Create an empty ramdisk image

dd if=/dev/zero of=/tmp/ramdisk.img bs=$BLKSIZE count=$RDSIZE

# Make it an ext2 mountable file system

/sbin/mke2fs -F -m 0 -b $BLKSIZE /tmp/ramdisk.img $RDSIZE

# Mount it so that we can populate

mount /tmp/ramdisk.img /mnt/initrd -t ext2 -o loop=/dev/loop0

# Populate the filesystem (subdirectories)

mkdir /mnt/initrd/bin

mkdir /mnt/initrd/sys

mkdir /mnt/initrd/dev

mkdir /mnt/initrd/proc

mkdir /mnt/initrd/etc

mkdir /mnt/initrd/newroot

# Grab busybox and create the symbolic links

pushd /mnt/initrd/bin

cp /bin/busybox .

ln -s busybox ash

ln -s busybox mount

ln -s busybox echo

ln -s busybox ls

ln -s busybox cat

ln -s busybox ps

ln -s busybox dmesg

ln -s busybox sysctl

ln -s busybox mknod

ln -s busybox switch_root

ln -s busybox pivot_root

ln -s busybox touch

ln -s busybox sleep

ln -s busybox chroot

ln -s busybox umount

# cryptsetup & lvm 

cp /sbin/cryptsetup .

cp /sbin/lvm .

ln -s lvm lvm.static

ln -s lvm lvchange

ln -s lvm lvconvert

ln -s lvm lvcreate

ln -s lvm lvdisplay

ln -s lvm lvextend

ln -s lvm lvmchange

ln -s lvm lvmdiskscan

ln -s lvm lvmdump

ln -s lvm lvmsadc

ln -s lvm lvmsar

ln -s lvm lvreduce

ln -s lvm lvremove

ln -s lvm lvrename

ln -s lvm lvresize

ln -s lvm lvs

ln -s lvm lvscan

ln -s lvm vgcfgbackup

ln -s lvm vgcfgrestore

ln -s lvm vgchange

ln -s lvm vgck

ln -s lvm vgconvert

ln -s lvm vgcreate

ln -s lvm vgdisplay

ln -s lvm vgexport

ln -s lvm vgimport

ln -s lvm vgmerge

ln -s lvm vgmknodes

ln -s lvm vgreduce

ln -s lvm vgremove

ln -s lvm vgrename

ln -s lvm vgs

ln -s lvm vgscan

ln -s lvm vgsplit

ln -s lvm pvchange

ln -s lvm pvck

ln -s lvm pvcreate

ln -s lvm pvdisplay

ln -s lvm pvmove

ln -s lvm pvremove

ln -s lvm pvresize

ln -s lvm pvs

ln -s lvm pvscan

popd

# Grab the necessary dev files

cp -a /dev/console /mnt/initrd/dev

cp -a /dev/ramdisk /mnt/initrd/dev

cp -a /dev/ram0 /mnt/initrd/dev

cp -a /dev/null /mnt/initrd/dev

cp -a /dev/tty1 /mnt/initrd/dev

cp -a /dev/tty2 /mnt/initrd/dev

# Equate sbin with bin

pushd /mnt/initrd

ln -s bin sbin

popd

# Create the init file

cat >> /mnt/initrd/linuxrc << EOF

#!/bin/ash

echo

echo "Simple initrd is active"

echo

touch /etc/mtab

mount -t proc /proc /proc

mount -t sysfs none /sys

# create mdraid devices

mknod /dev/md0 b 9 0

mknod /dev/md1 b 9 1

# open encrypted device

cryptsetup luksOpen /dev/md1 vol_disk

# populate lvm devices

echo

lvmdiskscan 

vgchange -ay 

# mount root fs

echo

mount -t ext3 /dev/mapper/vg0-vol_root /newroot -o noatime,ro 

umount /proc

umount /sys 

# pivot_root & chroot

echo

cd /newroot

pivot_root . initrd

exec chroot . /sbin/init

echo "init failed. starting rescue shell"

/bin/ash --login

EOF

chmod +x /mnt/initrd/linuxrc

ls -lhR /mnt/initrd

# Finish up...

umount /mnt/initrd

gzip -9 /tmp/ramdisk.img

cp /boot/ramdisk.img.gz /boot/ramdisk.img.gz_bak

cp /tmp/ramdisk.img.gz /boot/ramdisk.img.gz

```

Here is my GRUB config:

```

title  GentooLinux 

root (hd0,0)

kernel /vmlinux root=/dev/ram0 vga=0x31B video=vesafb:mtrr:3,ywrap init=/linuxrc rw

initrd /ramdisk.img.gz

```

LVM, Busybox and cryptsetup have to be compiled statically. This way you don't need any libc stuff in the initrd.

Suggestions? Questions?Last edited by kaazoo on Thu Nov 13, 2008 10:25 pm; edited 1 time in total

----------

## jkomar

How do you find it's working for you? Do you get good disk performance? Any quirks you've noticed so far?

I've been thinking about full disk encryption for my laptop since I carry financial data (my own as well as that of some clients), but I haven't taken the plunge yet.

Jason

----------

## Hu

Although it is not entirely trivial to prepare a laptop to be booted when / is encrypted, it can be done using existing documentation from the Wiki and a bit of experimentation.  I strongly recommend that any sensitive material be kept in an encrypted container, even if you do not encrypt the whole disk.  This avoids all the complexity associated with preparing an early userspace, and still offers reasonable security if the laptop is stolen while halted.  As a caution for anyone considering a laptop without encrypted swap, remember that keys for any open cryptographic containers are stored to disk during hibernation, and are therefore vulnerable if the hibernation image is not encrypted.

There will be some overhead associated with the encryption, but the difference is hard to notice with typical laptop workloads.

----------

## kaazoo

Here are some performance values (only read by hdparm):

This is not really a benchmark. Using bonnie++ or dd would have been better. But a least you can see that encryption hits performance a lot. But it's ok for me. Data security is more important to me.

1) single drive:

hdparm -tT /dev/sda

/dev/sda:

 Timing cached reads:   1302 MB in  2.00 seconds = 651.44 MB/sec

 Timing buffered disk reads:  346 MB in  3.02 seconds = 114.71 MB/sec

2) both RAID1 drives as MDRAID:

hdparm -tT /dev/md1

/dev/md1:

 Timing cached reads:   1538 MB in  2.00 seconds = 768.99 MB/sec

 Timing buffered disk reads:  278 MB in  3.01 seconds =  92.41 MB/sec

3) encrypted LUKS partition

hdparm -tT /dev/mapper/vol_disk 

/dev/mapper/vol_disk:

 Timing cached reads:   1710 MB in  2.00 seconds = 855.53 MB/sec

 Timing buffered disk reads:  210 MB in  3.00 seconds =  69.97 MB/sec

4) LVM on top

hdparm -tT /dev/mapper/vg0-vol_root 

/dev/mapper/vg0-vol_root:

 Timing cached reads:   1766 MB in  2.00 seconds = 883.55 MB/sec

 Timing buffered disk reads:  202 MB in  3.05 seconds =  66.28 MB/sec

----------

## kaazoo

OK. Now the same using dd (only read).

1) single drive:

dd if=/dev/sda of=/dev/null bs=1024M count=1

1+0 Datensätze ein

1+0 Datensätze aus

1073741824 Bytes (1,1 GB) kopiert, 9,31895 s, 115 MB/s

2) both RAID1 drives as MDRAID: 

dd if=/dev/md1 of=/dev/null bs=1024M count=1

1+0 Datensätze ein

1+0 Datensätze aus

1073741824 Bytes (1,1 GB) kopiert, 10,2185 s, 105 MB/s

3) encrypted LUKS partition:

dd if=/dev/mapper/vol_disk of=/dev/null bs=1024M count=1

1+0 Datensätze ein

1+0 Datensätze aus

1073741824 Bytes (1,1 GB) kopiert, 10,979 s, 97,8 MB/s

4) LVM on top:

dd if=/dev/mapper/vg0-vol_root of=/dev/null bs=1024M count=1

1+0 Datensätze ein

1+0 Datensätze aus

1073741824 Bytes (1,1 GB) kopiert, 17,7227 s, 60,6 MB/s

So, these values are a bit better, but similar.

By the way, if you have a lot of RAM (I have 4GB) Linux caches a lot of disk data, which speeds up things a lot when you read the same stuff over and over again:

#1:

dd if=/dev/mapper/vg0-vol_root of=/dev/null bs=1024M count=1

1+0 Datensätze ein

1+0 Datensätze aus

1073741824 Bytes (1,1 GB) kopiert, 17,7227 s, 60,6 MB/s

#2:

dd if=/dev/mapper/vg0-vol_root of=/dev/null bs=1024M count=1

1+0 Datensätze ein

1+0 Datensätze aus

1073741824 Bytes (1,1 GB) kopiert, 2,91969 s, 368 MB/s

#3:

dd if=/dev/mapper/vg0-vol_root of=/dev/null bs=1024M count=1

1+0 Datensätze ein

1+0 Datensätze aus

1073741824 Bytes (1,1 GB) kopiert, 1,77232 s, 606 MB/s

#4:

dd if=/dev/mapper/vg0-vol_root of=/dev/null bs=1024M count=1

1+0 Datensätze ein

1+0 Datensätze aus

1073741824 Bytes (1,1 GB) kopiert, 2,22368 s, 483 MB/s

#5: 

dd if=/dev/mapper/vg0-vol_root of=/dev/null bs=1024M count=1

1+0 Datensätze ein

1+0 Datensätze aus

1073741824 Bytes (1,1 GB) kopiert, 2,1235 s, 506 MB/s

----------

## kaazoo

Sorry for spamming my own thread  :Wink: 

Here are the values for writing to encrypted storage with dd.

1) creating ~1G testfile:

dd if=/dev/zero of=/testfile bs=1024M count=1

1+0 Datensätze ein

1+0 Datensätze aus

1073741824 Bytes (1,1 GB) kopiert, 9,86874 s, 109 MB/s

2) creating ~10G testfile:

dd if=/dev/zero of=/testfile bs=1024M count=10

10+0 Datensätze ein

10+0 Datensätze aus

10737418240 Bytes (11 GB) kopiert, 113,312 s, 94,8 MB/s

Strange, I always thought writing would be much slower than reading....

----------

## rev138

Thanks, kaazoo, this comes just in time. I'm getting a new laptop for work tomorrow and my employer requires that I use full disk encryption.

Could you please give a bit more detail on how you did the various steps?

Also, what "problems" did you encounter when using genkernel?

----------

## Gamma746

I've heard that the performance costs from LVM and RAID together are minimal if you have compatible chunk sizes and your LVM chunks are stipe aligned with your RAID chunks (Source: http://www.mail-archive.com/linux-raid@vger.kernel.org/msg10804.html) have you tried that and, if so, what kind of performance overhead was there?

----------

## kaazoo

@ rev138:

I inserted the command to create the encrypted volume in step 2 of my first post. You will find the rest in various howtos and wikis.

I have ne real problems with genkernel. I just want to understand things and try to do it myself. Genkernel produces a kernel with a lot of features I don't need.

@ Gamma746:

I haven't tried to align those chunk sizes. Now that my systems seems to work fine for me it's too late  :Wink: 

----------

## rev138

Thanks, kaazoo.

Just an FYI -- if you run genkernel with the '--menuconfig' option, you can customize your kernel any way you want and still get an initrd. If you aready configured your .config, you can use the '--no-clean' option to tell genkernel not to modify it.  :Smile: 

----------

## rev138

I got full disk encryption working just fine with genkernel. The important parts were:

+ Install device mapper, dm-crypt, aes, and sha256 as built-ins, rather than modules

+ Install 'cryptsetup'

+ Run genkernel with the '--luks' flag

+ Add 'crypt_root=/dev/path/to/device' to the kernel arguments in grub.

That's about it. Works fine  :Smile: 

----------

