#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. #set -x if [ ${SWTPM_TEST_IBMTSS2:-0} -eq 0 ]; then echo "SWTPM_TEST_IBMTSS2 must be set to run this test." exit 77 fi type -p nvdefinespace startup &>/dev/null if [ $? -ne 0 ]; then PREFIX=tss type -p ${PREFIX}nvdefinespace ${PREFIX}startup fi if [ $? -ne 0 ]; then echo "Could not find TPM2 tools (e.g., (tss)startup, (tss)nvdefinespace) in PATH." exit 77 fi TOOLSPATH=$(dirname $(type -P ${PREFIX}startup)) ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM=swtpm SWTPM_EXE=${SWTPM_EXE:-$ROOT/src/swtpm/$SWTPM} SWTPM_IOCTL=$ROOT/src/swtpm_ioctl/swtpm_ioctl TPMDIR="$(mktemp -d)" || exit 1 PID_FILE=$TPMDIR/${SWTPM}.pid SOCK_PATH=$TPMDIR/sock CMD_PATH=$TPMDIR/cmd RESP_PATH=$TPMDIR/resp LOGFILE=$TPMDIR/logfile TMPFILE=$TPMDIR/tmpfile BINFILE=$TPMDIR/binfile SIGFILE=$TPMDIR/sigfile STATEFILE=${STATEFILE:-$TPMDIR/state} STORE_PARAM="dir=$TPMDIR" if [ ${SWTPM_TEST_LINEAR_FILE:-0} -ne 0 ]; then echo "Testing with linear file backend ($STATEFILE)" STORE_PARAM="backend-uri=file://$STATEFILE" fi source ${TESTDIR}/test_common source ${TESTDIR}/common skip_test_no_tpm20 "${SWTPM_EXE}" trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf $TPMDIR # remove files from tss tools rm -f h01*.bin nvp*.bin if [ -n "$PID" ]; then kill_quiet -SIGTERM $PID 2>/dev/null fi } # Fill up the NVRAM space with 2048 bit signing keys and then an NVRAM area that # fills it up to the last byte. We want to make sure that the OBJECTs that the # RSA keys are creating in NVRAM can be loaded into the NVRAM again when the size # of the OBJECT increases when for example the size of the RSA keys increases. # This may force us to increase the NVRAM memory space in libtpms then. function fillup_nvram() { local create="$1" local check="$2" local i sz if [ $create -eq 1 ]; then # Fill up the NVRAM space with RSA 2048 keys; # exactly 65 have to fit ${TOOLSPATH}/${PREFIX}createprimary -hi o -si > $TMPFILE if [ $? -ne 0 ]; then echo "Error: createprimary failed." exit 1 fi if [ -z "$(grep 80000000 $TMPFILE)" ]; then echo "Error: createprimary did not result in expected handle 80000000" exit 1 fi for ((i = 0x81000000; i < 0x81000100; i++)); do ${TOOLSPATH}/${PREFIX}evictcontrol \ -hi o \ -ho 80000000 \ -hp $(printf "%x" $i) &>$TMPFILE || break done ${TOOLSPATH}/${PREFIX}getcapability -cap 1 -pr 81000000 -pc 80 > $TMPFILE # We need know we need to see '65 Handles' for state created with # libtpms-0.6.0 and 128kb NVRAM size grep -i "65 Handles" $TMPFILE if [ $? -ne 0 ]; then echo "Error: Did not find '65 Handles' keyword in output" cat $TMPFILE exit 1 fi # Fill up the rest of the NVRAM with a single NVRAM index whose size # we now have to find; # for reference: libtpms v0.6.0 allowed 236 bytes for ((sz = 0; ; sz++)); do ${TOOLSPATH}/${PREFIX}nvdefinespace \ -hi o \ -ha 01000000 \ -sz ${sz} > ${TMPFILE} || break # this worked, so lets remove it and try the next size #echo "NVRAM space of size $sz could be created" ${TOOLSPATH}/${PREFIX}nvundefinespace \ -hi o \ -ha 01000000 > ${TMPFILE} done if [ $sz -gt 0 ]; then sz=$((sz - 1)) echo "Creating final space of size ${sz}" ${TOOLSPATH}/${PREFIX}nvdefinespace \ -hi o \ -ha 01000000 \ -sz ${sz} > ${TMPFILE} if [ $? -ne 0 ]; then echo "Error: Could not create final NVRAM space." cat ${TMPFILE} exit 1 fi fi if [ $sz -eq 0 ]; then echo "Error: NVRAM space could not be created at all; not enough space!" exit 1 elif [ $sz -lt 236 ]; then echo "Error: Insufficient NVRAM memory. Needed to create an NVRAM index with size 236 bytes." exit 1 elif [ $sz -gt 236 ]; then echo "Error: The NVRAM index is too large. Only needed 236 bytes but got $sz bytes." exit 1 else echo "The NVRAM index is exactly of the right size (236 bytes)." fi echo -n "123" > $BINFILE ${TOOLSPATH}/${PREFIX}sign \ -hk 81000000 \ -if ${BINFILE} \ -os ${SIGFILE} > $TMPFILE if [ $? -ne 0 ]; then echo "Error: Could not create signature." cat $TMPFILE exit 1 fi fi if [ $check -eq 1 ]; then ${TOOLSPATH}/${PREFIX}getcapability -cap 1 -pr 81000000 -pc 80 > $TMPFILE # We need know we need to see '65 Handles' for state created with # libtpms-0.6.0 and 128kb NVRAM size grep -i "65 Handles" $TMPFILE if [ $? -ne 0 ]; then echo "Error: Did not find '65 Handles' keyword in output" cat $TMPFILE exit 1 fi printf "Verifying signature with all the persisted keys\n" echo -n "123" > $BINFILE for ((i = 0x81000000; i < 0x81000040; i++)); do ${TOOLSPATH}/${PREFIX}verifysignature \ -hk $(printf "%x" $i) \ -is ${SIGFILE} \ -if ${BINFILE} > $TMPFILE if [ $? -ne 0 ]; then echo "Verifying signature failed for handle $(printf "%x" $i)." exit 1 fi done fi } export TPM_SERVER_TYPE=raw export TPM_SERVER_NAME=127.0.0.1 export TPM_INTERFACE_TYPE=socsim export TPM_COMMAND_PORT=${TPM_COMMAND_PORT:-65460} export TPM_DATA_DIR=$TPMDIR export TPM_SESSION_ENCKEY="807e2bfe898ddaed8fa6310e716a24dc" # for sessions $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate $STORE_PARAM \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (1) Socket TPM did not write pidfile." exit 1 fi PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." exit 1 fi fillup_nvram 1 1 # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: swtpm did not shut down" exit 1 fi echo "============================" >> $LOGFILE echo "TPM was shut down" # Store this state for later usage; use a really old version of libtpms: 0.6.0 #cp $TPMDIR/tpm2-00.permall ${TESTDIR}/data/tpm2state5; #cp $SIGFILE ${TESTDIR}/data/tpm2state5/signature.bin ################################################################# # Run TPM2 with the created state and verify it's the same $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate $STORE_PARAM \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (2) Socket TPM did not write pidfile." exit 1 fi echo "TPM re-started" PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" cat $LOGFILE exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." cat $LOGFILE exit 1 fi fillup_nvram 0 1 ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi echo "============================" >> $LOGFILE echo "TPM was shut down" ################################################################# # Run TPM2 with previously saved state and verify it's the same if [ ${SWTPM_TEST_LINEAR_FILE:-0} -ne 0 ]; then echo "Test 1 OK (skipped last with linear file)" exit 0 fi rm -f $TPMDIR/* cp -f ${TESTDIR}/data/tpm2state5/tpm2-00.permall $TPMDIR/tpm2-00.permall cp ${TESTDIR}/data/tpm2state5/signature.bin $SIGFILE $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate $STORE_PARAM \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi echo "TPM started with previously generated state" PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." cat $LOGFILE exit 1 fi fillup_nvram 0 1 ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi echo "Test 1 OK"