diff --git a/src/luks/tests/meson.build b/src/luks/tests/meson.build index 9e51fb6c..be3ad3a1 100644 --- a/src/luks/tests/meson.build +++ b/src/luks/tests/meson.build @@ -26,6 +26,7 @@ env.prepend('PATH', join_paths(meson.source_root(), 'src', 'luks'), join_paths(meson.source_root(), 'src', 'pins', 'sss'), join_paths(meson.source_root(), 'src', 'pins', 'tang'), + join_paths(meson.source_root(), 'src', 'pins', 'tpm1'), join_paths(meson.source_root(), 'src', 'pins', 'tpm2'), meson.current_source_dir(), meson.current_build_dir(), @@ -34,6 +35,7 @@ env.prepend('PATH', join_paths(meson.build_root(), 'src', 'pins', 'sss'), join_paths(meson.build_root(), 'src', 'pins', 'tang'), join_paths(meson.build_root(), 'src', 'pins', 'tang', 'tests'), + join_paths(meson.build_root(), 'src', 'pins', 'tpm1'), join_paths(meson.build_root(), 'src', 'pins', 'tpm2'), separator: ':' ) diff --git a/src/pins/tpm1/meson.build b/src/pins/tpm1/meson.build index bc9da3bc..783c7297 100644 --- a/src/pins/tpm1/meson.build +++ b/src/pins/tpm1/meson.build @@ -12,3 +12,24 @@ if all else warning('Will not install tpm1 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', 'tpm1'), + 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', 'tpm1'), + join_paths(meson.build_root(), 'src', 'pins', 'tpm2'), + separator: ':' +) +test('pin-tpm1', find_program('pin-tpm1'), env: env, timeout: 300) diff --git a/src/pins/tpm1/pin-tpm1 b/src/pins/tpm1/pin-tpm1 new file mode 100755 index 00000000..bf2ab5f0 --- /dev/null +++ b/src/pins/tpm1/pin-tpm1 @@ -0,0 +1,132 @@ +#!/bin/bash -x +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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 . +# + +TEST=$(basename "${0}") + +# Code to return to mark test as skipped. +SKIP_RET_CODE=77 + +tpm1_available() { + tpm_version_bin="$(command -v tpm_version || echo /usr/sbin/tpm_version)" + if ! "$tpm_version_bin" >/dev/null 2>&1; then + # The tpm_version outputs garbage to stdout on success, so let the + # tpm_version output the error again cleanly now + echo "The tpm1 pin requires tcsd daemon (trousers) running:" >&2 + if [ -x "$tpm_version_bin" ]; then + ( "$tpm_version_bin" 2>&1 | tr '\0' ' ' ) >&2 + else + echo Cannot check, tpm_version from tpm-tools not found >&2 + fi + return 1 + fi +} + +validate_pcrs() { + local _pcr_bank="${1}" + local _pcrs="${2}" + local _pcr + [ -z "${_pcr_bank}" ] && return 1 + [ -z "${_pcrs}" ] && return 0 + + for _pcr in ${_pcrs//,/ }; do + [ -f "/sys/class/tpm/tpm0/pcr-${_pcr_bank}/${_pcr}" ] || return 1 + done + + return 0 +} + +# Checking if we can run this test. +if ! tpm1_available; then + exit ${SKIP_RET_CODE} +fi + +decode_jwe() { + local jwe="${1}" + + local coded + if ! coded=$(jose jwe fmt -i- <<< "${jwe}"); then + return 1 + fi + + coded=$(jose fmt -j- -g protected -u- <<< "${coded}" | tr -d '"') + jose b64 dec -i- <<< "${coded}" +} + +test_pcr_ids() { + local orig="${1}" + local cfg="${2}" + local expected_pcr_ids="${3}" + + local enc + if ! enc=$(echo "${orig}" | clevis encrypt tpm1 "${cfg}"); then + echo "${TEST}: encrypt failed for cfg: ${cfg}" >&1 + return 1 + fi + + local pcr_ids + pcr_ids=$(decode_jwe "${enc}" \ + | jose fmt -j- -Og clevis -Og tpm1 -Og pcr_ids -u- 2>/dev/null) + + local dec + dec=$(echo "${enc}" | clevis decrypt) + + if [ "${orig}" != "${dec}" ]; then + echo "${TEST}: decoded text (${dec}) does not match original one (${orig})" >&2 + return 1 + fi + + if [ "${pcr_ids}" != "${expected_pcr_ids}" ]; then + echo "${TEST}: pcr_ids (${pcr_ids}) do not match the expected (${expected_pcr_ids}) result." >&2 + return 1 + fi +} + +test_enc_dec() { + local cfg="${1}" + output=$(echo Working | clevis encrypt tpm1 "${cfg}" | clevis decrypt) + + if [ "$output" != "Working" ]; then + echo "Output after decrypting doesn't match: ${output} != 'Working'" + return 1 + fi +} + +test_enc_dec '{}' || exit 1 +test_pcr_ids "${orig}" '{}' "" || exit 1 +test_pcr_ids "${orig}" '{ }' "" || exit 1 + +# Issue #103: now let's try a few different configs with both strings and +# arrays and check if we get the expected pcr_ids. + +# Let's first make sure this would be a valid configuration. +_default_pcr_bank="sha1" +if validate_pcrs "${_default_pcr_bank}" "4,16"; then + test_pcr_ids "${orig}" '{"pcr_ids": "16"}' "16" || exit 1 + test_pcr_ids "${orig}" '{"pcr_ids": ["16"]}' "16" || exit 1 + test_pcr_ids "${orig}" '{"pcr_ids": "4, 16"}' "4,16" || exit 1 + test_pcr_ids "${orig}" '{"pcr_ids": "4,16"}' "4,16" || exit 1 + test_pcr_ids "${orig}" '{"pcr_ids": ["4,16"]}' "4,16" || exit 1 + test_pcr_ids "${orig}" '{"pcr_ids": [4,16]}' "4,16" || exit 1 + test_pcr_ids "${orig}" '{"pcr_ids": [4, 16]}' "4,16" || exit 1 + test_pcr_ids "${orig}" '{"pcr_ids": ["4","16"]}' "4,16" || exit 1 + ! test_pcr_ids "${orig}" '{"pcr_ids": ["4","16"]}' "foo bar" || exit 1 +else + echo "Skipping tests related to issue#103 because the combination of pcr_bank and PCRs is invalid" >&2 +fi