After many headaches, I've upgraded my system to lfs-7.1, so here's the new 
crypt-rootfs hint in diff -aur and as the new version.

Lars

Attachment: crypt-rootfs.diff
Description: Binary data

AUTHOR: Lars Bamberger <Lars.Bamberger at gmx dot de>

DATE: 2012-05-15

LICENSE: GNU Free Documentation License Version 1.2

SYNOPSIS: How to setup an encrypted file system including the rootfs.

DESCRIPTION:
This describes one possible way of encrypting your hard drive, including the
root file system. It is intended for experienced users and tries to
circumnavigate the pitfalls of encrypting your root file system in a
straightforward way.

PREREQUISITES:
This hint requires that you have sufficient knowledge of BeyondLinuxFromScratch
and reasonably up to date software. You must be comfortable building software,
finding, reading and understanding other pertinent documentation.
You must know how to set up an initramfs. (See
'filesystems/ramfs-rootfs-initramfs.txt' in the kernel's documentation.)
You must be aware why you'd want an encrypted file system and you must
understand the nature of the threat you're trying to protect yourself against.
You must also understand shortcomings and security issues if you follow the
instructions contained in this hint.

You must have a complete backup of you system somewhere safe! That includes an
alternative boot device.

You ABSOLUTELY MUST READ AND UNDERSTAND THIS HINT BEFORE YOU MODIFY YOUR SYSTEM!


HINT:

1. What is this about?
======================

This is about encrypting all but one of your hard drive partitions using LUKS
for dm-crypt. We'll boot from one small unencrypted partition using initramfs in
order to decrypt the rootfs.
This hint assumes that a small partition from where to boot from is already set
up. This partition should be 10 to 15 MB in size in order to store more than
one kernel and more than one initramfs image for testing and upgrading
purposes. Avoid any larger partition because during every boot we'll calculate
a checksum for this partition, a time consuming process.


2. Required software and dependencies
=====================================

2.1 Software in the BLFS book (BLFS-svn as of date of writing)

To satisfy dependencies of 'cryptsetup', you need to install
* 'Popt'
* 'lvm2'
* 'libgcrypt' (has futher dependencies mentioned in the book)

Furthermore, you need 'uuencode' to create key files. 'uuencode' is included in
'sharutils' and in 'GMime' which has further dependencies mentioned in the BLFS
book.
To create the initramfs, you need 'Cpio'. 

2.2 Software not in the BLFS book

2.2.1 cryptsetup with LUKS extension

Get it from http://code.google.com/p/cryptsetup/
Compile and install it. (CMMI-Standard) Required to handle encrypted partitions.

2.2.2 busybox

Get it from http://www.busybox.net/

The configuration system is quite similar to that of the Linux kernel.
First, we build a minimalistic version of busybox:
Do 'make allnoconfig' followed by 'make menuconfig' (or 'make config' if
that doesn't work). Configure as follows:

Busybox Settings -> Build Options -> Build as a static binary
Coreutils -> cp
Linux System Utilities -> mount with support for lots of -o flags
Linux System Utilities -> switch_root
Shells -> hush (interactive mode not required)

Compile it, but DO NOT install it. Keep the binary and name it
'busybox-minimum'. Next, reconfigure busybox for a full-blown desktop system.
You will need all the standard tools and utilities for the purpose of initially
encrypting your root partition and for troubleshooting. (Don't forget 'mkefs'.) 
Doing a 'make defconfig' should do the trick. Using 'make menuconfig', you can 
safely disable all Networking, Print, and Mail Utiliies as some of these have 
dependencies and are not needed for your purpose. If busybox complains about 
missing dependencies, check if you really need the feature and disable it. 
Configure busybox to compile as a static binary (Build Options). If some libs 
will be linked to it anyway, use 'ldd busybox' to find out which ones those are 
and note the names of those libs. If possible, avoid generating a dynamically 
linked busybox. This behavoiur may vary with the version of busybox used, as 
this is a generic description.
Name this binary 'busybox-large' or something similar. Again, it is not
required to install it


3. Recompiling the kernel
=========================

Decide what algorithm you would like to use to encrypt your hard drive
with. Note that this is a crucial decision and you should read more background
information on this. (See ACKNOWLEDGMENTS below.)
The appropriate modules need to be compiled (hard-coded, not as modules) into
the kernel.
As an example you could use the "twofish-cbc-essiv:sha256" method.

Also, from the 'Device Drivers' -> 'Multiple devices driver support' menu in
the kernel configuration, select the 'Device mapper support' and the 'Crypt
target support' as well.

Under 'Device Drivers' -> 'Block devices', select 'RAM block device support'
and from 'General setup', select 'Initial RAM filesystem and RAM disk'.

NOTE: You must boot this new kernel before proceeding.


4. Encrypting partitions partitions other than rootfs and other than swap
=========================================================================

You need to modify your system in order for it to be able to handle encrypted
partitions. In the first step, we modify the system so that it can handle
encrypted partitions OTHER than the rootfs. It is strongly suggested that you
keep a backup of all files you modify in the process.

4.1 Encrypting the partitions

NOTE: This document describes how to encrypt every partition separately. If you
      have more than one HDD in your system, you might consider encrypting the
      whole device including the partition table. Using the method described in
      this document leaves the partition table unencrypted and thus may be
      exposed to an attack. Consider this a potential security risk.

*** PITFALL ***
If /usr is a separate partition, cryptsetup and all libraries needed to run
cryptsetup must be on the root partition. Use 'ldd cryptsetup' to find out.
It may be necessary to switch to runlevel 1 because you need to be able to
unmount /usr. Also, make sure that root's shell does not use any libs on that
partition. If required, compile a statically linked shell for root's use.

The process is as follows for every partition:

1) Create as many passphrases as you like for the partition, for example:
   head -c 2880 /dev/urandom | uuencode -m - | head -n-1 | tail -n+2 > keyfile
   or use an easy to remember passphrase.

2) Make a secure backup of your passphrases and secure the keyfile by
   'chmod 0400' or so. Your backup passphrases must be absolutely secure (i.e.
   not on your computer).
   Remember: If you lose your passphrase, you will absolutely, definitely NOT
   be able to access your data!

3) Make a backup of the data on the partition.

