1 /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Tests for rollback_index functions
6  */
7 
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #define _STUB_IMPLEMENTATION_  /* So we can use memset() ourselves */
14 
15 #include "crc8.h"
16 #include "rollback_index.h"
17 #include "test_common.h"
18 #include "tlcl.h"
19 #include "utility.h"
20 #include "vboot_common.h"
21 
22 /*
23  * Buffer to hold accumulated list of calls to mocked Tlcl functions.
24  * Each function appends itself to the buffer and updates mock_cnext.
25  *
26  * Size of mock_calls[] should be big enough to handle all expected
27  * call sequences; 16KB should be plenty since none of the sequences
28  * below is more than a few hundred bytes.  We could be more clever
29  * and use snprintf() with length checking below, at the expense of
30  * making all the mock implementations bigger.  If this were code used
31  * outside of unit tests we'd want to do that, but here if we did
32  * overrun the buffer the worst that's likely to happen is we'll crash
33  * the test, and crash = failure anyway.
34  */
35 static char mock_calls[16384];
36 static char *mock_cnext = mock_calls;
37 
38 /*
39  * Variables to support mocked error values from Tlcl functions.  Each
40  * call, mock_count is incremented.  If mock_count==fail_at_count, return
41  * fail_with_error instead of the normal return value.
42  */
43 static int mock_count = 0;
44 static int fail_at_count = 0;
45 static uint32_t fail_with_error = TPM_SUCCESS;
46 
47 /* Similar, to determine when to inject noise during reads & writes */
48 #define MAX_NOISE_COUNT 64              /* no noise after this many */
49 static int noise_count = 0;             /* read/write attempt (zero-based) */
50 static int noise_on[MAX_NOISE_COUNT];   /* calls to inject noise on */
51 
52 /* Params / backing store for mocked Tlcl functions. */
53 static TPM_PERMANENT_FLAGS mock_pflags;
54 static RollbackSpaceFirmware mock_rsf;
55 static RollbackSpaceKernel mock_rsk;
56 static uint32_t mock_permissions;
57 
58 /* Reset the variables for the Tlcl mock functions. */
ResetMocks(int fail_on_call,uint32_t fail_with_err)59 static void ResetMocks(int fail_on_call, uint32_t fail_with_err)
60 {
61 	*mock_calls = 0;
62 	mock_cnext = mock_calls;
63 	mock_count = 0;
64 	fail_at_count = fail_on_call;
65 	fail_with_error = fail_with_err;
66 	noise_count = 0;
67 	Memset(&noise_on, 0, sizeof(noise_on));
68 
69 	Memset(&mock_pflags, 0, sizeof(mock_pflags));
70 	Memset(&mock_rsf, 0, sizeof(mock_rsf));
71 	Memset(&mock_rsk, 0, sizeof(mock_rsk));
72 	mock_permissions = 0;
73 }
74 
75 /****************************************************************************/
76 /* Function to garble data on its way to or from the TPM */
MaybeInjectNoise(void * data,uint32_t length)77 static void MaybeInjectNoise(void *data, uint32_t length)
78 {
79 	if (noise_count < MAX_NOISE_COUNT && noise_on[noise_count]) {
80 		uint8_t *val = data;
81 		val[length - 1]++;
82 	}
83 	noise_count++;
84 }
85 
86 /****************************************************************************/
87 /* Mocks for tlcl functions which log the calls made to mock_calls[]. */
88 
TlclLibInit(void)89 uint32_t TlclLibInit(void)
90 {
91 	mock_cnext += sprintf(mock_cnext, "TlclLibInit()\n");
92 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
93 }
94 
TlclStartup(void)95 uint32_t TlclStartup(void)
96 {
97 	mock_cnext += sprintf(mock_cnext, "TlclStartup()\n");
98 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
99 }
100 
TlclResume(void)101 uint32_t TlclResume(void)
102 {
103 	mock_cnext += sprintf(mock_cnext, "TlclResume()\n");
104 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
105 }
106 
TlclForceClear(void)107 uint32_t TlclForceClear(void)
108 {
109 	mock_cnext += sprintf(mock_cnext, "TlclForceClear()\n");
110 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
111 }
112 
TlclSetEnable(void)113 uint32_t TlclSetEnable(void)
114 {
115 	mock_cnext += sprintf(mock_cnext, "TlclSetEnable()\n");
116 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
117 }
118 
TlclSetDeactivated(uint8_t flag)119 uint32_t TlclSetDeactivated(uint8_t flag)
120 {
121 	mock_cnext += sprintf(mock_cnext, "TlclSetDeactivated(%d)\n", flag);
122 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
123 }
124 
TlclRead(uint32_t index,void * data,uint32_t length)125 uint32_t TlclRead(uint32_t index, void* data, uint32_t length)
126 {
127 	mock_cnext += sprintf(mock_cnext, "TlclRead(0x%x, %d)\n",
128 			      index, length);
129 
130 	if (FIRMWARE_NV_INDEX == index) {
131 		TEST_EQ(length, sizeof(mock_rsf), "TlclRead rsf size");
132 		Memcpy(data, &mock_rsf, length);
133 		MaybeInjectNoise(data, length);
134 	} else if (KERNEL_NV_INDEX == index) {
135 		TEST_EQ(length, sizeof(mock_rsk), "TlclRead rsk size");
136 		Memcpy(data, &mock_rsk, length);
137 		MaybeInjectNoise(data, length);
138 	} else {
139 		Memset(data, 0, length);
140 	}
141 
142 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
143 }
144 
TlclWrite(uint32_t index,const void * data,uint32_t length)145 uint32_t TlclWrite(uint32_t index, const void *data, uint32_t length)
146 {
147 	mock_cnext += sprintf(mock_cnext, "TlclWrite(0x%x, %d)\n",
148 			      index, length);
149 
150 	if (FIRMWARE_NV_INDEX == index) {
151 		TEST_EQ(length, sizeof(mock_rsf), "TlclWrite rsf size");
152 		Memcpy(&mock_rsf, data, length);
153 		MaybeInjectNoise(&mock_rsf, length);
154 	} else if (KERNEL_NV_INDEX == index) {
155 		TEST_EQ(length, sizeof(mock_rsk), "TlclWrite rsk size");
156 		Memcpy(&mock_rsk, data, length);
157 		MaybeInjectNoise(&mock_rsk, length);
158 	}
159 
160 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
161 }
162 
TlclDefineSpace(uint32_t index,uint32_t perm,uint32_t size)163 uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size)
164 {
165 	mock_cnext += sprintf(mock_cnext, "TlclDefineSpace(0x%x, 0x%x, %d)\n",
166 			      index, perm, size);
167 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
168 }
169 
TlclSelfTestFull(void)170 uint32_t TlclSelfTestFull(void)
171 {
172 	mock_cnext += sprintf(mock_cnext, "TlclSelfTestFull()\n");
173 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
174 }
175 
TlclContinueSelfTest(void)176 uint32_t TlclContinueSelfTest(void)
177 {
178 	mock_cnext += sprintf(mock_cnext, "TlclContinueSelfTest()\n");
179 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
180 }
181 
TlclGetPermanentFlags(TPM_PERMANENT_FLAGS * pflags)182 uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS *pflags)
183 {
184 	mock_cnext += sprintf(mock_cnext, "TlclGetPermanentFlags()\n");
185 	Memcpy(pflags, &mock_pflags, sizeof(mock_pflags));
186 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
187 }
188 
189 /* TlclGetFlags() doesn't need mocking; it calls TlclGetPermanentFlags() */
190 
TlclAssertPhysicalPresence(void)191 uint32_t TlclAssertPhysicalPresence(void)
192 {
193 	mock_cnext += sprintf(mock_cnext, "TlclAssertPhysicalPresence()\n");
194 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
195 }
196 
TlclFinalizePhysicalPresence(void)197 uint32_t TlclFinalizePhysicalPresence(void)
198 {
199 	mock_cnext += sprintf(mock_cnext, "TlclFinalizePhysicalPresence()\n");
200 	mock_pflags.physicalPresenceLifetimeLock = 1;
201 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
202 }
203 
TlclPhysicalPresenceCMDEnable(void)204 uint32_t TlclPhysicalPresenceCMDEnable(void)
205 {
206 	mock_cnext += sprintf(mock_cnext, "TlclPhysicalPresenceCMDEnable()\n");
207 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
208 }
209 
TlclSetNvLocked(void)210 uint32_t TlclSetNvLocked(void)
211 {
212 	mock_cnext += sprintf(mock_cnext, "TlclSetNvLocked()\n");
213 	mock_pflags.nvLocked = 1;
214 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
215 }
216 
TlclSetGlobalLock(void)217 uint32_t TlclSetGlobalLock(void)
218 {
219 	mock_cnext += sprintf(mock_cnext, "TlclSetGlobalLock()\n");
220 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
221 }
222 
TlclLockPhysicalPresence(void)223 uint32_t TlclLockPhysicalPresence(void)
224 {
225 	mock_cnext += sprintf(mock_cnext, "TlclLockPhysicalPresence()\n");
226 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
227 }
228 
TlclGetPermissions(uint32_t index,uint32_t * permissions)229 uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions)
230 {
231 	mock_cnext += sprintf(mock_cnext, "TlclGetPermissions(0x%x)\n", index);
232 	*permissions = mock_permissions;
233 	return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS;
234 }
235 
236 /****************************************************************************/
237 /* Tests for CRC errors  */
238 
239 extern uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf);
240 extern uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf);
241 
CrcTestFirmware(void)242 static void CrcTestFirmware(void)
243 {
244 	RollbackSpaceFirmware rsf;
245 
246 	/* Noise on reading, shouldn't matter here because version == 0 */
247 	ResetMocks(0, 0);
248 	noise_on[0] = 1;
249 	TEST_EQ(ReadSpaceFirmware(&rsf), 0, "ReadSpaceFirmware(), v0");
250 	TEST_STR_EQ(mock_calls,
251 		    "TlclRead(0x1007, 10)\n",
252 		    "tlcl calls");
253 
254 	/*
255 	 * But if the version >= 2, it will try three times and fail because
256 	 * the CRC is no good.
257 	 */
258 	ResetMocks(0, 0);
259 	mock_rsf.struct_version = 2;
260 	TEST_EQ(ReadSpaceFirmware(&rsf), TPM_E_CORRUPTED_STATE,
261 		"ReadSpaceFirmware(), v2, bad CRC");
262 	TEST_STR_EQ(mock_calls,
263 		    "TlclRead(0x1007, 10)\n"
264 		    "TlclRead(0x1007, 10)\n"
265 		    "TlclRead(0x1007, 10)\n",
266 		    "tlcl calls");
267 
268 	/* If the CRC is good and some noise happens, it should recover. */
269 	ResetMocks(0, 0);
270 	mock_rsf.struct_version = 2;
271 	mock_rsf.crc8 = Crc8(&mock_rsf, offsetof(RollbackSpaceFirmware, crc8));
272 	noise_on[0] = 1;
273 	TEST_EQ(ReadSpaceFirmware(&rsf), 0,
274 		"ReadSpaceFirmware(), v2, good CRC");
275 	TEST_STR_EQ(mock_calls,
276 		    "TlclRead(0x1007, 10)\n"
277 		    "TlclRead(0x1007, 10)\n",
278 		    "tlcl calls");
279 
280 	/* A write with version < 2 should convert to v2 and create the CRC */
281 	ResetMocks(0, 0);
282 	Memset(&rsf, 0, sizeof(rsf));
283 	TEST_EQ(WriteSpaceFirmware(&rsf), 0, "WriteSpaceFirmware(), v0");
284 	TEST_EQ(mock_rsf.struct_version, 2, "WriteSpaceFirmware(), check v2");
285 	TEST_STR_EQ(mock_calls,
286 		    "TlclWrite(0x1007, 10)\n"
287 		    "TlclRead(0x1007, 10)\n",
288 		    "tlcl calls");
289 
290 	/* Same as above, but with some noise during the readback */
291 	ResetMocks(0, 0);
292 	Memset(&rsf, 0, sizeof(rsf));
293 	noise_on[1] = 1;
294 	noise_on[2] = 1;
295 	TEST_EQ(WriteSpaceFirmware(&rsf), 0,
296 		"WriteSpaceFirmware(), read noise");
297 	TEST_STR_EQ(mock_calls,
298 		    "TlclWrite(0x1007, 10)\n"
299 		    "TlclRead(0x1007, 10)\n"
300 		    "TlclRead(0x1007, 10)\n"
301 		    "TlclRead(0x1007, 10)\n",
302 		    "tlcl calls");
303 
304 	/* With noise during the write, we'll try the write again */
305 	ResetMocks(0, 0);
306 	Memset(&rsf, 0, sizeof(rsf));
307 	noise_on[0] = 1;
308 	TEST_EQ(WriteSpaceFirmware(&rsf), 0,
309 		"WriteSpaceFirmware(), write noise");
310 	TEST_EQ(mock_rsf.struct_version, 2, "WriteSpaceFirmware(), check v2");
311 	TEST_STR_EQ(mock_calls,
312 		    "TlclWrite(0x1007, 10)\n"
313 		    "TlclRead(0x1007, 10)\n"
314 		    "TlclRead(0x1007, 10)\n"
315 		    "TlclRead(0x1007, 10)\n"
316 		    "TlclWrite(0x1007, 10)\n"
317 		    "TlclRead(0x1007, 10)\n",
318 		    "tlcl calls");
319 
320 	/* Only if it just keeps on failing forever do we eventually give up */
321 	ResetMocks(0, 0);
322 	Memset(&rsf, 0, sizeof(rsf));
323 	Memset(noise_on, 1, sizeof(noise_on));
324 	TEST_EQ(WriteSpaceFirmware(&rsf), TPM_E_CORRUPTED_STATE,
325 		"WriteSpaceFirmware(), always noise");
326 	TEST_STR_EQ(mock_calls,
327 		    "TlclWrite(0x1007, 10)\n"
328 		    "TlclRead(0x1007, 10)\n"
329 		    "TlclRead(0x1007, 10)\n"
330 		    "TlclRead(0x1007, 10)\n"
331 		    "TlclWrite(0x1007, 10)\n"
332 		    "TlclRead(0x1007, 10)\n"
333 		    "TlclRead(0x1007, 10)\n"
334 		    "TlclRead(0x1007, 10)\n"
335 		    "TlclWrite(0x1007, 10)\n"
336 		    "TlclRead(0x1007, 10)\n"
337 		    "TlclRead(0x1007, 10)\n"
338 		    "TlclRead(0x1007, 10)\n",
339 		    "tlcl calls");
340 }
341 
342 extern uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk);
343 extern uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk);
344 
CrcTestKernel(void)345 static void CrcTestKernel(void)
346 {
347 	RollbackSpaceKernel rsk;
348 
349 	/* Noise on reading shouldn't matter here because version == 0 */
350 	ResetMocks(0, 0);
351 	noise_on[0] = 1;
352 	TEST_EQ(ReadSpaceKernel(&rsk), 0, "ReadSpaceKernel(), v0");
353 	TEST_STR_EQ(mock_calls,
354 		    "TlclRead(0x1008, 13)\n",
355 		    "tlcl calls");
356 
357 	/*
358 	 * But if the version >= 2, it will try three times and fail because
359 	 * the CRC is no good.
360 	 */
361 	ResetMocks(0, 0);
362 	mock_rsk.struct_version = 2;
363 	TEST_EQ(ReadSpaceKernel(&rsk), TPM_E_CORRUPTED_STATE,
364 		"ReadSpaceKernel(), v2, bad CRC");
365 	TEST_STR_EQ(mock_calls,
366 		    "TlclRead(0x1008, 13)\n"
367 		    "TlclRead(0x1008, 13)\n"
368 		    "TlclRead(0x1008, 13)\n",
369 		    "tlcl calls");
370 
371 	/* If the CRC is good and some noise happens, it should recover. */
372 	ResetMocks(0, 0);
373 	mock_rsk.struct_version = 2;
374 	mock_rsk.crc8 = Crc8(&mock_rsk, offsetof(RollbackSpaceKernel, crc8));
375 	noise_on[0] = 1;
376 	TEST_EQ(ReadSpaceKernel(&rsk), 0, "ReadSpaceKernel(), v2, good CRC");
377 	TEST_STR_EQ(mock_calls,
378 		    "TlclRead(0x1008, 13)\n"
379 		    "TlclRead(0x1008, 13)\n",
380 		    "tlcl calls");
381 
382 	/* A write with version < 2 should convert to v2 and create the CRC */
383 	ResetMocks(0, 0);
384 	Memset(&rsk, 0, sizeof(rsk));
385 	TEST_EQ(WriteSpaceKernel(&rsk), 0, "WriteSpaceKernel(), v0");
386 	TEST_EQ(mock_rsk.struct_version, 2, "WriteSpaceKernel(), check v2");
387 	TEST_STR_EQ(mock_calls,
388 		    "TlclWrite(0x1008, 13)\n"
389 		    "TlclRead(0x1008, 13)\n",
390 		    "tlcl calls");
391 
392 	/* Same as above, but with some noise during the readback */
393 	ResetMocks(0, 0);
394 	Memset(&rsk, 0, sizeof(rsk));
395 	noise_on[1] = 1;
396 	noise_on[2] = 1;
397 	TEST_EQ(WriteSpaceKernel(&rsk), 0, "WriteSpaceKernel(), read noise");
398 	TEST_STR_EQ(mock_calls,
399 		    "TlclWrite(0x1008, 13)\n"
400 		    "TlclRead(0x1008, 13)\n"
401 		    "TlclRead(0x1008, 13)\n"
402 		    "TlclRead(0x1008, 13)\n",
403 		    "tlcl calls");
404 
405 	/* With noise during the write, we'll try the write again */
406 	ResetMocks(0, 0);
407 	Memset(&rsk, 0, sizeof(rsk));
408 	noise_on[0] = 1;
409 	TEST_EQ(WriteSpaceKernel(&rsk), 0, "WriteSpaceKernel(), write noise");
410 	TEST_EQ(mock_rsk.struct_version, 2, "WriteSpaceKernel(), check v2");
411 	TEST_STR_EQ(mock_calls,
412 		    "TlclWrite(0x1008, 13)\n"
413 		    "TlclRead(0x1008, 13)\n"
414 		    "TlclRead(0x1008, 13)\n"
415 		    "TlclRead(0x1008, 13)\n"
416 		    "TlclWrite(0x1008, 13)\n"
417 		    "TlclRead(0x1008, 13)\n",
418 		    "tlcl calls");
419 
420 	/* Only if it just keeps on failing forever do we eventually give up */
421 	ResetMocks(0, 0);
422 	Memset(&rsk, 0, sizeof(rsk));
423 	Memset(noise_on, 1, sizeof(noise_on));
424 	TEST_EQ(WriteSpaceKernel(&rsk), TPM_E_CORRUPTED_STATE,
425 		"WriteSpaceKernel(), always noise");
426 	TEST_STR_EQ(mock_calls,
427 		    "TlclWrite(0x1008, 13)\n"
428 		    "TlclRead(0x1008, 13)\n"
429 		    "TlclRead(0x1008, 13)\n"
430 		    "TlclRead(0x1008, 13)\n"
431 		    "TlclWrite(0x1008, 13)\n"
432 		    "TlclRead(0x1008, 13)\n"
433 		    "TlclRead(0x1008, 13)\n"
434 		    "TlclRead(0x1008, 13)\n"
435 		    "TlclWrite(0x1008, 13)\n"
436 		    "TlclRead(0x1008, 13)\n"
437 		    "TlclRead(0x1008, 13)\n"
438 		    "TlclRead(0x1008, 13)\n",
439 		    "tlcl calls");
440 }
441 
442 /****************************************************************************/
443 /* Tests for misc helper functions */
444 
MiscTest(void)445 static void MiscTest(void)
446 {
447 	uint8_t buf[8];
448 
449 	ResetMocks(0, 0);
450 	TEST_EQ(TPMClearAndReenable(), 0, "TPMClearAndReenable()");
451 	TEST_STR_EQ(mock_calls,
452 		    "TlclForceClear()\n"
453 		    "TlclSetEnable()\n"
454 		    "TlclSetDeactivated(0)\n",
455 		    "tlcl calls");
456 
457 	ResetMocks(0, 0);
458 	TEST_EQ(SafeWrite(0x123, buf, 8), 0, "SafeWrite()");
459 	TEST_STR_EQ(mock_calls,
460 		    "TlclWrite(0x123, 8)\n",
461 		    "tlcl calls");
462 
463 	ResetMocks(1, TPM_E_BADINDEX);
464 	TEST_EQ(SafeWrite(0x123, buf, 8), TPM_E_BADINDEX, "SafeWrite() bad");
465 	TEST_STR_EQ(mock_calls,
466 		    "TlclWrite(0x123, 8)\n",
467 		    "tlcl calls");
468 
469 	ResetMocks(1, TPM_E_MAXNVWRITES);
470 	TEST_EQ(SafeWrite(0x123, buf, 8), 0, "SafeWrite() retry max writes");
471 	TEST_STR_EQ(mock_calls,
472 		    "TlclWrite(0x123, 8)\n"
473 		    "TlclForceClear()\n"
474 		    "TlclSetEnable()\n"
475 		    "TlclSetDeactivated(0)\n"
476 		    "TlclWrite(0x123, 8)\n",
477 		    "tlcl calls");
478 
479 	ResetMocks(0, 0);
480 	TEST_EQ(SafeDefineSpace(0x123, 6, 8), 0, "SafeDefineSpace()");
481 	TEST_STR_EQ(mock_calls,
482 		    "TlclDefineSpace(0x123, 0x6, 8)\n",
483 		    "tlcl calls");
484 
485 	ResetMocks(1, TPM_E_BADINDEX);
486 	TEST_EQ(SafeDefineSpace(0x123, 6, 8), TPM_E_BADINDEX,
487 		"SafeDefineSpace() bad");
488 	TEST_STR_EQ(mock_calls,
489 		    "TlclDefineSpace(0x123, 0x6, 8)\n",
490 		    "tlcl calls");
491 
492 	ResetMocks(1, TPM_E_MAXNVWRITES);
493 	TEST_EQ(SafeDefineSpace(0x123, 6, 8), 0,
494 		"SafeDefineSpace() retry max writes");
495 	TEST_STR_EQ(mock_calls,
496 		    "TlclDefineSpace(0x123, 0x6, 8)\n"
497 		    "TlclForceClear()\n"
498 		    "TlclSetEnable()\n"
499 		    "TlclSetDeactivated(0)\n"
500 		    "TlclDefineSpace(0x123, 0x6, 8)\n",
501 		    "tlcl calls");
502 }
503 
504 /****************************************************************************/
505 
506 /* Tests for one-time initialization */
OneTimeInitTest(void)507 static void OneTimeInitTest(void)
508 {
509 	RollbackSpaceFirmware rsf;
510 	RollbackSpaceKernel rsk;
511 
512 	/* Complete initialization */
513 	ResetMocks(0, 0);
514 	TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()");
515 	TEST_STR_EQ(mock_calls,
516 		    "TlclSelfTestFull()\n"
517 		    "TlclGetPermanentFlags()\n"
518 		    "TlclFinalizePhysicalPresence()\n"
519 		    "TlclSetNvLocked()\n"
520 		    "TlclForceClear()\n"
521 		    "TlclSetEnable()\n"
522 		    "TlclSetDeactivated(0)\n"
523 		    /* backup space */
524 		    "TlclDefineSpace(0x1009, 0x1, 16)\n"
525 		    /* kernel space */
526 		    "TlclDefineSpace(0x1008, 0x1, 13)\n"
527 		    "TlclWrite(0x1008, 13)\n"
528 		    "TlclRead(0x1008, 13)\n"
529 		    /* firmware space */
530 		    "TlclDefineSpace(0x1007, 0x8001, 10)\n"
531 		    "TlclWrite(0x1007, 10)\n"
532 		    "TlclRead(0x1007, 10)\n",
533 		    "tlcl calls");
534 	TEST_EQ(mock_rsf.struct_version, ROLLBACK_SPACE_FIRMWARE_VERSION,
535 		"rsf ver");
536 	TEST_EQ(mock_rsf.flags, 0, "rsf flags");
537 	TEST_EQ(mock_rsf.fw_versions, 0, "rsf fw_versions");
538 	TEST_EQ(mock_rsk.struct_version, ROLLBACK_SPACE_KERNEL_VERSION,
539 		"rsk ver");
540 	TEST_EQ(mock_rsk.uid, ROLLBACK_SPACE_KERNEL_UID, "rsk uid");
541 	TEST_EQ(mock_rsk.kernel_versions, 0, "rsk kernel_versions");
542 
543 	/* Physical presence already initialized */
544 	ResetMocks(0, 0);
545 	mock_pflags.physicalPresenceLifetimeLock = 1;
546 	TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()");
547 	TEST_STR_EQ(mock_calls,
548 		    "TlclSelfTestFull()\n"
549 		    "TlclGetPermanentFlags()\n"
550 		    "TlclSetNvLocked()\n"
551 		    "TlclForceClear()\n"
552 		    "TlclSetEnable()\n"
553 		    "TlclSetDeactivated(0)\n"
554 		    /* backup space */
555 		    "TlclDefineSpace(0x1009, 0x1, 16)\n"
556 		    /* kernel space */
557 		    "TlclDefineSpace(0x1008, 0x1, 13)\n"
558 		    "TlclWrite(0x1008, 13)\n"
559 		    "TlclRead(0x1008, 13)\n"
560 		    /* firmware space */
561 		    "TlclDefineSpace(0x1007, 0x8001, 10)\n"
562 		    "TlclWrite(0x1007, 10)\n"
563 		    "TlclRead(0x1007, 10)\n",
564 		    "tlcl calls");
565 
566 	/* NV locking already initialized */
567 	ResetMocks(0, 0);
568 	mock_pflags.nvLocked = 1;
569 	TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()");
570 	TEST_STR_EQ(mock_calls,
571 		    "TlclSelfTestFull()\n"
572 		    "TlclGetPermanentFlags()\n"
573 		    "TlclFinalizePhysicalPresence()\n"
574 		    "TlclForceClear()\n"
575 		    "TlclSetEnable()\n"
576 		    "TlclSetDeactivated(0)\n"
577 		    /* backup space */
578 		    "TlclDefineSpace(0x1009, 0x1, 16)\n"
579 		    /* kernel space */
580 		    "TlclDefineSpace(0x1008, 0x1, 13)\n"
581 		    "TlclWrite(0x1008, 13)\n"
582 		    "TlclRead(0x1008, 13)\n"
583 		    /* firmware space */
584 		    "TlclDefineSpace(0x1007, 0x8001, 10)\n"
585 		    "TlclWrite(0x1007, 10)\n"
586 		    "TlclRead(0x1007, 10)\n",
587 		    "tlcl calls");
588 
589 	/* Self test error */
590 	ResetMocks(1, TPM_E_IOERROR);
591 	TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), TPM_E_IOERROR,
592 		"OneTimeInitializeTPM() selftest");
593 	TEST_STR_EQ(mock_calls,
594 		    "TlclSelfTestFull()\n",
595 		    "tlcl calls");
596 }
597 
598 /****************************************************************************/
599 /* Tests for TPM setup */
600 
SetupTpmTest(void)601 static void SetupTpmTest(void)
602 {
603 	RollbackSpaceFirmware rsf;
604 
605 	/* Complete setup */
606 	ResetMocks(0, 0);
607 	TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM()");
608 	TEST_STR_EQ(mock_calls,
609 		    "TlclLibInit()\n"
610 		    "TlclStartup()\n"
611 		    "TlclAssertPhysicalPresence()\n"
612 		    "TlclGetPermanentFlags()\n"
613 		    "TlclRead(0x1007, 10)\n",
614 		    "tlcl calls");
615 
616 	/* If TPM is disabled or deactivated, must enable it */
617 	ResetMocks(0, 0);
618 	mock_pflags.disable = 1;
619 	TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_MUST_REBOOT,
620 		"SetupTPM() disabled");
621 	TEST_STR_EQ(mock_calls,
622 		    "TlclLibInit()\n"
623 		    "TlclStartup()\n"
624 		    "TlclAssertPhysicalPresence()\n"
625 		    "TlclGetPermanentFlags()\n"
626 		    "TlclSetEnable()\n"
627 		    "TlclSetDeactivated(0)\n",
628 		    "tlcl calls");
629 
630 	ResetMocks(0, 0);
631 	mock_pflags.deactivated = 1;
632 	TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_MUST_REBOOT,
633 		"SetupTPM() deactivated");
634 	TEST_STR_EQ(mock_calls,
635 		    "TlclLibInit()\n"
636 		    "TlclStartup()\n"
637 		    "TlclAssertPhysicalPresence()\n"
638 		    "TlclGetPermanentFlags()\n"
639 		    "TlclSetEnable()\n"
640 		    "TlclSetDeactivated(0)\n",
641 		    "tlcl calls");
642 
643 	/* If physical presence command isn't enabled, try to enable it */
644 	ResetMocks(3, TPM_E_IOERROR);
645 	TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() pp cmd");
646 	TEST_STR_EQ(mock_calls,
647 		    "TlclLibInit()\n"
648 		    "TlclStartup()\n"
649 		    "TlclAssertPhysicalPresence()\n"
650 		    "TlclPhysicalPresenceCMDEnable()\n"
651 		    "TlclAssertPhysicalPresence()\n"
652 		    "TlclGetPermanentFlags()\n"
653 		    "TlclRead(0x1007, 10)\n",
654 		    "tlcl calls");
655 
656 	/* If firmware space is missing, do one-time init */
657 	ResetMocks(5, TPM_E_BADINDEX);
658 	mock_pflags.physicalPresenceLifetimeLock = 1;
659 	mock_pflags.nvLocked = 1;
660 	TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() no firmware space");
661 	TEST_STR_EQ(mock_calls,
662 		    "TlclLibInit()\n"
663 		    "TlclStartup()\n"
664 		    "TlclAssertPhysicalPresence()\n"
665 		    "TlclGetPermanentFlags()\n"
666 		    "TlclRead(0x1007, 10)\n"
667 		    /* Calls from one-time init */
668 		    "TlclSelfTestFull()\n"
669 		    "TlclGetPermanentFlags()\n"
670 		    "TlclForceClear()\n"
671 		    "TlclSetEnable()\n"
672 		    "TlclSetDeactivated(0)\n"
673 		    /* backup space */
674 		    "TlclDefineSpace(0x1009, 0x1, 16)\n"
675 		    "TlclDefineSpace(0x1008, 0x1, 13)\n"
676 		    "TlclWrite(0x1008, 13)\n"
677 		    "TlclRead(0x1008, 13)\n"
678 		    "TlclDefineSpace(0x1007, 0x8001, 10)\n"
679 		    "TlclWrite(0x1007, 10)\n"
680 		    "TlclRead(0x1007, 10)\n",
681 		    "tlcl calls");
682 
683 	/* Other firmware space error is passed through */
684 	ResetMocks(5, TPM_E_IOERROR);
685 	TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_CORRUPTED_STATE,
686 		"SetupTPM() bad firmware space");
687 	TEST_STR_EQ(mock_calls,
688 		    "TlclLibInit()\n"
689 		    "TlclStartup()\n"
690 		    "TlclAssertPhysicalPresence()\n"
691 		    "TlclGetPermanentFlags()\n"
692 		    "TlclRead(0x1007, 10)\n",
693 		    "tlcl calls");
694 
695 	/* If developer flag has toggled, clear ownership and write new flag */
696 	ResetMocks(0, 0);
697 	TEST_EQ(SetupTPM(1, 0, 0, &rsf), 0, "SetupTPM() to dev");
698 	TEST_STR_EQ(mock_calls,
699 		    "TlclLibInit()\n"
700 		    "TlclStartup()\n"
701 		    "TlclAssertPhysicalPresence()\n"
702 		    "TlclGetPermanentFlags()\n"
703 		    "TlclRead(0x1007, 10)\n"
704 		    "TlclForceClear()\n"
705 		    "TlclSetEnable()\n"
706 		    "TlclSetDeactivated(0)\n"
707 		    "TlclWrite(0x1007, 10)\n"
708 		    "TlclRead(0x1007, 10)\n",
709 		    "tlcl calls");
710 	TEST_EQ(mock_rsf.flags, FLAG_LAST_BOOT_DEVELOPER,
711 		"fw space flags to dev 1");
712 
713 	ResetMocks(0, 0);
714 	mock_rsf.flags = FLAG_LAST_BOOT_DEVELOPER;
715 	TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() from dev");
716 	TEST_STR_EQ(mock_calls,
717 		    "TlclLibInit()\n"
718 		    "TlclStartup()\n"
719 		    "TlclAssertPhysicalPresence()\n"
720 		    "TlclGetPermanentFlags()\n"
721 		    "TlclRead(0x1007, 10)\n"
722 		    "TlclForceClear()\n"
723 		    "TlclSetEnable()\n"
724 		    "TlclSetDeactivated(0)\n"
725 		    "TlclWrite(0x1007, 10)\n"
726 		    "TlclRead(0x1007, 10)\n",
727 		    "tlcl calls");
728 	TEST_EQ(mock_rsf.flags, 0, "fw space flags from dev 1");
729 
730 	/* If TPM clear request, clear ownership also */
731 	ResetMocks(0, 0);
732 	TEST_EQ(SetupTPM(0, 0, 1, &rsf), 0, "SetupTPM() clear owner");
733 	TEST_STR_EQ(mock_calls,
734 		    "TlclLibInit()\n"
735 		    "TlclStartup()\n"
736 		    "TlclAssertPhysicalPresence()\n"
737 		    "TlclGetPermanentFlags()\n"
738 		    "TlclRead(0x1007, 10)\n"
739 		    "TlclForceClear()\n"
740 		    "TlclSetEnable()\n"
741 		    "TlclSetDeactivated(0)\n",
742 		    "tlcl calls");
743 
744 	/* Handle request to clear virtual dev switch */
745 	ResetMocks(0, 0);
746 	mock_rsf.flags = FLAG_VIRTUAL_DEV_MODE_ON | FLAG_LAST_BOOT_DEVELOPER;
747 	TEST_EQ(SetupTPM(0, 1, 0, &rsf), 0, "SetupTPM() clear virtual dev");
748 	TEST_EQ(mock_rsf.flags, 0, "Clear virtual dev");
749 
750 	/* If virtual dev switch is on, that should set last boot developer */
751 	ResetMocks(0, 0);
752 	mock_rsf.flags = FLAG_VIRTUAL_DEV_MODE_ON;
753 	SetupTPM(0, 0, 0, &rsf);
754 	TEST_EQ(mock_rsf.flags,
755 		FLAG_VIRTUAL_DEV_MODE_ON | FLAG_LAST_BOOT_DEVELOPER,
756 		"virtual dev sets last boot");
757 
758 	/*
759 	 * Note: SetupTPM() recovery_mode parameter sets a global flag in
760 	 * rollback_index.c; this is tested along with RollbackKernelLock()
761 	 * below.
762 	 */
763 }
764 
765 /****************************************************************************/
766 /* Tests for RollbackFirmware() calls */
767 
RollbackFirmwareTest(void)768 static void RollbackFirmwareTest(void)
769 {
770 	uint32_t version;
771 	int dev_mode;
772 
773 	/* Normal setup */
774 	ResetMocks(0, 0);
775 	dev_mode = 0;
776 	version = 123;
777 	mock_rsf.fw_versions = 0x12345678;
778 	TEST_EQ(RollbackFirmwareSetup(0, dev_mode, 0, &dev_mode, &version),
779 		0, "RollbackFirmwareSetup()");
780 	TEST_STR_EQ(mock_calls,
781 		    "TlclLibInit()\n"
782 		    "TlclStartup()\n"
783 		    "TlclAssertPhysicalPresence()\n"
784 		    "TlclGetPermanentFlags()\n"
785 		    "TlclRead(0x1007, 10)\n",
786 		    "tlcl calls");
787 	TEST_EQ(version, 0x12345678, "RollbackFirmwareSetup() version");
788 
789 	/* Error during setup should clear version */
790 	ResetMocks(1, TPM_E_IOERROR);
791 	dev_mode = 0;
792 	version = 123;
793 	mock_rsf.fw_versions = 0x12345678;
794 	TEST_EQ(RollbackFirmwareSetup(0, dev_mode, 0, &dev_mode, &version),
795 		TPM_E_IOERROR,
796 		"RollbackFirmwareSetup() error");
797 	TEST_STR_EQ(mock_calls,
798 		    "TlclLibInit()\n",
799 		    "tlcl calls");
800 	TEST_EQ(version, 0, "RollbackFirmwareSetup() version on error");
801 
802 	/* Developer mode flag gets passed properly */
803 	ResetMocks(0, 0);
804 	dev_mode = 1;
805 	TEST_EQ(RollbackFirmwareSetup(dev_mode, 0, 0, &dev_mode, &version),
806 		0, "RollbackFirmwareSetup() to dev");
807 	TEST_STR_EQ(mock_calls,
808 		    "TlclLibInit()\n"
809 		    "TlclStartup()\n"
810 		    "TlclAssertPhysicalPresence()\n"
811 		    "TlclGetPermanentFlags()\n"
812 		    "TlclRead(0x1007, 10)\n"
813 		    "TlclForceClear()\n"
814 		    "TlclSetEnable()\n"
815 		    "TlclSetDeactivated(0)\n"
816 		    "TlclWrite(0x1007, 10)\n"
817 		    "TlclRead(0x1007, 10)\n",
818 		    "tlcl calls");
819 	TEST_EQ(mock_rsf.flags, FLAG_LAST_BOOT_DEVELOPER,
820 		"fw space flags to dev 2");
821 
822 	/* So does clear-TPM request */
823 	ResetMocks(0, 0);
824 	dev_mode = 0;
825 	TEST_EQ(RollbackFirmwareSetup(dev_mode, 0, 1, &dev_mode, &version),
826 		0, "RollbackFirmwareSetup() clear owner");
827 	TEST_STR_EQ(mock_calls,
828 		    "TlclLibInit()\n"
829 		    "TlclStartup()\n"
830 		    "TlclAssertPhysicalPresence()\n"
831 		    "TlclGetPermanentFlags()\n"
832 		    "TlclRead(0x1007, 10)\n"
833 		    "TlclForceClear()\n"
834 		    "TlclSetEnable()\n"
835 		    "TlclSetDeactivated(0)\n",
836 		    "tlcl calls");
837 
838 	/* Test write */
839 	ResetMocks(0, 0);
840 	TEST_EQ(RollbackFirmwareWrite(0xBEAD1234), 0,
841 		"RollbackFirmwareWrite()");
842 	TEST_EQ(mock_rsf.fw_versions, 0xBEAD1234,
843 		"RollbackFirmwareWrite() version");
844 	TEST_STR_EQ(mock_calls,
845 		    "TlclRead(0x1007, 10)\n"
846 		    "TlclWrite(0x1007, 10)\n"
847 		    "TlclRead(0x1007, 10)\n",
848 		    "tlcl calls");
849 
850 	ResetMocks(1, TPM_E_IOERROR);
851 	TEST_EQ(RollbackFirmwareWrite(123), TPM_E_IOERROR,
852 		"RollbackFirmwareWrite() error");
853 
854 	/* Test setting virtual dev mode */
855 	ResetMocks(0, 0);
856 	TEST_EQ(SetVirtualDevMode(1), 0, "SetVirtualDevMode(1)");
857 	TEST_EQ(mock_rsf.flags, FLAG_VIRTUAL_DEV_MODE_ON, "Virtual dev on");
858 	TEST_STR_EQ(mock_calls,
859 		    "TlclRead(0x1007, 10)\n"
860 		    "TlclWrite(0x1007, 10)\n"
861 		    "TlclRead(0x1007, 10)\n",
862 		    "tlcl calls");
863 	ResetMocks(0, 0);
864 	TEST_EQ(SetVirtualDevMode(0), 0, "SetVirtualDevMode(0)");
865 	TEST_EQ(mock_rsf.flags, 0, "Virtual dev off");
866 	TEST_STR_EQ(mock_calls,
867 		    "TlclRead(0x1007, 10)\n"
868 		    "TlclWrite(0x1007, 10)\n"
869 		    "TlclRead(0x1007, 10)\n",
870 		    "tlcl calls");
871 
872 	/* Test lock */
873 	ResetMocks(0, 0);
874 	TEST_EQ(RollbackFirmwareLock(), 0, "RollbackFirmwareLock()");
875 	TEST_STR_EQ(mock_calls,
876 		    "TlclSetGlobalLock()\n",
877 		    "tlcl calls");
878 
879 	ResetMocks(1, TPM_E_IOERROR);
880 	TEST_EQ(RollbackFirmwareLock(), TPM_E_IOERROR,
881 		"RollbackFirmwareLock() error");
882 }
883 
884 /****************************************************************************/
885 /* Tests for RollbackKernel() calls */
886 
RollbackKernelTest(void)887 static void RollbackKernelTest(void)
888 {
889 	RollbackSpaceFirmware rsf;
890 	uint32_t version = 0;
891 
892 	/*
893 	 * RollbackKernel*() functions use a global flag inside
894 	 * rollback_index.c based on recovery mode, which is set by SetupTPM().
895 	 * Clear the flag for the first set of tests.
896 	 */
897 	TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM()");
898 
899 	/* Normal read */
900 	ResetMocks(0, 0);
901 	mock_rsk.uid = ROLLBACK_SPACE_KERNEL_UID;
902 	mock_permissions = TPM_NV_PER_PPWRITE;
903 	mock_rsk.kernel_versions = 0x87654321;
904 	TEST_EQ(RollbackKernelRead(&version), 0, "RollbackKernelRead()");
905 	TEST_STR_EQ(mock_calls,
906 		    "TlclRead(0x1008, 13)\n"
907 		    "TlclGetPermissions(0x1008)\n",
908 		    "tlcl calls");
909 	TEST_EQ(version, 0x87654321, "RollbackKernelRead() version");
910 
911 	/* Read error */
912 	ResetMocks(1, TPM_E_IOERROR);
913 	TEST_EQ(RollbackKernelRead(&version), TPM_E_IOERROR,
914 		"RollbackKernelRead() error");
915 	TEST_STR_EQ(mock_calls,
916 		    "TlclRead(0x1008, 13)\n",
917 		    "tlcl calls");
918 
919 	/* Wrong permission or UID will return error */
920 	ResetMocks(0, 0);
921 	mock_rsk.uid = ROLLBACK_SPACE_KERNEL_UID + 1;
922 	mock_permissions = TPM_NV_PER_PPWRITE;
923 	TEST_EQ(RollbackKernelRead(&version), TPM_E_CORRUPTED_STATE,
924 		"RollbackKernelRead() bad uid");
925 
926 	ResetMocks(0, 0);
927 	mock_rsk.uid = ROLLBACK_SPACE_KERNEL_UID;
928 	mock_permissions = TPM_NV_PER_PPWRITE + 1;
929 	TEST_EQ(RollbackKernelRead(&version), TPM_E_CORRUPTED_STATE,
930 		"RollbackKernelRead() bad permissions");
931 
932 	/* Test write */
933 	ResetMocks(0, 0);
934 	TEST_EQ(RollbackKernelWrite(0xBEAD4321), 0, "RollbackKernelWrite()");
935 	TEST_EQ(mock_rsk.kernel_versions, 0xBEAD4321,
936 		"RollbackKernelWrite() version");
937 	TEST_STR_EQ(mock_calls,
938 		    "TlclRead(0x1008, 13)\n"
939 		    "TlclWrite(0x1008, 13)\n"
940 		    "TlclRead(0x1008, 13)\n",
941 		    "tlcl calls");
942 
943 	ResetMocks(1, TPM_E_IOERROR);
944 	TEST_EQ(RollbackKernelWrite(123), TPM_E_IOERROR,
945 		"RollbackKernelWrite() error");
946 
947 	/* Test lock (recovery off) */
948 	ResetMocks(0, 0);
949 	TEST_EQ(RollbackKernelLock(0), 0, "RollbackKernelLock()");
950 	TEST_STR_EQ(mock_calls,
951 		    "TlclLockPhysicalPresence()\n",
952 		    "tlcl calls");
953 
954 	ResetMocks(1, TPM_E_IOERROR);
955 	TEST_EQ(RollbackKernelLock(0), TPM_E_IOERROR,
956 		"RollbackKernelLock() error");
957 
958 	/* Test lock with recovery on; shouldn't lock PP */
959 	SetupTPM(0, 0, 0, &rsf);
960 	ResetMocks(0, 0);
961 	TEST_EQ(RollbackKernelLock(1), 0, "RollbackKernelLock() in recovery");
962 	TEST_STR_EQ(mock_calls, "", "no tlcl calls");
963 }
964 
965 /* Tests for RollbackS3Resume() */
RollbackS3ResumeTest(void)966 static void RollbackS3ResumeTest(void)
967 {
968 	ResetMocks(0, 0);
969 	TEST_EQ(RollbackS3Resume(), 0, "RollbackS3Resume()");
970 	TEST_STR_EQ(mock_calls,
971 		    "TlclLibInit()\n"
972 		    "TlclResume()\n",
973 		    "tlcl calls");
974 
975 	/* Should ignore postinit error */
976 	ResetMocks(2, TPM_E_INVALID_POSTINIT);
977 	TEST_EQ(RollbackS3Resume(), 0, "RollbackS3Resume() postinit");
978 
979 	/* Resume with other error */
980 	ResetMocks(2, TPM_E_IOERROR);
981 	TEST_EQ(RollbackS3Resume(), TPM_E_IOERROR,
982 		"RollbackS3Resume() other error");
983 }
984 
main(int argc,char * argv[])985 int main(int argc, char* argv[])
986 {
987 	CrcTestFirmware();
988 	CrcTestKernel();
989 	MiscTest();
990 	OneTimeInitTest();
991 	SetupTpmTest();
992 	RollbackFirmwareTest();
993 	RollbackKernelTest();
994 	RollbackS3ResumeTest();
995 
996 	return gTestSuccess ? 0 : 255;
997 }
998