Blame tests/tpmtool_test.sh

Packit aea12f
#!/bin/sh
Packit aea12f
Packit aea12f
# Copyright (C) 2018 IBM Corporation
Packit aea12f
#
Packit aea12f
# Author: Stefan Berger
Packit aea12f
#
Packit aea12f
# This file is part of GnuTLS.
Packit aea12f
#
Packit aea12f
# GnuTLS is free software; you can redistribute it and/or modify it
Packit aea12f
# under the terms of the GNU General Public License as published by the
Packit aea12f
# Free Software Foundation; either version 3 of the License, or (at
Packit aea12f
# your option) any later version.
Packit aea12f
#
Packit aea12f
# GnuTLS is distributed in the hope that it will be useful, but
Packit aea12f
# WITHOUT ANY WARRANTY; without even the implied warranty of
Packit aea12f
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit aea12f
# General Public License for more details.
Packit aea12f
#
Packit aea12f
# You should have received a copy of the GNU General Public License
Packit aea12f
# along with GnuTLS; if not, write to the Free Software Foundation,
Packit aea12f
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit aea12f
Packit aea12f
srcdir="${srcdir:-.}"
Packit aea12f
CERTTOOL="${CERTTOOL:-../src/certtool${EXEEXT}}"
Packit aea12f
TPMTOOL="${TPMTOOL:-../src/tpmtool${EXEEXT}}"
Packit aea12f
Packit aea12f
if [ "$(id -u)" -ne 0 ]; then
Packit aea12f
	echo "Need to be root to run this test."
Packit aea12f
	exit 77
Packit aea12f
fi
Packit aea12f
Packit aea12f
if [ -z "$(which swtpm 2>/dev/null)" ]; then
Packit aea12f
	echo "Need swtpm package to run this test."
Packit aea12f
	exit 77
Packit aea12f
fi
Packit aea12f
Packit aea12f
if [ -z "$(which tcsd 2>/dev/null)" ]; then
Packit aea12f
	echo "Need tcsd (TrouSerS) package to run this test."
Packit aea12f
	exit 77
Packit aea12f
fi
Packit aea12f
Packit aea12f
if [ -z "$(which tpm_createek 2>/dev/null)" ]; then
Packit aea12f
	echo "Need tpm_createek from tpm-tools package to run this test."
Packit aea12f
	exit 77
Packit aea12f
fi
Packit aea12f
Packit aea12f
if [ -z "$(which ncat 2>/dev/null)" ]; then
Packit aea12f
	echo "Need ncat from nmap-ncat package to run this test."
Packit aea12f
	exit 77
Packit aea12f
fi
Packit aea12f
Packit aea12f
if [ -z "$(which expect 2>/dev/null)" ]; then
Packit aea12f
	echo "Need expect from expect package to run this test."
Packit aea12f
	exit 77
Packit aea12f
fi
Packit aea12f
Packit aea12f
$TPMTOOL --help >/dev/null
Packit aea12f
if [ $? -ne 0 ]; then
Packit aea12f
	echo "tpmtool cannot show help screen (TPMTOOL=$TPMTOOL)."
Packit aea12f
	exit 77
Packit aea12f
fi
Packit aea12f
Packit aea12f
$CERTTOOL --help >/dev/null
Packit aea12f
if [ $? -ne 0 ]; then
Packit aea12f
	echo "certtool cannot show help screen (CERTTOOL=$CERTTOOL)."
Packit aea12f
	exit 77
