Chapter 14. The cryptographic device driver (CGD)

Table of Contents

14.1. Overview
14.1.1. Why use disk encryption?
14.1.2. Logical Disk Drivers
14.1.3. Availability
14.2. Components of the Crypto-Graphic Disk system
14.2.1. Kernel driver pseudo-device
14.2.2. Ciphers
14.2.3. Verification Methods
14.3. Example: encrypting your disk
14.3.1. Preparing the disk
14.3.2. Scrubbing the disk
14.3.3. Creating the cgd
14.3.4. Modifying configuration files
14.3.5. Restoring data
14.4. Example: encrypted CDs/DVDs
14.4.1. Introduction
14.4.2. Creating an encrypted CD/DVD
14.4.3. Using an encrypted CD/DVD
14.5. Suggestions and Warnings
14.5.1. Using a random-key cgd for swap
14.5.2. Warnings
14.6. Further Reading

The cgd driver provides functionality which allows you to use disks or partitions for encrypted storage. After providing the appropriate key, the encrypted partition is accessible using cgd pseudo-devices.

14.1. Overview

People often store sensitive information on their hard disks and are concerned about this information falling into the wrong hands. This is particularly relevant to users of laptops and other portable devices, or portable media, which might be stolen or accidentally misplaced.

14.1.1. Why use disk encryption?

File-oriented encryption tools like GnuPG are great for encrypting individual files, which can then be sent across untrusted networks as well as stored encrypted on disk. But sometimes they can be 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 you don't know about, or have been paged to swapspace - and even your hard disk might have silently remapped failing sectors with data still in them.

The solution is to simply never 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.

14.1.2. Logical Disk Drivers

The cgd device looks and behaves to the rest of the operating system 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.

NetBSD includes several other similar logical block devices, each of which provides some other function where cgd provides encryption. You can stack several of these logical block devices together: you can make an encrypted raid to protect your encrypted data against hard disk failure as well.

Once you have created a cgd disk, you can use disklabel to divide it up into partitions, swapctl to enable swapping to those partitions or newfs to make filesystems, then mount and use those filesystems, just like any other new disk.

14.1.3. Availability

The cgd driver was written by Roland C. Dowdeswell, and introduced in NetBSD-current between the 1.6 and 2.0 release branches. As a result, it is not in the 1.6 release series; it is in the 2.0 release.

14.2. Components of the Crypto-Graphic Disk system

A number of components and tools work together to make the cgd system effective.

14.2.1. Kernel driver pseudo-device

To use cgd you need a kernel with support for the cgd pseudo-device. Make sure the following line is in the kernel configuration file:

pseudo-device   cgd     4       # cryptographic disk driver

The number specifies how many cgd devices may be configured at the same time. After configuring the cgd pseudo-device you can recompile the kernel and boot it to enable cgd support.

14.2.2. Ciphers

The cgd driver provides the following encryption algorithms:

Encryption Methods

aes-cbc

AES (Rijndael). AES uses a 128 bit blocksize and accepts 128, 192 or 256 bit keys.

blowfish-cbc

Blowfish uses a 64 bit blocksize and accepts 128 bit keys

3des-cbc

Triple DES uses a 64 bit blocksize and accepts 192 bit keys (only 168 bits are actually used for encryption)

All three ciphers are used in CBC mode. This means each block is XORed with the previous encrypted block before encryption. This reduces the risk that a pattern can be found, which can be used to break the encryption.

14.2.3. Verification Methods

Another aspect of cgd that needs some attention are the verification methods cgdconfig provides. These verification methods are used to verify the passphrase is correct. The following verification methods are available:

Verification Methods

none

no verification is performed. This can be dangerous, because the key is not verified at all. When a wrong key is entered cgdconfig configures the cgd device as normal, but data which was available on the volume will be destroyed (decrypting blocks with a wrong key will result in random data, which will result in a regeneration of the disklabel with the current key).

disklabel

cgdconfig scans for a valid disklabel. If a valid disklabel is found with the key that is provided authentication will succeed.

