Skip to content

Commit

Permalink
tpm2: added TPM 2 software TPM tests
Browse files Browse the repository at this point in the history
Signed-off-by: Oldřich Jedlička <[email protected]>
  • Loading branch information
oldium committed Nov 14, 2024
1 parent e27d968 commit 6b23f47
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 79 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/install-dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ debian:*|ubuntu:*)
build-essential pkg-config libssl-dev libjansson-dev libjose-dev \
luksmeta libluksmeta-dev libpwquality-tools libglib2.0-dev \
libudisks2-dev libaudit-dev systemd opensc pcscd libsofthsm2-dev \
swtpm-tools tpm-tools; do
swtpm-tools tpm-tools tpm2-tools; do
sleep 5
done
;;
Expand Down
20 changes: 1 addition & 19 deletions src/pins/tpm2/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,7 @@ if all
bins += join_paths(meson.current_source_dir(), 'clevis-decrypt-tpm2')
bins += join_paths(meson.current_source_dir(), 'clevis-encrypt-tpm2')
mans += join_paths(meson.current_source_dir(), 'clevis-encrypt-tpm2.1')
subdir('tests')
else
warning('Will not install tpm2 pin due to missing dependencies!')
endif

# Tests.
env = environment()
env.prepend('PATH',
join_paths(meson.source_root(), 'src'),
join_paths(meson.source_root(), 'src', 'luks'),
join_paths(meson.source_root(), 'src', 'luks', 'tests'),
join_paths(meson.source_root(), 'src', 'pins', 'sss'),
join_paths(meson.source_root(), 'src', 'pins', 'tang'),
join_paths(meson.source_root(), 'src', 'pins', 'tpm2'),
join_paths(meson.build_root(), 'src'),
join_paths(meson.build_root(), 'src', 'luks'),
join_paths(meson.build_root(), 'src', 'luks', 'tests'),
join_paths(meson.build_root(), 'src', 'pins', 'sss'),
join_paths(meson.build_root(), 'src', 'pins', 'tang'),
join_paths(meson.build_root(), 'src', 'pins', 'tpm2'),
separator: ':'
)
test('pin-tpm2', find_program('pin-tpm2'), env: env, timeout: 120)
42 changes: 42 additions & 0 deletions src/pins/tpm2/tests/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Tests.
env = environment()
env.prepend('PATH',
join_paths(meson.source_root(), 'src'),
join_paths(meson.source_root(), 'src', 'luks'),
join_paths(meson.source_root(), 'src', 'luks', 'tests'),
join_paths(meson.source_root(), 'src', 'pins', 'sss'),
join_paths(meson.source_root(), 'src', 'pins', 'tang'),
join_paths(meson.source_root(), 'src', 'pins', 'tpm2'),
join_paths(meson.source_root(), 'src', 'pins', 'tpm2', 'tests'),
join_paths(meson.build_root(), 'src'),
join_paths(meson.build_root(), 'src', 'luks'),
join_paths(meson.build_root(), 'src', 'luks', 'tests'),
join_paths(meson.build_root(), 'src', 'pins', 'sss'),
join_paths(meson.build_root(), 'src', 'pins', 'tang'),
join_paths(meson.build_root(), 'src', 'pins', 'tpm2'),
join_paths(meson.build_root(), 'src', 'pins', 'tpm2', 'tests'),
separator: ':'
)

tpm2_data = configuration_data()
tpm2_data.merge_from(data)

socat = find_program('socat', required: false)
swtpm = find_program('swtpm', '/usr/bin/swtpm', required: false)
swtpm_setup = find_program('swtpm_setup', '/usr/bin/swtpm_setup', required: false)
swtpm_bios = find_program('swtpm_bios', '/usr/bin/swtpm_bios', required: false)


tpm2_data.set('SOCAT_BIN', socat.found() ? socat.path() : '')
tpm2_data.set('SWTPM_BIN', swtpm.found() ? swtpm.path() : '')
tpm2_data.set('SWTPM_SETUP_BIN', swtpm_setup.found() ? swtpm_setup.path() : '')
tpm2_data.set('SWTPM_BIOS_BIN', swtpm_bios.found() ? swtpm_bios.path() : '')

configure_file(
input: 'tpm2-common-test-functions.in',
output: 'tpm2-common-test-functions',
configuration: tpm2_data,
)

test('pin-tpm2-hw', find_program('pin-tpm2-hw'), env: env, timeout: 120)
test('pin-tpm2-sw', find_program('pin-tpm2-sw'), env: env, timeout: 120)
26 changes: 26 additions & 0 deletions src/pins/tpm2/tests/pin-tpm2-hw
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash -x
# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
#
# Copyright (c) 2019 Red Hat, Inc.
# Author: Sergio Correia <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

