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