]>
Commit | Line | Data |
---|---|---|
be4bc80d SB |
1 | #!/bin/bash |
2 | ||
3 | # For the license, see the LICENSE file in the root directory. | |
4 | #set -x | |
5 | ||
6 | ||
313cf75c SB |
7 | ROOT=${abs_top_builddir:-$(pwd)/..} |
8 | TESTDIR=${abs_top_testdir:-$(dirname "$0")} | |
9 | ||
be4bc80d SB |
10 | VTPM_NAME="${VTPM_NAME:-vtpm-tpm2-test-save-load-state-da-timeout}" |
11 | SWTPM_DEV_NAME="/dev/${VTPM_NAME}" | |
cce7503c | 12 | export TPM_PATH="$(mktemp -d)" || exit 1 |
be4bc80d SB |
13 | STATE_FILE=$TPM_PATH/tpm2-00.permall |
14 | VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate | |
15 | MY_VOLATILE_STATE_FILE=$TPM_PATH/my.volatilestate | |
16 | MY_PERMANENT_STATE_FILE=$TPM_PATH/my.permanent | |
17 | SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} | |
18 | SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock | |
19 | SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock | |
20 | ||
cce7503c | 21 | logfile="$(mktemp)" || exit 1 |
be4bc80d SB |
22 | |
23 | function cleanup() | |
24 | { | |
25 | pid=${SWTPM_PID} | |
26 | if [ -n "$pid" ]; then | |
47c7ea77 | 27 | kill_quiet -9 $pid |
be4bc80d SB |
28 | fi |
29 | rm -f $logfile | |
30 | rm -rf $TPM_PATH | |
31 | } | |
32 | ||
33 | trap "cleanup" EXIT | |
34 | ||
313cf75c SB |
35 | [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse |
36 | source ${TESTDIR}/common | |
be4bc80d SB |
37 | |
38 | rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null | |
39 | ||
40 | run_swtpm ${SWTPM_INTERFACE} \ | |
41 | --log file=$logfile,level=20 \ | |
42 | --tpm2 | |
43 | ||
100317d5 | 44 | display_processes_by_name "$SWTPM" |
be4bc80d | 45 | |
47c7ea77 | 46 | kill_quiet -0 ${SWTPM_PID} |
be4bc80d SB |
47 | if [ $? -ne 0 ]; then |
48 | echo "Error: ${SWTPM_INTERFACE} TPM did not start." | |
49 | echo "TPM Logfile:" | |
50 | cat $logfile | |
51 | exit 1 | |
52 | fi | |
53 | ||
54 | # Init the TPM | |
55 | run_swtpm_ioctl ${SWTPM_INTERFACE} -i | |
56 | if [ $? -ne 0 ]; then | |
57 | echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." | |
58 | echo "TPM Logfile:" | |
59 | cat $logfile | |
60 | exit 1 | |
61 | fi | |
62 | ||
47c7ea77 | 63 | kill_quiet -0 ${SWTPM_PID} 2>/dev/null |
be4bc80d SB |
64 | if [ $? -ne 0 ]; then |
65 | echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." | |
66 | echo "TPM Logfile:" | |
67 | cat $logfile | |
68 | exit 1 | |
69 | fi | |
70 | ||
71 | # Startup the TPM | |
be4bc80d SB |
72 | RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') |
73 | exp=' 80 01 00 00 00 0a 00 00 00 00' | |
74 | if [ "$RES" != "$exp" ]; then | |
75 | echo "Error: Did not get expected result from TPM2_Startup(ST_Clear)" | |
76 | echo "expected: $exp" | |
77 | echo "received: $RES" | |
78 | exit 1 | |
79 | fi | |
80 | ||
81 | # Create an NVRAM location: nvdefinespace -hi o -ha 01000000 -pwdn nnn -sz 16 -at da | |
be4bc80d SB |
82 | RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x02\x00\x00\x00\x30\x00\x00\x01\x2a\x40\x00\x00\x01\x00\x00\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x03\x6e\x6e\x6e\x00\x0e\x01\x00\x00\x00\x00\x0b\x00\x04\x00\x04\x00\x00\x00\x10') |
83 | exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' | |
84 | if [ "$RES" != "$exp" ]; then | |
85 | echo "Error: Did not get expected result from TPM2_NV_DefineSpace()" | |
86 | echo "expected: $exp" | |
87 | echo "received: $RES" | |
88 | exit 1 | |
89 | fi | |
90 | ||
91 | sleep 1 | |
92 | ||
93 | # TPM2_NV_Write with good password 'nnn' and bad password 'nn' | |
94 | NVWRITE_GOOD='\x80\x02\x00\x00\x00\x2a\x00\x00\x01\x37\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0c\x40\x00\x00\x09\x00\x00\x00\x00\x03\x6e\x6e\x6e\x00\x04\x74\x65\x73\x74\x00\x00' | |
95 | NVWRITE_BAD='\x80\x02\x00\x00\x00\x29\x00\x00\x01\x37\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0b\x40\x00\x00\x09\x00\x00\x00\x00\x02\x6e\x6e\x00\x04\x74\x65\x73\x74\x00\x00' | |
96 | ||
97 | # Write some data into the NVRAM area: nvwrite -ha 01000000 -ic test -pwdn nnn | |
98 | # Due to -at da being used on TPM2_NV_DefineSpace, the first time the command will request a retry | |
99 | for ((i = 0; i < 2; i++)); do | |
be4bc80d SB |
100 | RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_GOOD}) |
101 | exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' | |
102 | if [ $i -eq 1 ] && [ "$RES" != "$exp" ]; then | |
103 | echo "Error: Did not get expected result from TPM2_NV_Write()" | |
104 | echo "expected: $exp" | |
105 | echo "received: $RES" | |
106 | exit 1 | |
107 | fi | |
108 | done | |
109 | ||
110 | # Set the dictionary attack parameters: dictionaryattackparameters -lr 6 -nrt 6 | |
be4bc80d SB |
111 | RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x02\x00\x00\x00\x27\x00\x00\x01\x3a\x40\x00\x00\x0a\x00\x00\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x06') |
112 | exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' | |
113 | if [ "$RES" != "$exp" ]; then | |
114 | echo "Error: Did not get expected result fron TPM2_DictionaryAttackParameters()" | |
115 | echo "expected: $exp" | |
116 | echo "received: $RES" | |
117 | exit 1 | |
118 | fi | |
119 | ||
c0ccbb04 ET |
120 | timenow=$(date +%s) |
121 | timeout=$((timenow + 6)) | |
be4bc80d | 122 | # Send TPM2_NV_Write with wrong password |
be4bc80d SB |
123 | RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_BAD}) |
124 | exp=' 80 01 00 00 00 0a 00 00 09 8e' | |
125 | if [ "$RES" != "$exp" ]; then | |
126 | echo "Error: Did not get expected result from TPM2_NV_Write() with bad password" | |
127 | echo "expected: $exp" | |
128 | echo "received: $RES" | |
129 | exit 1 | |
130 | fi | |
9c616474 | 131 | timenow=$(date +%s) |
c0ccbb04 | 132 | timerecovery=$((timenow + 6)) |
be4bc80d SB |
133 | |
134 | # TPM2_NV_Write with good password must now fail until $timeout | |
e049a947 | 135 | while :; do |
9c616474 SB |
136 | timenow=$(date +%s) |
137 | echo "Writing with good password failed due to lockout until $timeout - now is $timenow." | |
be4bc80d SB |
138 | RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_GOOD}) |
139 | exp=' 80 01 00 00 00 0a 00 00 09 21' | |
e049a947 | 140 | # busy systems may run the above at >= $timeout and get an unexpected result; check time again |
acc3b68c | 141 | timenow=$(date +%s) |
9c616474 | 142 | if [ "$RES" != "$exp" ] && [ $timenow -lt $timeout ]; then |
be4bc80d SB |
143 | echo "Error: Did not get expected failure from TPM2_NV_Write() with good password. Lockout should be enabled." |
144 | echo "expected: $exp" | |
145 | echo "received: $RES" | |
146 | exit 1 | |
147 | fi | |
9c616474 | 148 | [ $timenow -ge $timeout ] && break |
be4bc80d SB |
149 | sleep 1 |
150 | done | |
151 | ||
c0ccbb04 ET |
152 | while :; do |
153 | sleep 1 | |
154 | timenow=$(date +%s) | |
155 | [ $timenow -gt $timerecovery ] && break | |
156 | done | |
9c616474 SB |
157 | timenow_after=$(date +%s) |
158 | echo "Time is now ${timenow_after} -- trying with good password should work now." | |
be4bc80d | 159 | # Now writing with the good password must work again |
be4bc80d SB |
160 | RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_GOOD}) |
161 | exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' | |
162 | if [ "$RES" != "$exp" ]; then | |
163 | echo "Error: Did not get expected result from TPM2_NV_Write() with good password" | |
164 | echo "expected: $exp" | |
165 | echo "received: $RES" | |
9c616474 SB |
166 | # OS X special check |
167 | if [ $timenow_after -lt $timenow ]; then | |
168 | echo "Time went backwards..." | |
169 | exit 77 | |
170 | fi | |
be4bc80d SB |
171 | exit 1 |
172 | fi | |
173 | ||
c0ccbb04 ET |
174 | timenow=$(date +%s) |
175 | timeout=$((timenow + 6)) | |
176 | # Again cause lockout: Send TPM2_NV_Write with wrong password | |
be4bc80d SB |
177 | RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_BAD}) |
178 | exp=' 80 01 00 00 00 0a 00 00 09 8e' | |
179 | if [ "$RES" != "$exp" ]; then | |
180 | echo "Error: Did not get expected result from TPM2_NV_Write() with bad password" | |
181 | echo "expected: $exp" | |
182 | echo "received: $RES" | |
183 | exit 1 | |
184 | fi | |
9c616474 | 185 | timenow=$(date +%s) |
c0ccbb04 | 186 | timerecovery=$((timenow + 6)) |
be4bc80d SB |
187 | |
188 | # Save the state and restore it and then try to poll again | |
189 | run_swtpm_ioctl ${SWTPM_INTERFACE} --save permanent $MY_PERMANENT_STATE_FILE | |
190 | if [ $? -ne 0 ]; then | |
191 | echo "Error: Could not write permanent state file $MY_PERMANENT_STATE_FILE." | |
192 | echo "TPM Logfile:" | |
193 | cat $logfile | |
194 | exit 1 | |
195 | fi | |
196 | if [ ! -r $MY_PERMANENT_STATE_FILE ]; then | |
197 | echo "Error: Permanent state file $MY_PERMANENT_STATE_FILE does not exist." | |
198 | echo "TPM Logfile:" | |
199 | cat $logfile | |
200 | exit 1 | |
201 | fi | |
202 | echo "Saved permanent state." | |
203 | ||
204 | run_swtpm_ioctl ${SWTPM_INTERFACE} --save volatile $MY_VOLATILE_STATE_FILE | |
205 | if [ $? -ne 0 ]; then | |
206 | echo "Error: Could not write volatile state file $MY_VOLATILE_STATE_FILE." | |
207 | echo "TPM Logfile:" | |
208 | cat $logfile | |
209 | exit 1 | |
210 | fi | |
211 | if [ ! -r $MY_VOLATILE_STATE_FILE ]; then | |
212 | echo "Error: Volatile state file $MY_VOLATILE_STATE_FILE does not exist." | |
213 | echo "TPM Logfile:" | |
214 | cat $logfile | |
215 | exit 1 | |
216 | fi | |
217 | echo "Saved volatile state." | |
218 | ||
219 | # we will use our own volatile state | |
220 | rm -f $VOLATILE_STATE_FILE $STATE_FILE | |
221 | ||
222 | # Stop the TPM; this will not shut it down | |
be4bc80d SB |
223 | run_swtpm_ioctl ${SWTPM_INTERFACE} --stop |
224 | if [ $? -ne 0 ]; then | |
225 | echo "Error: Could not stop the ${SWTPM_INTERFACE} TPM." | |
226 | echo "TPM Logfile:" | |
227 | cat $logfile | |
228 | exit 1 | |
229 | fi | |
230 | ||
47c7ea77 | 231 | kill_quiet -0 ${SWTPM_PID} |
be4bc80d SB |
232 | if [ $? -ne 0 ]; then |
233 | echo "Error (2): ${SWTPM_INTERFACE} TPM is not running anymore." | |
234 | echo "TPM Logfile:" | |
235 | cat $logfile | |
236 | exit 1 | |
237 | fi | |
238 | ||
239 | # load state into the TPM | |
240 | run_swtpm_ioctl ${SWTPM_INTERFACE} --load permanent $MY_PERMANENT_STATE_FILE | |
241 | if [ $? -ne 0 ]; then | |
242 | echo "Could not load permanent state into vTPM" | |
243 | echo "TPM Logfile:" | |
244 | cat $logfile | |
245 | exit 1 | |
246 | fi | |
247 | echo "Loaded permanent state." | |
248 | ||
249 | run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $MY_VOLATILE_STATE_FILE | |
250 | if [ $? -ne 0 ]; then | |
251 | echo "Could not load volatile state into vTPM" | |
252 | echo "TPM Logfile:" | |
253 | cat $logfile | |
254 | exit 1 | |
255 | fi | |
256 | echo "Loaded volatile state." | |
257 | ||
258 | #ls -l $(dirname $MY_VOLATILE_STATE_FILE)/* | |
259 | #sha1sum $(dirname $MY_VOLATILE_STATE_FILE)/* | |
260 | ||
261 | # Init the TPM | |
262 | run_swtpm_ioctl ${SWTPM_INTERFACE} -i | |
263 | if [ $? -ne 0 ]; then | |
264 | echo "TPM Init failed." | |
265 | echo "TPM Logfile:" | |
266 | cat $logfile | |
267 | exit 1 | |
268 | fi | |
269 | ||
270 | # Volatile state must have been removed by TPM now | |
271 | if [ -r $VOLATILE_STATE_FILE ]; then | |
272 | echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." | |
273 | echo "TPM Logfile:" | |
274 | cat $logfile | |
275 | exit 1 | |
276 | fi | |
277 | ||
278 | ||
279 | # TPM2_NV_Write with good password must now fail until $timeout | |
e049a947 | 280 | while :; do |
9c616474 SB |
281 | timenow=$(date +%s) |
282 | echo "Writing with good password failed due to lockout until $timeout - now is $timenow." | |
be4bc80d SB |
283 | RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_GOOD}) |
284 | exp=' 80 01 00 00 00 0a 00 00 09 21' | |
e049a947 | 285 | # busy systems may run the above at >= $timeout and get an unexpected result; check time again |
acc3b68c | 286 | timenow=$(date +%s) |
9c616474 | 287 | if [ "$RES" != "$exp" ] && [ $timenow -lt $timeout ]; then |
be4bc80d SB |
288 | echo "Error: Did not get expected failure from TPM2_NV_Write() with good password. Lockout should be enabled." |
289 | echo "expected: $exp" | |
290 | echo "received: $RES" | |
291 | exit 1 | |
292 | fi | |
9c616474 | 293 | [ $timenow -ge $timeout ] && break |
be4bc80d SB |
294 | sleep 1 |
295 | done | |
296 | ||
c0ccbb04 ET |
297 | while :; do |
298 | sleep 1 | |
299 | timenow=$(date +%s) | |
300 | [ $timenow -gt $timerecovery ] && break | |
301 | done | |
9c616474 SB |
302 | timenow_after=$(date +%s) |
303 | echo "Time is now $timenow_after -- trying with good password should work now." | |
be4bc80d | 304 | # Now writing with the good password must work again |
be4bc80d SB |
305 | RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_GOOD}) |
306 | exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' | |
307 | if [ "$RES" != "$exp" ]; then | |
308 | echo "Error: Did not get expected result from TPM2_NV_Write() with good password" | |
309 | echo "expected: $exp" | |
310 | echo "received: $RES" | |
9c616474 SB |
311 | # OS X special check |
312 | if [ $timenow_after -lt $timenow ]; then | |
313 | echo "Time went backwards..." | |
314 | exit 77 | |
315 | fi | |
be4bc80d SB |
316 | exit 1 |
317 | fi | |
318 | ||
be4bc80d | 319 | # Final shut down |
be4bc80d SB |
320 | run_swtpm_ioctl ${SWTPM_INTERFACE} -s |
321 | if [ $? -ne 0 ]; then | |
322 | echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." | |
323 | echo "TPM Logfile:" | |
324 | cat $logfile | |
325 | exit 1 | |
326 | fi | |
327 | ||
45d2d092 | 328 | if wait_process_gone ${SWTPM_PID} 4; then |
be4bc80d SB |
329 | echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." |
330 | echo "TPM Logfile:" | |
331 | cat $logfile | |
332 | exit 1 | |
333 | fi | |
334 | ||
335 | if [ ! -e $STATE_FILE ]; then | |
336 | echo "Error: TPM state file $STATE_FILE does not exist." | |
337 | echo "TPM Logfile:" | |
338 | cat $logfile | |
339 | exit 1 | |
340 | fi | |
341 | ||
342 | echo "OK" | |
343 | ||
344 | exit 0 |