Packit aea12f
fi
Packit aea12f
Packit aea12f
. "${srcdir}/scripts/common.sh"
Packit aea12f
Packit aea12f
workdir=$(mktemp -d)
Packit aea12f
Packit aea12f
SWTPM_SERVER_PORT=12345
Packit aea12f
SWTPM_CTRL_PORT=$((SWTPM_SERVER_PORT + 1))
Packit aea12f
SWTPM_PIDFILE=${workdir}/swtpm.pid
Packit aea12f
TCSD_LISTEN_PORT=12347
Packit aea12f
export TSS_TCSD_PORT=$TCSD_LISTEN_PORT
Packit aea12f
Packit aea12f
cleanup()
Packit aea12f
{
Packit aea12f
	stop_tcsd
Packit aea12f
	if [ -n "$workdir" ]; then
Packit aea12f
		rm -rf $workdir
Packit aea12f
	fi
Packit aea12f
}
Packit aea12f
Packit aea12f
start_swtpm()
Packit aea12f
{
Packit aea12f
	local workdir="$1"
Packit aea12f
Packit aea12f
	local res
Packit aea12f
Packit aea12f
	swtpm socket \
Packit aea12f
		--flags not-need-init \
Packit aea12f
		--pid file=$SWTPM_PIDFILE \
Packit aea12f
		--tpmstate dir=$workdir \
Packit aea12f
		--server type=tcp,port=$SWTPM_SERVER_PORT,disconnect \
Packit aea12f
		--ctrl type=tcp,port=$SWTPM_CTRL_PORT &
Packit aea12f
Packit aea12f
	if wait_for_file $SWTPM_PIDFILE 3; then
Packit aea12f
		echo "Starting the swtpm failed"
Packit aea12f
		return 1
Packit aea12f
	fi
Packit aea12f
Packit aea12f
	SWTPM_PID=$(cat $SWTPM_PIDFILE)
Packit aea12f
	kill -0 ${SWTPM_PID}
Packit aea12f
	if [ $? -ne 0 ]; then
Packit aea12f
		echo "swtpm must have terminated"
Packit aea12f
		return 1
Packit aea12f
	fi
Packit aea12f
Packit aea12f
	# Send TPM_Startup to TPM
Packit aea12f
	res="$(/bin/echo -en '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01' |
Packit aea12f
		ncat localhost ${SWTPM_SERVER_PORT} | od -tx1 -An)"
Packit aea12f
	exp=' 00 c4 00 00 00 0a 00 00 00 00'
Packit aea12f
	if [ "$res" != "$exp" ]; then
Packit aea12f
		echo "Did not get expected response from TPM_Startup(ST_CLEAR)"
Packit aea12f
		echo "expected: $exp"
Packit aea12f
		echo "received: $res"
Packit aea12f
		return 1
Packit aea12f
	fi
Packit aea12f
Packit aea12f
	return 0
