#!/bin/bash

[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
TST_DIR=luks1-images
MAP=luks1tst
KEYFILE=keyfile1

CRYPTOCHECK=./crypto-check

if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then
	CRYPTSETUP_VALGRIND=$CRYPTSETUP
else
	CRYPTSETUP_VALGRIND=../.libs/cryptsetup
	CRYPTSETUP_LIB_VALGRIND=../.libs
fi

[ -z "$srcdir" ] && srcdir="."

remove_mapping()
{
	[ -b /dev/mapper/$MAP ] && dmsetup remove --retry $MAP
	rm -rf $TST_DIR
}

fail()
{
	[ -n "$1" ] && echo "$1"
	echo " [FAILED]"
	echo "FAILED backtrace:"
	while caller $frame; do ((frame++)); done
	remove_mapping
	exit 2
}

_sigchld() { local c=$?; [ $c -eq 139 ] && fail "Segfault"; [ $c -eq 134 ] && fail "Aborted"; }
trap _sigchld CHLD

skip()
{
	[ -n "$1" ] && echo "$1"
	remove_mapping
	exit 77
}

valgrind_setup()
{
	command -v valgrind >/dev/null || fail "Cannot find valgrind."
	[ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
	[ ! -f valg.sh ] && fail "Unable to get location of valg runner script."
	if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then
		export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
	fi
}

valgrind_run()
{
	INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
}

remove_imgs()
{
	echo "WARNING: $1 not available, not testing some images."
	rm $(ls $TST_DIR/*$1*.img)
}

test_one()
{
	$CRYPTOCHECK cipher $1 $2 $3 || remove_imgs "$1-$2"
}

test_required()
{
	echo "REQUIRED KDF TEST"
	$CRYPTOCHECK hash whirlpool || remove_imgs whirlpool

	echo "REQUIRED CIPHERS TEST"
	test_one aes xts 256
	test_one twofish xts 256
	test_one serpent xts 256
	test_one aes cbc 256
	test_one aes lrw 256
}

export LANG=C
[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
[ ! -x "$CRYPTOCHECK" ] && skip "Cannot find $CRYPTOCHECK, test skipped."
command -v blkid >/dev/null || skip "blkid tool required, test skipped."
[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
[ ! -d $TST_DIR ] && tar xJf $srcdir/luks1-images.tar.xz --no-same-owner
test_required

echo "PASSPHRASE CHECK"
for file in $(ls $TST_DIR/luks1_*) ; do
	echo -n " $file"
	$CRYPTSETUP luksOpen -d $TST_DIR/$KEYFILE $file --test-passphrase 2>/dev/null
	ret=$?
	# ignore missing whirlpool (pwd failed is exit code 2)
	[ $ret -eq 1 ] && (echo $file | grep -q -e "whirlpool") && echo " [N/A]" && continue
	# ignore flawed whirlpool (pwd failed is exit code 2)
	[ $ret -eq 2 ] && (echo $file | grep -q -e "whirlpool") && \
		($CRYPTSETUP luksDump $file --debug | grep -q -e "flawed whirlpool") && \
		echo " [IGNORED (flawed Whirlpool library)]" && continue
	[ $ret -ne 0 ] && fail
	echo " [OK]"
done

if [ $(id -u) != 0 ]; then
	echo "WARNING: You must be root to run activation part of test, test skipped."
	remove_mapping
	exit 0
fi

echo "ACTIVATION FS UUID CHECK"
for file in $(ls $TST_DIR/luks1_*) ; do
	echo -n " $file"
	$CRYPTSETUP luksOpen -d $TST_DIR/$KEYFILE $file $MAP 2>/dev/null
	ret=$?
	# ignore missing whirlpool (pwd failed is exit code 2)
	[ $ret -eq 1 ] && (echo $file | grep -q -e "whirlpool") && echo " [N/A]" && continue
	# ignore flawed whirlpool (pwd failed is exit code 2)
	[ $ret -eq 2 ] && (echo $file | grep -q -e "whirlpool") && \
		($CRYPTSETUP luksDump $file --debug | grep -q -e "flawed whirlpool") && \
		echo " [IGNORED (flawed Whirlpool library)]" && continue
	[ $ret -ne 0 ] && fail
	$CRYPTSETUP status $MAP >/dev/null || fail
	$CRYPTSETUP status /dev/mapper/$MAP >/dev/null || fail
	UUID=$(blkid -p -o value -s UUID /dev/mapper/$MAP)
	$CRYPTSETUP remove $MAP || fail
	[ "$UUID" != "DEAD-BABE" ] && fail "UUID check failed."
	echo " [OK]"
done

remove_mapping
exit 0
