![]() |
Table of contentsThe Goal of this howtoThe goal is to acquire a fully encrypted Debian system on the NSLU2 via LUKS. Usually we would have to type in a passphrase at boot time to decrypt the root partition, but because the NSLU2 doesn't seem to work with a USB keyboard out of the box, we'll have to search for another option, which might be
As I haven't been able to find any infos how to realize the first option, we go with the "key file on a stick" option. Some additional notes on the project:
Notes about this howto:
Requirements
The planThe (initial) idea
Problems
The new strategyUsually (on a desktop machine), we would use a live CD to create an encrypted root partition, decrypt it, install a base system on it and configure our bootloader to be able to later open the encrypted root partition. Unfortunately, we cannot use the Debian net-installer that way, because the NSLU2 has not enough RAM and it also doesn't come with cryptsetup (for LUKS support) out of the box. And because there's no trivial way to get a live CD to boot from the NSLU2 with an external CD drive, we'll first install an unencrypted Debian system (the usual way) to let it act as a live CD replacement. So the plan now looks like this:
One way to successPartition layoutHere's the suggested/used partition layout for the first part of this howto. We'll make a separate boot partition, because then it can be left unmounted when the system is running, thus preventing an attacker from examining your kernel and initramfs. sda6 will be used as the root partition for the life system, and will be deleted once the encrypted system is up and running. sda5 will later become the root partition of the encrypted system, so make a choice here how much space it might need. FYI, a base system (such as the one for sda6) will require 510-600MB of free space. Because sda6 will be deleted later, we'll leave the rest of our harddrive blank for the time being.
Here's a suggestion for the resulting partition layout after the root switch:
The provisional installationFirst of all we need a standard system. The best way is to just follow an existing howto, like this one: Choose an appropriate key fileWe now have a working unencrypted base system on sda6. Before we proceed, it's time to think about whether we'll use only a key file for the to-be-encrypted root partition, or additionally a passphrase in case the key file is lost (or has to be deleted). In my case, I've chosen an additional strong passphase for the root partition. As for the key file, many howtos do something like the following to generate a file of a few KB with random data: # head -c 2880 /dev/urandom | uuencode -m - | head -n 65 | tail -n 64 > root.key However, we can also be creative and use an existing file, like a small pictures or a document or whatever, so that even if the USB stick is compromised, the key file is hidden in maybe a bunch of other files and is not as suspicious as a file named root.key or a file filled with completely random data. Of course the security gain is not very high, because every file on the stick can be tried out as the key file by an attacker, and, last but not least, the file name of the key file will be written to the internal flash of the NSLU2 in clear text in the initramfs. But that's entirely your choice what to choose. To simplify the howto, I'll call the key file root.key, but you can (and maybe should) rename it to something else. Copy it to your USB stick and make a backup of it, preferably on another encrypted machine or medium. Create the encrypted root partitionNext, we shutdown the NSLU2 and attach the harddrive to our workstation. There are many encryption algorithms out there, most of which work with different key sizes (currently most between 128 and 256 bytes), and they use a hash function to store the hash of the passphrase on the partition. Considering the low-end performance of the NSLU2, you might want to use a small key size of 128 bytes, which is by-the-way also the default value for cryptsetup. In this tutorial, we'll use the AES algorithm in cbc-essiv mode with a key size of 256 and the sha256 hash algorithm. Note that the external harddrive device name might change on your system, because of the other attached disk(s). In my case, it's now located under /dev/sdb # cryptsetup luksFormat /dev/sdb5 -y --cipher aes-cbc-essiv:sha256 --key-size 256 WARNING! ======== This will overwrite data on /dev/sdb5 irrevocably. Are you sure? (Type uppercase yes): YES Enter LUKS passphrase: Verify passphrase: Command successful. # cryptsetup luksAddKey /dev/sdb5 root.key Enter any LUKS passphrase: key slot 0 unlocked. Command successful. We have now created our encrypted partition with a passphrase and a key file. BTW, you can look at the partition's info with this command: # cryptsetup luksDump /dev/sdb5 Now we open it, create an ext3 filesystem on it, and mount it. # cryptsetup luksOpen /dev/sdb5 root2 --key-file root.key key slot 1 unlocked. # mkfs.ext3 /dev/mapper/root2 # mount /dev/mapper/root2 /mnt/sdb5 Now we also mount the unencrypted base system, and copy the content to the other partition. But we take a detour and first copy everything to our workstation, and then on the encrypted partition. That way, the harddrive doesn't have to constantly switch between the two partitions, thus sparing the harddrive. Additionally we'll have a complete backup of the base system on our workstation. In my case, I prefer to use tar for this task: # mount /dev/sdb6 /mnt/sdb6 # cd /mnt/sdb6 # tar -cvjf /path/to/slug-root-backup.tar.bz2 ./ # tar -xvjf /path/to/slug-root-backup.tar.bz2 -C /mnt/sdb5 # umount /mnt/sdb5 # umount /mnt/sdb6 # crpytsetup luksClose root2 If you've chosen to use an extra boot partition, back it up, too: # mount /dev/sdb1 /mnt/sdb1 # cd /mnt/sdb1 # tar -cvjf /path/to/slug-boot-backup.tar.bz2 ./ # umount /mnt/sdb1 Now you can attach the external harddrive to your NSLU2 again. Save the flash imageTake this step seriously! If you forget it, you're almost guaranteed to spend another day of free time, because in case the switch to the encrypted root will fail, your NSLU2 won't give you a chance to reboot into the unencrypted system unless you reflash it with this flash image. Otherwise you'll have to install Debian via the net-installer again! So now boot into your NSLU2 again, and make a copy of your current flash image: # cat /dev/mtdblock* > image.bin And then get it from your workstation: # scp root@slug1:~/image.bin . root@slug1's password: image.bin 100% 8192KB 1.0MB/s 00:08 I've needed to reflash the NSLU2 a couple of dozen times to complete this howto! Mount the encrypted partitionNow we'll mount the encrypted partition and chroot into it. That means we change the root directory in which we (and every of our executed commands) operate. Therefore we need to mount a couple of directories, e.g. dev, proc and sys. We also mount the boot partition and, if you've already installed any new software (like cryptsetup), you can also mount the package cache: # apt-get install cryptsetup # modprobe sha256 # modprobe dm-crypt # modprobe aes # cryptsetup luksOpen /dev/sda5 root # mkdir /mnt/misc # mount /dev/mapper/root /mnt/misc/ # mount -o bind /dev/ /mnt/misc/dev/ # mount -t proc none /mnt/misc/proc/ # mount -t sysfs none /mnt/misc/sys/ # mount -o bind /var/cache/apt/archives/ /mnt/misc/var/cache/apt/archives/ # mount -o bind /boot/ /mnt/misc/boot/ # chroot /mnt/misc/ /bin/bash Congratulations! You are now in your encrypted root, at least to some extend. :) But to be able to boot into this root partition, we'll now have to modify the initramfs. Modify the initramfsFinally, we've arrived at the central part of this howto!
This section is heavily based on the following article: If you don't understand everything in this part, take a look at the original article above, because it's more verbose than this howto. There are several tools to generate an initramfs. We'll use yaird to accomplish our goal, so we'll install it now together with cryptsetup. Yes, you've read right, we'll need to install cryptsetup again because we're now in the encrypted root: # apt-get install cryptsetup yaird Now we'll edit /etc/yaird/Default.cfg and add a couple of modules, which will be required at boot time. Just append them after the other modules: File: /etc/yaird/Default.cfg (extract only) # Required for decryption MODULE dm_crypt MODULE sha256 MODULE aes # Required for the USB harddrive MODULE ohci_hcd MODULE sd_mod MODULE usb_storage # Required for your USB stick MODULE vfat MODULE nls_cp437 MODULE nls_iso8859_1 Note that your modules might vary, especially for the USB stick. You can use lsmod to see what modules are currently loaded to use your hardware. You can also check what dmesg says after you plug in your USB stick. First we'll add a few more files which will be included in the initramfs at the beginning of the file,
in the prologue-section of File: /etc/yaird/Templates.cfg (extract only) FILE "/sbin/cryptsetup" FILE "/sbin/halt" DIRECTORY "/tmp" Now we'll modify the init-script section. Here's a part of the section, along with a few added lines. The new lines are marked with a ** at the beginning, which is not part of that line!
The File: /etc/yaird/Templates.cfg (extract only)
!ro=-r
!ip=
!nfsroot=
!noresume=
!resume=
!resume2=
!init=/sbin/init
** !keyfile=root.key
** !waitusb=10
!for i in $(cat /proc/cmdline)
!do
! case "$i" in
! init=*)
! init=${i#init=}
! ;;
! ro)
! ro=-r
! ;;
! rw)
! ro=
! ;;
! ip=*|nfsaddrs=*)
! ip="$ip $i"
! ;;
! nfsroot=*)
! nfsroot="$i"
! ;;
! noresume)
! noresume=1
! ;;
! resume=*)
! resume=${i#resume=}
! ;;
! resume2=*)
! resume2=${i#resume2=}
! ;;
! ydebug)
! INIT_DEBUG=yes
** ! ;;
** ! key=*)
** ! keyfile=${i#key=}
** ! ;;
** ! waitusb=*)
** ! waitusb=${i#waitusb=}
** ! ;;
! esac
!done
Because we'll use our own hack to do the decryption, we'll comment out the content of the cryptsetup_luks-section: File: /etc/yaird/Templates.cfg (extract only) TEMPLATE cryptsetup_luks BEGIN # FILE "/sbin/cryptsetup" # SCRIPT "/init" # BEGIN # !DOCRYPT=1 # !while [ "$DOCRYPT" != "0" ] # !do # ! /sbin/cryptsetup \ # ! <TMPL_IF NAME=verify>-y </TMPL_IF> \ # ! luksOpen '<TMPL_VAR NAME=src>' \ # ! '<TMPL_VAR NAME=target>' # ! DOCRYPT=$? # !done # END SCRIPT END TEMPLATE Next, we'll replace the mount-section. The result looks like the following: File: /etc/yaird/Templates.cfg (extract only)
TEMPLATE mount
BEGIN
# SCRIPT "/init"
# BEGIN
# !/bin/mount -n \
# ! <TMPL_IF NAME=isRoot>$ro</TMPL_IF> \
# ! -t <TMPL_VAR NAME=fsType> \
# ! <TMPL_VAR NAME=options> \
# ! '<TMPL_VAR NAME=device>' \
# ! '<TMPL_VAR NAME=target>'
# END SCRIPT
SCRIPT "/init"
BEGIN
!ROOTDEV=/dev/sda5
!if ( /sbin/cryptsetup isLuks $ROOTDEV 2>/dev/null ); then
! NOTOPEN=1
! /bin/sleep $waitusb
! for DEV in a b c d; do
! if [ "$NOTOPEN" != "0" ]; then
! if [ -f /sys/block/sd${DEV}/sd${DEV}1/dev ]; then
! mkbdev /dev/sd${DEV} sd${DEV}
! mkbdev /dev/sd${DEV}1 sd${DEV}/sd${DEV}1
! mount -n /dev/sd${DEV}1 /tmp
! if [ -f /tmp/$keyfile ]; then
! /sbin/cryptsetup --key-file /tmp/$keyfile luksOpen $ROOTDEV root
! NOTOPEN=$?
! fi
! umount /tmp
! fi
! fi
! done
! if [ "$NOTOPEN" != "0" ]; then
! /sbin/halt -n -d -f -p
! else
! /bin/mount -n $ro -t ext3 -o 'errors=remount-ro' /dev/mapper/root /mnt
! fi
!else
! /bin/mount -n $ro -t ext3 -o 'errors=remount-ro' $ROOTDEV /mnt
!fi
END SCRIPT
END TEMPLATE
Now we can finally leave /etc/yaird/Templates.cfg. The next step is to tell the system that we actually want to use yaird, so add the following into /etc/kernel-img.conf: File: /etc/kernel-img.conf (extract only) ramdisk = /usr/sbin/mkinitrd.yaird Now comment out any dublicated entries in Finally the time has come to generate the new initramfs and flash it into your NSLU2. This can be done with one simple command. :) This is the second most exciting part of the howto. # dpkg-reconfigure linux-image-$(uname -r) If you haven't made any mistakes so far, you should now have the right flash image installed, but don't just reboot yet! You have to make 2 last changes: First, edit Second, edit File: /etc/crypttab root /dev/sda5 none luks If you had done those two steps before-head, yaird might have complained upon creating the initramfs. If you haven't done it yet, plug in your USB stick into the NSLU2. And now we've reached the most exciting part of the howto. # reboot Reboot and hope that the system will boot into your new and shiny root. The system should change it's LED-blinking mode after 2min 15sec, and should be accessible via ssh after 2min 24sec. If nothing has happened after 3 minutes, it's most likely that something has failed, but there's also the possibility that the failure was just temporal, which sometimes happens. If nothing should happen for 3 minutes, the system has frozen, and you'll have to cut the power off and on again to restart it. If, after the 3. try it still freezes, the configuration and/or flash image might contain errors, and that is when your flash image, which you of course backed up before, will come in handy. Because then you'll have to reflash the NSLU2 with the upslug2 tool and that image to be able to access your unencrypted system, so you can make changes to the yaird configs and run dpkg-reconfigure again. If you are confident that the flash image is OK, and that only the other configs like If the system has successfully booted into the encrypted root, don't forget to make a backup of your new flash image! You never know when you'll need it next! Encrypt the remaining partitionsNow comes the relaxing part of the howto, because most of what comes now is already known to us. :) What remains to us now are the boot and the swap partitions which are still unencrypted. As already stated above, we'll use a key file for the boot partition, which will be located on the root partition, and we'll use a randomly generated key for the swap partition for every new session. First of all we create a directory to store the key(s) and generate one for the boot partition. # install -d -m700 /etc/cryptkeys # this already sets the permissions correctly # cd /etc/cryptkeys # head -c 2880 /dev/urandom | uuencode -m - | head -n 65 | tail -n 64 > ./boot # chmod 600 boot.key Now we have a new key file for the boot partition. What follows now is pretty similar to what we've done before before. So backup the content of the boot partition, unmount it, create a new encrypted volume on it with boot.key as the key file,
open it with cryptsetup with the tag boot (which will create the device Now we only need to make some changes in File: /etc/crypttab root /dev/sda5 none luks boot /dev/sda1 /etc/cryptkeys/boot.key luks swap /dev/sda2 /dev/urandom swap File: /etc/fstab (extract only) /dev/mapper/boot /boot ext3 defaults,noauto 0 2 /dev/mapper/swap none swap sw 0 0 Note that the noauto option will result that every time you install or modify the kernel or initramfs, you'll have to mount it manually. Remember, that was part of the original strategy. And thats it. After a reboot, you can check whether the changes are correct: # swapon -s # should point to /dev/mapper/swap now # ls -l /boot # should now be empty # mount /boot # ls -l /boot # should now be filled Thats it. Congratulations, you now have an NSLU2 with a fully encrypted root! You can now safely delete TodoOr to be more precise, to find out how to do... Make the NSLU2 beep at boot timeIf I haven't made any mistakes in this howto, and you haven't made any yourself, you'll just have a running encrypted slug (at least most of the time). But if there's occurred a mistake, this setup is really difficult to debug and find out what's gone wrong. Therefore, it would be cool it the slug could beep for between any commands of the init-script, so that we can at least find out when the failure occurred. Here's one of my unsuccessful tries: We can beep via a neat tool called beep, and even polyphonic: # apt-get install beep # beep -f 10 # beep -f 15 # beep -f 20 This program would also have to be included into File: /etc/yaird/Templates.cfg (extract only) FILE "/dev/tty0" # beep complains, if this isn't included... FILE "/usr/bin/beep" # yaird -f directory -o ~/yaird # chroot ~/yaird /bin/dash # beep -f 10 Great, we can now hear a beep! But that doesn't seem to be enough, because if I add a few beeps into So this problem is not solved yet. Use UUIDs for the partitionsI don't know why the slug sometimes fails to boot into the encrypted system, but perhaps because the harddrive (sda) and the USB stick(sdb)
might switch sometimes, because the order should be random. So I've tried to use UUID entries in So that project is frozen for the time being... |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||