4) Un-mount the partition.

5) Create an encrypted partition. (All data will be lost on that partition.)
   Do a
   cryptsetup -c $cipher-algorithm luksFormat /dev/sd?? $keyfile
   Replace '$cipher-algorithm', '/dev/sd??' and '$keyfile' with the
   corresponding values.
   
6) Optionally, add more passphrases to the partition. Do a
   cryptsetup -y -d $keyfile luksAddKey /dev/sd??
   Replace '$keyfile' with the same as above and '/dev/sd??' with the
   corresponding partition.

7) Open the encrypted partition. Do a
   cryptsetup -d $keyfile luksOpen /dev/sd?? sd??
   Replace '$keyfile' and '/dev/sd??' with the corresponding values. Replace
   'sd??' with a meaningful name. If everything worked out, the unencrypted
   partition will appear as '/dev/mapper/sd??' with sd?? being the name you
   chose.

8) Create a filesystem on the partition. Do a
   mkefs.$WHATEVER /dev/mapper/sd??
   Replace '$WHATEVER' with the type of filesystem you would like to use
   (e.g. ext2) and '/dev/mapper/sd??' with the corresponding partition.
   NOTE: Do NOT use the -cc option. The system will hang forever!

9) Adjust /etc/fstab
   Because the device for the partition has changed, you need to
   tell the system where to find it. Change the device by inserting
   "mapper/" in the device field.

   Example:
   /dev/sda4         /home ext2 defaults 1 2
   becomes
   /dev/mapper/sda4  /home ext2 defaults 1 2

10) Mount the filesystem by 'mount /dev/mapper/sd??'
    
11) Copy the data back to the partition.


4.2 Making the system automatically decrypt and mount the partition(s)

Create a bootscript that will decrypt your encrypted partition. It is assumed
that the passphrases are stored in /etc/crypt for example. Note that storing
the passphrases on disk might pose a security problem! Use the template for
bootscripts included with LFS and make it do:

(/usr)/sbin/cryptsetup -d /etc/crypt/$PARTITION.key luksOpen \
   /dev/$PARTITION $PARTITION

for every encrypted partition other than the root partition and the swap
partition(s).

Example:

#!/bin/sh
########################################################################
# Begin cryptsetup
#
# Description : Make encrypted filesystems available for mounting
#               And clean up afterwards
#
# Authors     : Lars Bamberger
#
# Version     : 00.01
#
# Notes       : This should never be automatically called with any
#               argument other than "start". During shutdown and reboot,
#               it is sufficient to umount the filesystems.
#               /dev/mapper/*
#               will be gone when the kernel stops or reboots.
#
########################################################################

