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

Root filesystem encryption patch set



I would like to see these patches make it in for FC7 test4, although it may be a tight squeeze.  Both patches should be against T3.  The only thing missing here is anaconda support, but I will need some help on that.  I know the anaconda support won't be for FC7 but we can make it happen for FC8.

The complete instructions for using the modified versions are posted on www.cygnetech.com/linux/howtos/index.html It will be prettier at a later date, but I wanted to get this out to the community as soon as possible.

In short, with the modified mkinitrd, you can massage a FC6 and FC7 (test3) CD installation into a fully encrypted installation (sans boot media).   The byproduct is being able to resume a hibernated session from an encrypted disk as well as detected media for removable keys.

Extra functionality added to mkinitrd is ability to add persistent options in /etc/mkinitrd.conf ... This also allows for some anaconda flexibility when generating encrypted installation when we can get to that point.

I'll send this up through bugzilla as soon as I get my password reset. ARGH!  Thoughts and feedback are appreciated.

--
The early bird may get the worm, but the it's the second mouse that gets the cheese.

Attachment: mkinitrd
Description: Binary data

--- /sbin/mkinitrd	2007-03-12 14:54:08.000000000 -0500
+++ ./mkinitrd	2007-04-25 04:44:48.000000000 -0500
@@ -23,6 +23,7 @@
 #       Bill Nottingham <notting redhat com>
 #       Guillaume Cottenceau <gc mandrakesoft com>
 #       Peter Jones <pjones redhat com>
+#       Thomas Swan <thomas swan gmail com>
 
 export MALLOC_PERTURB_=204
 
@@ -48,6 +49,15 @@
 CONFMODS="$MODULES"
 MODULES=""
 
+CRYPTODEVICES=""
+CRYPTOMODS="DEFAULT"
+crypto=""
+crypto_omit=0
+crypto_reps=0
+
+CONFIG=/etc/mkinintrd.conf
+config=1
+
 compress=1
 allowmissing=""
 target=""
@@ -98,7 +108,9 @@
     $cmd "       [--force-ide-probe] [--force-scsi-probe | --omit-scsi-modules]"
     $cmd "       [--image-version] [--force-raid-probe | --omit-raid-modules]"
     $cmd "       [--with=<module>] [--force-lvm-probe | --omit-lvm-modules]"
-    $cmd "       [--builtin=<module>] [--omit-dmraid] [--net-dev=<interface>]"
+    $cmd "       [--builtin=<module>] [--net-dev=<interface>] [--config=<config>]"
+    $cmd "       [--nocrypto] [--crypto-module=<module>|DEFAULT|ALL] [--omit-dmraid] "
+    $cmd "       [--crypto-dev=<device>[@<key-device>,<key-device-fstype>][:<key-file>]"
     $cmd "       [--fstab=<fstab>] [--nocompress] <initrd-image> <kernel-version>"
     $cmd ""
     $cmd "       (ex: `basename $0` /boot/initrd-2.2.5-15.img 2.2.5-15)"
@@ -437,6 +449,100 @@
     addnetdev $netdev
 }
 