ffs

cgdconfig scans for a valid FFS file system. If a valid FFS file system is found with the key that is provided authentication will succeed.

14.3. Example: encrypting your disk

This section works through a step-by-step example of converting an existing system to use cgd, performing the following actions:

  1. Preparing the disk and partitions

  2. Scrub off all data

  3. Create the cgd

  4. Adjust config-files

  5. Restoring your backed-up files to the encrypted disk

14.3.1. Preparing the disk

First, decide which filesystems you want to move to an encrypted device. You're going to need to leave at least the small root (/) filesystem 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 the root (/) filesystem.

We are going to delete and re-make 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 partition layout before you started.

With the system at single user, / mounted read-write and everything else unmounted, use disklabel to 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 partition type for this partition to cgd Though it doesn't really matter what it is, it will help remind you that it's not a normal filesystem later. When finished, label the disk to save the new partition table.

14.3.2. Scrubbing the disk

We have 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 still contain our data in plaintext. 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 copy /dev/zero over the new wd0e partition, but this will leave our disk full of zeros, except where we've written encrypted data later. 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. So we'll create a temporary cgd, configured with a random, unknown key.

First, we configure a cgd to use a random key:

# cgdconfig -s cgd0 /dev/wd0e aes-cbc 128 < /dev/urandom 

Now we can write zeros into the raw partition of our cgd (/dev/rcgd0d on NetBSD/i386, /dev/rcgd0c 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

14.3.3. Creating the cgd

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 need to 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 700):

# cgdconfig -g -V disklabel -o /etc/cgd/wd0e aes-cbc 256

This creates a parameters file /etc/cgd/wd0e describing a cgd using the aes-cbc cipher method, a key verification method of disklabel, and a key length of 256 bits. It will look something like this:

algorithm aes-cbc;
iv-method encblkno;
keylength 256;
verify_method disklabel;
keygen pkcs5_pbkdf2/sha1 {
        iterations 6275;
        salt AAAAgHTg/jKCd2ZJiOSGrgnadGw=;
};

Note

Remember, you'll want to save this file somewhere safe later.

Tip

When creating the parameters file, cgdconfig reads from /dev/random to create the password salt. This read may block if there is not enough collected entropy in the random pool. This is unlikely, especially if you just finished overwriting the disk as in the previous step, but if it happens you can press keys on the console and/or move your mouse until the rnd device gathers enough entropy.

Now it's time to create our cgd, for which we'll need a passphrase. This passphrase needs to be entered every time the cgd is opened, which is usually at each reboot. The encryption key is derived from this passphrase and the salt. Make sure you choose something you won't forget, and others won't guess.

The first time we configure the cgd, there is no valid disklabel on the logical device, 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, just in case you make a typo, which would otherwise leave you with a cgd encrypted with a passphrase that's different to what you expected.

Now that we have a new cgd, we need to partition it and create filesystems. Recreate your previous partitions with all the same sizes, with the same letter names.

Tip

Remember to use the disklabel -I argument, because you're creating an initial label for a new disk.

Note

Although you want the sizes of your new partitions to be the same as the old, unencrypted ones, the offsets will be different because they're starting at the beginning of this virtual disk.

Then, use newfs to create filesystems on all the relevant partitions. This time your partitions will reflect the cgd disk names, for example:

# newfs /dev/rcgd0h

14.3.4. Modifying configuration files

We've moved several filesystems to another (logical) disk, and we need to update /etc/fstab accordingly. Each partition will have the same letter (in this example), but will be on cgd0 rather than wd0. So you'll have /etc/fstab entries something like this:

/dev/wd0a   /     ffs     rw    1 1
/dev/cgd0b  none  swap    sw            0 0
/dev/cgd0b  /tmp  mfs     rw,-s=132m    0 0
/dev/cgd0e  /var  ffs     rw            1 2
/dev/cgd0f  /usr  ffs     rw            1 2
/dev/cgd0h  /home ffs     rw            1 2

