Encrypting your laptop with ELI and ZFS

Some time ago, I've given my laptop yet another FreeBSD reinstall - mostly beause I wanted to encrypt its contents (hey, you never know!). It turns out the best way to do this is to use GEOM_ELI. Of course, I can't quite live without ZFS, so the idea was that I have a minimal /boot paritition and everything else lives on ZFS, which is encrypted using ELI.

In order to do this, I first performed a minimal 7.0-RELEASE install, using the following layout:

ad0s2a = 512MB = /
ad0s2b = 2GB = swap
ad0s2d = everything else = /X

Once installed, I rebooted. The idea is to move the install to the swap partition so I could turn ad0s2a into /boot. I used the commands below to do this:

# swapoff -a
# newfs /dev/ad0s2b
# mount /dev/ad0s2b /mnt
# cd /
# tar cf - --one-file-system * | tar xpf - -C /mnt

I edited /mnt/etc/fstab, so it would understand ad0s2b as /, and no swap or anything. Once that was done, I rebooted, and entered '0:ad(0,b)/boot/loader' (note the 'b' !) in the bootprompt, as I wanted to boot from the 'b' slice.

Once I was in my new install, I initialized my ELI encryption on ad0s2d and put a ZFS pool on it (note: the '-s 4096' means use a sector size of 4KB - this speeds ZFS up quite a lot - also, you do not need data authentication by means of '-a algo' as ZFS uses Merkle trees, which already perform the required authentication)

# geli init -b -v -s 4096 /dev/ad0s2b
# zpool create tank ad0s2b.eli


It's now time to create the new /boot and pollute it. Since the bootloader only understands /boot/..., we have to apply symlink magic to ensure our things like 'make installkernel' work correctly afterwards (/boot/... needs to go to ad0s1a:/boot/...)

# newfs /dev/ad0s2a
# mkdir /tank/bootdir
# mount /dev/ad0s2a /tank/bootdir
# cp -Rp /boot /tank/bootdir/
# ln -sf /tank/boot /tank/bootdir/boot

Note: ZFS needs a file '/boot/zfs/zpool.cache' if you attempt to boot from it. By the order of the commands above, it should be created before we are initializing the new /boot, but better make sure it is there or your system will not boot!

Now, edit /tank/boot/loader.conf and ensure it contains the following:

zfs_load="YES"
geom_eli_load="YES"

Note: on my laptop, I need 'hint.kbdmux.0.disabled=1' there as well - otherwise, the ELI password prompt misses keypresses. This appears to be a known issue.

We have to create /tank/bootdir/etc/fstab too, so the loader knows which filesystem to pass to the kernel; put the following in it:

tank / zfs rw 0 0


We have a working /boot now, so let's fill up the ZFS root:

# cd /
# tar cf - --one-file-system * | tar xpf - -C /tank


We need to update the fstab on the ZFS partion now, so edit /tank/etc/fstab and put the following into it (we can use ad0s1b as swap again once the system is rebooted):

tank / zfs rw 0 0
/dev/ad0s2a /bootdir ufs rw 1 1
/dev/ad0s2b swap swap sw 0 0


Final step is to prevent ZFS from re-mounting tank, as it will be used to root filesystem. This can be done by:

# zfs set mountpoint=legacy tank

The previous command probably will give an error regarding being unable to umount - this can be safely ignored.

Finally, reboot, and enjoy your uber-secure ELI-protected ZFS system! You'll probably want to fetch sources and build/install world/kernel, but I'll leave that up to you.

Closing words, I used to following guides to construct this post: http://www.wanda25.de/geli.html on how to initialize ELI, and http://wiki.freebsd.org/ZFSOnRoot on how to place / on ZFS.

Prepare for MADness: The MAD project is finally released!

Back in 1998, I started my largest project ever: the creation of a script language with assorted toolset, specifically designed to create adventure games: the MAD project (even though MAD never stood for anything). One of the main sources of inspiration was Sierra's Creative Interpreter, which was used as the building blocks of the famous King's Quest and Quest for Glory series of adventure games.

