I do the same thing, however I'm afraid my answer won't be satisfactory, as for various reasons I went with a completely custom Initramfs.
Instead of GnuPG
, which is an extra binary that has to be included in the Initramfs (and in case of GnuPG-2
, a rather complex one), I simply used what's already there. And that's obviously dm-crypt/LUKS
.
So suppose you have a keyfile
. Preferably one with random data.
# dd if=/dev/urandom of=keyfile count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000189802 s, 2.7 MB/s
Add encryption for it with LUKS (feel free to add your cipher settings of choice).
# truncate -s 2M keyfile.luks
# cryptsetup luksFormat keyfile --header keyfile.luks
WARNING!
========
This will overwrite data on keyfile.luks irrevocably.
Are you sure? (Type uppercase yes): YES
Enter passphrase: bananas
Verify passphrase: bananas
Now you have a keyfile (512 byte) and a keyfile.luks (2MB, which cryptsetup for some reason needs to write the 192k LUKS header). Since the Initramfs will be compressed anyway, that is not too bad (still smaller than GnuPG
).
Now you can decrypt the keyfile:
# cryptsetup luksOpen keyfile --header keyfile.luks lukskey
Enter passphrase for keyfile: bananas
And you have 512 byte of random data in /dev/mapper/lukskey
. (You may write to it if you want to change it, so we could have initialized the file with zeroes earlier.)
# blockdev --getsize64 /dev/mapper/lukskey
512
In Initramfs init
you could then proceed to open the real LUKS volume with it (assuming you added the key first).
cryptsetup --key-file=/dev/mapper/lukskey luksOpen /dev/yourdisk luksyourdisk
cryptsetup luksClose lukskey # clean up
This approach makes GnuPG entirely superfluous, plus you get all LUKS advantages, such as multiple passphrases for the key, cipher of your choice, et cetera. Not to mention a nice (mostly regular) password prompt with multiple retries.
This is more a comment than an answer, sorry. But since you didn't get any replies yet, I wanted to write something anyway.
As for how does it even work:
In the Initramfs you usually have one master process (usually a busybox based /init
shell script) which is responsible for making the root partition available before handing off the boot process to the real init system of your Ubuntu install.
In case of dropbear
in Initramfs, that is a separate process started by /init
. Logging into dropbear you get a shell which is yet another process. All the while the original /init
has to be running and waiting for something, in this case the LUKS password.
So what the /init
script most likely does here, once it started dropbear, is create a named pipe, or fifo, i.e. the /lib/cryptsetup/passfifo
. And then it reads from that named pipe. This read will block until there actually is something to read, so that's how /init
hangs and waits for input.
Then some years later you log into dropbear
and do your echo passphrase > /lib/cryptsetup/passfifo
, at which point /init
wakes up from its slumber and resumes to unlock LUKS and go on with the rest of the boot process.
And that's basically the general idea of how it works. If there is no documentation for it you would have to read the shell script.
As for a GPG encrypted key in Initramfs, I'm sure this is the standard method in Ubuntu somehow, probably to be set up via /etc/crypttab
. Did you check the wiki for a howto?
It certainly would require GPG to be included in the Initramfs. but I outlined an alternative approach here which could be made to work without additional dependencies:
How do I use dm-crypt (LUKS) with GnuPG to use two-factor for FDE?
The problem with this is of course that it is not standard, so while it could be simpler in theory it might actually be harder to set up.
Best Answer
I've just been through this on my new home server, it took a lot of googling and guessing, but I've got it working. I'll attempt to reproduce the steps here. I'm using Ubuntu Server 11.10, and started with a pretty much standard install using encrypted LVM, so I'll just relate the changes I made from there.
Setup:
First, I created a keyfile, just in my home directory:
(you can use a larger blocksize or count for a larger key)
Tell cryptsetup the new key (it's the contents that are important, not the filename):
Then, I formatted my USB flash drive with ext2 and gave it a label. I used a label, so that later I can mount it by label, and replace the USB flash drive in case something goes wrong with it.
(of course, your device will vary)
Now, copy the keyfile to the USB flash drive, owned by root mode 400:
Modify /etc/crypttab. Mine originally contained
which I changed to
Finally, update the initramfs:
It now boots using the keyfile on the USB flash drive. If I remove the flash drive (say, when I go on holiday) it doesn't boot and my data is secure.
If anyone knows how to get it to ask for the passphrase if the USB flash drive is missing, that would be handy as a fallback. Hope this helps, any additions or corrections would be more than welcome!