Back to Article Listing

I want my cgd

aka: I want an encrypted psuedo-device on my laptop

cgd = cryptographic device driver

(snipped from the Overview in the cgd documentation on NetBSD.org)

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.

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.

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.

Roland C. Dowdeswell and NetBSD has made this a relatively easy task. The cgd docs, mentioned above, is good. These are my notes on how I implemented cgd.

I have done loopback devices on linux PCs, so I understood the basics. Also, a while back, I attended a talk by Mr. Dowdeswell at NYCBUG. His cryptographic device driver (cgd) was presented as a better alternative. The psuedo-device is included with NetBSD 2.0, which was released in December 2004. It was not long after that I wiped the hard drive on my notebook and installed the latest version of NetBSD. You do not have to start fresh, as the docs point out; I just chose to.

Prep

My approach was to create a small partition for NetBSD and get a good working system before I complicated it with cgd. During the initial operating system install, I prepared most of the hard drive to be used later as the encrypted drive (wd0e, 15g as fstype=ccd) and let NetBSD create wd0a (4g fstype=4.2BSD) for itself. That is more than enough room for a working system. Frankly, I was not sure if/when I would actually get around to creating the encrypted device, so I used more headroom that was necessary. When I started writing Section 3, I was only using about one third of wd0a, so obviously, you could get by with a lot less.

disklabel wd0
#        size    offset     fstype [fsize bsize cpg/sgs]
 a:   8086365        63     4.2BSD   1024  8192     0  # (Cyl.      0*-   8557*)
 b:    262710   8086428       swap                     # (Cyl.   8557*-   8835*)
 c:  39070017        63     unused      0     0        # (Cyl.      0*-  41343)
 d:  39070080         0     unused      0     0        # (Cyl.      0 -  41343)
 e:  30720942   8349138        ccd                     # (Cyl.   8835*-  41343)

After I had the laptop in a solid working state, I turned back to the documentation. On of the first things you read is; 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

