| #!/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 |