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 */
24 static char debug_info[4096];
25 static VbError_t mock_retval;
26 
27 /* Call to mocked VbExTpmSendReceive() */
28 struct 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
40 static struct srcall calls[MAXCALLS];
41 static int ncalls;
42 
43 /**
44  * Reset mock data (for use before each test)
45  */
ResetMocks(void)46 static 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  */
SetResponse(int call_idx,uint32_t response_code,int rsp_size)62 static 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 
VbExTpmInit(void)72 VbError_t VbExTpmInit(void)
73 {
74 	return mock_retval;
75 }
76 
77 
VbExTpmClose(void)78 VbError_t VbExTpmClose(void)
79 {
80 	return mock_retval;
81 }
82 
VbExTpmSendReceive(const uint8_t * request,uint32_t request_length,uint8_t * response,uint32_t * response_length)83 VbError_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  */
TlclTest(void)108 static 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  */
SendCommandTest(void)157 static 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  */
ReadWriteTest(void)233 static 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  */
PcrTest(void)271 static 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  */
FlagsTest(void)293 static 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  */
RandomTest(void)330 static 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 
main(void)342 int main(void)
343 {
344 	TlclTest();
345 	SendCommandTest();
346 	ReadWriteTest();
347 	PcrTest();
348 	FlagsTest();
349 	RandomTest();
350 
351 	return gTestSuccess ? 0 : 255;
352 }
353