### BEGIN INIT INFO
# Provides:            cryptsetup
# Required-Start:      udev
# Should-Start:
# Required-Stop:
# Should-Stop:
# Default-Start:       S
# Default-Stop:
# Short-Description:   Make encrypted filesystems available for mounting
# Description:         Make encrypted filesystems available for mounting
# X-LFS-Provided-By:
### END INIT INFO

. /lib/lsb/init-functions
PROC=/sbin/cryptsetup

case "${1}" in
   start)
        log_info_msg "luksOpen sdb3"
        $PROC -d /etc/crypt/sdb3.key luksOpen /dev/sdb3 sdb3
        evaluate_retval
      ;;

   stop)
        log_info_msg "luksClose sdb3"
        $PROC luksClose sdb3
        evaluate_retval
      ;;

   restart)
      ${0} stop
      sleep 1
      ${0} start
      ;;

   status)
        $PROC status sdb3
        ;;
   *)
      echo "Usage: ${0} {start|stop|restart|status}"
      exit 1
      ;;
esac

exit 0

# End cryptsetup

Now, before proceeding, make sure everything works as expected up until now.
Become familiar with encrypting your partitions this way.
Make an appropriate softlink so that this script is called at boottime:

# cd /etc/rc.d/rcS.d
# ln -s ../init.d/cryptsetup S19cryptsetup

Double-check everything so that booting, rebooting, shutting down etc. works as
expected. You may find that the 'checkfs' and 'mountfs' bootscripts check for an
installation of LVM. Since this was installed as cryptsetup needs libdevmapper,
and if your system does NOT use LVM for any other purpose than encrypting your
filesystem, you may choose to comment out the respective parts in those
bootscripts.

5. A word about encrypting the swap partition(s)
================================================

Do not omit encrypting your swap partitions. Lot's of interesting data can be
found on swap spaces. Do not consider you data safe if you don't use encrypted
swap spaces. 
In theory, the data on the swap partition(s) does not need to be consistent
between reboots. This means we could create a swap space anew during boottime,
using a random (and thus different) cryptokey every time the system boots. This
way you don't have to bother with managing swap's cryptokeys and you won't have
to store them anywhere (except in memory). This can be considered an additional
security feature.
However, if you suspend your system (either to RAM or to disk), data in
swap space must remain consistent. Therefore you have to treat the swap
partition(s) just as if they were a regular partition, meaning you should
encrypt them like explained above. Note that I have not experimented with
system hiberantion or supension. If you have anything to contribute toward
encrypting swap partiations, feel free to contact me.


6. Encrypting rootfs (This is where the fun starts)
====================

You can't just encrypt the rootfs the way the other partitions were encrypted
because the system is running on it. The idea is to create an initramfs
containing everything you need to encrypt (and decrypt) the rootfs. (Details can
be found in the kernel's documentation:
'filesystems/ramfs-rootfs-initramfs.txt'.)

You'll need the standard directories (bin, sbin, usr/{bin,sbin}, proc, sys,
dev, lib). In bin we put our busybox-large (rename to busybox) and a softlink to
busybox named hush. Copy cryptsetup to sbin.
In dev put some useful devices: console, null, random, urandom, sd?? and a
directory 'mapper' containing 'control'.
In lib (and dev) put everything needed to run busybox and cryptsetup.

The init script is like this:
#!/bin/hush
/bin/busybox mount -t proc proc /proc
/bin/busybox mount -t sysfs sysfs /sys
/bin/busybox mount -t devtmpfs devtmpfs /dev
/bin/busybox --install -s
exec /bin/busybox hush

Put all this into one directory (init goes there as well and not into sbin). Cd
into this directory and create the image using
find . | cpio --quiet -H newc -o | gzip -9 -n > /boot/initramfs.img
Pass the appropriate initrd argument (e.g. initrd (hd0,0)/initramfs.img) to the
kernel when booting and this will drop you into the hush shell after system
boot.

*** PITFALL ***
Cryptsetup needs /proc and /sys mounted. It also requires the /dev directory and
'random' and 'urandom'. Be aware that you need at least 'null' and 'console' in
/dev before mounting tmpfs on /dev.

Once in the shell, encrypt your rootfs like any other partition as described
above. Don't forget the backup! ABSOLUTELY, POSITIVELY make certain that you are
able to mount and access the unencrypted backup of the rootfs from within the
hush shell!

