2023-10-25 14:48:30 +02:00
#!/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
2023-07-24 20:04:28 -04:00
# enroll TPM using device key instead of direct access, then verify unlock using TPM
tpm2_pcrread -Q -o /tmp/pcr.dat sha256:12
CURRENT_PCR_VALUE = $( cat /sys/class/tpm/tpm0/pcr-sha256/12)
tpm2_readpublic -c 0x81000001 -o /tmp/srk.pub
2023-11-08 22:46:44 +01:00
systemd-analyze srk > /tmp/srk2.pub
cmp /tmp/srk.pub /tmp/srk2.pub
if [ -f /run/systemd/tpm2-srk-public-key.tpm2b_public ] ; then
cmp /tmp/srk.pub /run/systemd/tpm2-srk-public-key.tpm2b_public
fi
2023-11-13 20:35:29 +01:00
# --tpm2-device-key= requires OpenSSL >= 3 with KDF-SS
if openssl_supports_kdf SSKDF; then
PASSWORD = passphrase systemd-cryptenroll --tpm2-device-key= /tmp/srk.pub --tpm2-pcrs= " 12:sha256= $CURRENT_PCR_VALUE " " $IMAGE "
systemd-cryptsetup attach test-volume " $IMAGE " - tpm2-device= auto,headless= 1
systemd-cryptsetup detach test-volume
fi
2023-07-24 20:04:28 -04:00
rm -f /tmp/pcr.dat /tmp/srk.pub
2023-10-25 14:48:30 +02:00
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)
2023-11-07 12:18:08 -05:00
PERSISTENT_HANDLE = " 0x ${ PERSISTENT_LINE ##*0x } "
2023-10-25 14:48:30 +02:00
tpm2_flushcontext -t
systemd-cryptenroll --wipe-slot= tpm2 " $IMAGE "
2023-11-07 12:18:08 -05:00
PASSWORD = passphrase systemd-cryptenroll --tpm2-device= auto --tpm2-seal-key-handle= " ${ PERSISTENT_HANDLE #0x } " " $IMAGE "
2023-10-25 14:48:30 +02:00
systemd-cryptsetup attach test-volume " $IMAGE " - tpm2-device= auto,headless= 1
systemd-cryptsetup detach test-volume
systemd-cryptenroll --wipe-slot= tpm2 " $IMAGE "
2023-11-07 12:18:08 -05:00
PASSWORD = passphrase systemd-cryptenroll --tpm2-device= auto --tpm2-seal-key-handle= " $PERSISTENT_HANDLE " " $IMAGE "
2023-10-25 14:48:30 +02:00
systemd-cryptsetup attach test-volume " $IMAGE " - tpm2-device= auto,headless= 1
systemd-cryptsetup detach test-volume
2023-11-13 20:35:29 +01:00
# --tpm2-device-key= requires OpenSSL >= 3 with KDF-SS
if openssl_supports_kdf SSKDF; then
# Make sure that --tpm2-device-key= also works with systemd-repart
tpm2_readpublic -c 0x81000001 -o /tmp/srk.pub
mkdir /tmp/dditest
cat > /tmp/dditest/50-root.conf <<EOF
2023-11-09 12:25:07 +01:00
[ Partition]
Type = root
Format = ext4
CopyFiles = /tmp/dditest:/
Encrypt = tpm2
EOF
2024-07-25 13:22:42 +02:00
PASSWORD = passphrase systemd-repart --tpm2-device-key= /tmp/srk.pub --definitions= /tmp/dditest --empty= create --size= 80M /tmp/dditest.raw --tpm2-pcrs=
2023-11-13 20:35:29 +01:00
DEVICE = " $( systemd-dissect --attach /tmp/dditest.raw) "
2024-05-17 14:21:44 +09:00
udevadm wait --settle --timeout= 10 " $DEVICE " p1
2023-11-13 20:35:29 +01:00
systemd-cryptsetup attach dditest " $DEVICE " p1 - tpm2-device= auto,headless= yes
mkdir /tmp/dditest.mnt
mount -t ext4 /dev/mapper/dditest /tmp/dditest.mnt
cmp /tmp/dditest.mnt/50-root.conf /tmp/dditest/50-root.conf
umount /tmp/dditest.mnt
rmdir /tmp/dditest.mnt
rm /tmp/dditest.raw
rm /tmp/dditest/50-root.conf
rmdir /tmp/dditest
fi
2023-11-09 12:25:07 +01:00
2023-10-25 14:48:30 +02:00
rm -f " $IMAGE " " $PRIMARY "