. tpm2-common-test-functions

tpm2_hw_available || skip_test
tpm2_version || skip_test

. pin-tpm2-tests
27 changes: 27 additions & 0 deletions src/pins/tpm2/tests/pin-tpm2-sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash -x
# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
#
# Copyright (c) 2019 Red Hat, Inc.
# Author: Sergio Correia <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

. tpm2-common-test-functions

tpm2_sw_check_preconditions
tpm2_version || skip_test
tpm2_start_emulation

. pin-tpm2-tests
61 changes: 2 additions & 59 deletions src/pins/tpm2/pin-tpm2 → src/pins/tpm2/tests/pin-tpm2-tests
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,6 @@

TEST=$(basename "${0}")

# Code to return to mark test as skipped.
SKIP_RET_CODE=77

tpm2_available() {
# Old environment variables for tpm2-tools 3.0
export TPM2TOOLS_TCTI_NAME=device
export TPM2TOOLS_DEVICE_FILE=
for dev in /dev/tpmrm?; do
[ -e "${dev}" ] || continue
TPM2TOOLS_DEVICE_FILE="${dev}"
break
done

# New environment variable for tpm2-tools >= 3.1
export TPM2TOOLS_TCTI="${TPM2TOOLS_TCTI_NAME}:${TPM2TOOLS_DEVICE_FILE}"

if [ -z "${TPM2TOOLS_DEVICE_FILE}" ]; then
echo "A TPM2 device with the in-kernel resource manager is needed!" >&2
return 1
fi

if ! [[ -r "${TPM2TOOLS_DEVICE_FILE}" \
&& -w "${TPM2TOOLS_DEVICE_FILE}" ]]; then
echo "The ${TPM2TOOLS_DEVICE_FILE} device must be readable and writable!" >&2
return 1
fi

local _tpm2tools_info="$(tpm2_createprimary -v)"
local _match='version="(.)\.'
[[ ${_tpm2tools_info} =~ ${_match} ]] && TPM2TOOLS_VERSION="${BASH_REMATCH[1]}"
if [[ $TPM2TOOLS_VERSION -lt 3 ]] || [[ $TPM2TOOLS_VERSION -gt 5 ]]; then
echo "The tpm2 pin requires a tpm2-tools version between 3 and 5" >&2
return 1
fi
export TPM2TOOLS_VERSION
}

