[Pkg-cryptsetup-devel] Bug#358452: cryptsetup: new version of
scripts
David Härdeman
david at 2gen.com
Sat Apr 8 23:29:25 UTC 2006
Hey,
this is an updated version of the hook and script for adding cryptoroot
functionality to cryptsetup/initramfs.
The script has seen minor changes to address the issues raised by
Maximilian, while the hook script has undergone some major changes.
It now expects the root volume to be present in /etc/crypttab, and if it
is, the modules to include in the initramfs are decided by looking at
the /etc/crypttab options.
The settings are then automatically added to the generated initramfs
image.
As for compability with the (old) initrd ways of doing thing, as far as
I could tell, initrd simply deduced at build time whether or not root
was encrypted and then hardcoded that knowledge within the initrd, so
there is no mismatch in options between the two as initrd had none...
Regards,
David
PS
This should of course still not be applied until after 348147 is fixed.
-------------- next part --------------
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
. /usr/share/initramfs-tools/hook-functions
find_root_device() {
[ -r /etc/fstab ] || return
grep '^[^#]' /etc/fstab | ( \
while read device mount type options dump pass; do
if [ "$mount" = "/" ]; then
echo "$device"
return
fi
done )
}
get_root_opts() {
local node rootopts
node=$1
[ -z $node ] && return
[ -r /etc/crypttab ] || return
rootopts=$( grep ^$node /etc/crypttab | \
head -1 | sed 's/[[:space:]]+*/ /g' | cut -d " " -f 4-)
echo "$rootopts"
[ ! -z $rootopts ] || return 1
return 0
}
get_root_modules() {
local rootopts
rootopts=$1
[ ! -z $rootopts ] || return
echo "dm_mod"
echo "dm_crypt"
local IFS=", "
for opt in $rootopts; do
# Does option start with cipher=?
value=${opt#cipher=}
[ $value != $opt ] || continue
# Add the cipher to the list of modules
cipher=${value%%-*}
echo $cipher
# Possibly add a hash as well
hash=${value##*:}
[ ! -z $hash -o $hash != $value ] || continue
echo $hash
done
}
get_root_initramfsopts() {
local rootnode rootopts
rootnode=$1
rootopts=$2
[ ! -z $rootnode ] || return
[ ! -z $rootopts ] || return
echo -n "node=$rootnode"
local IFS=", "
for opt in $rootopts; do
case $opt in
cipher=*)
echo -n ",$opt"
;;
hash=*)
echo -n ",$opt"
;;
size=*)
echo -n ",$opt"
;;
*)
# Presumably a non-supported option
;;
esac
done
echo ""
}
# Find out which device root is on
rootdev=$(find_root_device)
[ ! -z $rootdev ] || exit 0
# Check that it is a node under /dev/mapper/
node=${rootdev#/dev/mapper/}
[ "$node" != $rootdev ] || exit 0
# Get crypttab root options
rootopts=$(get_root_opts $node $opts)
[ ! -z $rootopts ] || exit 0
# Calculate needed modules
modules=$(get_root_modules $rootopts | sort | uniq)
for x in $modules; do
manual_add_modules ${x}
done
# Check the root options to write to the initramfs
initramfsopts=$(get_root_initramfsopts $node $rootopts)
echo "CRYPTOPTS=\"$initramfsopts\"" > ${DESTDIR}/conf/conf.d/cryptroot
copy_exec /sbin/cryptsetup /sbin
copy_exec /sbin/dmsetup /sbin
[ -x "/etc/mkinitramfs/cryptgetpw" ] && copy_exec /etc/mkinitramfs/cryptgetpw /sbin
exit 0
-------------- next part --------------
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
esac
# Do we have any settings from the /conf/conf.d/cryptroot file?
[ -r /conf/conf.d/cryptroot ] && . /conf/conf.d/cryptroot
cryptopts="${CRYPTOPTS}"
# Does the kernel boot command line override them?
for x in $(cat /proc/cmdline); do
case $x in
cryptopts=*)
cryptopts=${x#cryptopts=}
;;
esac
done
# Sanity checks
eval $(fstype < ${ROOT})
if [ "$FSTYPE" != "luks" -a -z "$cryptopts" ]; then
# Apparently the root partition isn't encrypted
echo "No cryptoroot configured or detected"
exit 0
fi
# There are two possible scenarios here:
#
# 1) The fstype of the root device has been identified as "luks"
# 2) The fstype is not "luks" but cryptopts has been set
#
# The former means that we use the luks functionality of cryptsetup, the
# latter means that we do it the old-fashioned way.
# Start by parsing some options, all options are relevant to regular cryptsetup
# but only cryptnode is relevant to luks which picks up the rest of the
# parameters by reading the partition header
cryptcipher=aes-cbc-essiv:sha256
cryptsize=256
crypthash=sha256
cryptnode=cryptroot
if [ -n "$cryptopts" ]; then
IFS=" ,"
for x in $cryptopts; do
case $x in
hash=*)
crypthash=${x#hash=}
;;
size=*)
cryptsize=${x#size=}
;;
cipher=*)
cryptcipher=${x#cipher=}
;;
node=*)
cryptnode=${x#node=}
;;
esac
done
unset IFS
fi
NEWROOT="/dev/mapper/$cryptnode"
# Check which cryptosolution we want
if [ "$FSTYPE" = "luks" ]; then
# 1) The fstype of the root device has been identified as "luks"
cryptcreate="/sbin/cryptsetup luksOpen $ROOT $cryptnode"
cryptremove=""
else
# 2) The fstype is not "luks" but cryptopts have been set
cryptcreate="/sbin/cryptsetup -c $cryptcipher -s $cryptsize -h $crypthash create $cryptnode $ROOT"
cryptremove="/sbin/cryptsetup remove $cryptnode"
fi
# Loop until we have a satisfactory password
while [ 1 ]; do
if [ -x "/sbin/cryptgetpw" ]; then
/sbin/cryptgetpw | $cryptcreate
else
$cryptcreate
fi
if [ $? -eq 0 ]; then
fstype < "$NEWROOT" > /dev/.initramfs/source.me
if [ $? -eq 0 ]; then
. /dev/.initramfs/source.me
if [ "$FSTYPE" != "unknown" ]; then
break
fi
fi
fi
echo "$0: cryptsetup failed or fstype not recognized, bad password or options?"
$cryptremove
sleep 3
done
# init can now pick up new FSTYPE, FSSIZE and ROOT
echo "ROOT=\"$NEWROOT\"" >> /dev/.initramfs/source.me
exit 0
More information about the Pkg-cryptsetup-devel
mailing list