suspend2+encrypted swap+encrypted root ---------------------------------------------------- The mission is to create an encrypted system using suspend2 that is encrypted also when suspended. I want to thank Nigel Cunningham who made suspend2 available! And to Jary Ruusu who made loop-aes available! The following instructs how to making it work and check if the unencrypted boot partition was changed, so that you know that computer is compromised. I hope you will find this information useful Alon Bar-Lev Components ------------------ - suspend2 from http://www.suspend2.net needed for suspending. - loop-aes from http://sourceforge.net/projects/loop-aes/ needed to encrypt a disk on-the-fly. - aespipe from http://sourceforge.net/projects/loop-aes/ needed to encrypt/decrypt partition. - gpg from http://www.gnupg.org/ needed to handle keys. - perl Digest-SHA1 - genkernel from http://www.gentoo.org needed to build kernel+initrd (optional) - splashutils from http://www.gentoo.org needed if you like to use splash util [gentoo] app-crypt/gnupg -> but you should compile it static manual, no use dev-perl/Digest-SHA1 sys-kernel/genkernel media-gfx/splashutils sys-fs/loop-aes (USE: keyscrub) -> but you should add ebuild for version 3.0c app-crypt/aespipe (USE: static) -> but you should add ebuild for version 2.3b sys-apps/util-linux (USE: crypt static) -> but you should add q patch from loop-aes (sys-apps/util-linux-2.12q-r1) Prerequisites ------------------ - I assume you know how to compile utilities in static mode. - I assume you know how to create initrd. - Make sure you have a working initrd and that you control the linuxrc script. - Make sure you have a working suspend2 environment. - Make sure you have a working loop-aes environment, test loop on files. - Generate gpg keys to be used to encrypt your disk. - Compile gpg, losetup, aespipe as static. - BACKUP YOUR SYSTEM!!! Partitions ------------------ In order to have encrypted root and encrypted swap you need to have at least three partitions on disk. - boot partition unencrypted boot partition, used to hold kernel, initrd, utilities and keyfile. Should be none journal type. - swap partition encrypted swap partition, used for suspending and resuming. Should be at least the size of RAM (-compress). - root partition encrypted root partition, your data may be stored here. Through out this document the following partitions are used, you should replace them with your own: /dev/hda1 - boot /dev/hda2 - swap /dev/hda3 - root Boot partition ------------------ Create the following tree in the boot partition + / + boot-util | + `uname -r` <-- allows to use more than one kernel | + -etc | | - splash <-- boot splash files | + bin | | - gpg.static | | - gpg -> gpg.static | | - losetup.q.static | | - losetup.q -> losetup.static | | - aespipe.static | | - aespipe -> aespipe.static | | - splash_util.static | | - splash_util -> splash_util.static | + lib | + modules | + `uname -r` | + block | - loop.ko - keyfile.gpg <-- your keys goes into here - kernel <-- your kernel - initrd <-- your initrd I use two version of a kernel one for testing and one for production, each have a unique name. If you have encrypted root partition it is most important to do so, since if you make your kernel unbootable or modules misplaced, it is very difficult to recover. losetup patch for loop-aes must be called losetup.q in order to not conflict with busybox's losetup. Root partition ------------------ Since loop device is loaded during initrd, initrd cannot be released. You must create /initrd in you root partition so initrd will remount there. Boot utilities ------------------ Attached are several utilities - mygenkernel used in order to generate my kernels (for gentoo system) the whole process uses files on encrypted partition so modifications to unencrypted partition will not affect. - mygenkernel-commit used in order to commit debug kernel and compile a production kernel. - mygenkernel.conf configuration. - digest-dir used in order to calculate a digest of all files in a specific directory. should be executed during startup or after resume. - mark-boot-digest mark current /boot partition digest as base. - check-boot-digest check current boot digest against base. - check-boot-digest-service execute check-boot-digest as gentoo service Put in /usr/local/share/boot-scripts Run create-links so that links will be created. Compile your kernel --------------------- - Compile your kernel with suspend2 support, initrd support and NO loop device module. - Create initrd with the attached linuxrc script. - Compile loop-aes module [gentoo] Copy default sys-kernel/gentoo-sources into new ebuild (eg. gentoo_suspend2_test-sources-2.6.11-r9.ebuild) and modify so suspend2 will be merged. [..snip..] -inherit kernel-2 +inherit kernel-2 eutils [..snip..] +SUSPEND2_VERSION="2.1.9" +SUSPEND2_TARGET="${PV/_/-}" +SUSPEND2_SRC="software-suspend-${SUSPEND2_VERSION}-for-${SUSPEND2_TARGET}" +SUSPEND2_URI="http://www.suspend2.net/downloads/all/${SUSPEND2_SRC}.tar.bz2" [..snip..] -SRC_URI="${KERNEL_URI} ${GPV_SRC} ${ARCH_URI}" +SRC_URI="${KERNEL_URI} ${GPV_SRC} ${ARCH_URI} ${SUSPEND2_URI}" [..snip..] +src_unpack() { + kernel-2_src_unpack + + cd ${WORKDIR} + unpack ${SUSPEND2_SRC}.tar.bz2 + + cd ${S} + EPATCH_EXCLUDE="apply unapply ToDo" \ + EPATCH_FORCE="yes" \ + EPATCH_SUFFIX="" \ + EPATCH_OPTS="-p1" \ + epatch ${WORKDIR}/${SUSPEND2_SRC} +} [snip] You need to enable stty of busybox, change configuration at: /usr/share/genkernel/@@ARCH@@/busy-config -# CONFIG_STTY is not set +CONFIG_STTY=y Remove /usr/share/genkernel/pkg/@@ARCH@@/busybox-* Now use genkernel or mygenkernel to create your initrd. Boot partition ---------------------------- Put gpg keys at /keyfile.gpg file or link exists on boot partition Create boot partition boot-util as described above. Put loop module under boot-util/`uname -r`/lib/modules/`uname -r`/block [gentoo] You can use mygenkernel that takes boot-util from cache on root file system and put it in boot file system. initrd kernel parameters ---------------------------- - initrd_util=/dev/hdaX - location of the boot partition. - initrd_loops=/dev/hdaX,/dev/hdaY,... - devices to loop over. - initrd_loopstart=N - first loop index - initrd_shell=N (0-none,1-on start,2-after setup,3-after loop) - root=anything but /dev/ramX since suspend2 will not resume Example: initrd_util=/dev/hda1 initrd_loops=/dev/hda2,/dev/hda3 initrd_loopstart=4 initrd_shell=0 This will load utilities from /dev/hda1 and map: - /dev/loop4->/dev/hda2 - /dev/loop5->/dev/hda3 Expected busybox applets for initrd --------------------------------------- If you create your own initrd, please make sure the following commands are available: - echo - cp - cat - sh - test - [ - dd - sed - mount - umount - mknod - stty - mkdir - ln - modprobe /etc/fstab ------------------ Here is my example of fstab, suspend will be written to /dev/loop4 /dev/hda1 /boot ext2 defaults,noatime 1 2 /dev/loop5 / ext3 noatime 0 1 /dev/loop4 none swap sw 0 0 Encrypting your root partition ----------------------------------- Setup /etc/fstab to map loop device or root. Boot your kernel with my initrd and the following arguments: root=/dev/hda3 initrd_util=/dev/hda1 initrd_shell=2 You should get a shell after initrd was setup correctly. Set console as tty (required for asepipe) rm /dev/tty ln -s /dev/console /dev/tty Run aespipe busybox dd if=/dev/hda3 bs=64k | \ aespipe -G / -K /mnt/keyfile.gpg -e AES256 | \ busybox dd of=/dev/hda3 conv=notrunc Reboot your kernel, now put the following arguments: root=/dev/loop5 initrd_util=/dev/hda1 initrd_loops=/dev/hda3 initrd_loopstart=5 initrd_shell=0 You should be prompted with password for the gpg file and boot should succeed. Encrypting swap partition ----------------------------------- Reboot your kernel, now put the following arguments: root=/dev/loop5 initrd_util=/dev/hda1 initrd_loops=/dev/hda2,/dev/hda3 initrd_loopstart=4 initrd_shell=0 resume2=/dev/hda2 You should be prompted with password for the gpg file and boot should succeed. After boot create swap file: mkswap /dev/loop4 swapon -a Update hibernate.conf ------------------------ This will execute boot partition digest check OnResume 00 /usr/local/bin/check-boot-digest This will unmount boot partition so it can be mounted during boot by initrd Unmount /boot Mount /boot Grub -------- Here is my grub file default 0 timeout 30 splashimage=(hd0,0)/grub/splash.xpm.gz title=initrd-2.6.11-gentoo_suspend2_test-r9 root (hd0,0) kernel (hd0,0)/kernel-2.6.11-gentoo_suspend2_test-r9 root=/dev/loop5 ro resume2=swap:/dev/loop4 video=vesafb:ywrap,mtrr,1400x1050-32@60 splash=silent,theme:gentoo initrd_util=/dev/hda1 initrd_loops=/dev/hda2,/dev/hda3 initrd_loopstart=4 initrd_shell=0 initrd (hd0,0)/initrd-2.6.11-gentoo_suspend2_test-r9 boot title=initrd-2.6.11-gentoo_suspend2-r9 root (hd0,0) kernel (hd0,0)/kernel-2.6.11-gentoo_suspend2-r9 root=/dev/loop5 ro resume2=swap:/dev/loop4 video=vesafb:ywrap,mtrr,1400x1050-32@60 splash=silent,theme:gentoo initrd_util=/dev/hda1 initrd_loops=/dev/hda2,/dev/hda3 initrd_loopstart=4 initrd_shell=0 initrd (hd0,0)/initrd-2.6.11-gentoo_suspend2-r9 boot Digesting boot -------------------- After you finish all modifications mark current boot digest by: mark-boot-digest So that you know if someone has tempered your unencrypted root. Test suspend2 ------------------- Now try to hibernate... Good luck! Open issues ------------------- There is no known way to protect against sophisticated kernel attach on the unencrypted boot partition that will cause the hash check to succeed but will write your password on a location of the disk. For now the only way to detect this is to digest the boot partition and compare it to one stored on the encrypted file system. What next ------------------- I will provide a solution to put gpg keys on PKCS#11 smartcard token.