Hint update cryptrootfs part 1

Lars Bamberger maillist at herr-der-mails.de
Sat Apr 13 08:06:12 PDT 2013


This is a resubmit as the list moderator has obviously not reviewed my
submission dated 9 April 13. It is being held because of its size, so
I'm braking it into two parts.

Original message:

I have updated my hint on how to encrypt the file system on an (B)LFS
machine. Major changes include an adjustment to LFS 7.2 (I know the
latest version is LFS-7.3, but I just can't keep up with the spare time
I have.)
Also, the scripts have been removed from the hint and into attachments.
The locations of the attachments need to be changed in the hint.

Please find attached the hint and all attachments.

Cheers,
Lars
-------------- next part --------------
#!/bin/sh
########################################################################
# Begin checkbootfs
#
# Description : Calculates checksums of the boot partition to detect changes
#
# Authors     : Lars Bamberger
#
# Version     : LFS 7.2
#
# Notes       : The MD5 algorithm has been broken, so we will calculate
#               two checksums.
#
########################################################################

### BEGIN INIT INFO
# Provides:            checkbootfs
# Required-Start:      S
# Should-Start:
# Required-Stop:
# Should-Stop:
# Default-Start:
# Default-Stop:
# Short-Description:
# Description:
# X-LFS-Provided-By:
### END INIT INFO

. /lib/lsb/init-functions

case "${1}" in
   start)
	log_info_msg "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
	;;
	*)
	echo "Usage: ${0} {start}"
      exit 1
      ;;
esac


exit 0

# End checkbootfs
-------------- next part --------------
AUTHOR: Lars Bamberger <Lars.Bamberger at gmx dot de>

DATE: 2013-04-09

LICENSE: GNU Free Documentation License Version 1.2

SYNOPSIS: How to setup an encrypted file system from within a LFS installation.

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.

ATTACHMENTS:
* http://www.linuxfromscratch.org/hints/downloads/files/{...}/busybox-1.21.0-minimal.config
* http://www.linuxfromscratch.org/hints/downloads/files/{...}/busybox-1.21.0-large.config
* http://www.linuxfromscratch.org/hints/downloads/files/{...}/cryptsetup
* http://www.linuxfromscratch.org/hints/downloads/files/{...}/checkbootfs

PREREQUISITES:
This hint requires that you have sufficient knowledge of (Beyond) Linux From
Scratch 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, accessible backup of you system somewhere safe! That
includes an alternative method of booting in case your system becomes
unbootable. 

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,
decrypt the original root file system, switch the root file system to that and
continue booting the (B)LFS system in a normal way.
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
checksums for this partition, a time consuming process.


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

2.1 A LFS installation

The author's system is a 64 bit-only lfs-7.2 release built on a x86_64 machine.
Any other LFS version should also work, as this hint aims to be generic.

2.2 Software in the BLFS book

The author's system is built on BLFS version 2012-11-02 (this was a major
milestone) but you should be good to go with any recent version of BLFS.

To satisfy dependencies of cryptsetup, you need to install Popt, LVM2, and
libgcrypt. The LVM2 instructions contain a section about reconfiguring the
kernel. You may choose to recompile the kernel later when this hints gets to
that point, but note that some tests may fail if you decide to do so. Libgcrypt
has further dependencies mentioned in the book.

You will need uuencode to create key files. Uuencode is included in sharutils.

Finally, to create the initramfs, you need cpio. 


2.3 Software not in the BLFS book

2.3.1 Cryptsetup with LUKS extension

Get it from http://code.google.com/p/cryptsetup/
Compile and install it using the CMMI-standard. This is required to handle
encrypted partitions and is the heart of this hint. At the time of writing,
cryptsetup-1.6.1 was the current version.

2.2.2 busybox

Get it from http://www.busybox.net/ At the time of writing, busybox-1.21.0 was
the latest (unstable) version.

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 -> Support for lots of -o flags in mount
* Linux System Utilities -> switch_root
* Shells -> hush (interactive mode and other options are not required)

The configuration file can be found in the attachments.
(busybox-1.21.0-minimal.config)

Compile it, but DO NOT install it. Keep the binary and name it busybox-minimal.
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 mkfs and friends.)
Doing a 'make defconfig' should do the trick. Using 'make menuconfig', you can
safely disable all Print and Mail Utilities, as some of these have extra
dependencies and are not needed for your purpose. Unless you want to recover
your backup over the network (which is not explained in this hint), you can
also disable all the Networking Utilities. If busybox complains about missing
dependencies, check if you really need the feature and disable it. Configure
busybox to compile as a static binary in Busybox Settings -> Build Options. Use
'ldd busybox' to find out if any libraries are linked to the busybox binary
anyway and note the names of those libraries. If possible, avoid generating a
dynamically linked busybox. This may vary with the version of busybox used, as
this is a generic description.
The configuration file can be found in the attachments.
(busybox-1.21.0-large.config)
Name this binary busybox-large. 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 cryptographic options and also all options mentioned below need
to be hard-coded (not compiled as modules) into the kernel. 
As an example you could use the "twofish-cbc-essiv:sha256" method. You can find
the appropriate options in the 'Cryptographic API' section of the kernel
configuration.

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. See also the instructions for installing LVM2 in the
BLFS book.

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 root file system and other than the swap
partition. 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 using a
      different method of 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