Packit aea12f
}
Packit aea12f
Packit aea12f
stop_swtpm()
Packit aea12f
{
Packit aea12f
	if [ -n "$SWTPM_PID" ]; then
Packit aea12f
		terminate_proc $SWTPM_PID
Packit aea12f
		unset SWTPM_PID
Packit aea12f
	fi
Packit aea12f
}
Packit aea12f
Packit aea12f
start_tcsd()
Packit aea12f
{
Packit aea12f
	local workdir="$1"
Packit aea12f
Packit aea12f
	local tcsd_conf=$workdir/tcsd.conf
Packit aea12f
	local tcsd_system_ps_file=$workdir/system_ps_file
Packit aea12f
	local tcsd_pidfile=$workdir/tcsd.pid
Packit aea12f
Packit aea12f
	start_swtpm "$workdir"
Packit aea12f
	[ $? -ne 0 ] && return 1
Packit aea12f
Packit aea12f
	cat <<_EOF_ > $tcsd_conf
Packit aea12f
port = $TCSD_LISTEN_PORT
Packit aea12f
system_ps_file = $tcsd_system_ps_file
Packit aea12f
_EOF_
Packit aea12f
Packit aea12f
	chown tss:tss $tcsd_conf
Packit aea12f
	chmod 0600 $tcsd_conf
Packit aea12f
Packit aea12f
	bash -c "TCSD_USE_TCP_DEVICE=1 TCSD_TCP_DEVICE_PORT=$SWTPM_SERVER_PORT tcsd -c $tcsd_conf -e -f &>/dev/null & echo \$! > $tcsd_pidfile; wait" &
Packit aea12f
	BASH_PID=$!
Packit aea12f
Packit aea12f
	if wait_for_file $tcsd_pidfile 3; then
Packit aea12f
		echo "Could not get TCSD's PID file"
Packit aea12f
		return 1
Packit aea12f
	fi
Packit aea12f
Packit aea12f
	TCSD_PID=$(cat $tcsd_pidfile)
Packit aea12f
	return 0
Packit aea12f
}
Packit aea12f
Packit aea12f
stop_tcsd()
Packit aea12f
{
Packit aea12f
	if [ -n "$TCSD_PID" ]; then
Packit aea12f
		terminate_proc $TCSD_PID
Packit aea12f
		unset TCSD_PID
Packit aea12f
	fi
Packit aea12f
	stop_swtpm
Packit aea12f
}
Packit aea12f
Packit aea12f
run_tpm_takeownership()
Packit aea12f
{
Packit aea12f
	local owner_password="$1"
Packit aea12f
	local srk_password="$2"
Packit aea12f
Packit aea12f
	local prg out rc
Packit aea12f
	local parm_z=""
Packit aea12f
Packit aea12f
	if [ -z "$srk_password" ]; then
Packit aea12f
		parm_z="--srk-well-known"
Packit aea12f
	fi
Packit aea12f
Packit aea12f
	prg="set parm_z \"$parm_z\"
Packit aea12f
		spawn tpm_takeownership \$parm_z
Packit aea12f
		expect {
Packit aea12f
			\"Enter owner password:\"
Packit aea12f
				{ send \"$owner_password\n\" }
Packit aea12f
		}
Packit aea12f
		expect {
Packit aea12f
			\"Confirm password:\"
Packit aea12f
				{ send \"$owner_password\n\" }
Packit aea12f
		}
Packit aea12f
		if { \$parm_z == \"\" } {
Packit aea12f
			expect {
Packit aea12f
				\"Enter SRK password:\"
Packit aea12f
					{ send \"$srk_password\n\" }
Packit aea12f
			}
Packit aea12f
			expect {
Packit aea12f
				\"Confirm password:\"
Packit aea12f
					{ send \"$srk_password\n\" }
Packit aea12f
			}
Packit aea12f
		}
Packit aea12f
		expect {
Packit aea12f
			eof
Packit aea12f
		}
Packit aea12f
		catch wait result
Packit aea12f
		exit [lindex \$result 3]
Packit aea12f
	"
Packit aea12f
	out=$(expect -c "$prg")
Packit aea12f
	rc=$?
Packit aea12f
	echo "$out"
Packit aea12f
	return $rc
Packit aea12f
}
Packit aea12f
Packit aea12f
setup_tcsd()
Packit aea12f
{
Packit aea12f
	local workdir="$1"
Packit aea12f
	local owner_password="$2"
Packit aea12f
	local srk_password="$3"
Packit aea12f
Packit aea12f
	local msg
Packit aea12f
Packit aea12f
	start_tcsd "$workdir"
Packit aea12f
	[ $? -ne 0 ] && return 1
Packit aea12f
Packit aea12f
	tpm_createek
Packit aea12f
	[ $? -ne 0 ] && {
Packit aea12f
		echo "Could not create EK"
Packit aea12f
		return 1
Packit aea12f
	}
Packit aea12f
	msg="$(run_tpm_takeownership "$owner_password" "$srk_password")"
Packit aea12f
	[ $? -ne 0 ] && {
Packit aea12f
		echo "Could not take ownership of TPM"
Packit aea12f
		echo "$msg"
Packit aea12f
		return 1
Packit aea12f
	}
Packit aea12f
	return 0
Packit aea12f
}
Packit aea12f
Packit aea12f
run_tpmtool()
Packit aea12f
{
Packit aea12f
	local srk_password="$1"
Packit aea12f
	local key_password="$2"
Packit aea12f
Packit aea12f
	shift 2
Packit aea12f
Packit aea12f
	local prg out rc
Packit aea12f
Packit aea12f
	prg="spawn $TPMTOOL $@
Packit aea12f
		expect {
Packit aea12f
			\"Enter SRK password:\" {
Packit aea12f
				send \"$srk_password\n\"
Packit aea12f
				exp_continue
Packit aea12f
			}
Packit aea12f
			\"Enter key password:\" {
Packit aea12f
				send \"$key_password\n\"
Packit aea12f
				exp_continue
Packit aea12f
			}
Packit aea12f
			\"tpmkey:\" {
Packit aea12f
				exp_continue
Packit aea12f
			}
Packit aea12f
			eof
Packit aea12f
		}
Packit aea12f
		catch wait result
Packit aea12f
		exit [lindex \$result 3]
Packit aea12f
	"
Packit aea12f
	out=$(expect -c "$prg")
Packit aea12f
	rc=$?
Packit aea12f
	echo "$out"
Packit aea12f
	return $rc
Packit aea12f
}
Packit aea12f
Packit aea12f
tpmtool_test()
Packit aea12f
{
Packit aea12f
	local workdir="$1"
Packit aea12f
	local owner_password="$2"
Packit aea12f
	local srk_password="$3"
Packit aea12f
	local key_password="$4"
Packit aea12f
	local register=$5  # whether to --register the key
Packit aea12f
Packit aea12f
	local params msg tpmkeyurl
Packit aea12f
	local tpmpubkey=${workdir}/tpmpubkey.pem
Packit aea12f
	local tpmca=${workdir}/tpmca.pem
Packit aea12f
	local template=${workdir}/template
Packit aea12f
	local tpmkey=${workdir}/tpmkey.pem # if --register is not used
Packit aea12f
Packit aea12f
	setup_tcsd "$workdir" "$owner_password" "$srk_password"
Packit aea12f
	[ $? -ne 0 ] && return 1
Packit aea12f
Packit aea12f
	if [ -z "$srk_password" ]; then
Packit aea12f
		params="--srk-well-known"
Packit aea12f
		unset GNUTLS_PIN
Packit aea12f
	else
Packit aea12f
		export GNUTLS_PIN="$srk_password"
Packit aea12f
	fi
Packit aea12f
Packit aea12f
	if [ $register -ne 0 ]; then
Packit aea12f
		# --register key
Packit aea12f
		msg="$(run_tpmtool "$srk_password" "$key_password" \
Packit aea12f
			$params --register --generate-rsa --signing)"
Packit aea12f
		[ $? -ne 0 ] && {
Packit aea12f
			echo "Could not create TPM signing key"
Packit aea12f
			echo "$msg"
Packit aea12f
			return 1
Packit aea12f
		}
Packit aea12f
		tpmkeyurl=$(echo "$msg" | sed -n 's/\(tpmkey:uuid=[^;]*\);.*/\1/p')
Packit aea12f
		[ -z "$tpmkeyurl" ] && {
Packit aea12f
			echo "Could not get TPM key URL"
Packit aea12f
			return 1
Packit aea12f
		}
Packit aea12f
	else
Packit aea12f
		msg="$(run_tpmtool "$srk_password" "$key_password" \
Packit aea12f
			$params --generate-rsa --signing --outfile ${tpmkey})"
