--- /dev/null
+Creating a minimal file system to ease the boot process
+=======================================================
+
+:date: 1970-01-01 00:00
+:category: System Administration
+:tags: initramfs, boot, luks, gpg, ssh
+:authors: Maximilian Friedersdorff
+:summary: Booting a system with full disk encryption can be tricky.
+:status: draft
+
+Context
+-------
+
+My personal systems use full disk encryption according to the scheme
+`LVM on LUKS`_. This works great, but obviously requires some way of supplying
+(or unlocking) the decryption key during the early boot process.
+
+Passphrase
+__________
+
+Using a passhrase to protect the decryption key is easy, provided the user is
+sitting in front of the machine. If the machine needs to be started remotely,
+then it becomes necessary to install a SSH server like dropbear_, or decrypt the
+LUKS partition in some other way.
+
+Key File
+________
+
+One can use a key file that either contains the decryption key directly, or just
+contains a passphrase that unlocks the decryption key. This requires the key to
+be available during the early boot process.
+
+This is tricky, because if it
+exists in plaintext on the machine it is supposed to unlock, then there is not
+much point in encrypting in the first place. If instead the key is on a
+different machine, the key has to be transmitted accross the network, and the
+other machine has to be on and running. Alternatively the key might be stored
+on a USB device and carried on one's person at all times, but USB devices can be
+unreliable. This is also sensitive to loss.
+
+Solution
+________
+
+I use a Yubikey (a USB SmartCard_) to store my GPG key. This enables a
+convenient compromise.
+
+The solution I propose is to store a GPG encrypted key file on the encrypted
+machine. When starting the machine remotely, the key can be transmitted to the
+remote client, decrypted on the SmartCard_ and transmitted back to the encrypted
+machine. Transmission happens over SSH authenticated with a GPG authentication
+key stored on the same SmartCard_.
+
+When starting the machine locally, the decryption takes place directly on the
+SmartCard_ itself.
+
+This has an additional benefit. The SmartCard_ is protected by a passphrase
+forcing the use of two different factors to decrypt the drive.
+
+Required Software
+_________________
+
+To get all of this to work, several pieces of software need to be available
+during the early boot process:
+
+* GnuPG, preferably V2.1 or above
+* pcscd, the PC/SC Smart Card Daemon
+* dm-crypt
+* LVM, Logical Volume Manager
+* SSH server, for instance dropbear_
+
+Some of these can be built with static linking. This makes their inclusion in
+an initramfs relatively straightforward. However neither pcscd nor recent
+version of GnuPG can be built this way. They must be dynamically linked to
+at least glibc. Including dynamic executable in an initramfs is substantially
+more tedious as all of their library dependencies have to be included also.
+
+Initramfs vs ?
+______________
+
+Building an initramfs that can do these things is tedious. Existing automated
+tools that build an initramfs would require substantial additions to make this
+possible. Doing it manually or building an automated tool from scratch is lots
+of work. An initramfs like this will also be fairly large (since it contains
+lots of libraries) and has to be loaded in it's entirety at boot time.
+
+Instead I will build a minimal, self hosted root file system. This way I can
+use a proper package manager to manage the file system, I don't have to worry
+too much about it's overall size (it doesn't all have to be read at boot
+time) and I have easy access to any package included in the distribution I base
+this on. I will call this an initfs.
+
+I use gentoo on all of my personal systems, so I will base the initfs on gentoo
+also. An initramfs is typically built from source anyway, so this makes sense.
+This is also an opportunity to play with alternative libc's like uClib-ng_ or
+musl_ which gentoo has some support for.
+
+Building the initfs
+-------------------
+
+Minimal Gentoo
+______________
+
+
+I start by building a very minimal Gentoo system. Initially I follow the amd64
+handbook_. All of this is done on a fully installed gentoo system. As such the
+network is already set up, the bootloader is installed, the kernel is configured
+and compiled and the disk is already partially partitioned.
+
+First I add an additional small partition that is *outside* the encrypted LUKS
+volume, formatting it to ext4 and mounting it somewhere convenient::
+
+ $ sudo fdisk /dev/sda
+ Password:
+
+ Welcome to fdisk (util-linux 2.33.1).
+ Changes will remain in memory only, until you decide to write them.
+ Be careful before using the write command.
+
+
+ Command (m for help): n
+ Partition number (2-4,7-128, default 2): 2
+ First sector (534528-500118158, default 534528):
+ Last sector, +/-sectors or +/-size{K,M,G,T,P} (534528-83509247, default 83509247): +1G
+
+ Created a new partition 2 of type 'Linux filesystem' and of size 1 GiB.
+
+ Command (m for help): p
+ Disk /dev/sda: 238.5 GiB, 256060514304 bytes, 500118192 sectors
+ Disk model: SanDisk SD8SNAT2
+ Units: sectors of 1 * 512 = 512 bytes
+ Sector size (logical/physical): 512 bytes / 512 bytes
+ I/O size (minimum/optimal): 512 bytes / 512 bytes
+ Disklabel type: gpt
+ Disk identifier: 699BC6B3-E694-4D9B-AE65-2C7101253C99
+
+ Device Start End Sectors Size Type
+ /dev/sda1 2048 534527 532480 260M EFI System
+ /dev/sda2 534528 2631679 2097152 1G Linux filesystem
+ /dev/sda5 83509248 84557823 1048576 512M Linux filesystem
+ /dev/sda6 84557824 500117503 415559680 198.2G Linux filesystem
+
+ Command (m for help): w
+ The partition table has been altered.
+ Syncing disks.
+
+ $ sudo mkfs.ext4 /dev/sda2
+ mke2fs 1.45.0 (6-Mar-2019)
+ Discarding device blocks: done
+ Creating filesystem with 262144 4k blocks and 65536 inodes
+ Filesystem UUID: 97904c89-51e3-4a6b-b3f3-24bb5f083f60
+ Superblock backups stored on blocks:
+ 32768, 98304, 163840, 229376
+
+ Allocating group tables: done
+ Writing inode tables: done
+ Creating journal (8192 blocks): done
+ Writing superblocks and filesystem accounting information: done
+
+ $ sudo mount /dev/sda2 /mnt/initfs
+
+I then move on to installing a stage3 tarball. The main system will be in a
+chroot anyway, so a No-multilib (pure 64-bit) system is appropriate here and will
+save some small amount of space. For a first attempt I choose the uclibc stage3
+tarball. I download the file tarball and it's signed DIGESTS file, verify the
+DIGESTS file and finally check the hash::
+
+ # cd /mnt/initfs
+ # wget http://distfiles.gentoo.org/releases/amd64/autobuilds/20190405/uclibc/stage3-amd64-uclibc-vanilla-20190405.tar.bz2
+ .
+ .
+ .
+ # wget http://distfiles.gentoo.org/releases/amd64/autobuilds/current-stage3-amd64-uclibc-vanilla/stage3-amd64-uclibc-v
+ anilla-20190405.tar.bz2.DIGESTS.asc
+ .
+ .
+ .
+ # gpg --verify stage3-amd64-uclibc-vanilla-20190405.tar.bz2.DIGESTS.asc
+ gpg: Signature made Sat 06 Apr 2019 07:13:22 BST
+ gpg: using RSA key 534E4209AB49EEE1C19D96162C44695DB9F6043D
+ gpg: Good signature from "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" [unknown]
+ gpg: WARNING: This key is not certified with a trusted signature!
+ gpg: There is no indication that the signature belongs to the owner.
+ Primary key fingerprint: 13EB BDBE DE7A 1277 5DFD B1BA BB57 2E0E 2D18 2910
+ Subkey fingerprint: 534E 4209 AB49 EEE1 C19D 9616 2C44 695D B9F6 043D
+ # sha512sum -c ./stage3-amd64-uclibc-vanilla-20190405.tar.bz2.DIGESTS.asc
+ stage3-amd64-uclibc-vanilla-20190405.tar.bz2: OK
+ stage3-amd64-uclibc-vanilla-20190405.tar.bz2: FAILED
+ sha512sum: stage3-amd64-uclibc-vanilla-20190405.tar.bz2.CONTENTS: No such file or directory
+ stage3-amd64-uclibc-vanilla-20190405.tar.bz2.CONTENTS: FAILED open or read
+ sha512sum: stage3-amd64-uclibc-vanilla-20190405.tar.bz2.CONTENTS: No such file or directory
+ stage3-amd64-uclibc-vanilla-20190405.tar.bz2.CONTENTS: FAILED open or read
+ sha512sum: WARNING: 14 lines are improperly formatted
+ sha512sum: WARNING: 2 listed files could not be read
+ sha512sum: WARNING: 1 computed checksum did NOT match
+
+Some things to note: I verified the fingerprint of the "Gentoo Linux Release
+Engineering" GPG key from the official `gentoo website`_, accessed via https.
+I can be reasonably confident that that is proper. The error messages in the
+output of sha512sum exist because there are some other files listed in the
+DIGESTS, because for each file there is also a WHIRLPOOL hash and there is an
+inline GPG signature in the file.
+
+Extracting the tarball::
+
+ # tar xpf stage3-*.tar.bz2 --xattrs-include='*.*' --numeric-owner
+
+And editing the ``/etc/portage/make.conf`` to have sensible values::
+
+ # cat etc/portage/make.conf
+
+The portage tree is definitely *not* required during boot and is quite large. I
+just mount it from the host system and chroot::
+
+ # mount --types proc /proc proc
+ # mount --rbind /sys sys
+ # mount --make-rslave sys
+ # mount --rbind /dev dev
+ # mount --make-rslave dev
+ # mount --rbind /usr/portage usr/
+ # mkdir usr/portage
+ # mount --rbind /usr/portage usr/portage
+ # mount --make-rslave usr/portage
+ # chroot /mnt/initfs /bin/bash
+ # source /etc/profile
+ # export PS1="(chroot) ${PS1}"k
+
+Because I am building a *minimal* gentoo system, and because I will be writing
+my own init script anyway, I can remove the installed init system::
+
+ (chroot) # emerge -C openrc virtual/service-manager netifrc
+ (chroot) # echo 'virtual/service-manager' >> /etc/portage/package.mask
+ (chroot) # emerge -av --depclean
+
+Replacing openssh with dropbear::
+
+ (chroot) # emerge -C openssh
+ (chroot) # emerge -av dropbear
+
+Updating the whole system::
+
+ (chroot) # emerge -avuDN --with-bdeps y world
+
+
+
+
+.. _`LVM on LUKS`: https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_Entire_System#LVM_on_LUKS
+.. _dropbear: https://matt.ucc.asn.au/dropbear/dropbear.html
+.. _SmartCard: https://wiki.gnupg.org/SmartCard
+.. _UClib-ng: https://uclibc-ng.org/
+.. _musl: https://www.musl-libc.org/
+.. _handbook: https://wiki.gentoo.org/wiki/Handbook:AMD64
+.. _gentoo website: https://www.gentoo.org/downloads/signatures/