swtpm/tests/_test_tpm2_encrypted_state
Stefan Berger bd77a3440a tests: Extend existing test case to use the new fsync option
Extend an existing test case to use the new fsync option to at least test
the option parser. That fsync() is actually being called is not easy to
observe.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2025-05-27 16:28:39 -04:00

442 lines
12 KiB
Bash
Executable File

#!/bin/bash
# For the license, see the LICENSE file in the root directory.
#set -x
ROOT=${abs_top_builddir:-$(pwd)/..}
TESTDIR=${abs_top_testdir:-$(dirname "$0")}
VTPM_NAME=${VTPM_NAME:-vtpm-test-tpm2-encrypted-state}
SWTPM_DEV_NAME="/dev/${VTPM_NAME}"
TPM_PATH="$(mktemp -d)" || exit 1
STATE_FILE=$TPM_PATH/tpm2-00.permall
STATE_FILE_BAK=$TPM_PATH/tpm2-00.permall.bak
VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate
KEY=1234567890abcdef1234567890abcdef
BINKEY='\x12\x34\x56\x78\x90\xab\xcd\xef\x12\x34\x56\x78\x90\xab\xcd\xef'
SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse}
SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock
SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock
keyfile=${TPM_PATH}/keyfile
logfile=${TPM_PATH}/logfile
binkeyfile=${TPM_PATH}/binkeyfile
echo "$KEY" > "${keyfile}"
echo -en "$BINKEY" > "${binkeyfile}"
function cleanup()
{
pid=${SWTPM_PID}
if [ -n "$pid" ]; then
kill_quiet -9 "$pid"
fi
rm -rf "$TPM_PATH"
}
trap "cleanup" EXIT
source "${TESTDIR}/common"
[ "${SWTPM_INTERFACE}" == "cuse" ] && source "${TESTDIR}/test_cuse"
rm -f "$STATE_FILE" "$VOLATILE_STATE_FILE" 2>/dev/null
TPM_PATH=$TPM_PATH run_swtpm "${SWTPM_INTERFACE}" \
--key "file=$keyfile,mode=aes-cbc,format=hex,remove" \
--log "file=$logfile" \
--tpm2
display_processes_by_name "swtpm"
if ! kill_quiet -0 "${SWTPM_PID}"; then
echo "Error: ${SWTPM_INTERFACE} TPM did not start."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
if wait_file_gone "${keyfile}" 4; then
echo "Error: Keyfile $keyfile was not removed by ${SWTPM_INTERFACE} tpm."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Init the TPM
if ! run_swtpm_ioctl "${SWTPM_INTERFACE}" -i; then
echo "Error: ${SWTPM_INTERFACE} TPM initialization failed."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
if ! kill_quiet -0 "${SWTPM_PID}" 2>/dev/null; then
echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Startup the TPM
RES=$(swtpm_cmd_tx "${SWTPM_INTERFACE}" '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00')
exp=' 80 01 00 00 00 0a 00 00 00 00'
if [ "$RES" != "$exp" ]; then
echo "Error: Did not get expected result from TPM2_Startup(SU_Clear)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
if ! run_swtpm_ioctl "${SWTPM_INTERFACE}" -h 1234; then
echo "Error: Hash command did not work."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Read PCR 17
RES=$(swtpm_cmd_tx "${SWTPM_INTERFACE}" '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02')
exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54'
if [ "$RES" != "$exp" ]; then
echo "Error: (1) Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Save the volatile state
if ! run_swtpm_ioctl "${SWTPM_INTERFACE}" -v; then
echo "Error: Saving the volatile state failed."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
if [ ! -r "$VOLATILE_STATE_FILE" ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
if ! tmp=$(run_swtpm_ioctl "${SWTPM_INTERFACE}" -g | cut -d":" -f2); then
echo "Error: Could not get the configuration flags of the ${SWTPM_INTERFACE} TPM."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
if [ "$tmp" != " 0x1" ]; then
echo "Error: Unexpected configuration flags: $tmp; expected 0x1."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Shut the TPM down
if ! run_swtpm_ioctl "${SWTPM_INTERFACE}" -s; then
echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Start the TPM again; have the keyfile removed; create state backup file
run_swtpm "${SWTPM_INTERFACE}" \
--tpmstate "dir=${TPM_PATH},backup" \
--key "file=$binkeyfile,mode=aes-cbc,format=binary,remove" \
--log "file=$logfile" \
--tpm2
display_processes_by_name "swtpm"
if ! kill_quiet -0 "${SWTPM_PID}"; then
echo "Error (2): ${SWTPM_INTERFACE} TPM did not start."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
if wait_file_gone "${binkeyfile}" 4; then
echo "Error: Keyfile $binkeyfile was not removed by ${SWTPM_INTERFACE} TPM."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Init the TPM
if ! run_swtpm_ioctl "${SWTPM_INTERFACE}" -i; then
echo "Error: ${SWTPM_INTERFACE} TPM initialization failed."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Volatile state must have been removed by TPM now
if [ -r "$VOLATILE_STATE_FILE" ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Read the PCR again ...
RES=$(swtpm_cmd_tx "${SWTPM_INTERFACE}" '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02')
exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54'
if [ "$RES" != "$exp" ]; then
echo "Error: (2) Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Save the volatile state again
if ! run_swtpm_ioctl "${SWTPM_INTERFACE}" -v; then
echo "Error: Saving the volatile state failed."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
if [ ! -r "$VOLATILE_STATE_FILE" ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Send a new TPM_Init
if ! run_swtpm_ioctl "${SWTPM_INTERFACE}" -i; then
echo "Error: ${SWTPM_INTERFACE} TPM initialization failed."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Volatile state must have been removed by TPM now
if [ -r "$VOLATILE_STATE_FILE" ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Read the PCR again ...
RES=$(swtpm_cmd_tx "${SWTPM_INTERFACE}" '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02')
exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54'
if [ "$RES" != "$exp" ]; then
echo "Error: (2) Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Final shut down
if ! run_swtpm_ioctl "${SWTPM_INTERFACE}" -s; then
echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
if wait_process_gone "${SWTPM_PID}" 4; then
echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
if [ ! -e "$STATE_FILE" ]; then
echo "Error: TPM state file $STATE_FILE does not exist."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
if [ "${SWTPM_INTERFACE}" = "socket+socket" ]; then
# Record hashes of permanent state file
if ! permall_hash=$(get_sha1_file "${STATE_FILE}") || \
! permall_bak_hash=$(get_sha1_file "${STATE_FILE_BAK}"); then
echo "Error: Could not get hashes of state files"
ls -l "${TPM_PATH}"
exit 1
fi
# Start the TPM with backup option; it will not start
# and must not modify files
${SWTPM_EXE} socket \
--tpmstate "dir=${TPM_PATH},backup" \
--log "file=$logfile" \
--flags not-need-init \
--tpm2 \
${SWTPM_TEST_SECCOMP_OPT:+${SWTPM_TEST_SECCOMP_OPT}} \
--server "type=tcp,port=${SWTPM_SERVER_PORT}" \
--ctrl "type=tcp,port=${SWTPM_CTRL_PORT}" &
rc=$?
if [ "$rc" -ne 0 ]; then
echo "Error: Could not run ${SWTPM_EXE}"
exit 1
fi
SWTPM_PID=$!
if wait_process_gone "${SWTPM_PID}" 4; then
echo "Error: ${SWTPM_INTERFACE} TPM should not have started without key."
exit 1
fi
if [ "$(get_sha1_file "${STATE_FILE}")" != "${permall_hash}" ]; then
echo "Error: The ${STATE_FILE} file hash changed."
exit 1
fi
if [ "$(get_sha1_file "${STATE_FILE_BAK}")" != "${permall_bak_hash}" ]; then
echo "Error: The ${STATE_FILE_BAK} file hash changed."
exit 1
fi
rm -f "${STATE_FILE_BAK}"
# swtpm should not run; no changes to state files
${SWTPM_EXE} socket \
--tpmstate "dir=${TPM_PATH},backup" \
--log "file=$logfile" \
--flags not-need-init \
--tpm2 \
${SWTPM_TEST_SECCOMP_OPT:+${SWTPM_TEST_SECCOMP_OPT}} \
--server "type=tcp,port=${SWTPM_SERVER_PORT}" \
--ctrl "type=tcp,port=${SWTPM_CTRL_PORT}" &
rc=$?
if [ "$rc" -ne 0 ]; then
echo "Error: Could not run ${SWTPM_EXE}"
exit 1
fi
SWTPM_PID=$!
if wait_process_gone "${SWTPM_PID}" 4; then
echo "Error: ${SWTPM_INTERFACE} TPM should not have started without key and without backup file."
cat "$logfile"
exit 1
fi
if [ "$(get_sha1_file "${STATE_FILE}")" != "${permall_hash}" ]; then
echo "Error: The ${STATE_FILE} file hash changed."
exit 1
fi
if [ -f "${STATE_FILE_BAK}" ]; then
echo "Error: The state backup file ${STATE_FILE_BAK} should not exist."
ls -l "${TPM_PATH}"
exit 1
fi
mv "${STATE_FILE}" "${STATE_FILE_BAK}"
${SWTPM_EXE} socket \
--tpmstate "dir=${TPM_PATH},backup" \
--log "file=$logfile" \
--flags not-need-init \
--tpm2 \
${SWTPM_TEST_SECCOMP_OPT:+${SWTPM_TEST_SECCOMP_OPT}} \
--server "type=tcp,port=${SWTPM_SERVER_PORT}" \
--ctrl "type=tcp,port=${SWTPM_CTRL_PORT}" &
rc=$?
if [ "$rc" -ne 0 ]; then
echo "Error: Could not run ${SWTPM_EXE}"
exit 1
fi
SWTPM_PID=$!
if wait_process_gone "${SWTPM_PID}" 4; then
echo "Error: ${SWTPM_INTERFACE} TPM should not have started without key and without backup file."
cat "$logfile"
exit 1
fi
if [ "$(get_sha1_file "${STATE_FILE}")" != "${permall_hash}" ]; then
echo "Error: The ${STATE_FILE} file hash changed."
exit 1
fi
if [ -f "${STATE_FILE_BAK}" ]; then
echo "Error: The state backup file ${STATE_FILE_BAK} should not exist."
exit 1
fi
mv "${STATE_FILE}" "${STATE_FILE_BAK}"
touch "${STATE_FILE}"
if ! emptyfile_hash=$(get_sha1_file "${STATE_FILE}"); then
echo "Error: Could not get hash of empty state files"
exit 1
fi
${SWTPM_EXE} socket \
--tpmstate "dir=${TPM_PATH},backup,fsync" \
--log "file=$logfile" \
--flags not-need-init \
--tpm2 \
${SWTPM_TEST_SECCOMP_OPT:+${SWTPM_TEST_SECCOMP_OPT}} \
--server "type=tcp,port=${SWTPM_SERVER_PORT}" \
--ctrl "type=tcp,port=${SWTPM_CTRL_PORT}" &
rc=$?
if [ "$rc" -ne 0 ]; then
echo "Error: Could not run ${SWTPM_EXE}"
exit 1
fi
SWTPM_PID=$!
if wait_process_gone "${SWTPM_PID}" 4; then
echo "Error: ${SWTPM_INTERFACE} TPM should not have started without key and without backup file."
cat "$logfile"
exit 1
fi
# .bak file was previously 'normal' state file
if [ "$(get_sha1_file "${STATE_FILE_BAK}")" != "${permall_hash}" ]; then
echo "Error: The ${STATE_FILE_BAK} file hash changed."
exit 1
fi
if [ "$(get_sha1_file "${STATE_FILE}")" != "${emptyfile_hash}" ]; then
echo "Error: The (empty) ${STATE_FILE} file hash changed."
exit 1
fi
# Have it start successfully with a corrupted permanent state file and
# and available backup file
echo -en "$BINKEY" > "${binkeyfile}"
rm -f "$logfile"
run_swtpm "${SWTPM_INTERFACE}" \
--tpmstate "dir=${TPM_PATH},backup,fsync" \
--key "file=$binkeyfile,mode=aes-cbc,format=binary,remove" \
--log "file=$logfile" \
--tpm2
if wait_file_gone "${binkeyfile}" 4; then
echo "Error: Keyfile $binkeyfile was not removed by ${SWTPM_INTERFACE} TPM."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Send TPM_Init
if ! run_swtpm_ioctl "${SWTPM_INTERFACE}" -i; then
echo "Error: ${SWTPM_INTERFACE} TPM initialization failed when started with backup file."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
# Final shut down
if ! run_swtpm_ioctl "${SWTPM_INTERFACE}" -s; then
echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM when started with backup file."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
if wait_process_gone "${SWTPM_PID}" 4; then
echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore."
echo "TPM Logfile:"
cat "$logfile"
exit 1
fi
echo "INFO: socket+socket interface passed backup option test"
fi
echo "OK"
exit 0