mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #29710 from mrc0mmand/test-pcrextend
test: TEST-70-TPM2 shenagians
This commit is contained in:
@@ -32,7 +32,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
printf("%1$s [OPTIONS...] COMMAND\n"
|
||||
printf("%1$s [OPTIONS...]\n"
|
||||
"\n%5$sSet up the TPM2 Storage Root Key (SRK).%6$s\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" -h --help Show this help\n"
|
||||
@@ -63,6 +63,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
|
||||
{ "early", required_argument, NULL, ARG_EARLY },
|
||||
{}
|
||||
};
|
||||
|
||||
int c, r;
|
||||
|
||||
@@ -169,6 +169,7 @@ BASICTOOLS=(
|
||||
echo
|
||||
env
|
||||
false
|
||||
findmnt
|
||||
flock
|
||||
getconf
|
||||
getent
|
||||
@@ -188,6 +189,7 @@ BASICTOOLS=(
|
||||
login
|
||||
losetup
|
||||
lsattr
|
||||
lsblk
|
||||
lz4cat
|
||||
mkfifo
|
||||
mknod
|
||||
|
||||
16
test/units/testsuite-70.creds.sh
Executable file
16
test/units/testsuite-70.creds.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
export SYSTEMD_LOG_LEVEL=debug
|
||||
|
||||
# Ensure that sandboxing doesn't stop creds from being accessible
|
||||
echo "test" > /tmp/testdata
|
||||
systemd-creds encrypt /tmp/testdata /tmp/testdata.encrypted --with-key=tpm2
|
||||
# LoadCredentialEncrypted
|
||||
systemd-run -p PrivateDevices=yes -p LoadCredentialEncrypted=testdata.encrypted:/tmp/testdata.encrypted --pipe --wait systemd-creds cat testdata.encrypted | cmp - /tmp/testdata
|
||||
# SetCredentialEncrypted
|
||||
systemd-run -p PrivateDevices=yes -p SetCredentialEncrypted=testdata.encrypted:"$(cat /tmp/testdata.encrypted)" --pipe --wait systemd-creds cat testdata.encrypted | cmp - /tmp/testdata
|
||||
|
||||
rm -f /tmp/testdata
|
||||
84
test/units/testsuite-70.cryptenroll.sh
Executable file
84
test/units/testsuite-70.cryptenroll.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
cryptenroll_wipe_and_check() {(
|
||||
set +o pipefail
|
||||
|
||||
: >/tmp/cryptenroll.out
|
||||
systemd-cryptenroll "$@" |& tee /tmp/cryptenroll.out
|
||||
grep -qE "Wiped slot [[:digit:]]+" /tmp/cryptenroll.out
|
||||
)}
|
||||
|
||||
# There is an external issue with libcryptsetup on ppc64 that hits 95% of Ubuntu ppc64 test runs, so skip it
|
||||
if [[ "$(uname -m)" == "ppc64le" ]]; then
|
||||
echo "Skipping systemd-cryptenroll tests on ppc64le, see https://github.com/systemd/systemd/issues/27716"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
export SYSTEMD_LOG_LEVEL=debug
|
||||
IMAGE="$(mktemp /tmp/systemd-cryptenroll-XXX.image)"
|
||||
|
||||
truncate -s 20M "$IMAGE"
|
||||
echo -n password >/tmp/password
|
||||
# Change file mode to avoid "/tmp/password has 0644 mode that is too permissive" messages
|
||||
chmod 0600 /tmp/password
|
||||
cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$IMAGE" /tmp/password
|
||||
|
||||
# Enroll additional tokens, keys, and passwords to exercise the list and wipe stuff
|
||||
systemd-cryptenroll --unlock-key-file=/tmp/password --tpm2-device=auto "$IMAGE"
|
||||
NEWPASSWORD="" systemd-cryptenroll --unlock-key-file=/tmp/password --password "$IMAGE"
|
||||
NEWPASSWORD=foo systemd-cryptenroll --unlock-key-file=/tmp/password --password "$IMAGE"
|
||||
for _ in {0..9}; do
|
||||
systemd-cryptenroll --unlock-key-file=/tmp/password --recovery-key "$IMAGE"
|
||||
done
|
||||
PASSWORD="" NEWPIN=123456 systemd-cryptenroll --tpm2-device=auto --tpm2-with-pin=true "$IMAGE"
|
||||
# Do some basic checks before we start wiping stuff
|
||||
systemd-cryptenroll "$IMAGE"
|
||||
systemd-cryptenroll "$IMAGE" | grep password
|
||||
systemd-cryptenroll "$IMAGE" | grep recovery
|
||||
# Let's start wiping
|
||||
cryptenroll_wipe_and_check "$IMAGE" --wipe=empty
|
||||
(! cryptenroll_wipe_and_check "$IMAGE" --wipe=empty)
|
||||
cryptenroll_wipe_and_check "$IMAGE" --wipe=empty,0
|
||||
PASSWORD=foo NEWPASSWORD=foo cryptenroll_wipe_and_check "$IMAGE" --wipe=0,0,empty,0,pkcs11,fido2,000,recovery,password --password
|
||||
systemd-cryptenroll "$IMAGE" | grep password
|
||||
(! systemd-cryptenroll "$IMAGE" | grep recovery)
|
||||
# We shouldn't be able to wipe all keyslots without enrolling a new key first
|
||||
(! systemd-cryptenroll "$IMAGE" --wipe=all)
|
||||
PASSWORD=foo NEWPASSWORD=foo cryptenroll_wipe_and_check "$IMAGE" --password --wipe=all
|
||||
# Check if the newly (and only) enrolled password works
|
||||
(! systemd-cryptenroll --unlock-key-file=/tmp/password --recovery-key "$IMAGE")
|
||||
(! PASSWORD="" systemd-cryptenroll --recovery-key "$IMAGE")
|
||||
PASSWORD=foo systemd-cryptenroll --recovery-key "$IMAGE"
|
||||
|
||||
systemd-cryptenroll --fido2-with-client-pin=false "$IMAGE"
|
||||
systemd-cryptenroll --fido2-with-user-presence=false "$IMAGE"
|
||||
systemd-cryptenroll --fido2-with-user-verification=false "$IMAGE"
|
||||
systemd-cryptenroll --tpm2-pcrs=8 "$IMAGE"
|
||||
systemd-cryptenroll --tpm2-pcrs=boot-loader-code+boot-loader-config "$IMAGE"
|
||||
|
||||
(! systemd-cryptenroll --fido2-with-client-pin=false)
|
||||
(! systemd-cryptenroll --fido2-with-user-presence=f "$IMAGE" /tmp/foo)
|
||||
(! systemd-cryptenroll --fido2-with-client-pin=1234 "$IMAGE")
|
||||
(! systemd-cryptenroll --fido2-with-user-presence=1234 "$IMAGE")
|
||||
(! systemd-cryptenroll --fido2-with-user-verification=1234 "$IMAGE")
|
||||
(! systemd-cryptenroll --tpm2-with-pin=1234 "$IMAGE")
|
||||
(! systemd-cryptenroll --recovery-key --password "$IMAGE")
|
||||
(! systemd-cryptenroll --password --recovery-key "$IMAGE")
|
||||
(! systemd-cryptenroll --password --fido2-device=auto "$IMAGE")
|
||||
(! systemd-cryptenroll --password --pkcs11-token-uri=auto "$IMAGE")
|
||||
(! systemd-cryptenroll --password --tpm2-device=auto "$IMAGE")
|
||||
(! systemd-cryptenroll --unlock-fido2-device=auto --unlock-fido2-device=auto "$IMAGE")
|
||||
(! systemd-cryptenroll --unlock-fido2-device=auto --unlock-key-file=/tmp/unlock "$IMAGE")
|
||||
(! systemd-cryptenroll --fido2-credential-algorithm=es512 "$IMAGE")
|
||||
(! systemd-cryptenroll --tpm2-public-key-pcrs=key "$IMAGE")
|
||||
(! systemd-cryptenroll --tpm2-pcrs=key "$IMAGE")
|
||||
(! systemd-cryptenroll --tpm2-pcrs=44+8 "$IMAGE")
|
||||
(! systemd-cryptenroll --tpm2-pcrs=hello "$IMAGE")
|
||||
(! systemd-cryptenroll --wipe-slot "$IMAGE")
|
||||
(! systemd-cryptenroll --wipe-slot=10240000 "$IMAGE")
|
||||
(! systemd-cryptenroll --fido2-device=auto --unlock-fido2-device=auto "$IMAGE")
|
||||
|
||||
rm -f "$IMAGE"
|
||||
184
test/units/testsuite-70.cryptsetup.sh
Executable file
184
test/units/testsuite-70.cryptsetup.sh
Executable file
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
set -ex
|
||||
set -o pipefail
|
||||
|
||||
# shellcheck source=test/units/util.sh
|
||||
. "$(dirname "$0")"/util.sh
|
||||
|
||||
export SYSTEMD_LOG_LEVEL=debug
|
||||
|
||||
cryptsetup_has_token_plugin_support() {
|
||||
local plugin_path
|
||||
|
||||
plugin_path="$(cryptsetup --help | sed -nr 's/.*LUKS2 external token plugin path: (.*)\./\1/p')/libcryptsetup-token-systemd-tpm2.so)"
|
||||
cryptsetup --help | grep -q 'LUKS2 external token plugin support is compiled-in' && [[ -f "$plugin_path" ]]
|
||||
}
|
||||
|
||||
tpm_check_failure_with_wrong_pin() {
|
||||
local testIMAGE="${1:?}"
|
||||
local badpin="${2:?}"
|
||||
local goodpin="${3:?}"
|
||||
|
||||
# We need to be careful not to trigger DA lockout; allow 2 failures
|
||||
tpm2_dictionarylockout -s -n 2
|
||||
(! PIN=$badpin systemd-cryptsetup attach test-volume "$testIMAGE" - tpm2-device=auto,headless=1)
|
||||
# Verify the correct PIN works, to be sure the failure wasn't a DA lockout
|
||||
PIN=$goodpin systemd-cryptsetup attach test-volume "$testIMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
# Clear/reset the DA lockout counter
|
||||
tpm2_dictionarylockout -c
|
||||
}
|
||||
|
||||
at_exit() {
|
||||
# Evict the TPM primary key that we persisted
|
||||
if [[ -n "${PERSISTENT_HANDLE:-}" ]]; then
|
||||
tpm2_evictcontrol -c "$PERSISTENT_HANDLE"
|
||||
fi
|
||||
}
|
||||
|
||||
trap at_exit EXIT
|
||||
|
||||
# Prepare a fresh disk image
|
||||
IMAGE="$(mktemp /tmp/systemd-cryptsetup-XXX.IMAGE)"
|
||||
|
||||
truncate -s 20M "$IMAGE"
|
||||
echo -n passphrase >/tmp/passphrase
|
||||
# Change file mode to avoid "/tmp/passphrase has 0644 mode that is too permissive" messages
|
||||
chmod 0600 /tmp/passphrase
|
||||
cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$IMAGE" /tmp/passphrase
|
||||
|
||||
# Unlocking via keyfile
|
||||
systemd-cryptenroll --unlock-key-file=/tmp/passphrase --tpm2-device=auto "$IMAGE"
|
||||
|
||||
# Enroll unlock with default PCR policy
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto "$IMAGE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Check with wrong PCR
|
||||
tpm2_pcrextend 7:sha256=0000000000000000000000000000000000000000000000000000000000000000
|
||||
(! systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1)
|
||||
|
||||
# Enroll unlock with PCR+PIN policy
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
PASSWORD=passphrase NEWPIN=123456 systemd-cryptenroll --tpm2-device=auto --tpm2-with-pin=true "$IMAGE"
|
||||
PIN=123456 systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Check failure with wrong PIN; try a few times to make sure we avoid DA lockout
|
||||
for _ in {0..3}; do
|
||||
tpm_check_failure_with_wrong_pin "$IMAGE" 123457 123456
|
||||
done
|
||||
|
||||
# Check LUKS2 token plugin unlock (i.e. without specifying tpm2-device=auto)
|
||||
if cryptsetup_has_token_plugin_support; then
|
||||
PIN=123456 systemd-cryptsetup attach test-volume "$IMAGE" - headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Check failure with wrong PIN
|
||||
for _ in {0..3}; do
|
||||
tpm_check_failure_with_wrong_pin "$IMAGE" 123457 123456
|
||||
done
|
||||
else
|
||||
echo 'cryptsetup has no LUKS2 token plugin support, skipping'
|
||||
fi
|
||||
|
||||
# Check failure with wrong PCR (and correct PIN)
|
||||
tpm2_pcrextend 7:sha256=0000000000000000000000000000000000000000000000000000000000000000
|
||||
(! PIN=123456 systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1)
|
||||
|
||||
# Enroll unlock with PCR 0+7
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 "$IMAGE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Check with wrong PCR 0
|
||||
tpm2_pcrextend 0:sha256=0000000000000000000000000000000000000000000000000000000000000000
|
||||
(! systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1)
|
||||
|
||||
if tpm_has_pcr sha256 12; then
|
||||
# Enroll using an explicit PCR value (that does match current PCR value)
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
EXPECTED_PCR_VALUE=$(cat /sys/class/tpm/tpm0/pcr-sha256/12)
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="12:sha256=$EXPECTED_PCR_VALUE" "$IMAGE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Same as above plus more PCRs without the value or alg specified
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
EXPECTED_PCR_VALUE=$(cat /sys/class/tpm/tpm0/pcr-sha256/12)
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="1,12:sha256=$EXPECTED_PCR_VALUE,3" "$IMAGE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Same as above plus more PCRs with hash alg specified but hash value not specified
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
EXPECTED_PCR_VALUE=$(cat /sys/class/tpm/tpm0/pcr-sha256/12)
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="1:sha256,12:sha256=$EXPECTED_PCR_VALUE,3" "$IMAGE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Now the interesting part, enrolling using a hash value that doesn't match the current PCR value
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
tpm2_pcrread -Q -o /tmp/pcr.dat sha256:12
|
||||
CURRENT_PCR_VALUE=$(cat /sys/class/tpm/tpm0/pcr-sha256/12)
|
||||
EXPECTED_PCR_VALUE=$(cat /tmp/pcr.dat /tmp/pcr.dat | openssl dgst -sha256 -r | cut -d ' ' -f 1)
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="12:sha256=$EXPECTED_PCR_VALUE" "$IMAGE"
|
||||
(! systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1)
|
||||
tpm2_pcrextend "12:sha256=$CURRENT_PCR_VALUE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
rm -f /tmp/pcr.dat
|
||||
fi
|
||||
|
||||
# Use default (0) seal key handle
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0 "$IMAGE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x0 "$IMAGE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Use SRK seal key handle
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=81000001 "$IMAGE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x81000001 "$IMAGE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Test invalid ranges: pcr, nv, session, permanent
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
(! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=7 "$IMAGE") # PCR
|
||||
(! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x01000001 "$IMAGE") # NV index
|
||||
(! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x02000001 "$IMAGE") # HMAC/loaded session
|
||||
(! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x03000001 "$IMAGE") # Policy/saved session
|
||||
(! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x40000001 "$IMAGE") # Permanent
|
||||
|
||||
# Use non-SRK persistent seal key handle (by creating/persisting new key)
|
||||
PRIMARY=/tmp/primary.ctx
|
||||
tpm2_createprimary -c "$PRIMARY"
|
||||
PERSISTENT_LINE=$(tpm2_evictcontrol -c "$PRIMARY" | grep persistent-handle)
|
||||
PERSISTENT="0x${PERSISTENT_LINE##*0x}"
|
||||
tpm2_flushcontext -t
|
||||
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle="${PERSISTENT#0x}" "$IMAGE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle="$PERSISTENT" "$IMAGE"
|
||||
systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
rm -f "$IMAGE" "$PRIMARY"
|
||||
130
test/units/testsuite-70.measure.sh
Executable file
130
test/units/testsuite-70.measure.sh
Executable file
@@ -0,0 +1,130 @@
|
||||
#!/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
|
||||
SD_MEASURE="/usr/lib/systemd/systemd-measure"
|
||||
|
||||
if [[ ! -x "${SD_MEASURE:?}" ]]; then
|
||||
echo "$SD_MEASURE not found, skipping the test"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
IMAGE="$(mktemp /tmp/systemd-measure-XXX.image)"
|
||||
|
||||
echo HALLO >/tmp/tpmdata1
|
||||
echo foobar >/tmp/tpmdata2
|
||||
|
||||
cat >/tmp/result <<EOF
|
||||
11:sha1=5177e4ad69db92192c10e5f80402bf81bfec8a81
|
||||
11:sha256=37b48bd0b222394dbe3cceff2fca4660c4b0a90ae9369ec90b42f14489989c13
|
||||
11:sha384=5573f9b2caf55b1d0a6a701f890662d682af961899f0419cf1e2d5ea4a6a68c1f25bd4f5b8a0865eeee82af90f5cb087
|
||||
11:sha512=961305d7e9981d6606d1ce97b3a9a1f92610cac033e9c39064895f0e306abc1680463d55767bd98e751eae115bdef3675a9ee1d29ed37da7885b1db45bb2555b
|
||||
EOF
|
||||
"$SD_MEASURE" calculate --linux=/tmp/tpmdata1 --initrd=/tmp/tpmdata2 --bank=sha1 --bank=sha256 --bank=sha384 --bank=sha512 --phase=: | cmp - /tmp/result
|
||||
|
||||
cat >/tmp/result.json <<EOF
|
||||
{"sha1":[{"pcr":11,"hash":"5177e4ad69db92192c10e5f80402bf81bfec8a81"}],"sha256":[{"pcr":11,"hash":"37b48bd0b222394dbe3cceff2fca4660c4b0a90ae9369ec90b42f14489989c13"}],"sha384":[{"pcr":11,"hash":"5573f9b2caf55b1d0a6a701f890662d682af961899f0419cf1e2d5ea4a6a68c1f25bd4f5b8a0865eeee82af90f5cb087"}],"sha512":[{"pcr":11,"hash":"961305d7e9981d6606d1ce97b3a9a1f92610cac033e9c39064895f0e306abc1680463d55767bd98e751eae115bdef3675a9ee1d29ed37da7885b1db45bb2555b"}]}
|
||||
EOF
|
||||
"$SD_MEASURE" calculate --linux=/tmp/tpmdata1 --initrd=/tmp/tpmdata2 --bank=sha1 --bank=sha256 --bank=sha384 --bank=sha512 --phase=: -j | diff -u - /tmp/result.json
|
||||
|
||||
cat >/tmp/result <<EOF
|
||||
11:sha1=6765ee305db063040c454d32697d922b3d4f232b
|
||||
11:sha256=21c49c1242042649e09c156546fd7d425ccc3c67359f840507b30be4e0f6f699
|
||||
11:sha384=08d0b003a134878eee552070d51d58abe942f457ca85704131dd36f73728e7327ca837594bc9d5ac7de818d02a3d5dd2
|
||||
11:sha512=65120f6ebc04b156421c6f3d543b2fad545363d9ca61c514205459e9c0e0b22e09c23605eae5853e38458ef3ca54e087168af8d8a882a98d220d9391e48be6d0
|
||||
EOF
|
||||
"$SD_MEASURE" calculate --linux=/tmp/tpmdata1 --initrd=/tmp/tpmdata2 --bank=sha1 --bank=sha256 --bank=sha384 --bank=sha512 --phase=foo | cmp - /tmp/result
|
||||
|
||||
cat >/tmp/result.json <<EOF
|
||||
{"sha1":[{"phase":"foo","pcr":11,"hash":"6765ee305db063040c454d32697d922b3d4f232b"}],"sha256":[{"phase":"foo","pcr":11,"hash":"21c49c1242042649e09c156546fd7d425ccc3c67359f840507b30be4e0f6f699"}],"sha384":[{"phase":"foo","pcr":11,"hash":"08d0b003a134878eee552070d51d58abe942f457ca85704131dd36f73728e7327ca837594bc9d5ac7de818d02a3d5dd2"}],"sha512":[{"phase":"foo","pcr":11,"hash":"65120f6ebc04b156421c6f3d543b2fad545363d9ca61c514205459e9c0e0b22e09c23605eae5853e38458ef3ca54e087168af8d8a882a98d220d9391e48be6d0"}]}
|
||||
EOF
|
||||
"$SD_MEASURE" calculate --linux=/tmp/tpmdata1 --initrd=/tmp/tpmdata2 --bank=sha1 --bank=sha256 --bank=sha384 --bank=sha512 --phase=foo -j | diff -u - /tmp/result.json
|
||||
|
||||
rm /tmp/result /tmp/result.json
|
||||
|
||||
if ! tpm_has_pcr sha1 11 || ! tpm_has_pcr sha256 11; then
|
||||
echo "PCR sysfs files not found, skipping signed PCR policy tests"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Generate key pair
|
||||
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out "/tmp/pcrsign-private.pem"
|
||||
openssl rsa -pubout -in "/tmp/pcrsign-private.pem" -out "/tmp/pcrsign-public.pem"
|
||||
|
||||
MEASURE_BANKS=("--bank=sha256")
|
||||
# Check if SHA1 signatures are supported
|
||||
#
|
||||
# Some distros have started phasing out SHA1, so make sure the SHA1
|
||||
# signatures are supported before trying to use them.
|
||||
if echo hello | openssl dgst -sign /tmp/pcrsign-private.pem -sha1 >/dev/null; then
|
||||
MEASURE_BANKS+=("--bank=sha1")
|
||||
fi
|
||||
|
||||
# Sign current PCR state with it
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: | tee "/tmp/pcrsign.sig"
|
||||
dd if=/dev/urandom of=/tmp/pcrtestdata bs=1024 count=64
|
||||
systemd-creds encrypt /tmp/pcrtestdata /tmp/pcrtestdata.encrypted --with-key=host+tpm2-with-public-key --tpm2-public-key="/tmp/pcrsign-public.pem"
|
||||
systemd-creds decrypt /tmp/pcrtestdata.encrypted - --tpm2-signature="/tmp/pcrsign.sig" | cmp - /tmp/pcrtestdata
|
||||
|
||||
# Invalidate PCR, decrypting should fail now
|
||||
tpm2_pcrextend 11:sha256=0000000000000000000000000000000000000000000000000000000000000000
|
||||
(! systemd-creds decrypt /tmp/pcrtestdata.encrypted - --tpm2-signature="/tmp/pcrsign.sig" >/dev/null)
|
||||
|
||||
# Sign new PCR state, decrypting should work now.
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: >"/tmp/pcrsign.sig2"
|
||||
systemd-creds decrypt /tmp/pcrtestdata.encrypted - --tpm2-signature="/tmp/pcrsign.sig2" | cmp - /tmp/pcrtestdata
|
||||
|
||||
# Now, do the same, but with a cryptsetup binding
|
||||
truncate -s 20M "$IMAGE"
|
||||
cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$IMAGE" /tmp/passphrase
|
||||
# Ensure that an unrelated signature, when not requested, is not used
|
||||
touch /run/systemd/tpm2-pcr-signature.json
|
||||
systemd-cryptenroll --unlock-key-file=/tmp/passphrase --tpm2-device=auto --tpm2-public-key="/tmp/pcrsign-public.pem" "$IMAGE"
|
||||
# Reset and use the signature now
|
||||
rm -f /run/systemd/tpm2-pcr-signature.json
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE"
|
||||
systemd-cryptenroll --unlock-key-file=/tmp/passphrase --tpm2-device=auto --tpm2-public-key="/tmp/pcrsign-public.pem" --tpm2-signature="/tmp/pcrsign.sig2" "$IMAGE"
|
||||
|
||||
# Check if we can activate that (without the token module stuff)
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup detach test-volume2
|
||||
|
||||
# Check if we can activate that (and a second time with the token module stuff enabled)
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup detach test-volume2
|
||||
|
||||
# After extending the PCR things should fail
|
||||
tpm2_pcrextend 11:sha256=0000000000000000000000000000000000000000000000000000000000000000
|
||||
(! SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1)
|
||||
(! SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1)
|
||||
|
||||
# But once we sign the current PCRs, we should be able to unlock again
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: >"/tmp/pcrsign.sig3"
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig3",headless=1
|
||||
systemd-cryptsetup detach test-volume2
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig3",headless=1
|
||||
systemd-cryptsetup detach test-volume2
|
||||
|
||||
# Test --append mode and de-duplication. With the same parameters signing should not add a new entry
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: --append="/tmp/pcrsign.sig3" >"/tmp/pcrsign.sig4"
|
||||
cmp "/tmp/pcrsign.sig3" "/tmp/pcrsign.sig4"
|
||||
|
||||
# Sign one more phase, this should
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=quux:waldo --append="/tmp/pcrsign.sig4" >"/tmp/pcrsign.sig5"
|
||||
(! cmp "/tmp/pcrsign.sig4" "/tmp/pcrsign.sig5")
|
||||
|
||||
# Should still be good to unlock, given the old entry still exists
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig5",headless=1
|
||||
systemd-cryptsetup detach test-volume2
|
||||
|
||||
# Adding both signatures once more should not change anything, due to the deduplication
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: --append="/tmp/pcrsign.sig5" >"/tmp/pcrsign.sig6"
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=quux:waldo --append="/tmp/pcrsign.sig6" >"/tmp/pcrsign.sig7"
|
||||
cmp "/tmp/pcrsign.sig5" "/tmp/pcrsign.sig7"
|
||||
|
||||
rm -f "$IMAGE"
|
||||
124
test/units/testsuite-70.pcrextend.sh
Executable file
124
test/units/testsuite-70.pcrextend.sh
Executable file
@@ -0,0 +1,124 @@
|
||||
#!/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
|
||||
SD_PCREXTEND="/usr/lib/systemd/systemd-pcrextend"
|
||||
|
||||
if [[ ! -x "${SD_PCREXTEND:?}" ]] || ! tpm_has_pcr sha256 11 || ! tpm_has_pcr sha256 15; then
|
||||
echo "$SD_PCREXTEND or PCR sysfs files not found, skipping PCR extension tests"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
at_exit() {
|
||||
if [[ $? -ne 0 ]]; then
|
||||
# Dump the event log on fail, to make debugging a bit easier
|
||||
jq --seq --slurp </run/log/systemd/tpm2-measure.log
|
||||
fi
|
||||
}
|
||||
|
||||
trap at_exit EXIT
|
||||
|
||||
# Temporarily override sd-pcrextend's sanity checks
|
||||
export SYSTEMD_FORCE_MEASURE=1
|
||||
|
||||
"$SD_PCREXTEND" --help
|
||||
"$SD_PCREXTEND" --version
|
||||
"$SD_PCREXTEND" foo
|
||||
"$SD_PCREXTEND" --machine-id
|
||||
"$SD_PCREXTEND" --tpm2-device=list
|
||||
"$SD_PCREXTEND" --tpm2-device=auto foo
|
||||
"$SD_PCREXTEND" --tpm2-device=/dev/tpm0 foo
|
||||
"$SD_PCREXTEND" --bank=sha256 foo
|
||||
"$SD_PCREXTEND" --bank=sha256 --bank=sha256 foo
|
||||
"$SD_PCREXTEND" --graceful foo
|
||||
"$SD_PCREXTEND" --pcr=15 foo
|
||||
"$SD_PCREXTEND" --file-system=/
|
||||
"$SD_PCREXTEND" --file-system=/tmp --file-system=/
|
||||
"$SD_PCREXTEND" --file-system=/tmp --file-system=/ --pcr=15 --pcr=11
|
||||
|
||||
if tpm_has_pcr sha1 11; then
|
||||
"$SD_PCREXTEND" --bank=sha1 --pcr=11 foo
|
||||
fi
|
||||
|
||||
(! "$SD_PCREXTEND")
|
||||
(! "$SD_PCREXTEND" "")
|
||||
(! "$SD_PCREXTEND" foo bar)
|
||||
(! "$SD_PCREXTEND" --bank= foo)
|
||||
(! "$SD_PCREXTEND" --tpm2-device= foo)
|
||||
(! "$SD_PCREXTEND" --tpm2-device=/dev/null foo)
|
||||
(! "$SD_PCREXTEND" --pcr= foo)
|
||||
(! "$SD_PCREXTEND" --pcr=-1 foo)
|
||||
(! "$SD_PCREXTEND" --pcr=1024 foo)
|
||||
(! "$SD_PCREXTEND" --foo=bar)
|
||||
|
||||
unset SYSTEMD_FORCE_MEASURE
|
||||
|
||||
# Note: since we're reading the TPM event log as json-seq, the same rules apply to the output
|
||||
# as well, i.e. each record is prefixed by RS (0x1E, 036) and suffixed by LF (0x0A, 012).
|
||||
# LF is usually eaten by bash, but RS needs special handling.
|
||||
|
||||
# Save the number of events in the current event log, so we can skip them when
|
||||
# checking changes caused by following tests
|
||||
RECORD_COUNT="$(jq --seq --slurp '. | length' </run/log/systemd/tpm2-measure.log | tr -d '\036')"
|
||||
|
||||
# Let's measure the machine ID
|
||||
tpm2_pcrread sha256:15 -Q -o /tmp/oldpcr15
|
||||
mv /etc/machine-id /etc/machine-id.save
|
||||
echo 994013bf23864ee7992eab39a96dd3bb >/etc/machine-id
|
||||
SYSTEMD_FORCE_MEASURE=1 "$SD_PCREXTEND" --machine-id
|
||||
mv /etc/machine-id.save /etc/machine-id
|
||||
tpm2_pcrread sha256:15 -Q -o /tmp/newpcr15
|
||||
|
||||
# And check it matches expectations
|
||||
diff /tmp/newpcr15 \
|
||||
<(cat /tmp/oldpcr15 <(echo -n "machine-id:994013bf23864ee7992eab39a96dd3bb" | openssl dgst -binary -sha256) | openssl dgst -binary -sha256)
|
||||
|
||||
# Check that the event log record was properly written
|
||||
test "$(jq --seq --slurp ".[$RECORD_COUNT].pcr" </run/log/systemd/tpm2-measure.log)" == "$(printf '\x1e15')"
|
||||
DIGEST_EXPECTED="$(echo -n "machine-id:994013bf23864ee7992eab39a96dd3bb" | openssl dgst -hex -sha256 -r)"
|
||||
DIGEST_CURRENT="$(jq --seq --slurp --raw-output ".[$RECORD_COUNT].digests[] | select(.hashAlg == \"sha256\").digest" </run/log/systemd/tpm2-measure.log) *stdin"
|
||||
test "$DIGEST_EXPECTED" == "$DIGEST_CURRENT"
|
||||
|
||||
RECORD_COUNT=$((RECORD_COUNT + 1))
|
||||
# And similar for the boot phase measurement into PCR 11
|
||||
tpm2_pcrread sha256:11 -Q -o /tmp/oldpcr11
|
||||
# Do the equivalent of 'SYSTEMD_FORCE_MEASURE=1 "$SD_PCREXTEND" foobar' via Varlink, just to test the Varlink logic (but first we need to patch out the conditionalization...)
|
||||
mkdir -p /run/systemd/system/systemd-pcrextend.socket.d
|
||||
cat > /run/systemd/system/systemd-pcrextend.socket.d/50-no-condition.conf <<EOF
|
||||
[Unit]
|
||||
# Turn off all conditions */
|
||||
ConditionSecurity=
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl restart systemd-pcrextend.socket
|
||||
varlinkctl call /run/systemd/io.systemd.PCRExtend io.systemd.PCRExtend.Extend '{"pcr":11,"text":"foobar"}'
|
||||
tpm2_pcrread sha256:11 -Q -o /tmp/newpcr11
|
||||
|
||||
diff /tmp/newpcr11 \
|
||||
<(cat /tmp/oldpcr11 <(echo -n "foobar" | openssl dgst -binary -sha256) | openssl dgst -binary -sha256)
|
||||
|
||||
# Check the event log for the 2nd new record since $RECORD_COUNT
|
||||
test "$(jq --seq --slurp ".[$RECORD_COUNT].pcr" </run/log/systemd/tpm2-measure.log)" == "$(printf '\x1e11')"
|
||||
DIGEST_EXPECTED="$(echo -n "foobar" | openssl dgst -hex -sha256 -r)"
|
||||
DIGEST_CURRENT="$(jq --seq --slurp --raw-output ".[$RECORD_COUNT].digests[] | select(.hashAlg == \"sha256\").digest" </run/log/systemd/tpm2-measure.log) *stdin"
|
||||
test "$DIGEST_EXPECTED" == "$DIGEST_CURRENT"
|
||||
|
||||
# Measure a file system into PCR 15
|
||||
tpm2_pcrread sha256:15 -Q -o /tmp/oldpcr15
|
||||
SYSTEMD_FORCE_MEASURE=1 "$SD_PCREXTEND" --file-system=/
|
||||
# Put together the "file system word" we just sent to the TPM
|
||||
# file-system:MOUNTPOINT:TYPE:UUID:LABEL:PART_ENTRY_UUID:PART_ENTRY_TYPE:PART_ENTRY_NAME
|
||||
ROOT_DEVICE="$(findmnt -n -o SOURCE /)"
|
||||
FS_WORD="$(lsblk -n -o MOUNTPOINT,FSTYPE,UUID,LABEL,PARTUUID,PARTTYPE,PARTLABEL "$ROOT_DEVICE" | sed -r 's/[ ]+/:/g')"
|
||||
tpm2_pcrread sha256:15 -Q -o /tmp/newpcr15
|
||||
|
||||
# And check if it matches with the current PCR 15 state
|
||||
diff /tmp/newpcr15 \
|
||||
<(cat /tmp/oldpcr15 <(echo -n "file-system:$FS_WORD" | openssl dgst -binary -sha256) | openssl dgst -binary -sha256)
|
||||
|
||||
rm -f /tmp/oldpcr{11,15} /tmp/newpcr{11,15}
|
||||
@@ -1,455 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
set -ex
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
SD_MEASURE="/usr/lib/systemd/systemd-measure"
|
||||
SD_PCREXTEND="/usr/lib/systemd/systemd-pcrextend"
|
||||
SD_TPM2SETUP="/usr/lib/systemd/systemd-tpm2-setup"
|
||||
export SYSTEMD_LOG_LEVEL=debug
|
||||
# shellcheck source=test/units/test-control.sh
|
||||
. "$(dirname "$0")"/test-control.sh
|
||||
|
||||
trap cleanup ERR
|
||||
cleanup() {
|
||||
# Evict the TPM primary key that we persisted
|
||||
if [[ -n $persistent ]]; then
|
||||
tpm2_evictcontrol -c "$persistent"
|
||||
fi
|
||||
}
|
||||
persistent=""
|
||||
|
||||
cryptsetup_has_token_plugin_support() {
|
||||
local plugin_path
|
||||
|
||||
plugin_path="$(cryptsetup --help | sed -nr 's/.*LUKS2 external token plugin path: (.*)\./\1/p')/libcryptsetup-token-systemd-tpm2.so)"
|
||||
cryptsetup --help | grep -q 'LUKS2 external token plugin support is compiled-in' && [[ -f "$plugin_path" ]]
|
||||
}
|
||||
|
||||
tpm_has_pcr() {
|
||||
local algorithm="${1:?}"
|
||||
local pcr="${2:?}"
|
||||
|
||||
[[ -f "/sys/class/tpm/tpm0/pcr-$algorithm/$pcr" ]]
|
||||
}
|
||||
|
||||
tpm_check_failure_with_wrong_pin() {
|
||||
local testimg="${1:?}"
|
||||
local badpin="${2:?}"
|
||||
local goodpin="${3:?}"
|
||||
|
||||
# We need to be careful not to trigger DA lockout; allow 2 failures
|
||||
tpm2_dictionarylockout -s -n 2
|
||||
(! PIN=$badpin systemd-cryptsetup attach test-volume "$testimg" - tpm2-device=auto,headless=1)
|
||||
# Verify the correct PIN works, to be sure the failure wasn't a DA lockout
|
||||
PIN=$goodpin systemd-cryptsetup attach test-volume "$testimg" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
# Clear/reset the DA lockout counter
|
||||
tpm2_dictionarylockout -c
|
||||
}
|
||||
|
||||
# Prepare a fresh disk image
|
||||
img="/tmp/test.img"
|
||||
truncate -s 20M "$img"
|
||||
echo -n passphrase >/tmp/passphrase
|
||||
# Change file mode to avoid "/tmp/passphrase has 0644 mode that is too permissive" messages
|
||||
chmod 0600 /tmp/passphrase
|
||||
cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$img" /tmp/passphrase
|
||||
|
||||
# Unlocking via keyfile
|
||||
systemd-cryptenroll --unlock-key-file=/tmp/passphrase --tpm2-device=auto "$img"
|
||||
|
||||
# Enroll unlock with default PCR policy
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto "$img"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Check with wrong PCR
|
||||
tpm2_pcrextend 7:sha256=0000000000000000000000000000000000000000000000000000000000000000
|
||||
(! systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1)
|
||||
|
||||
# Enroll unlock with PCR+PIN policy
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
PASSWORD=passphrase NEWPIN=123456 systemd-cryptenroll --tpm2-device=auto --tpm2-with-pin=true "$img"
|
||||
PIN=123456 systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Check failure with wrong PIN; try a few times to make sure we avoid DA lockout
|
||||
for _ in {0..3}; do
|
||||
tpm_check_failure_with_wrong_pin "$img" 123457 123456
|
||||
done
|
||||
|
||||
# Check LUKS2 token plugin unlock (i.e. without specifying tpm2-device=auto)
|
||||
if cryptsetup_has_token_plugin_support; then
|
||||
PIN=123456 systemd-cryptsetup attach test-volume "$img" - headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Check failure with wrong PIN
|
||||
for _ in {0..3}; do
|
||||
tpm_check_failure_with_wrong_pin "$img" 123457 123456
|
||||
done
|
||||
else
|
||||
echo 'cryptsetup has no LUKS2 token plugin support, skipping'
|
||||
fi
|
||||
|
||||
# Check failure with wrong PCR (and correct PIN)
|
||||
tpm2_pcrextend 7:sha256=0000000000000000000000000000000000000000000000000000000000000000
|
||||
(! PIN=123456 systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1)
|
||||
|
||||
# Enroll unlock with PCR 0+7
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 "$img"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Check with wrong PCR 0
|
||||
tpm2_pcrextend 0:sha256=0000000000000000000000000000000000000000000000000000000000000000
|
||||
(! systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1)
|
||||
|
||||
if tpm_has_pcr sha256 12; then
|
||||
# Enroll using an explicit PCR value (that does match current PCR value)
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
EXPECTED_PCR_VALUE=$(cat /sys/class/tpm/tpm0/pcr-sha256/12)
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="12:sha256=$EXPECTED_PCR_VALUE" "$img"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Same as above plus more PCRs without the value or alg specified
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
EXPECTED_PCR_VALUE=$(cat /sys/class/tpm/tpm0/pcr-sha256/12)
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="1,12:sha256=$EXPECTED_PCR_VALUE,3" "$img"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Same as above plus more PCRs with hash alg specified but hash value not specified
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
EXPECTED_PCR_VALUE=$(cat /sys/class/tpm/tpm0/pcr-sha256/12)
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="1:sha256,12:sha256=$EXPECTED_PCR_VALUE,3" "$img"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Now the interesting part, enrolling using a hash value that doesn't match the current PCR value
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
tpm2_pcrread -Q -o /tmp/pcr.dat sha256:12
|
||||
CURRENT_PCR_VALUE=$(cat /sys/class/tpm/tpm0/pcr-sha256/12)
|
||||
EXPECTED_PCR_VALUE=$(cat /tmp/pcr.dat /tmp/pcr.dat | openssl dgst -sha256 -r | cut -d ' ' -f 1)
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="12:sha256=$EXPECTED_PCR_VALUE" "$img"
|
||||
(! systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1)
|
||||
tpm2_pcrextend "12:sha256=$CURRENT_PCR_VALUE"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
rm -f /tmp/pcr.dat
|
||||
fi
|
||||
|
||||
# Use default (0) seal key handle
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0 "$img"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x0 "$img"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Use SRK seal key handle
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=81000001 "$img"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x81000001 "$img"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
# Test invalid ranges: pcr, nv, session, permanent
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
(! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=7 "$img") # PCR
|
||||
(! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x01000001 "$img") # NV index
|
||||
(! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x02000001 "$img") # HMAC/loaded session
|
||||
(! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x03000001 "$img") # Policy/saved session
|
||||
(! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x40000001 "$img") # Permanent
|
||||
|
||||
# Use non-SRK persistent seal key handle (by creating/persisting new key)
|
||||
primary=/tmp/primary.ctx
|
||||
tpm2_createprimary -c "$primary"
|
||||
persistent_line=$(tpm2_evictcontrol -c "$primary" | grep persistent-handle)
|
||||
persistent="0x${persistent_line##*0x}"
|
||||
tpm2_flushcontext -t
|
||||
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle="${persistent#0x}" "$img"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle="$persistent" "$img"
|
||||
systemd-cryptsetup attach test-volume "$img" - tpm2-device=auto,headless=1
|
||||
systemd-cryptsetup detach test-volume
|
||||
|
||||
tpm2_evictcontrol -c "$persistent"
|
||||
persistent=""
|
||||
rm -f "$primary"
|
||||
|
||||
rm -f "${img:?}"
|
||||
|
||||
if [[ -x "$SD_MEASURE" ]]; then
|
||||
echo HALLO >/tmp/tpmdata1
|
||||
echo foobar >/tmp/tpmdata2
|
||||
|
||||
cat >/tmp/result <<EOF
|
||||
11:sha1=5177e4ad69db92192c10e5f80402bf81bfec8a81
|
||||
11:sha256=37b48bd0b222394dbe3cceff2fca4660c4b0a90ae9369ec90b42f14489989c13
|
||||
11:sha384=5573f9b2caf55b1d0a6a701f890662d682af961899f0419cf1e2d5ea4a6a68c1f25bd4f5b8a0865eeee82af90f5cb087
|
||||
11:sha512=961305d7e9981d6606d1ce97b3a9a1f92610cac033e9c39064895f0e306abc1680463d55767bd98e751eae115bdef3675a9ee1d29ed37da7885b1db45bb2555b
|
||||
EOF
|
||||
"$SD_MEASURE" calculate --linux=/tmp/tpmdata1 --initrd=/tmp/tpmdata2 --bank=sha1 --bank=sha256 --bank=sha384 --bank=sha512 --phase=: | cmp - /tmp/result
|
||||
|
||||
cat >/tmp/result.json <<EOF
|
||||
{"sha1":[{"pcr":11,"hash":"5177e4ad69db92192c10e5f80402bf81bfec8a81"}],"sha256":[{"pcr":11,"hash":"37b48bd0b222394dbe3cceff2fca4660c4b0a90ae9369ec90b42f14489989c13"}],"sha384":[{"pcr":11,"hash":"5573f9b2caf55b1d0a6a701f890662d682af961899f0419cf1e2d5ea4a6a68c1f25bd4f5b8a0865eeee82af90f5cb087"}],"sha512":[{"pcr":11,"hash":"961305d7e9981d6606d1ce97b3a9a1f92610cac033e9c39064895f0e306abc1680463d55767bd98e751eae115bdef3675a9ee1d29ed37da7885b1db45bb2555b"}]}
|
||||
EOF
|
||||
"$SD_MEASURE" calculate --linux=/tmp/tpmdata1 --initrd=/tmp/tpmdata2 --bank=sha1 --bank=sha256 --bank=sha384 --bank=sha512 --phase=: -j | diff -u - /tmp/result.json
|
||||
|
||||
cat >/tmp/result <<EOF
|
||||
11:sha1=6765ee305db063040c454d32697d922b3d4f232b
|
||||
11:sha256=21c49c1242042649e09c156546fd7d425ccc3c67359f840507b30be4e0f6f699
|
||||
11:sha384=08d0b003a134878eee552070d51d58abe942f457ca85704131dd36f73728e7327ca837594bc9d5ac7de818d02a3d5dd2
|
||||
11:sha512=65120f6ebc04b156421c6f3d543b2fad545363d9ca61c514205459e9c0e0b22e09c23605eae5853e38458ef3ca54e087168af8d8a882a98d220d9391e48be6d0
|
||||
EOF
|
||||
"$SD_MEASURE" calculate --linux=/tmp/tpmdata1 --initrd=/tmp/tpmdata2 --bank=sha1 --bank=sha256 --bank=sha384 --bank=sha512 --phase=foo | cmp - /tmp/result
|
||||
|
||||
cat >/tmp/result.json <<EOF
|
||||
{"sha1":[{"phase":"foo","pcr":11,"hash":"6765ee305db063040c454d32697d922b3d4f232b"}],"sha256":[{"phase":"foo","pcr":11,"hash":"21c49c1242042649e09c156546fd7d425ccc3c67359f840507b30be4e0f6f699"}],"sha384":[{"phase":"foo","pcr":11,"hash":"08d0b003a134878eee552070d51d58abe942f457ca85704131dd36f73728e7327ca837594bc9d5ac7de818d02a3d5dd2"}],"sha512":[{"phase":"foo","pcr":11,"hash":"65120f6ebc04b156421c6f3d543b2fad545363d9ca61c514205459e9c0e0b22e09c23605eae5853e38458ef3ca54e087168af8d8a882a98d220d9391e48be6d0"}]}
|
||||
EOF
|
||||
"$SD_MEASURE" calculate --linux=/tmp/tpmdata1 --initrd=/tmp/tpmdata2 --bank=sha1 --bank=sha256 --bank=sha384 --bank=sha512 --phase=foo -j | diff -u - /tmp/result.json
|
||||
|
||||
rm /tmp/result /tmp/result.json
|
||||
else
|
||||
echo "$SD_MEASURE not found, skipping PCR policy test case"
|
||||
fi
|
||||
|
||||
if [[ -x "$SD_MEASURE" ]] && tpm_has_pcr sha1 11 && tpm_has_pcr sha256 11; then
|
||||
# Generate key pair
|
||||
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out "/tmp/pcrsign-private.pem"
|
||||
openssl rsa -pubout -in "/tmp/pcrsign-private.pem" -out "/tmp/pcrsign-public.pem"
|
||||
|
||||
MEASURE_BANKS=("--bank=sha256")
|
||||
# Check if SHA1 signatures are supported
|
||||
#
|
||||
# Some distros have started phasing out SHA1, so make sure the SHA1
|
||||
# signatures are supported before trying to use them.
|
||||
if echo hello | openssl dgst -sign /tmp/pcrsign-private.pem -sha1 >/dev/null; then
|
||||
MEASURE_BANKS+=("--bank=sha1")
|
||||
fi
|
||||
|
||||
# Sign current PCR state with it
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: | tee "/tmp/pcrsign.sig"
|
||||
dd if=/dev/urandom of=/tmp/pcrtestdata bs=1024 count=64
|
||||
systemd-creds encrypt /tmp/pcrtestdata /tmp/pcrtestdata.encrypted --with-key=host+tpm2-with-public-key --tpm2-public-key="/tmp/pcrsign-public.pem"
|
||||
systemd-creds decrypt /tmp/pcrtestdata.encrypted - --tpm2-signature="/tmp/pcrsign.sig" | cmp - /tmp/pcrtestdata
|
||||
|
||||
# Invalidate PCR, decrypting should fail now
|
||||
tpm2_pcrextend 11:sha256=0000000000000000000000000000000000000000000000000000000000000000
|
||||
(! systemd-creds decrypt /tmp/pcrtestdata.encrypted - --tpm2-signature="/tmp/pcrsign.sig" >/dev/null)
|
||||
|
||||
# Sign new PCR state, decrypting should work now.
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: >"/tmp/pcrsign.sig2"
|
||||
systemd-creds decrypt /tmp/pcrtestdata.encrypted - --tpm2-signature="/tmp/pcrsign.sig2" | cmp - /tmp/pcrtestdata
|
||||
|
||||
# Now, do the same, but with a cryptsetup binding
|
||||
truncate -s 20M "$img"
|
||||
cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$img" /tmp/passphrase
|
||||
# Ensure that an unrelated signature, when not requested, is not used
|
||||
touch /run/systemd/tpm2-pcr-signature.json
|
||||
systemd-cryptenroll --unlock-key-file=/tmp/passphrase --tpm2-device=auto --tpm2-public-key="/tmp/pcrsign-public.pem" "$img"
|
||||
# Reset and use the signature now
|
||||
rm -f /run/systemd/tpm2-pcr-signature.json
|
||||
systemd-cryptenroll --wipe-slot=tpm2 "$img"
|
||||
systemd-cryptenroll --unlock-key-file=/tmp/passphrase --tpm2-device=auto --tpm2-public-key="/tmp/pcrsign-public.pem" --tpm2-signature="/tmp/pcrsign.sig2" "$img"
|
||||
|
||||
# Check if we can activate that (without the token module stuff)
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$img" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup detach test-volume2
|
||||
|
||||
# Check if we can activate that (and a second time with the token module stuff enabled)
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup attach test-volume2 "$img" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup detach test-volume2
|
||||
|
||||
# After extending the PCR things should fail
|
||||
tpm2_pcrextend 11:sha256=0000000000000000000000000000000000000000000000000000000000000000
|
||||
(! SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$img" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1)
|
||||
(! SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup attach test-volume2 "$img" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1)
|
||||
|
||||
# But once we sign the current PCRs, we should be able to unlock again
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: >"/tmp/pcrsign.sig3"
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$img" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig3",headless=1
|
||||
systemd-cryptsetup detach test-volume2
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup attach test-volume2 "$img" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig3",headless=1
|
||||
systemd-cryptsetup detach test-volume2
|
||||
|
||||
# Test --append mode and de-duplication. With the same parameters signing should not add a new entry
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: --append="/tmp/pcrsign.sig3" >"/tmp/pcrsign.sig4"
|
||||
cmp "/tmp/pcrsign.sig3" "/tmp/pcrsign.sig4"
|
||||
|
||||
# Sign one more phase, this should
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=quux:waldo --append="/tmp/pcrsign.sig4" >"/tmp/pcrsign.sig5"
|
||||
(! cmp "/tmp/pcrsign.sig4" "/tmp/pcrsign.sig5")
|
||||
|
||||
# Should still be good to unlock, given the old entry still exists
|
||||
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$img" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig5",headless=1
|
||||
systemd-cryptsetup detach test-volume2
|
||||
|
||||
# Adding both signatures once more should not change anything, due to the deduplication
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: --append="/tmp/pcrsign.sig5" >"/tmp/pcrsign.sig6"
|
||||
"$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=quux:waldo --append="/tmp/pcrsign.sig6" >"/tmp/pcrsign.sig7"
|
||||
cmp "/tmp/pcrsign.sig5" "/tmp/pcrsign.sig7"
|
||||
|
||||
rm -f "$img"
|
||||
else
|
||||
echo "$SD_MEASURE or PCR sysfs files not found, skipping signed PCR policy test case"
|
||||
fi
|
||||
|
||||
if [[ -x "$SD_PCREXTEND" ]] && tpm_has_pcr sha256 11 && tpm_has_pcr sha256 15; then
|
||||
# Let's measure the machine ID
|
||||
tpm2_pcrread sha256:15 -Q -o /tmp/oldpcr15
|
||||
mv /etc/machine-id /etc/machine-id.save
|
||||
echo 994013bf23864ee7992eab39a96dd3bb >/etc/machine-id
|
||||
SYSTEMD_FORCE_MEASURE=1 "$SD_PCREXTEND" --machine-id
|
||||
mv /etc/machine-id.save /etc/machine-id
|
||||
tpm2_pcrread sha256:15 -Q -o /tmp/newpcr15
|
||||
|
||||
# And check it matches expectations
|
||||
diff /tmp/newpcr15 \
|
||||
<(cat /tmp/oldpcr15 <(echo -n "machine-id:994013bf23864ee7992eab39a96dd3bb" | openssl dgst -binary -sha256) | openssl dgst -binary -sha256)
|
||||
|
||||
rm -f /tmp/oldpcr15 /tmp/newpcr15
|
||||
|
||||
# Check that the event log record was properly written:
|
||||
test "$(jq --seq --slurp '.[0].pcr' < /run/log/systemd/tpm2-measure.log)" == "$(printf '\x1e15')"
|
||||
test "$(jq --seq --slurp --raw-output '.[0].digests[1].digest' < /run/log/systemd/tpm2-measure.log) *stdin" == "$(echo -n "machine-id:994013bf23864ee7992eab39a96dd3bb" | openssl dgst -hex -sha256 -r)"
|
||||
|
||||
# And similar for the boot phase measurement into PCR 11
|
||||
tpm2_pcrread sha256:11 -Q -o /tmp/oldpcr11
|
||||
# Do the equivalent of 'SYSTEMD_FORCE_MEASURE=1 "$SD_PCREXTEND" foobar' via Varlink, just to test the Varlink logic (but first we need to patch out the conditionalization...)
|
||||
mkdir -p /run/systemd/system/systemd-pcrextend.socket.d
|
||||
cat > /run/systemd/system/systemd-pcrextend.socket.d/50-no-condition.conf <<EOF
|
||||
[Unit]
|
||||
# Turn off all conditions */
|
||||
ConditionSecurity=
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl restart systemd-pcrextend.socket
|
||||
varlinkctl call /run/systemd/io.systemd.PCRExtend io.systemd.PCRExtend.Extend '{"pcr":11,"text":"foobar"}'
|
||||
tpm2_pcrread sha256:11 -Q -o /tmp/newpcr11
|
||||
|
||||
diff /tmp/newpcr11 \
|
||||
<(cat /tmp/oldpcr11 <(echo -n "foobar" | openssl dgst -binary -sha256) | openssl dgst -binary -sha256)
|
||||
|
||||
# Check the event log for the 2nd record
|
||||
jq --seq --slurp < /run/log/systemd/tpm2-measure.log
|
||||
|
||||
test "$(jq --seq --slurp .[1].pcr < /run/log/systemd/tpm2-measure.log)" == "$(printf '\x1e11')"
|
||||
test "$(jq --seq --slurp --raw-output .[1].digests[0].digest < /run/log/systemd/tpm2-measure.log) *stdin" == "$(echo -n "foobar" | openssl dgst -hex -sha256 -r)"
|
||||
|
||||
rm -f /tmp/oldpcr11 /tmp/newpcr11
|
||||
else
|
||||
echo "$SD_PCREXTEND or PCR sysfs files not found, skipping PCR extension test case"
|
||||
fi
|
||||
|
||||
# Ensure that sandboxing doesn't stop creds from being accessible
|
||||
echo "test" > /tmp/testdata
|
||||
systemd-creds encrypt /tmp/testdata /tmp/testdata.encrypted --with-key=tpm2
|
||||
# LoadCredentialEncrypted
|
||||
systemd-run -p PrivateDevices=yes -p LoadCredentialEncrypted=testdata.encrypted:/tmp/testdata.encrypted --pipe --wait systemd-creds cat testdata.encrypted | cmp - /tmp/testdata
|
||||
# SetCredentialEncrypted
|
||||
systemd-run -p PrivateDevices=yes -p SetCredentialEncrypted=testdata.encrypted:"$(cat /tmp/testdata.encrypted)" --pipe --wait systemd-creds cat testdata.encrypted | cmp - /tmp/testdata
|
||||
rm -f /tmp/testdata
|
||||
|
||||
# There is an external issue with libcryptsetup on ppc64 that hits 95% of Ubuntu ppc64 test runs, so skip it
|
||||
machine="$(uname -m)"
|
||||
if [ "${machine}" = "ppc64le" ]; then
|
||||
touch /testok
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cryptenroll_wipe_and_check() {(
|
||||
set +o pipefail
|
||||
|
||||
: >/tmp/cryptenroll.out
|
||||
systemd-cryptenroll "$@" |& tee /tmp/cryptenroll.out
|
||||
grep -qE "Wiped slot [[:digit:]]+" /tmp/cryptenroll.out
|
||||
)}
|
||||
|
||||
img="/tmp/cryptenroll.img"
|
||||
truncate -s 20M "$img"
|
||||
echo -n password >/tmp/password
|
||||
# Change file mode to avoid "/tmp/password has 0644 mode that is too permissive" messages
|
||||
chmod 0600 /tmp/password
|
||||
cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$img" /tmp/password
|
||||
|
||||
# Enroll additional tokens, keys, and passwords to exercise the list and wipe stuff
|
||||
systemd-cryptenroll --unlock-key-file=/tmp/password --tpm2-device=auto "$img"
|
||||
NEWPASSWORD="" systemd-cryptenroll --unlock-key-file=/tmp/password --password "$img"
|
||||
NEWPASSWORD=foo systemd-cryptenroll --unlock-key-file=/tmp/password --password "$img"
|
||||
for _ in {0..9}; do
|
||||
systemd-cryptenroll --unlock-key-file=/tmp/password --recovery-key "$img"
|
||||
done
|
||||
PASSWORD="" NEWPIN=123456 systemd-cryptenroll --tpm2-device=auto --tpm2-with-pin=true "$img"
|
||||
# Do some basic checks before we start wiping stuff
|
||||
systemd-cryptenroll "$img"
|
||||
systemd-cryptenroll "$img" | grep password
|
||||
systemd-cryptenroll "$img" | grep recovery
|
||||
# Let's start wiping
|
||||
cryptenroll_wipe_and_check "$img" --wipe=empty
|
||||
(! cryptenroll_wipe_and_check "$img" --wipe=empty)
|
||||
cryptenroll_wipe_and_check "$img" --wipe=empty,0
|
||||
PASSWORD=foo NEWPASSWORD=foo cryptenroll_wipe_and_check "$img" --wipe=0,0,empty,0,pkcs11,fido2,000,recovery,password --password
|
||||
systemd-cryptenroll "$img" | grep password
|
||||
(! systemd-cryptenroll "$img" | grep recovery)
|
||||
# We shouldn't be able to wipe all keyslots without enrolling a new key first
|
||||
(! systemd-cryptenroll "$img" --wipe=all)
|
||||
PASSWORD=foo NEWPASSWORD=foo cryptenroll_wipe_and_check "$img" --password --wipe=all
|
||||
# Check if the newly (and only) enrolled password works
|
||||
(! systemd-cryptenroll --unlock-key-file=/tmp/password --recovery-key "$img")
|
||||
(! PASSWORD="" systemd-cryptenroll --recovery-key "$img")
|
||||
PASSWORD=foo systemd-cryptenroll --recovery-key "$img"
|
||||
|
||||
systemd-cryptenroll --fido2-with-client-pin=false "$img"
|
||||
systemd-cryptenroll --fido2-with-user-presence=false "$img"
|
||||
systemd-cryptenroll --fido2-with-user-verification=false "$img"
|
||||
systemd-cryptenroll --tpm2-pcrs=8 "$img"
|
||||
systemd-cryptenroll --tpm2-pcrs=boot-loader-code+boot-loader-config "$img"
|
||||
|
||||
(! systemd-cryptenroll --fido2-with-client-pin=false)
|
||||
(! systemd-cryptenroll --fido2-with-user-presence=f "$img" /tmp/foo)
|
||||
(! systemd-cryptenroll --fido2-with-client-pin=1234 "$img")
|
||||
(! systemd-cryptenroll --fido2-with-user-presence=1234 "$img")
|
||||
(! systemd-cryptenroll --fido2-with-user-verification=1234 "$img")
|
||||
(! systemd-cryptenroll --tpm2-with-pin=1234 "$img")
|
||||
(! systemd-cryptenroll --recovery-key --password "$img")
|
||||
(! systemd-cryptenroll --password --recovery-key "$img")
|
||||
(! systemd-cryptenroll --password --fido2-device=auto "$img")
|
||||
(! systemd-cryptenroll --password --pkcs11-token-uri=auto "$img")
|
||||
(! systemd-cryptenroll --password --tpm2-device=auto "$img")
|
||||
(! systemd-cryptenroll --unlock-fido2-device=auto --unlock-fido2-device=auto "$img")
|
||||
(! systemd-cryptenroll --unlock-fido2-device=auto --unlock-key-file=/tmp/unlock "$img")
|
||||
(! systemd-cryptenroll --fido2-credential-algorithm=es512 "$img")
|
||||
(! systemd-cryptenroll --tpm2-public-key-pcrs=key "$img")
|
||||
(! systemd-cryptenroll --tpm2-pcrs=key "$img")
|
||||
(! systemd-cryptenroll --tpm2-pcrs=44+8 "$img")
|
||||
(! systemd-cryptenroll --tpm2-pcrs=hello "$img")
|
||||
(! systemd-cryptenroll --wipe-slot "$img")
|
||||
(! systemd-cryptenroll --wipe-slot=10240000 "$img")
|
||||
(! systemd-cryptenroll --fido2-device=auto --unlock-fido2-device=auto "$img")
|
||||
|
||||
# Run this, just to get sanitizer coverage. The tools should be idempotent, hence run the multiple times.
|
||||
if [[ -x "$SD_TPM2SETUP" ]]; then
|
||||
"$SD_TPM2SETUP" --early=yes
|
||||
"$SD_TPM2SETUP" --early=yes
|
||||
"$SD_TPM2SETUP" --early=no
|
||||
"$SD_TPM2SETUP" --early=no
|
||||
fi
|
||||
|
||||
cleanup
|
||||
run_subtests
|
||||
|
||||
touch /testok
|
||||
|
||||
27
test/units/testsuite-70.tpm2-setup.sh
Executable file
27
test/units/testsuite-70.tpm2-setup.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
export SYSTEMD_LOG_LEVEL=debug
|
||||
SD_TPM2SETUP="/usr/lib/systemd/systemd-tpm2-setup"
|
||||
|
||||
if [[ ! -x "${SD_TPM2SETUP:?}" ]]; then
|
||||
echo "$SD_TPM2SETUP not found, skipping the test"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
"$SD_TPM2SETUP" --help
|
||||
"$SD_TPM2SETUP" --version
|
||||
"$SD_TPM2SETUP" --tpm2-device=list
|
||||
"$SD_TPM2SETUP" --tpm2-device=auto
|
||||
"$SD_TPM2SETUP" --tpm2-device=/dev/tpm0
|
||||
"$SD_TPM2SETUP" --early=yes
|
||||
"$SD_TPM2SETUP" --early=yes
|
||||
"$SD_TPM2SETUP" --early=no
|
||||
"$SD_TPM2SETUP" --early=no
|
||||
|
||||
(! "$SD_TPM2SETUP" "")
|
||||
(! "$SD_TPM2SETUP" --tpm2-device=)
|
||||
(! "$SD_TPM2SETUP" --tpm2-device=/dev/null)
|
||||
(! "$SD_TPM2SETUP" --foo=bar)
|
||||
@@ -182,3 +182,10 @@ cgroupfs_supports_user_xattrs() {
|
||||
setfattr --name="$xattr" --value=254 /sys/fs/cgroup
|
||||
[[ "$(getfattr --name="$xattr" --absolute-names --only-values /sys/fs/cgroup)" -eq 254 ]]
|
||||
}
|
||||
|
||||
tpm_has_pcr() {
|
||||
local algorithm="${1:?}"
|
||||
local pcr="${2:?}"
|
||||
|
||||
[[ -f "/sys/class/tpm/tpm0/pcr-$algorithm/$pcr" ]]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user