]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test: add pcrlock integration test
authorLennart Poettering <lennart@poettering.net>
Thu, 26 Oct 2023 11:52:06 +0000 (13:52 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 3 Nov 2023 10:25:14 +0000 (11:25 +0100)
(Contains various test additions added by @mrc0mmand)

test/units/testsuite-70.pcrlock.sh [new file with mode: 0755]

diff --git a/test/units/testsuite-70.pcrlock.sh b/test/units/testsuite-70.pcrlock.sh
new file mode 100755 (executable)
index 0000000..415bfa8
--- /dev/null
@@ -0,0 +1,137 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+# shellcheck source=test/units/util.sh
+. "$(dirname "$0")"/util.sh
+
+export SYSTEMD_LOG_LEVEL=debug
+export PAGER=
+SD_PCREXTEND="/usr/lib/systemd/systemd-pcrextend"
+SD_PCRLOCK="/usr/lib/systemd/systemd-pcrlock"
+
+if [[ ! -x "${SD_PCREXTEND:?}" ]] || [[ ! -x "${SD_PCRLOCK:?}" ]] ; then
+    echo "$SD_PCREXTEND or $SD_PCRLOCK not found, skipping pcrlock tests"
+    exit 0
+fi
+
+at_exit() {
+    if [[ $? -ne 0 ]]; then
+        # Dump the event log on fail, to make debugging a bit easier
+        [[ -e /run/log/systemd/tpm2-measure.log ]] && jq --seq --slurp </run/log/systemd/tpm2-measure.log
+    fi
+
+    return 0
+}
+
+trap at_exit EXIT
+
+# Temporarily override sd-pcrextend's sanity checks
+export SYSTEMD_FORCE_MEASURE=1
+
+# The PCRs we are going to lock to. We exclude the various PCRs we touched
+# above where no event log record was written, because we cannot analyze
+# things without event log. We include debug PCR 16, see below.
+PCRS="1+2+3+4+5+16"
+
+# Remove the old measurement log, as it contains all kinds of nonsense from the
+# previous test, which will fail our consistency checks. Removing the file also
+# means we'll fail consistency check, but at least we'll fail them consistently
+# (as the PCR values simply won't match the log).
+rm -f /run/log/systemd/tpm2-measure.log
+
+SYSTEMD_COLORS=256 "$SD_PCRLOCK"
+"$SD_PCRLOCK" cel --no-pager --json=pretty
+"$SD_PCRLOCK" log --pcr="$PCRS"
+"$SD_PCRLOCK" log --json=pretty --pcr="$PCRS"
+"$SD_PCRLOCK" list-components
+"$SD_PCRLOCK" list-components --location=250-
+"$SD_PCRLOCK" list-components --location=250-:350-
+"$SD_PCRLOCK" lock-firmware-config
+"$SD_PCRLOCK" lock-gpt
+"$SD_PCRLOCK" lock-machine-id
+"$SD_PCRLOCK" lock-file-system
+"$SD_PCRLOCK" lock-file-system /
+"$SD_PCRLOCK" predict --pcr="$PCRS"
+"$SD_PCRLOCK" predict --pcr="0x1+0x3+4"
+"$SD_PCRLOCK" predict --json=pretty --pcr="$PCRS"
+
+SD_STUB="$(find /usr/lib/systemd/boot/efi/ -name "systemd-boot*.efi" | head -n1)"
+if [[ -n "$SD_STUB" ]]; then
+    "$SD_PCRLOCK" lock-pe "$SD_STUB"
+    "$SD_PCRLOCK" lock-pe <"$SD_STUB"
+    "$SD_PCRLOCK" lock-uki "$SD_STUB"
+    "$SD_PCRLOCK" lock-uki <"$SD_STUB"
+fi
+
+PIN=huhu "$SD_PCRLOCK" make-policy --pcr="$PCRS" --recovery-pin=yes
+# Repeat immediately (this call will have to reuse the nvindex, rather than create it)
+"$SD_PCRLOCK" make-policy --pcr="$PCRS"
+"$SD_PCRLOCK" make-policy --pcr="$PCRS" --force
+
+img="/tmp/pcrlock.img"
+truncate -s 20M "$img"
+echo -n hoho >/tmp/pcrlockpwd
+chmod 0600 /tmp/pcrlockpwd
+cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$img" /tmp/pcrlockpwd
+
+systemd-cryptenroll --unlock-key-file=/tmp/pcrlockpwd --tpm2-device=auto --tpm2-pcrlock=/var/lib/systemd/pcrlock.json --tpm2-public-key= --wipe-slot=tpm2 "$img"
+systemd-cryptsetup attach pcrlock "$img" - tpm2-device=auto,tpm2-pcrlock=/var/lib/systemd/pcrlock.json
+systemd-cryptsetup detach pcrlock
+
+# Measure something into PCR 16 (the "debug" PCR), which should make the activation fail
+"$SD_PCREXTEND" --pcr=16 test70
+
+"$SD_PCRLOCK" cel --json=pretty
+
+(! systemd-cryptsetup attach pcrlock "$img" - tpm2-device=auto,tpm2-pcrlock=/var/lib/systemd/pcrlock.json,headless )
+
+# Now add a component for it, rebuild policy and it should work (we'll rebuild
+# once like that, but don't provide the recovery pin. This should fail, since
+# the PCR is hosed after all. But then we'll use recovery pin, and it should
+# work.
+echo -n test70 | "$SD_PCRLOCK" lock-raw --pcrlock=/var/lib/pcrlock.d/910-test70.pcrlock --pcr=16
+(! "$SD_PCRLOCK" make-policy --pcr="$PCRS")
+PIN=huhu "$SD_PCRLOCK" make-policy --pcr="$PCRS" --recovery-pin=yes
+
+systemd-cryptsetup attach pcrlock "$img" - tpm2-device=auto,tpm2-pcrlock=/var/lib/systemd/pcrlock.json
+systemd-cryptsetup detach pcrlock
+
+# And now let's do it the clean way, and generate the right policy ahead of time.
+echo -n test70-take-two | "$SD_PCRLOCK" lock-raw --pcrlock=/var/lib/pcrlock.d/920-test70.pcrlock --pcr=16
+"$SD_PCRLOCK" make-policy --pcr="$PCRS"
+
+"$SD_PCREXTEND" --pcr=16 test70-take-two
+
+"$SD_PCRLOCK" cel --json=pretty
+
+systemd-cryptsetup attach pcrlock "$img" - tpm2-device=auto,tpm2-pcrlock=/var/lib/systemd/pcrlock.json
+systemd-cryptsetup detach pcrlock
+
+"$SD_PCRLOCK" remove-policy
+
+"$SD_PCRLOCK" unlock-firmware-config
+"$SD_PCRLOCK" unlock-gpt
+"$SD_PCRLOCK" unlock-machine-id
+"$SD_PCRLOCK" unlock-file-system
+"$SD_PCRLOCK" unlock-raw --pcrlock=/var/lib/pcrlock.d/910-test70.pcrlock
+"$SD_PCRLOCK" unlock-raw --pcrlock=/var/lib/pcrlock.d/920-test70.pcrlock
+
+(! "$SD_PCRLOCK" "")
+(! "$SD_PCRLOCK" predict --pcr=-1)
+(! "$SD_PCRLOCK" predict --pcr=foo)
+(! "$SD_PCRLOCK" predict --pcr=1+1)
+(! "$SD_PCRLOCK" predict --pcr=1+++++1)
+(! "$SD_PCRLOCK" make-policy --nv-index=0)
+(! "$SD_PCRLOCK" make-policy --nv-index=foo)
+(! "$SD_PCRLOCK" list-components --location=:)
+(! "$SD_PCRLOCK" lock-gpt "")
+(! "$SD_PCRLOCK" lock-gpt /dev/sr0)
+(! "$SD_PCRLOCK" lock-pe /dev/full)
+(! "$SD_PCRLOCK" lock-pe /bin/true)
+(! "$SD_PCRLOCK" lock-uki /dev/full)
+(! "$SD_PCRLOCK" lock-uki /bin/true)
+(! "$SD_PCRLOCK" lock-file-system "")
+
+rm "$img" /tmp/pcrlockpwd