In its final days, MAD was taken over by Nunzio Hayslip and Javier Gonzales who substantially rewrote the engine and switched to the Lua language instead of the custom language, and made numerous improvements. Their work has always been available at SourceForge - the release on my website is the older versions of MAD, which were used in the first two demos of the Hero6 Project.

I originally intended to release my MAD sources on 1 October 2008, as this would be exactly 10 years after the first recorded MAD log entry. However, as real life took the better of me, this was delayed until today, so here it is: the complete MAD project, licensed under the GPLv2! (note that the included demo projects have other licenses due to their content, refer to the readme.txt file in the MAD source distribution for more details)

It's worth noting that the Lua version of MAD is thoroughly discussed in the book "Game Programming with Python, Lua, and Ruby" by Tom Gutschmidt (Even though my name was misspelled, but then again, you get used to that :-). Even though I had little involvement in the Lua version of MAD, most ideas of the previous versions are still present in the Lua version - so I guess there were my 5 minutes of fame!

MAD has been an interesting voyage for me, and I dearly hope it will serve as an inspiration for other people. It is available at the projects page. Enjoy!

I'm a big boy now...

Last Thursday, I held my graduation presentation and associated defense. There were a lot of people present during my presentation, which was something I didn't quite expect. Yet, it was quite nice to have such a large crowd listening to what I had to say :-)

The presentation went very well: I didn't see any puzzeled faces in the audience! After the presentation, there were some questions from the public, and finally, the graduation committee had their turn to ask questions in private, which lasted about an hour. There were only one or two very difficult questions, which I believe I managed pretty well. Finally, the committee started discussing the mark in private, yet I had a pretty good feeling already.

After 20 minutes or so, I was called in and congratulated: I passed, with a mark of 70%. As you can imagine, while the result was kind of expected, I was so relieved... I GRADUATED! :-D

Thus, I'm a big boy now: I've obtained a Master of Science (M.Sc) / Dutch ingenieur (ir.) degree, which is about as good as it gets. Next stop is the world of the working... and a brave new world 't is!

Compaq Evo T30 hackery

Yeah, I know things have been pretty silent here. Mostly because I'm quite busy with my graduation route, and things are turning out pretty well there!

Anyway, a few months ago, I acquired a Compaq Evo T30 thinclient. After playing with it for a fair bit, I found out I could run Linux on it - but guess again: Linux 2.4.xx works fine, but 2.6.yy doesn't (the onboard NIC doesn't work well, you'll be getting device resets all over).

To this end, I decided if I could get FreeBSD to run on it, as the Linux community seems to be focussed mostly on Evo T20's. Anyway, I found that you can netboot the machines by repeatingly tapping the 'P' key once you turn it on. This was designed to update the device: it does DHCP on ports 10067/10068, and will try TFTP on 10069. I figured I first had to get my FreeBSD machine to properly feed it updates, and to this end, I used the following dhcpd.conf file:

authorative;
ddns-update-style none;

subnet 10.0.0.0 netmask 255.255.255.0 {
allow unknown-clients;
range dynamic-bootp 10.0.0.1 10.0.0.254;
next-server 10.0.0.1;
filename "bootp.bin";
}

And in order to start dhcpd, a simple 'dhcpd -p 10067' will do it. You can just rename the tftp port to 10068 in your /etc/services, uncomment the tftpd line in /etc/inetd.conf and start inetd.

What's this mysterious bootp.bin file? That's the firmware it tries to load. For my device, I got a file named 'P472_3CMe72.bin' and that worked fine, it upgraded my Windows CE to some other Windows CE version. Great! Now, to business!

I wrote a small tool, bsd-ce (available in the various projects page), which given a BSD ELF file constructs a NK.BIN Windows CE kernel image file, including some glue to make the kernel happy. In order to put this in the firmware, I hackishly used this script (this works because NK.BIN files always begin with ASCII text 'B000FF')