which libraries are required to run cryptsetup. Also, it may be necessary to
switch to runlevel 1 because you need to be able to unmount /usr. Make sure
that root's shell does not use any libraries 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
   mkfs.$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 and possibly delete the unencrypted
    backup of your data.


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). Find an example in the attachements. (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

If you feel like keeping your system tidy, you can also add symlinks to call
this script at system shutdown and/or reboot.

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 hibernation or suspension. If you have anything to contribute toward
encrypting swap partitions, 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'.)

We will create two initramfs', one that will drop us into an interactive shell
with basic system tools that will allow us to encrypt the rootfs and serve as a
means of system rescue if things should go wrong. The other one will execute a
non-interactive script, decrypt the rootfs and continue the system boot
sequence for a normal system start.

6.1 Creating an initramfs for an interactive shell

Create a working directory who's contents will become the initrams. In this
directory, create the standard directories (bin, sbin, usr/{bin,sbin}, proc,
sys, dev, and lib). If you have a 64-bit system, create a symlink named lib64
that points to lib. Copy and rename the busybox-large binary to bin/busybox and
add a softlink to busybox named hush. Copy the cryptsetup binary to sbin.
In dev, create the following devices usin mknod: console, null, random,
urandom. Also, create a directory 'mapper' containing 'control' and devices for
your harddrive and all partitions. (Example: sda, sda{1,...,6}). Check your
/dev directory for the device types and major and minor numbers. There's also
documentation on linux devices in the kernel's documentation directory. Use ldd
to check and make sure that everything needed to run busybox and cryptsetup can
be found in the lib directory in your working directory.

Next, create an executable 'init' script in the working directory:
#!/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

From within the working directory, create the image using
find . | cpio --quiet -H newc -o | gzip -9 -n > /boot/initramfs-interactive.img
Pass the appropriate initrd argument (e.g. initrd
(hd0,0)/initramfs-interactive.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.


6.2 Encrypting the rootfs proper

Once in the shell, encrypt your rootfs like any other partition as described
above following the steps below. Don't forget the backup! ABSOLUTELY,
POSITIVELY make certain that you are able to access the backup of the rootfs
from within the hush shell BEFORE you destroy the data on the original root
file system!

Create the encrypted root partition using
cryptsetup -y -c $cipher-algorithm luksFormat /dev/sd??
Replace '$cipher-algorithm' and '/dev/sd??' with the respective values. Note
that the passphrase won't be stored anywhere on disk. YOU will have to remember
your passphrase which you will be required to enter on every boot.
Next, open the partition, format it creating a file system type of you choosing
and recover the backup:

cryptsetup luksOpen /dev/sd?? sd??
mkfs.$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 'mkfs' 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 'mkfs'
from busybox. Be sure to configure busybox accordingly.

Next, modify etc/fstab (on /new-root) to reflect the new device for the rootfs.


6.1 Creating an initramfs in order to decrypt the rootfs on subsequent boots

Now we creat another initramfs, just like the one we created before. The
difference is that now the 'busybox-minimal' binary is used (rename to busybox)
and that we'll need an additional directory 'new-root'. Don't forget the 'hush' softlink.
The 'init' script is also different: (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 $FSTYPE /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.

Configure your bootloader to boot using this initramfs. You will be asked to
enter the passphrase for your root partition after which it is mounted and the
normal boot process continues.

7. 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. See ATTACHMENTS for an example. Create an
appropriate link from /etc/rc.d/rcS.d to this script.

*** 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. If /usr is not a separate partition,
modify the script to reflect the location of the programs.


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


CHANGELOG:
[2008-02-17]
  * Initial hint.
[2009-02-15]
  * Basic rewrite.
[2009-11-20]
  * cryptsetup needs /dev/urandom
  * mkefs might not work from initramfs
  * update some URLs
  * some minor touchups
[2009-11-23]
  * list dependencies in the BLFS book
[2009-12-30]
  * Merged suggestions (typos, format and others) from Emmanuel Trillaud
  * More verbosity on the boot partition size
  * Some reformatting
[2010-04-17]
  * Dev-mapper is now in the BLFS book
  * More verbosity for configuring busybox
[2011-11-13]
  * Adjust for LFS-7.0
  * Some touchups
[2012-05-15]
  * Adjust for LFS-7.1
[2013-04-09]
  * Adust for LFS-7.2 and BLFS version 2012-11-02
  * Moved scripts to ATTACHMENTS
  * Reformatting to conform more to the hint template
  * Reworked the text to contain more verbosity
-------------- next part --------------
#!/bin/sh
########################################################################
# Begin cryptsetup
#
# Description : Make encrypted filesystems available for mounting
#               And clean up afterwards
#
# Authors     : Lars Bamberger
#
# Version     : 00.01
#
# Notes       : You may get away with never calling this script 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


More information about the hints mailing list