swtpm/tests/test_samples_create_tpmca
Stefan Berger 8ff6418949 tests: Try with tcsd.conf ownership of root:tss if tss:tss did not work
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>
2020-11-09 17:06:09 -05:00

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