Packit aea12f
		[ $? -ne 0 ] && {
Packit aea12f
			echo "Could not create TPM signing key"
Packit aea12f
			echo "$msg"
Packit aea12f
			return 1
Packit aea12f
		}
Packit aea12f
		tpmkeyurl="tpmkey:file=${tpmkey}"
Packit aea12f
	fi
Packit aea12f
Packit aea12f
	if [ $register -ne 0 ]; then
Packit aea12f
		msg=$(run_tpmtool "$srk_password" "$key_password" \
Packit aea12f
			$params --test-sign $tpmkeyurl)
Packit aea12f
		[ $? -ne 0 ] && {
Packit aea12f
			echo "Could not test sign with key $tpmkeyurl"
Packit aea12f
			echo "$msg"
Packit aea12f
			return 1
Packit aea12f
		}
Packit aea12f
	fi
Packit aea12f
Packit aea12f
	msg=$(run_tpmtool "$srk_password" "$key_password" \
Packit aea12f
		$params --pubkey "$tpmkeyurl" --outfile "$tpmpubkey")
Packit aea12f
	[ $? -ne 0 ] && {
Packit aea12f
		echo "Could not get TPM key's public key"
Packit aea12f
		echo "$msg"
Packit aea12f
		return 1
Packit aea12f
	}
