2 # SPDX-License-Identifier: LGPL-2.1-or-later
6 # shellcheck source=test/units/util.sh
7 .
"$(dirname "$0")"/util.sh
9 export SYSTEMD_LOG_LEVEL
=debug
11 cryptsetup_has_token_plugin_support
() {
14 plugin_path
="$(cryptsetup --help | sed -nr 's/.*LUKS2 external token plugin path: (.*)\./\1/p')/libcryptsetup-token-systemd-tpm2.so)"
15 cryptsetup
--help |
grep -q 'LUKS2 external token plugin support is compiled-in' && [[ -f "$plugin_path" ]]
18 tpm_check_failure_with_wrong_pin
() {
19 local testIMAGE
="${1:?}"
21 local goodpin
="${3:?}"
23 # We need to be careful not to trigger DA lockout; allow 2 failures
24 tpm2_dictionarylockout
-s -n 2
25 (! PIN
=$badpin systemd-cryptsetup attach test-volume
"$testIMAGE" - tpm2-device
=auto
,headless
=1)
26 # Verify the correct PIN works, to be sure the failure wasn't a DA lockout
27 PIN
=$goodpin systemd-cryptsetup attach test-volume
"$testIMAGE" - tpm2-device
=auto
,headless
=1
28 systemd-cryptsetup detach test-volume
29 # Clear/reset the DA lockout counter
30 tpm2_dictionarylockout
-c
34 # Evict the TPM primary key that we persisted
35 if [[ -n "${PERSISTENT_HANDLE:-}" ]]; then
36 tpm2_evictcontrol
-c "$PERSISTENT_HANDLE"
42 # Prepare a fresh disk image
43 IMAGE
="$(mktemp /tmp/systemd-cryptsetup-XXX.IMAGE)"
45 truncate
-s 20M
"$IMAGE"
46 echo -n passphrase
>/tmp
/passphrase
47 # Change file mode to avoid "/tmp/passphrase has 0644 mode that is too permissive" messages
48 chmod 0600 /tmp
/passphrase
49 cryptsetup luksFormat
-q --pbkdf pbkdf2
--pbkdf-force-iterations 1000 --use-urandom "$IMAGE" /tmp
/passphrase
51 # Unlocking via keyfile
52 systemd-cryptenroll
--unlock-key-file=/tmp
/passphrase
--tpm2-device=auto
--tpm2-pcrs=7 "$IMAGE"
54 # Enroll unlock with SecureBoot (PCR 7) PCR policy
55 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-pcrs=7 "$IMAGE"
56 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
57 systemd-cryptsetup detach test-volume
59 # Check with wrong PCR
60 tpm2_pcrextend
7:sha256
=0000000000000000000000000000000000000000000000000000000000000000
61 (! systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1)
63 # Enroll unlock with PCR+PIN policy
64 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
65 PASSWORD
=passphrase NEWPIN
=123456 systemd-cryptenroll
--tpm2-device=auto
--tpm2-with-pin=true
--tpm2-pcrs=7 "$IMAGE"
66 PIN
=123456 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
67 systemd-cryptsetup detach test-volume
69 # Check failure with wrong PIN; try a few times to make sure we avoid DA lockout
71 tpm_check_failure_with_wrong_pin
"$IMAGE" 123457 123456
74 # Check LUKS2 token plugin unlock (i.e. without specifying tpm2-device=auto)
75 if cryptsetup_has_token_plugin_support
; then
76 PIN
=123456 systemd-cryptsetup attach test-volume
"$IMAGE" - headless
=1
77 systemd-cryptsetup detach test-volume
79 # Check failure with wrong PIN
81 tpm_check_failure_with_wrong_pin
"$IMAGE" 123457 123456
84 echo 'cryptsetup has no LUKS2 token plugin support, skipping'
87 # Check failure with wrong PCR (and correct PIN)
88 tpm2_pcrextend
7:sha256
=0000000000000000000000000000000000000000000000000000000000000000
89 (! PIN
=123456 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1)
91 # Enroll unlock with PCR 0+7
92 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
93 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-pcrs=0+7 "$IMAGE"
94 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
95 systemd-cryptsetup detach test-volume
97 # Check with wrong PCR 0
98 tpm2_pcrextend
0:sha256
=0000000000000000000000000000000000000000000000000000000000000000
99 (! systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1)
101 if tpm_has_pcr sha256
12; then
102 # Enroll using an explicit PCR value (that does match current PCR value)
103 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
104 EXPECTED_PCR_VALUE
=$
(cat /sys
/class
/tpm
/tpm
0/pcr-sha256
/12)
105 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-pcrs="12:sha256=$EXPECTED_PCR_VALUE" "$IMAGE"
106 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
107 systemd-cryptsetup detach test-volume
109 # Same as above plus more PCRs without the value or alg specified
110 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
111 EXPECTED_PCR_VALUE
=$
(cat /sys
/class
/tpm
/tpm
0/pcr-sha256
/12)
112 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-pcrs="1,12:sha256=$EXPECTED_PCR_VALUE,3" "$IMAGE"
113 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
114 systemd-cryptsetup detach test-volume
116 # Same as above plus more PCRs with hash alg specified but hash value not specified
117 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
118 EXPECTED_PCR_VALUE
=$
(cat /sys
/class
/tpm
/tpm
0/pcr-sha256
/12)
119 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-pcrs="1:sha256,12:sha256=$EXPECTED_PCR_VALUE,3" "$IMAGE"
120 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
121 systemd-cryptsetup detach test-volume
123 # Now the interesting part, enrolling using a hash value that doesn't match the current PCR value
124 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
125 tpm2_pcrread
-Q -o /tmp
/pcr.dat sha256
:12
126 CURRENT_PCR_VALUE
=$
(cat /sys
/class
/tpm
/tpm
0/pcr-sha256
/12)
127 EXPECTED_PCR_VALUE
=$
(cat /tmp
/pcr.dat
/tmp
/pcr.dat | openssl dgst
-sha256 -r | cut
-d ' ' -f 1)
128 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-pcrs="12:sha256=$EXPECTED_PCR_VALUE" "$IMAGE"
129 (! systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1)
130 tpm2_pcrextend
"12:sha256=$CURRENT_PCR_VALUE"
131 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
132 systemd-cryptsetup detach test-volume
134 # enroll TPM using device key instead of direct access, then verify unlock using TPM
135 tpm2_pcrread
-Q -o /tmp
/pcr.dat sha256
:12
136 CURRENT_PCR_VALUE
=$
(cat /sys
/class
/tpm
/tpm
0/pcr-sha256
/12)
137 tpm2_readpublic
-c 0x81000001 -o /tmp
/srk.pub
138 systemd-analyze srk
> /tmp
/srk2.pub
139 cmp /tmp
/srk.pub
/tmp
/srk2.pub
140 if [ -f /run
/systemd
/tpm2-srk-public-key.tpm2b_public
] ; then
141 cmp /tmp
/srk.pub
/run
/systemd
/tpm2-srk-public-key.tpm2b_public
144 # --tpm2-device-key= requires OpenSSL >= 3 with KDF-SS
145 if openssl_supports_kdf SSKDF
; then
146 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device-key=/tmp
/srk.pub
--tpm2-pcrs="12:sha256=$CURRENT_PCR_VALUE" "$IMAGE"
147 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
148 systemd-cryptsetup detach test-volume
151 rm -f /tmp
/pcr.dat
/tmp
/srk.pub
154 # Use default (0) seal key handle
155 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
156 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-seal-key-handle=0 "$IMAGE"
157 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
158 systemd-cryptsetup detach test-volume
160 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
161 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-seal-key-handle=0x0 "$IMAGE"
162 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
163 systemd-cryptsetup detach test-volume
165 # Use SRK seal key handle
166 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
167 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-seal-key-handle=81000001 "$IMAGE"
168 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
169 systemd-cryptsetup detach test-volume
171 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
172 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-seal-key-handle=0x81000001 "$IMAGE"
173 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
174 systemd-cryptsetup detach test-volume
176 # Test invalid ranges: pcr, nv, session, permanent
177 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
178 (! PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-seal-key-handle=7 "$IMAGE") # PCR
179 (! PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-seal-key-handle=0x01000001 "$IMAGE") # NV index
180 (! PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-seal-key-handle=0x02000001 "$IMAGE") # HMAC/loaded session
181 (! PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-seal-key-handle=0x03000001 "$IMAGE") # Policy/saved session
182 (! PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-seal-key-handle=0x40000001 "$IMAGE") # Permanent
184 # Use non-SRK persistent seal key handle (by creating/persisting new key)
185 PRIMARY
=/tmp
/primary.ctx
186 tpm2_createprimary
-c "$PRIMARY"
187 PERSISTENT_LINE
=$
(tpm2_evictcontrol
-c "$PRIMARY" |
grep persistent-handle
)
188 PERSISTENT_HANDLE
="0x${PERSISTENT_LINE##*0x}"
191 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
192 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-seal-key-handle="${PERSISTENT_HANDLE#0x}" "$IMAGE"
193 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
194 systemd-cryptsetup detach test-volume
196 systemd-cryptenroll
--wipe-slot=tpm2
"$IMAGE"
197 PASSWORD
=passphrase systemd-cryptenroll
--tpm2-device=auto
--tpm2-seal-key-handle="$PERSISTENT_HANDLE" "$IMAGE"
198 systemd-cryptsetup attach test-volume
"$IMAGE" - tpm2-device
=auto
,headless
=1
199 systemd-cryptsetup detach test-volume
201 # --tpm2-device-key= requires OpenSSL >= 3 with KDF-SS
202 if openssl_supports_kdf SSKDF
; then
203 # Make sure that --tpm2-device-key= also works with systemd-repart
204 tpm2_readpublic
-c 0x81000001 -o /tmp
/srk.pub
206 cat > /tmp
/dditest
/50-root.conf
<<EOF
210 CopyFiles=/tmp/dditest:/
213 PASSWORD
=passphrase systemd-repart
--tpm2-device-key=/tmp
/srk.pub
--definitions=/tmp
/dditest
--empty=create
--size=80M
/tmp
/dditest.raw
--tpm2-pcrs=
214 DEVICE
="$(systemd-dissect --attach /tmp/dditest.raw)"
215 udevadm
wait --settle --timeout=10 "$DEVICE"p1
216 systemd-cryptsetup attach dditest
"$DEVICE"p1
- tpm2-device
=auto
,headless
=yes
217 mkdir
/tmp
/dditest.mnt
218 mount
-t ext4
/dev
/mapper
/dditest
/tmp
/dditest.mnt
219 cmp /tmp
/dditest.mnt
/50-root.conf
/tmp
/dditest
/50-root.conf
220 umount
/tmp
/dditest.mnt
221 rmdir /tmp
/dditest.mnt
223 rm /tmp
/dditest
/50-root.conf
227 rm -f "$IMAGE" "$PRIMARY"