1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
#!/bin/bash
#
# Calculate the boot_aggregate for each TPM bank, verifying that the
# boot_aggregate in the IMA measurement list matches one of them.
#
# A software TPM may be used to verify the boot_aggregate. If a
# software TPM is not already running on the system, this test
# starts one and initializes the TPM PCR banks by walking the sample
# binary_bios_measurements event log, included in this directory, and
# extending the TPM PCRs. The associated ascii_runtime_measurements
# for verifying the calculated boot_aggregate is included in this
# directory as well.
trap '_report_exit_and_cleanup cleanup' SIGINT SIGTERM EXIT
# Base VERBOSE on the environment variable, if set.
VERBOSE="${VERBOSE:-0}"
cd "$(dirname "$0")"
export PATH=../src:$PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH
. ./functions.sh
_require evmctl
TSSDIR="$(dirname -- "$(which tssstartup)")"
PCRFILE="/sys/class/tpm/tpm0/device/pcrs"
MISC_PCRFILE="/sys/class/misc/tpm0/device/pcrs"
# Only stop this test's software TPM
cleanup() {
if [ -n "${SWTPM_PID}" ]; then
kill -SIGTERM "${SWTPM_PID}"
elif [ -n "${TPMSERVER_PID}" ]; then
"${TSSDIR}/tsstpmcmd" -stop
fi
}
# Try to start a software TPM if needed.
swtpm_start() {
local tpm_server swtpm
tpm_server="$(which tpm_server)"
swtpm="$(which swtpm)"
if [ -z "${tpm_server}" ] && [ -z "${swtpm}" ]; then
echo "${CYAN}SKIP: Software TPM (tpm_server and swtpm) not found${NORM}"
return "$SKIP"
fi
if [ -n "${swtpm}" ]; then
pgrep swtpm
if [ $? -eq 0 ]; then
echo "INFO: Software TPM (swtpm) already running"
return 114
else
echo "INFO: Starting software TPM: ${swtpm}"
mkdir -p ./myvtpm
${swtpm} socket --tpmstate dir=./myvtpm --tpm2 --ctrl type=tcp,port=2322 --server type=tcp,port=2321 --flags not-need-init > /dev/null 2>&1 &
SWTPM_PID=$!
fi
elif [ -n "${tpm_server}" ]; then
# tpm_server uses the Microsoft simulator encapsulated packet format
export TPM_SERVER_TYPE="mssim"
pgrep tpm_server
if [ $? -eq 0 ]; then
echo "INFO: Software TPM (tpm_server) already running"
return 114
else
echo "INFO: Starting software TPM: ${tpm_server}"
${tpm_server} > /dev/null 2>&1 &
TPMSERVER_PID=$!
fi
fi
return 0
}
# Initialize the software TPM using the sample binary_bios_measurements log.
swtpm_init() {
if [ ! -f "${TSSDIR}/tssstartup" ] || [ ! -f "${TSSDIR}/tsseventextend" ]; then
echo "${CYAN}SKIP: tssstartup and tsseventextend needed for test${NORM}"
return "$SKIP"
fi
echo "INFO: Sending software TPM startup"
"${TSSDIR}/tssstartup"
if [ $? -ne 0 ]; then
echo "INFO: Retry sending software TPM startup"
sleep 1
"${TSSDIR}/tssstartup"
fi
if [ $? -ne 0 ]; then
echo "INFO: Software TPM startup failed"
return "$SKIP"
fi
echo "INFO: Walking ${BINARY_BIOS_MEASUREMENTS} initializing the software TPM"
# $(${TSSDIR}/tsseventextend -tpm -if "${BINARY_BIOS_MEASUREMENTS}" -v) 2>&1 > /dev/null
"${TSSDIR}/tsseventextend" -tpm -if "${BINARY_BIOS_MEASUREMENTS}" -v > /dev/null 2>&1
}
# In VERBOSE mode, display the calculated TPM PCRs for the different banks.
display_pcrs() {
local PCRMAX=9
local banks=("sha1" "sha256")
local i;
for bank in "${banks[@]}"; do
echo "INFO: Displaying ${bank} TPM bank (PCRs 0 - 9)"
for i in $(seq 0 $PCRMAX); do
rc=0
pcr=$("${TSSDIR}/tsspcrread" -halg "${bank}" -ha "${i}" -ns)
if [ $rc -ne 0 ]; then
echo "INFO: tsspcrread failed: $pcr"
break
fi
echo "$i: $pcr"
done
done
}
# The first entry in the IMA measurement list is the "boot_aggregate".
# For each kexec, an additional "boot_aggregate" will appear in the
# measurement list, assuming the previous measurement list is carried
# across the kexec.
#
# Verify that the last "boot_aggregate" record in the IMA measurement
# list matches.
check() {
local options=$1
echo "INFO: Calculating the boot_aggregate (PCRs 0 - 9) for multiple banks"
bootaggr=$(evmctl ima_boot_aggregate ${options})
if [ $? -ne 0 ]; then
echo "${CYAN}SKIP: evmctl ima_boot_aggregate: $bootaggr${NORM}"
exit "$SKIP"
fi
boot_aggr=( $bootaggr )
echo "INFO: Searching for the boot_aggregate in ${ASCII_RUNTIME_MEASUREMENTS}"
for hash in "${boot_aggr[@]}"; do
if [ "$VERBOSE" != "0" ]; then
echo "$hash"
fi
if grep -e " boot_aggregate$" -e " boot_aggregate.$" "${ASCII_RUNTIME_MEASUREMENTS}" | tail -n 1 | grep -q "${hash}"; then
echo "${GREEN}SUCCESS: boot_aggregate ${hash} found${NORM}"
return "$OK"
fi
done
echo "${RED}FAILURE: boot_aggregate not found${NORM}"
echo "$bootaggr"
return "$FAIL"
}
if [ "$(id -u)" = 0 ] && [ -c "/dev/tpm0" ]; then
BOOTAGGR_OPTIONS="--hwtpm"
ASCII_RUNTIME_MEASUREMENTS="/sys/kernel/security/ima/ascii_runtime_measurements"
if [ ! -d "/sys/kernel/security/ima" ]; then
echo "${CYAN}SKIP: CONFIG_IMA not enabled${NORM}"
exit "$SKIP"
fi
else
BINARY_BIOS_MEASUREMENTS="./sample-binary_bios_measurements-pcrs-8-9"
ASCII_RUNTIME_MEASUREMENTS="./sample-ascii_runtime_measurements-pcrs-8-9"
export TPM_INTERFACE_TYPE="socsim"
export TPM_COMMAND_PORT=2321
export TPM_PLATFORM_PORT=2322
export TPM_SERVER_NAME="localhost"
# swtpm uses the raw, unencapsulated packet format
export TPM_SERVER_TYPE="raw"
fi
# Start and initialize a software TPM as needed
if [ "$(id -u)" != 0 ] || [ ! -c "/dev/tpm0" ]; then
if [ -f "$PCRFILE" ] || [ -f "$MISC_PCRFILE" ]; then
echo "${CYAN}SKIP: system has discrete TPM 1.2, sample TPM 2.0 event log test not supported.${NORM}"
exit "$SKIP"
fi
swtpm_start
error=$?
if [ $error -eq "$SKIP" ]; then
echo "skip: swtpm not installed"
exit "$SKIP"
fi
if [ $error -eq 0 ]; then
swtpm_init
if [ $? -eq "$SKIP" ]; then
echo "testing boot_aggregate without entries"
exit "$SKIP"
fi
fi
if [ "$VERBOSE" != "0" ]; then
display_pcrs
fi
fi
expect_pass check $BOOTAGGR_OPTIONS
|