]> Git Repo - J-u-boot.git/blob - cmd/tpm_test.c
Subtree merge tag 'v6.12-dts' of dts repo [1] into dts/upstream
[J-u-boot.git] / cmd / tpm_test.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2015 Google, Inc
4  */
5
6 #include <command.h>
7 #include <cpu_func.h>
8 #include <log.h>
9 #include <time.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
35 static 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
42 static int test_timer(struct udevice *dev)
43 {
44         printf("get_timer(0) = %lu\n", get_timer(0));
45         return 0;
46 }
47
48 static 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
69 static 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
76 static 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
86 static 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
101 static 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
115 static 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
129 static 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
155 static 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
184 static 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
225 static 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
238 static 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
258 static 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
312 static 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
367 static 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
384 static 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 static int test_timing(struct udevice *dev)
428 {
429         uint8_t in[20], out[20];
430         uint32_t x;
431
432         printf("Testing timing ...");
433         tpm_init(dev);
434         TTPM_CHECK(TlclStartupIfNeeded(dev), 50);
435         TTPM_CHECK(tpm_continue_self_test(dev), 100);
436         TTPM_CHECK(tpm_self_test_full(dev), 1000);
437         TTPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE), 100);
438         TTPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
439                    100);
440         TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
441                    100);
442         TTPM_CHECK(tpm_pcr_extend(dev, 0, in, sizeof(in), out, "test"), 200);
443         TTPM_CHECK(tpm_set_global_lock(dev), 50);
444         TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100);
445         printf("done\n");
446         return 0;
447 }
448
449 #define TPM_MAX_NV_WRITES_NOOWNER 64
450
451 static int test_write_limit(struct udevice *dev)
452 {
453         uint32_t result;
454         int i;
455
456         printf("Testing writelimit ...\n");
457         tpm_init(dev);
458         TPM_CHECK(TlclStartupIfNeeded(dev));
459         TPM_CHECK(tpm_self_test_full(dev));
460         TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
461         TPM_CHECK(tpm_force_clear(dev));
462         TPM_CHECK(tpm_physical_enable(dev));
463         TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
464
465         for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
466                 printf("\twriting %d\n", i);
467                 result = tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i,
468                                             sizeof(i));
469                 switch (result) {
470                 case TPM_SUCCESS:
471                         break;
472                 case TPM_MAXNVWRITES:
473                         assert(i >= TPM_MAX_NV_WRITES_NOOWNER);
474                         break;
475                 default:
476                         pr_err("\tunexpected error code %d (0x%x)\n",
477                               result, result);
478                 }
479         }
480
481         /* Reset write count */
482         TPM_CHECK(tpm_force_clear(dev));
483         TPM_CHECK(tpm_physical_enable(dev));
484         TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
485
486         /* Try writing again. */
487         TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i, sizeof(i)));
488         printf("\tdone\n");
489         return 0;
490 }
491
492 #define VOIDTEST(XFUNC) \
493         int do_test_##XFUNC(struct cmd_tbl *cmd_tbl, int flag, int argc, \
494         char *const argv[]) \
495         { \
496                 struct udevice *dev; \
497                 int ret; \
498 \
499                 ret = get_tpm(&dev); \
500                 if (ret) \
501                         return ret; \
502                 return test_##XFUNC(dev); \
503         }
504
505 #define VOIDENT(XNAME) \
506         U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""),
507
508 VOIDTEST(early_extend)
509 VOIDTEST(early_nvram)
510 VOIDTEST(early_nvram2)
511 VOIDTEST(enable)
512 VOIDTEST(fast_enable)
513 VOIDTEST(global_lock)
514 VOIDTEST(lock)
515 VOIDTEST(readonly)
516 VOIDTEST(redefine_unowned)
517 VOIDTEST(space_perm)
518 VOIDTEST(startup)
519 VOIDTEST(timing)
520 VOIDTEST(write_limit)
521 VOIDTEST(timer)
522
523 static struct cmd_tbl cmd_cros_tpm_sub[] = {
524         VOIDENT(early_extend)
525         VOIDENT(early_nvram)
526         VOIDENT(early_nvram2)
527         VOIDENT(enable)
528         VOIDENT(fast_enable)
529         VOIDENT(global_lock)
530         VOIDENT(lock)
531         VOIDENT(readonly)
532         VOIDENT(redefine_unowned)
533         VOIDENT(space_perm)
534         VOIDENT(startup)
535         VOIDENT(timing)
536         VOIDENT(write_limit)
537         VOIDENT(timer)
538 };
539
540 static int do_tpmtest(struct cmd_tbl *cmdtp, int flag, int argc,
541                       char *const argv[])
542 {
543         struct cmd_tbl *c;
544         int i;
545
546         printf("argc = %d, argv = ", argc);
547
548         for (i = 0; i < argc; i++)
549                 printf(" %s", argv[i]);
550
551         printf("\n------\n");
552
553         argc--;
554         argv++;
555         c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub,
556                          ARRAY_SIZE(cmd_cros_tpm_sub));
557         return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp);
558 }
559
560 U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests",
561         "\n\tearly_extend\n"
562         "\tearly_nvram\n"
563         "\tearly_nvram2\n"
564         "\tenable\n"
565         "\tfast_enable\n"
566         "\tglobal_lock\n"
567         "\tlock\n"
568         "\treadonly\n"
569         "\tredefine_unowned\n"
570         "\tspace_perm\n"
571         "\tstartup\n"
572         "\ttiming\n"
573         "\twrite_limit\n");
This page took 0.059523 seconds and 4 git commands to generate.