I did not compile my present kernel (GENERIC_LAPTOP #0), so I can not say for certain what is in it. To know for sure, I need to download the src and compile my own. As instructed, I untarred syssrc.tgz to /usr/src after downloading. This took a little while. When that finished, I checked the /usr/src/sys/arch/i386/conf/GENERIC_LAPTOP for cgd, and confirmed it is commented out by default. I will need to compile a new kernel and I will use this config as the base. To keep things very simple I will only change the cgd flag. I can tune the kernel later, if needed.

Here are my steps.. yours may differ slightly (my computer is i386, and I chose the laptop config as base). Also, I wrote 'vi' in step 3. The is the default editor in NetBSD, but you can use any editor.

cd /sys/arch/i386/conf
cp GENERIC_LAPTOP [MYCONF] (whatever you want to name it)
vi [MYCONF] (uncomment "pseudo-device   cgd     4 ")
config [MYCONF]
cd ../compile/[MYCONF]
make depend
make
cp /netbsd /netbsd.old
cp /sys/arch/i386/compile/[MYCONF]/netbsd /
reboot

OK, now I have new kernel with cgd enabled, and plenty of drive space to play with.

Create

I started by 'scrubbing' the big blank area of my hard drive. This is not to make it clean. On the contrary, this is to make it dirty and noisy. This will help to camouflage the parts of the drive that are used later.

cgdconfig -s cgd0 /dev/wd0e aes-cbc 128 < /dev/urandom
dd if=/dev/zero of=/dev/rcgd0d bs=32k
cgdconfig -u cgd0

The second step took a little more than 1/2 hour to do on my P3-800 with 384m RAM.

Now, I actually generate the parameters file and create the device. First I created the working directory, and, while I was there, I created the cgd.conf file.

mkdir /etc/cgd
chmod 700 /etc/cgd
echo 'cgd0    /dev/wd0e' > /etc/cgd/cgd.conf
cgdconfig -g -V disklabel -o /etc/cgd/wd0e aes-cbc 256
cgdconfig -V re-enter cgd0 /dev/wd0e

I entered a passphrase (twice) and the device (cgd0) is created. The system sees it as if I added a new hard drive.

Now I have to partition it and create file systems. The next few steps are fdisk, disklabel, newfs:

I first tried disklabel but it complained "Invalid signature in mbr record" so I tried fdisk and it, too, found no magic in sector 0. As I ran fdisk, I accepted all the defaults. I just wanted the last line "Should we write new partition table? [n] y"

fdisk -u cgd0
fdisk: primarypartition table invalid, no magic in sector 0
Disk: /dev/rcgd0d
NetBSD disklabel disk geometry:
cylinders: 15000, heads: 1, sectors/track: 2048 (2048 sectors/cylinder)
total sectors: 30720942

BIOS disk geometry:
cylinders: 1023, heads: 255, sectors/track: 63 (16065 sectors/cylinder)
total sectors: 30720942

Do you want to change our idea of what BIOS thinks? [n]

Partition table:
0: <UNUSED>
1: <UNUSED>
2: <UNUSED>
3: <UNUSED>
Bootselector disabled.
Which partition do you want to change?: [none]

We have not written the MBR back to disk yet.  This is your last chance.
Partition table:
0: <UNUSED>
1: <UNUSED>
2: <UNUSED>
3: <UNUSED>
Bootselector disabled.
Should we write new partition table? [n] y

I had mapped out, in advance, what was to go into the 15gig crypt. Yours will be different. It helped me to have it written down as a reference when doing the disklabel.

a    swap    250
b    /etc    250
c    /home   8000
e    /root   1000
f    /tmp    500
g    /usr    3000
h    /var    2000
------------------------------
total        15000

Here is my conversation with disklabel:

disklabel -I -i cgd0
partition> a
Filesystem type [?] [unused]: swap
Start offset ('x' to start after partition 'x') [0c, 0s, 0M]: 0
Partition size ('$' for all remaining) [0c, 0s, 0M]: 250M
 a:    512000         0       swap                     # (Cyl.      0 -    249)
partition> b
Filesystem type [?] [unused]: 4.2BSD
Start offset ('x' to start after partition 'x') [0c, 0s, 0M]: a
Partition size ('$' for all remaining) [0c, 0s, 0M]: 250M
 b:    512000    512000     4.2BSD      0     0     0  # (Cyl.    250 -    499)
partition> c
Filesystem type [?] [unused]: 4.2BSD
Start offset ('x' to start after partition 'x') [0c, 0s, 0M]: b
Partition size ('$' for all remaining) [0c, 0s, 0M]: 8000M
 c:  16384000   1024000     4.2BSD      0     0     0  # (Cyl.    500 -   8499)
partition> e
Filesystem type [?] [unused]: 4.2BSD
Start offset ('x' to start after partition 'x') [0c, 0s, 0M]: c
Partition size ('$' for all remaining) [0c, 0s, 0M]: 1000M
 e:   2048000  17408000     4.2BSD      0     0     0  # (Cyl.   8500 -   9499)
partition> f
Filesystem type [?] [unused]: 4.2BSD
Start offset ('x' to start after partition 'x') [0c, 0s, 0M]: e
Partition size ('$' for all remaining) [0c, 0s, 0M]: 500M
 f:   1024000  19456000     4.2BSD      0     0     0  # (Cyl.   9500 -   9999)
partition> g
Filesystem type [?] [unused]: 4.2BSD
Start offset ('x' to start after partition 'x') [0c, 0s, 0M]: f
Partition size ('$' for all remaining) [0c, 0s, 0M]: 3000M
 g:   6144000  20480000     4.2BSD      0     0     0  # (Cyl.  10000 -  12999)
partition> h
Filesystem type [?] [unused]: 4.2BSD
Start offset ('x' to start after partition 'x') [0c, 0s, 0M]: g
Partition size ('$' for all remaining) [0c, 0s, 0M]: $
 h:   4096942  26624000     4.2BSD      0     0     0  # (Cyl.  13000 -  15000*)
partition> P
8 partitions:
#        size    offset     fstype [fsize bsize cpg/sgs]
 a:    512000         0       swap                     # (Cyl.      0 -    249)
 b:    512000    512000     4.2BSD      0     0     0  # (Cyl.    250 -    499)
 c:  16384000   1024000     4.2BSD      0     0     0  # (Cyl.    500 -   8499)
 d:  30720942         0     unused      0     0        # (Cyl.      0 -  15000*)
 e:   2048000  17408000     4.2BSD      0     0     0  # (Cyl.   8500 -   9499)
 f:   1024000  19456000     4.2BSD      0     0     0  # (Cyl.   9500 -   9999)
 g:   6144000  20480000     4.2BSD      0     0     0  # (Cyl.  10000 -  12999)
 h:   4096942  26624000     4.2BSD      0     0     0  # (Cyl.  13000 -  15000*)
partition> W
Label disk [n]? y
Label written
partition> Q

I saved out my disklabels to the / directory. You never know when they will come in handy.

disklabel wd0 > /wd0.protofile
disklabel cgd0 > /cgd0.protofile

OK, the 'drive' is installed and partitioned. Now I need to make it writable:

newfs cgd0a
newfs: `a` partition type is not `4.2BSD`

Oh, right.. that was swap. Now the rest:

newfs cgd0b
/dev/rcgd0b: 250.0MB (512000 sectors) block size 8192, fragment size 1024
        using 6 cylinder groups of 41.67MB, 5334 blks, 10304 inodes.
super-block backups (for fsck -b #) at:
     32,  85376, 170720, 256064, 341408, 426752,

And that was repeated for c,e,f,g,h. Now reboot.

During the boot process I was prompted for the passphrase. I typed it in and it was accepted. WHOOT!

Use

Now I have a 15gig working, encrypted, device. I need to fill it up. I wanted to try something harmless first: user homespace. I changed the name of the current homespace, created a new home, mounted the big partition, and copied everything over. Don't forget to chown the users space.

mv /home /home.old
mkdir /home
mount /dev/cgd0c /home
cp -R /home.old /home

<CTRL><ALT><F2> and logged on as a nonroot user and it worked. To make it permanent, I added

/dev/cgd0c      /home   ffs     rw,softdep 0 0

to my /etc/fstab and -rebooted- to make sure everything was working smoothly.

I was a little cautious, so I changed the swap space and /tmp directory in the fstab and rebooted; everything is cool.

That was easy, now the system directories. I cheated my way through these. I created a directory: /mnt/cgd. I would then mount each cgd0x partition to that directory, copy everything over that I wanted in that mountpoint, and then make a new entry in fstab. The only concern I had was moving /usr. It was HUGE due to the src and pkgsrc trees. So, I deleted those two trees (I can untar new ones later) and copied the rest. The copy command needs to be specific so the contents of the directory are copied over and not the directory itself. So, remeber to put the slash after usr in the copy command or you will end up with /usr/usr/ when it is mounted.

cp -R /usr/ /mnt/cgd

Even after removing the src and pkgsrc directories, this took 25 minutes on my laptop. Here's my final fstab:

/dev/wd0a       /       ffs     rw 1 1
/dev/cgd0a      none    swap    sw 0 0
kernfs          /kern   kernfs  rw
procfs          /proc   procfs  rw,noauto
/dev/cgd0c      /home   ffs     rw,softdep 1 2
/dev/cgd0e      /root   ffs     rw,softdep 1 2
/dev/cgd0f      /tmp    mfs     rw 0 0
/dev/cgd0g      /usr    ffs     rw,softdep 1 2
/dev/cgd0h      /var    ffs     rw,softdep 1 2

While you are reading the manual on cgd, do not skip the last section: "13.4. Suggestions and Warnings"

I apologize for any omissions, mistakes, or misleading assumptions.



Copyright © 20050216 genoverly
(db datestamp: 20070821)

nautical_flag_icon
Copyright © 2003-2015 genoverly