]> Git Repo - J-u-boot.git/blame - cmd/tpm-v2.c
mtd: spi-nor-ids: Add support for XMC XM25QH64C
[J-u-boot.git] / cmd / tpm-v2.c
CommitLineData
ff32245b
MR
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2018 Bootlin
4 * Author: Miquel Raynal <[email protected]>
5 */
6
7#include <common.h>
09140113 8#include <command.h>
ff32245b
MR
9#include <dm.h>
10#include <log.h>
6284be5a 11#include <mapmem.h>
ff32245b
MR
12#include <tpm-common.h>
13#include <tpm-v2.h>
14#include "tpm-user-utils.h"
15
09140113
SG
16static int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,
17 char *const argv[])
1922df20
MR
18{
19 enum tpm2_startup_types mode;
abdc7b8a
SG
20 struct udevice *dev;
21 int ret;
1922df20 22
abdc7b8a
SG
23 ret = get_tpm(&dev);
24 if (ret)
25 return ret;
1922df20
MR
26 if (argc != 2)
27 return CMD_RET_USAGE;
28
29 if (!strcasecmp("TPM2_SU_CLEAR", argv[1])) {
30 mode = TPM2_SU_CLEAR;
31 } else if (!strcasecmp("TPM2_SU_STATE", argv[1])) {
32 mode = TPM2_SU_STATE;
33 } else {
34 printf("Couldn't recognize mode string: %s\n", argv[1]);
35 return CMD_RET_FAILURE;
36 }
37
abdc7b8a 38 return report_return_code(tpm2_startup(dev, mode));
1922df20
MR
39}
40
09140113
SG
41static int do_tpm2_self_test(struct cmd_tbl *cmdtp, int flag, int argc,
42 char *const argv[])
2dc6d97e
MR
43{
44 enum tpm2_yes_no full_test;
abdc7b8a
SG
45 struct udevice *dev;
46 int ret;
2dc6d97e 47
abdc7b8a
SG
48 ret = get_tpm(&dev);
49 if (ret)
50 return ret;
2dc6d97e
MR
51 if (argc != 2)
52 return CMD_RET_USAGE;
53
54 if (!strcasecmp("full", argv[1])) {
55 full_test = TPMI_YES;
56 } else if (!strcasecmp("continue", argv[1])) {
57 full_test = TPMI_NO;
58 } else {
59 printf("Couldn't recognize test mode: %s\n", argv[1]);
60 return CMD_RET_FAILURE;
61 }
62
abdc7b8a 63 return report_return_code(tpm2_self_test(dev, full_test));
2dc6d97e
MR
64}
65
09140113
SG
66static int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag, int argc,
67 char *const argv[])
bad8ff56
MR
68{
69 u32 handle = 0;
70 const char *pw = (argc < 3) ? NULL : argv[2];
71 const ssize_t pw_sz = pw ? strlen(pw) : 0;
abdc7b8a
SG
72 struct udevice *dev;
73 int ret;
74
75 ret = get_tpm(&dev);
76 if (ret)
77 return ret;
bad8ff56
MR
78
79 if (argc < 2 || argc > 3)
80 return CMD_RET_USAGE;
81
82 if (pw_sz > TPM2_DIGEST_LEN)
83 return -EINVAL;
84
85 if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
86 handle = TPM2_RH_LOCKOUT;
87 else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
88 handle = TPM2_RH_PLATFORM;
89 else
90 return CMD_RET_USAGE;
91
abdc7b8a 92 return report_return_code(tpm2_clear(dev, handle, pw, pw_sz));
bad8ff56
MR
93}
94
09140113
SG
95static int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag, int argc,
96 char *const argv[])
6284be5a
MR
97{
98 struct udevice *dev;
99 struct tpm_chip_priv *priv;
100 u32 index = simple_strtoul(argv[1], NULL, 0);
101 void *digest = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
102 int ret;
103 u32 rc;
104
105 if (argc != 3)
106 return CMD_RET_USAGE;
107
abdc7b8a 108 ret = get_tpm(&dev);
6284be5a
MR
109 if (ret)
110 return ret;
111
112 priv = dev_get_uclass_priv(dev);
113 if (!priv)
114 return -EINVAL;
115
116 if (index >= priv->pcr_count)
117 return -EINVAL;
118
e926136b
IA
119 rc = tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, digest,
120 TPM2_DIGEST_LEN);
6284be5a
MR
121
122 unmap_sysmem(digest);
123
124 return report_return_code(rc);
125}
126
09140113
SG
127static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,
128 char *const argv[])
1c4ea8f4
MR
129{
130 struct udevice *dev;
131 struct tpm_chip_priv *priv;
132 u32 index, rc;
133 unsigned int updates;
134 void *data;
135 int ret;
136
137 if (argc != 3)
138 return CMD_RET_USAGE;
139
abdc7b8a 140 ret = get_tpm(&dev);
1c4ea8f4
MR
141 if (ret)
142 return ret;
143
144 priv = dev_get_uclass_priv(dev);
145 if (!priv)
146 return -EINVAL;
147
148 index = simple_strtoul(argv[1], NULL, 0);
149 if (index >= priv->pcr_count)
150 return -EINVAL;
151
152 data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
153
abdc7b8a 154 rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, data, &updates);
1c4ea8f4 155 if (!rc) {
1d1af2ae 156 printf("PCR #%u content (%u known updates):\n", index, updates);
1c4ea8f4
MR
157 print_byte_string(data, TPM2_DIGEST_LEN);
158 }
159
160 unmap_sysmem(data);
161
162 return report_return_code(rc);
163}
164
09140113
SG
165static int do_tpm_get_capability(struct cmd_tbl *cmdtp, int flag, int argc,
166 char *const argv[])
69cd8f06
MR
167{
168 u32 capability, property, rc;
169 u8 *data;
170 size_t count;
171 int i, j;
abdc7b8a
SG
172 struct udevice *dev;
173 int ret;
174
175 ret = get_tpm(&dev);
176 if (ret)
177 return ret;
69cd8f06
MR
178
179 if (argc != 5)
180 return CMD_RET_USAGE;
181
182 capability = simple_strtoul(argv[1], NULL, 0);
183 property = simple_strtoul(argv[2], NULL, 0);
184 data = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
185 count = simple_strtoul(argv[4], NULL, 0);
186
abdc7b8a 187 rc = tpm2_get_capability(dev, capability, property, data, count);
69cd8f06
MR
188 if (rc)
189 goto unmap_data;
190
191 printf("Capabilities read from TPM:\n");
192 for (i = 0; i < count; i++) {
193 printf("Property 0x");
194 for (j = 0; j < 4; j++)
a322f54f 195 printf("%02x", data[(i * 8) + j + sizeof(u32)]);
69cd8f06
MR
196 printf(": 0x");
197 for (j = 4; j < 8; j++)
a322f54f 198 printf("%02x", data[(i * 8) + j + sizeof(u32)]);
69cd8f06
MR
199 printf("\n");
200 }
201
202unmap_data:
203 unmap_sysmem(data);
204
205 return report_return_code(rc);
206}
207
09140113 208static int do_tpm_dam_reset(struct cmd_tbl *cmdtp, int flag, int argc,
da9c3392
MR
209 char *const argv[])
210{
211 const char *pw = (argc < 2) ? NULL : argv[1];
212 const ssize_t pw_sz = pw ? strlen(pw) : 0;
abdc7b8a
SG
213 struct udevice *dev;
214 int ret;
215
216 ret = get_tpm(&dev);
217 if (ret)
218 return ret;
da9c3392
MR
219
220 if (argc > 2)
221 return CMD_RET_USAGE;
222
223 if (pw_sz > TPM2_DIGEST_LEN)
224 return -EINVAL;
225
abdc7b8a 226 return report_return_code(tpm2_dam_reset(dev, pw, pw_sz));
da9c3392
MR
227}
228
09140113 229static int do_tpm_dam_parameters(struct cmd_tbl *cmdtp, int flag, int argc,
da9c3392
MR
230 char *const argv[])
231{
232 const char *pw = (argc < 5) ? NULL : argv[4];
233 const ssize_t pw_sz = pw ? strlen(pw) : 0;
234 /*
235 * No Dictionary Attack Mitigation (DAM) means:
236 * maxtries = 0xFFFFFFFF, recovery_time = 1, lockout_recovery = 0
237 */
238 unsigned long int max_tries;
239 unsigned long int recovery_time;
240 unsigned long int lockout_recovery;
abdc7b8a
SG
241 struct udevice *dev;
242 int ret;
243
244 ret = get_tpm(&dev);
245 if (ret)
246 return ret;
da9c3392
MR
247
248 if (argc < 4 || argc > 5)
249 return CMD_RET_USAGE;
250
251 if (pw_sz > TPM2_DIGEST_LEN)
252 return -EINVAL;
253
254 if (strict_strtoul(argv[1], 0, &max_tries))
255 return CMD_RET_USAGE;
256
257 if (strict_strtoul(argv[2], 0, &recovery_time))
258 return CMD_RET_USAGE;
259
260 if (strict_strtoul(argv[3], 0, &lockout_recovery))
261 return CMD_RET_USAGE;
262
263 log(LOGC_NONE, LOGL_INFO, "Changing dictionary attack parameters:\n");
264 log(LOGC_NONE, LOGL_INFO, "- maxTries: %lu", max_tries);
265 log(LOGC_NONE, LOGL_INFO, "- recoveryTime: %lu\n", recovery_time);
266 log(LOGC_NONE, LOGL_INFO, "- lockoutRecovery: %lu\n", lockout_recovery);
267
abdc7b8a 268 return report_return_code(tpm2_dam_parameters(dev, pw, pw_sz, max_tries,
da9c3392
MR
269 recovery_time,
270 lockout_recovery));
271}
272
09140113 273static int do_tpm_change_auth(struct cmd_tbl *cmdtp, int flag, int argc,
dc26e913
MR
274 char *const argv[])
275{
276 u32 handle;
277 const char *newpw = argv[2];
278 const char *oldpw = (argc == 3) ? NULL : argv[3];
279 const ssize_t newpw_sz = strlen(newpw);
280 const ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;
abdc7b8a
SG
281 struct udevice *dev;
282 int ret;
283
284 ret = get_tpm(&dev);
285 if (ret)
286 return ret;
dc26e913
MR
287
288 if (argc < 3 || argc > 4)
289 return CMD_RET_USAGE;
290
291 if (newpw_sz > TPM2_DIGEST_LEN || oldpw_sz > TPM2_DIGEST_LEN)
292 return -EINVAL;
293
294 if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
295 handle = TPM2_RH_LOCKOUT;
296 else if (!strcasecmp("TPM2_RH_ENDORSEMENT", argv[1]))
297 handle = TPM2_RH_ENDORSEMENT;
298 else if (!strcasecmp("TPM2_RH_OWNER", argv[1]))
299 handle = TPM2_RH_OWNER;
300 else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
301 handle = TPM2_RH_PLATFORM;
302 else
303 return CMD_RET_USAGE;
304
abdc7b8a 305 return report_return_code(tpm2_change_auth(dev, handle, newpw, newpw_sz,
dc26e913
MR
306 oldpw, oldpw_sz));
307}
308
09140113
SG
309static int do_tpm_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag, int argc,
310 char *const argv[])
b9dd4fab
MR
311{
312 u32 index = simple_strtoul(argv[1], NULL, 0);
313 char *key = argv[2];
314 const char *pw = (argc < 4) ? NULL : argv[3];
315 const ssize_t pw_sz = pw ? strlen(pw) : 0;
abdc7b8a
SG
316 struct udevice *dev;
317 int ret;
318
319 ret = get_tpm(&dev);
320 if (ret)
321 return ret;
b9dd4fab
MR
322
323 if (strlen(key) != TPM2_DIGEST_LEN)
324 return -EINVAL;
325
326 if (argc < 3 || argc > 4)
327 return CMD_RET_USAGE;
328
abdc7b8a 329 return report_return_code(tpm2_pcr_setauthpolicy(dev, pw, pw_sz, index,
b9dd4fab
MR
330 key));
331}
332
09140113
SG
333static int do_tpm_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
334 int argc, char *const argv[])
b9dd4fab
MR
335{
336 u32 index = simple_strtoul(argv[1], NULL, 0);
337 char *key = argv[2];
338 const ssize_t key_sz = strlen(key);
339 const char *pw = (argc < 4) ? NULL : argv[3];
340 const ssize_t pw_sz = pw ? strlen(pw) : 0;
abdc7b8a
SG
341 struct udevice *dev;
342 int ret;
343
344 ret = get_tpm(&dev);
345 if (ret)
346 return ret;
b9dd4fab
MR
347
348 if (strlen(key) != TPM2_DIGEST_LEN)
349 return -EINVAL;
350
351 if (argc < 3 || argc > 4)
352 return CMD_RET_USAGE;
353
abdc7b8a 354 return report_return_code(tpm2_pcr_setauthvalue(dev, pw, pw_sz, index,
b9dd4fab
MR
355 key, key_sz));
356}
357
09140113 358static struct cmd_tbl tpm2_commands[] = {
3780e2d0 359 U_BOOT_CMD_MKENT(device, 0, 1, do_tpm_device, "", ""),
ff32245b
MR
360 U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
361 U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""),
1922df20 362 U_BOOT_CMD_MKENT(startup, 0, 1, do_tpm2_startup, "", ""),
2dc6d97e 363 U_BOOT_CMD_MKENT(self_test, 0, 1, do_tpm2_self_test, "", ""),
bad8ff56 364 U_BOOT_CMD_MKENT(clear, 0, 1, do_tpm2_clear, "", ""),
6284be5a 365 U_BOOT_CMD_MKENT(pcr_extend, 0, 1, do_tpm2_pcr_extend, "", ""),
1c4ea8f4 366 U_BOOT_CMD_MKENT(pcr_read, 0, 1, do_tpm_pcr_read, "", ""),
69cd8f06 367 U_BOOT_CMD_MKENT(get_capability, 0, 1, do_tpm_get_capability, "", ""),
da9c3392
MR
368 U_BOOT_CMD_MKENT(dam_reset, 0, 1, do_tpm_dam_reset, "", ""),
369 U_BOOT_CMD_MKENT(dam_parameters, 0, 1, do_tpm_dam_parameters, "", ""),
dc26e913 370 U_BOOT_CMD_MKENT(change_auth, 0, 1, do_tpm_change_auth, "", ""),
b9dd4fab
MR
371 U_BOOT_CMD_MKENT(pcr_setauthpolicy, 0, 1,
372 do_tpm_pcr_setauthpolicy, "", ""),
373 U_BOOT_CMD_MKENT(pcr_setauthvalue, 0, 1,
374 do_tpm_pcr_setauthvalue, "", ""),
ff32245b
MR
375};
376
09140113 377struct cmd_tbl *get_tpm2_commands(unsigned int *size)
ff32245b
MR
378{
379 *size = ARRAY_SIZE(tpm2_commands);
380
381 return tpm2_commands;
382}
383
2a2096ea 384U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
ff32245b
MR
385"<command> [<arguments>]\n"
386"\n"
3780e2d0
PR
387"device [num device]\n"
388" Show all devices or set the specified device\n"
ff32245b
MR
389"info\n"
390" Show information about the TPM.\n"
391"init\n"
392" Initialize the software stack. Always the first command to issue.\n"
1922df20
MR
393"startup <mode>\n"
394" Issue a TPM2_Startup command.\n"
395" <mode> is one of:\n"
396" * TPM2_SU_CLEAR (reset state)\n"
397" * TPM2_SU_STATE (preserved state)\n"
2dc6d97e
MR
398"self_test <type>\n"
399" Test the TPM capabilities.\n"
400" <type> is one of:\n"
401" * full (perform all tests)\n"
402" * continue (only check untested tests)\n"
bad8ff56
MR
403"clear <hierarchy>\n"
404" Issue a TPM2_Clear command.\n"
405" <hierarchy> is one of:\n"
406" * TPM2_RH_LOCKOUT\n"
407" * TPM2_RH_PLATFORM\n"
6284be5a
MR
408"pcr_extend <pcr> <digest_addr>\n"
409" Extend PCR #<pcr> with digest at <digest_addr>.\n"
410" <pcr>: index of the PCR\n"
411" <digest_addr>: address of a 32-byte SHA256 digest\n"
1c4ea8f4
MR
412"pcr_read <pcr> <digest_addr>\n"
413" Read PCR #<pcr> to memory address <digest_addr>.\n"
414" <pcr>: index of the PCR\n"
415" <digest_addr>: address to store the a 32-byte SHA256 digest\n"
69cd8f06
MR
416"get_capability <capability> <property> <addr> <count>\n"
417" Read and display <count> entries indexed by <capability>/<property>.\n"
418" Values are 4 bytes long and are written at <addr>.\n"
419" <capability>: capability\n"
420" <property>: property\n"
421" <addr>: address to store <count> entries of 4 bytes\n"
422" <count>: number of entries to retrieve\n"
dc26e913
MR
423"dam_reset [<password>]\n"
424" If the TPM is not in a LOCKOUT state, reset the internal error counter.\n"
425" <password>: optional password\n"
426"dam_parameters <max_tries> <recovery_time> <lockout_recovery> [<password>]\n"
427" If the TPM is not in a LOCKOUT state, set the DAM parameters\n"
428" <maxTries>: maximum number of failures before lockout,\n"
429" 0 means always locking\n"
430" <recoveryTime>: time before decrement of the error counter,\n"
431" 0 means no lockout\n"
432" <lockoutRecovery>: time of a lockout (before the next try),\n"
433" 0 means a reboot is needed\n"
434" <password>: optional password of the LOCKOUT hierarchy\n"
435"change_auth <hierarchy> <new_pw> [<old_pw>]\n"
436" <hierarchy>: the hierarchy\n"
437" <new_pw>: new password for <hierarchy>\n"
438" <old_pw>: optional previous password of <hierarchy>\n"
b9dd4fab
MR
439"pcr_setauthpolicy|pcr_setauthvalue <pcr> <key> [<password>]\n"
440" Change the <key> to access PCR #<pcr>.\n"
441" hierarchy and may be empty.\n"
442" /!\\WARNING: untested function, use at your own risks !\n"
443" <pcr>: index of the PCR\n"
444" <key>: secret to protect the access of PCR #<pcr>\n"
445" <password>: optional password of the PLATFORM hierarchy\n"
ff32245b 446);
This page took 0.140573 seconds and 4 git commands to generate.