Encrypted Root Filesystem in Gentoo SUMMARY: The basic idea is to boot off the gentoo installer cd, prepare encrypted partion(s) (except for boot where the kernel image and intrd will live), format and mount the encrypted partition(s), prepare the system on it and finally prepare the kernel and initrd. These steps pretty much follow the vanilla gentoo installation, but deviate when it comes to preparing the disks, and preparing initrd. You should be familiar with a vanilla gentoo installtion before attempting the following steps: http://www.gentoo.org/doc/en/handbook/index.xml Most of the work is in preparing initrd. There are a couple of suggestions on the web for doing this --- see the following urls: 1) http://luks.endorphin.org/gentoo 2) http://gentoo-wiki.com/SECURITY_FileSystem_Encryption_without_ROOT The recipe described here for constructing initrd differs from these references in that this recipe is more manual (I don't use LUKS or genkernel and write linuxrc from scratch), and I use busybox to populate the filesystem in initrd. I'm not sure that there is any advantage of one method over another. I like doing things manually because I feel I understand the system better and have more confidence in what I've set up. HOWTO: ---------------------------------------------------------------- 1. Boot off the gentoo installation CD. I used 2005.1. ---------------------------------------------------------------- 2. Partition the drive(s) using fdisk. Here's what I did with a 20 gig drive in vmware: Device Start End Blocks Id System /dev/hda1 1 518 244723 83 Linux /dev/hda2 519 44384 20726685 83 Linux Notice I didn't set aside a swap partition. You can but then you need to encrypt it separately, otherwise information could be read cleartext out of the swap area. Rather, we'll use a swap file in /dev/hda2 which will be encrypted. The boot partition will live on /dev/hda1 which will not be encrypted. ---------------------------------------------------------------- 3. Let's make it as difficult as possible to find the encrypted filesystem on /dev/hda2. Before encrypting/formatting, let's shred the device: shred /dev/hda2 This will take a long time, so you may just want to lay down some random data: dd if=/dev/urandom of=/dev/hda2 ---------------------------------------------------------------- 4. For the next step, make sure you've got networking up. See the Gentoo Handbook. Or at the very least: ifconfig eth0 xxx.xxx.xxx.xxx route add default gw yyy.yyy.yyy.yyy echo "nameserver zzz.zzz.zzz.zzz" >> /etc/resolv.conf ---------------------------------------------------------------- 5. We now need to map /dev/hda2 through dm-crypt. I've written a little script which makes this straightforword. Get it using: wget http://www.virtualblueness.net/~blueness/encryptedroot/setup.sh Basically this script first inserts the needed module: modprobe dm-crypt modprobe serpent The dm-crypt module is necessary. The second module inserts the cipher of your choice. (You could substitute serpent with twofish, sha512, etc. If anyone knows studies on which cipher is better, please email me. As far as I know, they are all uncracked.) The userland utilites we'll need are on the installation cd: hashalot reads in a passphrase and generates a hash blockdev returns the size of the device in blocks dmsetup is the userland utility for setting up the map Again, my setup.sh script makes their use simple. Edit it with nano if you want to change the device or the cipher and hash for the encrypted filesystem. When ready, run it: sh setup.sh Enter a strong passphrase. (Google for guidelines in choosing a strong passphrase.) REMEMBER THE PASSPHRASE!!! If you forget it, you will loose your data. There is no way to reset it. Let me say this again. If you loose the passphrase, you will no longer be able to access your data. If you want to remove the mapping, you can delete it and start over again by doing dmsetup remove hda2 ---------------------------------------------------------------- 6. Confirm that you've created the mapped devices: ls /dev/mapper should return hda2. Now, put down a filesystem. I like ext3: mke2fs -j /dev/mapper/hda2 ---------------------------------------------------------------- 7. Mount it: mount /dev/mapper/hda2 /mnt/gentoo ---------------------------------------------------------------- 8. Also format and mount /dev/hda1 for boot. However, it will not be encrypted: mke2fs -j /dev/hda1 mkdir /mnt/gentoo/boot mount /dev/hda1 /mnt/gentoo/boot ---------------------------------------------------------------- 9. Install stage3 as per a vanilla gentoo installation. If you want to get it from the net, then do cd /mnt/gentoo links2 http://www.gentoo.org/main/en/mirrors.xml Pick a mirror and navigate to the stage3 for your architecture. For example, if your arch is i686, then navigate to releases/x86/2005.1-r1/stages/i686 and download stage3-i686-2005.1-r1.tar.bz2 You'll also want to download the .md5 to do the sumcheck and .asc to verify the gpg signiture. When you are satisfied that you've downloaded an uncorrupted and legitimate tarball, untar it: tar jxvf stage3-i686-2005.1-r1.tar.bz2 ---------------------------------------------------------------- 10. Install portage as per a vanilla gentoo installation. To get it from the net, do cd /mnt/gentoo/usr links2 http://www.gentoo.org/main/en/mirrors.xml Pick a mirror and navigate to snapshots/portages-.tar.bz2 Again, you want to download the .md5 and .asc and test for corruption or tampering. Finally untar: tar jxvf portages-.tar.bz2 ---------------------------------------------------------------- 11. Chroot into your fledgeling system: mount -t proc none /mnt/gentoo/proc cp -L /etc/resolv.conf /mnt/gentoo/etc/resolv.conf chroot /mnt/gentoo /bin/bash env-update source /etc/profile emerge --metadata You may at this point want to edit /etc/make.conf and change CFLAGS CXXFLAGS MAKEOPTS and USE. The defaults are probably adequate for your needs. ---------------------------------------------------------------- 12. Bring your system up to date emerge -uvDN world etc-update You'll also need to put dmsetup on your system, so emerge device-mapper ---------------------------------------------------------------- 13. Compile the kernel: cp /usr/share/zoneinfo/GMT /etc/localtime emerge gentoo-sources cd /usr/src/linux make menuconfig While there are disadvantages to compiling a monolithic kernel versus a modular one, I prefer the monolithic for two reasons: 1) it is more secure and stable since one cannot insert malicious or bad modules and 2) we won't have to copy modules from /lib/modules into initrd. Thus, when we recompile the kernel we won't have to reconstruct initrd. So, Loadable Module Support [ ] Enable loadable module support Device Drivers Block devices [*] RAM disk support (32000) Default RAM disk size (kbytes) [*] Initial RAM disk (initrd) support Multi-device Support (RAId and LVM) [*] Device mapper support [*] Crypt target support Cryptographi Options -> Turn on everything you need Configure whatever else you'll need in the kernel and then make to make the bzImage. Finally, copy the bzImage to /boot ... cp /usr/src/linux/arch/i386/boot/bzImage /boot/kernel If you want to compare your kernel configuration to one that I know works, get my kernel config: wget http://www.virtualblueness.net/~blueness/encryptedroot/kernel-config ---------------------------------------------------------------- 14. Here's the hard/fun part. We need to construct initrd. You can also just use my own initrd.gz which I constructed following the steps below: wget http://www.virtualblueness.net/~blueness/encryptedroot/initrd.gz Please go easy on my bandwidth!!! 1) First, let's compile a statically linked version of busybox. USE="static" emerge busybox cd /root dd if=/dev/zero of=initrd count=28 bs=1M mke2fs initrd mkdir zzz mount -o loop initrd zzz cd zzz mkdir bin dev etc lib proc sys tmp usr var ln -sf bin sbin cd usr ln -sf ../bin bin ln -sf ../bin sbin cd ../bin cp /bin/busybox . Now we need to create a series of symbolic links to busybox -- one for each of the Unix utilities you'll need. You can see what busybox gives you by doing busybox --help I like creating a link for every possible busybox utility -- I've written a script to do this for you. Download it wget http://www.virtualblueness.net/~blueness/encryptedroot/links.sh and then run it sh links.sh rm links.sh 2) busybox doesn't give us everything we need. In addition we need blockdev, dmsetup, e2fsck (if you're using ext2/3), and hashalot. We'll statically compile these: USE="static" emerge util-linux #For blockdev cp /sbin/blockdev . USE="static" emerge e2fsprogs #For e2fsck cp /sbin/e2fsck . 3a) Unfortunately there is no static USE flag for dmsetup and hashalot. We'll have to do these manually. Let's do hashalot first: emerge hashalot cd /tmp cp /usr/portage/distfiles/hashalot-0.3.tar.gz . tar zxvf hashalot-0.3.tar.gz cd hashalot-0.3 ./configure At this point edit Makefile using nano, look for the CFLAGS line and add -static so that it reads CFLAGS = -g -O2 -static Exit nano and then make. The directory now contains a statically linked version of hashalot. Check using ldd: ldd hashalot Copy it to bin in our initrd: cp hashalot /root/zzz/bin 3b) We need to do the same for dmsetup: emerge device-mapper cd /tmp cp /usr/portage/distfiles/device-mapper-1.01.03.tgz . tar zxvf device-mapper-1.01.03.tgz cd device-mapper.1.01.03 ./configure --enable-static_link make cd dmsetup ldd dmsetup.static #As a check cp dmsetup.static /root/zzz/bin/dmsetup NOTE: Step 2 will leave you with a set of statically linked utilities on your final gentoo filesystem. If this bothers you, and you'd rather have dynamically linked binaries for util-linux and e2fsprogs, then just do the same hack that you did in steps 3a) and 3b) with util-linux and e2fsprogs. Or, you could re-emerge those packages without USE="static" once your system is up. 4) We also need to populate dev, so cd into that directory cd /root/zzz/dev cp -a /dev/* . This is probably overkill and you can certainly be more selective about what device files you create. Even so, this only makes /dev 85k in size and takes up 1476 inodes out of 7168. 5) Next, let's create fstab in /etc. cd ../etc cat << EOF > fstab /dev/ram0 / ext2 defaults 0 0 none /proc proc defaults 0 0 EOF 6) Finally, we need a linuxrc. I've written a skeleton for you which is sufficient, but you may want to modify. Get it: cd /root/zzz wget http://www.virtualblueness.net/~blueness/encryptedroot/linuxrc chmod 755 linuxrc We're done setting the image up. NOTE: If you didn't compile a monolithic kernel, remember to also cp /lib/modules into initrd. ---------------------------------------------------------------- 15. cd out of the mounted image, gzip it and copy it to /boot: cd .. umount zzz gzip -9 initrd cp initrd.gz /boot ---------------------------------------------------------------- 16. We now need to install a bootloader. I prefer grub: 1) emerge grub and configure it emerge grub cd /boot/grub cat << EOF > grub.conf timeout 10 default 0 title gentoo root (hd0,0) kernel /kernel root=/dev/ram0 init=linuxrc initrd /initrd.gz EOF 2) install it onto the MBR grub root (hd0,0) setup (hd0) quit ---------------------------------------------------------------- 17. Let's set a root password: passwd root ---------------------------------------------------------------- 18. Let's set the system fstab. Note this is different than the initrd fstab: cd /etc cat << EOF > fstab /dev/mapper/hda2 / ext3 noatime 1 1 /dev/hda1 /boot ext2 noatime,noauto 1 2 /dev/cdroms/cdrom0 /mnt/cdrom iso9660 noauto,ro 0 0 /dev/fd0 /mnt/floppy auto noauto 0 0 proc /proc proc defaults 0 0 shm /dev/shm tmpfs nodev,nosuid,noexec 0 0 EOF Don't enter a line for the swapfile. The reason is that, in the gentoo init scripts, swap is turned on before the root filesystem is checked for errors. If swapping is done to a file on the root filesystem, the mount will not be able to remount that filesystem read only to run a safe fsck. Rather, we'll add swap in /etc/conf.d/local.start. ---------------------------------------------------------------- 19. We can now reboot into our encrypted filesystem: exit #To leave our chroot environment cd / umount /mnt/gentoo/boot umount /mnt/gentoo/proc umount /mnt/gentoo reboot Make sure to remove the CD. NOTE: When you reboot, you'll get a shell before initrd filesystem is pivoted to /dev/mapper/hda2. You can at that point check the root filesystem or do other maintenance: e2fsck /dev/mapper/hda2 Once you exit the shell, the system will continue booting. ---------------------------------------------------------------- 20. Finish the system off by configuring: edit /etc/conf.d/net.eth0 -> to setup the network emerge syslog-ng -> for a system logger emerge fcron -> for a system cron emerge slocate -> for a system indexer emerge anything else you want. ---------------------------------------------------------------- 21. If you want swap, then create a swapfile in / cd / dd if=/dev/zero of=SWAP count=512 bs=1M mkswap SWAP and add the following line to /etc/conf.d/local.start: swapon /SWAP ---------------------------------------------------------------- 22. To minimize information leak, you can remove /dev/mapper/hda2. This is safe and the filesystem will remain mounted just fine. Add the following line to /etc/conf.d/local.start: dmsetup remove hda2 ---------------------------------------------------------------- Enjoy. Email comments blueness@virtualblueness.net. I'm interested in suggestions for improvement or critiques. Anthony Basile, Ph.D. Chair Information Technology D'Youville College Buffalo NY 14201 (716) 829-8197