Note

/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:

cgd0    /dev/wd0e

This will use /etc/cgd/wd0e as config file for cgd0.

To finally enable cgd on each boot, put the following line into /etc/rc.conf:

cgd=YES

You should now be prompted for /dev/cgd0's passphrase whenever /etc/rc starts.

14.3.5. 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 temporary space when extracting a large dumpfile.

To test your changes to the boot configuration, umount the filesystems and unconfigure the cgd, so when you exit the single-user shell, rc will run like on a clean boot, prompting you for the passphrase and mounting your filesystems correctly. Now you can bring the system up to multi-user, and make sure everything works as before.

14.4. Example: encrypted CDs/DVDs

14.4.1. Introduction

This section explains how to create and use encrypted CDs/DVDs with NetBSD (all I say about "CDs" here does also apply to "DVDs"). I assume that you have basic knowledge of cgd(4), so I will not explain what cgd is or what's inside it in detail. The same applies to vnd(4). One can make use of encrypted CDs after reading this howto, but for more detailed information about different cgd configuration options, please read Chapter 14, The cryptographic device driver (CGD) or the manpages.

14.4.2. Creating an encrypted CD/DVD

cgd(4) provides highly secure encryption of whole partitions or disks. Unfortunately, creating "normal" CDs is not disklabeling something and running newfs on it. Neither can you just put a CDR into the drive, configure cgd and assume it to write encrypted data when syncing. Standard CDs contain at least an ISO-9660 filesystem created with mkisofs(8) from the sysutils/cdrtools package. ISO images may not contain disklabels or cgd partitions.

But of course CD reader/writer hardware doesn't care about filesystems at all. You can write raw data to the CD if you like - or an encrypted FFS filesystem, which is what we'll do here. But be warned, there is NO way to read this CD with any OS except NetBSD - not even other BSDs due to the lack of cgd.

The basic steps when creating an encrypted CD are:

  • Create an (empty) imagefile

  • Register it as a virtual disk using vnd(4)

  • Configure cgd inside the vnd disk

  • Copy content to the cgd

  • Unconfigure all (flush!)

  • Write the image on a CD

The first step when creating an encrypted CD is to create a single image file with dd. The image may not grow, so make it large enough to allow all CD content to fit into. Note that the whole image gets written to the CD later, so creating a 700 MB image for 100 MB content will still require a 700 MB write operation to the CD. Some info on DVDs here: DVDs are only 4.7 GB in marketing language. 4.7GB = 4.7 x 1024 x 1024 x 1024 = 5046586573 bytes. In fact, a DVD can only approximately hold 4.7 x 1000 x 1000 x 1000 = 4700000000 bytes, which is about 4482 MB or about 4.37 GB. Keep this in mind when creating DVD images. Don't worry for CDs, they hold "real" 700 MB (734003200 Bytes).

Invoke all following commands as root!

For a CD:

# dd if=/dev/zero of=image.img bs=1m count=700

or, for a DVD:

# dd if=/dev/zero of=image.img bs=1m count=4482

Now configure a vnd(4)-pseudo disk with the image:

# vnconfig vnd0 image.img

In order to use cgd, a so-called parameter file, describing encryption parameters and a containing "password salt" must be generated. We'll call it /etc/cgd/image here. You can use one parameter file for several encrypted partitions (I use one different file for each host and a shared file image for all removable media, but that's up to you).

I'll use AES-CBC with a keylength of 256 bits. Refer to cgd(4) and cgdconfig(8) for details and alternatives.

The following command will create the parameter file as /etc/cgd/image. YOU DO NOT WANT TO INVOKE THE FOLLOWING COMMAND AGAIN after you burnt any CD, since a recreated parameter file is a lost parameter file and you'll never access your encrypted CD again (the "salt" this file contains will differ among each call). Consider this file being HOLY, BACKUP IT and BACKUP IT AGAIN! Use switch -V to specify verification method "disklabel" for the CD (cgd cannot detect whether you entered a valid password for the CD later when mounting it otherwise).

