Apr 25, 2010

LUKS + dm-crypt rootfs without password via smartcard

While I'm on a vacation, I've decided to try out new distro I've been meaning to for quite awhile - exherbo.
Mostly it's the same source-based gentoo-linux derivative, yet it's not cloned from gentoo, like funtoo or sabayon, but built from scratch by the guys who've seen gentoo and it's core concepts (like portage or baselayout) as quite a stagnant thing.
While I don't share much of the disgust they have for gentoo legacy, the ideas incorporated in that distro sound quite interesting, but I digress...

I don't believe in fairly common practice of "trying out" something new on a VM - it just don't work for me, probably because I see it as a stupid and posintless thing on some subconscious level, so I've decided to put it onto one of my two laptops, which kinda needed a good cleanup anyway.

While at it, I thought it'd be a good idea to finally dump that stupid practice of entering fs-password on boot, yet I did like the idea of encrypted fs, especially in case of laptop, so I've needed to devise reasonably secure yet paswordless boot method.

I use in-kernel LUKS-enabled dm-crypt (with the help of cryptsetup tool), and I need some initrd (or init-fs) for LVM-root anyway.

There are lots of guides on how to do that with a key from a flash drive but I don't see it particulary secure, since the key can always be copied from a drive just about anywhere, plus I don't trust the flash drives much as they seem to fail me quite often.
As an alternative to that, I have a smartcard-token, which can have a key that can't be copied in any way.
Problem is, of course, that I need to see some key to decrypt filesystem, so my idea was to use that key to sign some temporary data which then used to as an encryption secret.
Furthermore, I thought it'd be nice to have a "dynamic key" that'd change on every bootup, so even if anything would be able to snatch it from fs and use token to sign it, that data would be useless after a single reboot.
Initrd software is obviously a busybox, lvm and a smartcard-related stuff.
Smartcard I have is Alladin eToken PRO 64k, it works fine with OpenSC but not via pcsc-lite, which seem to be preferred hardware abstraction, but with openct, which seems a bit obsolete way. I haven't tried pcsc-lite in quite a while though, so maybe now it supports eToken as well, but since openct works fairly stable for me, I thought I'd stick with it anyway.

Boot sequence comes down to these:

  • Mount pseudofs like proc/sys, get encrypted partition dev and real-rootfs signature (for findfs tool, like label or uuid) from cmdline.
  • Init openct, find smartcard in /sys by hardcoded product id and attach it to openct.
  • Mount persistent key-material storage (same /boot in my case).
  • Read "old" key, replace it with a hashed version, aka "new key".
  • Sign old key using smartcard, open fs with the resulting key.
  • Drop this key from LUKS storage, add a signed "new" key to it.
  • Kill openct processes, effectively severing link with smartcard.
  • Detect and activate LVM volume groups.
  • Find (findfs) and mount rootfs among currently-available partitions.
  • Umount proc/sys, pivot_root, chroot.
  • Here comes the target OS' init.

Took me some time to assemble and test this stuff, although it was fun playing with linux+busybox mini-OS. Makes me somewhat wonder about what takes several GiBs of space in a full-fledged OS when BB contains pretty much everything in less than one MiB ;)

And it's probably a good idea to put some early check of /boot partition (hashes, mounts, whatever) into booted OS init-scripts to see if it was not altered in any significant way. Not really a guarantee that something nasty weren't done to it (and then cleaned up, for example) plus there's no proof that actual OS was booted up from it and the kernel isn't tainted in some malicious way, but should be enough against some lame tampering or pranks, should these ever happen.

Anyway, here's the repo with all the initrd stuff, should anyone need it.

Member of The Internet Defense League