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 TPM lite library
6 */
7
8#include <stdint.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include <tss/tcs.h>
14/* Don't use the vboot constants, since they conflict with the TCS lib */
15#define VBOOT_REFERENCE_TSS_CONSTANTS_H_
16
17#include "host_common.h"
18#include "test_common.h"
19#include "tlcl.h"
20#include "tlcl_internal.h"
21#include "vboot_common.h"
22
23/* Mock data */
24static char debug_info[4096];
25static VbError_t mock_retval;
26
27/* Call to mocked VbExTpmSendReceive() */
28struct srcall
29{
30	const uint8_t *req;  /* Request */
31	uint8_t *rsp;  /* Response */
32	uint8_t rsp_buf[32];  /* Default response buffer, if not overridden */
33	int req_size;  /* Request size */
34	uint32_t req_cmd;  /* Request command code */
35	int rsp_size;  /* Response size */
36	VbError_t retval;  /* Value to return */
37};
38
39#define MAXCALLS 8
40static struct srcall calls[MAXCALLS];
41static int ncalls;
42
43/**
44 * Reset mock data (for use before each test)
45 */
46static void ResetMocks(void)
47{
48	int i;
49
50	*debug_info = 0;
51	mock_retval = VBERROR_SUCCESS;
52
53	memset(calls, 0, sizeof(calls));
54	for (i = 0; i < MAXCALLS; i++)
55		calls[i].rsp = calls[i].rsp_buf;
56	ncalls = 0;
57}
58
59/**
60 * Set response code and length for call <call_idx>.
61 */
62static void SetResponse(int call_idx, uint32_t response_code, int rsp_size)
63{
64	struct srcall *c = calls + call_idx;
65
66	c->rsp_size = rsp_size;
67	ToTpmUint32(c->rsp_buf + 6, response_code);
68}
69
70/* Mocks */
71
72VbError_t VbExTpmInit(void)
73{
74	return mock_retval;
75}
76
77
78VbError_t VbExTpmClose(void)
79{
80	return mock_retval;
81}
82
83VbError_t VbExTpmSendReceive(const uint8_t *request, uint32_t request_length,
84                             uint8_t *response, uint32_t *response_length)
85{
86	struct srcall *c = calls + ncalls++;
87
88	c->req = request;
89	c->req_size = request_length;
90
91	/* Parse out the command code */
92	FromTpmUint32(request + 6, &c->req_cmd);
93
94	// KLUDGE - remove
95	printf("TSR [%d] 0x%x\n", ncalls-1, c->req_cmd);
96
97	memset(response, 0, *response_length);
98	if (c->rsp_size)
99		memcpy(response, c->rsp, c->rsp_size);
100	*response_length = c->rsp_size;
101
102	return c->retval;
103}
104
105/**
106 * Test assorted tlcl functions
107 */
108static void TlclTest(void)
109{
110	uint8_t buf[32], buf2[32];
111
112	ResetMocks();
113	TEST_EQ(TlclLibInit(), VBERROR_SUCCESS, "Init");
114
115	ResetMocks();
116	mock_retval = VBERROR_SIMULATED;
117	TEST_EQ(TlclLibInit(), mock_retval, "Init bad");
118
119	ResetMocks();
120	TEST_EQ(TlclLibClose(), VBERROR_SUCCESS, "Close");
121
122	ResetMocks();
123	mock_retval = VBERROR_SIMULATED;
124	TEST_EQ(TlclLibClose(), mock_retval, "Close bad");
125
126	ResetMocks();
127	ToTpmUint32(buf + 2, 123);
128	TEST_EQ(TlclPacketSize(buf), 123, "TlclPacketSize");
129
130	ResetMocks();
131	ToTpmUint32(buf + 2, 10);
132	TEST_EQ(TlclSendReceive(buf, buf2, sizeof(buf2)), 0, "SendReceive");
133	TEST_PTR_EQ(calls[0].req, buf, "SendReceive req ptr");
134	TEST_EQ(calls[0].req_size, 10, "SendReceive size");
135
136	ResetMocks();
137	calls[0].retval = VBERROR_SIMULATED;
138	ToTpmUint32(buf + 2, 10);
139	TEST_EQ(TlclSendReceive(buf, buf2, sizeof(buf2)), VBERROR_SIMULATED,
140		"SendReceive fail");
141
142	ResetMocks();
143	SetResponse(0, 123, 10);
144	ToTpmUint32(buf + 2, 10);
145	TEST_EQ(TlclSendReceive(buf, buf2, sizeof(buf2)), 123,
146		"SendReceive error response");
147
148	// TODO: continue self test (if needed or doing)
149	// TODO: then retry doing self test
150
151}
152
153
154/**
155 * Test send-command functions
156 */
157static void SendCommandTest(void)
158{
159	ResetMocks();
160	TEST_EQ(TlclStartup(), 0, "SaveState");
161	TEST_EQ(calls[0].req_cmd, TPM_ORD_Startup, "  cmd");
162
163	ResetMocks();
164	TEST_EQ(TlclSaveState(), 0, "SaveState");
165	TEST_EQ(calls[0].req_cmd, TPM_ORD_SaveState, "  cmd");
166
167	ResetMocks();
168	TEST_EQ(TlclResume(), 0, "Resume");
169	TEST_EQ(calls[0].req_cmd, TPM_ORD_Startup, "  cmd");
170
171	ResetMocks();
172	TEST_EQ(TlclSelfTestFull(), 0, "SelfTestFull");
173	TEST_EQ(calls[0].req_cmd, TPM_ORD_SelfTestFull, "  cmd");
174
175	ResetMocks();
176	TEST_EQ(TlclContinueSelfTest(), 0, "ContinueSelfTest");
177	TEST_EQ(calls[0].req_cmd, TPM_ORD_ContinueSelfTest, "  cmd");
178
179	ResetMocks();
180	TEST_EQ(TlclAssertPhysicalPresence(), 0,
181		"AssertPhysicalPresence");
182	TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, "  cmd");
183
184	ResetMocks();
185	TEST_EQ(TlclPhysicalPresenceCMDEnable(), 0,
186		"PhysicalPresenceCMDEnable");
187	TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, "  cmd");
188
189	ResetMocks();
190	TEST_EQ(TlclFinalizePhysicalPresence(), 0,
191		"FinalizePhysicalPresence");
192	TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, "  cmd");
193
194	ResetMocks();
195	TEST_EQ(TlclAssertPhysicalPresenceResult(), 0,
196		"AssertPhysicalPresenceResult");
197	TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, "  cmd");
198
199	ResetMocks();
200	TEST_EQ(TlclLockPhysicalPresence(), 0,
201		"LockPhysicalPresence");
202	TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, "  cmd");
203
204	ResetMocks();
205	TEST_EQ(TlclIsOwned(), 0, "IsOwned");
206	TEST_EQ(calls[0].req_cmd, TPM_ORD_ReadPubek, "  cmd");
207	ResetMocks();
208	calls[0].retval = VBERROR_SIMULATED;
209	TEST_NEQ(TlclIsOwned(), 0, "IsOwned");
210
211	ResetMocks();
212	TEST_EQ(TlclForceClear(), 0, "ForceClear");
213	TEST_EQ(calls[0].req_cmd, TPM_ORD_ForceClear, "  cmd");
214
215	ResetMocks();
216	TEST_EQ(TlclSetEnable(), 0, "SetEnable");
217	TEST_EQ(calls[0].req_cmd, TPM_ORD_PhysicalEnable, "  cmd");
218
219	ResetMocks();
220	TEST_EQ(TlclClearEnable(), 0, "ClearEnable");
221	TEST_EQ(calls[0].req_cmd, TPM_ORD_PhysicalDisable, "  cmd");
222
223	ResetMocks();
224	TEST_EQ(TlclSetDeactivated(0), 0, "SetDeactivated");
225	TEST_EQ(calls[0].req_cmd, TPM_ORD_PhysicalSetDeactivated, "  cmd");
226}
227
228/**
229 * NV spaces test
230 *
231 * TODO: check params/data read/written.
232 */
233static void ReadWriteTest(void)
234{
235	uint8_t buf[32];
236
237	ResetMocks();
238	TEST_EQ(TlclDefineSpace(1, 2, 3), 0, "DefineSpace");
239	TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_DefineSpace, "  cmd");
240
241	ResetMocks();
242	TEST_EQ(TlclSetNvLocked(), 0, "SetNvLocked");
243	TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_DefineSpace, "  cmd");
244
245	ResetMocks();
246	TEST_EQ(TlclWrite(1, buf, 3), 0, "Write");
247	TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_WriteValue, "  cmd");
248
249	ResetMocks();
250	TEST_EQ(TlclRead(1, buf, 3), 0, "Read");
251	TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_ReadValue, "  cmd");
252
253	ResetMocks();
254	TEST_EQ(TlclWriteLock(1), 0, "WriteLock");
255	TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_WriteValue, "  cmd");
256
257	ResetMocks();
258	TEST_EQ(TlclReadLock(1), 0, "ReadLock");
259	TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_ReadValue, "  cmd");
260
261	ResetMocks();
262	TEST_EQ(TlclSetGlobalLock(), 0, "SetGlobalLock");
263	TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_WriteValue, "  cmd");
264}
265
266/**
267 * Test PCR funcs
268 *
269 * TODO: check params/data read/written.
270 */
271static void PcrTest(void)
272{
273	uint8_t buf[kPcrDigestLength], buf2[kPcrDigestLength];
274
275	ResetMocks();
276	TEST_EQ(TlclPCRRead(1, buf, kPcrDigestLength), 0, "PCRRead");
277	TEST_EQ(calls[0].req_cmd, TPM_ORD_PcrRead, "  cmd");
278
279	ResetMocks();
280	TEST_EQ(TlclPCRRead(1, buf, kPcrDigestLength - 1), TPM_E_IOERROR,
281		"PCRRead too small");
282
283	ResetMocks();
284	TEST_EQ(TlclExtend(1, buf, buf2), 0, "Extend");
285	TEST_EQ(calls[0].req_cmd, TPM_ORD_Extend, "  cmd");
286}
287
288/**
289 * Test flags / capabilities
290 *
291 * TODO: check params/data read/written.
292 */
293static void FlagsTest(void)
294{
295	TPM_PERMANENT_FLAGS pflags;
296	TPM_STCLEAR_FLAGS vflags;
297	uint8_t disable = 0, deactivated = 0, nvlocked = 0;
298	uint32_t u;
299	uint8_t buf[32];
300
301	ResetMocks();
302	TEST_EQ(TlclGetPermanentFlags(&pflags), 0, "GetPermanentFlags");
303	TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, "  cmd");
304
305	ResetMocks();
306	TEST_EQ(TlclGetSTClearFlags(&vflags), 0, "GetSTClearFlags");
307	TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, "  cmd");
308
309	ResetMocks();
310	TEST_EQ(TlclGetFlags(NULL, NULL, NULL), 0, "GetFlags NULL");
311	TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, "  cmd");
312	ResetMocks();
313	TEST_EQ(TlclGetFlags(&disable, &deactivated, &nvlocked), 0, "GetFlags");
314
315	ResetMocks();
316	TEST_EQ(TlclGetPermissions(1, &u), 0, "GetPermissions");
317	TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, "  cmd");
318
319	ResetMocks();
320	TEST_EQ(TlclGetOwnership(buf), 0, "GetOwnership");
321	TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, "  cmd");
322}
323
324/**
325 * Test random
326 *
327 * TODO: check params/data read/written.
328 * TODO: check overflow tests.
329 */
330static void RandomTest(void)
331{
332	uint8_t buf[32];
333	uint32_t size;
334
335	ResetMocks();
336	size = sizeof(buf);
337	TEST_EQ(TlclGetRandom(buf, sizeof(buf), &size), 0, "GetRandom");
338	TEST_EQ(calls[0].req_cmd, TPM_ORD_GetRandom, "  cmd");
339	TEST_EQ(size, 0, "  size 0");
340}
341
342int main(void)
343{
344	TlclTest();
345	SendCommandTest();
346	ReadWriteTest();
347	PcrTest();
348	FlagsTest();
349	RandomTest();
350
351	return gTestSuccess ? 0 : 255;
352}
353