From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B48BC2D0E8 for ; Wed, 25 Mar 2020 22:27:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2EC632070A for ; Wed, 25 Mar 2020 22:27:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727402AbgCYW1d (ORCPT ); Wed, 25 Mar 2020 18:27:33 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:23438 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727389AbgCYW1d (ORCPT ); Wed, 25 Mar 2020 18:27:33 -0400 Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 02PM4YEO077105 for ; Wed, 25 Mar 2020 18:27:29 -0400 Received: from e06smtp07.uk.ibm.com (e06smtp07.uk.ibm.com [195.75.94.103]) by mx0a-001b2d01.pphosted.com with ESMTP id 2ywe7v6bf4-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 25 Mar 2020 18:27:29 -0400 Received: from localhost by e06smtp07.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 25 Mar 2020 22:27:26 -0000 Received: from b06cxnps4074.portsmouth.uk.ibm.com (9.149.109.196) by e06smtp07.uk.ibm.com (192.168.101.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Wed, 25 Mar 2020 22:27:24 -0000 Received: from d06av22.portsmouth.uk.ibm.com (d06av22.portsmouth.uk.ibm.com [9.149.105.58]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 02PMRNdV44761246 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 25 Mar 2020 22:27:23 GMT Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AE8574C044; Wed, 25 Mar 2020 22:27:23 +0000 (GMT) Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 99D274C040; Wed, 25 Mar 2020 22:27:22 +0000 (GMT) Received: from localhost.localdomain (unknown [9.85.132.168]) by d06av22.portsmouth.uk.ibm.com (Postfix) with ESMTP; Wed, 25 Mar 2020 22:27:22 +0000 (GMT) From: Mimi Zohar To: linux-integrity@vger.kernel.org Cc: Roberto Sassu , Vitaly Chikunov , Patrick Uiterwijk , Lakshmi Ramasubramanian , Mimi Zohar Subject: [RFC PATCH 1/3] ima-evm-utils: tests: verify boot_aggregate Date: Wed, 25 Mar 2020 18:26:15 -0400 X-Mailer: git-send-email 2.7.5 In-Reply-To: <1585175177-20739-1-git-send-email-zohar@linux.ibm.com> References: <1585175177-20739-1-git-send-email-zohar@linux.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 20032522-0028-0000-0000-000003EBD2BC X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 20032522-0029-0000-0000-000024B14208 Message-Id: <1585175177-20739-2-git-send-email-zohar@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138,18.0.645 definitions=2020-03-25_13:2020-03-24,2020-03-25 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 impostorscore=0 bulkscore=0 phishscore=0 spamscore=0 adultscore=0 mlxscore=0 lowpriorityscore=0 suspectscore=1 malwarescore=0 priorityscore=1501 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2003250166 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Calculate the boot_aggregate for each TPM bank and verify 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. Signed-off-by: Mimi Zohar --- tests/Makefile.am | 2 +- tests/boot_aggregate.test | 144 ++++++++++++++++++++++++++++++++++ tests/test_ascii_runtime_measurements | 3 + tests/test_binary_bios_measurements | Bin 0 -> 23248 bytes 4 files changed, 148 insertions(+), 1 deletion(-) create mode 100755 tests/boot_aggregate.test create mode 100644 tests/test_ascii_runtime_measurements create mode 100644 tests/test_binary_bios_measurements diff --git a/tests/Makefile.am b/tests/Makefile.am index 029f2ffd5efb..ff928e177406 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,7 @@ check_SCRIPTS = TESTS = $(check_SCRIPTS) -check_SCRIPTS += ima_hash.test sign_verify.test +check_SCRIPTS += ima_hash.test sign_verify.test boot_aggregate.test clean-local: -rm -f *.txt *.out *.sig *.sig2 diff --git a/tests/boot_aggregate.test b/tests/boot_aggregate.test new file mode 100755 index 000000000000..307a309433fe --- /dev/null +++ b/tests/boot_aggregate.test @@ -0,0 +1,144 @@ +#!/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 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)) + +if [ $(id -u) = 0 ] && [ -c "/dev/tpm0" ]; then + ASCII_RUNTIME_MEASUREMENTS="/sys/kernel/security/ima/ascii_runtime_measurements" +else + BINARY_BIOS_MEASUREMENTS="./test_binary_bios_measurements" + ASCII_RUNTIME_MEASUREMENTS="./test_ascii_runtime_measurements" + export TPM_INTERFACE_TYPE="socsim" + export TPM_COMMAND_PORT=2321 +fi + +# Only stop this test's software TPM. Preferred method: "tsstpmcmd -stop" +cleanup() { + if [ ! -z ${SWTPM_PPID} ]; then + if [ -f ${TSSDIR}/tsstpmcmd ]; then + ${TSSDIR}/tsstpmcmd -stop + else + pkill -P ${SWTPM_PPID} + fi + fi +} + +# Try to start a software TPM if needed. +swtpm_start() { + local swtpm="$(which tpm_server)" + + if [ -z ${swtpm} ]; then + echo "SKIP: Softare TPM (tpm_server) not found" + return $SKIP + fi + + ps -ael | grep -q tpm_server + if [ $? -eq 0 ]; then + echo "INFO: Software TPM (tpm_server) already running" + return 114 + else + echo "INFO: Starting software TPM: ${swtpm}" + $(${swtpm}) 2>1 > /dev/null & + SWTPM_PPID=$! + 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 "SKIP: tssstartup and tsseventextend needed for test" + return $SKIP + fi + + echo "INFO: Walking ${BINARY_BIOS_MEASUREMENTS} initializing the software TPM" + $(${TSSDIR}/tssstartup) + $(${TSSDIR}/tsseventextend -tpm -if "${BINARY_BIOS_MEASUREMENTS}" -v) 2>1 > /dev/null +} + +# In VERBOSE mode, display the calculated TPM PCRs for the different banks. +display_pcrs() { + local PCRMAX=7 + local banks=("sha1" "sha256") + local i; + + for bank in "${banks[@]}"; do + echo "INFO: Displaying ${bank} TPM bank (PCRs 0 - 7)" + 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: $tpm1" + break + fi + echo "$i: $pcr" + done + done +} + +# The first entry in the IMA measuremnet list is the "boot_aggregate". +check() { + echo "INFO: Calculating the boot_aggregate (PCRs 0 - 7) for multiple banks" + bootaggr=$(evmctl ima_boot_aggregate) + if [ $? -ne 0 ]; then + echo "SKIP: evmctl ima_boot_aggregate: $bootaggr" + 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 -q "${hash}" "${ASCII_RUNTIME_MEASUREMENTS}"; then + echo "SUCCESS: boot_aggregate ${hash} found" + return $OK + fi + done + echo "FAILURE: boot_aggregate not found" + return $FAIL +} + +# Start and initialize a software TPM as needed +if [ $(id -u) != 0 ] || [ ! -c "/dev/tpm0" ]; then + swtpm_start + error=$? + if [ $error -eq $SKIP ]; then + exit $SKIP + fi + + if [ $error -eq 0 ]; then + swtpm_init + if [ $? -eq $SKIP ]; then + exit $SKIP + fi + fi + if [ "$VERBOSE" != "0" ]; then + display_pcrs + fi +fi + +expect_pass check diff --git a/tests/test_ascii_runtime_measurements b/tests/test_ascii_runtime_measurements new file mode 100644 index 000000000000..937b5038127e --- /dev/null +++ b/tests/test_ascii_runtime_measurements @@ -0,0 +1,3 @@ +10 cf41b43c4031672fcc2bd358b309ad33b977424f ima-ng sha256:f1b4c7c9b27e94569f4c2b64051c452bc609c3cb891dd7fae06b758f8bc83d14 boot_aggregate +10 983dcd8e6f7c84a1a5f10e762d1850623966ceab ima-ng sha256:ae06e032a65fed8102aff5f8f31c678dcf2eb25b826f77ecb699faa0411f89e0 /init +10 b6e4d01c73f6e4b698eaf48e7d76a2bae0c02514 ima-ng sha256:4b1764ee112aa8b2a6ae9a3a2f1e272b6601681f610708497673cd49e5bd2f5c /bin/sh diff --git a/tests/test_binary_bios_measurements b/tests/test_binary_bios_measurements new file mode 100644 index 0000000000000000000000000000000000000000..338ba22f9e41e9039ff5ce81bb18197c5ac1647c GIT binary patch literal 23248 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 literal 0 HcmV?d00001 -- 2.7.5