--- tj-crypto-usb-key-20080816.sh	2008-08-16 21:25:09.000000000 +0200
+++ hendrik-crypto-usb-key.sh	2008-10-05 16:47:15.000000000 +0200
@@ -12,8 +12,14 @@
 # For use with Ubuntu Hardy, usplash, automatic detection of USB devices,
 # detection and examination of *all* partitions on the device (not just partition #1), 
 # automatic detection of partition type, refactored, commented, debugging code.
+#
+# Updated by Hendrik van Antwerpen <hendrik at van-antwerpen dot net> 3 Sept 2008
+# For encrypted key device support, also added stty support for not
+# showing your password in console mode.
 
 # define counter-intuitive shell logic values (based on /bin/true & /bin/false)
+# NB. use FALSE only to *set* something to false, but don't test for
+# equality, because a program might return any non-zero on error
 TRUE=0
 FALSE=1
 
@@ -22,12 +28,14 @@
 
 # is usplash available? default false
 USPLASH=$FALSE
-if [ -f /sbin/usplash_write ]; then
+# test for outfifo from Ubuntu Hardy cryptroot script, the second test
+# alone proves not completely reliable.
+if [ -p /dev/.initramfs/usplash_outfifo -a -x /sbin/usplash_write ]; then
 	# use innocuous command to determine if usplash is running
 	# usplash_write will return exit-code 1 if usplash isn't running
 	# need to set a flag to tell usplash_write to report no usplash
 	FAIL_NO_USPLASH=1
-	#enable verbose messages (required to display messages if kernel boot option "quiet" is enabled
+	# enable verbose messages (required to display messages if kernel boot option "quiet" is enabled
 	/sbin/usplash_write "VERBOSE on"
 	if [ $? -eq $TRUE ]; then
 		# usplash is running
@@ -36,6 +44,18 @@
 	fi
 fi
 
+# is stty available? default false
+STTY=$FALSE
+STTYCMD=false
+# check for stty executable
+if [ -x /bin/stty ]; then
+	STTY=$TRUE
+	STTYCMD=/bin/stty
+elif [ `(busybox stty >/dev/null 2>&1; echo $?)` -eq $TRUE ]; then
+	STTY=$TRUE
+	STTYCMD="busybox stty"
+fi
+
 # print message to usplash or stderr
 # usage: msg <command> "message" [switch]
 # command: TEXT | STATUS | SUCCESS | FAILURE | CLEAR (see 'man usplash_write' for all commands)
@@ -60,7 +80,34 @@
 	fi
 }
 
