mirror of
https://github.com/stefanberger/swtpm.git
synced 2025-08-22 19:04:35 +00:00

Due to recent changes in tcsd, it doesn't accept 'tss:tss 0600' anymore for the tcsd config file but we need to use 'root:tss 0640' for it. So far only Fedora seems to be affected. It now depends on whether tcsd has been patched what ownership is required. So we try first the old configuration and then the new one. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
334 lines
9.1 KiB
Bash
Executable File
334 lines
9.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#set -x
|
|
|
|
# For the license, see the LICENSE file in the root directory.
|
|
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
echo "Need to be root to run this test."
|
|
exit 77
|
|
fi
|
|
|
|
# tpmtool is not packaged everywhere ...
|
|
if [ -z "$(type -P tpmtool)" ]; then
|
|
echo "Could not find tpmtool in PATH"
|
|
exit 77
|
|
fi
|
|
|
|
ROOT=${abs_top_builddir:-$(dirname "$0")/..}
|
|
TESTDIR=${abs_top_testdir:=$(dirname "$0")}
|
|
SRCDIR=${abs_top_srcdir:-$(dirname "$0")/..}
|
|
|
|
PATH=$ROOT/src/swtpm:$PATH
|
|
|
|
source ${abs_top_builddir:-$(dirname "$0")/..}/tests/test_config
|
|
|
|
SWTPM_SETUP=${ROOT}/src/swtpm_setup/swtpm_setup
|
|
SWTPM_CREATE_TPMCA=${SRCDIR}/samples/swtpm-create-tpmca
|
|
SWTPM_LOCALCA=${ROOT}/samples/swtpm-localca
|
|
SWTPM=${ROOT}/src/swtpm/swtpm
|
|
SWTPM_IOCTL=${ROOT}/src/swtpm_ioctl/swtpm_ioctl
|
|
|
|
SWTPM_INTERFACE=socket+socket
|
|
SWTPM_SERVER_NAME=localhost
|
|
SWTPM_SERVER_PORT=65434
|
|
SWTPM_CTRL_PORT=65435
|
|
|
|
TCSD_LISTEN_PORT=65436
|
|
|
|
SRK_PASSWORD=srk
|
|
OWNER_PASSWORD=owner
|
|
|
|
workdir=$(mktemp -d)
|
|
|
|
TCSD_CONF=${workdir}/tcsd.conf
|
|
TCSD_SYSTEM_PS_FILE=${workdir}/system_ps_file
|
|
TCSD_PIDFILE=${workdir}/tcsd.pid
|
|
SWTPM_LOCALCA_DIR="${workdir}/my localca"
|
|
SWTPM_LOCALCA_CONF="${workdir}/my localca/swtpm-localca.conf"
|
|
|
|
# Captured TCSD file when using a SRK_PASSWORD=srk
|
|
TCSD_FILE="AQEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAABLwEAAAAAAwAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAQEAAAARAAAAAAEAAAABAAMAAQAAAAwAAAgAAAAAAgAAAAAAAAAA
|
|
AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
|
|
|
function cleanup()
|
|
{
|
|
if [ -n "${TCSD_PID}" ]; then
|
|
kill_quiet -15 ${TCSD_PID}
|
|
fi
|
|
if [ -n "${SWTPM_PID}" ]; then
|
|
kill_quiet -9 ${SWTPM_PID}
|
|
fi
|
|
if [ -n "${BASH_PID}" ]; then
|
|
kill_quiet -9 ${BASH_PID}
|
|
fi
|
|
rm -rf "${workdir}"
|
|
}
|
|
|
|
trap "cleanup" SIGTERM EXIT
|
|
source ${TESTDIR}/common
|
|
|
|
case "$(uname -s)" in
|
|
Darwin)
|
|
CERTTOOL=gnutls-certtool;;
|
|
*)
|
|
CERTTOOL=certtool;;
|
|
esac
|
|
|
|
PATH=${ROOT}/src/swtpm_bios:${ROOT}/src/swtpm_cert:${PATH}
|
|
|
|
# run the test with the given owner and SRK passwords
|
|
# @param1: owner password; empty means to use well known password
|
|
# @param2: SRK password; empty means to use well known password
|
|
# @param3: vTPM is a TPM 2.0
|
|
function run_test() {
|
|
local owner_password="$1"
|
|
local srk_password="$2"
|
|
local vtpm_is_tpm2="$3"
|
|
|
|
local params certinfo regex regexs fil i skip
|
|
|
|
rm -rf "${workdir}"/*
|
|
|
|
cat <<_EOF_ > "${workdir}/swtpm_setup.conf"
|
|
create_certs_tool=${SWTPM_LOCALCA}
|
|
create_certs_tool_config=${workdir}/swtpm-localca.conf
|
|
create_certs_tool_options=/dev/null
|
|
_EOF_
|
|
|
|
params=""
|
|
if [ -n "${owner_password}" ]; then
|
|
params="${params} --ownerpass ${owner_password}"
|
|
else
|
|
params="${params} --owner-well-known"
|
|
fi
|
|
params="${params} --srkpass ${srk_password}"
|
|
|
|
# First setup the TPM and take ownership of it and set SRK password
|
|
$SWTPM_SETUP \
|
|
--runas root \
|
|
--tpm-state "${workdir}" \
|
|
--logfile "${workdir}/logfile" \
|
|
--config "${workdir}/swtpm_setup.conf" \
|
|
--tpm "${SWTPM_EXE} socket ${SWTPM_TEST_SECCOMP_OPT}" \
|
|
--take-ownership \
|
|
${params} >/dev/null
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Could not run $SWTPM_SETUP."
|
|
echo "Setup Logfile:"
|
|
cat ${workdir}/logfile
|
|
exit 1
|
|
fi
|
|
|
|
echo "Successfully took ownership of TPM and set owner and SRK passwords."
|
|
|
|
run_swtpm ${SWTPM_INTERFACE} \
|
|
--flags not-need-init \
|
|
--tpmstate "dir=${workdir}"
|
|
|
|
swtpm_open_cmddev ${SWTPM_INTERFACE} 100
|
|
|
|
# Startup the TPM
|
|
res="$(swtpm_cmd_tx "${SWTPM_INTERFACE}" '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01')"
|
|
exp=' 00 c4 00 00 00 0a 00 00 00 00'
|
|
if [ "$res" != "$exp" ]; then
|
|
echo "Error: Did not get expected result from TPM_Startup(ST_Clear)"
|
|
echo "expected: $exp"
|
|
echo "received: $res"
|
|
exit 1
|
|
fi
|
|
|
|
echo "$TCSD_FILE" | base64 -d > "${TCSD_SYSTEM_PS_FILE}"
|
|
|
|
# Setup the TCSD config file and start TCSD with it
|
|
cat <<_EOF_ > "${TCSD_CONF}"
|
|
port = ${TCSD_LISTEN_PORT}
|
|
system_ps_file = ${TCSD_SYSTEM_PS_FILE}
|
|
_EOF_
|
|
|
|
# Due to recent changes in tcsd we have to try with TSS_USER=tss and TSS_USER=root
|
|
# Before the following worked:
|
|
# - tss:tss 0600 for TSS_USER=tss and TSS_GROUP=tss
|
|
# - root:tss 0640 for TSS_USER=root and TSS_GROUP=tss
|
|
# After the changes:
|
|
# - root:tss 0640 for TSS_USER=tss and TSS_GROUP=tss
|
|
while :; do
|
|
chown ${TSS_USER}:${TSS_GROUP} "${TCSD_CONF}"
|
|
if [ "${TSS_USER}" == "${TSS_GROUP}" ]; then
|
|
chmod 0600 "${TCSD_CONF}"
|
|
else
|
|
chmod 0640 "${TCSD_CONF}"
|
|
fi
|
|
|
|
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" &
|
|
BASH_PID=$!
|
|
|
|
if wait_for_file "${TCSD_PIDFILE}" 3; then
|
|
echo "Error: Could not get TCSD's PID file"
|
|
exit 1
|
|
fi
|
|
|
|
TCSD_PID=$(cat "${TCSD_PIDFILE}")
|
|
kill_quiet -0 "${TCSD_PID}"
|
|
if [ $? -ne 0 ]; then
|
|
# Try again with root unless we already tried
|
|
if [ "$TSS_USER" != "root" ]; then
|
|
TSS_USER="root"
|
|
continue
|
|
fi
|
|
echo "Error: TCSD with pid ${TCSD_PID} must have terminated"
|
|
exit 1
|
|
fi
|
|
break
|
|
done
|
|
|
|
${SWTPM_CREATE_TPMCA} \
|
|
--dir "${SWTPM_LOCALCA_DIR}" \
|
|
--srk-password "${srk_password}" \
|
|
--register \
|
|
--group "${TSS_GROUP}" \
|
|
--tss-tcsd-port "${TCSD_LISTEN_PORT}" \
|
|
--outfile "${SWTPM_LOCALCA_CONF}" &>/dev/null
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Could not create TPM CA"
|
|
exit 1
|
|
fi
|
|
|
|
for fil in \
|
|
swtpm-localca-rootca-cert.pem \
|
|
swtpm-localca-rootca-privkey.pem \
|
|
swtpm-localca-tpmca-cert.pem \
|
|
swtpm-localca-tpmca-pubkey.pem; do
|
|
if [ ! -r "${SWTPM_LOCALCA_DIR}/${fil}" ]; then
|
|
echo "Error: TPM CA tool did not create file ${fil}."
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
params=""
|
|
if [ -n "${srk_password}" ]; then
|
|
params="^parentkey_password ="
|
|
fi
|
|
|
|
for regex in \
|
|
"^statedir = " \
|
|
"^signingkey = " \
|
|
"^issuercert = " \
|
|
"^certserial = " \
|
|
"^TSS_TCSD_HOSTNAME = " \
|
|
"^TSS_TCSD_PORT = " \
|
|
${params}; do
|
|
if [ -n "${regex}" ] && \
|
|
[ -z "$(grep -E "${regex}" "${SWTPM_LOCALCA_CONF}")" ]; then
|
|
echo "Error: Could not find regex '${line}' in CA config file."
|
|
cat "${SWTPM_LOCALCA_CONF}"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
params=""
|
|
if [ ${vtpm_is_tpm2} -ne 0 ]; then
|
|
params="--tpm2"
|
|
skip=0
|
|
else
|
|
skip=7 # header in cert
|
|
fi
|
|
|
|
# make sure we can actually sign with this new certificate
|
|
${SWTPM_LOCALCA} \
|
|
--type ek \
|
|
--ek x=739192d8f1004283957a7b1568d610b41c637ccc114aadcac4908c20456468fa,y=59f63ac06f8011f6fdd1460c6bc8e3e0a2d090d4fc188c7e04870e06795ce8ae \
|
|
--dir "${workdir}" --vmid test \
|
|
${params} \
|
|
--tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 00 \
|
|
--tpm-model swtpm --tpm-version 20170101 --tpm-manufacturer IBM \
|
|
--configfile "${SWTPM_LOCALCA_CONF}" \
|
|
--optsfile /dev/null
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: The CA could not sign with the new certificate"
|
|
exit 1
|
|
fi
|
|
if [ ! -f "${workdir}/ek.cert" ]; then
|
|
echo "Error: The CA did not produce a certificate"
|
|
exit 1
|
|
fi
|
|
# cert was for example 541 bytes long
|
|
if [ $(get_filesize "${workdir}/ek.cert") -lt 500 ]; then
|
|
echo "Error: The certificate's size is dubious"
|
|
ls -l "${workdir}/ek.cert"
|
|
exit 1
|
|
fi
|
|
|
|
# Check the contents of the certificate
|
|
certinfo=$(dd "if=${workdir}/ek.cert" bs=1 "skip=$skip" status=none | \
|
|
"$CERTTOOL" -i --inder)
|
|
regexs=('^[[:space:]]+2.23.133.8.1$'
|
|
'^[[:space:]]+directoryName:.*(,)?2.23.133.2.3=.*'
|
|
'^[[:space:]]+directoryName:.*(,)?2.23.133.2.2=.*'
|
|
'^[[:space:]]+directoryName:.*(,)?2.23.133.2.1=.*'
|
|
'^[[:space:]]+Certificate Authority \(CA\): FALSE$'
|
|
'^[[:space:]]+Unknown extension 2.5.29.9 \(not critical\):$'
|
|
'^[[:space:]]+Hexdump: 3019301706056781050210310e300c0c03322e3002010002020092$')
|
|
if [ ${vtpm_is_tpm2} -ne 0 ]; then
|
|
# TPM 2.0; due to ecc: Key agreement
|
|
regexs+=('^[[:space:]]+Key agreement\.$'
|
|
'^[[:space:]]+Signature Algorithm: RSA-SHA256$')
|
|
else
|
|
regexs+=('^[[:space:]]+Key encipherment\.$'
|
|
'^[[:space:]]+Signature Algorithm: RSA-SHA1$')
|
|
fi
|
|
|
|
for ((i=0; i < ${#regexs}; i++)); do \
|
|
if [ -n "${regexs[$i]}" ] && \
|
|
[ -z "$(echo "${certinfo}" | grep -E "${regexs[$i]}")" ]; then
|
|
echo "Error: Could not match regex '${regexs[$i]}' with certificate info:"
|
|
echo "${certinfo}"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Send SIGTERM to TCSD
|
|
kill_quiet -15 "${TCSD_PID}"
|
|
|
|
# Shut down TPM
|
|
run_swtpm_ioctl "${SWTPM_INTERFACE}" -s
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM."
|
|
exit 1
|
|
fi
|
|
|
|
if wait_process_gone "${SWTPM_PID}" 4; then
|
|
echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore."
|
|
exit 1
|
|
fi
|
|
|
|
if wait_process_gone "${SWTPM_PID}" 4; then
|
|
echo "Error: tcsd should not be running anymore."
|
|
exit 1
|
|
fi
|
|
} # run_test
|
|
|
|
run_test "${OWNER_PASSWORD}" "${SRK_PASSWORD}" 1
|
|
echo "Test 1: OK"
|
|
|
|
run_test "${OWNER_PASSWORD}" "${SRK_PASSWORD}" 0
|
|
echo "Test 2: OK"
|
|
|
|
run_test "" "${SRK_PASSWORD}" 1
|
|
echo "Test 3: OK"
|
|
|
|
run_test "" "${SRK_PASSWORD}" 0
|
|
echo "Test 4: OK"
|
|
|
|
exit 0
|