| #!/usr/bin/env bash |
| |
| # For the license, see the LICENSE file in the root directory. |
| #set -x |
| |
| if [ "$(id -u)" -ne 0 ]; then |
| echo "Need to be root to run this test." |
| exit 77 |
| fi |
| |
| ROOT=${abs_top_builddir:-$(dirname "$0")/..} |
| TESTDIR=${abs_top_testdir:-$(dirname "$0")} |
| |
| SWTPM=swtpm |
| SWTPM_EXE=${SWTPM_EXE:-$ROOT/src/swtpm/$SWTPM} |
| TPM_PATH="$(mktemp -d)" || exit 1 |
| STATE_FILE=$TPM_PATH/tpm-00.permall |
| VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate |
| PID_FILE=$TPM_PATH/${SWTPM}.pid |
| SOCK_PATH=$TPM_PATH/sock |
| CMD_PATH=$TPM_PATH/cmd |
| RESP_PATH=$TPM_PATH/resp |
| LOGFILE=$TPM_PATH/logfile |
| |
| function cleanup() |
| { |
| pid=$(ps aux | grep "$SWTPM" | grep -E " file=${PID_FILE}\$" | gawk '{print $2}') |
| if [ -n "$pid" ]; then |
| kill_quiet -9 "$pid" |
| fi |
| rm -rf "$TPM_PATH" |
| } |
| |
| trap "cleanup" EXIT |
| |
| source "${TESTDIR}/common" |
| skip_test_no_tpm12 "${SWTPM_EXE}" |
| |
| source "${TESTDIR}/load_vtpm_proxy" |
| |
| rm -f "$STATE_FILE" "$VOLATILE_STATE_FILE" 2>/dev/null |
| |
| $SWTPM_EXE chardev --vtpm-proxy \ |
| --tpmstate "dir=$TPM_PATH" \ |
| --ctrl "type=unixio,path=$SOCK_PATH" \ |
| ${SWTPM_TEST_SECCOMP_OPT:+${SWTPM_TEST_SECCOMP_OPT}} \ |
| --pid "file=$PID_FILE" &>"$LOGFILE" & |
| sleep 0.5 |
| PID=$(ps aux | grep $SWTPM | grep -E " file=${PID_FILE}\$" | gawk '{print $2}') |
| |
| display_processes_by_name "$SWTPM" |
| |
| if ! kill_quiet -0 "$PID"; then |
| echo "Error: Chardev TPM did not start." |
| exit 1 |
| fi |
| |
| if wait_for_file "$PID_FILE" 3; then |
| echo "Error: Chardev TPM did not write pidfile." |
| exit 1 |
| fi |
| |
| # Wait for chardev to appear; TPM 1.2 may take a long time to self-test |
| # with valgrind |
| for ((i = 0; i < 200; i ++)); do |
| if [ -z "${TPM_DEVICE}" ]; then |
| TPM_DEVICE=$(sed -n 's,.*\(/dev/tpm[0-9]\+\).*,\1,p' "$LOGFILE") |
| if [ -n "${TPM_DEVICE}" ]; then |
| echo "Using ${TPM_DEVICE}." |
| fi |
| fi |
| if [ -n "${TPM_DEVICE}" ]; then |
| [ -c "${TPM_DEVICE}" ] && break |
| fi |
| sleep 0.1 |
| done |
| if ! [ -c "${TPM_DEVICE}" ]; then |
| echo "Error: Chardev ${TPM_DEVICE} did not appear" |
| exit 1 |
| fi |
| |
| # Open access to the TPM |
| if ! exec 100<>"$TPM_DEVICE"; then |
| echo "Error: Could not open $TPM_DEVICE" |
| exit 1 |
| fi |
| |
| # Read PCR 17 -- this should give a fatal error response |
| echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100 |
| #RES=$(cat <&100 | od -t x1 -A n -w128) |
| RES=$(od -t x1 -A n -w128 <&100) |
| exp=' 00 c4 00 00 00 1e 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff' |
| if [ "$RES" != "$exp" ]; then |
| echo "Error: Did not get expected result from TPM_PCRRead(17)" |
| echo "expected: $exp" |
| echo "received: $RES" |
| exit 1 |
| fi |
| |
| exec 100>&- |
| |
| if ! kill_quiet -0 "$PID"; then |
| echo "Error: Chardev TPM must have crashed." |
| exit 1 |
| fi |
| |
| if [ ! -e "$STATE_FILE" ]; then |
| echo "Error: TPM state file $STATE_FILE does not exist." |
| exit 1 |
| fi |
| |
| # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 |
| echo -en '\x00\x00\x00\x03' > "$CMD_PATH" |
| socat -x -t10 "FILE:$CMD_PATH,rdonly" "UNIX-CONNECT:$SOCK_PATH" 2>&1 | \ |
| sed -n '/^ /p' | \ |
| tail -n1 > "$RESP_PATH" |
| res="$(cat "$RESP_PATH")" |
| exp=" 00 00 00 00" |
| if [ "$res" != "$exp" ]; then |
| echo "Error: Unexpected response from CMD_SHUTDOWN:" |
| echo " actual : $res" |
| echo " expected: $exp" |
| exit 1 |
| fi |
| |
| if wait_file_gone "$PID_FILE" 2; then |
| echo "Error: TPM should have removed PID file by now." |
| exit 1 |
| fi |
| |
| if wait_process_gone "${PID}" 4; then |
| echo "Error: TPM should not be running anymore." |
| exit 1 |
| fi |
| |
| echo "OK" |
| |
| exit 0 |