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