-[ $DEBUG -eq $TRUE ] && msg STATUS "Executing crypto-usb-key.sh ..."
+dbg ()
+{
+	if [ $DEBUG -eq $TRUE ]; then
+		msg "$@"
+	fi
+}
+
+# read password from console or with usplash
+# usage: readpass "prompt"
+readpass ()
+{
+	if [ $# -gt 0 ]; then
+		if [ $USPLASH -eq $TRUE ]; then
+			usplash_write "INPUTQUIET $1: "
+			PASS="$(cat /dev/.initramfs/usplash_outfifo)"
+		else
+			[ $STTY -ne $TRUE ] && msg TEXT "WARNING stty not found, password will be visible"
+			echo -n "$1" >&2
+			$STTYCMD -echo
+			read -r PASS </dev/console >/dev/null
+			[ $STTY -eq $TRUE ] && echo >&2
+			$STTYCMD echo
+		fi
+	fi
+	echo -n "$PASS"
+}
+
+dbg STATUS "Executing crypto-usb-key.sh ..."
 
 # flag tracking key-file availability
 OPENED=$FALSE
@@ -79,7 +126,7 @@
 # This is useful where an encrypted volume contains keyfile(s) for later
 # volumes and is now mounted and accessible
 if [ -f $KEYFILE ]; then
-	[ $DEBUG -eq $TRUE ] && msg TEXT "Found $KEYFILE"
+	dbg TEXT "Found $KEYFILE"
 	cat $KEYFILE
 	OPENED=$TRUE
 	DEV="existing mount"
@@ -89,7 +136,7 @@
 	cat /proc/modules | busybox grep usb_storage >/dev/null 2>&1
 	USBLOAD=0$?
 	if [ $USBLOAD -gt 0 ]; then
-		[ $DEBUG -eq $TRUE ] && msg TEXT "Loading driver 'usb_storage'"
+		dbg TEXT "Loading driver 'usb_storage'"
 		modprobe usb_storage >/dev/null 2>&1
 	fi
 
@@ -102,54 +149,86 @@
 
 	if [ $SBD -eq $TRUE ]; then
 		mkdir -p $MD
-		[ $DEBUG -eq $TRUE ] && msg TEXT "Trying to get key-file '$KEYFILE' ..."
+		dbg TEXT "Trying to get key-file '$KEYFILE' ..."
 		for SFS in /sys/block/sd*/sd??; do
-			[ $DEBUG -eq $TRUE ] && msg TEXT "Examining $SFS" -n
+			dbg TEXT "Examining $SFS" -n
 			# is it a USB device?
 			ls -l ${SFS}/../device | busybox grep 'usb' >/dev/null 2>&1
 			USB=0$?
-			[ $DEBUG -eq $TRUE ] && msg TEXT ", USB=$USB" -n
+			dbg TEXT ", USB=$USB" -n
 			# Is the device removable?
 			REMOVABLE=0`cat ${SFS}/../removable`
-			[ $DEBUG -eq $TRUE ] && msg TEXT ", REMOVABLE=$REMOVABLE" -n
+			dbg TEXT ", REMOVABLE=$REMOVABLE" -n
 			if [ $USB -eq $TRUE -a $REMOVABLE -eq 1 -a -f $SFS/dev ]; then
-				[ $DEBUG -eq $TRUE ] && msg TEXT ", *possible key device*" -n
+				dbg TEXT ", *possible key device*" -n
 				DEV=`busybox basename $SFS`
-				[ $DEBUG -eq $TRUE ] && msg TEXT ", device $DEV" -n
-				# No access to /sbin/vol_id so query the UDEV database directly
-				# to get the file-system label
-				LABEL=" (`cat /dev/.udev/db/*${DEV} | busybox sed -n 's/.*ID_FS_LABEL_SAFE=\(.*\)/\1/p'`) "
-				[ $DEBUG -eq $TRUE ] && msg TEXT ", label $LABEL" -n
-				# No access to /sbin/vol_id and /bin/fstype reports vfat/msdos/ntfs as 'unknown', so
-				# query the UDEV database directly to get the file-system type
-				FSTYPE=`cat /dev/.udev/db/*${DEV} | busybox sed -n 's/.*ID_FS_TYPE=\(.*\)/\1/p'`
-				[ $DEBUG -eq $TRUE ] && msg TEXT ", fstype $FSTYPE" -n
+				# Check if key device itself is encrypted
+				/sbin/cryptsetup isLuks /dev/${DEV} >/dev/null 2>&1
+				ENCRYPTED=0$?
+				# Open crypted partition and prepare for mount
+				if [ $ENCRYPTED -eq $TRUE ]; then
+					dbg TEXT ", encrypted device" -n
+					# Use vol_id to determine label
+					LABEL="`/lib/udev/vol_id /dev/${DEV} | busybox sed -n 's/.*ID_FS_LABEL_SAFE=\(.*\)/\1/p'`"
+					dbg TEXT ", label $LABEL" -n
+					TRIES=3
+					DECRYPTED=$FALSE
+					while [ $TRIES -gt 0 -a $DECRYPTED -ne $TRUE ]; do
+						TRIES=$(($TRIES-1))
+						PASS="`readpass \"Enter LUKS password for key device ${DEV} (${LABEL}) (or empty to skip): \"`"
+						if [ -z "$PASS" ]; then
+							dbg TEXT ", device skipped" -n
+							break
+						fi
+						echo $PASS | /sbin/cryptsetup luksOpen /dev/${DEV} bootkey >/dev/null 2>&1
+						DECRYPTED=0$?
+					done
+					# If open failed, skip this device
+					if [ $DECRYPTED -ne $TRUE ]; then
+						dbg TEXT "decrypting device failed" -n
+						break
+					fi
+					# Decrypted device to use
+					DEV=mapper/bootkey
+				fi
+				dbg TEXT ", device $DEV" -n
+				# Use vol_id to determine label
+				LABEL="`/lib/udev/vol_id /dev/${DEV} | busybox sed -n 's/.*ID_FS_LABEL_SAFE=\(.*\)/\1/p'`"
+				dbg TEXT ", label $LABEL" -n
+				# Use vol_id to determine fstype
+				FSTYPE="`/lib/udev/vol_id /dev/${DEV} | busybox sed -n 's/.*ID_FS_TYPE=\(.*\)/\1/p'`"
+				dbg TEXT ", fstype $FSTYPE" -n
 				# Is the file-system driver loaded?
 				cat /proc/modules | busybox grep $FSTYPE >/dev/null 2>&1
 				FSLOAD=0$?
 				if [ $FSLOAD -gt 0 ]; then
-					[ $DEBUG -eq $TRUE ] && msg TEXT ", loading driver for $FSTYPE" -n
+					dbg TEXT ", loading driver for $FSTYPE" -n
 					# load the correct file-system driver
 					modprobe $FSTYPE >/dev/null 2>&1
 				fi
-				[ $DEBUG -eq $TRUE ] && msg TEXT ", mounting /dev/$DEV on $MD" -n
-				mount /dev/${DEV} $MD -t $FSTYPE -o ro 2>/dev/null
-				[ $DEBUG -eq $TRUE ] && msg TEXT ", (`mount | busybox grep $DEV`)" -n
+				dbg TEXT ", mounting /dev/$DEV on $MD" -n
+				mount /dev/${DEV} $MD -t $FSTYPE -o ro >/dev/null 2>&1
+				dbg TEXT ", (`mount | busybox grep $DEV`)" -n
 				if [ -f $MD/$KEYFILE ]; then
-					[ $DEBUG -eq $TRUE ] && msg TEXT ", found $MD/$KEYFILE" -n
+					dbg TEXT ", found $MD/$KEYFILE" -n
 					cat $MD/$KEYFILE
-					[ $DEBUG -eq $TRUE ] && msg TEXT ", umount $MD"
-					umount $MD 2>/dev/null
 					OPENED=$TRUE
+				fi
+				dbg TEXT ", umount $MD" -n
+				umount $MD >/dev/null 2>&1
+				# Close encrypted key device
+				if [ $ENCRYPTED -eq $TRUE -a $DECRYPTED -eq $TRUE ]; then
+					dbg TEXT ", closing encrypted device" -n
+					/sbin/cryptsetup luksClose bootkey >/dev/null 2>&1
+				fi
+				dbg TEXT ", done\n\n" -n
+				if [ $OPENED -eq $TRUE ]; then
 					break
 				fi
-				[ $DEBUG -eq $TRUE ] && msg TEXT ", umount $MD" -n
-				umount $MD 2>/dev/null
-				[ $DEBUG -eq $TRUE ] && msg TEXT ", done\n\n" -n
 			else
-				[ $DEBUG -eq $TRUE ] && msg TEXT ", device `busybox basename $SFS` ignored" -n
+				dbg TEXT ", device `busybox basename $SFS` ignored" -n
 			fi
-			[ $DEBUG -eq $TRUE ] && msg CLEAR ""
+			dbg CLEAR ""
 		done
 	fi
 fi
@@ -157,13 +236,11 @@
 # clear existing usplash text and status messages
 [ $USPLASH -eq $TRUE ] && msg STATUS "                               " && msg CLEAR ""
 
-if [ $OPENED -eq $FALSE ]; then
+if [ $OPENED -ne $TRUE ]; then
 	msg TEXT "FAILED to find suitable USB key-file ..."
-	msg TEXT "Try to enter the LUKS password: "
-	read -r A </dev/console >/dev/null
-	echo -n "$A"
+	readpass "Try to enter the LUKS password: "
 else
-	msg TEXT "Success loading key-file from $DEV $LABEL"
+	msg TEXT "Success loading key-file from $SFS ($LABEL)"
 fi
 
 # 
