]> Git Repo - u-boot.git/blame - lib/tpm-v2.c
configs: Resync with savedefconfig
[u-boot.git] / lib / tpm-v2.c
CommitLineData
ff32245b
MR
1// SPDX-License-Identifier: GPL-2.0+
2/*
97707f12 3 * Copyright (c) 2023 Linaro Limited
ff32245b
MR
4 * Copyright (c) 2018 Bootlin
5 * Author: Miquel Raynal <[email protected]>
6 */
7
ff32245b 8#include <dm.h>
97707f12
EJ
9#include <dm/of_access.h>
10#include <tpm_api.h>
ff32245b
MR
11#include <tpm-common.h>
12#include <tpm-v2.h>
27b462ce 13#include <tpm_tcg2.h>
97707f12
EJ
14#include <u-boot/sha1.h>
15#include <u-boot/sha256.h>
16#include <u-boot/sha512.h>
17#include <version_string.h>
18#include <asm/io.h>
cd93d625 19#include <linux/bitops.h>
97707f12
EJ
20#include <linux/unaligned/be_byteshift.h>
21#include <linux/unaligned/generic.h>
22#include <linux/unaligned/le_byteshift.h>
23
ff32245b 24#include "tpm-utils.h"
1922df20 25
ffdbf775
IA
26static int tpm2_update_active_banks(struct udevice *dev)
27{
28 struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
29 struct tpml_pcr_selection pcrs;
30 int ret, i;
31
32 ret = tpm2_get_pcr_info(dev, &pcrs);
33 if (ret)
34 return ret;
35
36 priv->active_bank_count = 0;
37 for (i = 0; i < pcrs.count; i++) {
38 if (!tpm2_is_active_bank(&pcrs.selection[i]))
39 continue;
40 priv->active_banks[priv->active_bank_count] = pcrs.selection[i].hash;
41 priv->active_bank_count++;
42 }
43
44 return 0;
45}
46
b6228b2e
RM
47static void tpm2_print_selected_algorithm_name(u32 selected)
48{
49 size_t i;
50 const char *str;
51
52 for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
53 const struct digest_info *algo = &hash_algo_list[i];
54
55 if (!(selected & algo->hash_mask))
56 continue;
57
58 str = tpm2_algorithm_name(algo->hash_alg);
59 if (str)
60 log_info("%s\n", str);
61 }
62}
63
64int tpm2_scan_masks(struct udevice *dev, u32 log_active, u32 *mask)
65{
66 struct tpml_pcr_selection pcrs;
67 u32 active = 0;
68 u32 supported = 0;
69 int rc, i;
70
71 *mask = 0;
72
73 rc = tpm2_get_pcr_info(dev, &pcrs);
74 if (rc)
75 return rc;
76
77 for (i = 0; i < pcrs.count; i++) {
78 struct tpms_pcr_selection *sel = &pcrs.selection[i];
79 size_t j;
80 u32 hash_mask = 0;
81
82 for (j = 0; j < ARRAY_SIZE(hash_algo_list); j++) {
83 if (hash_algo_list[j].hash_alg == sel->hash)
84 hash_mask = hash_algo_list[j].hash_mask;
85 }
86
87 if (tpm2_algorithm_supported(sel->hash))
88 supported |= hash_mask;
89
90 if (tpm2_is_active_bank(sel))
91 active |= hash_mask;
92 }
93
94 /* All eventlog algorithm(s) must be supported */
95 if (log_active & ~supported) {
96 log_err("EventLog contains U-Boot unsupported algorithm(s)\n");
97 tpm2_print_selected_algorithm_name(log_active & ~supported);
98 rc = -1;
99 }
100 if (log_active && active & ~log_active) {
101 log_warning("TPM active algorithm(s) not exist in eventlog\n");
102 tpm2_print_selected_algorithm_name(active & ~log_active);
103 *mask = log_active;
104 }
105
106 /* Any active algorithm(s) which are not supported must be removed */
107 if (active & ~supported) {
108 log_warning("TPM active algorithm(s) unsupported by u-boot\n");
109 tpm2_print_selected_algorithm_name(active & ~supported);
110 if (*mask)
111 *mask = active & supported & *mask;
112 else
113 *mask = active & supported;
114 }
115
116 return rc;
117}
118
119static int tpm2_pcr_allocate(struct udevice *dev, u32 algo_mask)
120{
121 struct tpml_pcr_selection pcr = { 0 };
122 u32 pcr_len = 0;
123 int rc;
124
125 rc = tpm2_get_pcr_info(dev, &pcr);
126 if (rc)
127 return rc;
128
129 rc = tpm2_pcr_config_algo(dev, algo_mask, &pcr, &pcr_len);
130 if (rc)
131 return rc;
132
133 /* Assume no password */
134 rc = tpm2_send_pcr_allocate(dev, NULL, 0, &pcr, pcr_len);
135 if (rc)
136 return rc;
137
138 /* Send TPM2_Shutdown, assume mode = TPM2_SU_CLEAR */
139 return tpm2_startup(dev, false, TPM2_SU_CLEAR);
140}
141
142int tpm2_activate_banks(struct udevice *dev, u32 log_active)
143{
144 u32 algo_mask = 0;
145 int rc;
146
147 rc = tpm2_scan_masks(dev, log_active, &algo_mask);
148 if (rc)
149 return rc;
150
151 if (algo_mask) {
152 if (!IS_ENABLED(CONFIG_TPM_PCR_ALLOCATE))
153 return -1;
154
155 rc = tpm2_pcr_allocate(dev, algo_mask);
156 if (rc)
157 return rc;
158
159 log_info("PCR allocate done, shutdown TPM and reboot\n");
160 do_reset(NULL, 0, 0, NULL);
161 log_err("reset does not work!\n");
162 return -1;
163 }
164
165 return 0;
166}
167
6d8e52a6 168u32 tpm2_startup(struct udevice *dev, bool bon, enum tpm2_startup_types mode)
1922df20 169{
6d8e52a6 170 int op = bon ? TPM2_CC_STARTUP : TPM2_CC_SHUTDOWN;
1922df20
MR
171 const u8 command_v2[12] = {
172 tpm_u16(TPM2_ST_NO_SESSIONS),
173 tpm_u32(12),
6d8e52a6 174 tpm_u32(op),
1922df20
MR
175 tpm_u16(mode),
176 };
177 int ret;
178
179 /*
180 * Note TPM2_Startup command will return RC_SUCCESS the first time,
181 * but will return RC_INITIALIZE otherwise.
182 */
abdc7b8a 183 ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
6d8e52a6 184 if ((ret && ret != TPM2_RC_INITIALIZE) || !bon)
1922df20
MR
185 return ret;
186
ffdbf775 187 return tpm2_update_active_banks(dev);
1922df20 188}
2dc6d97e 189
abdc7b8a 190u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
2dc6d97e
MR
191{
192 const u8 command_v2[12] = {
193 tpm_u16(TPM2_ST_NO_SESSIONS),
194 tpm_u32(11),
195 tpm_u32(TPM2_CC_SELF_TEST),
196 full_test,
197 };
198
abdc7b8a 199 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
2dc6d97e 200}
bad8ff56 201
a595be3a
IA
202u32 tpm2_auto_start(struct udevice *dev)
203{
204 u32 rc;
205
a595be3a
IA
206 rc = tpm2_self_test(dev, TPMI_YES);
207
208 if (rc == TPM2_RC_INITIALIZE) {
6d8e52a6 209 rc = tpm2_startup(dev, true, TPM2_SU_CLEAR);
a595be3a
IA
210 if (rc)
211 return rc;
212
213 rc = tpm2_self_test(dev, TPMI_YES);
214 }
ffdbf775
IA
215 if (rc)
216 return rc;
a595be3a 217
ffdbf775 218 return tpm2_update_active_banks(dev);
a595be3a
IA
219}
220
abdc7b8a
SG
221u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
222 const ssize_t pw_sz)
bad8ff56 223{
1bea7cc4
SG
224 /* Length of the message header, up to start of password */
225 uint offset = 27;
bad8ff56
MR
226 u8 command_v2[COMMAND_BUFFER_SIZE] = {
227 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1bea7cc4 228 tpm_u32(offset + pw_sz), /* Length */
bad8ff56
MR
229 tpm_u32(TPM2_CC_CLEAR), /* Command code */
230
231 /* HANDLE */
232 tpm_u32(handle), /* TPM resource handle */
233
234 /* AUTH_SESSION */
235 tpm_u32(9 + pw_sz), /* Authorization size */
236 tpm_u32(TPM2_RS_PW), /* Session handle */
237 tpm_u16(0), /* Size of <nonce> */
238 /* <nonce> (if any) */
239 0, /* Attributes: Cont/Excl/Rst */
240 tpm_u16(pw_sz), /* Size of <hmac/password> */
241 /* STRING(pw) <hmac/password> (if any) */
242 };
bad8ff56
MR
243 int ret;
244
245 /*
246 * Fill the command structure starting from the first buffer:
247 * - the password (if any)
248 */
249 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
250 offset, pw, pw_sz);
251 offset += pw_sz;
252 if (ret)
253 return TPM_LIB_ERROR;
254
abdc7b8a 255 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
bad8ff56 256}
6284be5a 257
eadcbc78
SG
258u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
259 size_t space_size, u32 nv_attributes,
260 const u8 *nv_policy, size_t nv_policy_size)
261{
262 /*
263 * Calculate the offset of the nv_policy piece by adding each of the
264 * chunks below.
265 */
1c32eee3
SG
266 const int platform_len = sizeof(u32);
267 const int session_hdr_len = 13;
268 const int message_len = 14;
269 uint offset = TPM2_HDR_LEN + platform_len + session_hdr_len +
270 message_len;
eadcbc78
SG
271 u8 command_v2[COMMAND_BUFFER_SIZE] = {
272 /* header 10 bytes */
273 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1c32eee3 274 tpm_u32(offset + nv_policy_size + 2),/* Length */
eadcbc78
SG
275 tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
276
1c32eee3 277 /* handles 4 bytes */
eadcbc78
SG
278 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
279
280 /* session header 13 bytes */
281 tpm_u32(9), /* Header size */
282 tpm_u32(TPM2_RS_PW), /* Password authorisation */
283 tpm_u16(0), /* nonce_size */
284 0, /* session_attrs */
285 tpm_u16(0), /* auth_size */
286
287 /* message 14 bytes + policy */
1c32eee3 288 tpm_u16(message_len + nv_policy_size), /* size */
eadcbc78
SG
289 tpm_u32(space_index),
290 tpm_u16(TPM2_ALG_SHA256),
291 tpm_u32(nv_attributes),
292 tpm_u16(nv_policy_size),
1c32eee3
SG
293 /*
294 * nv_policy
295 * space_size
296 */
eadcbc78
SG
297 };
298 int ret;
299
300 /*
301 * Fill the command structure starting from the first buffer:
302 * - the password (if any)
303 */
1c32eee3
SG
304 ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
305 offset, nv_policy, nv_policy_size,
306 offset + nv_policy_size, space_size);
eadcbc78
SG
307 if (ret)
308 return TPM_LIB_ERROR;
309
310 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
311}
312
e926136b
IA
313u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
314 const u8 *digest, u32 digest_len)
6284be5a 315{
1bea7cc4
SG
316 /* Length of the message header, up to start of digest */
317 uint offset = 33;
6284be5a
MR
318 u8 command_v2[COMMAND_BUFFER_SIZE] = {
319 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1bea7cc4 320 tpm_u32(offset + digest_len), /* Length */
6284be5a
MR
321 tpm_u32(TPM2_CC_PCR_EXTEND), /* Command code */
322
323 /* HANDLE */
324 tpm_u32(index), /* Handle (PCR Index) */
325
326 /* AUTH_SESSION */
327 tpm_u32(9), /* Authorization size */
328 tpm_u32(TPM2_RS_PW), /* Session handle */
329 tpm_u16(0), /* Size of <nonce> */
330 /* <nonce> (if any) */
331 0, /* Attributes: Cont/Excl/Rst */
332 tpm_u16(0), /* Size of <hmac/password> */
333 /* <hmac/password> (if any) */
1bea7cc4
SG
334
335 /* hashes */
6284be5a 336 tpm_u32(1), /* Count (number of hashes) */
e926136b 337 tpm_u16(algorithm), /* Algorithm of the hash */
6284be5a
MR
338 /* STRING(digest) Digest */
339 };
6284be5a
MR
340 int ret;
341
a557d258
SG
342 if (!digest)
343 return -EINVAL;
e7505b3b 344
0698f133 345 if (!tpm2_check_active_banks(dev)) {
e7505b3b 346 log_err("Cannot extend PCRs if all the TPM enabled algorithms are not supported\n");
e7e166da
RM
347
348 ret = tpm2_pcr_allocate(dev, 0);
349 if (ret)
350 return -EINVAL;
e7505b3b 351 }
6284be5a
MR
352 /*
353 * Fill the command structure starting from the first buffer:
354 * - the digest
355 */
356 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
e926136b 357 offset, digest, digest_len);
6284be5a
MR
358 if (ret)
359 return TPM_LIB_ERROR;
360
abdc7b8a 361 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
6284be5a 362}
1c4ea8f4 363
6719cbe3
SG
364u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
365{
366 u8 command_v2[COMMAND_BUFFER_SIZE] = {
367 /* header 10 bytes */
368 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
369 tpm_u32(10 + 8 + 4 + 9 + 4), /* Length */
370 tpm_u32(TPM2_CC_NV_READ), /* Command code */
371
372 /* handles 8 bytes */
373 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
374 tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
375
376 /* AUTH_SESSION */
377 tpm_u32(9), /* Authorization size */
378 tpm_u32(TPM2_RS_PW), /* Session handle */
379 tpm_u16(0), /* Size of <nonce> */
380 /* <nonce> (if any) */
381 0, /* Attributes: Cont/Excl/Rst */
382 tpm_u16(0), /* Size of <hmac/password> */
383 /* <hmac/password> (if any) */
384
385 tpm_u16(count), /* Number of bytes */
386 tpm_u16(0), /* Offset */
387 };
388 size_t response_len = COMMAND_BUFFER_SIZE;
389 u8 response[COMMAND_BUFFER_SIZE];
390 int ret;
391 u16 tag;
392 u32 size, code;
393
394 ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
395 if (ret)
396 return log_msg_ret("read", ret);
397 if (unpack_byte_string(response, response_len, "wdds",
398 0, &tag, 2, &size, 6, &code,
399 16, data, count))
400 return TPM_LIB_ERROR;
401
402 return 0;
403}
404
405u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
406 u32 count)
407{
408 struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
409 uint offset = 10 + 8 + 4 + 9 + 2;
410 uint len = offset + count + 2;
411 /* Use empty password auth if platform hierarchy is disabled */
412 u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index :
413 TPM2_RH_PLATFORM;
414 u8 command_v2[COMMAND_BUFFER_SIZE] = {
415 /* header 10 bytes */
416 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
417 tpm_u32(len), /* Length */
418 tpm_u32(TPM2_CC_NV_WRITE), /* Command code */
419
420 /* handles 8 bytes */
421 tpm_u32(auth), /* Primary platform seed */
422 tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
423
424 /* AUTH_SESSION */
425 tpm_u32(9), /* Authorization size */
426 tpm_u32(TPM2_RS_PW), /* Session handle */
427 tpm_u16(0), /* Size of <nonce> */
428 /* <nonce> (if any) */
429 0, /* Attributes: Cont/Excl/Rst */
430 tpm_u16(0), /* Size of <hmac/password> */
431 /* <hmac/password> (if any) */
432
433 tpm_u16(count),
434 };
435 size_t response_len = COMMAND_BUFFER_SIZE;
436 u8 response[COMMAND_BUFFER_SIZE];
437 int ret;
438
439 ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
440 offset, data, count,
441 offset + count, 0);
442 if (ret)
443 return TPM_LIB_ERROR;
444
445 return tpm_sendrecv_command(dev, command_v2, response, &response_len);
446}
447
abdc7b8a 448u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
2957a1e2
RG
449 u16 algorithm, void *data, u32 digest_len,
450 unsigned int *updates)
1c4ea8f4
MR
451{
452 u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
453 u8 command_v2[COMMAND_BUFFER_SIZE] = {
454 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
455 tpm_u32(17 + idx_array_sz), /* Length */
456 tpm_u32(TPM2_CC_PCR_READ), /* Command code */
457
458 /* TPML_PCR_SELECTION */
459 tpm_u32(1), /* Number of selections */
2957a1e2 460 tpm_u16(algorithm), /* Algorithm of the hash */
1c4ea8f4
MR
461 idx_array_sz, /* Array size for selection */
462 /* bitmap(idx) Selected PCR bitmap */
463 };
464 size_t response_len = COMMAND_BUFFER_SIZE;
465 u8 response[COMMAND_BUFFER_SIZE];
466 unsigned int pcr_sel_idx = idx / 8;
467 u8 pcr_sel_bit = BIT(idx % 8);
468 unsigned int counter = 0;
469 int ret;
470
471 if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b",
472 17 + pcr_sel_idx, pcr_sel_bit))
473 return TPM_LIB_ERROR;
474
abdc7b8a 475 ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
1c4ea8f4
MR
476 if (ret)
477 return ret;
478
2957a1e2
RG
479 if (digest_len > response_len)
480 return TPM_LIB_ERROR;
481
1c4ea8f4
MR
482 if (unpack_byte_string(response, response_len, "ds",
483 10, &counter,
2957a1e2
RG
484 response_len - digest_len, data,
485 digest_len))
1c4ea8f4
MR
486 return TPM_LIB_ERROR;
487
488 if (updates)
489 *updates = counter;
490
491 return 0;
492}
69cd8f06 493
abdc7b8a
SG
494u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
495 void *buf, size_t prop_count)
69cd8f06
MR
496{
497 u8 command_v2[COMMAND_BUFFER_SIZE] = {
498 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
499 tpm_u32(22), /* Length */
500 tpm_u32(TPM2_CC_GET_CAPABILITY), /* Command code */
501
502 tpm_u32(capability), /* Capability */
503 tpm_u32(property), /* Property */
504 tpm_u32(prop_count), /* Property count */
505 };
506 u8 response[COMMAND_BUFFER_SIZE];
507 size_t response_len = COMMAND_BUFFER_SIZE;
508 unsigned int properties_off;
509 int ret;
510
abdc7b8a 511 ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
69cd8f06
MR
512 if (ret)
513 return ret;
514
515 /*
516 * In the response buffer, the properties are located after the:
517 * tag (u16), response size (u32), response code (u32),
a322f54f 518 * YES/NO flag (u8), TPM_CAP (u32).
69cd8f06
MR
519 */
520 properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
a322f54f 521 sizeof(u8) + sizeof(u32);
69cd8f06
MR
522 memcpy(buf, &response[properties_off], response_len - properties_off);
523
524 return 0;
525}
da9c3392 526
9d2bc92b
RM
527u32 tpm2_pcr_config_algo(struct udevice *dev, u32 algo_mask,
528 struct tpml_pcr_selection *pcr, u32 *pcr_len)
529{
530 int i;
531
532 if (pcr->count > TPM2_NUM_PCR_BANKS)
533 return TPM_LIB_ERROR;
534
535 *pcr_len = sizeof(pcr->count);
536
537 for (i = 0; i < pcr->count; i++) {
538 struct tpms_pcr_selection *sel = &pcr->selection[i];
539 u8 pad = 0;
540 int j;
541
542 if (sel->size_of_select > TPM2_PCR_SELECT_MAX)
543 return TPM_LIB_ERROR;
544
545 /*
546 * Found the algorithm (bank) that matches, and enable all PCR
547 * bits.
548 * TODO: only select the bits needed
549 */
550 for (j = 0; j < ARRAY_SIZE(hash_algo_list); j++) {
551 if (hash_algo_list[j].hash_alg != sel->hash)
552 continue;
553
554 if (algo_mask & hash_algo_list[j].hash_mask)
555 pad = 0xff;
556 }
557
558 for (j = 0; j < sel->size_of_select; j++)
559 sel->pcr_select[j] = pad;
560
561 log_info("set bank[%d] %s %s\n", i,
562 tpm2_algorithm_name(sel->hash),
563 tpm2_is_active_bank(sel) ? "on" : "off");
564
565 *pcr_len += sizeof(sel->hash) + sizeof(sel->size_of_select) +
566 sel->size_of_select;
567 }
568
569 return 0;
570}
571
572u32 tpm2_send_pcr_allocate(struct udevice *dev, const char *pw,
573 const ssize_t pw_sz, struct tpml_pcr_selection *pcr,
574 u32 pcr_len)
575{
576 /* Length of the message header, up to start of password */
577 uint offset = 27;
578 u8 command_v2[COMMAND_BUFFER_SIZE] = {
579 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
580 tpm_u32(offset + pw_sz + pcr_len), /* Length */
581 tpm_u32(TPM2_CC_PCR_ALLOCATE), /* Command code */
582
583 /* handles 4 bytes */
584 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
585
586 /* AUTH_SESSION */
587 tpm_u32(9 + pw_sz), /* Authorization size */
588 tpm_u32(TPM2_RS_PW), /* Session handle */
589 tpm_u16(0), /* Size of <nonce> */
590 /* <nonce> (if any) */
591 0, /* Attributes: Cont/Excl/Rst */
592 tpm_u16(pw_sz), /* Size of <hmac/password> */
593 /* STRING(pw) <hmac/password> (if any) */
594
595 /* TPML_PCR_SELECTION */
596 };
597 u8 response[COMMAND_BUFFER_SIZE];
598 size_t response_len = COMMAND_BUFFER_SIZE;
599 u32 i;
600 int ret;
601
602 /*
603 * Fill the command structure starting from the first buffer:
604 * the password (if any)
605 */
606 if (pack_byte_string(command_v2, sizeof(command_v2), "s", offset, pw,
607 pw_sz))
608 return TPM_LIB_ERROR;
609
610 offset += pw_sz;
611
612 /* Pack the count field */
613 if (pack_byte_string(command_v2, sizeof(command_v2), "d", offset, pcr->count))
614 return TPM_LIB_ERROR;
615
616 offset += sizeof(pcr->count);
617
618 /* Pack each tpms_pcr_selection */
619 for (i = 0; i < pcr->count; i++) {
620 struct tpms_pcr_selection *sel = &pcr->selection[i];
621
622 /* Pack hash (16-bit) */
623 if (pack_byte_string(command_v2, sizeof(command_v2), "w", offset,
624 sel->hash))
625 return TPM_LIB_ERROR;
626
627 offset += sizeof(sel->hash);
628
629 /* Pack size_of_select (8-bit) */
630 if (pack_byte_string(command_v2, sizeof(command_v2), "b", offset,
631 sel->size_of_select))
632 return TPM_LIB_ERROR;
633
634 offset += sizeof(sel->size_of_select);
635
636 /* Pack pcr_select array */
637 if (pack_byte_string(command_v2, sizeof(command_v2), "s", offset,
638 sel->pcr_select, sel->size_of_select))
639 return TPM_LIB_ERROR;
640
641 offset += sel->size_of_select;
642 }
643
644 ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
645 if (!ret)
646 tpm_init(dev);
647
648 return ret;
649}
650
97707f12
EJ
651static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
652{
653 u8 response[(sizeof(struct tpms_capability_data) -
654 offsetof(struct tpms_capability_data, data))];
655 u32 properties_offset =
656 offsetof(struct tpml_tagged_tpm_property, tpm_property) +
657 offsetof(struct tpms_tagged_property, value);
658 u32 ret;
659
660 memset(response, 0, sizeof(response));
661 ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
662 TPM2_PT_PCR_COUNT, response, 1);
663 if (ret)
664 return ret;
665
666 *num_pcr = get_unaligned_be32(response + properties_offset);
667 if (*num_pcr > TPM2_MAX_PCRS) {
668 printf("%s: too many pcrs: %u\n", __func__, *num_pcr);
669 return -E2BIG;
670 }
671
672 return 0;
673}
674
cba3fa90 675int tpm2_get_pcr_info(struct udevice *dev, struct tpml_pcr_selection *pcrs)
97707f12
EJ
676{
677 u8 response[(sizeof(struct tpms_capability_data) -
678 offsetof(struct tpms_capability_data, data))];
97707f12
EJ
679 u32 num_pcr;
680 size_t i;
681 u32 ret;
682
97707f12
EJ
683 ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
684 if (ret)
685 return ret;
686
cba3fa90 687 pcrs->count = get_unaligned_be32(response);
97707f12 688 /*
e7505b3b 689 * We only support 4 algorithms for now so check against that
97707f12
EJ
690 * instead of TPM2_NUM_PCR_BANKS
691 */
e7505b3b 692 if (pcrs->count > 4 || pcrs->count < 1) {
cba3fa90 693 printf("%s: too many pcrs: %u\n", __func__, pcrs->count);
97707f12
EJ
694 return -EMSGSIZE;
695 }
696
697 ret = tpm2_get_num_pcr(dev, &num_pcr);
698 if (ret)
699 return ret;
700
cba3fa90 701 for (i = 0; i < pcrs->count; i++) {
97707f12
EJ
702 /*
703 * Definition of TPMS_PCR_SELECTION Structure
704 * hash: u16
705 * size_of_select: u8
706 * pcr_select: u8 array
707 *
708 * The offsets depend on the number of the device PCRs
709 * so we have to calculate them based on that
710 */
711 u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
712 i * offsetof(struct tpms_pcr_selection, pcr_select) +
713 i * ((num_pcr + 7) / 8);
714 u32 size_select_offset =
715 hash_offset + offsetof(struct tpms_pcr_selection,
716 size_of_select);
717 u32 pcr_select_offset =
718 hash_offset + offsetof(struct tpms_pcr_selection,
719 pcr_select);
720
cba3fa90 721 pcrs->selection[i].hash =
97707f12 722 get_unaligned_be16(response + hash_offset);
cba3fa90 723 pcrs->selection[i].size_of_select =
97707f12 724 __get_unaligned_be(response + size_select_offset);
cba3fa90 725 if (pcrs->selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
97707f12 726 printf("%s: pcrs selection too large: %u\n", __func__,
cba3fa90 727 pcrs->selection[i].size_of_select);
97707f12
EJ
728 return -ENOBUFS;
729 }
730 /* copy the array of pcr_select */
cba3fa90
IA
731 memcpy(pcrs->selection[i].pcr_select, response + pcr_select_offset,
732 pcrs->selection[i].size_of_select);
97707f12
EJ
733 }
734
97707f12
EJ
735 return 0;
736}
737
abdc7b8a 738u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
da9c3392
MR
739{
740 u8 command_v2[COMMAND_BUFFER_SIZE] = {
741 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
742 tpm_u32(27 + pw_sz), /* Length */
743 tpm_u32(TPM2_CC_DAM_RESET), /* Command code */
744
745 /* HANDLE */
746 tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */
747
748 /* AUTH_SESSION */
749 tpm_u32(9 + pw_sz), /* Authorization size */
750 tpm_u32(TPM2_RS_PW), /* Session handle */
751 tpm_u16(0), /* Size of <nonce> */
752 /* <nonce> (if any) */
753 0, /* Attributes: Cont/Excl/Rst */
754 tpm_u16(pw_sz), /* Size of <hmac/password> */
755 /* STRING(pw) <hmac/password> (if any) */
756 };
757 unsigned int offset = 27;
758 int ret;
759
760 /*
761 * Fill the command structure starting from the first buffer:
762 * - the password (if any)
763 */
764 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
765 offset, pw, pw_sz);
766 offset += pw_sz;
767 if (ret)
768 return TPM_LIB_ERROR;
769
abdc7b8a 770 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
da9c3392
MR
771}
772
abdc7b8a
SG
773u32 tpm2_dam_parameters(struct udevice *dev, const char *pw,
774 const ssize_t pw_sz, unsigned int max_tries,
775 unsigned int recovery_time,
da9c3392
MR
776 unsigned int lockout_recovery)
777{
778 u8 command_v2[COMMAND_BUFFER_SIZE] = {
779 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
780 tpm_u32(27 + pw_sz + 12), /* Length */
781 tpm_u32(TPM2_CC_DAM_PARAMETERS), /* Command code */
782
783 /* HANDLE */
784 tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */
785
786 /* AUTH_SESSION */
787 tpm_u32(9 + pw_sz), /* Authorization size */
788 tpm_u32(TPM2_RS_PW), /* Session handle */
789 tpm_u16(0), /* Size of <nonce> */
790 /* <nonce> (if any) */
791 0, /* Attributes: Cont/Excl/Rst */
792 tpm_u16(pw_sz), /* Size of <hmac/password> */
793 /* STRING(pw) <hmac/password> (if any) */
794
795 /* LOCKOUT PARAMETERS */
796 /* tpm_u32(max_tries) Max tries (0, always lock) */
797 /* tpm_u32(recovery_time) Recovery time (0, no lock) */
798 /* tpm_u32(lockout_recovery) Lockout recovery */
799 };
800 unsigned int offset = 27;
801 int ret;
802
803 /*
804 * Fill the command structure starting from the first buffer:
805 * - the password (if any)
806 * - max tries
807 * - recovery time
808 * - lockout recovery
809 */
810 ret = pack_byte_string(command_v2, sizeof(command_v2), "sddd",
811 offset, pw, pw_sz,
812 offset + pw_sz, max_tries,
813 offset + pw_sz + 4, recovery_time,
814 offset + pw_sz + 8, lockout_recovery);
815 offset += pw_sz + 12;
816 if (ret)
817 return TPM_LIB_ERROR;
818
abdc7b8a 819 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
da9c3392 820}
dc26e913 821
abdc7b8a
SG
822int tpm2_change_auth(struct udevice *dev, u32 handle, const char *newpw,
823 const ssize_t newpw_sz, const char *oldpw,
824 const ssize_t oldpw_sz)
dc26e913
MR
825{
826 unsigned int offset = 27;
827 u8 command_v2[COMMAND_BUFFER_SIZE] = {
828 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
829 tpm_u32(offset + oldpw_sz + 2 + newpw_sz), /* Length */
830 tpm_u32(TPM2_CC_HIERCHANGEAUTH), /* Command code */
831
832 /* HANDLE */
833 tpm_u32(handle), /* TPM resource handle */
834
835 /* AUTH_SESSION */
836 tpm_u32(9 + oldpw_sz), /* Authorization size */
837 tpm_u32(TPM2_RS_PW), /* Session handle */
838 tpm_u16(0), /* Size of <nonce> */
839 /* <nonce> (if any) */
840 0, /* Attributes: Cont/Excl/Rst */
841 tpm_u16(oldpw_sz) /* Size of <hmac/password> */
842 /* STRING(oldpw) <hmac/password> (if any) */
843
844 /* TPM2B_AUTH (TPM2B_DIGEST) */
845 /* tpm_u16(newpw_sz) Digest size, new pw length */
846 /* STRING(newpw) Digest buffer, new pw */
847 };
848 int ret;
849
850 /*
851 * Fill the command structure starting from the first buffer:
852 * - the old password (if any)
853 * - size of the new password
854 * - new password
855 */
856 ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
857 offset, oldpw, oldpw_sz,
858 offset + oldpw_sz, newpw_sz,
859 offset + oldpw_sz + 2, newpw, newpw_sz);
860 offset += oldpw_sz + 2 + newpw_sz;
861 if (ret)
862 return TPM_LIB_ERROR;
863
abdc7b8a 864 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
dc26e913 865}
b9dd4fab 866
abdc7b8a
SG
867u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
868 const ssize_t pw_sz, u32 index, const char *key)
b9dd4fab
MR
869{
870 u8 command_v2[COMMAND_BUFFER_SIZE] = {
871 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
872 tpm_u32(35 + pw_sz + TPM2_DIGEST_LEN), /* Length */
873 tpm_u32(TPM2_CC_PCR_SETAUTHPOL), /* Command code */
874
875 /* HANDLE */
876 tpm_u32(TPM2_RH_PLATFORM), /* TPM resource handle */
877
878 /* AUTH_SESSION */
879 tpm_u32(9 + pw_sz), /* Authorization size */
880 tpm_u32(TPM2_RS_PW), /* session handle */
881 tpm_u16(0), /* Size of <nonce> */
882 /* <nonce> (if any) */
883 0, /* Attributes: Cont/Excl/Rst */
884 tpm_u16(pw_sz) /* Size of <hmac/password> */
885 /* STRING(pw) <hmac/password> (if any) */
886
887 /* TPM2B_AUTH (TPM2B_DIGEST) */
888 /* tpm_u16(TPM2_DIGEST_LEN) Digest size length */
889 /* STRING(key) Digest buffer (PCR key) */
890
891 /* TPMI_ALG_HASH */
892 /* tpm_u16(TPM2_ALG_SHA256) Algorithm of the hash */
893
894 /* TPMI_DH_PCR */
895 /* tpm_u32(index), PCR Index */
896 };
897 unsigned int offset = 27;
898 int ret;
899
900 /*
901 * Fill the command structure starting from the first buffer:
902 * - the password (if any)
903 * - the PCR key length
904 * - the PCR key
905 * - the hash algorithm
906 * - the PCR index
907 */
908 ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd",
909 offset, pw, pw_sz,
910 offset + pw_sz, TPM2_DIGEST_LEN,
911 offset + pw_sz + 2, key, TPM2_DIGEST_LEN,
912 offset + pw_sz + 2 + TPM2_DIGEST_LEN,
913 TPM2_ALG_SHA256,
914 offset + pw_sz + 4 + TPM2_DIGEST_LEN, index);
915 offset += pw_sz + 2 + TPM2_DIGEST_LEN + 2 + 4;
916 if (ret)
917 return TPM_LIB_ERROR;
918
abdc7b8a 919 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
b9dd4fab
MR
920}
921
abdc7b8a
SG
922u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
923 const ssize_t pw_sz, u32 index, const char *key,
924 const ssize_t key_sz)
b9dd4fab
MR
925{
926 u8 command_v2[COMMAND_BUFFER_SIZE] = {
927 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
928 tpm_u32(33 + pw_sz + TPM2_DIGEST_LEN), /* Length */
929 tpm_u32(TPM2_CC_PCR_SETAUTHVAL), /* Command code */
930
931 /* HANDLE */
932 tpm_u32(index), /* Handle (PCR Index) */
933
934 /* AUTH_SESSION */
935 tpm_u32(9 + pw_sz), /* Authorization size */
936 tpm_u32(TPM2_RS_PW), /* session handle */
937 tpm_u16(0), /* Size of <nonce> */
938 /* <nonce> (if any) */
939 0, /* Attributes: Cont/Excl/Rst */
940 tpm_u16(pw_sz), /* Size of <hmac/password> */
941 /* STRING(pw) <hmac/password> (if any) */
942
943 /* TPM2B_DIGEST */
944 /* tpm_u16(key_sz) Key length */
945 /* STRING(key) Key */
946 };
947 unsigned int offset = 27;
948 int ret;
949
950 /*
951 * Fill the command structure starting from the first buffer:
952 * - the password (if any)
953 * - the number of digests, 1 in our case
954 * - the algorithm, sha256 in our case
955 * - the digest (64 bytes)
956 */
957 ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
958 offset, pw, pw_sz,
959 offset + pw_sz, key_sz,
960 offset + pw_sz + 2, key, key_sz);
961 offset += pw_sz + 2 + key_sz;
962 if (ret)
963 return TPM_LIB_ERROR;
964
abdc7b8a 965 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
b9dd4fab 966}
06bea498
DP
967
968u32 tpm2_get_random(struct udevice *dev, void *data, u32 count)
969{
970 const u8 command_v2[10] = {
971 tpm_u16(TPM2_ST_NO_SESSIONS),
972 tpm_u32(12),
973 tpm_u32(TPM2_CC_GET_RANDOM),
974 };
975 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
976
977 const size_t data_size_offset = 10;
978 const size_t data_offset = 12;
979 size_t response_length = sizeof(response);
980 u32 data_size;
981 u8 *out = data;
982
983 while (count > 0) {
984 u32 this_bytes = min((size_t)count,
985 sizeof(response) - data_offset);
986 u32 err;
987
988 if (pack_byte_string(buf, sizeof(buf), "sw",
989 0, command_v2, sizeof(command_v2),
990 sizeof(command_v2), this_bytes))
991 return TPM_LIB_ERROR;
992 err = tpm_sendrecv_command(dev, buf, response,
993 &response_length);
994 if (err)
995 return err;
996 if (unpack_byte_string(response, response_length, "w",
997 data_size_offset, &data_size))
998 return TPM_LIB_ERROR;
999 if (data_size > this_bytes)
1000 return TPM_LIB_ERROR;
1001 if (unpack_byte_string(response, response_length, "s",
1002 data_offset, out, data_size))
1003 return TPM_LIB_ERROR;
1004
1005 count -= data_size;
1006 out += data_size;
1007 }
1008
1009 return 0;
1010}
7785bc1d
SG
1011
1012u32 tpm2_write_lock(struct udevice *dev, u32 index)
1013{
1014 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1015 /* header 10 bytes */
1016 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1017 tpm_u32(10 + 8 + 13), /* Length */
1018 tpm_u32(TPM2_CC_NV_WRITELOCK), /* Command code */
1019
1020 /* handles 8 bytes */
1021 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
1022 tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
1023
1024 /* session header 9 bytes */
1025 tpm_u32(9), /* Header size */
1026 tpm_u32(TPM2_RS_PW), /* Password authorisation */
1027 tpm_u16(0), /* nonce_size */
1028 0, /* session_attrs */
1029 tpm_u16(0), /* auth_size */
1030 };
1031
1032 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1033}
63af92e8
SG
1034
1035u32 tpm2_disable_platform_hierarchy(struct udevice *dev)
1036{
1037 struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
1038 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1039 /* header 10 bytes */
1040 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1041 tpm_u32(10 + 4 + 13 + 5), /* Length */
1042 tpm_u32(TPM2_CC_HIER_CONTROL), /* Command code */
1043
1044 /* 4 bytes */
1045 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
1046
1047 /* session header 9 bytes */
1048 tpm_u32(9), /* Header size */
1049 tpm_u32(TPM2_RS_PW), /* Password authorisation */
1050 tpm_u16(0), /* nonce_size */
1051 0, /* session_attrs */
1052 tpm_u16(0), /* auth_size */
1053
1054 /* payload 5 bytes */
1055 tpm_u32(TPM2_RH_PLATFORM), /* Hierarchy to disable */
1056 0, /* 0=disable */
1057 };
1058 int ret;
1059
1060 ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1061 log_info("ret=%s, %x\n", dev->name, ret);
1062 if (ret)
1063 return ret;
1064
1065 priv->plat_hier_disabled = true;
1066
1067 return 0;
1068}
7fc93cae
MK
1069
1070u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
1071 u8 *recvbuf, size_t *recv_size)
1072{
1073 return tpm_sendrecv_command(dev, sendbuf, recvbuf, recv_size);
1074}
4c57ec76
SG
1075
1076u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
1077 u8 *recvbuf, size_t *recv_size)
1078{
1079 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1080 /* header 10 bytes */
1081 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
1082 tpm_u32(10 + 2), /* Length */
1083 tpm_u32(vendor_cmd), /* Command code */
1084
1085 tpm_u16(vendor_subcmd),
1086 };
1087 int ret;
1088
1089 ret = tpm_sendrecv_command(dev, command_v2, recvbuf, recv_size);
1090 log_debug("ret=%s, %x\n", dev->name, ret);
1091 if (ret)
1092 return ret;
1093 if (*recv_size < 12)
1094 return -ENODATA;
1095 *recv_size -= 12;
6c717d95 1096 memmove(recvbuf, recvbuf + 12, *recv_size);
4c57ec76
SG
1097
1098 return 0;
1099}
5208ed18
SG
1100
1101u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
1102 uint vendor_subcmd)
1103{
1104 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1105 /* header 10 bytes */
1106 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
1107 tpm_u32(10 + 2), /* Length */
1108 tpm_u32(vendor_cmd), /* Command code */
1109
1110 tpm_u16(vendor_subcmd),
1111 };
1112 int ret;
1113
1114 ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1115 log_debug("ret=%s, %x\n", dev->name, ret);
1116 if (ret)
1117 return ret;
1118
1119 return 0;
1120}
954b95e7 1121
dbe08c7b 1122bool tpm2_is_active_bank(struct tpms_pcr_selection *selection)
cba3fa90
IA
1123{
1124 int i;
1125
1126 for (i = 0; i < selection->size_of_select; i++) {
1127 if (selection->pcr_select[i])
1128 return true;
1129 }
1130
1131 return false;
1132}
1133
954b95e7
TH
1134enum tpm2_algorithms tpm2_name_to_algorithm(const char *name)
1135{
1136 size_t i;
1137
1138 for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
1139 if (!strcasecmp(name, hash_algo_list[i].hash_name))
1140 return hash_algo_list[i].hash_alg;
1141 }
1142 printf("%s: unsupported algorithm %s\n", __func__, name);
1143
1144 return -EINVAL;
1145}
1146
1147const char *tpm2_algorithm_name(enum tpm2_algorithms algo)
1148{
1149 size_t i;
1150
1151 for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
1152 if (hash_algo_list[i].hash_alg == algo)
1153 return hash_algo_list[i].hash_name;
1154 }
1155
1156 return "";
1157}
1158
27891e85
RM
1159bool tpm2_algorithm_supported(enum tpm2_algorithms algo)
1160{
1161 size_t i;
1162
1163 for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
1164 if (hash_algo_list[i].hash_alg == algo)
1165 return hash_algo_list[i].supported;
1166 }
1167
1168 return false;
1169}
1170
e7505b3b
IA
1171u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo)
1172{
1173 size_t i;
1174
1175 for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
1176 if (hash_algo_list[i].hash_alg == algo)
1177 return hash_algo_list[i].hash_len;
1178 }
1179
1180 return 0;
1181}
1182
0698f133 1183bool tpm2_check_active_banks(struct udevice *dev)
e7505b3b
IA
1184{
1185 struct tpml_pcr_selection pcrs;
1186 size_t i;
1187 int rc;
1188
1189 rc = tpm2_get_pcr_info(dev, &pcrs);
1190 if (rc)
1191 return false;
1192
1193 for (i = 0; i < pcrs.count; i++) {
dbe08c7b 1194 if (tpm2_is_active_bank(&pcrs.selection[i]) &&
27891e85 1195 !tpm2_algorithm_supported(pcrs.selection[i].hash))
e7505b3b
IA
1196 return false;
1197 }
1198
1199 return true;
1200}
8dc886ce
IA
1201
1202void tpm2_print_active_banks(struct udevice *dev)
1203{
1204 struct tpml_pcr_selection pcrs;
1205 size_t i;
1206 int rc;
1207
1208 rc = tpm2_get_pcr_info(dev, &pcrs);
1209 if (rc) {
1210 log_err("Can't retrieve active PCRs\n");
1211 return;
1212 }
1213
1214 for (i = 0; i < pcrs.count; i++) {
1215 if (tpm2_is_active_bank(&pcrs.selection[i])) {
1216 const char *str;
1217
1218 str = tpm2_algorithm_name(pcrs.selection[i].hash);
1219 if (str)
1220 log_info("%s\n", str);
1221 }
1222 }
1223}
This page took 0.315963 seconds and 5 git commands to generate.