#!/bin/sh

set -e

IMG="P472_3CMe72.bin"
OFFS=`strings -td $IMG|grep B000FF|awk '{print $1}'`

# fetch everything before the CE image
dd if=$IMG bs=$OFFS count=1 of=tmp

# add the BSD NK-ified
cat tmp nk.bin > tmp.2

# add everything else
SZ=`ls -ld tmp.2|awk '{print $5}'`
dd if=$IMG of=tmp.3 bs=$SZ skip=1
cat tmp.2 tmp.3 > bootp.bin

Well, that's all nice, but the kernel crashes. After some debugging, I found that this was since the Evo does not provide any BIOS services, so querying memory bluntly fails! To this end, I wrote a kernel patch, if you apply this patch and put 'options PHYSMEM_SIZE="16384"', you will force the kernel to assume there is 16MB of memory in the device and it will boot happily. However, it crashed somewhere else - this is because while the Evo claims to support BIOS32 functions, trying to use them will cause a solid hang. To this end, I updated the bsd-ce loader to pass options to the kernel, requesting that it should do direct PCI access. And voila, it works, and FreeBSD 8-CURRENT supports the network device just fine!

So, what do you have to do to make this work? Use the PHYSMEM_SIZE patch and build a custom kernel which forces memory to 16MB (or whatever your Evo contains), force hints to be in the kernel (otherwise serial devices won't be found), use bsd-ce to nk.bin-ify the kernel and use the script above to create the bootp.bin file which you can in turn put inside your device.

Note: The USB controller in the Evo (Compaq ZFMicro) contains a bug which will give corrupted transfers! As far as I know, there is no workaround on BSD (there is on Linux), but I hope to give this a go once I'm more familiar with the problem - the Linux code just seems to add delays which seem to make the chip happy. If you have any idea what is actually wrong with the device, please contact me!

Finally, I'd like to stress that this project would not have been possible without the Linux Winterm hacking project! My big thanks for publicizing the information on there, which allowed me to quickly figure out why my Evo kept crashing on the BIOS32 stuff!

Beware of XFX/NetCell Revo!

As my hardware page states, I've got an XFX (previous NetCell) Revo64 PCI32 SATA RAID controller. Basically, this is a 3-channel SATA-I card which can do hardware RAID3. As they are very cheap, I once decided to get one for my colo box, but as they have no usuable (ie. non-Windows) management tools, I've only kept it for playing purposes.

Either way, as I recently added juicy 3 * 500GB Western Digital disks to my system, I decided to give this controller a try. It struck me that the performance is really good. However, the paranoid person that I am, I decided to yank out a disk and see what it does...

There is nothing visible from the OS - only the BIOS-thing of the controller usually says "All is well" and instead said "Drive(s) needs service" or something simular. FreeBSD could still find all my data, so that was nice. However, I tried to do a rebuild of the array - but you cannot do this from either FreeBSD or from the BIOS, so I tried the supplied Windows tool.

The tool claims it's rebuilding, but after an hour or so, it's still at 0%. Rebooting the machine shows that the RAID BIOS thinks the volume is being rebuild, whereas in fact it's not. Bummer - so rebuilding is broken! Nothing I tried worked - but when I reassigned the formerly unplugged disk to a new RAID volume, hell broke loose: the bloody controller *erased* my RAID3 array configuration (array 0), and created a new RAID0 array (array 1) of the disk, which was definately not what I asked for (or what the menus told me it would do)

Anyway, this wasn't fixable - so I decided to use the XFX thing as a simple SATA controller with a single disk - it's good enough for that. But my warning to all is: If you have an XFX, *TRY* to rebuild the array. I haven't lost anything valuable, for some reason I expected the controller wouldn't work that well ... Apperantly, it's no wonder NetCell went broke.

Concluding, I'll stick to my main point: if you care about your data, get an Areca. They're expensive, but definately worth it!