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