| #!/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" |