Next, create the encrypted root partition. Note that the passphrase won't be
stored anywhere on disk, so do:
cryptsetup -y -c $cipher-algorithm luksFormat /dev/sd??
to create the encrypted rootfs. Replace '$cipher-algorithm' and '/dev/sd??' with
the respective values. Next, open the partition, format it and recover the
backup:

cryptsetup luksOpen /dev/sd?? sd??
$BACKUPROOTFS/mkefs.$TYPE /dev/mapper/sd??
mkdir /new-root
mount -t $FSTYPE /dev/mapper/sd?? /new-root
cp -a $BACKUPROOTFS /new-root

*** PITFALL ***
Since your old rootfs isn't mounted, you might not be able to to run 'mkefs' do
to missing libraries. Either copy everything needed to where the linker can
find it, reconfigure the linker's search path via 'ldconfig', or use the 'mkefs'
from busybox. Be sure to configure busybox accordingly.

Next, modify /etc/fstab (on /new-root) to reflect the new device for the rootfs.
Also modify the cryptsetup script as described below (7. PITFALL).


7. Decrypting the rootfs on subsequent boots
============================================

Like in 6., create an initramfs. The difference is that now the
"busybox-minimum" binary is used and you'll need an additional directory
new-root. Don't forget the 'hush' softlink.
The init is like this: (Replace 'sd??' with your root-device and adjust for the
fstype.)

#!/bin/hush
/bin/busybox mount -t proc proc /proc
/bin/busybox mount -t sysfs sysfs /sys
/bin/busybox mount -t tmpfs tmpfs /dev
/sbin/cryptsetup luksOpen /dev/sd?? sd??
/bin/busybox mount -r -t ext2 /dev/mapper/sd?? /new-root
/bin/busybox mount --move /proc /new-root/proc
/bin/busybox mount --move /sys /new-root/sys
/bin/busybox mount --move /dev /new-root/dev 
exec /bin/busybox switch_root /new-root /sbin/init $@

*** PITFALL ***
You want to keep /proc, /sys and /dev after switch_root because cryptsetup uses
them. Hence the 'mount --move' commands.

8. Making sure security is not compromised
==========================================

Once everything works as it should, remove the unencrypted backup of your
rootfs. Protect your bootloader (and possibly the BIOS) with a password to
disable unauthorized fiddling with the boot parameters.
Create a bootscript (checkbootfs) that makes sure that the unencrypted partition
we booted from was not compromised. Use something like:

        log_info_mesg "Checking integrity of boot FS..."
                if
                [[ $(/bin/md5sum -b /dev/sd??) == \
                "$whatevermd5sum */dev/sd??" ]] \
                        && \
                [[ $(/bin/sha1sum -b /dev/sd??) == \
                "$whatevensha1sum */dev/sd??" ]];
        then
        log_success_msg;
        else
        log_failure_msg "The boot file system has been altered!"
        log_warning_msg "DO NOT TRUST THIS SYSTEM!"
        log_info_msg "Press Enter to continue anyway ..."
        wait_for_user
        fi

*** PITFALL ***
Make sure this is the very last thing you implement, as the hashsums will
change as we go on. The hashsums will also change if you run a fsck on the boot
partition. Also, you will need to move 'md5sum' and 'sha1sum' from /usr/bin to
/bin, if /usr is a separate partition.


ACKNOWLEDGMENTS:
  * Emmanuel Trillaud for some suggestions and pointers.
  * Various for the Gentoo-Wiki at
    http://en.gentoo-wiki.com/wiki/DM-Crypt_with_LUKS
  * Clemens Fruhwirth (http://clemens.endorphin.org/) for LUKS for dm-crypt:
    http://code.google.com/p/cryptsetup


CHANGELOG:
[2012-05-15]
  * Adjust for LFS-7.1
[2011-11-13]
  * Adjust for LFS-7.0
  * Some touchups
[2010-04-17]
  * Dev-mapper is now in the BLFS book
  * More verbosity for configuring busybox
[2009-12-30]
  * Merged suggestions (typos, format and others) from Emmanuel Trillaud
  * More verbosity on the boot partition size
  * Some reformatting
[2009-11-23]
  * list dependencies in the BLFS book
[2009-11-20]
  * cryptsetup needs /dev/urandom
  * mkefs might not work from initramfs
  * update some URLs
  * some minor touchups
[2009-02-15]
  * Basic rewrite.
[2008-02-17]
  * Initial hint.

-- 
http://linuxfromscratch.org/mailman/listinfo/hints
FAQ: http://www.linuxfromscratch.org/faq/
Unsubscribe: See the above information page

Reply via email to