grub-devel
[Top][All Lists]
Advanced

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

[CRYPTOMOUNT-TEST 6/7] tests: Add grub-shell-luks-tester to facilitate f


From: Glenn Washburn
Subject: [CRYPTOMOUNT-TEST 6/7] tests: Add grub-shell-luks-tester to facilitate functional LUKS1/2 testing.
Date: Sun, 16 Aug 2020 19:05:17 -0500

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 Makefile.util.def                    |   6 +
 tests/util/grub-shell-luks-tester.in | 319 +++++++++++++++++++++++++++
 2 files changed, 325 insertions(+)
 create mode 100644 tests/util/grub-shell-luks-tester.in

diff --git a/Makefile.util.def b/Makefile.util.def
index d9e2bd84d..cfc71f1ab 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -742,6 +742,12 @@ script = {
   installdir = noinst;
 };
 
+script = {
+  name = grub-shell-luks-tester;
+  common = tests/util/grub-shell-luks-tester.in;
+  installdir = noinst;
+};
+
 script = {
   name = grub-fs-tester;
   common = tests/util/grub-fs-tester.in;
diff --git a/tests/util/grub-shell-luks-tester.in 
b/tests/util/grub-shell-luks-tester.in
new file mode 100644
index 000000000..01aaf6e4b
--- /dev/null
+++ b/tests/util/grub-shell-luks-tester.in
@@ -0,0 +1,319 @@
+#! @BUILD_SHEBANG@ -e
+
+# Compares GRUB script output with BASH output.
+# Copyright (C) 2009,2010  Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+
+# Initialize some variables.
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+datarootdir="@datarootdir@"
+builddir="@builddir@"
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_TARNAME=@PACKAGE_TARNAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+
+# Force build directory components
+PATH="${builddir}:$PATH"
+export PATH
+
+detached_header=
+keyfile=
+keyfile_offset=
+keyfile_size=
+KEYFILE_SIZE_MAX=4096
+
+# Usage: usage
+# Print the usage.
+usage () {
+    cat <<EOF
+Usage: $0 [OPTION] [SOURCE]
+Create a LUKS disk with cryptsetup, then verify that it is accessible by grub
+running in a QEMU instance.
+
+  -h, --help              print this message and exit
+  -v, --version           print the version information and exit
+  --modules=MODULES       pre-load specified modules MODULES
+  --qemu-opts=OPTIONS     extra options to pass to Qemu instance
+  --cs-opts=OPTIONS       extra options to pass to cryptsetup instance
+  --luks=1|2              Use LUKS1 or LUKS2 volumes
+  --detached-header       Use a detached header
+  --keyfile[=FILE]        Use a randomly generated key file of size 
$KEYFILE_SIZE_MAX if not
+                          given a FILE to use as the key file.
+
+$0 creates a LUKS disk with cryptsetup, then verify that it is accessible by
+grub running in a QEMU instance.
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+# Check the arguments.
+for option in "$@"; do
+    case "$option" in
+    -h | --help)
+       usage
+       exit 0 ;;
+    -v | --version)
+       echo "$0 (GNU GRUB ${PACKAGE_VERSION})"
+       exit 0 ;;
+    -d | --debug)
+        debug=$((${debug:-0}+1)) ;;
+    --modules=*)
+       ms=`echo "$option" | sed -e 's/--modules=//'`
+       modules="$modules,$ms" ;;
+    --qemu-opts=*)
+        qs=`echo "$option" | sed -e 's/--qemu-opts=//'`
+        qemuopts="$qemuopts $qs" ;;
+    --cs-opts=*)
+        qs=`echo "$option" | sed -e 's/--cs-opts=//'`
+        csopts="$csopts $qs" ;;
+    --luks=*)
+        qs=`echo "$option" | sed -e 's/--luks=//'`
+        csopts="$csopts --type luks$qs" ;;
+    --detached-header)
+        detached_header=1 ;;
+    --keyfile=*)
+        qs=`echo "$option" | sed -e 's/--keyfile=//'`
+        keyfile="$qs" ;;
+    --keyfile)
+        keyfile=1 ;;
+    -*)
+       echo "Unrecognized option \`$option'" 1>&2
+       usage
+       exit 3
+       ;;
+    *)
+       if [ "x${source}" != x ] ; then
+           echo "too many parameters at the end" 1>&2
+           usage
+           exit 4
+       fi
+       source="${option}" ;;
+    esac
+done
+
+# Make sure that the dm-crypto device is shutdown
+cleanup() {
+    if [ -e "$luksdev" ]; then
+        cryptsetup close "$luksdev"
+    fi
+    [ -z "$debug" ] && rm -rf "$lukstestdir"
+}
+trap cleanup EXIT INT TERM KILL QUIT
+
+get_random_bytes() {
+    local NUM_BYTES=$1
+    dd if=/dev/urandom bs=512 count=$((($NUM_BYTES / 512)+2)) 2>/dev/null \
+        | tr -d '\0' | dd bs=1 count=$(($NUM_BYTES)) 2>/dev/null
+}
+
+# create a random directory to be hold generated files
+lukstestdir="`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 20
+luksfile=$lukstestdir/luks.disk
+lukshdrfile=$lukstestdir/luks.header
+lukskeyfile=$lukstestdir/luks.key
+vfile=$lukstestdir/mnt/test.verify
+vtext="TEST VERIFIED"
+testvars=$lukstestdir/testvars
+testoutput=$lukstestdir/testoutput
+password=testpass
+
+[ -n "$debug" ] && echo "LUKS TEST directory: $lukstestdir" >&2
+
+# If testing keyfiles, create a big one.
+if [ -e "$keyfile" ]; then
+    password=`cat "$keyfile"`
+elif [ -n "$keyfile" ]; then
+    password=`get_random_bytes $KEYFILE_SIZE_MAX`
+fi
+
+if [ -n "$detached_header" ]; then
+    csopts="$csopts --header $lukshdrfile"
+fi
+
+# create the key file
+echo -n "$password" > $lukskeyfile
+
+# Create a very small LUKS container for the test
+truncate -s 20M $luksfile || exit 21
+
+# Format the luks disk file
+cryptsetup luksFormat -q $csopts $luksfile $lukskeyfile || exit 22
+
+# Look for --keyfile-offset and --keyfile-size options in the cryptsetup
+# options, and process them specially.
+csopen_opts=
+get_args=0
+varname=
+for option in $csopts; do
+    if [ "$get_args" -gt 0 ]; then
+        csopen_opts=" $csopen_opts $option"
+        get_args=$(($get_args - 1))
+        eval ${varname}=$option
+        continue
+    fi
+
+    case "$option" in
+    --keyfile-offset)
+        varname=keyfile_offset
+        get_args=1 ;;
+    --keyfile-offset=*)
+        keyfile_offset=`echo "$option" | sed -e 's/--keyfile-offset=//'` ;;
+    --keyfile-size | -l)
+        varname=keyfile_size
+        get_args=1 ;;
+    --keyfile-size=*)
+        keyfile_size=`echo "$option" | sed -e 's/--keyfile-size=//'` ;;
+    *)
+        continue ;;
+    esac
+
+    csopen_opts=" $csopen_opts $option"
+done
+
+# Open LUKS device
+luksdev=/dev/mapper/`basename $lukstestdir`
+cryptsetup open ${detached_header:+--header $lukshdrfile} $csopen_opts \
+    --key-file $lukskeyfile $luksfile `basename $luksdev` || exit 23
+
+# Make filesystem on the luks disk
+mkfs.vfat $luksdev >/dev/null 2>&1 || exit 24
+
+# Add verification file to filesystem
+mkdir $lukstestdir/mnt
+mount $luksdev $lukstestdir/mnt || exit 25
+echo "$vtext" > $vfile
+
+# Unmount filesystem
+umount $lukstestdir/mnt || exit 26
+
+. "@builddir@/grub-core/modinfo.sh"
+
+if [ x"${grub_modinfo_platform}" = xemu ]; then
+    grub_testvars="(host)$testvars"
+    grub_key_file="(host)$lukskeyfile"
+    grub_lukshdr_file="(host)$lukshdrfile"
+else
+    grub_testvars="/testvars"
+    grub_key_file="/keyfile"
+    grub_lukshdr_file="/luks.header"
+fi
+
+
+# Can not use --disk with a raw LUKS container because it appears qemu
+# tries to convert the image to and is failing with:
+#  "Parameter 'key-secret' is required for cipher"
+qemuopts="$qemuopts -drive file=$luksfile,index=0,media=disk,format=raw"
+
+# Add crypto modules
+modules="$modules cryptodisk luks luks2 fat"
+
+# Create randomly generated trim line
+trim_line=`mktemp -u XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`
+
+# Create vars to import into grub script
+cat >$testvars <<EOF
+grub_debug="$debug"
+grub_lukshdr_file="$grub_lukshdr_file"
+grub_key_file="$grub_key_file"
+grub_keyfile_offset="$keyfile_offset"
+grub_keyfile_size="$keyfile_size"
+vfilename="`basename $vfile`"
+vtext="$vtext"
+trim_line="$trim_line"
+EOF
+
+# If testing keyfiles, do not use password variable
+if [ -z "$keyfile" ]; then
+    echo "grub_password=\"$password\"" >>$testvars
+fi
+
+grub_shell_opts="$grub_shell_opts --trim=${trim_line}"
+if [ -n "$keyfile" ]; then
+    grub_shell_opts="$grub_shell_opts 
--files=${keyfile:+${grub_key_file}=${lukskeyfile}}"
+fi
+
+if [ -n "$detached_header" ]; then
+    grub_shell_opts="$grub_shell_opts 
--files=${detached_header:+${grub_lukshdr_file}=${lukshdrfile}}"
+fi
+
+# Run the test in grub-shell
+@builddir@/grub-shell ${debug:+--debug} $grub_shell_opts \
+    --modules="$modules" --qemu-opts="$qemuopts" \
+    --files="${grub_testvars}=${testvars}" \
+    >$testoutput <<'EOF'
+
+search -n -f --set=testvarsdev /testvars
+if [ "$?" -ne 0 ]; then
+    echo "Could not find testvars file."
+    # FIXME: Apparently halt doesn't work on some platforms?
+    halt
+    reboot
+    exit
+fi
+
+. ($testvarsdev)/testvars
+
+# If key file exists, use it instead of password
+if [ -e "$grub_key_file" ]; then
+    cryptomount_opts="$cryptomount_opts -k $grub_key_file"
+else
+    cryptomount_opts="$cryptomount_opts -p $grub_password"
+fi
+
+if [ -n "$grub_keyfile_offset" ]; then
+    cryptomount_opts="$cryptomount_opts -O $grub_keyfile_offset"
+fi
+
+if [ -n "$grub_keyfile_size" ]; then
+    cryptomount_opts="$cryptomount_opts -S $grub_keyfile_size"
+fi
+
+if [ -e "$grub_lukshdr_file" ]; then
+    cryptomount_opts="$cryptomount_opts -H $grub_lukshdr_file"
+fi
+
+cdisk=crypto0
+
+if test -n "$grub_debug" -a "$grub_debug" -gt 0; then
+    echo cmd: cryptomount $cryptomount_opts (hd0)
+elif test -n "$grub_debug" -a "$grub_debug" -gt 1; then
+    set debug=all
+fi
+cryptomount $cryptomount_opts (hd0)
+ret="$?"
+if test -n "$grub_debug" -a "$grub_debug" -eq 2; then
+    set debug=
+fi
+
+echo "$trim_line"
+if test $ret -eq 0; then
+    cat ($cdisk)/$vfilename
+else
+    echo "cryptomount failed: $ret"
+fi
+EOF
+ret=$?
+
+if [ "$ret" -eq 0 ]; then
+    v="`cat $testoutput`"
+    if test "$v" != "$vtext"; then echo "error: test not verified [$v]" >&2; 
exit 1; fi
+else
+    echo "grub-shell exited with error: $ret" >&2
+    exit 27
+fi
+
+exit $ret
-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]