[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#348147: Add support for cryptoroot



Package: initramfs-tools
Version: 0.49
Severity: wishlist
Tags: patch

I've attached a first attempt at adding cryptroot support.

It adds two new boot options:

cryptroot: the device which the encrypted filesystem resides on
          example: cryptroot=/dev/hda1

cryptopts: a comma-separated list of arguments to cryptsetup, currently supported options are hash, size and cipher. If none are specified, defaults (the example below) will be used. example: cryptopts=hash=sha256,size=256,cipher=aes-cbc-essiv:sha256

if cryptroot is present, the root argument is expected to be the node where cryptsetup should setup the unencrypted fs, so it should be under the /dev/mapper hierarchy. An example of a complete set of arguments for cryptroot is:
root=/dev/mapper/cryptroot cryptroot=/dev/hda1 cryptopts=hash=sha256,size=256,cipher=aes-cbc-essiv:sha256

Admittedly, having both a root and a cryptroot command line option is somewhat ugly, but avoiding it would require the init script to source the files under scripts instead of executing them. The ROOT variable could then be set to the encrypted node (/dev/hda1 in the example above) until the cryptroot script is run which could setup the /dev/mapper/cryptroot node and change the ROOT variable accordingly. This would for instance have the advantage of making any changes to the lvm script unnecessary. Alas, this is not possible without major changes...

The cryptroot hook copies cryptsetup to the initramfs (if present) and if /etc/mkinitramfs/cryptgetpw is present on the system it is also included.

If no cryptgetpw script is present, the cryptroot script will ask the user to input the password via keyboard. If the script is present, it is executed and its output piped to cryptsetup. This allows users to create more complex password schemes (for example, I currently use a cryptgetpw which loads the password from a USB key) by creating an appropriate script.

Comments/suggestions are very welcome (especially a clean way of altering the ROOT variable from the scripts/local-top/cryptroot would be nice)...

Re,
David Härdeman
diff -Nur -x udev initramfs-tools-bak/hooks/cryptroot initramfs-tools/hooks/cryptroot
--- initramfs-tools-bak/hooks/cryptroot	1970-01-01 01:00:00.000000000 +0100
+++ initramfs-tools/hooks/cryptroot	2006-01-14 20:50:37.000000000 +0100
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+PREREQ=""
+
+prereqs()
+{
+	echo "$PREREQ"
+}
+
+case $1 in
+prereqs)
+	prereqs
+	exit 0
+	;;
+esac
+
+. /usr/share/initramfs-tools/hook-functions
+
+if [ -x "/sbin/cryptsetup" ]; then
+	copy_exec /sbin/cryptsetup /sbin
+	if [ -x "/etc/mkinitramfs/cryptgetpw" ]; then
+		copy_exec /etc/mkinitramfs/cryptgetpw /sbin
+	fi
+fi
+
+exit 0
diff -Nur -x udev initramfs-tools-bak/init initramfs-tools/init
--- initramfs-tools-bak/init	2005-12-28 01:27:43.000000000 +0100
+++ initramfs-tools/init	2006-01-12 22:06:29.000000000 +0100
@@ -28,6 +28,9 @@
 export resume=${RESUME}
 export rootmnt=/root
 export debug=
+export cryptroot=
+export cryptopts=
+
 for x in $(cat /proc/cmdline); do
 	case $x in
 	init=*)
@@ -59,6 +62,12 @@
 		exec >/tmp/initramfs.debug 2>&1
 		set -x
 		;;
+	cryptroot=*)
+		cryptroot=${x#cryptroot=}
+		;;
+	cryptopts=*)
+		cryptopts=${x#cryptopts=}
+		;;
 	break=*)
 		break=${x#break=}
 		;;
diff -Nur -x udev initramfs-tools-bak/scripts/local-top/cryptroot initramfs-tools/scripts/local-top/cryptroot
--- initramfs-tools-bak/scripts/local-top/cryptroot	1970-01-01 01:00:00.000000000 +0100
+++ initramfs-tools/scripts/local-top/cryptroot	2006-01-15 09:27:03.000000000 +0100
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+PREREQ="md lvm evms"
+
+prereqs()
+{
+	echo "$PREREQ"
+}
+
+case $1 in
+# get pre-requisites
+prereqs)
+	prereqs
+	exit 0
+	;;
+esac
+
+if [ ! -x "/sbin/cryptsetup" ]; then
+	echo "$0: no cryptsetup present"
+	exit 0
+fi
+
+# If we have a cryptroot, root must be a device-mapper partition
+if [ -n "$cryptroot" ]; then
+	cryptnode=${ROOT#/dev/mapper/}
+	if [ "$cryptnode" = "$ROOT" ]; then
+		panic "$0: root must be a device-mapper partition"
+	fi
+else
+	exit 0
+fi
+
+cryptciper=aes-cbc-essiv:sha256
+cryptsize=256
+crypthash=sha256
+
+if [ -n "$cryptopts" ]; then
+	argc=0
+	while [ 1 ]; do
+		arg=$( echo "$cryptopts" | cut -d "," -f $argc )
+		[ -n "$arg" ] || break
+		argc=$(( argc + 1 ))
+
+		case "$arg" in
+		hash=*)
+			crypthash=${arg#hash=}
+			;;
+		size=*)
+			cryptsize=${arg#size=}
+			;;
+		cipher=*)
+			cryptcipher=${arg#cipher=}
+			;;
+		esac
+	done
+fi
+
+while [ 1 ]; do
+	if [ -x "/sbin/cryptgetpw" ]; then
+		/sbin/cryptgetpw | /sbin/cryptsetup -c $cryptcipher -s $cryptsize -h $crypthash create $cryptnode $cryptroot
+	else
+		/sbin/cryptsetup -c $cryptcipher -s $cryptsize -h $crypthash create $cryptnode $cryptroot
+	fi
+
+	eval $( fstype < "$ROOT" )
+	if [ "$FSTYPE" = "unknown" ]; then
+		echo "$0: fstype not recognized, bad password?"
+		/sbin/cryptsetup remove $cryptnode
+		sleep 3
+		continue
+	fi
+	break
+done
+
+exit 0
diff -Nur -x udev initramfs-tools-bak/scripts/local-top/lvm initramfs-tools/scripts/local-top/lvm
--- initramfs-tools-bak/scripts/local-top/lvm	2006-01-14 21:21:51.000000000 +0100
+++ initramfs-tools/scripts/local-top/lvm	2006-01-14 21:21:36.000000000 +0100
@@ -15,7 +15,11 @@
 	;;
 esac
 
-vg=${ROOT#/dev/mapper/}
+if [ -n "$cryptroot" ]; then
+	vg=${cryptroot#/dev/mapper/}
+else
+	vg=${ROOT#/dev/mapper/}
+fi
 
 case ${vg} in
 	/dev/root)

Reply to: