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 SD_PCREXTEND
="/usr/lib/systemd/systemd-pcrextend"
12 SD_PCRLOCK
="/usr/lib/systemd/systemd-pcrlock"
13 SD_MEASURE
="/usr/lib/systemd/systemd-measure"
15 if [[ ! -x "${SD_PCREXTEND:?}" ]] || [[ ! -x "${SD_PCRLOCK:?}" ]] || [[ ! -x "${SD_MEASURE:?}" ]] ; then
16 echo "$SD_PCREXTEND or $SD_PCRLOCK or $SD_MEASURE not found, skipping pcrlock tests"
21 if [[ $?
-ne 0 ]]; then
22 # Dump the event log on fail, to make debugging a bit easier
23 [[ -e /run
/log
/systemd
/tpm2-measure.log
]] && jq
--seq --slurp </run
/log
/systemd
/tpm2-measure.log
31 # Temporarily override sd-pcrextend's sanity checks
32 export SYSTEMD_FORCE_MEASURE
=1
34 # The PCRs we are going to lock to. We exclude the various PCRs we touched
35 # above where no event log record was written, because we cannot analyze
36 # things without event log. We include debug PCR 16, see below.
39 # Remove the old measurement log, as it contains all kinds of nonsense from the
40 # previous test, which will fail our consistency checks. Removing the file also
41 # means we'll fail consistency check, but at least we'll fail them consistently
42 # (as the PCR values simply won't match the log).
43 rm -f /run
/log
/systemd
/tpm2-measure.log
45 # Ensure a truncated log doesn't crash pcrlock
46 echo -n -e \\x1e
>/tmp
/borked
48 SYSTEMD_MEASURE_LOG_USERSPACE
=/tmp
/borked
"$SD_PCRLOCK" cel
--no-pager --json=pretty
51 # If it crashes the exit code will be 149
54 SYSTEMD_COLORS
=256 "$SD_PCRLOCK"
55 "$SD_PCRLOCK" cel
--no-pager --json=pretty
56 "$SD_PCRLOCK" log
--pcr="$PCRS"
57 "$SD_PCRLOCK" log
--json=pretty
--pcr="$PCRS"
58 "$SD_PCRLOCK" list-components
59 "$SD_PCRLOCK" list-components
--location=250-
60 "$SD_PCRLOCK" list-components
--location=250-:350-
61 "$SD_PCRLOCK" lock-firmware-config
62 "$SD_PCRLOCK" lock-gpt
63 "$SD_PCRLOCK" lock-machine-id
64 "$SD_PCRLOCK" lock-file-system
65 "$SD_PCRLOCK" lock-file-system
/
66 "$SD_PCRLOCK" predict
--pcr="$PCRS"
67 "$SD_PCRLOCK" predict
--pcr="0x1+0x3+4"
68 "$SD_PCRLOCK" predict
--json=pretty
--pcr="$PCRS"
70 SD_STUB
="$(find /usr/lib/systemd/boot/efi/ -name "systemd-boot
*.efi
" | head -n1)"
71 if [[ -n "$SD_STUB" ]]; then
72 "$SD_PCRLOCK" lock-pe
"$SD_STUB"
73 "$SD_PCRLOCK" lock-pe
<"$SD_STUB"
74 "$SD_PCRLOCK" lock-uki
"$SD_STUB"
75 "$SD_PCRLOCK" lock-uki
<"$SD_STUB"
78 PIN
=huhu
"$SD_PCRLOCK" make-policy
--pcr="$PCRS" --recovery-pin=query
79 # Repeat immediately (this call will have to reuse the nvindex, rather than create it)
80 "$SD_PCRLOCK" make-policy
--pcr="$PCRS"
81 "$SD_PCRLOCK" make-policy
--pcr="$PCRS" --force
83 img
="/tmp/pcrlock.img"
84 truncate
-s 20M
"$img"
85 echo -n hoho
>/tmp
/pcrlockpwd
86 chmod 0600 /tmp
/pcrlockpwd
87 cryptsetup luksFormat
-q --pbkdf pbkdf2
--pbkdf-force-iterations 1000 --use-urandom "$img" /tmp
/pcrlockpwd
89 systemd-cryptenroll
--unlock-key-file=/tmp
/pcrlockpwd
--tpm2-device=auto
--tpm2-pcrlock=/var
/lib
/systemd
/pcrlock.json
--tpm2-public-key= --wipe-slot=tpm2
"$img"
90 systemd-cryptsetup attach pcrlock
"$img" - tpm2-device
=auto
,tpm2-pcrlock
=/var
/lib
/systemd
/pcrlock.json
,headless
91 systemd-cryptsetup detach pcrlock
93 # Ensure systemd-pcrlock not crashing on empty variant directory
94 mkdir
-p /var
/lib
/pcrlock.d
/123-empty.pcrlock.d
95 "$SD_PCRLOCK" predict
--pcr="$PCRS"
96 rm -rf /var
/lib
/pcrlock.d
/123-empty.pcrlock.d
98 # Measure something into PCR 16 (the "debug" PCR), which should make the activation fail
99 "$SD_PCREXTEND" --pcr=16 test70
101 "$SD_PCRLOCK" cel
--json=pretty
103 (! systemd-cryptsetup attach pcrlock
"$img" - tpm2-device
=auto
,tpm2-pcrlock
=/var
/lib
/systemd
/pcrlock.json
,headless
)
105 # Now add a component for it, rebuild policy and it should work (we'll rebuild
106 # once like that, but don't provide the recovery pin. This should fail, since
107 # the PCR is hosed after all. But then we'll use recovery pin, and it should
109 echo -n test70 |
"$SD_PCRLOCK" lock-raw
--pcrlock=/var
/lib
/pcrlock.d
/910-test70.pcrlock
--pcr=16
110 (! "$SD_PCRLOCK" make-policy
--pcr="$PCRS")
111 PIN
=huhu
"$SD_PCRLOCK" make-policy
--pcr="$PCRS" --recovery-pin=query
113 systemd-cryptsetup attach pcrlock
"$img" - tpm2-device
=auto
,tpm2-pcrlock
=/var
/lib
/systemd
/pcrlock.json
,headless
114 systemd-cryptsetup detach pcrlock
116 # And now let's do it the clean way, and generate the right policy ahead of time.
117 echo -n test70-take-two |
"$SD_PCRLOCK" lock-raw
--pcrlock=/var
/lib
/pcrlock.d
/920-test70.pcrlock
--pcr=16
118 "$SD_PCRLOCK" make-policy
--pcr="$PCRS"
119 # the next one should be skipped because redundant
120 "$SD_PCRLOCK" make-policy
--pcr="$PCRS"
121 # but this one should not be skipped, even if redundant, because we force it
122 "$SD_PCRLOCK" make-policy
--pcr="$PCRS" --force --recovery-pin=show
124 "$SD_PCREXTEND" --pcr=16 test70-take-two
126 "$SD_PCRLOCK" cel
--json=pretty
128 systemd-cryptsetup attach pcrlock
"$img" - tpm2-device
=auto
,tpm2-pcrlock
=/var
/lib
/systemd
/pcrlock.json
,headless
129 systemd-cryptsetup detach pcrlock
131 # Now combined pcrlock and signed PCR
133 openssl genpkey
-algorithm RSA
-pkeyopt rsa_keygen_bits
:2048 -out "$img".private.pem
134 openssl rsa
-pubout -in "$img".private.pem
-out "$img".public.pem
135 systemd-cryptenroll
--unlock-tpm2-device=auto
--tpm2-device=auto
--tpm2-pcrlock=/var
/lib
/systemd
/pcrlock.json
--tpm2-public-key="$img".public.pem
--wipe-slot=tpm2
"$img"
136 "$SD_MEASURE" sign
--current --bank=sha256
--private-key="$img".private.pem
--public-key="$img".public.pem
--phase=: |
tee "$img".pcrsign
137 SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE
=0 systemd-cryptsetup attach pcrlock
"$img" - "tpm2-device=auto,tpm2-pcrlock=/var/lib/systemd/pcrlock.json,tpm2-signature=$img.pcrsign,headless"
138 systemd-cryptsetup detach pcrlock
139 systemd-cryptenroll
--unlock-key-file=/tmp
/pcrlockpwd
--tpm2-device=auto
--tpm2-pcrlock=/var
/lib
/systemd
/pcrlock.json
--tpm2-public-key= --wipe-slot=tpm2
"$img"
140 rm "$img".public.pem
"$img".private.pem
"$img".pcrsign
142 # Now use the root fs support, i.e. make the tool write a copy of the pcrlock
143 # file as service credential to some temporary dir and remove the local copy, so that
144 # it has to use the credential version.
145 mkdir
/tmp
/fakexbootldr
146 SYSTEMD_XBOOTLDR_PATH
=/tmp
/fakexbootldr SYSTEMD_RELAX_XBOOTLDR_CHECKS
=1 "$SD_PCRLOCK" make-policy
--pcr="$PCRS" --force
147 mv /var
/lib
/systemd
/pcrlock.json
/var
/lib
/systemd
/pcrlock.json.gone
149 ls -al /tmp
/fakexbootldr
/loader
/credentials
151 CREDENTIAL_FILE
="$(echo /tmp/fakexbootldr/loader/credentials/pcrlock.*.cred)"
152 test -f "$CREDENTIAL_FILE"
154 # Strip dir and .cred suffix from file name.
155 CREDENTIAL_NAME
=${CREDENTIAL_FILE#/tmp/fakexbootldr/loader/credentials/}
156 CREDENTIAL_NAME
=${CREDENTIAL_NAME%.cred}
158 systemd-creds decrypt
--name="$CREDENTIAL_NAME" "$CREDENTIAL_FILE"
159 ln -s "$CREDENTIAL_FILE" /tmp
/fakexbootldr
/loader
/credentials
/"$CREDENTIAL_NAME"
160 test -f /tmp
/fakexbootldr
/loader
/credentials
/"$CREDENTIAL_NAME"
162 SYSTEMD_ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY
=/tmp
/fakexbootldr
/loader
/credentials systemd-cryptsetup attach pcrlock
"$img" - tpm2-device
=auto
,headless
163 systemd-cryptsetup detach pcrlock
165 mv /var
/lib
/systemd
/pcrlock.json.gone
/var
/lib
/systemd
/pcrlock.json
166 SYSTEMD_XBOOTLDR_PATH
=/tmp
/fakexbootldr SYSTEMD_RELAX_XBOOTLDR_CHECKS
=1 "$SD_PCRLOCK" remove-policy
168 "$SD_PCRLOCK" unlock-firmware-config
169 "$SD_PCRLOCK" unlock-gpt
170 "$SD_PCRLOCK" unlock-machine-id
171 "$SD_PCRLOCK" unlock-file-system
172 "$SD_PCRLOCK" unlock-raw
--pcrlock=/var
/lib
/pcrlock.d
/910-test70.pcrlock
173 "$SD_PCRLOCK" unlock-raw
--pcrlock=/var
/lib
/pcrlock.d
/920-test70.pcrlock
176 (! "$SD_PCRLOCK" predict
--pcr=-1)
177 (! "$SD_PCRLOCK" predict
--pcr=foo
)
178 (! "$SD_PCRLOCK" predict
--pcr=1+1)
179 (! "$SD_PCRLOCK" predict
--pcr=1+++++1)
180 (! "$SD_PCRLOCK" make-policy
--nv-index=0)
181 (! "$SD_PCRLOCK" make-policy
--nv-index=foo
)
182 (! "$SD_PCRLOCK" list-components
--location=:)
183 (! "$SD_PCRLOCK" lock-gpt
"")
184 (! "$SD_PCRLOCK" lock-gpt
/dev
/sr0
)
185 (! "$SD_PCRLOCK" lock-pe
/dev
/full
)
186 (! "$SD_PCRLOCK" lock-pe
/bin
/true
)
187 (! "$SD_PCRLOCK" lock-uki
/dev
/full
)
188 (! "$SD_PCRLOCK" lock-uki
/bin
/true
)
189 (! "$SD_PCRLOCK" lock-file-system
"")
191 # Exercise Varlink API a bit (but first turn off condition)
193 mkdir
-p /run
/systemd
/system
/systemd-pcrlock.socket.d
194 cat > /run
/systemd
/system
/systemd-pcrlock.socket.d
/50-no-condition.conf
<<EOF
196 # Turn off all conditions
200 systemctl daemon-reload
201 systemctl restart systemd-pcrlock.socket
203 varlinkctl call
/run
/systemd
/io.systemd.PCRLock io.systemd.PCRLock.RemovePolicy
'{}'
204 varlinkctl call
/run
/systemd
/io.systemd.PCRLock io.systemd.PCRLock.MakePolicy
'{}'
205 varlinkctl call
--collect --json=pretty
/run
/systemd
/io.systemd.PCRLock io.systemd.PCRLock.ReadEventLog
'{}'
207 rm "$img" /tmp
/pcrlockpwd
211 run0
/usr
/lib
/systemd
/systemd-pcrlock