Keep your secrets secret by keeping everything secret.
People often store sensitive information on their hard disks and have concerns about this information falling into the wrong hands. This is particularly relevant to users of laptops and other portable devices, which might be stolen or accidentally misplaced.
File-oriented encryption tools like GnuPG are great for encrypting particular files that will be sent across untrusted networks or stored on disk. But sometimes these tools are inconvenient, because the file must be decrypted each time it is to be used; this is especially cumbersome when you have a large collection of files to protect. Any time a security tool is cumbersome to use, there's a chance you'll forget to use it properly, leaving the files unprotected for the sake of convenience.
Worse, readable copies of the encrypted contents might still exist on the hard disk. Even if you overwrite these files (using rm -P) before unlinking them, your application software might make temporary copies that you don't know about or that have been paged to swapspace. Even your hard disk might have silently remapped failing sectors with data still in them.
The solution is simply never to write the information unencrypted to the hard disk. Rather than taking a file-oriented approach to encryption, consider a block-oriented approach a virtual hard disk that looks just like a normal hard disk with normal filesystems, but which encrypts and decrypts each block on the way to and from the real disk.
NetBSD includes the encrypting block device driver cgd(4) to help you accomplish this task; the other BSDs have similar virtual devices that, with somewhat different commands, can achieve the same thing. This hack concentrates on NetBSD's cgd.
6.8.1 The Cryptographic Disk Device
To the rest of the operating system, the cgd(4) device looks and behaves like any other disk driver. Rather than driving real hardware directly, it provides a logical function layered on top of another block device. It has a special configuration program, cgdconfig , to create and configure a cgd device and point it at the underlying disk device that will hold the encrypted data. You can stack several logical block devices together; cgd(4) on top of vnd(4) is handy for making an encrypted volume in a regular file without repartitioning, or you can make an encrypted raid(4).
Once you have a cgd configured, you can put a disklabel on it to divide it up into partitions, make filesystems or enable swapping to those partitions, or mount and use those filesystems, just like any other new disk.
Roland C. Dowdeswell wrote the cgd driver. It first appeared in NetBSD-current after the 1.6 release branch. As a result, it is not in the 1.6 release series; it will be in the 2.0 release and, in the meantime, many people are using it with -current.
In order to use cgd, ensure that you have the line:
pseudo-device cgd 4 # cryptographic disk devices
in your kernel configuration file; otherwise, build and install a new kernel. You'll also need a running system, as the NetBSD installer currently doesn't support installing new systems directly into a cgd.
6.8.2 Preparing the Disk
First, decide which filesystems you want to move to an encrypted device. You need to leave at least the small root filesystem (at /) unencrypted in order to load the kernel and run init, cgdconfig, and the rc.d scripts that configure your cgd. In this example, we'll encrypt everything except /.
We are going to delete and remake partitions and filesystems, and will require a backup to restore the data. So, make sure you have a current, reliable backup stored on a different disk or machine. Do your backup in single-user mode, with the filesystems unmounted, to ensure you get a clean dump. Make sure you back up the disklabel of your hard disk as well, so you have a record of the original partition layout.
With the system in single-user mode, / mounted as read-write, and everything else unmounted, delete all the data partitions you want to move into cgd.
Then, make a single new partition in all the space you just freed up, say, wd0e. Set the type for this partition to ccd. (There's no code specifically for cgd, but ccd is very similar. Though it doesn't really matter what it is, it will help remind you that it's not a normal filesystem.) When finished, label the disk to save the new partition table.
6.8.3 Scrubbing the Disk
We've removed the partition table information, but the existing filesystems and data are still on disk. Even after we make a cgd device, create filesystems, and restore our data, some of these disk blocks might not yet be overwritten and might still contain our data in plain text. This is especially likely if the filesystems are mostly empty. We want to scrub the disk before we go further.
We could use dd to write /dev/zero over the new wd0e partition, but this will leave our disk full of zeros, except where we later write encrypted data. We might not want to give an attacker any clues about which blocks contain real data and which are free space, so we want to write noise into all the disk blocks. We'll create a temporary cgd, configured with a random, unknown key.
First, we make a parameters file to tell cgd to use a random key:
# cgdconfig -g -k randomkey -o /tmp/wd0e-rnd aes-cbc
Then, we use that file to configure a temporary cgd:
# cgdconfig cgd0 /dev/wd0e /tmp/wd0e-rnd
Now we can write zeros into the raw partition of our cgd (this device will be cgdxd on NetBSD/i386 and cgdxc on most other platforms):
# dd if=/dev/zero of=/dev/rcgd0d bs=32k
The encrypted zeros will look like random data on disk. This might take a while if you have a large disk. Once finished, unconfigure the random-key cgd:
# cgdconfig -u cgd0
6.8.4 Creating the Encrypted Disk Device
The cgdconfig program, which manipulates cgd devices, uses parameters files to store such information as the encryption type, key length, and a random password salt for each cgd. These files are very important and must be kept safe without them, you will not be able to decrypt the data!
We'll generate a parameters file and write it into the default location (make sure the directory /etc/cgd exists and is mode 600):
# cgdconfig -g -V disklabel -o /etc/cgd/wd0e aes-cbc 256
This creates a parameters file describing a cgd using aes-cbc encryption, a key verification (-V) method of disklabel, and a key length of 256 bits. Remember, you'll want to save this file somewhere safe later.
Now it's time to create our cgd, for which we'll need a passphrase. This passphrase must be entered every time the cgd is opened, usually at each reboot, and it is from this passphrase that the encryption key used is derived. Make sure you choose something you won't forget and others won't guess.
The first time we create the cgd, there is no valid disklabel, so the validation mechanism we want to use later won't work. We override it this one time:
# cgdconfig -V re-enter cgd0 /dev/wd0e
This will prompt twice for a matching passphrase.
Now that we have a new cgd, we need to partition it and create filesystems. Recreate your previous partitions with all the same sizes, although the offsets will be different because they're starting at the beginning of this virtual disk. Remember to include the -I argument to disklabel, because you're creating an initial label for a new disk.
Then, use newfs to create filesystems on all the relevant partitions. This time your partitions will reflect the cgd disk names:
# newfs /dev/rcgd0h
6.8.5 Modifying Configuration Files
We've moved several filesystems to another disk, and we need to update /etc/fstab accordingly. Each partition will have the same letter but will be on cgd0 rather than wd0. So, you'll have /etc/fstab entries that are similar to these:
/dev/wd0a / ffs rw,softdep 1 1 /dev/cgd0b none swap sw 0 0 /dev/cgd0b /tmp mfs rw,-s=132m 0 0 /dev/cgd0e /var ffs rw,softdep 1 2 /dev/cgd0f /usr ffs rw,softdep 1 2 /dev/cgd0h /home ffs rw,softdep 1 2
Note that /tmp should be a separate filesystem, either mfs or ffs, inside the cgd, so that your temporary files are not stored in plain text in the / filesystem.
Each time you reboot, you're going to need your cgd configured early, before fsck runs and filesystems are mounted.
Put the following line in /etc/cgd/cgd.conf:
and the following line into /etc/rc.conf:
You should now be prompted for cgd0's passphrase whenever rc starts.
6.8.6 Restoring Data
Next, mount your new filesystems, and restore your data into them. It often helps to have /tmp mounted properly first, as restore can use a fair amount of space when restoring a large dump.
To test your changes to the boot configuration, unmount the filesystems and unconfigure the cgd, so when you exit the single-user shell, rc will run as it does on a clean boot. Now you can bring the system up to multiuser and make sure everything works as before.
6.8.7 Hacking the Hack
Here are some other things you might consider doing, for extra hack value:
6.8.8 Final Thoughts and Warnings
Prevent cryptographic disasters by making sure you can always recover your passphrase and parameters file. Protect the parameters file from disclosure, perhaps by storing it on removable media as just mentioned, because the salt it contains helps protect against dictionary attacks on the passphrase.
Keeping the data encrypted on your disk is all very well, but what about other copies? You already have at least one other such copy (the backup we used during this setup), and it's not encrypted. Piping dump through a file-based encryption tool such as gpg can be one way of addressing this issue, but make sure you can decrypt it to restore after a disaster.
Like any form of software encryption, the cgd key stays in kernel memory while the device is configured and may be accessible to privileged programs and users, such as kmem grovelers. Running your system with an elevated securelevel is highly recommended.
Once the cgd volumes are mounted as normal filesystems, their accessibility is just like any other file. Take care of file permissions, and ensure that your running system is protected against application and network security attacks.
Avoid using suspend and resume, especially for laptops with a BIOS suspend-to-disk function. If an attacker can resume your laptop with the key still in memory or read it from the memory image on disk later, the whole point of using cgd is lost.
6.8.9 See Also