Full disk encryption in FreeBSD 9.x (well, almost!)

This article will tell you how to fully encrypt your hard disk in FreeBSD 9.x.  When I say ‘fully’, I mean as close as possible.  It will leave the bootloader and /boot folder unencrypted, but everything else will be encrypted (including your swap space).  Basically, all your data is encrypted and that’s the point…

Boot from any FreeBSD 9 install medium (except bootonly), and choose Live CD at the installer menu.

For this article, I will assume you’re using the /dev/ada0 disk, a 10GB /boot, a 4GB swap and remaining disk encrypted.  The contents will be encrypted using AES-XTS 256-bit encryption  with a 4 kilobit random data partial key and a passphrase (required to type on boot).  This method requires no external data (no USB sticks, no bootable CDs to boot the OS) – but does not offer two factor authentication which is better than this method.  For general encryption needs, this method is more than sufficient.

Note that more recent CPUs support AESNI flag for offloading. As GELI uses the crypto(4) framework, the OS will utilise this function of your CPU to assist the encryption to decrease CPU load.

First, we need to remove any existing GPT or MBR partition tables on the disk – ignore any ‘invalid argument’ messages you get at this stage:

gpart destroy -F ada0

Now we need to initialise a new GPT partition table, as follows:

gpart create -s gpt ada0

We will now create a 64kb boot partition (this contains the boot loader only, so is safe and required to be unencrypted):

gpart add -s 128 -t freebsd-boot ada0

Next, we will create the /boot partition – you can adjust the sizes here if you need, but i’d suggest not shrinking it too much or you’ll get into problems when doing OS upgrades later…

gpart add -s 10G -t freebsd-ufs ada0

Now for a swap partition.  Again, you can adjust the size if needed.  This will be encrypted during boot with a one-time 256bit key.

gpart add -s 4G -t freebsd-swap ada0

Finally, we assign the remaining data to a partition.  This will form the entire disk (excluding /boot) and will be encrypted shortly.

gpart add -t freebsd-ufs ada0

OK, so we’ve created… ada0p1 (bootloader), adap2 (unencrypted /boot partition), adap3 (swap partition) and adap4 (encrypted disk partition).  We need to write the boot loader to the disk now:

gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 ada0

Now we need to format the /boot partition:

newfs -O2 -U -m 0 -j /dev/ada0p2

And temporarily mount it as /mnt:

mount /dev/ada0p2 /mnt

Now we will create a 4kb random data file that will form part of the encryption key:

dd if=/dev/random of=/mnt/encryption.key bs=4096 count=1

Now we’re in a position to encrypt the main disk.  This part will ask for a passphrase twice to complete:

kldload geom_eli
geli init -a HMAC/SHA256 -b -B /mnt/ada0p4.eli -e AES-XTS -K /mnt/encryption.key -l 256 -s 4096 /dev/ada0p4
geli attach -k /mnt/encryption.key /dev/ada0p4

You will receive some messages on the console about checksum mismatches – this is normal and please ignore them.

If you have time, I recommend writing the entire disk with random data to initialise the checksums.  This is a VERY time consuming step – you can skip it if you wish, but it is recommended:

dd if=/dev/random of=/dev/ada0p4.eli bs=1m

Next we will unmount the old parition so we can mount the new “root” after formatting  (and re-mount the /boot partition too):

umount /mnt
newfs -O2 -U -j -m 6 /dev/ada0p4.eli
mount /dev/ada0p4.eli /mnt
mkdir /mnt/bootdir
mount /dev/ada0p2 /mnt/bootdir

OK, we’re ready to install the OS files onto the disk now… We will install the base, kernel, src and ports tarballs as follows:

cd /mnt
unxz -c /usr/freebsd-dist/base.txz | tar xpf -
unxz -c /usr/freebsd-dist/kernel.txz | tar xpf -
unxz -c /usr/freebsd-dist/src.txz | tar xpf -
unxz -c /usr/freebsd-dist/ports.txz | tar xpf -

Note: this can take a while (especially the ports extraction) so please be patient.  If you’d like to see some kind of progress, change the “xpf” to “xvpf” and it will scroll the files to the screen as they are extracted.

Now we have to move the /boot folder to the unencrypted partition (it’s really not much use if it’s encrypted!) – we will also move the keyfile and backup file into the /boot folder:

mv boot bootdir/
ln -fs bootdir/boot
mv encryption.key ada0p4.eli bootdir/boot/

Now we need to prepare a few things in the installed OS – so we will chroot into the folder:

chroot /mnt

We need to tell the boot loader to load kernel modules for decryption, and also tell it about the keyfile for the partition… edit the file /boot/loader.conf and enter the following:

vfs.root.mountfrom=”ufs:/dev/ada0p4.eli”
aesni_load=”YES”
geom_eli_load=”YES”
geli_ada0p4_keyfile0_load=”YES”
geli_ada0p4_keyfile0_type=”ada0p4:geli_keyfile0″
geli_ada0p4_keyfile0_name=”/boot/encryption.key”

Now we need to tell the system to encrypt our swap space using a one-time key on each boot (note: this prevents system dumps from working)… edit /etc/rc.conf and enter:

geli_swap_flags=”-e AES-XTS -l 256 -s 4096 -d”

Next we need to tell the system our mountpoints… edit the file /etc/fstab and enter:

# Device                   Mountpoint FStype Options Dump Pass#
/dev/ada0p4.eli   /                   ufs    rw      0    0
/dev/ada0p2         /bootdir   ufs    rw      1    1
/dev/ada0p3.eli   none           swap   sw      0    0

Now we need to initialise a few things… let’s start by setting the root password:

passwd root

And configuring your timezone:

tzsetup

And initialise the sendmail aliases file:

cd /etc/mail
make aliases

You can do any other system setup you need now, such as adding users, configuring SSH or networking…  when you’re done:

exit

Now we’re done, we can reboot…

reboot

On boot, you will see a prompt for:

Enter passphrase for ada0p4:

Note, however, that devices are still being detected while this occurs so it may scroll off the screen (usually while detecting USB devices) – this doesn’t affect your ability to enter the passphrase, but can be confusing if you’re not expecting it!

Once the system is up and running, you can use it as normal.

The only point to note is that when you do an OS upgrade, during the “mergemaster” stage, it will complain that /boot is a symlink not a directory.  Simply tell it to ignore/do nothing and it will install the files as normal.

41 thoughts on “Full disk encryption in FreeBSD 9.x (well, almost!)

  1. Eric LeBlanc

    Thanks for the nice how to. However, it should be noted that the command to format the ada0p4.eli partition be as follows: newfs -O2 -U -m 6 -j /dev/ada0p4.eli . Otherwise, you’ll keep getting an error and the process will abort (in FreeBSD 9.0 Release).

  2. bazzoola

    I cannot boot I get this error

    gptboot: No /boot/loader on 0:ad(0p2)
    ,,,
    FreeBSD/x86 boot
    Default: 0:ad(0p2)/boot/kernel/kernel
    Boot:

  3. dan Post author

    This error sounds like you haven’t installed the boot files into ada0p2.
    Double-check that you followed every command exactly.
    The error is saying that /boot/loader and /boot/kernel/kernel are not present on the small 10GB unencrypted partition (ada0p2) – this is the partition that is eventually mounted as /bootdir and contains a boot folder.

  4. bazzoola

    I did follow all commands exactly.
    I am using FreeBSD 9 Release CDROM i386.

    The only command that i didnt follow is the geli init
    when I use HMAC I cannot mount my newfs I only use
    %geli init -bl 256

    is it ada or just ad?

  5. bazzoola

    It worked fine now. I just logged in again using the boot CD and fixed loader.conf. Also, on my 1st attempted I forgot to copy the boot partition over.
    Thanks!

  6. ian

    When making new FS on encrypted partition (performing newfs -O2 -U -j -m 6 /dev/ada0p4.eli) I get strange error:

    GEOM_ELI: da0p4.eli: 8192 bytes corrupted at offset 8192.
    newfs: can’t read old UFS1 superblock: read error from block device: Inavlid argumens

  7. dan Post author

    hmm the corrupted message is normal if you skipped over the long ‘dd’ write section of the page, but the newfs error is unusual… not really sure what’s up there.

  8. Frank

    Nice instructions. Wonder, should this also work for a virtual host? Have tried this instruction with 9.0-Release and after rebooting I get error 19 and end up in mountroot> prompt. Any idea?

  9. dan Post author

    The OS doesn’t care what hardware it is (physical or virtual) – it should work the same either way.
    If you’re getting a mountroot> prompt, you may have missed a step of the installation perhaps.

  10. Lele

    “You will receive some messages on the console about checksum mismatches – this is normal and please ignore them.”

    Why is it normal? I mean, if everything is going right, why are such warning being issued?

    What filesystem will be installed this way?

    Thanks.

  11. dan Post author

    It’s normal because you haven’t generated the checksums on the disk yet.
    To do so, you need to write the entire disk once which is a time consuming task (depending on the size of the disk).

    If you run the command I mention as being time consuming in the post (which is recommended) then you will not get any checksum errors as you will have written a full disk of data and therefore generated all checksums.

    It’s simply there for people who want the quick method (a lot of people are impatient) – I included the recommendation to run the ‘dd’ command to generate them so it should please both sets of people!

    For a more technical description… when you try to partition the disk, it looks for entries at various points on the drive. The checksums fail as it is trying to read an area of the disk that has not been written to yet (so has no checksums). This means the checksums are mismatched (or nonexistent).

  12. Lele

    Thank you for clarifying.

    You didn’t tell what filesystem will be installed this way, but I guess it will be UFS.

    The Handbook advises against manual partitioning for beginners. What would change if a beginner user chose the automatic partition layout (“Auto Defaults” in the FreeBSD partition editor) instead?

  13. dan Post author

    It uses a UFS2 with journalled soft-updates filesystem (with space optimisation on the unencrypted boot filesystem, and time optimisation on the encrypted filesystem – it also reserves only 6% of space compared to the default of 8%).

    There is no way to do encryption in FreeBSD for beginners. You have to skip the installer entirely so there’s no way to choose the automatic partition layout.
    The installer supports only standard installations and can’t currently support encryption or other technologies like raid or ZFS.

  14. Lele

    Thanks. Then the issue would be only about the size of the swap partition. You used 4GB for how much system RAM?

    Also, any pointers to continue the installation for a desktop with a window manager? All the tutorials I’ve seen show installation via bsdinstall, but since it cannot be used here…

  15. dan Post author

    long gone are the days when swap should be relative to your system ram in FreeBSD… 4GB should be more than enough for any system these days – if anything probably larger than needed.
    I have a post on here for installing xorg+gnome for a desktop from either ports or packages.
    You can always use bsdinstall post-install to set options or install packages as normal. You just can’t use it to do the initial install due to the disk configuration.

  16. Lele

    I’ve found your post about Xorg + Gnome, thanks. So, bsdinstall can be run later… I didn’t know that. Should I choose the “Install” option then? If so, I guess I will have to choose the Manual partitioning, and just press Finish because the partitions are already in place, right?

  17. Ville

    I am getting an error (after reboot) with this quide using FreeBSD 9 as guest OS with KVM ->
    “mounting from ufs:/dev/label/eee.elia failed with error 19″

    I did by the instructions and double checked for mistakes. Any ideas?

  18. dan Post author

    You can’t use labels as they will not work. You have to use the raw device names (e.g. /dev/da0p2.eli)

  19. Micah

    Hi,could you tell me how to encrypt a ramdisk?
    I have build a kernel with “options MD_ROOT, options MD_ROOT_SIZE=53248″
    and make a mfsroot file includ some codes.
    Then put the mfsroot file into kernel.
    But I want encrypt the mfsroot file first and won’t to input “boot password”(just like: On boot, you will see a prompt for:Enter passphrase for ada0p4:)
    Could you help me? Sorry for my pool English.
    Thanks.
    MR_Micah@126.com

  20. dan Post author

    It is not possible to encrypt the kernel (nor should it be required as there’s nothing sensitive in the kernel) – the contents of the /boot folder must be left unencrypted.

  21. Oscar

    When I get to extracting the src.txz on FreeBSD 9.1 the disk fills up, I get “Write to restore size failed” I have been following the commands exactly as stated here 3-4 times. /mnt has ada0p4.eli mounted and a capacity of 881M and /mnt/bootdir is 10G with ada0p2 mounted.

  22. dan Post author

    if ada0p4.eli is only 881MB, you need a bigger disk! You will be filling up the encrypted partition with the base OS.

  23. Oscar

    Figured it out, not enough disk space. Leave more free space for the last partition. No need to publish these comments. Thanks for the guide!

  24. Bob

    This worked great for me a few months ago and have zfs jails running over the top.

    How would I go about changing the device name? Due to a hardware change the device name is changing and I can’t figure out where to change it, have changed in loader.conf but does not mount. Is there something in the GELI metadata or if it fully controlled by loader.conf?

  25. desmo

    Thanks for your documentation, I wonder if you feel the encryption when you use your computer (like slower).
    I thinking to use encryption on my laptop, and for I don’t known why each time I use a little CPU (launching flash, starting building some ports) the fan start immedialty. So I’m little afraid about cpu comsuption when using encrypted disk, if my cpu load is always high that’s going to make me very sad.

    Thanks again

  26. dan Post author

    I’ve always used it on laptops and not noticed a significant increase in CPU usage… of course it depends on just how much disk activity you do.
    But generally so long as your CPU isn’t really slow to begin with, you should be fine.

  27. dan Post author

    It should all be in loader.conf – but you should be more worried about why the device names are changing!

  28. Anonymous Coward

    i’m fairly certain
    dd if=/dev/random of=/dev/ada0p4.eli bs=1m
    should actually be
    dd if=/dev/random of=/dev/ada0p4 bs=1m

  29. B

    Hi,
    I did everything like in tutorial and it worked fine, I rebooted my home server many times… But once I got electricity off period, and after that when I boot I always get incorrect password… I tried with debug=3 and showpassword=1 in loader.conf but no luck?

    Do i need to restore with ada0p4.eli backup file or smth?

    Regards.

  30. dan Post author

    nope, it’s definitely /dev/ada0p4.eli :-)
    By writing to the .eli device, you’re forcing an encrypted write of the entire disk which stops annoying messages to syslog/screen about mismatched checksums on random reads.

  31. Bab

    Hi. Tnx about your article.
    i wan’t to find any way to crypt my hard, but don’t ask any password in startup, and limit my os to motherboard HWID ?

  32. Walter Hartford

    Hi Dan, great article. I’ve set up two machines this way. I noticed that both machines are yelling “WARNING: / was not dismounted properly” on every reboot. Is this “normal” behaviour? I don’t see any problems so far, so I ignored this message.

  33. dan Post author

    Hmm no, it should never say that unless you don’t shutdown the computer correctly.
    It’s unlikely to cause you an issue as that partition isn’t written to unless you update/upgrade the kernel – but still it shouldn’t be doing it.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>