# cgdconfig -g -V disklabel aes-cbc 256 > /etc/cgd/image

Now it's time to configure a cgd for our vnd drive. (Replace slice "d" with "c" for all platforms that use "c" as the whole disk (where "sysctl kern.rawpartition" prints "2", not "3"); if you're on i386 or amd64, "d" is OK for you):

# cgdconfig -V re-enter cgd1 /dev/vnd0d /etc/cgd/image

The "-V re-enter" option is necessary as long as the cgd doesn't have a disklabel yet so we can access and configure it. This switch asks for a password twice and uses it for encryption.

Now it's time to create a disklabel inside the cgd. The defaults of the label are ok, so invoking disklabel with

# disklabel -e -I cgd1

and leaving vi with ":wq" immediately will do.

Let's create a filesystem on the cgd, and finally mount it somewhere:

# newfs /dev/rcgd1a
# mount /dev/cgd1a /mnt

The cgd is alive! Now fill /mnt with content. When finished, reverse the configuration process. The steps are:

  1. Unmounting the cgd1a:

    # umount /mnt
  2. Unconfiguring the cgd:

    # cgdconfig -u cgd1
  3. Unconfiguring the vnd:

    # vnconfig -u vnd0

The following commands are examples to burn the images on CD or DVD. Please adjust the dev= for cdrecord or the /dev/rcd0d for growisofs. Note the "rcd0d" is necessary with NetBSD. Growisofs is available in the sysutils/dvd+rw-tools package. Again, use "c" instead of "d" if this is the raw partition on your platform.

Finally, write the image file to a CD:

# cdrecord dev=/dev/rcd0d -v image.img

...or to a DVD:

# growisofs -dvd-compat -Z /dev/rcd0d=image.img

Congratulations! You've just created a really secure CD!

14.4.3. Using an encrypted CD/DVD

After creating an encrypted CD as described above, we're not done yet - what about mounting it again? One might guess, configuring the cgd on /dev/cd0d is enough - no, it is not.

NetBSD cannot access FFS file systems on media that is not 512 bytes/sector format. It doesn't matter that the cgd on the CD is, since the CD's disklabel the cgd resides in has 2048 bytes/sector.

But the CD driver cd(4) is smart enough to grant "write" access to the (emulated) disklabel on the CD. So before configuring the cgd, let's have a look at the disklabel and modify it a bit:

# disklabel -e cd0
# /dev/rcd0d:
type: ATAPI
disk: mydisc
label: fictitious
flags: removable
bytes/sector: 2048    # -- Change to 512 (= orig / 4)
sectors/track: 100    # -- Change to 400 (= orig * 4)
tracks/cylinder: 1
sectors/cylinder: 100 # -- Change to 400 (= orig * 4)
cylinders: 164
total sectors: 16386  # -- Change to value of slice "d" (=65544)
rpm: 300
interleave: 1
trackskew: 0
cylinderskew: 0
headswitch: 0           # microseconds
track-to-track seek: 0  # microseconds
drivedata: 0

4 partitions:
#     size  offset  fstype [fsize bsize cpg/sgs]
 a:   65544   0     4.2BSD  0     0     0  # (Cyl. 0 - 655+)
 d:   65544   0     ISO9660 0     0        # (Cyl. 0 - 655+)

If you don't want to do these changes every time by hand, you can use Florian Stoehr's tool neb-cd512 which is (at time of writing this) in pkgsrc-wip and will move to sysutils/neb-cd512 soon. You can also download the neb-cd512 source from http://sourceforge.net/projects/neb-stoehr/ (be sure to use neb-cd512, not neb-wipe!).

It is invoked with the disk name as parameter, by root:

# neb-cd512 cd0

Now as the disklabel is in 512 b/s format, accessing the CD is as easy as:

# cgdconfig cgd1 /dev/cd0d /etc/cgd/image
# mount -o ro /dev/cgd1a /mnt

Note that the cgd MUST be mounted read-only or you'll get illegal command errors from the cd(4) driver which can in some cases make even mounting a CD-based cgd impossible!

Now we're done! Enjoy your secure CD!

# ls /mnt

Remember you have to reverse all steps to remove the CD:

# umount /mnt
# cgdconfig -u cgd1
# eject cd0

14.5. Suggestions and Warnings

You now have your filesystems encrypted within a cgd. When your machine is shut down, the data is protected, and can't be decrypted without the passphrase. However, there are still some dangers you should be aware of, and more you can do with cgd. This section documents several further suggestions and warnings that will help you use cgd effectively.

  • Use multiple cgd's for different kinds of data, one mounted all the time and others mounted only when needed.

  • Use a cgd configured on top of a vnd made from a file on a remote network fileserver (NFS, SMBFS, CODA, etc) to safely store private data on a shared system. This is similar to the procedure for using encrypted CDs and DVDs described in Section 14.4, “Example: encrypted CDs/DVDs”.

14.5.1. Using a random-key cgd for swap

You may want to use a dedicated random-key cgd for swap space, regenerating the key each reboot. The advantage of this is that once your machine is rebooted, any sensitive program memory contents that may have been paged out are permanently unrecoverable, because the decryption key is never known to you.

We created a temporary cgd with a random key when scrubbing the disk in the example above, using a shorthand cgdconfig -s invocation to avoid creating a parameters file.

The cgdconfig params file includes a randomkey keygen method. This is more appropriate for "permanent" random-key configurations, and facilitates the easy automatic configuration of these volumes at boot time.

For example, if you wanted to convert your existing /dev/wd0b partition to a dedicated random-key cgd1, use the following command to generate /etc/cgd/wd0b:

# cgdconfig -g -o /etc/cgd/wd0b -V none -k randomkey blowfish-cbc

When using the randomkey keygen method, only verification method "none" can be used, because the contents of the new cgd are effectively random each time (the previous data decrypted with a random key). Likewise, the new disk will not have a valid label or partitions, and swapctl will complain about configuring swap devices not marked as such in a disklabel.

In order to automate the process of labeling the disk, prepare an appropriate disklabel and save it to a file, for example /etc/cgd/wd0b.disklabel. Please refer to disklabel(8) for information about how to use disklabel to set up a swap partition.

On each reboot, to restore this saved label to the new cgd, create the /etc/rc.conf.d/cgd file as below:

swap_device="cgd1"
swap_disklabel="/etc/cgd/wd0b.disklabel"
start_postcmd="cgd_swap"

cgd_swap()
{
	if [ -f $swap_disklabel ]; then
		disklabel -R -r $swap_device $swap_disklabel
	fi
}

The same technique could be extended to encompass using newfs to re-create an ffs filesystem for /tmp if you didn't want to use mfs.

14.5.2. 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 above, 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 file-based encryption tools like gpg can be one way of addressing this issue, but make sure you have all the keys and tools you need to 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 /dev/kmem grovellers. Taking other system security steps, such as running with elevated securelevel, is highly recommended.

Once the cgd volumes are mounted as normal filesystems, their contents are accessible like any other file. Take care of file permissions and ensure your running system is protected against application and network security attack.

Avoid using suspend/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 suspend-to-disk memory image on the hard disk later, the whole point of using cgd is lost.

14.6. Further Reading

The following resources contain more information on CGD:

Bibliography

[smackie-cgd] NetBSD CGD Setup. Stuart Mackie.

[nycbug-cgd] I want my cgd aka: I want an encrypted pseudo-device on my laptop.

[elric-cgd] The original paper on The CryptoGraphic Disk Driver. Roland Dowdeswell and John Ioannidis.

[biancuzzi-cgd] Inside NetBSD's CGD - an interview with CGD creator Roland Dowdeswell. Biancuzzi Federico.

[hubertf-cgd] CryptoGraphicFile (CGF), or how to keep sensitive data on your laptop. Feyrer Hubert.