#!/bin/sh

set -e

PREREQ=""

prereqs()
{
	echo "$PREREQ"
}

case $1 in
prereqs)
	prereqs
	exit 0
	;;
esac

. /usr/share/initramfs-tools/hook-functions

get_root_device() {
    [ -r /etc/fstab ] || return

    grep '^[^#]' /etc/fstab | ( \
	while read dev mount type options dump pass; do
	    if [ "${mount}" = "/" ]; then
		echo "rootdev=\"${dev}\" rootoptions=\"${options}\""
		return
	    fi
	done )
}

cipher_modname() {
    # When changing this, don't forget to update the list of all known
    # cipher modules in the iterate_cipher_module call near the end
    # of this file. Also update the copy in initramfs-tools-script
    case "$1" in
	NONE|XOR|AES*)
	    ;;
	twofish*)
	    echo loop_twofish
	    ;;
	blowfish*)
	    echo loop_blowfish
	    ;;
	serpent*)
	    echo loop_serpent
	    ;;
	mars*|rc6*|tripleDES)
	    echo "WARNING| (loop-aes) Don't know how to handle encryption type $1" 1>&2
	    ;;
	*)
	    echo "WARNING| (loop-aes) Unknown encryption type $1" 1>&2
	    ;;
    esac
}

get_root_opts() {
    # If you change this, keep the version in initramfs-tools-script
    # in sync.
    local opt cipher
    local IFS=", "
    for opt in $rootoptions; do
	case "$opt" in
	    encryption=*)
		module="$(cipher_modname "${opt#encryption=}")"
		if [ -n "$module" ]; then
		    rootencryption="${rootencryption}${rootencryption:+:}${module}"
		fi
		loopaes_opts="${loopaes_opts},${opt}"
		;;
	    offset=*)
		loopaes_opts="${loopaes_opts},${opt}"
		;;
	    sizelimit=*)
		loopaes_opts="${loopaes_opts},${opt}"
		;;
	    pseed=*)
		loopaes_opts="${loopaes_opts},${opt}"
		;;
	    phash=*)
		loopaes_opts="${loopaes_opts},${opt}"
		;;
	    loinit=*)
		loopaes_opts="${loopaes_opts},${opt}"
		;;
	    itercountk=*)
		loopaes_opts="${loopaes_opts},${opt}"
		;;
	    gpgkey=*)
		rootgpgkey=${opt#gpgkey=}
		;;
	    gpghome=*)
		rootgpghome=${opt#gpghome=}
		;;
	    loop=*)
		rootloop=${opt#loop=}
		;;
	    *)
		# Presumably a non-supported or filesystem option
		;;
	esac
    done
}

# Find out which device root is on (sets rootdev and rootoptions)
eval $(get_root_device)
if [ -z "${rootdev}" ]; then
    echo "WARNING: (loop-aes) Could not determine root device. Skipping." >&2
    exit 0
fi

get_root_opts
loopaes_opts="${loopaes_opts},loop=${rootloop}"

detected=no
configured=no
forced=no

if [ -n "${rootloop}" ]; then
    detected=yes
fi

case "${INITRAMFS_LOOPAES}" in
    0|n|no|off)
	;;
    1|y|yes|on)
	configured=yes
	forced=yes
	;;
    auto|'')
	configured="${detected}"
	;;
    *)
	echo "WARNING! (loop-aes) ignoring invalid INITRAMFS_LOOPAES value: '${INITRAMFS_LOOPAES}'" 1>&2
	;;
esac

if [ "$configured" = no ]; then
    if [ "$detected" = yes ]; then
	cat >&2 <<END_WARN
WARNING: Your root partition appears to be encrypted with loop-AES, but
the initramfs support for loop-AES is disabled. The resulting initramfs
will most likely NOT be able to boot your system. Please make sure
that you have a good initramfs before the next reboot.
END_WARN
    fi
    exit 0
fi

case "${rootdev}" in
    /dev/loop*)
	cat >&2 <<END_WARN
WARNING: (loop-aes) According to /etc/fstab, your root device is on a
loop device. Probably you use the wrong syntax for this script in
/etc/fstab. See /usr/share/doc/loop-aes-utils/README . The initramfs
being created will NOT be able to mount your loop-AES encrypted root
automatically.
END_WARN
	;;
    *)
	if [ "$detected" = no ]; then
	    cat >&2 <<END_WARN
WARNING: (loop-aes) Support for loop-AES is forced on but this script was
unable to determine the loop-AES settings from /etc/fstab. Assuming
you want the possibility of using loopaesopts kernel command-line
option (and/or have losetup available in the initramfs shell), but
don't want a loop-AES-encrypted root to be mounted automatically by
default.

Note that you need to ensure that the keys for the encrypted root fs
you want to load through the loopaesopts kernel command-line option
are reachable from the initramfs.
END_WARN
	fi
	;;
esac

# Prepare the initramfs
if [ -n "${rootgpgkey}" ]; then
    mkdir ${DESTDIR}/keys/
    cp "${rootgpgkey}" ${DESTDIR}/keys/rootkeyfile.gpg
    copy_exec /usr/bin/gpg /bin/
    loopaes_opts="${loopaes_opts},gpgkey=/keys/rootkeyfile.gpg"
fi

if [ -n "${rootgpghome}" ]; then
    cp -R "${rootgpghome}" ${DESTDIR}/.gnupg
else
    mkdir ${DESTDIR}/.gnupg/
fi
loopaes_opts="${loopaes_opts},gpghome=/.gnupg"

echo "LOOPAESOPTS=\"$loopaes_opts\"" > ${DESTDIR}/conf/conf.d/loopaesroot

copy_exec /sbin/losetup /sbin/

manual_add_modules loop
if [ "${forced}" = no ]; then
    manual_add_modules $rootencryption
else
    for mod in loop_serpent loop_blowfish loop_twofish; do
        manual_add_modules $mod
    done
fi

# Check that loop is really loop-AES
have_loopaes=no
for mod in $(find $DESTDIR -name loop.ko -or -name loop.o); do
    if grep -q loop_compute_md5_iv_v3 $mod; then
        have_loopaes=yes
        break
    fi
done

if [ "$have_loopaes" = no ]; then
    cat >&2 <<END_WARN
ERROR: (loop-AES): This initramfs does not include the required
loop-AES kernel module. It will most likely NOT be able to boot 
your system. Please make sure that you install the loop-AES kernel
module and regenerate the initramfs before the next reboot.
END_WARN
    exit 1
fi

# Done
exit 0
