Full Disk Encryption On Raspberry Pi


Intro

The following instructions are for setting up a raspberry pi with raspbian and full disk encryption.

The basic process is:

  1. Put raspbian on an SD card and boot it up.
  2. Install dm-crypt.
  3. Configure the system to use an encrypted root partition.
  4. Shut it down and plug the SD card into another linux box.
  5. Make a backup of the contents of the root partition.
  6. Create an encrypted filesystem overtop the root partition on the SD card.
  7. Mount it and restore the backed up root partition contents.
  8. Plug the SD card back into the Raspberry Pi and pray!

A reasonable degree of Linux experience is assumed.

Steps

First, grab a copy of Raspbian from https://www.raspberrypi.org/downloads/raspbian/ and write it to an sd card. I prefer the "lite" version, but these instructions should work with the full version.

wget https://downloads.raspberrypi.org/raspbian_lite_latest -O raspbian.zip
unzip raspbian.zip
dd if=./*-raspbian-jessie-lite.img of=/dev/sd<whatever>

Plug the SD card into your Raspberry Pi and boot it up.

Log in with the default user/password (pi:raspberry) and get yourself a root shell.

sudo su -

Install our required packages.

apt-get update
apt-get install busybox
apt-get install cryptsetup

Edit /boot/cmdline.txt to change the existing root setting to reference our eventual encrypted file system and add a cryptdevice setting to open the device on boot.

root=/dev/mapper/crypt cryptdevice=/dev/mmcblk0p2:crypt

Edit /etc/fstab to point / at our future encrypted file system.

/dev/mapper/crypt / ext4 defaults,noatime 0 1

Add a line to /etc/crypttab to reference the encrypted partition. Important: use tabs not spaces!

crypt	/dev/mmcblk0p2	none	luks

Create a temporary encrypted filesystem to trick mkinitramfs into pulling the required modules in.

dd if=/dev/zero of=/tmp/fakecrypt.img bs=1M count=30
cryptsetup luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 /tmp/fakecrypt.img
cryptsetup luksOpen /tmp/fakecrypt.img crypt
mkfs.ext4 /dev/mapper/crypt

For our future convenience, we'll do some hackery so that when an initrd is (re)generated, we automatically copy the version tagged file (initrd.img-<version>) to a common file name (initrd.img-current). We can then just reference this file in the boot configuration, preventing our system from breaking on a kernel update.

First, create the directory where initramfs-tools looks for post update scripts.

mkdir -p /etc/initramfs/post-update.d/

Then create file /etc/initramfs/post-update.d/copy_initrd with the following contents:

#!/bin/sh

cp -v $2 /boot/initrd.img-current

And of course, make the script executable.

chmod a+x /etc/initramfs/post-update.d/copy_initrd

[TODO: tweak /etc/kernel/postinst.d/initramfs-tools to set INITRD="yes"

Generate the initrd the first time.

update-initramfs -c -t -k `uname -r` -v

Add a line to the end of /boot/config.txt to use our initrd. We also add a line to add a short delay before the kernel image is loaded (this is a workaround for a hardware issue).

initramfs initrd.img-current
boot_delay=5

Shut it down.

shutdown -h now

Pull the SD card and plug it back into our "other linux box".

Mount the second (currently unencrypted) partition on the SD card and grab a backup of it's contents.

mkdir pi_mnt
mount /dev/sd<whatever>2 ./pi_mnt
tar cf part2_contents.tar -C pi_mnt .
umount pi_mnt

Setup a new encrypted partition on the SD card.

cryptsetup luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 /dev/sd<whatever>2
cryptsetup luksOpen /dev/sd<whatever>2 pi_crypt
mkfs.ext4 /dev/mapper/pi_crypt

Copy the data back to the new encrypted partition.

mount /dev/mapper/pi_crypt ./pi_mnt
tar xf part2_contents.tar -C pi_mnt
umount pi_mnt
cryptsetup luksClose pi_crypt

Plug the SD card back into the Raspberry Pi and boot it up!