+findallcryptomods() {
+    local cryptomods=""
+    cryptomods="$cryptomods dm-crypt"
+    cryptomods="$cryptomods blkcipher"
+    for modName in `find /lib/modules/$1/kernel/crypto/ -type f | sed 's/.*\/\(.*\)\..*/\1/'` ; do
+        cryptomods="$cryptomods $modName"
+    done
+    echo $cryptomods
+}
+
+execconfig() {
+    if [ -e ${CONFIG} ] ; then
+        local OPTIONS
+        while read config ; do 
+            config=${config/##*/}
+            config=${config/#\{ ,    \}*//}
+            config=${config/%*\{ ,    \}//}
+            if [ -n ${config} ] ; then
+                OPTIONS="${OPTIONS} ${config}" 
+            fi
+        done < /etc/mkinitrd.conf
+        if [ -n "${OPTIONS}" ] ; then
+            OPTIONS="--noconfig ${OPTIONS} $*"
+            exec $progname ${OPTIONS}
+        fi
+    fi
+}
+
+emit_crypto() {
+    if [ -n "${crypto_reps}" ] ; then
+        let crypto_reps=${crypto_reps}+1
+    else    
+        crypto_reps=1
+    fi
+    if [ -n "$crypto" ] ; then
+        for i in $CRYPTODEVICES ; do 
+            # We want a complete predictable name for the encrypted device
+            # to use with device-mapper. ... Assume nothing!
+            crypto_device=${i%% *}
+            crypto_device=${crypto_device%%:*}
+            crypto_mapper_name=${crypto_device##/dev/}
+            crypto_mapper_name=`echo ${crypto_mapper_name} | sed 's!/!_!g'`
+            crypto_key_file=""
+            crypto_key_device=""
+            crypto_key_tmp=""
+            if [ ${i##*:} != ${i} ] ; then
+                crypto_key_file=${i##*:}
+                crypto_key_tmp=${i%%:*}
+                crypto_key_tmp=${crypto_key_tmp##* }
+            fi
+            if [ "${crypto_key_tmp}" != "${crypto_device}" ] ; then
+                crypto_key_device=${crypto_key_tmp%%,*}
+                crypto_key_device_fs=${crypto_key_tmp##*,}
+                crypto_key_file=${crypto_key_file##/}
+                if [ ${crypto_key_device} == ${crypto_key_tmp} ] ; then
+                    echo "Crypto: No fstype specified for external crypto key:"
+                    echo "   ${i}"
+                    exit 211
+                fi
+            fi
+
+            emit "echo Decrypting ${crypto_device} (Round ${crypto_reps})"
+            if [ -n "${crypto_key_device}" ] ; then
+                # Mount the filesystem with the key, and decrypt using the key
+                # on the mounted media.  
+                emit "mount -t ${crypto_key_device_fs} -o ro ${crypto_key_device} /crypto/mount"
+                emit "cryptsetup luksOpen ${crypto_device} ${crypto_mapper_name} -d /crypto/mount/${crypto_key_file}"
+                emit "umount /crypto/mount"
+                if [ $crypto_reps == 1 ] ; then
+                    vecho -n "Crypto: Decrypt ${crypto_device} using external keyfile ${crypto_key_file} "
+                    vecho  "located on ${crypto_key_device} mounted as an ${crypto_key_device_fs} filesystem "
+                fi
+            elif [ -n "${crypto_key_file}" ] ; then 
+                # Embed the key in the initrd image.  * Useful if /boot is a removable drive * 
+                emit "cryptsetup luksOpen ${crypto_device} ${crypto_mapper_name} -d /crypto/"`basename ${crypto_key_file}`
+                if [ ! -f "$MNTIMAGE/crypto/$(basename ${crypto_key_file})" ] ; then
+                    if ! inst ${crypto_key_file} "$MNTIMAGE/crypto/$(basename ${crypto_key_file})" ; then
+                        echo "Unable to import key file ${crypto_key_file}" 
+                        exit 1
+                    fi
+                fi
+                if [ $crypto_reps == 1 ] ; then
+                    vecho "Crypto: Decrypt ${crypto_device} using embedded keyfile imported from ${crypto_key_file}"
+                fi
+            else
+                emit "cryptsetup luksOpen ${crypto_device} ${crypto_mapper_name}"
+                if [ $crypto_reps == 1 ] ; then
+                    vecho "Crypto: Decrypt ${crypto_device} using passphrase decryption"
+                fi
+            fi
+        done
+    fi
+}
+
 handleraid() {
     local start=0
 
@@ -552,9 +658,33 @@
 }
 
 
+option_next=1
+for option in $@ ; do 
+    let option_next=$option_next+1
+    case $option in 
+    --noconfig*)
+        config=0
+        ;;
+    --config*)
+    	if [ "$option" != "${option##--config=}" ] ; then
+    		CONFIG=${option##--config=}
+    	else
+    		CONFIG=${!option_next}
+    	fi
+    	;;
+    esac
+done    
+unset option_next
+
+if [ "$config" == "1" ] ; then 
+    progname=$0
+    execconfig $@
+fi
+
 while [ $# -gt 0 ]; do
     case $1 in
         --fstab*)
+            preserve_options=$1 $2
             if [ "$1" != "${1##--fstab=}" ]; then
                 fstab=${1##--fstab=}
             else
@@ -725,6 +855,34 @@
                 shift
             fi
 	    ;;
+        --noconfig*)
+            config=0
+            ;;
+        --omit-crypt*)
+            crypto_omit=1
+            ;;
+        --crypto-module*)
+            crypto=1
+            if [ "$1" != "${1##--crypto-module=}" ]; then
+                modname="${1##--crypto-module=}"
+            else
+                modname="$2"
+                if [ -z "$2" ] ; then
+                    modname="DEFAULT"
+                fi
+            fi
+            CRYPTOMODS="$CRYPTOMODS $modname"
+            ;;
+        --crypto-dev*)
+            crypto=1
+            cryptodevice=""
+            if [ "$1" != "${1##--crypto-dev=}" ]; then
+                cryptodevice="${1##--crypto-dev=}"
+            else
+                cryptodevice="$2"
+            fi
+            CRYPTODEVICES="$CRYPTODEVICES $cryptodevice"
+            ;;
         --help)
             usage -n
             ;;
@@ -780,6 +938,26 @@
     exit 1
 fi
 
+if [ $crypto_omit == 1 ] ; then 
+    crypto=""
+fi
+
+if [ -n "$crypto" ] ; then
+    for modname in $CRYPTOMODS ; do 
+        case $modname in 
+        ALL)
+            PREMODS="$PREMODS "`findallcryptomods $kernel`
+            ;;
+        DEFAULT)
+            PREMODS="$PREMODS dm-crypt blkcipher aes cbc sha256 crypto_null"
+            ;;
+        *)
+            PREMODS="$PREMODS $modname"
+            ;;
+        esac
+    done
+fi
+
 vecho "Creating initramfs"
 modulefile=/etc/modprobe.conf
 
@@ -931,6 +1109,9 @@
         findmodule -dm-mirror
         findmodule -dm-zero
         findmodule -dm-snapshot
+        if [ -n "$crypto" ] ; then
+            findmodule -dm-crypt
+        fi
         
         RAIDS=$(/sbin/dmraid -s -craidname 2>/dev/null | grep -vi "no raid disks") 
     
@@ -1059,6 +1240,11 @@
 mkdir -p $MNTIMAGE/sysroot
 ln -s bin $MNTIMAGE/sbin
 
+if [ -n "$crypto" ] ; then
+    mkdir -p $MNTIMAGE/crypto
+    mkdir -p $MNTIMAGE/crypto/mount
+fi
+
 if [ -e /etc/fstab.sys ]; then
     inst /etc/fstab.sys "$MNTIMAGE/etc/fstab.sys"
 fi
@@ -1066,6 +1252,10 @@
 inst /sbin/insmod.static "$MNTIMAGE/bin/insmod"
 ln -s /sbin/nash $MNTIMAGE/sbin/modprobe
 
+if [ -n "$crypto" ] ; then
+    inst /sbin/cryptsetup "$MNTIMAGE/bin/cryptsetup"
+fi
+
 for MODULE in $MODULES; do
     if [ -x /usr/bin/strip ]; then
         /usr/bin/strip -g $verbose $MODULE -o $MNTIMAGE/lib/$(basename $MODULE)
@@ -1233,6 +1423,11 @@
 # things like RAID or LVM
 emit "mkblkdevs"
 
+# Chickens and eggs.  Because you can encrypt both LV's and the devices
+# containing containing LV's, we need try to try to decrypt twice or we
+# need to be far more clever.
+emit_crypto
+
 emitdms
 
 if [ -n "$raiddevices" ]; then
@@ -1249,6 +1444,14 @@
     emit "lvm vgchange -ay --ignorelockingfailure $vg_list"
 fi
 
+# Eggs and chickens.  Try decrypting just in case any LV's are encrypted.
+# We need to do to this before resuming on the off chance that swap has been
+# encrypted with a permanent key.  
+#
+# If the volume has already been decrypted, no harm has been done doing it 
+# twice.
+emit_crypto
+
 if [ -z "$noresume" -a -n "$swsuspdev" ]; then
     emit "resume $swsuspdev"
 fi

Attachment: mkinitrd.8
Description: Binary data

--- mkinitrd.8.old	2007-04-25 00:30:34.000000000 -0500
+++ mkinitrd.8	2007-04-25 04:14:08.000000000 -0500
@@ -3,11 +3,14 @@
 mkinitrd \- creates initial ramdisk images for preloading modules
 .SH SYNOPSIS
 \fBmkinitrd\fR [--version] [-v] [-f] 
-         [--preload=\fImodule\fR] [--omit-scsi-modules] 
+         [--preload=\fImodule\fR] 
+         [--crypto-module=(ALL|DEFAULT|\fImodule\fR)]
+         [--crypto-dev=\fIdevice\fR[ \fIkey-device\fR,\fIkey-device-fstype\fR][:\fIkey\fR]]
+         [--omit-crypto] [--omit-scsi-modules] 
          [--omit-raid-modules] [--omit-lvm-modules] 
          [--with=\fImodule\fR] [--image-version]
-         [--fstab=\fIfstab\fR] [--nocompress]
-         [--builtin=\fImodule\fR] [--nopivot]
+         [--fstab=\fIfstab\fR] [--nocompress] [--nopivot] 
+         [--builtin=\fImodule\fR] [--config=\fIfile\fR] [--noconfig]
          \fIimage\fR \fIkernel-version\fR
 
 .SH DESCRIPTION
@@ -36,6 +39,61 @@
 exist. This option may be used multiple times.
 
 .TP
+\fB-\-config=\fR\fIfile\fR
+Specify an alternate \fBmkinitrd.conf\fR file to load. 
+
+.TP
+\fB-\-crypto-module=\fR\fI(module|ALL|DEFAULT)\fR
+Specify a crypto \fImodule\fR to preload. 
+
+\fB--crypto-module=DEFAULT\fR will load aes cbc and sha256 crypto modules
+\fB--crypto-module=ALL\fR will load all available crypto modules. 
+
+This option may be used multiple times.
+
+.TP
+\fB-\-crypto-dev=\fR\fIdevice\fR[ \fIkey-device\fR,\fIkey-device-fstype\fR][:\fIkey\fR]]
+Specify the encrypted device to decrypt prior to mounting. Password 
+decryption is supported by default.  <key-device> may use any mount identifier
+such as LABEL= or UUID= in addition to the physical device identifier. When
+using <key-device>, <key-device-fstype> \fImust\fR be specified.
+<device> must not be listed in \fB/etc/crypttab\fR because it will
+decrypted before init begins.  This option may be used multiple times.
+
+-\-crypto-dev=\fIdevice\fR
+<dev> is the device to decrypt.
+
+-\-crypto-dev=\fIdevice\fR:\fI/path/to/key\fR
+\fIdevice\fR is the device to decrypt.  The file located at \fI/path/to/key\fR will
+be embedded in the initrd.img file and used to decrypt \fIdevice\fR.
+
+-\-crypto-dev=\fIdevice\fR \fIkey-device\fR,\fIkey-device-fstype\fR:\fI/path/to/key\fR
+\fIdevice\fR is the device to decrypt.  \fIkey-device\fR is the device containing the key
+file used to decrypt \fIdevice\fR. \fIkey-device-fstype\fR is the filesystem type for \fIkey-device\fR: 
+eg. ext2. \fI/path/to/key\fR is the key file \fIrelative\fR to the root of
+<dev2>.
+
+Examples
+
+-\-crypto-dev=/dev/hdb1 would try to decrypt /dev/hdb1 using a password
+entered by the user during the boot process.
+
+-\-crypto-dev=/dev/hdb1:/media/flash/my.key would embed /media/flash/my.key
+in the initrd image file to and use that key to decrypt /dev/hdb1.
+
+-\-crypto-dev=/dev/hdb1 LABEL=flash,ext2:/my.key would try to decrypt 
+/dev/hdb1 using the key, "/my.key", located on an unencrypted ext2 
+filesystem with the label, "flash".  During boot, it will mount
+the the LABEL=flash device read-only, and use the key on the disk to decrypt
+the specified device, /dev/hdb1.  Then the LABEL=flash device would be 
+unmounted before continuing. \fIThe key device must be present during 
+system boot.\fR
+
+.TP
+\fB-\-version\fR
+Prints the version of \fBmkinitrd\fR that's being used and then exits.
+
+.TP
 \fB-f\fR
 Allows \fBmkinitrd\fR to overwrite an existing image file.
 
@@ -50,6 +108,11 @@
 is created.
 
 .TP
+\fB-\-noconfig\fR
+Prohibit the reading the \fB/etc/mkinitrd.conf\fR file for persistent
+options.
+
+.TP
 \fB-\-nocompress
 Normally the created initrd image is compressed with \fBgzip\fR. If this
 option is specified, the compression is skipped.
@@ -63,6 +126,11 @@
 option is not recommended, and will be removed in future versions.
 
 .TP
+\fB-\-omit-crypto
+Do not load any cryptographic modules, even if specified on \fBmkinitrd\fR's
+command line.
+
+.TP
 \fB-\-omit-lvm-modules 
 Do not load any lvm modules, even if /etc/fstab expects them.
 
@@ -114,7 +182,18 @@
 Specifies SCSI modules to be loaded and module options to be used.
 \fI(only used on kernels < 2.6)\fR
 
+.TP 20
+\fI/etc/mkinitrd.conf\fR
+Specifies persistent options to be used with mkinitrd.
+
+Lines beginning with # are considered comments
+Options can be on one or more lines.
+
+\fINOTE:\fR -\-crypt-dev, -\-crypt-cipher, and -\-with-usb options may 
+need to be preserved\fR
+
 .PD
 .SH "SEE ALSO"
+.BR cryptsetup (8),
 .BR fstab (5),
 .BR insmod (1)

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