validate_pcrs() {
local _pcr_bank="${1}"
local _pcrs="${2}"
Expand All @@ -77,11 +40,6 @@ validate_pcrs() {
return 0
}

# Checking if we can run this test.
if ! tpm2_available; then
exit ${SKIP_RET_CODE}
fi

decode_jwe() {
local jwe="${1}"

Expand Down Expand Up @@ -160,32 +118,17 @@ else
fi

# Test with policies if we have the PIN rewrite available
if ! $(which clevis-pin-tpm2 >/dev/null 2>&1);
if ! command -v clevis-pin-tpm2 >/dev/null 2>&1;
then
echo "No PIN rewrite available"
exit 0
fi
if ! $(which clevis-pin-tpm2-signtool >/dev/null 2>&1);
if ! command -v clevis-pin-tpm2-signtool >/dev/null 2>&1;
then
echo "No policy signtool available"
exit 0
fi

function on_exit() {
popd
if [ ! -d "$TMP" ] || ! rm -rf "$TMP"; then
echo "Delete temporary files failed!" >&2
echo "You need to clean up: $TMP" >&2
exit 1
fi
}
if ! TMP="$(mktemp -d)"; then
echo "Creating a temporary dir for TPM files failed!" >&2
exit 1
fi
trap 'on_exit' EXIT
pushd $TMP

clevis-pin-tpm2-signtool >policy_working.json << EOP
---
- policy_ref:
Expand Down
135 changes: 135 additions & 0 deletions src/pins/tpm2/tests/tpm2-common-test-functions.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/bin/bash -x
# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
#
# Copyright (c) 2019 Red Hat, Inc.
# Author: Sergio Correia <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

. tests-common-functions

SOCAT_BIN="@SOCAT_BIN@"
SWTPM_BIN="@SWTPM_BIN@"
SWTPM_SETUP_BIN="@SWTPM_SETUP_BIN@"
SWTPM_BIOS_BIN="@SWTPM_BIOS_BIN@"

SWTPM_SOCKET_PID=
SOCAT_SERVER_PID=
SOCAT_CONTROL_PID=

function on_exit() {
popd || error "Unable to change directory"
if [ ! -d "$TESTDIR" ] || ! rm -rf "$TESTDIR"; then
echo "Delete temporary files failed!" >&2
echo "You need to clean up: $TESTDIR" >&2
exit 1
fi

# Cleanup sw emulation
[ -n "$SOCAT_SERVER_PID" ] && kill $SOCAT_SERVER_PID >/dev/null 2>&1
[ -n "$SOCAT_CONTROL_PID" ] && kill $SOCAT_CONTROL_PID >/dev/null 2>&1
if [ -n "$SWTPM_SOCKET_PID" ]; then
kill $SWTPM_SOCKET_PID >/dev/null 2>&1
sleep .5
# swtpm does not always terminate gracefully, so kill it
kill -9 $SWTPM_SOCKET_PID >/dev/null 2>&1
fi
}
if ! TESTDIR="$(mktemp -d)"; then
echo "Creating a temporary dir for TPM files failed!" >&2
exit 1
fi
trap 'on_exit' EXIT
pushd "$TESTDIR" || error "Unable to change directory"


tpm2_hw_available() {
# Old environment variables for tpm2-tools 3.0
export TPM2TOOLS_TCTI_NAME=device
export TPM2TOOLS_DEVICE_FILE=
for dev in /dev/tpmrm?; do
[ -e "${dev}" ] || continue
TPM2TOOLS_DEVICE_FILE="${dev}"
break
done

# New environment variable for tpm2-tools >= 3.1
export TPM2TOOLS_TCTI="${TPM2TOOLS_TCTI_NAME}:${TPM2TOOLS_DEVICE_FILE}"

if [ -z "${TPM2TOOLS_DEVICE_FILE}" ]; then
echo "A TPM2 device with the in-kernel resource manager is needed!" >&2
return 1
fi

if ! [[ -r "${TPM2TOOLS_DEVICE_FILE}" \
&& -w "${TPM2TOOLS_DEVICE_FILE}" ]]; then
echo "The ${TPM2TOOLS_DEVICE_FILE} device must be readable and writable!" >&2
return 1
fi
return 0
}

tpm2_version() {
local _tpm2tools_info
local _match='version="(.)\.'
_tpm2tools_info="$(tpm2_createprimary -v)"
[[ ${_tpm2tools_info} =~ ${_match} ]] && TPM2TOOLS_VERSION="${BASH_REMATCH[1]}"
if [[ $TPM2TOOLS_VERSION -lt 3 ]] || [[ $TPM2TOOLS_VERSION -gt 5 ]]; then
echo "The tpm2 pin requires a tpm2-tools version between 3 and 5" >&2
return 1
fi
export TPM2TOOLS_VERSION
}

tpm2_sw_check_preconditions() {
[ -x "${SWTPM_BIN}" ] || skip_test "Skipping TPM2 test with software emulation, swtpm not found"
[ -x "${SWTPM_SETUP_BIN}" ] || skip_test "Skipping TPM2 test with software emulation, swtpm_setup not found"
[ -x "${SWTPM_BIOS_BIN}" ] || skip_test "Skipping TPM2 test with software emulation, swtpm_bios not found"

if ! "${SWTPM_BIN}" socket --print-capabilities | jq -e '(.version | test("^0\\.[0-6](\\..*)?$")) or (.features | index("tpm-2.0"))' >/dev/null 2>&1; then
skip_test "Skipping TPM2 test with software emulation, no support for TPM 2.0 in swtpm"
fi
}

tpm2_start_emulation() {
local socket_wait
local server_sock
local control_sock

echo "Starting TPM 2 emulation" >&2

# Setup TPM 2 data
"${SWTPM_SETUP_BIN}" --tpm-state "$TESTDIR" --tpm2 --create-ek-cert --create-platform-cert --lock-nvram --display >&2 || error "Unable to setup TPM 2 emulation"

# Start emulation over socket
server_sock="$TESTDIR"/swtpm.server.sock
control_sock="$TESTDIR"/swtpm.ctrl.sock
"${SWTPM_BIN}" socket --tpmstate dir="$TESTDIR" --tpm2 --ctrl type=unixio,path="$control_sock" --server type=unixio,path="$server_sock" --flags not-need-init >&2 &
SWTPM_SOCKET_PID=$!

socket_wait=1
while [ $socket_wait -le 100 ]; do
[ -S "$server_sock" ] && break
socket_wait=$((socket_wait + 1))
sleep 0.1
done
[ "$socket_wait" -gt 100 ] && error "Unable to start TPM 2 emulation"

# Run BIOS checks
"${SWTPM_BIOS_BIN}" --tpm2 --unix "$server_sock" || error "Unable to prepare TPM 2 emulation"

# Use swtpm in tpm2-tools
export TPM2TOOLS_TCTI="cmd:\"$SOCAT_BIN\" - \"UNIX-CONNECT:$server_sock\""
}

0 comments on commit 6b23f47

Please sign in to comment.