blob: 78bc6ba132228d788224b649584077c9fefbf45b [file] [log] [blame]
#!/usr/bin/env bash
# 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")/..}
SWTPM_SETUP=${ROOT}/src/swtpm_setup/swtpm_setup
SWTPM_CREATE_TPMCA=${SRCDIR}/samples/swtpm-create-tpmca
SWTPM_LOCALCA=${SRCDIR}/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}/localca
SWTPM_LOCALCA_CONF=${workdir}/localca/swtpm-localca.conf
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
if [ -n "${srk_password}" ]; then
params="${params} --srkpass ${srk_password}"
else
params="${params} --srk-well-known"
fi
# 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}" \
--swtpm_ioctl ${SWTPM_IOCTL} \
--take-ownership \
${params} \
--tcsd-system-ps-file ${TCSD_SYSTEM_PS_FILE} &>/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
# 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_
chown tss:tss ${TCSD_CONF}
chmod 0600 ${TCSD_CONF}
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
echo "Error: TCSD with pid ${TCSD_PID} must have terminated"
exit 1
fi
if [ -n "${srk_password}" ]; then
params="--srk-password ${srk_password}"
else
params=""
fi
${SWTPM_CREATE_TPMCA} \
--dir ${SWTPM_LOCALCA_DIR} \
${params} \
--register \
--group tss \
--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"
# Repeat the test with the SRK having the well known password of 20 zero bytes
# We will have to check the help screen of swtpm-create-tpmca for whether
# it supports it, which in turn depends on tpmtool supporting it...
if [ -n "$(${SWTPM_CREATE_TPMCA} --help | grep "use 'well known' password if")" ]; then
run_test "${OWNER_PASSWORD}" "" 1
echo "Test 5: OK"
run_test "${OWNER_PASSWORD}" "" 0
echo "Test 6: OK"
run_test "" "" 1
echo "Test 7: OK"
run_test "" "" 0
echo "Test 8: OK"
else
if [ -n "$(tpmtool --help | grep srk-well-known)" ]; then
echo "Error: tpmtool seems to support --srk-well-known"
exit 1
fi
echo "tpmtool does not seem to support --srk-well-known"
echo "Tests 5..8: SKIP"
fi
exit 0