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 */
35static char mock_calls[16384];
36static 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 */
43static int mock_count = 0;
44static int fail_at_count = 0;
45static 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 */
49static int noise_count = 0;             /* read/write attempt (zero-based) */
50static int noise_on[MAX_NOISE_COUNT];   /* calls to inject noise on */
51
52/* Params / backing store for mocked Tlcl functions. */
53static TPM_PERMANENT_FLAGS mock_pflags;
54static RollbackSpaceFirmware mock_rsf;
55static RollbackSpaceKernel mock_rsk;
56static uint32_t mock_permissions;
57
58/* Reset the variables for the Tlcl mock functions. */
59static 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 */
77static 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
89uint32_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
95uint32_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
101uint32_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
107uint32_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
113uint32_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
119uint32_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
125uint32_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
145uint32_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
163uint32_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
170uint32_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
176uint32_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
182uint32_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
191uint32_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
197uint32_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
204uint32_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
210uint32_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
217uint32_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
223uint32_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
229uint32_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
239extern uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf);
240extern uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf);
241
242static 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
342extern uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk);
343extern uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk);
344
345static 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
445static 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 */
507static 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
601static 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
768static 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
887static 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() */
966static 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
985int 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