Packit aea12f
Packit aea12f
	cat <<_EOF_ >${template}
Packit aea12f
cn = test
Packit aea12f
ca
Packit aea12f
cert_signing_key
Packit aea12f
expiration_days = 1
Packit aea12f
_EOF_
Packit aea12f
Packit aea12f
	msg=$($CERTTOOL \
Packit aea12f
		--generate-self-signed \
Packit aea12f
		--template ${template} \
Packit aea12f
		--outfile ${tpmca} \
Packit aea12f
		--load-privkey ${tpmkeyurl} \
Packit aea12f
		--load-pubkey ${tpmpubkey} 2>&1)
Packit aea12f
	[ $? -ne 0 ] && {
Packit aea12f
		echo "Could not create self-signed certificate"
Packit aea12f
		echo "$msg"
Packit aea12f
		return 1
Packit aea12f
	}
Packit aea12f
Packit aea12f
	echo "Successfully created TPM root CA cert using key $tpmkeyurl"
Packit aea12f
Packit aea12f
	if [ $register -ne 0 ]; then
Packit aea12f
		if [ -z "$($TPMTOOL --list | grep "${tpmkeyurl}")" ]; then
Packit aea12f
			echo "TPM key '${tpmkeyurl}' was not found in list of TPM keys"
Packit aea12f
			return 1
Packit aea12f
		fi
Packit aea12f
Packit aea12f
		msg=$(run_tpmtool "$srk_password" "$key_password" \
Packit aea12f
			$params --delete $tpmkeyurl)
Packit aea12f
		[ $? -ne 0 ] && {
Packit aea12f
			echo "Could not delete TPM key ${tpmkeyurl}"
Packit aea12f
			echo "$msg"
Packit aea12f
			return 1
Packit aea12f
		}
Packit aea12f
Packit aea12f
		if [ -n "$($TPMTOOL --list | grep "$tpmkeyurl")" ]; then
Packit aea12f
			echo "TPM key '$tpmkeyurl' was not properly deleted"
Packit aea12f
			return 1
Packit aea12f
		fi
Packit aea12f
	fi
Packit aea12f
Packit aea12f
	stop_tcsd
Packit aea12f
}
Packit aea12f
Packit aea12f
run_tests()
Packit aea12f
{
Packit aea12f
	local workdir="$1"
Packit aea12f
Packit aea12f
	[ -z "$workdir" ] && {
Packit aea12f
		echo "No workdir"
Packit aea12f
		return 1
Packit aea12f
	}
Packit aea12f
	local srk_password key_password
Packit aea12f
	local owner_password="owner"
Packit aea12f
	local register
Packit aea12f
Packit aea12f
	register=1
Packit aea12f
	# Test with --register; key password is not needed
Packit aea12f
	for srk_password in "" "s"; do
Packit aea12f
		tpmtool_test "$workdir" "$owner_password" "$srk_password" "" "$register"
Packit aea12f
		[ $? -ne 0 ] && return 1
Packit aea12f
		stop_tcsd
Packit aea12f
		rm ${workdir}/*
Packit aea12f
	done
Packit aea12f
Packit aea12f
	# Test without --register; the key needs a password, but it has to be the same as the
Packit aea12f
	# srk_password due to a bug in TrouSerS
Packit aea12f
	register=0
Packit aea12f
	for srk_password in "s"; do
Packit aea12f
		key_password=$srk_password
Packit aea12f
		tpmtool_test "$workdir" "$owner_password" "$srk_password" "$key_password" "$register"
Packit aea12f
		[ $? -ne 0 ] && return 1
Packit aea12f
		stop_tcsd
Packit aea12f
		rm ${workdir}/*
Packit aea12f
	done
Packit aea12f
Packit aea12f
	echo "Ok"
Packit aea12f
Packit aea12f
	return 0
Packit aea12f
}
Packit aea12f
Packit aea12f
trap "cleanup" EXIT QUIT
Packit aea12f
Packit aea12f
run_tests "$workdir"
Packit aea12f
exit $?