1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2023 Linaro Limited
4 * Copyright (c) 2018 Bootlin
5 * Author: Miquel Raynal <miquel.raynal@bootlin.com>
9 #include <dm/of_access.h>
11 #include <tpm-common.h>
14 #include <u-boot/sha1.h>
15 #include <u-boot/sha256.h>
16 #include <u-boot/sha512.h>
17 #include <version_string.h>
19 #include <linux/bitops.h>
20 #include <linux/unaligned/be_byteshift.h>
21 #include <linux/unaligned/generic.h>
22 #include <linux/unaligned/le_byteshift.h>
24 #include "tpm-utils.h"
26 u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
28 const u8 command_v2[12] = {
29 tpm_u16(TPM2_ST_NO_SESSIONS),
31 tpm_u32(TPM2_CC_STARTUP),
37 * Note TPM2_Startup command will return RC_SUCCESS the first time,
38 * but will return RC_INITIALIZE otherwise.
40 ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
41 if (ret && ret != TPM2_RC_INITIALIZE)
47 u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
49 const u8 command_v2[12] = {
50 tpm_u16(TPM2_ST_NO_SESSIONS),
52 tpm_u32(TPM2_CC_SELF_TEST),
56 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
59 u32 tpm2_auto_start(struct udevice *dev)
63 rc = tpm2_self_test(dev, TPMI_YES);
65 if (rc == TPM2_RC_INITIALIZE) {
66 rc = tpm2_startup(dev, TPM2_SU_CLEAR);
70 rc = tpm2_self_test(dev, TPMI_YES);
76 u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
79 /* Length of the message header, up to start of password */
81 u8 command_v2[COMMAND_BUFFER_SIZE] = {
82 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
83 tpm_u32(offset + pw_sz), /* Length */
84 tpm_u32(TPM2_CC_CLEAR), /* Command code */
87 tpm_u32(handle), /* TPM resource handle */
90 tpm_u32(9 + pw_sz), /* Authorization size */
91 tpm_u32(TPM2_RS_PW), /* Session handle */
92 tpm_u16(0), /* Size of <nonce> */
93 /* <nonce> (if any) */
94 0, /* Attributes: Cont/Excl/Rst */
95 tpm_u16(pw_sz), /* Size of <hmac/password> */
96 /* STRING(pw) <hmac/password> (if any) */
101 * Fill the command structure starting from the first buffer:
102 * - the password (if any)
104 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
108 return TPM_LIB_ERROR;
110 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
113 u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
114 size_t space_size, u32 nv_attributes,
115 const u8 *nv_policy, size_t nv_policy_size)
118 * Calculate the offset of the nv_policy piece by adding each of the
121 const int platform_len = sizeof(u32);
122 const int session_hdr_len = 13;
123 const int message_len = 14;
124 uint offset = TPM2_HDR_LEN + platform_len + session_hdr_len +
126 u8 command_v2[COMMAND_BUFFER_SIZE] = {
127 /* header 10 bytes */
128 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
129 tpm_u32(offset + nv_policy_size + 2),/* Length */
130 tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
132 /* handles 4 bytes */
133 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
135 /* session header 13 bytes */
136 tpm_u32(9), /* Header size */
137 tpm_u32(TPM2_RS_PW), /* Password authorisation */
138 tpm_u16(0), /* nonce_size */
139 0, /* session_attrs */
140 tpm_u16(0), /* auth_size */
142 /* message 14 bytes + policy */
143 tpm_u16(message_len + nv_policy_size), /* size */
144 tpm_u32(space_index),
145 tpm_u16(TPM2_ALG_SHA256),
146 tpm_u32(nv_attributes),
147 tpm_u16(nv_policy_size),
156 * Fill the command structure starting from the first buffer:
157 * - the password (if any)
159 ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
160 offset, nv_policy, nv_policy_size,
161 offset + nv_policy_size, space_size);
163 return TPM_LIB_ERROR;
165 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
168 u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
169 const u8 *digest, u32 digest_len)
171 /* Length of the message header, up to start of digest */
173 u8 command_v2[COMMAND_BUFFER_SIZE] = {
174 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
175 tpm_u32(offset + digest_len), /* Length */
176 tpm_u32(TPM2_CC_PCR_EXTEND), /* Command code */
179 tpm_u32(index), /* Handle (PCR Index) */
182 tpm_u32(9), /* Authorization size */
183 tpm_u32(TPM2_RS_PW), /* Session handle */
184 tpm_u16(0), /* Size of <nonce> */
185 /* <nonce> (if any) */
186 0, /* Attributes: Cont/Excl/Rst */
187 tpm_u16(0), /* Size of <hmac/password> */
188 /* <hmac/password> (if any) */
191 tpm_u32(1), /* Count (number of hashes) */
192 tpm_u16(algorithm), /* Algorithm of the hash */
193 /* STRING(digest) Digest */
200 if (!tpm2_allow_extend(dev)) {
201 log_err("Cannot extend PCRs if all the TPM enabled algorithms are not supported\n");
205 * Fill the command structure starting from the first buffer:
208 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
209 offset, digest, digest_len);
211 return TPM_LIB_ERROR;
213 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
216 u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
218 u8 command_v2[COMMAND_BUFFER_SIZE] = {
219 /* header 10 bytes */
220 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
221 tpm_u32(10 + 8 + 4 + 9 + 4), /* Length */
222 tpm_u32(TPM2_CC_NV_READ), /* Command code */
224 /* handles 8 bytes */
225 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
226 tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
229 tpm_u32(9), /* Authorization size */
230 tpm_u32(TPM2_RS_PW), /* Session handle */
231 tpm_u16(0), /* Size of <nonce> */
232 /* <nonce> (if any) */
233 0, /* Attributes: Cont/Excl/Rst */
234 tpm_u16(0), /* Size of <hmac/password> */
235 /* <hmac/password> (if any) */
237 tpm_u16(count), /* Number of bytes */
238 tpm_u16(0), /* Offset */
240 size_t response_len = COMMAND_BUFFER_SIZE;
241 u8 response[COMMAND_BUFFER_SIZE];
246 ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
248 return log_msg_ret("read", ret);
249 if (unpack_byte_string(response, response_len, "wdds",
250 0, &tag, 2, &size, 6, &code,
252 return TPM_LIB_ERROR;
257 u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
260 struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
261 uint offset = 10 + 8 + 4 + 9 + 2;
262 uint len = offset + count + 2;
263 /* Use empty password auth if platform hierarchy is disabled */
264 u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index :
266 u8 command_v2[COMMAND_BUFFER_SIZE] = {
267 /* header 10 bytes */
268 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
269 tpm_u32(len), /* Length */
270 tpm_u32(TPM2_CC_NV_WRITE), /* Command code */
272 /* handles 8 bytes */
273 tpm_u32(auth), /* Primary platform seed */
274 tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
277 tpm_u32(9), /* Authorization size */
278 tpm_u32(TPM2_RS_PW), /* Session handle */
279 tpm_u16(0), /* Size of <nonce> */
280 /* <nonce> (if any) */
281 0, /* Attributes: Cont/Excl/Rst */
282 tpm_u16(0), /* Size of <hmac/password> */
283 /* <hmac/password> (if any) */
287 size_t response_len = COMMAND_BUFFER_SIZE;
288 u8 response[COMMAND_BUFFER_SIZE];
291 ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
295 return TPM_LIB_ERROR;
297 return tpm_sendrecv_command(dev, command_v2, response, &response_len);
300 u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
301 u16 algorithm, void *data, u32 digest_len,
302 unsigned int *updates)
304 u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
305 u8 command_v2[COMMAND_BUFFER_SIZE] = {
306 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
307 tpm_u32(17 + idx_array_sz), /* Length */
308 tpm_u32(TPM2_CC_PCR_READ), /* Command code */
310 /* TPML_PCR_SELECTION */
311 tpm_u32(1), /* Number of selections */
312 tpm_u16(algorithm), /* Algorithm of the hash */
313 idx_array_sz, /* Array size for selection */
314 /* bitmap(idx) Selected PCR bitmap */
316 size_t response_len = COMMAND_BUFFER_SIZE;
317 u8 response[COMMAND_BUFFER_SIZE];
318 unsigned int pcr_sel_idx = idx / 8;
319 u8 pcr_sel_bit = BIT(idx % 8);
320 unsigned int counter = 0;
323 if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b",
324 17 + pcr_sel_idx, pcr_sel_bit))
325 return TPM_LIB_ERROR;
327 ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
331 if (digest_len > response_len)
332 return TPM_LIB_ERROR;
334 if (unpack_byte_string(response, response_len, "ds",
336 response_len - digest_len, data,
338 return TPM_LIB_ERROR;
346 u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
347 void *buf, size_t prop_count)
349 u8 command_v2[COMMAND_BUFFER_SIZE] = {
350 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
351 tpm_u32(22), /* Length */
352 tpm_u32(TPM2_CC_GET_CAPABILITY), /* Command code */
354 tpm_u32(capability), /* Capability */
355 tpm_u32(property), /* Property */
356 tpm_u32(prop_count), /* Property count */
358 u8 response[COMMAND_BUFFER_SIZE];
359 size_t response_len = COMMAND_BUFFER_SIZE;
360 unsigned int properties_off;
363 ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
368 * In the response buffer, the properties are located after the:
369 * tag (u16), response size (u32), response code (u32),
370 * YES/NO flag (u8), TPM_CAP (u32).
372 properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
373 sizeof(u8) + sizeof(u32);
374 memcpy(buf, &response[properties_off], response_len - properties_off);
379 static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
381 u8 response[(sizeof(struct tpms_capability_data) -
382 offsetof(struct tpms_capability_data, data))];
383 u32 properties_offset =
384 offsetof(struct tpml_tagged_tpm_property, tpm_property) +
385 offsetof(struct tpms_tagged_property, value);
388 memset(response, 0, sizeof(response));
389 ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
390 TPM2_PT_PCR_COUNT, response, 1);
394 *num_pcr = get_unaligned_be32(response + properties_offset);
395 if (*num_pcr > TPM2_MAX_PCRS) {
396 printf("%s: too many pcrs: %u\n", __func__, *num_pcr);
403 int tpm2_get_pcr_info(struct udevice *dev, struct tpml_pcr_selection *pcrs)
405 u8 response[(sizeof(struct tpms_capability_data) -
406 offsetof(struct tpms_capability_data, data))];
411 ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
415 pcrs->count = get_unaligned_be32(response);
417 * We only support 4 algorithms for now so check against that
418 * instead of TPM2_NUM_PCR_BANKS
420 if (pcrs->count > 4 || pcrs->count < 1) {
421 printf("%s: too many pcrs: %u\n", __func__, pcrs->count);
425 ret = tpm2_get_num_pcr(dev, &num_pcr);
429 for (i = 0; i < pcrs->count; i++) {
431 * Definition of TPMS_PCR_SELECTION Structure
434 * pcr_select: u8 array
436 * The offsets depend on the number of the device PCRs
437 * so we have to calculate them based on that
439 u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
440 i * offsetof(struct tpms_pcr_selection, pcr_select) +
441 i * ((num_pcr + 7) / 8);
442 u32 size_select_offset =
443 hash_offset + offsetof(struct tpms_pcr_selection,
445 u32 pcr_select_offset =
446 hash_offset + offsetof(struct tpms_pcr_selection,
449 pcrs->selection[i].hash =
450 get_unaligned_be16(response + hash_offset);
451 pcrs->selection[i].size_of_select =
452 __get_unaligned_be(response + size_select_offset);
453 if (pcrs->selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
454 printf("%s: pcrs selection too large: %u\n", __func__,
455 pcrs->selection[i].size_of_select);
458 /* copy the array of pcr_select */
459 memcpy(pcrs->selection[i].pcr_select, response + pcr_select_offset,
460 pcrs->selection[i].size_of_select);
466 u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
468 u8 command_v2[COMMAND_BUFFER_SIZE] = {
469 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
470 tpm_u32(27 + pw_sz), /* Length */
471 tpm_u32(TPM2_CC_DAM_RESET), /* Command code */
474 tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */
477 tpm_u32(9 + pw_sz), /* Authorization size */
478 tpm_u32(TPM2_RS_PW), /* Session handle */
479 tpm_u16(0), /* Size of <nonce> */
480 /* <nonce> (if any) */
481 0, /* Attributes: Cont/Excl/Rst */
482 tpm_u16(pw_sz), /* Size of <hmac/password> */
483 /* STRING(pw) <hmac/password> (if any) */
485 unsigned int offset = 27;
489 * Fill the command structure starting from the first buffer:
490 * - the password (if any)
492 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
496 return TPM_LIB_ERROR;
498 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
501 u32 tpm2_dam_parameters(struct udevice *dev, const char *pw,
502 const ssize_t pw_sz, unsigned int max_tries,
503 unsigned int recovery_time,
504 unsigned int lockout_recovery)
506 u8 command_v2[COMMAND_BUFFER_SIZE] = {
507 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
508 tpm_u32(27 + pw_sz + 12), /* Length */
509 tpm_u32(TPM2_CC_DAM_PARAMETERS), /* Command code */
512 tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */
515 tpm_u32(9 + pw_sz), /* Authorization size */
516 tpm_u32(TPM2_RS_PW), /* Session handle */
517 tpm_u16(0), /* Size of <nonce> */
518 /* <nonce> (if any) */
519 0, /* Attributes: Cont/Excl/Rst */
520 tpm_u16(pw_sz), /* Size of <hmac/password> */
521 /* STRING(pw) <hmac/password> (if any) */
523 /* LOCKOUT PARAMETERS */
524 /* tpm_u32(max_tries) Max tries (0, always lock) */
525 /* tpm_u32(recovery_time) Recovery time (0, no lock) */
526 /* tpm_u32(lockout_recovery) Lockout recovery */
528 unsigned int offset = 27;
532 * Fill the command structure starting from the first buffer:
533 * - the password (if any)
538 ret = pack_byte_string(command_v2, sizeof(command_v2), "sddd",
540 offset + pw_sz, max_tries,
541 offset + pw_sz + 4, recovery_time,
542 offset + pw_sz + 8, lockout_recovery);
543 offset += pw_sz + 12;
545 return TPM_LIB_ERROR;
547 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
550 int tpm2_change_auth(struct udevice *dev, u32 handle, const char *newpw,
551 const ssize_t newpw_sz, const char *oldpw,
552 const ssize_t oldpw_sz)
554 unsigned int offset = 27;
555 u8 command_v2[COMMAND_BUFFER_SIZE] = {
556 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
557 tpm_u32(offset + oldpw_sz + 2 + newpw_sz), /* Length */
558 tpm_u32(TPM2_CC_HIERCHANGEAUTH), /* Command code */
561 tpm_u32(handle), /* TPM resource handle */
564 tpm_u32(9 + oldpw_sz), /* Authorization size */
565 tpm_u32(TPM2_RS_PW), /* Session handle */
566 tpm_u16(0), /* Size of <nonce> */
567 /* <nonce> (if any) */
568 0, /* Attributes: Cont/Excl/Rst */
569 tpm_u16(oldpw_sz) /* Size of <hmac/password> */
570 /* STRING(oldpw) <hmac/password> (if any) */
572 /* TPM2B_AUTH (TPM2B_DIGEST) */
573 /* tpm_u16(newpw_sz) Digest size, new pw length */
574 /* STRING(newpw) Digest buffer, new pw */
579 * Fill the command structure starting from the first buffer:
580 * - the old password (if any)
581 * - size of the new password
584 ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
585 offset, oldpw, oldpw_sz,
586 offset + oldpw_sz, newpw_sz,
587 offset + oldpw_sz + 2, newpw, newpw_sz);
588 offset += oldpw_sz + 2 + newpw_sz;
590 return TPM_LIB_ERROR;
592 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
595 u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
596 const ssize_t pw_sz, u32 index, const char *key)
598 u8 command_v2[COMMAND_BUFFER_SIZE] = {
599 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
600 tpm_u32(35 + pw_sz + TPM2_DIGEST_LEN), /* Length */
601 tpm_u32(TPM2_CC_PCR_SETAUTHPOL), /* Command code */
604 tpm_u32(TPM2_RH_PLATFORM), /* TPM resource handle */
607 tpm_u32(9 + pw_sz), /* Authorization size */
608 tpm_u32(TPM2_RS_PW), /* session handle */
609 tpm_u16(0), /* Size of <nonce> */
610 /* <nonce> (if any) */
611 0, /* Attributes: Cont/Excl/Rst */
612 tpm_u16(pw_sz) /* Size of <hmac/password> */
613 /* STRING(pw) <hmac/password> (if any) */
615 /* TPM2B_AUTH (TPM2B_DIGEST) */
616 /* tpm_u16(TPM2_DIGEST_LEN) Digest size length */
617 /* STRING(key) Digest buffer (PCR key) */
620 /* tpm_u16(TPM2_ALG_SHA256) Algorithm of the hash */
623 /* tpm_u32(index), PCR Index */
625 unsigned int offset = 27;
629 * Fill the command structure starting from the first buffer:
630 * - the password (if any)
631 * - the PCR key length
633 * - the hash algorithm
636 ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd",
638 offset + pw_sz, TPM2_DIGEST_LEN,
639 offset + pw_sz + 2, key, TPM2_DIGEST_LEN,
640 offset + pw_sz + 2 + TPM2_DIGEST_LEN,
642 offset + pw_sz + 4 + TPM2_DIGEST_LEN, index);
643 offset += pw_sz + 2 + TPM2_DIGEST_LEN + 2 + 4;
645 return TPM_LIB_ERROR;
647 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
650 u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
651 const ssize_t pw_sz, u32 index, const char *key,
652 const ssize_t key_sz)
654 u8 command_v2[COMMAND_BUFFER_SIZE] = {
655 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
656 tpm_u32(33 + pw_sz + TPM2_DIGEST_LEN), /* Length */
657 tpm_u32(TPM2_CC_PCR_SETAUTHVAL), /* Command code */
660 tpm_u32(index), /* Handle (PCR Index) */
663 tpm_u32(9 + pw_sz), /* Authorization size */
664 tpm_u32(TPM2_RS_PW), /* session handle */
665 tpm_u16(0), /* Size of <nonce> */
666 /* <nonce> (if any) */
667 0, /* Attributes: Cont/Excl/Rst */
668 tpm_u16(pw_sz), /* Size of <hmac/password> */
669 /* STRING(pw) <hmac/password> (if any) */
672 /* tpm_u16(key_sz) Key length */
673 /* STRING(key) Key */
675 unsigned int offset = 27;
679 * Fill the command structure starting from the first buffer:
680 * - the password (if any)
681 * - the number of digests, 1 in our case
682 * - the algorithm, sha256 in our case
683 * - the digest (64 bytes)
685 ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
687 offset + pw_sz, key_sz,
688 offset + pw_sz + 2, key, key_sz);
689 offset += pw_sz + 2 + key_sz;
691 return TPM_LIB_ERROR;
693 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
696 u32 tpm2_get_random(struct udevice *dev, void *data, u32 count)
698 const u8 command_v2[10] = {
699 tpm_u16(TPM2_ST_NO_SESSIONS),
701 tpm_u32(TPM2_CC_GET_RANDOM),
703 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
705 const size_t data_size_offset = 10;
706 const size_t data_offset = 12;
707 size_t response_length = sizeof(response);
712 u32 this_bytes = min((size_t)count,
713 sizeof(response) - data_offset);
716 if (pack_byte_string(buf, sizeof(buf), "sw",
717 0, command_v2, sizeof(command_v2),
718 sizeof(command_v2), this_bytes))
719 return TPM_LIB_ERROR;
720 err = tpm_sendrecv_command(dev, buf, response,
724 if (unpack_byte_string(response, response_length, "w",
725 data_size_offset, &data_size))
726 return TPM_LIB_ERROR;
727 if (data_size > this_bytes)
728 return TPM_LIB_ERROR;
729 if (unpack_byte_string(response, response_length, "s",
730 data_offset, out, data_size))
731 return TPM_LIB_ERROR;
740 u32 tpm2_write_lock(struct udevice *dev, u32 index)
742 u8 command_v2[COMMAND_BUFFER_SIZE] = {
743 /* header 10 bytes */
744 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
745 tpm_u32(10 + 8 + 13), /* Length */
746 tpm_u32(TPM2_CC_NV_WRITELOCK), /* Command code */
748 /* handles 8 bytes */
749 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
750 tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
752 /* session header 9 bytes */
753 tpm_u32(9), /* Header size */
754 tpm_u32(TPM2_RS_PW), /* Password authorisation */
755 tpm_u16(0), /* nonce_size */
756 0, /* session_attrs */
757 tpm_u16(0), /* auth_size */
760 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
763 u32 tpm2_disable_platform_hierarchy(struct udevice *dev)
765 struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
766 u8 command_v2[COMMAND_BUFFER_SIZE] = {
767 /* header 10 bytes */
768 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
769 tpm_u32(10 + 4 + 13 + 5), /* Length */
770 tpm_u32(TPM2_CC_HIER_CONTROL), /* Command code */
773 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
775 /* session header 9 bytes */
776 tpm_u32(9), /* Header size */
777 tpm_u32(TPM2_RS_PW), /* Password authorisation */
778 tpm_u16(0), /* nonce_size */
779 0, /* session_attrs */
780 tpm_u16(0), /* auth_size */
782 /* payload 5 bytes */
783 tpm_u32(TPM2_RH_PLATFORM), /* Hierarchy to disable */
788 ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
789 log_info("ret=%s, %x\n", dev->name, ret);
793 priv->plat_hier_disabled = true;
798 u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
799 u8 *recvbuf, size_t *recv_size)
801 return tpm_sendrecv_command(dev, sendbuf, recvbuf, recv_size);
804 u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
805 u8 *recvbuf, size_t *recv_size)
807 u8 command_v2[COMMAND_BUFFER_SIZE] = {
808 /* header 10 bytes */
809 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
810 tpm_u32(10 + 2), /* Length */
811 tpm_u32(vendor_cmd), /* Command code */
813 tpm_u16(vendor_subcmd),
817 ret = tpm_sendrecv_command(dev, command_v2, recvbuf, recv_size);
818 log_debug("ret=%s, %x\n", dev->name, ret);
824 memcpy(recvbuf, recvbuf + 12, *recv_size);
829 u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
832 u8 command_v2[COMMAND_BUFFER_SIZE] = {
833 /* header 10 bytes */
834 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
835 tpm_u32(10 + 2), /* Length */
836 tpm_u32(vendor_cmd), /* Command code */
838 tpm_u16(vendor_subcmd),
842 ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
843 log_debug("ret=%s, %x\n", dev->name, ret);
850 bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
854 for (i = 0; i < selection->size_of_select; i++) {
855 if (selection->pcr_select[i])
862 enum tpm2_algorithms tpm2_name_to_algorithm(const char *name)
866 for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
867 if (!strcasecmp(name, hash_algo_list[i].hash_name))
868 return hash_algo_list[i].hash_alg;
870 printf("%s: unsupported algorithm %s\n", __func__, name);
875 const char *tpm2_algorithm_name(enum tpm2_algorithms algo)
879 for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
880 if (hash_algo_list[i].hash_alg == algo)
881 return hash_algo_list[i].hash_name;
887 u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo)
891 for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
892 if (hash_algo_list[i].hash_alg == algo)
893 return hash_algo_list[i].hash_len;
899 bool tpm2_allow_extend(struct udevice *dev)
901 struct tpml_pcr_selection pcrs;
905 rc = tpm2_get_pcr_info(dev, &pcrs);
909 for (i = 0; i < pcrs.count; i++) {
910 if (tpm2_is_active_pcr(&pcrs.selection[i]) &&
911 !tpm2_algorithm_to_len(pcrs.selection[i].hash))