1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2015 Google, Inc
4 */
5
6#include <common.h>
7#include <command.h>
8#include <cpu_func.h>
9#include <log.h>
10#include <tpm-v1.h>
11#include <linux/printk.h>
12#include "tpm-user-utils.h"
13#include <tpm_api.h>
14
15/* Prints error and returns on failure */
16#define TPM_CHECK(tpm_command) do { \
17	uint32_t result; \
18	\
19	result = (tpm_command); \
20	if (result != TPM_SUCCESS) { \
21		printf("TEST FAILED: line %d: " #tpm_command ": 0x%x\n", \
22			__LINE__, result); \
23		return result; \
24	} \
25} while (0)
26
27#define INDEX0			0xda70
28#define INDEX1			0xda71
29#define INDEX2			0xda72
30#define INDEX3			0xda73
31#define INDEX_INITIALISED	0xda80
32#define PHYS_PRESENCE		4
33#define PRESENCE		8
34
35static uint32_t TlclStartupIfNeeded(struct udevice *dev)
36{
37	uint32_t result = tpm_startup(dev, TPM_ST_CLEAR);
38
39	return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result;
40}
41
42static int test_timer(struct udevice *dev)
43{
44	printf("get_timer(0) = %lu\n", get_timer(0));
45	return 0;
46}
47
48static uint32_t tpm_get_flags(struct udevice *dev, uint8_t *disable,
49			      uint8_t *deactivated, uint8_t *nvlocked)
50{
51	struct tpm_permanent_flags pflags;
52	uint32_t result;
53
54	result = tpm1_get_permanent_flags(dev, &pflags);
55	if (result)
56		return result;
57	if (disable)
58		*disable = pflags.disable;
59	if (deactivated)
60		*deactivated = pflags.deactivated;
61	if (nvlocked)
62		*nvlocked = pflags.nv_locked;
63	debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n",
64	      pflags.disable, pflags.deactivated, pflags.nv_locked);
65
66	return 0;
67}
68
69static uint32_t tpm_nv_write_value_lock(struct udevice *dev, uint32_t index)
70{
71	debug("TPM: Write lock 0x%x\n", index);
72
73	return tpm_nv_write_value(dev, index, NULL, 0);
74}
75
76static int tpm_is_owned(struct udevice *dev)
77{
78	uint8_t response[TPM_PUBEK_SIZE];
79	uint32_t result;
80
81	result = tpm_read_pubek(dev, response, sizeof(response));
82
83	return result != TPM_SUCCESS;
84}
85
86static int test_early_extend(struct udevice *dev)
87{
88	uint8_t value_in[20];
89	uint8_t value_out[20];
90
91	printf("Testing earlyextend ...");
92	tpm_init(dev);
93	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
94	TPM_CHECK(tpm_continue_self_test(dev));
95	TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, sizeof(value_in), value_out,
96				 "test"));
97	printf("done\n");
98	return 0;
99}
100
101static int test_early_nvram(struct udevice *dev)
102{
103	uint32_t x;
104
105	printf("Testing earlynvram ...");
106	tpm_init(dev);
107	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
108	TPM_CHECK(tpm_continue_self_test(dev));
109	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
110	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
111	printf("done\n");
112	return 0;
113}
114
115static int test_early_nvram2(struct udevice *dev)
116{
117	uint32_t x;
118
119	printf("Testing earlynvram2 ...");
120	tpm_init(dev);
121	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
122	TPM_CHECK(tpm_continue_self_test(dev));
123	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
124	TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
125	printf("done\n");
126	return 0;
127}
128
129static int test_enable(struct udevice *dev)
130{
131	uint8_t disable = 0, deactivated = 0;
132
133	printf("Testing enable ...\n");
134	tpm_init(dev);
135	TPM_CHECK(TlclStartupIfNeeded(dev));
136	TPM_CHECK(tpm_self_test_full(dev));
137	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
138	TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
139	printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
140	TPM_CHECK(tpm_physical_enable(dev));
141	TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
142	TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
143	printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
144	if (disable == 1 || deactivated == 1)
145		printf("\tfailed to enable or activate\n");
146	printf("\tdone\n");
147	return 0;
148}
149
150#define reboot() do { \
151	printf("\trebooting...\n"); \
152	reset_cpu(); \
153} while (0)
154
155static int test_fast_enable(struct udevice *dev)
156{
157	uint8_t disable = 0, deactivated = 0;
158	int i;
159
160	printf("Testing fastenable ...\n");
161	tpm_init(dev);
162	TPM_CHECK(TlclStartupIfNeeded(dev));
163	TPM_CHECK(tpm_self_test_full(dev));
164	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
165	TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
166	printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
167	for (i = 0; i < 2; i++) {
168		TPM_CHECK(tpm_force_clear(dev));
169		TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
170		printf("\tdisable is %d, deactivated is %d\n", disable,
171		       deactivated);
172		assert(disable == 1 && deactivated == 1);
173		TPM_CHECK(tpm_physical_enable(dev));
174		TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
175		TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
176		printf("\tdisable is %d, deactivated is %d\n", disable,
177		       deactivated);
178		assert(disable == 0 && deactivated == 0);
179	}
180	printf("\tdone\n");
181	return 0;
182}
183
184static int test_global_lock(struct udevice *dev)
185{
186	uint32_t zero = 0;
187	uint32_t result;
188	uint32_t x;
189
190	printf("Testing globallock ...\n");
191	tpm_init(dev);
192	TPM_CHECK(TlclStartupIfNeeded(dev));
193	TPM_CHECK(tpm_self_test_full(dev));
194	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
195	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
196	TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero,
197				     sizeof(uint32_t)));
198	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
199	TPM_CHECK(tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero,
200				     sizeof(uint32_t)));
201	TPM_CHECK(tpm_set_global_lock(dev));
202	/* Verifies that write to index0 fails */
203	x = 1;
204	result = tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x));
205	assert(result == TPM_AREA_LOCKED);
206	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
207	assert(x == 0);
208	/* Verifies that write to index1 is still possible */
209	x = 2;
210	TPM_CHECK(tpm_nv_write_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
211	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
212	assert(x == 2);
213	/* Turns off PP */
214	tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
215	/* Verifies that write to index1 fails */
216	x = 3;
217	result = tpm_nv_write_value(dev, INDEX1, (uint8_t *)&x, sizeof(x));
218	assert(result == TPM_BAD_PRESENCE);
219	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
220	assert(x == 2);
221	printf("\tdone\n");
222	return 0;
223}
224
225static int test_lock(struct udevice *dev)
226{
227	printf("Testing lock ...\n");
228	tpm_init(dev);
229	tpm_startup(dev, TPM_ST_CLEAR);
230	tpm_self_test_full(dev);
231	tpm_tsc_physical_presence(dev, PRESENCE);
232	tpm_nv_write_value_lock(dev, INDEX0);
233	printf("\tLocked 0x%x\n", INDEX0);
234	printf("\tdone\n");
235	return 0;
236}
237
238static void initialise_spaces(struct udevice *dev)
239{
240	uint32_t zero = 0;
241	uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
242
243	printf("\tInitialising spaces\n");
244	tpm1_nv_set_locked(dev);  /* useful only the first time */
245	tpm1_nv_define_space(dev, INDEX0, perm, 4);
246	tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero, 4);
247	tpm1_nv_define_space(dev, INDEX1, perm, 4);
248	tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero, 4);
249	tpm1_nv_define_space(dev, INDEX2, perm, 4);
250	tpm_nv_write_value(dev, INDEX2, (uint8_t *)&zero, 4);
251	tpm1_nv_define_space(dev, INDEX3, perm, 4);
252	tpm_nv_write_value(dev, INDEX3, (uint8_t *)&zero, 4);
253	perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
254		TPM_NV_PER_PPWRITE;
255	tpm1_nv_define_space(dev, INDEX_INITIALISED, perm, 1);
256}
257
258static int test_readonly(struct udevice *dev)
259{
260	uint8_t c;
261	uint32_t index_0, index_1, index_2, index_3;
262	int read0, read1, read2, read3;
263
264	printf("Testing readonly ...\n");
265	tpm_init(dev);
266	tpm_startup(dev, TPM_ST_CLEAR);
267	tpm_self_test_full(dev);
268	tpm_tsc_physical_presence(dev, PRESENCE);
269	/*
270	 * Checks if initialisation has completed by trying to read-lock a
271	 * space that's created at the end of initialisation
272	 */
273	if (tpm_nv_read_value(dev, INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) {
274		/* The initialisation did not complete */
275		initialise_spaces(dev);
276	}
277
278	/* Checks if spaces are OK or messed up */
279	read0 = tpm_nv_read_value(dev, INDEX0, (uint8_t *)&index_0,
280				  sizeof(index_0));
281	read1 = tpm_nv_read_value(dev, INDEX1, (uint8_t *)&index_1,
282				  sizeof(index_1));
283	read2 = tpm_nv_read_value(dev, INDEX2, (uint8_t *)&index_2,
284				  sizeof(index_2));
285	read3 = tpm_nv_read_value(dev, INDEX3, (uint8_t *)&index_3,
286				  sizeof(index_3));
287	if (read0 || read1 || read2 || read3) {
288		printf("Invalid contents\n");
289		return 0;
290	}
291
292	/*
293	 * Writes space, and locks it.  Then attempts to write again.
294	 * I really wish I could use the imperative.
295	 */
296	index_0 += 1;
297	if (tpm_nv_write_value(dev, INDEX0, (uint8_t *)&index_0,
298			       sizeof(index_0)) !=
299		TPM_SUCCESS) {
300		pr_err("\tcould not write index 0\n");
301	}
302	tpm_nv_write_value_lock(dev, INDEX0);
303	if (tpm_nv_write_value(dev, INDEX0, (uint8_t *)&index_0,
304			       sizeof(index_0)) ==
305			TPM_SUCCESS)
306		pr_err("\tindex 0 is not locked\n");
307
308	printf("\tdone\n");
309	return 0;
310}
311
312static int test_redefine_unowned(struct udevice *dev)
313{
314	uint32_t perm;
315	uint32_t result;
316	uint32_t x;
317
318	printf("Testing redefine_unowned ...");
319	tpm_init(dev);
320	TPM_CHECK(TlclStartupIfNeeded(dev));
321	TPM_CHECK(tpm_self_test_full(dev));
322	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
323	assert(!tpm_is_owned(dev));
324
325	/* Ensures spaces exist. */
326	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
327	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
328
329	/* Redefines spaces a couple of times. */
330	perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
331	TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm,
332				       2 * sizeof(uint32_t)));
333	TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)));
334	perm = TPM_NV_PER_PPWRITE;
335	TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm,
336				       2 * sizeof(uint32_t)));
337	TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
338
339	/* Sets the global lock */
340	tpm_set_global_lock(dev);
341
342	/* Verifies that index0 cannot be redefined */
343	result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
344	assert(result == TPM_AREA_LOCKED);
345
346	/* Checks that index1 can */
347	TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm,
348				       2 * sizeof(uint32_t)));
349	TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
350
351	/* Turns off PP */
352	tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
353
354	/* Verifies that neither index0 nor index1 can be redefined */
355	result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
356	assert(result == TPM_BAD_PRESENCE);
357	result = tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t));
358	assert(result == TPM_BAD_PRESENCE);
359
360	printf("done\n");
361	return 0;
362}
363
364#define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK)
365#define PERMPP TPM_NV_PER_PPWRITE
366
367static int test_space_perm(struct udevice *dev)
368{
369	uint32_t perm;
370
371	printf("Testing spaceperm ...");
372	tpm_init(dev);
373	TPM_CHECK(TlclStartupIfNeeded(dev));
374	TPM_CHECK(tpm_continue_self_test(dev));
375	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
376	TPM_CHECK(tpm_get_permissions(dev, INDEX0, &perm));
377	assert((perm & PERMPPGL) == PERMPPGL);
378	TPM_CHECK(tpm_get_permissions(dev, INDEX1, &perm));
379	assert((perm & PERMPP) == PERMPP);
380	printf("done\n");
381	return 0;
382}
383
384static int test_startup(struct udevice *dev)
385{
386	uint32_t result;
387
388	printf("Testing startup ...\n");
389
390	tpm_init(dev);
391	result = tpm_startup(dev, TPM_ST_CLEAR);
392	if (result != 0 && result != TPM_INVALID_POSTINIT)
393		printf("\ttpm startup failed with 0x%x\n", result);
394	result = tpm_get_flags(dev, NULL, NULL, NULL);
395	if (result != 0)
396		printf("\ttpm getflags failed with 0x%x\n", result);
397	printf("\texecuting SelfTestFull\n");
398	tpm_self_test_full(dev);
399	result = tpm_get_flags(dev, NULL, NULL, NULL);
400	if (result != 0)
401		printf("\ttpm getflags failed with 0x%x\n", result);
402	printf("\tdone\n");
403	return 0;
404}
405
406/*
407 * Runs [op] and ensures it returns success and doesn't run longer than
408 * [time_limit] in milliseconds.
409 */
410#define TTPM_CHECK(op, time_limit) do { \
411	ulong start, time; \
412	uint32_t __result; \
413	\
414	start = get_timer(0); \
415	__result = op; \
416	if (__result != TPM_SUCCESS) { \
417		printf("\t" #op ": error 0x%x\n", __result); \
418		return -1; \
419	} \
420	time = get_timer(start); \
421	printf("\t" #op ": %lu ms\n", time); \
422	if (time > (ulong)time_limit) { \
423		printf("\t" #op " exceeded " #time_limit " ms\n"); \
424	} \
425} while (0)
426
427
428static int test_timing(struct udevice *dev)
429{
430	uint8_t in[20], out[20];
431	uint32_t x;
432
433	printf("Testing timing ...");
434	tpm_init(dev);
435	TTPM_CHECK(TlclStartupIfNeeded(dev), 50);
436	TTPM_CHECK(tpm_continue_self_test(dev), 100);
437	TTPM_CHECK(tpm_self_test_full(dev), 1000);
438	TTPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE), 100);
439	TTPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
440		   100);
441	TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
442		   100);
443	TTPM_CHECK(tpm_pcr_extend(dev, 0, in, sizeof(in), out, "test"), 200);
444	TTPM_CHECK(tpm_set_global_lock(dev), 50);
445	TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100);
446	printf("done\n");
447	return 0;
448}
449
450#define TPM_MAX_NV_WRITES_NOOWNER 64
451
452static int test_write_limit(struct udevice *dev)
453{
454	uint32_t result;
455	int i;
456
457	printf("Testing writelimit ...\n");
458	tpm_init(dev);
459	TPM_CHECK(TlclStartupIfNeeded(dev));
460	TPM_CHECK(tpm_self_test_full(dev));
461	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
462	TPM_CHECK(tpm_force_clear(dev));
463	TPM_CHECK(tpm_physical_enable(dev));
464	TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
465
466	for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
467		printf("\twriting %d\n", i);
468		result = tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i,
469					    sizeof(i));
470		switch (result) {
471		case TPM_SUCCESS:
472			break;
473		case TPM_MAXNVWRITES:
474			assert(i >= TPM_MAX_NV_WRITES_NOOWNER);
475			break;
476		default:
477			pr_err("\tunexpected error code %d (0x%x)\n",
478			      result, result);
479		}
480	}
481
482	/* Reset write count */
483	TPM_CHECK(tpm_force_clear(dev));
484	TPM_CHECK(tpm_physical_enable(dev));
485	TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
486
487	/* Try writing again. */
488	TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i, sizeof(i)));
489	printf("\tdone\n");
490	return 0;
491}
492
493#define VOIDTEST(XFUNC) \
494	int do_test_##XFUNC(struct cmd_tbl *cmd_tbl, int flag, int argc, \
495	char *const argv[]) \
496	{ \
497		struct udevice *dev; \
498		int ret; \
499\
500		ret = get_tpm(&dev); \
501		if (ret) \
502			return ret; \
503		return test_##XFUNC(dev); \
504	}
505
506#define VOIDENT(XNAME) \
507	U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""),
508
509VOIDTEST(early_extend)
510VOIDTEST(early_nvram)
511VOIDTEST(early_nvram2)
512VOIDTEST(enable)
513VOIDTEST(fast_enable)
514VOIDTEST(global_lock)
515VOIDTEST(lock)
516VOIDTEST(readonly)
517VOIDTEST(redefine_unowned)
518VOIDTEST(space_perm)
519VOIDTEST(startup)
520VOIDTEST(timing)
521VOIDTEST(write_limit)
522VOIDTEST(timer)
523
524static struct cmd_tbl cmd_cros_tpm_sub[] = {
525	VOIDENT(early_extend)
526	VOIDENT(early_nvram)
527	VOIDENT(early_nvram2)
528	VOIDENT(enable)
529	VOIDENT(fast_enable)
530	VOIDENT(global_lock)
531	VOIDENT(lock)
532	VOIDENT(readonly)
533	VOIDENT(redefine_unowned)
534	VOIDENT(space_perm)
535	VOIDENT(startup)
536	VOIDENT(timing)
537	VOIDENT(write_limit)
538	VOIDENT(timer)
539};
540
541static int do_tpmtest(struct cmd_tbl *cmdtp, int flag, int argc,
542		      char *const argv[])
543{
544	struct cmd_tbl *c;
545	int i;
546
547	printf("argc = %d, argv = ", argc);
548
549	for (i = 0; i < argc; i++)
550		printf(" %s", argv[i]);
551
552	printf("\n------\n");
553
554	argc--;
555	argv++;
556	c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub,
557			 ARRAY_SIZE(cmd_cros_tpm_sub));
558	return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp);
559}
560
561U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests",
562	"\n\tearly_extend\n"
563	"\tearly_nvram\n"
564	"\tearly_nvram2\n"
565	"\tenable\n"
566	"\tfast_enable\n"
567	"\tglobal_lock\n"
568	"\tlock\n"
569	"\treadonly\n"
570	"\tredefine_unowned\n"
571	"\tspace_perm\n"
572	"\tstartup\n"
573	"\ttiming\n"
574	"\twrite_limit\n");
575