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>
13 #include <u-boot/sha1.h>
14 #include <u-boot/sha256.h>
15 #include <u-boot/sha512.h>
16 #include <version_string.h>
18 #include <linux/bitops.h>
19 #include <linux/unaligned/be_byteshift.h>
20 #include <linux/unaligned/generic.h>
21 #include <linux/unaligned/le_byteshift.h>
23 #include "tpm-utils.h"
25 const enum tpm2_algorithms tpm2_supported_algorithms[4] = {
32 int tcg2_get_active_pcr_banks(struct udevice *dev, u32 *active_pcr_banks)
39 rc = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
43 *active_pcr_banks = active;
48 u32 tcg2_event_get_size(struct tpml_digest_values *digest_list)
53 len = offsetof(struct tcg_pcr_event2, digests);
54 len += offsetof(struct tpml_digest_values, digests);
55 for (i = 0; i < digest_list->count; ++i) {
56 u16 l = tpm2_algorithm_to_len(digest_list->digests[i].hash_alg);
61 len += l + offsetof(struct tpmt_ha, digest);
68 int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
69 struct tpml_digest_values *digest_list)
71 u8 final[sizeof(union tpmu_ha)];
72 sha256_context ctx_256;
73 sha512_context ctx_512;
80 rc = tcg2_get_active_pcr_banks(dev, &active);
84 digest_list->count = 0;
85 for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
87 tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
92 switch (tpm2_supported_algorithms[i]) {
95 sha1_update(&ctx, input, length);
96 sha1_finish(&ctx, final);
97 len = TPM2_SHA1_DIGEST_SIZE;
100 sha256_starts(&ctx_256);
101 sha256_update(&ctx_256, input, length);
102 sha256_finish(&ctx_256, final);
103 len = TPM2_SHA256_DIGEST_SIZE;
105 case TPM2_ALG_SHA384:
106 sha384_starts(&ctx_512);
107 sha384_update(&ctx_512, input, length);
108 sha384_finish(&ctx_512, final);
109 len = TPM2_SHA384_DIGEST_SIZE;
111 case TPM2_ALG_SHA512:
112 sha512_starts(&ctx_512);
113 sha512_update(&ctx_512, input, length);
114 sha512_finish(&ctx_512, final);
115 len = TPM2_SHA512_DIGEST_SIZE;
118 printf("%s: unsupported algorithm %x\n", __func__,
119 tpm2_supported_algorithms[i]);
123 digest_list->digests[digest_list->count].hash_alg =
124 tpm2_supported_algorithms[i];
125 memcpy(&digest_list->digests[digest_list->count].digest, final,
127 digest_list->count++;
133 void tcg2_log_append(u32 pcr_index, u32 event_type,
134 struct tpml_digest_values *digest_list, u32 size,
135 const u8 *event, u8 *log)
141 pos = offsetof(struct tcg_pcr_event2, pcr_index);
142 put_unaligned_le32(pcr_index, log);
143 pos = offsetof(struct tcg_pcr_event2, event_type);
144 put_unaligned_le32(event_type, log + pos);
145 pos = offsetof(struct tcg_pcr_event2, digests) +
146 offsetof(struct tpml_digest_values, count);
147 put_unaligned_le32(digest_list->count, log + pos);
149 pos = offsetof(struct tcg_pcr_event2, digests) +
150 offsetof(struct tpml_digest_values, digests);
151 for (i = 0; i < digest_list->count; ++i) {
152 u16 hash_alg = digest_list->digests[i].hash_alg;
154 len = tpm2_algorithm_to_len(hash_alg);
158 pos += offsetof(struct tpmt_ha, hash_alg);
159 put_unaligned_le16(hash_alg, log + pos);
160 pos += offsetof(struct tpmt_ha, digest);
161 memcpy(log + pos, (u8 *)&digest_list->digests[i].digest, len);
165 put_unaligned_le32(size, log + pos);
167 memcpy(log + pos, event, size);
170 static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index,
172 struct tpml_digest_values *digest_list,
173 u32 size, const u8 *event)
178 event_size = size + tcg2_event_get_size(digest_list);
179 if (elog->log_position + event_size > elog->log_size) {
180 printf("%s: log too large: %u + %u > %u\n", __func__,
181 elog->log_position, event_size, elog->log_size);
185 log = elog->log + elog->log_position;
186 elog->log_position += event_size;
188 tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
193 static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog)
195 struct tcg_efi_spec_id_event *ev;
196 struct tcg_pcr_event *log;
206 rc = tcg2_get_active_pcr_banks(dev, &active);
210 event_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes);
211 for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
212 mask = tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
214 if (!(active & mask))
217 switch (tpm2_supported_algorithms[i]) {
219 case TPM2_ALG_SHA256:
220 case TPM2_ALG_SHA384:
221 case TPM2_ALG_SHA512:
230 (sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count);
231 log_size = offsetof(struct tcg_pcr_event, event) + event_size;
233 if (log_size > elog->log_size) {
234 printf("%s: log too large: %u > %u\n", __func__, log_size,
239 log = (struct tcg_pcr_event *)elog->log;
240 put_unaligned_le32(0, &log->pcr_index);
241 put_unaligned_le32(EV_NO_ACTION, &log->event_type);
242 memset(&log->digest, 0, sizeof(log->digest));
243 put_unaligned_le32(event_size, &log->event_size);
245 ev = (struct tcg_efi_spec_id_event *)log->event;
246 strlcpy((char *)ev->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
247 sizeof(ev->signature));
248 put_unaligned_le32(0, &ev->platform_class);
249 ev->spec_version_minor = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
250 ev->spec_version_major = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
251 ev->spec_errata = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
252 ev->uintn_size = sizeof(size_t) / sizeof(u32);
253 put_unaligned_le32(count, &ev->number_of_algorithms);
256 for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
257 mask = tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
259 if (!(active & mask))
262 len = tpm2_algorithm_to_len(tpm2_supported_algorithms[i]);
266 put_unaligned_le16(tpm2_supported_algorithms[i],
267 &ev->digest_sizes[count].algorithm_id);
268 put_unaligned_le16(len, &ev->digest_sizes[count].digest_size);
272 *((u8 *)ev + (event_size - 1)) = 0;
273 elog->log_position = log_size;
278 static int tcg2_replay_eventlog(struct tcg2_event_log *elog,
280 struct tpml_digest_values *digest_list,
283 const u32 offset = offsetof(struct tcg_pcr_event2, digests) +
284 offsetof(struct tpml_digest_values, digests);
295 while (log_position + offset < elog->log_size) {
296 log = elog->log + log_position;
298 pos = offsetof(struct tcg_pcr_event2, pcr_index);
299 pcr = get_unaligned_le32(log + pos);
300 pos = offsetof(struct tcg_pcr_event2, event_type);
301 if (!get_unaligned_le32(log + pos))
304 pos = offsetof(struct tcg_pcr_event2, digests) +
305 offsetof(struct tpml_digest_values, count);
306 count = get_unaligned_le32(log + pos);
307 if (count > ARRAY_SIZE(tpm2_supported_algorithms) ||
308 (digest_list->count && digest_list->count != count))
311 pos = offsetof(struct tcg_pcr_event2, digests) +
312 offsetof(struct tpml_digest_values, digests);
313 for (i = 0; i < count; ++i) {
314 pos += offsetof(struct tpmt_ha, hash_alg);
315 if (log_position + pos + sizeof(u16) >= elog->log_size)
318 algo = get_unaligned_le16(log + pos);
319 pos += offsetof(struct tpmt_ha, digest);
322 case TPM2_ALG_SHA256:
323 case TPM2_ALG_SHA384:
324 case TPM2_ALG_SHA512:
325 len = tpm2_algorithm_to_len(algo);
331 if (digest_list->count) {
332 if (algo != digest_list->digests[i].hash_alg ||
333 log_position + pos + len >= elog->log_size)
336 memcpy(digest_list->digests[i].digest.sha512,
343 if (log_position + pos + sizeof(u32) >= elog->log_size)
346 event_size = get_unaligned_le32(log + pos);
347 pos += event_size + sizeof(u32);
348 if (log_position + pos > elog->log_size)
351 if (digest_list->count) {
352 rc = tcg2_pcr_extend(dev, pcr, digest_list);
360 elog->log_position = log_position;
365 static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
367 struct tpml_digest_values digest_list;
368 struct tcg_efi_spec_id_event *event;
369 struct tcg_pcr_event *log;
382 if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
385 log = (struct tcg_pcr_event *)elog->log;
386 if (get_unaligned_le32(&log->pcr_index) != 0 ||
387 get_unaligned_le32(&log->event_type) != EV_NO_ACTION)
390 for (i = 0; i < sizeof(log->digest); i++) {
395 evsz = get_unaligned_le32(&log->event_size);
396 if (evsz < offsetof(struct tcg_efi_spec_id_event, digest_sizes) ||
397 evsz + offsetof(struct tcg_pcr_event, event) > elog->log_size)
400 event = (struct tcg_efi_spec_id_event *)log->event;
401 if (memcmp(event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
402 sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03)))
405 if (event->spec_version_minor != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
406 event->spec_version_major != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
409 count = get_unaligned_le32(&event->number_of_algorithms);
410 if (count > ARRAY_SIZE(tpm2_supported_algorithms))
413 calc_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
414 (sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count) +
416 if (evsz != calc_size)
419 rc = tcg2_get_active_pcr_banks(dev, &active);
423 digest_list.count = 0;
426 for (i = 0; i < count; ++i) {
427 algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id);
428 mask = tpm2_algorithm_to_mask(algo);
430 if (!(active & mask))
435 case TPM2_ALG_SHA256:
436 case TPM2_ALG_SHA384:
437 case TPM2_ALG_SHA512:
438 len = get_unaligned_le16(&event->digest_sizes[i].digest_size);
439 if (tpm2_algorithm_to_len(algo) != len)
441 digest_list.digests[digest_list.count++].hash_alg = algo;
450 /* Ensure the previous firmware extended all the PCRs. */
451 if (log_active != active)
454 /* Read PCR0 to check if previous firmware extended the PCRs or not. */
455 rc = tcg2_pcr_read(dev, 0, &digest_list);
459 for (i = 0; i < digest_list.count; ++i) {
460 len = tpm2_algorithm_to_len(digest_list.digests[i].hash_alg);
461 for (j = 0; j < len; ++j) {
462 if (digest_list.digests[i].digest.sha512[j])
466 /* PCR is non-zero; it has been extended, so skip extending. */
468 digest_list.count = 0;
473 return tcg2_replay_eventlog(elog, dev, &digest_list,
474 offsetof(struct tcg_pcr_event, event) +
478 int tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
479 struct tpml_digest_values *digest_list)
484 for (i = 0; i < digest_list->count; i++) {
485 u32 alg = digest_list->digests[i].hash_alg;
487 rc = tpm2_pcr_extend(dev, pcr_index, alg,
488 (u8 *)&digest_list->digests[i].digest,
489 tpm2_algorithm_to_len(alg));
491 printf("%s: error pcr:%u alg:%08x\n", __func__,
500 int tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
501 struct tpml_digest_values *digest_list)
503 struct tpm_chip_priv *priv;
507 priv = dev_get_uclass_priv(dev);
511 for (i = 0; i < digest_list->count; i++) {
512 u32 alg = digest_list->digests[i].hash_alg;
513 u8 *digest = (u8 *)&digest_list->digests[i].digest;
515 rc = tpm2_pcr_read(dev, pcr_index, priv->pcr_select_min, alg,
516 digest, tpm2_algorithm_to_len(alg), NULL);
518 printf("%s: error pcr:%u alg:%08x\n", __func__,
527 int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
528 u32 pcr_index, u32 size, const u8 *data, u32 event_type,
529 u32 event_size, const u8 *event)
531 struct tpml_digest_values digest_list;
535 rc = tcg2_create_digest(dev, data, size, &digest_list);
537 rc = tcg2_create_digest(dev, event, event_size, &digest_list);
541 rc = tcg2_pcr_extend(dev, pcr_index, &digest_list);
545 return tcg2_log_append_check(elog, pcr_index, event_type, &digest_list,
549 int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
550 bool ignore_existing_log)
552 struct tcg2_event_log log;
555 elog->log_position = 0;
558 rc = tcg2_platform_get_log(dev, (void **)&log.log, &log.log_size);
560 log.log_position = 0;
563 if (!ignore_existing_log) {
564 rc = tcg2_log_parse(dev, &log);
569 if (elog->log_size) {
571 if (elog->log_size < log.log_position)
575 * Copy the discovered log into the user buffer
576 * if there's enough space.
578 memcpy(elog->log, log.log, log.log_position);
581 unmap_physmem(log.log, MAP_NOCACHE);
584 elog->log_size = log.log_size;
587 elog->log_position = log.log_position;
588 elog->found = log.found;
592 * Initialize the log buffer if no log was discovered and the buffer is
593 * valid. User's can pass in their own buffer as a fallback if no
594 * memory region is found.
596 if (!elog->found && elog->log_size)
597 rc = tcg2_log_init(dev, elog);
602 int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog,
603 bool ignore_existing_log)
607 rc = tcg2_platform_get_tpm2(dev);
611 rc = tpm_auto_start(*dev);
615 rc = tcg2_log_prepare_buffer(*dev, elog, ignore_existing_log);
617 tcg2_measurement_term(*dev, elog, true);
621 rc = tcg2_measure_event(*dev, elog, 0, EV_S_CRTM_VERSION,
622 strlen(version_string) + 1,
623 (u8 *)version_string);
625 tcg2_measurement_term(*dev, elog, true);
632 void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
635 u32 event = error ? 0x1 : 0xffffffff;
638 for (i = 0; i < 8; ++i)
639 tcg2_measure_event(dev, elog, i, EV_SEPARATOR, sizeof(event),
643 unmap_physmem(elog->log, MAP_NOCACHE);
646 __weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
648 const __be32 *addr_prop;
649 const __be32 *size_prop;
656 addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize);
658 addr_prop = dev_read_prop(dev, "linux,sml-base", &asize);
660 size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize);
662 size_prop = dev_read_prop(dev, "linux,sml-size", &ssize);
664 if (addr_prop && size_prop) {
665 u64 a = of_read_number(addr_prop, asize / sizeof(__be32));
666 u64 s = of_read_number(size_prop, ssize / sizeof(__be32));
668 *addr = map_physmem(a, s, MAP_NOCACHE);
671 struct ofnode_phandle_args args;
675 if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
679 a = ofnode_get_addr_size(args.node, "reg", &s);
680 if (a == FDT_ADDR_T_NONE)
683 *addr = map_physmem(a, s, MAP_NOCACHE);
690 __weak int tcg2_platform_get_tpm2(struct udevice **dev)
692 for_each_tpm_device(*dev) {
693 if (tpm_get_version(*dev) == TPM_V2)
700 __weak void tcg2_platform_startup_error(struct udevice *dev, int rc) {}
702 u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
704 const u8 command_v2[12] = {
705 tpm_u16(TPM2_ST_NO_SESSIONS),
707 tpm_u32(TPM2_CC_STARTUP),
713 * Note TPM2_Startup command will return RC_SUCCESS the first time,
714 * but will return RC_INITIALIZE otherwise.
716 ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
717 if (ret && ret != TPM2_RC_INITIALIZE)
723 u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
725 const u8 command_v2[12] = {
726 tpm_u16(TPM2_ST_NO_SESSIONS),
728 tpm_u32(TPM2_CC_SELF_TEST),
732 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
735 u32 tpm2_auto_start(struct udevice *dev)
739 rc = tpm2_self_test(dev, TPMI_YES);
741 if (rc == TPM2_RC_INITIALIZE) {
742 rc = tpm2_startup(dev, TPM2_SU_CLEAR);
746 rc = tpm2_self_test(dev, TPMI_YES);
752 u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
755 /* Length of the message header, up to start of password */
757 u8 command_v2[COMMAND_BUFFER_SIZE] = {
758 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
759 tpm_u32(offset + pw_sz), /* Length */
760 tpm_u32(TPM2_CC_CLEAR), /* Command code */
763 tpm_u32(handle), /* TPM resource handle */
766 tpm_u32(9 + pw_sz), /* Authorization size */
767 tpm_u32(TPM2_RS_PW), /* Session handle */
768 tpm_u16(0), /* Size of <nonce> */
769 /* <nonce> (if any) */
770 0, /* Attributes: Cont/Excl/Rst */
771 tpm_u16(pw_sz), /* Size of <hmac/password> */
772 /* STRING(pw) <hmac/password> (if any) */
777 * Fill the command structure starting from the first buffer:
778 * - the password (if any)
780 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
784 return TPM_LIB_ERROR;
786 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
789 u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
790 size_t space_size, u32 nv_attributes,
791 const u8 *nv_policy, size_t nv_policy_size)
794 * Calculate the offset of the nv_policy piece by adding each of the
797 const int platform_len = sizeof(u32);
798 const int session_hdr_len = 13;
799 const int message_len = 14;
800 uint offset = TPM2_HDR_LEN + platform_len + session_hdr_len +
802 u8 command_v2[COMMAND_BUFFER_SIZE] = {
803 /* header 10 bytes */
804 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
805 tpm_u32(offset + nv_policy_size + 2),/* Length */
806 tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
808 /* handles 4 bytes */
809 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
811 /* session header 13 bytes */
812 tpm_u32(9), /* Header size */
813 tpm_u32(TPM2_RS_PW), /* Password authorisation */
814 tpm_u16(0), /* nonce_size */
815 0, /* session_attrs */
816 tpm_u16(0), /* auth_size */
818 /* message 14 bytes + policy */
819 tpm_u16(message_len + nv_policy_size), /* size */
820 tpm_u32(space_index),
821 tpm_u16(TPM2_ALG_SHA256),
822 tpm_u32(nv_attributes),
823 tpm_u16(nv_policy_size),
832 * Fill the command structure starting from the first buffer:
833 * - the password (if any)
835 ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
836 offset, nv_policy, nv_policy_size,
837 offset + nv_policy_size, space_size);
839 return TPM_LIB_ERROR;
841 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
844 u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
845 const u8 *digest, u32 digest_len)
847 /* Length of the message header, up to start of digest */
849 u8 command_v2[COMMAND_BUFFER_SIZE] = {
850 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
851 tpm_u32(offset + digest_len), /* Length */
852 tpm_u32(TPM2_CC_PCR_EXTEND), /* Command code */
855 tpm_u32(index), /* Handle (PCR Index) */
858 tpm_u32(9), /* Authorization size */
859 tpm_u32(TPM2_RS_PW), /* Session handle */
860 tpm_u16(0), /* Size of <nonce> */
861 /* <nonce> (if any) */
862 0, /* Attributes: Cont/Excl/Rst */
863 tpm_u16(0), /* Size of <hmac/password> */
864 /* <hmac/password> (if any) */
867 tpm_u32(1), /* Count (number of hashes) */
868 tpm_u16(algorithm), /* Algorithm of the hash */
869 /* STRING(digest) Digest */
876 * Fill the command structure starting from the first buffer:
879 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
880 offset, digest, digest_len);
882 return TPM_LIB_ERROR;
884 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
887 u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
889 u8 command_v2[COMMAND_BUFFER_SIZE] = {
890 /* header 10 bytes */
891 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
892 tpm_u32(10 + 8 + 4 + 9 + 4), /* Length */
893 tpm_u32(TPM2_CC_NV_READ), /* Command code */
895 /* handles 8 bytes */
896 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
897 tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
900 tpm_u32(9), /* Authorization size */
901 tpm_u32(TPM2_RS_PW), /* Session handle */
902 tpm_u16(0), /* Size of <nonce> */
903 /* <nonce> (if any) */
904 0, /* Attributes: Cont/Excl/Rst */
905 tpm_u16(0), /* Size of <hmac/password> */
906 /* <hmac/password> (if any) */
908 tpm_u16(count), /* Number of bytes */
909 tpm_u16(0), /* Offset */
911 size_t response_len = COMMAND_BUFFER_SIZE;
912 u8 response[COMMAND_BUFFER_SIZE];
917 ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
919 return log_msg_ret("read", ret);
920 if (unpack_byte_string(response, response_len, "wdds",
921 0, &tag, 2, &size, 6, &code,
923 return TPM_LIB_ERROR;
928 u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
931 struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
932 uint offset = 10 + 8 + 4 + 9 + 2;
933 uint len = offset + count + 2;
934 /* Use empty password auth if platform hierarchy is disabled */
935 u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index :
937 u8 command_v2[COMMAND_BUFFER_SIZE] = {
938 /* header 10 bytes */
939 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
940 tpm_u32(len), /* Length */
941 tpm_u32(TPM2_CC_NV_WRITE), /* Command code */
943 /* handles 8 bytes */
944 tpm_u32(auth), /* Primary platform seed */
945 tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
948 tpm_u32(9), /* Authorization size */
949 tpm_u32(TPM2_RS_PW), /* Session handle */
950 tpm_u16(0), /* Size of <nonce> */
951 /* <nonce> (if any) */
952 0, /* Attributes: Cont/Excl/Rst */
953 tpm_u16(0), /* Size of <hmac/password> */
954 /* <hmac/password> (if any) */
958 size_t response_len = COMMAND_BUFFER_SIZE;
959 u8 response[COMMAND_BUFFER_SIZE];
962 ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
966 return TPM_LIB_ERROR;
968 return tpm_sendrecv_command(dev, command_v2, response, &response_len);
971 u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
972 u16 algorithm, void *data, u32 digest_len,
973 unsigned int *updates)
975 u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
976 u8 command_v2[COMMAND_BUFFER_SIZE] = {
977 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
978 tpm_u32(17 + idx_array_sz), /* Length */
979 tpm_u32(TPM2_CC_PCR_READ), /* Command code */
981 /* TPML_PCR_SELECTION */
982 tpm_u32(1), /* Number of selections */
983 tpm_u16(algorithm), /* Algorithm of the hash */
984 idx_array_sz, /* Array size for selection */
985 /* bitmap(idx) Selected PCR bitmap */
987 size_t response_len = COMMAND_BUFFER_SIZE;
988 u8 response[COMMAND_BUFFER_SIZE];
989 unsigned int pcr_sel_idx = idx / 8;
990 u8 pcr_sel_bit = BIT(idx % 8);
991 unsigned int counter = 0;
994 if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b",
995 17 + pcr_sel_idx, pcr_sel_bit))
996 return TPM_LIB_ERROR;
998 ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
1002 if (digest_len > response_len)
1003 return TPM_LIB_ERROR;
1005 if (unpack_byte_string(response, response_len, "ds",
1007 response_len - digest_len, data,
1009 return TPM_LIB_ERROR;
1017 u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
1018 void *buf, size_t prop_count)
1020 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1021 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
1022 tpm_u32(22), /* Length */
1023 tpm_u32(TPM2_CC_GET_CAPABILITY), /* Command code */
1025 tpm_u32(capability), /* Capability */
1026 tpm_u32(property), /* Property */
1027 tpm_u32(prop_count), /* Property count */
1029 u8 response[COMMAND_BUFFER_SIZE];
1030 size_t response_len = COMMAND_BUFFER_SIZE;
1031 unsigned int properties_off;
1034 ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
1039 * In the response buffer, the properties are located after the:
1040 * tag (u16), response size (u32), response code (u32),
1041 * YES/NO flag (u8), TPM_CAP (u32).
1043 properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
1044 sizeof(u8) + sizeof(u32);
1045 memcpy(buf, &response[properties_off], response_len - properties_off);
1050 static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
1052 u8 response[(sizeof(struct tpms_capability_data) -
1053 offsetof(struct tpms_capability_data, data))];
1054 u32 properties_offset =
1055 offsetof(struct tpml_tagged_tpm_property, tpm_property) +
1056 offsetof(struct tpms_tagged_property, value);
1059 memset(response, 0, sizeof(response));
1060 ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
1061 TPM2_PT_PCR_COUNT, response, 1);
1065 *num_pcr = get_unaligned_be32(response + properties_offset);
1066 if (*num_pcr > TPM2_MAX_PCRS) {
1067 printf("%s: too many pcrs: %u\n", __func__, *num_pcr);
1074 static bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
1079 * check the pcr_select. If at least one of the PCRs supports the
1080 * algorithm add it on the active ones
1082 for (i = 0; i < selection->size_of_select; i++) {
1083 if (selection->pcr_select[i])
1090 int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
1093 u8 response[(sizeof(struct tpms_capability_data) -
1094 offsetof(struct tpms_capability_data, data))];
1095 struct tpml_pcr_selection pcrs;
1103 memset(response, 0, sizeof(response));
1104 ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
1108 pcrs.count = get_unaligned_be32(response);
1110 * We only support 5 algorithms for now so check against that
1111 * instead of TPM2_NUM_PCR_BANKS
1113 if (pcrs.count > ARRAY_SIZE(tpm2_supported_algorithms) ||
1115 printf("%s: too many pcrs: %u\n", __func__, pcrs.count);
1119 ret = tpm2_get_num_pcr(dev, &num_pcr);
1123 for (i = 0; i < pcrs.count; i++) {
1125 * Definition of TPMS_PCR_SELECTION Structure
1127 * size_of_select: u8
1128 * pcr_select: u8 array
1130 * The offsets depend on the number of the device PCRs
1131 * so we have to calculate them based on that
1133 u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
1134 i * offsetof(struct tpms_pcr_selection, pcr_select) +
1135 i * ((num_pcr + 7) / 8);
1136 u32 size_select_offset =
1137 hash_offset + offsetof(struct tpms_pcr_selection,
1139 u32 pcr_select_offset =
1140 hash_offset + offsetof(struct tpms_pcr_selection,
1143 pcrs.selection[i].hash =
1144 get_unaligned_be16(response + hash_offset);
1145 pcrs.selection[i].size_of_select =
1146 __get_unaligned_be(response + size_select_offset);
1147 if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
1148 printf("%s: pcrs selection too large: %u\n", __func__,
1149 pcrs.selection[i].size_of_select);
1152 /* copy the array of pcr_select */
1153 memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
1154 pcrs.selection[i].size_of_select);
1157 for (i = 0; i < pcrs.count; i++) {
1158 u32 hash_mask = tpm2_algorithm_to_mask(pcrs.selection[i].hash);
1161 *supported_pcr |= hash_mask;
1162 if (tpm2_is_active_pcr(&pcrs.selection[i]))
1163 *active_pcr |= hash_mask;
1165 printf("%s: unknown algorithm %x\n", __func__,
1166 pcrs.selection[i].hash);
1170 *pcr_banks = pcrs.count;
1175 u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
1177 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1178 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1179 tpm_u32(27 + pw_sz), /* Length */
1180 tpm_u32(TPM2_CC_DAM_RESET), /* Command code */
1183 tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */
1186 tpm_u32(9 + pw_sz), /* Authorization size */
1187 tpm_u32(TPM2_RS_PW), /* Session handle */
1188 tpm_u16(0), /* Size of <nonce> */
1189 /* <nonce> (if any) */
1190 0, /* Attributes: Cont/Excl/Rst */
1191 tpm_u16(pw_sz), /* Size of <hmac/password> */
1192 /* STRING(pw) <hmac/password> (if any) */
1194 unsigned int offset = 27;
1198 * Fill the command structure starting from the first buffer:
1199 * - the password (if any)
1201 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
1205 return TPM_LIB_ERROR;
1207 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1210 u32 tpm2_dam_parameters(struct udevice *dev, const char *pw,
1211 const ssize_t pw_sz, unsigned int max_tries,
1212 unsigned int recovery_time,
1213 unsigned int lockout_recovery)
1215 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1216 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1217 tpm_u32(27 + pw_sz + 12), /* Length */
1218 tpm_u32(TPM2_CC_DAM_PARAMETERS), /* Command code */
1221 tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */
1224 tpm_u32(9 + pw_sz), /* Authorization size */
1225 tpm_u32(TPM2_RS_PW), /* Session handle */
1226 tpm_u16(0), /* Size of <nonce> */
1227 /* <nonce> (if any) */
1228 0, /* Attributes: Cont/Excl/Rst */
1229 tpm_u16(pw_sz), /* Size of <hmac/password> */
1230 /* STRING(pw) <hmac/password> (if any) */
1232 /* LOCKOUT PARAMETERS */
1233 /* tpm_u32(max_tries) Max tries (0, always lock) */
1234 /* tpm_u32(recovery_time) Recovery time (0, no lock) */
1235 /* tpm_u32(lockout_recovery) Lockout recovery */
1237 unsigned int offset = 27;
1241 * Fill the command structure starting from the first buffer:
1242 * - the password (if any)
1245 * - lockout recovery
1247 ret = pack_byte_string(command_v2, sizeof(command_v2), "sddd",
1249 offset + pw_sz, max_tries,
1250 offset + pw_sz + 4, recovery_time,
1251 offset + pw_sz + 8, lockout_recovery);
1252 offset += pw_sz + 12;
1254 return TPM_LIB_ERROR;
1256 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1259 int tpm2_change_auth(struct udevice *dev, u32 handle, const char *newpw,
1260 const ssize_t newpw_sz, const char *oldpw,
1261 const ssize_t oldpw_sz)
1263 unsigned int offset = 27;
1264 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1265 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1266 tpm_u32(offset + oldpw_sz + 2 + newpw_sz), /* Length */
1267 tpm_u32(TPM2_CC_HIERCHANGEAUTH), /* Command code */
1270 tpm_u32(handle), /* TPM resource handle */
1273 tpm_u32(9 + oldpw_sz), /* Authorization size */
1274 tpm_u32(TPM2_RS_PW), /* Session handle */
1275 tpm_u16(0), /* Size of <nonce> */
1276 /* <nonce> (if any) */
1277 0, /* Attributes: Cont/Excl/Rst */
1278 tpm_u16(oldpw_sz) /* Size of <hmac/password> */
1279 /* STRING(oldpw) <hmac/password> (if any) */
1281 /* TPM2B_AUTH (TPM2B_DIGEST) */
1282 /* tpm_u16(newpw_sz) Digest size, new pw length */
1283 /* STRING(newpw) Digest buffer, new pw */
1288 * Fill the command structure starting from the first buffer:
1289 * - the old password (if any)
1290 * - size of the new password
1293 ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
1294 offset, oldpw, oldpw_sz,
1295 offset + oldpw_sz, newpw_sz,
1296 offset + oldpw_sz + 2, newpw, newpw_sz);
1297 offset += oldpw_sz + 2 + newpw_sz;
1299 return TPM_LIB_ERROR;
1301 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1304 u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
1305 const ssize_t pw_sz, u32 index, const char *key)
1307 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1308 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1309 tpm_u32(35 + pw_sz + TPM2_DIGEST_LEN), /* Length */
1310 tpm_u32(TPM2_CC_PCR_SETAUTHPOL), /* Command code */
1313 tpm_u32(TPM2_RH_PLATFORM), /* TPM resource handle */
1316 tpm_u32(9 + pw_sz), /* Authorization size */
1317 tpm_u32(TPM2_RS_PW), /* session handle */
1318 tpm_u16(0), /* Size of <nonce> */
1319 /* <nonce> (if any) */
1320 0, /* Attributes: Cont/Excl/Rst */
1321 tpm_u16(pw_sz) /* Size of <hmac/password> */
1322 /* STRING(pw) <hmac/password> (if any) */
1324 /* TPM2B_AUTH (TPM2B_DIGEST) */
1325 /* tpm_u16(TPM2_DIGEST_LEN) Digest size length */
1326 /* STRING(key) Digest buffer (PCR key) */
1329 /* tpm_u16(TPM2_ALG_SHA256) Algorithm of the hash */
1332 /* tpm_u32(index), PCR Index */
1334 unsigned int offset = 27;
1338 * Fill the command structure starting from the first buffer:
1339 * - the password (if any)
1340 * - the PCR key length
1342 * - the hash algorithm
1345 ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd",
1347 offset + pw_sz, TPM2_DIGEST_LEN,
1348 offset + pw_sz + 2, key, TPM2_DIGEST_LEN,
1349 offset + pw_sz + 2 + TPM2_DIGEST_LEN,
1351 offset + pw_sz + 4 + TPM2_DIGEST_LEN, index);
1352 offset += pw_sz + 2 + TPM2_DIGEST_LEN + 2 + 4;
1354 return TPM_LIB_ERROR;
1356 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1359 u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
1360 const ssize_t pw_sz, u32 index, const char *key,
1361 const ssize_t key_sz)
1363 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1364 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1365 tpm_u32(33 + pw_sz + TPM2_DIGEST_LEN), /* Length */
1366 tpm_u32(TPM2_CC_PCR_SETAUTHVAL), /* Command code */
1369 tpm_u32(index), /* Handle (PCR Index) */
1372 tpm_u32(9 + pw_sz), /* Authorization size */
1373 tpm_u32(TPM2_RS_PW), /* session handle */
1374 tpm_u16(0), /* Size of <nonce> */
1375 /* <nonce> (if any) */
1376 0, /* Attributes: Cont/Excl/Rst */
1377 tpm_u16(pw_sz), /* Size of <hmac/password> */
1378 /* STRING(pw) <hmac/password> (if any) */
1381 /* tpm_u16(key_sz) Key length */
1382 /* STRING(key) Key */
1384 unsigned int offset = 27;
1388 * Fill the command structure starting from the first buffer:
1389 * - the password (if any)
1390 * - the number of digests, 1 in our case
1391 * - the algorithm, sha256 in our case
1392 * - the digest (64 bytes)
1394 ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
1396 offset + pw_sz, key_sz,
1397 offset + pw_sz + 2, key, key_sz);
1398 offset += pw_sz + 2 + key_sz;
1400 return TPM_LIB_ERROR;
1402 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1405 u32 tpm2_get_random(struct udevice *dev, void *data, u32 count)
1407 const u8 command_v2[10] = {
1408 tpm_u16(TPM2_ST_NO_SESSIONS),
1410 tpm_u32(TPM2_CC_GET_RANDOM),
1412 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
1414 const size_t data_size_offset = 10;
1415 const size_t data_offset = 12;
1416 size_t response_length = sizeof(response);
1421 u32 this_bytes = min((size_t)count,
1422 sizeof(response) - data_offset);
1425 if (pack_byte_string(buf, sizeof(buf), "sw",
1426 0, command_v2, sizeof(command_v2),
1427 sizeof(command_v2), this_bytes))
1428 return TPM_LIB_ERROR;
1429 err = tpm_sendrecv_command(dev, buf, response,
1433 if (unpack_byte_string(response, response_length, "w",
1434 data_size_offset, &data_size))
1435 return TPM_LIB_ERROR;
1436 if (data_size > this_bytes)
1437 return TPM_LIB_ERROR;
1438 if (unpack_byte_string(response, response_length, "s",
1439 data_offset, out, data_size))
1440 return TPM_LIB_ERROR;
1449 u32 tpm2_write_lock(struct udevice *dev, u32 index)
1451 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1452 /* header 10 bytes */
1453 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1454 tpm_u32(10 + 8 + 13), /* Length */
1455 tpm_u32(TPM2_CC_NV_WRITELOCK), /* Command code */
1457 /* handles 8 bytes */
1458 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
1459 tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
1461 /* session header 9 bytes */
1462 tpm_u32(9), /* Header size */
1463 tpm_u32(TPM2_RS_PW), /* Password authorisation */
1464 tpm_u16(0), /* nonce_size */
1465 0, /* session_attrs */
1466 tpm_u16(0), /* auth_size */
1469 return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1472 u32 tpm2_disable_platform_hierarchy(struct udevice *dev)
1474 struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
1475 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1476 /* header 10 bytes */
1477 tpm_u16(TPM2_ST_SESSIONS), /* TAG */
1478 tpm_u32(10 + 4 + 13 + 5), /* Length */
1479 tpm_u32(TPM2_CC_HIER_CONTROL), /* Command code */
1482 tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
1484 /* session header 9 bytes */
1485 tpm_u32(9), /* Header size */
1486 tpm_u32(TPM2_RS_PW), /* Password authorisation */
1487 tpm_u16(0), /* nonce_size */
1488 0, /* session_attrs */
1489 tpm_u16(0), /* auth_size */
1491 /* payload 5 bytes */
1492 tpm_u32(TPM2_RH_PLATFORM), /* Hierarchy to disable */
1497 ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1498 log_info("ret=%s, %x\n", dev->name, ret);
1502 priv->plat_hier_disabled = true;
1507 u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
1508 u8 *recvbuf, size_t *recv_size)
1510 return tpm_sendrecv_command(dev, sendbuf, recvbuf, recv_size);
1513 u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
1514 u8 *recvbuf, size_t *recv_size)
1516 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1517 /* header 10 bytes */
1518 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
1519 tpm_u32(10 + 2), /* Length */
1520 tpm_u32(vendor_cmd), /* Command code */
1522 tpm_u16(vendor_subcmd),
1526 ret = tpm_sendrecv_command(dev, command_v2, recvbuf, recv_size);
1527 log_debug("ret=%s, %x\n", dev->name, ret);
1530 if (*recv_size < 12)
1533 memcpy(recvbuf, recvbuf + 12, *recv_size);
1538 u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
1541 u8 command_v2[COMMAND_BUFFER_SIZE] = {
1542 /* header 10 bytes */
1543 tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
1544 tpm_u32(10 + 2), /* Length */
1545 tpm_u32(vendor_cmd), /* Command code */
1547 tpm_u16(vendor_subcmd),
1551 ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1552 log_debug("ret=%s, %x\n", dev->name, ret);