1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (c) 2018 Bootlin
4 * Author: Miquel Raynal <miquel.raynal@bootlin.com>
5 */
6
7 #include <command.h>
8 #include <dm.h>
9 #include <log.h>
10 #include <mapmem.h>
11 #include <tpm-common.h>
12 #include <tpm-v2.h>
13 #include "tpm-user-utils.h"
14
do_tpm2_startup(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])15 static int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,
16 char *const argv[])
17 {
18 enum tpm2_startup_types mode;
19 struct udevice *dev;
20 int ret;
21 bool bon = true;
22
23 ret = get_tpm(&dev);
24 if (ret)
25 return ret;
26
27 /* argv[2] is optional to perform a TPM2_CC_SHUTDOWN */
28 if (argc > 3 || (argc == 3 && strcasecmp("off", argv[2])))
29 return CMD_RET_USAGE;
30
31 if (!strcasecmp("TPM2_SU_CLEAR", argv[1])) {
32 mode = TPM2_SU_CLEAR;
33 } else if (!strcasecmp("TPM2_SU_STATE", argv[1])) {
34 mode = TPM2_SU_STATE;
35 } else {
36 printf("Couldn't recognize mode string: %s\n", argv[1]);
37 return CMD_RET_FAILURE;
38 }
39
40 if (argv[2])
41 bon = false;
42
43 return report_return_code(tpm2_startup(dev, bon, mode));
44 }
45
do_tpm2_self_test(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])46 static int do_tpm2_self_test(struct cmd_tbl *cmdtp, int flag, int argc,
47 char *const argv[])
48 {
49 enum tpm2_yes_no full_test;
50 struct udevice *dev;
51 int ret;
52
53 ret = get_tpm(&dev);
54 if (ret)
55 return ret;
56 if (argc != 2)
57 return CMD_RET_USAGE;
58
59 if (!strcasecmp("full", argv[1])) {
60 full_test = TPMI_YES;
61 } else if (!strcasecmp("continue", argv[1])) {
62 full_test = TPMI_NO;
63 } else {
64 printf("Couldn't recognize test mode: %s\n", argv[1]);
65 return CMD_RET_FAILURE;
66 }
67
68 return report_return_code(tpm2_self_test(dev, full_test));
69 }
70
do_tpm2_clear(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])71 static int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag, int argc,
72 char *const argv[])
73 {
74 u32 handle = 0;
75 const char *pw = (argc < 3) ? NULL : argv[2];
76 const ssize_t pw_sz = pw ? strlen(pw) : 0;
77 struct udevice *dev;
78 int ret;
79
80 ret = get_tpm(&dev);
81 if (ret)
82 return ret;
83
84 if (argc < 2 || argc > 3)
85 return CMD_RET_USAGE;
86
87 if (pw_sz > TPM2_DIGEST_LEN)
88 return -EINVAL;
89
90 if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
91 handle = TPM2_RH_LOCKOUT;
92 else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
93 handle = TPM2_RH_PLATFORM;
94 else
95 return CMD_RET_USAGE;
96
97 return report_return_code(tpm2_clear(dev, handle, pw, pw_sz));
98 }
99
do_tpm2_pcr_extend(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])100 static int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag, int argc,
101 char *const argv[])
102 {
103 struct udevice *dev;
104 struct tpm_chip_priv *priv;
105 u32 index = simple_strtoul(argv[1], NULL, 0);
106 void *digest = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
107 int algo = TPM2_ALG_SHA256;
108 int algo_len;
109 int ret;
110 u32 rc;
111
112 if (argc < 3 || argc > 4)
113 return CMD_RET_USAGE;
114 if (argc == 4) {
115 algo = tpm2_name_to_algorithm(argv[3]);
116 if (algo == TPM2_ALG_INVAL)
117 return CMD_RET_FAILURE;
118 }
119 algo_len = tpm2_algorithm_to_len(algo);
120
121 ret = get_tpm(&dev);
122 if (ret)
123 return ret;
124
125 priv = dev_get_uclass_priv(dev);
126 if (!priv)
127 return -EINVAL;
128
129 if (index >= priv->pcr_count)
130 return -EINVAL;
131
132 rc = tpm2_pcr_extend(dev, index, algo, digest, algo_len);
133 if (!rc) {
134 printf("PCR #%u extended with %d byte %s digest\n", index,
135 algo_len, tpm2_algorithm_name(algo));
136 print_byte_string(digest, algo_len);
137 }
138
139 unmap_sysmem(digest);
140
141 return report_return_code(rc);
142 }
143
do_tpm_pcr_read(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])144 static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,
145 char *const argv[])
146 {
147 enum tpm2_algorithms algo = TPM2_ALG_SHA256;
148 struct udevice *dev;
149 struct tpm_chip_priv *priv;
150 u32 index, rc;
151 int algo_len;
152 unsigned int updates;
153 void *data;
154 int ret;
155
156 if (argc < 3 || argc > 4)
157 return CMD_RET_USAGE;
158 if (argc == 4) {
159 algo = tpm2_name_to_algorithm(argv[3]);
160 if (algo == TPM2_ALG_INVAL)
161 return CMD_RET_FAILURE;
162 }
163 algo_len = tpm2_algorithm_to_len(algo);
164
165 ret = get_tpm(&dev);
166 if (ret)
167 return ret;
168
169 priv = dev_get_uclass_priv(dev);
170 if (!priv)
171 return -EINVAL;
172
173 index = simple_strtoul(argv[1], NULL, 0);
174 if (index >= priv->pcr_count)
175 return -EINVAL;
176
177 data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
178
179 rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, algo,
180 data, algo_len, &updates);
181 if (!rc) {
182 printf("PCR #%u %s %d byte content (%u known updates):\n", index,
183 tpm2_algorithm_name(algo), algo_len, updates);
184 print_byte_string(data, algo_len);
185 }
186
187 unmap_sysmem(data);
188
189 return report_return_code(rc);
190 }
191
do_tpm_get_capability(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])192 static int do_tpm_get_capability(struct cmd_tbl *cmdtp, int flag, int argc,
193 char *const argv[])
194 {
195 u32 capability, property, rc;
196 u8 *data;
197 size_t count;
198 int i, j;
199 struct udevice *dev;
200 int ret;
201
202 ret = get_tpm(&dev);
203 if (ret)
204 return ret;
205
206 if (argc != 5)
207 return CMD_RET_USAGE;
208
209 capability = simple_strtoul(argv[1], NULL, 0);
210 property = simple_strtoul(argv[2], NULL, 0);
211 data = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
212 count = simple_strtoul(argv[4], NULL, 0);
213
214 rc = tpm2_get_capability(dev, capability, property, data, count);
215 if (rc)
216 goto unmap_data;
217
218 printf("Capabilities read from TPM:\n");
219 for (i = 0; i < count; i++) {
220 printf("Property 0x");
221 for (j = 0; j < 4; j++)
222 printf("%02x", data[(i * 8) + j + sizeof(u32)]);
223 printf(": 0x");
224 for (j = 4; j < 8; j++)
225 printf("%02x", data[(i * 8) + j + sizeof(u32)]);
226 printf("\n");
227 }
228
229 unmap_data:
230 unmap_sysmem(data);
231
232 return report_return_code(rc);
233 }
234
select_mask(u32 mask,enum tpm2_algorithms algo,bool select)235 static u32 select_mask(u32 mask, enum tpm2_algorithms algo, bool select)
236 {
237 size_t i;
238
239 for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
240 if (hash_algo_list[i].hash_alg != algo)
241 continue;
242
243 if (select)
244 mask |= hash_algo_list[i].hash_mask;
245 else
246 mask &= ~hash_algo_list[i].hash_mask;
247
248 break;
249 }
250
251 return mask;
252 }
253
254 static bool
is_algo_in_pcrs(enum tpm2_algorithms algo,struct tpml_pcr_selection * pcrs)255 is_algo_in_pcrs(enum tpm2_algorithms algo, struct tpml_pcr_selection *pcrs)
256 {
257 size_t i;
258
259 for (i = 0; i < pcrs->count; i++) {
260 if (algo == pcrs->selection[i].hash)
261 return true;
262 }
263
264 return false;
265 }
266
do_tpm2_pcrallocate(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])267 static int do_tpm2_pcrallocate(struct cmd_tbl *cmdtp, int flag, int argc,
268 char *const argv[])
269 {
270 struct udevice *dev;
271 int ret;
272 enum tpm2_algorithms algo;
273 const char *pw = (argc < 4) ? NULL : argv[3];
274 const ssize_t pw_sz = pw ? strlen(pw) : 0;
275 static struct tpml_pcr_selection pcr = { 0 };
276 u32 pcr_len = 0;
277 bool bon = false;
278 static u32 mask;
279 int i;
280
281 /* argv[1]: algorithm (bank), argv[2]: on/off */
282 if (argc < 3 || argc > 4)
283 return CMD_RET_USAGE;
284
285 if (!strcasecmp("on", argv[2]))
286 bon = true;
287 else if (strcasecmp("off", argv[2]))
288 return CMD_RET_USAGE;
289
290 algo = tpm2_name_to_algorithm(argv[1]);
291 if (algo == TPM2_ALG_INVAL)
292 return CMD_RET_USAGE;
293
294 ret = get_tpm(&dev);
295 if (ret)
296 return ret;
297
298 if (!pcr.count) {
299 /*
300 * Get current active algorithms (banks), PCRs and mask via the
301 * first call
302 */
303 ret = tpm2_get_pcr_info(dev, &pcr);
304 if (ret)
305 return ret;
306
307 for (i = 0; i < pcr.count; i++) {
308 struct tpms_pcr_selection *sel = &pcr.selection[i];
309 const char *name;
310
311 if (!tpm2_is_active_bank(sel))
312 continue;
313
314 mask = select_mask(mask, sel->hash, true);
315 name = tpm2_algorithm_name(sel->hash);
316 if (name)
317 printf("Active bank[%d]: %s\n", i, name);
318 }
319 }
320
321 if (!is_algo_in_pcrs(algo, &pcr)) {
322 printf("%s is not supported by the tpm device\n", argv[1]);
323 return CMD_RET_USAGE;
324 }
325
326 mask = select_mask(mask, algo, bon);
327 ret = tpm2_pcr_config_algo(dev, mask, &pcr, &pcr_len);
328 if (ret)
329 return ret;
330
331 return report_return_code(tpm2_send_pcr_allocate(dev, pw, pw_sz, &pcr,
332 pcr_len));
333 }
334
do_tpm_dam_reset(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])335 static int do_tpm_dam_reset(struct cmd_tbl *cmdtp, int flag, int argc,
336 char *const argv[])
337 {
338 const char *pw = (argc < 2) ? NULL : argv[1];
339 const ssize_t pw_sz = pw ? strlen(pw) : 0;
340 struct udevice *dev;
341 int ret;
342
343 ret = get_tpm(&dev);
344 if (ret)
345 return ret;
346
347 if (argc > 2)
348 return CMD_RET_USAGE;
349
350 if (pw_sz > TPM2_DIGEST_LEN)
351 return -EINVAL;
352
353 return report_return_code(tpm2_dam_reset(dev, pw, pw_sz));
354 }
355
do_tpm_dam_parameters(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])356 static int do_tpm_dam_parameters(struct cmd_tbl *cmdtp, int flag, int argc,
357 char *const argv[])
358 {
359 const char *pw = (argc < 5) ? NULL : argv[4];
360 const ssize_t pw_sz = pw ? strlen(pw) : 0;
361 /*
362 * No Dictionary Attack Mitigation (DAM) means:
363 * maxtries = 0xFFFFFFFF, recovery_time = 1, lockout_recovery = 0
364 */
365 unsigned long int max_tries;
366 unsigned long int recovery_time;
367 unsigned long int lockout_recovery;
368 struct udevice *dev;
369 int ret;
370
371 ret = get_tpm(&dev);
372 if (ret)
373 return ret;
374
375 if (argc < 4 || argc > 5)
376 return CMD_RET_USAGE;
377
378 if (pw_sz > TPM2_DIGEST_LEN)
379 return -EINVAL;
380
381 if (strict_strtoul(argv[1], 0, &max_tries))
382 return CMD_RET_USAGE;
383
384 if (strict_strtoul(argv[2], 0, &recovery_time))
385 return CMD_RET_USAGE;
386
387 if (strict_strtoul(argv[3], 0, &lockout_recovery))
388 return CMD_RET_USAGE;
389
390 log(LOGC_NONE, LOGL_INFO, "Changing dictionary attack parameters:\n");
391 log(LOGC_NONE, LOGL_INFO, "- maxTries: %lu", max_tries);
392 log(LOGC_NONE, LOGL_INFO, "- recoveryTime: %lu\n", recovery_time);
393 log(LOGC_NONE, LOGL_INFO, "- lockoutRecovery: %lu\n", lockout_recovery);
394
395 return report_return_code(tpm2_dam_parameters(dev, pw, pw_sz, max_tries,
396 recovery_time,
397 lockout_recovery));
398 }
399
do_tpm_change_auth(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])400 static int do_tpm_change_auth(struct cmd_tbl *cmdtp, int flag, int argc,
401 char *const argv[])
402 {
403 u32 handle;
404 const char *newpw = argv[2];
405 const char *oldpw = (argc == 3) ? NULL : argv[3];
406 const ssize_t newpw_sz = strlen(newpw);
407 const ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;
408 struct udevice *dev;
409 int ret;
410
411 ret = get_tpm(&dev);
412 if (ret)
413 return ret;
414
415 if (argc < 3 || argc > 4)
416 return CMD_RET_USAGE;
417
418 if (newpw_sz > TPM2_DIGEST_LEN || oldpw_sz > TPM2_DIGEST_LEN)
419 return -EINVAL;
420
421 if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
422 handle = TPM2_RH_LOCKOUT;
423 else if (!strcasecmp("TPM2_RH_ENDORSEMENT", argv[1]))
424 handle = TPM2_RH_ENDORSEMENT;
425 else if (!strcasecmp("TPM2_RH_OWNER", argv[1]))
426 handle = TPM2_RH_OWNER;
427 else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
428 handle = TPM2_RH_PLATFORM;
429 else
430 return CMD_RET_USAGE;
431
432 return report_return_code(tpm2_change_auth(dev, handle, newpw, newpw_sz,
433 oldpw, oldpw_sz));
434 }
435
do_tpm_pcr_setauthpolicy(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])436 static int do_tpm_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag, int argc,
437 char *const argv[])
438 {
439 u32 index = simple_strtoul(argv[1], NULL, 0);
440 char *key = argv[2];
441 const char *pw = (argc < 4) ? NULL : argv[3];
442 const ssize_t pw_sz = pw ? strlen(pw) : 0;
443 struct udevice *dev;
444 int ret;
445
446 ret = get_tpm(&dev);
447 if (ret)
448 return ret;
449
450 if (strlen(key) != TPM2_DIGEST_LEN)
451 return -EINVAL;
452
453 if (argc < 3 || argc > 4)
454 return CMD_RET_USAGE;
455
456 return report_return_code(tpm2_pcr_setauthpolicy(dev, pw, pw_sz, index,
457 key));
458 }
459
do_tpm_pcr_setauthvalue(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])460 static int do_tpm_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
461 int argc, char *const argv[])
462 {
463 u32 index = simple_strtoul(argv[1], NULL, 0);
464 char *key = argv[2];
465 const ssize_t key_sz = strlen(key);
466 const char *pw = (argc < 4) ? NULL : argv[3];
467 const ssize_t pw_sz = pw ? strlen(pw) : 0;
468 struct udevice *dev;
469 int ret;
470
471 ret = get_tpm(&dev);
472 if (ret)
473 return ret;
474
475 if (strlen(key) != TPM2_DIGEST_LEN)
476 return -EINVAL;
477
478 if (argc < 3 || argc > 4)
479 return CMD_RET_USAGE;
480
481 return report_return_code(tpm2_pcr_setauthvalue(dev, pw, pw_sz, index,
482 key, key_sz));
483 }
484
485 static struct cmd_tbl tpm2_commands[] = {
486 U_BOOT_CMD_MKENT(device, 0, 1, do_tpm_device, "", ""),
487 U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
488 U_BOOT_CMD_MKENT(state, 0, 1, do_tpm_report_state, "", ""),
489 U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""),
490 U_BOOT_CMD_MKENT(startup, 0, 1, do_tpm2_startup, "", ""),
491 U_BOOT_CMD_MKENT(self_test, 0, 1, do_tpm2_self_test, "", ""),
492 U_BOOT_CMD_MKENT(clear, 0, 1, do_tpm2_clear, "", ""),
493 U_BOOT_CMD_MKENT(pcr_extend, 0, 1, do_tpm2_pcr_extend, "", ""),
494 U_BOOT_CMD_MKENT(pcr_read, 0, 1, do_tpm_pcr_read, "", ""),
495 U_BOOT_CMD_MKENT(get_capability, 0, 1, do_tpm_get_capability, "", ""),
496 U_BOOT_CMD_MKENT(dam_reset, 0, 1, do_tpm_dam_reset, "", ""),
497 U_BOOT_CMD_MKENT(dam_parameters, 0, 1, do_tpm_dam_parameters, "", ""),
498 U_BOOT_CMD_MKENT(change_auth, 0, 1, do_tpm_change_auth, "", ""),
499 U_BOOT_CMD_MKENT(autostart, 0, 1, do_tpm_autostart, "", ""),
500 U_BOOT_CMD_MKENT(pcr_setauthpolicy, 0, 1,
501 do_tpm_pcr_setauthpolicy, "", ""),
502 U_BOOT_CMD_MKENT(pcr_setauthvalue, 0, 1,
503 do_tpm_pcr_setauthvalue, "", ""),
504 U_BOOT_CMD_MKENT(pcr_allocate, 0, 1, do_tpm2_pcrallocate, "", ""),
505 };
506
get_tpm2_commands(unsigned int * size)507 struct cmd_tbl *get_tpm2_commands(unsigned int *size)
508 {
509 *size = ARRAY_SIZE(tpm2_commands);
510
511 return tpm2_commands;
512 }
513
514 U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
515 "<command> [<arguments>]\n"
516 "\n"
517 "device [num device]\n"
518 " Show all devices or set the specified device\n"
519 "info\n"
520 " Show information about the TPM.\n"
521 "state\n"
522 " Show internal state from the TPM (if available)\n"
523 "autostart\n"
524 " Initalize the tpm, perform a Startup(clear) and run a full selftest\n"
525 " sequence\n"
526 "init\n"
527 " Initialize the software stack. Always the first command to issue.\n"
528 " 'tpm startup' is the only acceptable command after a 'tpm init' has been\n"
529 " issued\n"
530 "startup <mode> [<op>]\n"
531 " Issue a TPM2_Startup command.\n"
532 " <mode> is one of:\n"
533 " * TPM2_SU_CLEAR (reset state)\n"
534 " * TPM2_SU_STATE (preserved state)\n"
535 " <op>:\n"
536 " * off - To shutdown the TPM\n"
537 "self_test <type>\n"
538 " Test the TPM capabilities.\n"
539 " <type> is one of:\n"
540 " * full (perform all tests)\n"
541 " * continue (only check untested tests)\n"
542 "clear <hierarchy>\n"
543 " Issue a TPM2_Clear command.\n"
544 " <hierarchy> is one of:\n"
545 " * TPM2_RH_LOCKOUT\n"
546 " * TPM2_RH_PLATFORM\n"
547 "pcr_extend <pcr> <digest_addr> [<digest_algo>]\n"
548 " Extend PCR #<pcr> with digest at <digest_addr> with digest_algo.\n"
549 " <pcr>: index of the PCR\n"
550 " <digest_addr>: address of digest of digest_algo type (defaults to SHA256)\n"
551 "pcr_read <pcr> <digest_addr> [<digest_algo>]\n"
552 " Read PCR #<pcr> to memory address <digest_addr> with <digest_algo>.\n"
553 " <pcr>: index of the PCR\n"
554 " <digest_addr>: address of digest of digest_algo type (defaults to SHA256)\n"
555 "get_capability <capability> <property> <addr> <count>\n"
556 " Read and display <count> entries indexed by <capability>/<property>.\n"
557 " Values are 4 bytes long and are written at <addr>.\n"
558 " <capability>: capability\n"
559 " <property>: property\n"
560 " <addr>: address to store <count> entries of 4 bytes\n"
561 " <count>: number of entries to retrieve\n"
562 "dam_reset [<password>]\n"
563 " If the TPM is not in a LOCKOUT state, reset the internal error counter.\n"
564 " <password>: optional password\n"
565 "dam_parameters <max_tries> <recovery_time> <lockout_recovery> [<password>]\n"
566 " If the TPM is not in a LOCKOUT state, set the DAM parameters\n"
567 " <maxTries>: maximum number of failures before lockout,\n"
568 " 0 means always locking\n"
569 " <recoveryTime>: time before decrement of the error counter,\n"
570 " 0 means no lockout\n"
571 " <lockoutRecovery>: time of a lockout (before the next try),\n"
572 " 0 means a reboot is needed\n"
573 " <password>: optional password of the LOCKOUT hierarchy\n"
574 "change_auth <hierarchy> <new_pw> [<old_pw>]\n"
575 " <hierarchy>: the hierarchy\n"
576 " <new_pw>: new password for <hierarchy>\n"
577 " <old_pw>: optional previous password of <hierarchy>\n"
578 "pcr_setauthpolicy|pcr_setauthvalue <pcr> <key> [<password>]\n"
579 " Change the <key> to access PCR #<pcr>.\n"
580 " hierarchy and may be empty.\n"
581 " /!\\WARNING: untested function, use at your own risks !\n"
582 " <pcr>: index of the PCR\n"
583 " <key>: secret to protect the access of PCR #<pcr>\n"
584 " <password>: optional password of the PLATFORM hierarchy\n"
585 "pcr_allocate <algorithm> <on/off> [<password>]\n"
586 " Issue a TPM2_PCR_Allocate Command to reconfig PCR bank algorithm.\n"
587 " <algorithm> is one of:\n"
588 " * sha1\n"
589 " * sha256\n"
590 " * sha384\n"
591 " * sha512\n"
592 " <on|off> is one of:\n"
593 " * on - Select all available PCRs associated with the specified\n"
594 " algorithm (bank)\n"
595 " * off - Clear all available PCRs associated with the specified\n"
596 " algorithm (bank)\n"
597 " <password>: optional password\n"
598 );
599