1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2023 Linaro Limited
4 * Copyright (c) 2018 Bootlin
5 * Author: Miquel Raynal <miquel.raynal@bootlin.com>
6 */
7
8#include <dm.h>
9#include <dm/of_access.h>
10#include <tpm_api.h>
11#include <tpm-common.h>
12#include <tpm-v2.h>
13#include <u-boot/sha1.h>
14#include <u-boot/sha256.h>
15#include <u-boot/sha512.h>
16#include <version_string.h>
17#include <asm/io.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>
22
23#include "tpm-utils.h"
24
25int tcg2_get_active_pcr_banks(struct udevice *dev, u32 *active_pcr_banks)
26{
27	u32 supported = 0;
28	u32 pcr_banks = 0;
29	u32 active = 0;
30	int rc;
31
32	rc = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
33	if (rc)
34		return rc;
35
36	*active_pcr_banks = active;
37
38	return 0;
39}
40
41u32 tcg2_event_get_size(struct tpml_digest_values *digest_list)
42{
43	u32 len;
44	size_t i;
45
46	len = offsetof(struct tcg_pcr_event2, digests);
47	len += offsetof(struct tpml_digest_values, digests);
48	for (i = 0; i < digest_list->count; ++i) {
49		u16 l = tpm2_algorithm_to_len(digest_list->digests[i].hash_alg);
50
51		if (!l)
52			continue;
53
54		len += l + offsetof(struct tpmt_ha, digest);
55	}
56	len += sizeof(u32);
57
58	return len;
59}
60
61int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
62		       struct tpml_digest_values *digest_list)
63{
64	u8 final[sizeof(union tpmu_ha)];
65	sha256_context ctx_256;
66	sha512_context ctx_512;
67	sha1_context ctx;
68	u32 active;
69	size_t i;
70	u32 len;
71	int rc;
72
73	rc = tcg2_get_active_pcr_banks(dev, &active);
74	if (rc)
75		return rc;
76
77	digest_list->count = 0;
78	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
79		if (!(active & hash_algo_list[i].hash_mask))
80			continue;
81
82		switch (hash_algo_list[i].hash_alg) {
83		case TPM2_ALG_SHA1:
84			sha1_starts(&ctx);
85			sha1_update(&ctx, input, length);
86			sha1_finish(&ctx, final);
87			len = TPM2_SHA1_DIGEST_SIZE;
88			break;
89		case TPM2_ALG_SHA256:
90			sha256_starts(&ctx_256);
91			sha256_update(&ctx_256, input, length);
92			sha256_finish(&ctx_256, final);
93			len = TPM2_SHA256_DIGEST_SIZE;
94			break;
95		case TPM2_ALG_SHA384:
96			sha384_starts(&ctx_512);
97			sha384_update(&ctx_512, input, length);
98			sha384_finish(&ctx_512, final);
99			len = TPM2_SHA384_DIGEST_SIZE;
100			break;
101		case TPM2_ALG_SHA512:
102			sha512_starts(&ctx_512);
103			sha512_update(&ctx_512, input, length);
104			sha512_finish(&ctx_512, final);
105			len = TPM2_SHA512_DIGEST_SIZE;
106			break;
107		default:
108			printf("%s: unsupported algorithm %x\n", __func__,
109			       hash_algo_list[i].hash_alg);
110			continue;
111		}
112
113		digest_list->digests[digest_list->count].hash_alg =
114			hash_algo_list[i].hash_alg;
115		memcpy(&digest_list->digests[digest_list->count].digest, final,
116		       len);
117		digest_list->count++;
118	}
119
120	return 0;
121}
122
123void tcg2_log_append(u32 pcr_index, u32 event_type,
124		     struct tpml_digest_values *digest_list, u32 size,
125		     const u8 *event, u8 *log)
126{
127	size_t len;
128	size_t pos;
129	u32 i;
130
131	pos = offsetof(struct tcg_pcr_event2, pcr_index);
132	put_unaligned_le32(pcr_index, log);
133	pos = offsetof(struct tcg_pcr_event2, event_type);
134	put_unaligned_le32(event_type, log + pos);
135	pos = offsetof(struct tcg_pcr_event2, digests) +
136		offsetof(struct tpml_digest_values, count);
137	put_unaligned_le32(digest_list->count, log + pos);
138
139	pos = offsetof(struct tcg_pcr_event2, digests) +
140		offsetof(struct tpml_digest_values, digests);
141	for (i = 0; i < digest_list->count; ++i) {
142		u16 hash_alg = digest_list->digests[i].hash_alg;
143
144		len = tpm2_algorithm_to_len(hash_alg);
145		if (!len)
146			continue;
147
148		pos += offsetof(struct tpmt_ha, hash_alg);
149		put_unaligned_le16(hash_alg, log + pos);
150		pos += offsetof(struct tpmt_ha, digest);
151		memcpy(log + pos, (u8 *)&digest_list->digests[i].digest, len);
152		pos += len;
153	}
154
155	put_unaligned_le32(size, log + pos);
156	pos += sizeof(u32);
157	memcpy(log + pos, event, size);
158}
159
160static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index,
161				 u32 event_type,
162				 struct tpml_digest_values *digest_list,
163				 u32 size, const u8 *event)
164{
165	u32 event_size;
166	u8 *log;
167
168	event_size = size + tcg2_event_get_size(digest_list);
169	if (elog->log_position + event_size > elog->log_size) {
170		printf("%s: log too large: %u + %u > %u\n", __func__,
171		       elog->log_position, event_size, elog->log_size);
172		return -ENOBUFS;
173	}
174
175	log = elog->log + elog->log_position;
176	elog->log_position += event_size;
177
178	tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
179
180	return 0;
181}
182
183static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog)
184{
185	struct tcg_efi_spec_id_event *ev;
186	struct tcg_pcr_event *log;
187	u32 event_size;
188	u32 count = 0;
189	u32 log_size;
190	u32 active;
191	size_t i;
192	u16 len;
193	int rc;
194
195	rc = tcg2_get_active_pcr_banks(dev, &active);
196	if (rc)
197		return rc;
198
199	event_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes);
200	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
201		if (!(active & hash_algo_list[i].hash_mask))
202			continue;
203
204		switch (hash_algo_list[i].hash_alg) {
205		case TPM2_ALG_SHA1:
206		case TPM2_ALG_SHA256:
207		case TPM2_ALG_SHA384:
208		case TPM2_ALG_SHA512:
209			count++;
210			break;
211		default:
212			continue;
213		}
214	}
215
216	event_size += 1 +
217		(sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count);
218	log_size = offsetof(struct tcg_pcr_event, event) + event_size;
219
220	if (log_size > elog->log_size) {
221		printf("%s: log too large: %u > %u\n", __func__, log_size,
222		       elog->log_size);
223		return -ENOBUFS;
224	}
225
226	log = (struct tcg_pcr_event *)elog->log;
227	put_unaligned_le32(0, &log->pcr_index);
228	put_unaligned_le32(EV_NO_ACTION, &log->event_type);
229	memset(&log->digest, 0, sizeof(log->digest));
230	put_unaligned_le32(event_size, &log->event_size);
231
232	ev = (struct tcg_efi_spec_id_event *)log->event;
233	strlcpy((char *)ev->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
234		sizeof(ev->signature));
235	put_unaligned_le32(0, &ev->platform_class);
236	ev->spec_version_minor = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
237	ev->spec_version_major = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
238	ev->spec_errata = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
239	ev->uintn_size = sizeof(size_t) / sizeof(u32);
240	put_unaligned_le32(count, &ev->number_of_algorithms);
241
242	count = 0;
243	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
244		if (!(active & hash_algo_list[i].hash_mask))
245			continue;
246
247		len = hash_algo_list[i].hash_len;
248		if (!len)
249			continue;
250
251		put_unaligned_le16(hash_algo_list[i].hash_alg,
252				   &ev->digest_sizes[count].algorithm_id);
253		put_unaligned_le16(len, &ev->digest_sizes[count].digest_size);
254		count++;
255	}
256
257	*((u8 *)ev + (event_size - 1)) = 0;
258	elog->log_position = log_size;
259
260	return 0;
261}
262
263static int tcg2_replay_eventlog(struct tcg2_event_log *elog,
264				struct udevice *dev,
265				struct tpml_digest_values *digest_list,
266				u32 log_position)
267{
268	const u32 offset = offsetof(struct tcg_pcr_event2, digests) +
269		offsetof(struct tpml_digest_values, digests);
270	u32 event_size;
271	u32 count;
272	u16 algo;
273	u32 pcr;
274	u32 pos;
275	u16 len;
276	u8 *log;
277	int rc;
278	u32 i;
279
280	while (log_position + offset < elog->log_size) {
281		log = elog->log + log_position;
282
283		pos = offsetof(struct tcg_pcr_event2, pcr_index);
284		pcr = get_unaligned_le32(log + pos);
285		pos = offsetof(struct tcg_pcr_event2, event_type);
286		if (!get_unaligned_le32(log + pos))
287			return 0;
288
289		pos = offsetof(struct tcg_pcr_event2, digests) +
290			offsetof(struct tpml_digest_values, count);
291		count = get_unaligned_le32(log + pos);
292		if (count > ARRAY_SIZE(hash_algo_list) ||
293		    (digest_list->count && digest_list->count != count))
294			return 0;
295
296		pos = offsetof(struct tcg_pcr_event2, digests) +
297			offsetof(struct tpml_digest_values, digests);
298		for (i = 0; i < count; ++i) {
299			pos += offsetof(struct tpmt_ha, hash_alg);
300			if (log_position + pos + sizeof(u16) >= elog->log_size)
301				return 0;
302
303			algo = get_unaligned_le16(log + pos);
304			pos += offsetof(struct tpmt_ha, digest);
305			switch (algo) {
306			case TPM2_ALG_SHA1:
307			case TPM2_ALG_SHA256:
308			case TPM2_ALG_SHA384:
309			case TPM2_ALG_SHA512:
310				len = tpm2_algorithm_to_len(algo);
311				break;
312			default:
313				return 0;
314			}
315
316			if (digest_list->count) {
317				if (algo != digest_list->digests[i].hash_alg ||
318				    log_position + pos + len >= elog->log_size)
319					return 0;
320
321				memcpy(digest_list->digests[i].digest.sha512,
322				       log + pos, len);
323			}
324
325			pos += len;
326		}
327
328		if (log_position + pos + sizeof(u32) >= elog->log_size)
329			return 0;
330
331		event_size = get_unaligned_le32(log + pos);
332		pos += event_size + sizeof(u32);
333		if (log_position + pos > elog->log_size)
334			return 0;
335
336		if (digest_list->count) {
337			rc = tcg2_pcr_extend(dev, pcr, digest_list);
338			if (rc)
339				return rc;
340		}
341
342		log_position += pos;
343	}
344
345	elog->log_position = log_position;
346	elog->found = true;
347	return 0;
348}
349
350static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
351{
352	struct tpml_digest_values digest_list;
353	struct tcg_efi_spec_id_event *event;
354	struct tcg_pcr_event *log;
355	u32 log_active;
356	u32 calc_size;
357	u32 active;
358	u32 count;
359	u32 evsz;
360	u32 mask;
361	u16 algo;
362	u16 len;
363	int rc;
364	u32 i;
365	u16 j;
366
367	if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
368		return 0;
369
370	log = (struct tcg_pcr_event *)elog->log;
371	if (get_unaligned_le32(&log->pcr_index) != 0 ||
372	    get_unaligned_le32(&log->event_type) != EV_NO_ACTION)
373		return 0;
374
375	for (i = 0; i < sizeof(log->digest); i++) {
376		if (log->digest[i])
377			return 0;
378	}
379
380	evsz = get_unaligned_le32(&log->event_size);
381	if (evsz < offsetof(struct tcg_efi_spec_id_event, digest_sizes) ||
382	    evsz + offsetof(struct tcg_pcr_event, event) > elog->log_size)
383		return 0;
384
385	event = (struct tcg_efi_spec_id_event *)log->event;
386	if (memcmp(event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
387		   sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03)))
388		return 0;
389
390	if (event->spec_version_minor != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
391	    event->spec_version_major != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
392		return 0;
393
394	count = get_unaligned_le32(&event->number_of_algorithms);
395	if (count > ARRAY_SIZE(hash_algo_list))
396		return 0;
397
398	calc_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
399		(sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count) +
400		1;
401	if (evsz != calc_size)
402		return 0;
403
404	rc = tcg2_get_active_pcr_banks(dev, &active);
405	if (rc)
406		return rc;
407
408	digest_list.count = 0;
409	log_active = 0;
410
411	for (i = 0; i < count; ++i) {
412		algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id);
413		mask = tpm2_algorithm_to_mask(algo);
414
415		if (!(active & mask))
416			return 0;
417
418		switch (algo) {
419		case TPM2_ALG_SHA1:
420		case TPM2_ALG_SHA256:
421		case TPM2_ALG_SHA384:
422		case TPM2_ALG_SHA512:
423			len = get_unaligned_le16(&event->digest_sizes[i].digest_size);
424			if (tpm2_algorithm_to_len(algo) != len)
425				return 0;
426			digest_list.digests[digest_list.count++].hash_alg = algo;
427			break;
428		default:
429			return 0;
430		}
431
432		log_active |= mask;
433	}
434
435	/* Ensure the previous firmware extended all the PCRs. */
436	if (log_active != active)
437		return 0;
438
439	/* Read PCR0 to check if previous firmware extended the PCRs or not. */
440	rc = tcg2_pcr_read(dev, 0, &digest_list);
441	if (rc)
442		return rc;
443
444	for (i = 0; i < digest_list.count; ++i) {
445		len = tpm2_algorithm_to_len(digest_list.digests[i].hash_alg);
446		for (j = 0; j < len; ++j) {
447			if (digest_list.digests[i].digest.sha512[j])
448				break;
449		}
450
451		/* PCR is non-zero; it has been extended, so skip extending. */
452		if (j != len) {
453			digest_list.count = 0;
454			break;
455		}
456	}
457
458	return tcg2_replay_eventlog(elog, dev, &digest_list,
459				    offsetof(struct tcg_pcr_event, event) +
460				    evsz);
461}
462
463int tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
464		    struct tpml_digest_values *digest_list)
465{
466	u32 rc;
467	u32 i;
468
469	for (i = 0; i < digest_list->count; i++) {
470		u32 alg = digest_list->digests[i].hash_alg;
471
472		rc = tpm2_pcr_extend(dev, pcr_index, alg,
473				     (u8 *)&digest_list->digests[i].digest,
474				     tpm2_algorithm_to_len(alg));
475		if (rc) {
476			printf("%s: error pcr:%u alg:%08x\n", __func__,
477			       pcr_index, alg);
478			return rc;
479		}
480	}
481
482	return 0;
483}
484
485int tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
486		  struct tpml_digest_values *digest_list)
487{
488	struct tpm_chip_priv *priv;
489	u32 rc;
490	u32 i;
491
492	priv = dev_get_uclass_priv(dev);
493	if (!priv)
494		return -ENODEV;
495
496	for (i = 0; i < digest_list->count; i++) {
497		u32 alg = digest_list->digests[i].hash_alg;
498		u8 *digest = (u8 *)&digest_list->digests[i].digest;
499
500		rc = tpm2_pcr_read(dev, pcr_index, priv->pcr_select_min, alg,
501				   digest, tpm2_algorithm_to_len(alg), NULL);
502		if (rc) {
503			printf("%s: error pcr:%u alg:%08x\n", __func__,
504			       pcr_index, alg);
505			return rc;
506		}
507	}
508
509	return 0;
510}
511
512int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
513		      u32 pcr_index, u32 size, const u8 *data, u32 event_type,
514		      u32 event_size, const u8 *event)
515{
516	struct tpml_digest_values digest_list;
517	int rc;
518
519	if (data)
520		rc = tcg2_create_digest(dev, data, size, &digest_list);
521	else
522		rc = tcg2_create_digest(dev, event, event_size, &digest_list);
523	if (rc)
524		return rc;
525
526	rc = tcg2_pcr_extend(dev, pcr_index, &digest_list);
527	if (rc)
528		return rc;
529
530	return tcg2_log_append_check(elog, pcr_index, event_type, &digest_list,
531				     event_size, event);
532}
533
534int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
535			    bool ignore_existing_log)
536{
537	struct tcg2_event_log log;
538	int rc;
539
540	elog->log_position = 0;
541	elog->found = false;
542
543	rc = tcg2_platform_get_log(dev, (void **)&log.log, &log.log_size);
544	if (!rc) {
545		log.log_position = 0;
546		log.found = false;
547
548		if (!ignore_existing_log) {
549			rc = tcg2_log_parse(dev, &log);
550			if (rc)
551				return rc;
552		}
553
554		if (elog->log_size) {
555			if (log.found) {
556				if (elog->log_size < log.log_position)
557					return -ENOSPC;
558
559				/*
560				 * Copy the discovered log into the user buffer
561				 * if there's enough space.
562				 */
563				memcpy(elog->log, log.log, log.log_position);
564			}
565
566			unmap_physmem(log.log, MAP_NOCACHE);
567		} else {
568			elog->log = log.log;
569			elog->log_size = log.log_size;
570		}
571
572		elog->log_position = log.log_position;
573		elog->found = log.found;
574	}
575
576	/*
577	 * Initialize the log buffer if no log was discovered and the buffer is
578	 * valid. User's can pass in their own buffer as a fallback if no
579	 * memory region is found.
580	 */
581	if (!elog->found && elog->log_size)
582		rc = tcg2_log_init(dev, elog);
583
584	return rc;
585}
586
587int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog,
588			  bool ignore_existing_log)
589{
590	int rc;
591
592	rc = tcg2_platform_get_tpm2(dev);
593	if (rc)
594		return rc;
595
596	rc = tpm_auto_start(*dev);
597	if (rc)
598		return rc;
599
600	rc = tcg2_log_prepare_buffer(*dev, elog, ignore_existing_log);
601	if (rc) {
602		tcg2_measurement_term(*dev, elog, true);
603		return rc;
604	}
605
606	rc = tcg2_measure_event(*dev, elog, 0, EV_S_CRTM_VERSION,
607				strlen(version_string) + 1,
608				(u8 *)version_string);
609	if (rc) {
610		tcg2_measurement_term(*dev, elog, true);
611		return rc;
612	}
613
614	return 0;
615}
616
617void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
618			   bool error)
619{
620	u32 event = error ? 0x1 : 0xffffffff;
621	int i;
622
623	for (i = 0; i < 8; ++i)
624		tcg2_measure_event(dev, elog, i, EV_SEPARATOR, sizeof(event),
625				   (const u8 *)&event);
626
627	if (elog->log)
628		unmap_physmem(elog->log, MAP_NOCACHE);
629}
630
631__weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
632{
633	const __be32 *addr_prop;
634	const __be32 *size_prop;
635	int asize;
636	int ssize;
637
638	*addr = NULL;
639	*size = 0;
640
641	addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize);
642	if (!addr_prop)
643		addr_prop = dev_read_prop(dev, "linux,sml-base", &asize);
644
645	size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize);
646	if (!size_prop)
647		size_prop = dev_read_prop(dev, "linux,sml-size", &ssize);
648
649	if (addr_prop && size_prop) {
650		u64 a = of_read_number(addr_prop, asize / sizeof(__be32));
651		u64 s = of_read_number(size_prop, ssize / sizeof(__be32));
652
653		*addr = map_physmem(a, s, MAP_NOCACHE);
654		*size = (u32)s;
655	} else {
656		struct ofnode_phandle_args args;
657		phys_addr_t a;
658		fdt_size_t s;
659
660		if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
661					       0, &args))
662			return -ENODEV;
663
664		a = ofnode_get_addr_size(args.node, "reg", &s);
665		if (a == FDT_ADDR_T_NONE)
666			return -ENOMEM;
667
668		*addr = map_physmem(a, s, MAP_NOCACHE);
669		*size = (u32)s;
670	}
671
672	return 0;
673}
674
675__weak int tcg2_platform_get_tpm2(struct udevice **dev)
676{
677	for_each_tpm_device(*dev) {
678		if (tpm_get_version(*dev) == TPM_V2)
679			return 0;
680	}
681
682	return -ENODEV;
683}
684
685__weak void tcg2_platform_startup_error(struct udevice *dev, int rc) {}
686
687u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
688{
689	const u8 command_v2[12] = {
690		tpm_u16(TPM2_ST_NO_SESSIONS),
691		tpm_u32(12),
692		tpm_u32(TPM2_CC_STARTUP),
693		tpm_u16(mode),
694	};
695	int ret;
696
697	/*
698	 * Note TPM2_Startup command will return RC_SUCCESS the first time,
699	 * but will return RC_INITIALIZE otherwise.
700	 */
701	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
702	if (ret && ret != TPM2_RC_INITIALIZE)
703		return ret;
704
705	return 0;
706}
707
708u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
709{
710	const u8 command_v2[12] = {
711		tpm_u16(TPM2_ST_NO_SESSIONS),
712		tpm_u32(11),
713		tpm_u32(TPM2_CC_SELF_TEST),
714		full_test,
715	};
716
717	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
718}
719
720u32 tpm2_auto_start(struct udevice *dev)
721{
722	u32 rc;
723
724	rc = tpm2_self_test(dev, TPMI_YES);
725
726	if (rc == TPM2_RC_INITIALIZE) {
727		rc = tpm2_startup(dev, TPM2_SU_CLEAR);
728		if (rc)
729			return rc;
730
731		rc = tpm2_self_test(dev, TPMI_YES);
732	}
733
734	return rc;
735}
736
737u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
738	       const ssize_t pw_sz)
739{
740	/* Length of the message header, up to start of password */
741	uint offset = 27;
742	u8 command_v2[COMMAND_BUFFER_SIZE] = {
743		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
744		tpm_u32(offset + pw_sz),	/* Length */
745		tpm_u32(TPM2_CC_CLEAR),		/* Command code */
746
747		/* HANDLE */
748		tpm_u32(handle),		/* TPM resource handle */
749
750		/* AUTH_SESSION */
751		tpm_u32(9 + pw_sz),		/* Authorization size */
752		tpm_u32(TPM2_RS_PW),		/* Session handle */
753		tpm_u16(0),			/* Size of <nonce> */
754						/* <nonce> (if any) */
755		0,				/* Attributes: Cont/Excl/Rst */
756		tpm_u16(pw_sz),			/* Size of <hmac/password> */
757		/* STRING(pw)			   <hmac/password> (if any) */
758	};
759	int ret;
760
761	/*
762	 * Fill the command structure starting from the first buffer:
763	 *     - the password (if any)
764	 */
765	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
766			       offset, pw, pw_sz);
767	offset += pw_sz;
768	if (ret)
769		return TPM_LIB_ERROR;
770
771	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
772}
773
774u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
775			 size_t space_size, u32 nv_attributes,
776			 const u8 *nv_policy, size_t nv_policy_size)
777{
778	/*
779	 * Calculate the offset of the nv_policy piece by adding each of the
780	 * chunks below.
781	 */
782	const int platform_len = sizeof(u32);
783	const int session_hdr_len = 13;
784	const int message_len = 14;
785	uint offset = TPM2_HDR_LEN + platform_len + session_hdr_len +
786		message_len;
787	u8 command_v2[COMMAND_BUFFER_SIZE] = {
788		/* header 10 bytes */
789		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
790		tpm_u32(offset + nv_policy_size + 2),/* Length */
791		tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
792
793		/* handles 4 bytes */
794		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
795
796		/* session header 13 bytes */
797		tpm_u32(9),			/* Header size */
798		tpm_u32(TPM2_RS_PW),		/* Password authorisation */
799		tpm_u16(0),			/* nonce_size */
800		0,				/* session_attrs */
801		tpm_u16(0),			/* auth_size */
802
803		/* message 14 bytes + policy */
804		tpm_u16(message_len + nv_policy_size),	/* size */
805		tpm_u32(space_index),
806		tpm_u16(TPM2_ALG_SHA256),
807		tpm_u32(nv_attributes),
808		tpm_u16(nv_policy_size),
809		/*
810		 * nv_policy
811		 * space_size
812		 */
813	};
814	int ret;
815
816	/*
817	 * Fill the command structure starting from the first buffer:
818	 *     - the password (if any)
819	 */
820	ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
821			       offset, nv_policy, nv_policy_size,
822			       offset + nv_policy_size, space_size);
823	if (ret)
824		return TPM_LIB_ERROR;
825
826	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
827}
828
829u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
830		    const u8 *digest, u32 digest_len)
831{
832	/* Length of the message header, up to start of digest */
833	uint offset = 33;
834	u8 command_v2[COMMAND_BUFFER_SIZE] = {
835		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
836		tpm_u32(offset + digest_len),	/* Length */
837		tpm_u32(TPM2_CC_PCR_EXTEND),	/* Command code */
838
839		/* HANDLE */
840		tpm_u32(index),			/* Handle (PCR Index) */
841
842		/* AUTH_SESSION */
843		tpm_u32(9),			/* Authorization size */
844		tpm_u32(TPM2_RS_PW),		/* Session handle */
845		tpm_u16(0),			/* Size of <nonce> */
846						/* <nonce> (if any) */
847		0,				/* Attributes: Cont/Excl/Rst */
848		tpm_u16(0),			/* Size of <hmac/password> */
849						/* <hmac/password> (if any) */
850
851		/* hashes */
852		tpm_u32(1),			/* Count (number of hashes) */
853		tpm_u16(algorithm),	/* Algorithm of the hash */
854		/* STRING(digest)		   Digest */
855	};
856	int ret;
857
858	if (!digest)
859		return -EINVAL;
860	/*
861	 * Fill the command structure starting from the first buffer:
862	 *     - the digest
863	 */
864	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
865			       offset, digest, digest_len);
866	if (ret)
867		return TPM_LIB_ERROR;
868
869	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
870}
871
872u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
873{
874	u8 command_v2[COMMAND_BUFFER_SIZE] = {
875		/* header 10 bytes */
876		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
877		tpm_u32(10 + 8 + 4 + 9 + 4),	/* Length */
878		tpm_u32(TPM2_CC_NV_READ),	/* Command code */
879
880		/* handles 8 bytes */
881		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
882		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
883
884		/* AUTH_SESSION */
885		tpm_u32(9),			/* Authorization size */
886		tpm_u32(TPM2_RS_PW),		/* Session handle */
887		tpm_u16(0),			/* Size of <nonce> */
888						/* <nonce> (if any) */
889		0,				/* Attributes: Cont/Excl/Rst */
890		tpm_u16(0),			/* Size of <hmac/password> */
891						/* <hmac/password> (if any) */
892
893		tpm_u16(count),			/* Number of bytes */
894		tpm_u16(0),			/* Offset */
895	};
896	size_t response_len = COMMAND_BUFFER_SIZE;
897	u8 response[COMMAND_BUFFER_SIZE];
898	int ret;
899	u16 tag;
900	u32 size, code;
901
902	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
903	if (ret)
904		return log_msg_ret("read", ret);
905	if (unpack_byte_string(response, response_len, "wdds",
906			       0, &tag, 2, &size, 6, &code,
907			       16, data, count))
908		return TPM_LIB_ERROR;
909
910	return 0;
911}
912
913u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
914			u32 count)
915{
916	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
917	uint offset = 10 + 8 + 4 + 9 + 2;
918	uint len = offset + count + 2;
919	/* Use empty password auth if platform hierarchy is disabled */
920	u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index :
921		TPM2_RH_PLATFORM;
922	u8 command_v2[COMMAND_BUFFER_SIZE] = {
923		/* header 10 bytes */
924		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
925		tpm_u32(len),			/* Length */
926		tpm_u32(TPM2_CC_NV_WRITE),	/* Command code */
927
928		/* handles 8 bytes */
929		tpm_u32(auth),			/* Primary platform seed */
930		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
931
932		/* AUTH_SESSION */
933		tpm_u32(9),			/* Authorization size */
934		tpm_u32(TPM2_RS_PW),		/* Session handle */
935		tpm_u16(0),			/* Size of <nonce> */
936						/* <nonce> (if any) */
937		0,				/* Attributes: Cont/Excl/Rst */
938		tpm_u16(0),			/* Size of <hmac/password> */
939						/* <hmac/password> (if any) */
940
941		tpm_u16(count),
942	};
943	size_t response_len = COMMAND_BUFFER_SIZE;
944	u8 response[COMMAND_BUFFER_SIZE];
945	int ret;
946
947	ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
948			       offset, data, count,
949			       offset + count, 0);
950	if (ret)
951		return TPM_LIB_ERROR;
952
953	return tpm_sendrecv_command(dev, command_v2, response, &response_len);
954}
955
956u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
957		  u16 algorithm, void *data, u32 digest_len,
958		  unsigned int *updates)
959{
960	u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
961	u8 command_v2[COMMAND_BUFFER_SIZE] = {
962		tpm_u16(TPM2_ST_NO_SESSIONS),	/* TAG */
963		tpm_u32(17 + idx_array_sz),	/* Length */
964		tpm_u32(TPM2_CC_PCR_READ),	/* Command code */
965
966		/* TPML_PCR_SELECTION */
967		tpm_u32(1),			/* Number of selections */
968		tpm_u16(algorithm),		/* Algorithm of the hash */
969		idx_array_sz,			/* Array size for selection */
970		/* bitmap(idx)			   Selected PCR bitmap */
971	};
972	size_t response_len = COMMAND_BUFFER_SIZE;
973	u8 response[COMMAND_BUFFER_SIZE];
974	unsigned int pcr_sel_idx = idx / 8;
975	u8 pcr_sel_bit = BIT(idx % 8);
976	unsigned int counter = 0;
977	int ret;
978
979	if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b",
980			     17 + pcr_sel_idx, pcr_sel_bit))
981		return TPM_LIB_ERROR;
982
983	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
984	if (ret)
985		return ret;
986
987	if (digest_len > response_len)
988		return TPM_LIB_ERROR;
989
990	if (unpack_byte_string(response, response_len, "ds",
991			       10, &counter,
992			       response_len - digest_len, data,
993			       digest_len))
994		return TPM_LIB_ERROR;
995
996	if (updates)
997		*updates = counter;
998
999	return 0;
1000}
1001
1002u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
1003			void *buf, size_t prop_count)
1004{
1005	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1006		tpm_u16(TPM2_ST_NO_SESSIONS),		/* TAG */
1007		tpm_u32(22),				/* Length */
1008		tpm_u32(TPM2_CC_GET_CAPABILITY),	/* Command code */
1009
1010		tpm_u32(capability),			/* Capability */
1011		tpm_u32(property),			/* Property */
1012		tpm_u32(prop_count),			/* Property count */
1013	};
1014	u8 response[COMMAND_BUFFER_SIZE];
1015	size_t response_len = COMMAND_BUFFER_SIZE;
1016	unsigned int properties_off;
1017	int ret;
1018
1019	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
1020	if (ret)
1021		return ret;
1022
1023	/*
1024	 * In the response buffer, the properties are located after the:
1025	 * tag (u16), response size (u32), response code (u32),
1026	 * YES/NO flag (u8), TPM_CAP (u32).
1027	 */
1028	properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
1029			 sizeof(u8) + sizeof(u32);
1030	memcpy(buf, &response[properties_off], response_len - properties_off);
1031
1032	return 0;
1033}
1034
1035static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
1036{
1037	u8 response[(sizeof(struct tpms_capability_data) -
1038		offsetof(struct tpms_capability_data, data))];
1039	u32 properties_offset =
1040		offsetof(struct tpml_tagged_tpm_property, tpm_property) +
1041		offsetof(struct tpms_tagged_property, value);
1042	u32 ret;
1043
1044	memset(response, 0, sizeof(response));
1045	ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
1046				  TPM2_PT_PCR_COUNT, response, 1);
1047	if (ret)
1048		return ret;
1049
1050	*num_pcr = get_unaligned_be32(response + properties_offset);
1051	if (*num_pcr > TPM2_MAX_PCRS) {
1052		printf("%s: too many pcrs: %u\n", __func__, *num_pcr);
1053		return -E2BIG;
1054	}
1055
1056	return 0;
1057}
1058
1059static bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
1060{
1061	int i;
1062
1063	/*
1064	 * check the pcr_select. If at least one of the PCRs supports the
1065	 * algorithm add it on the active ones
1066	 */
1067	for (i = 0; i < selection->size_of_select; i++) {
1068		if (selection->pcr_select[i])
1069			return true;
1070	}
1071
1072	return false;
1073}
1074
1075int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
1076		      u32 *pcr_banks)
1077{
1078	u8 response[(sizeof(struct tpms_capability_data) -
1079		offsetof(struct tpms_capability_data, data))];
1080	struct tpml_pcr_selection pcrs;
1081	u32 num_pcr;
1082	size_t i;
1083	u32 ret;
1084
1085	*supported_pcr = 0;
1086	*active_pcr = 0;
1087	*pcr_banks = 0;
1088	memset(response, 0, sizeof(response));
1089	ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
1090	if (ret)
1091		return ret;
1092
1093	pcrs.count = get_unaligned_be32(response);
1094	/*
1095	 * We only support 5 algorithms for now so check against that
1096	 * instead of TPM2_NUM_PCR_BANKS
1097	 */
1098	if (pcrs.count > ARRAY_SIZE(hash_algo_list) ||
1099	    pcrs.count < 1) {
1100		printf("%s: too many pcrs: %u\n", __func__, pcrs.count);
1101		return -EMSGSIZE;
1102	}
1103
1104	ret = tpm2_get_num_pcr(dev, &num_pcr);
1105	if (ret)
1106		return ret;
1107
1108	for (i = 0; i < pcrs.count; i++) {
1109		/*
1110		 * Definition of TPMS_PCR_SELECTION Structure
1111		 * hash: u16
1112		 * size_of_select: u8
1113		 * pcr_select: u8 array
1114		 *
1115		 * The offsets depend on the number of the device PCRs
1116		 * so we have to calculate them based on that
1117		 */
1118		u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
1119			i * offsetof(struct tpms_pcr_selection, pcr_select) +
1120			i * ((num_pcr + 7) / 8);
1121		u32 size_select_offset =
1122			hash_offset + offsetof(struct tpms_pcr_selection,
1123					       size_of_select);
1124		u32 pcr_select_offset =
1125			hash_offset + offsetof(struct tpms_pcr_selection,
1126					       pcr_select);
1127
1128		pcrs.selection[i].hash =
1129			get_unaligned_be16(response + hash_offset);
1130		pcrs.selection[i].size_of_select =
1131			__get_unaligned_be(response + size_select_offset);
1132		if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
1133			printf("%s: pcrs selection too large: %u\n", __func__,
1134			       pcrs.selection[i].size_of_select);
1135			return -ENOBUFS;
1136		}
1137		/* copy the array of pcr_select */
1138		memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
1139		       pcrs.selection[i].size_of_select);
1140	}
1141
1142	for (i = 0; i < pcrs.count; i++) {
1143		u32 hash_mask = tpm2_algorithm_to_mask(pcrs.selection[i].hash);
1144
1145		if (hash_mask) {
1146			*supported_pcr |= hash_mask;
1147			if (tpm2_is_active_pcr(&pcrs.selection[i]))
1148				*active_pcr |= hash_mask;
1149		} else {
1150			printf("%s: unknown algorithm %x\n", __func__,
1151			       pcrs.selection[i].hash);
1152		}
1153	}
1154
1155	*pcr_banks = pcrs.count;
1156
1157	return 0;
1158}
1159
1160u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
1161{
1162	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1163		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
1164		tpm_u32(27 + pw_sz),		/* Length */
1165		tpm_u32(TPM2_CC_DAM_RESET),	/* Command code */
1166
1167		/* HANDLE */
1168		tpm_u32(TPM2_RH_LOCKOUT),	/* TPM resource handle */
1169
1170		/* AUTH_SESSION */
1171		tpm_u32(9 + pw_sz),		/* Authorization size */
1172		tpm_u32(TPM2_RS_PW),		/* Session handle */
1173		tpm_u16(0),			/* Size of <nonce> */
1174						/* <nonce> (if any) */
1175		0,				/* Attributes: Cont/Excl/Rst */
1176		tpm_u16(pw_sz),			/* Size of <hmac/password> */
1177		/* STRING(pw)			   <hmac/password> (if any) */
1178	};
1179	unsigned int offset = 27;
1180	int ret;
1181
1182	/*
1183	 * Fill the command structure starting from the first buffer:
1184	 *     - the password (if any)
1185	 */
1186	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
1187			       offset, pw, pw_sz);
1188	offset += pw_sz;
1189	if (ret)
1190		return TPM_LIB_ERROR;
1191
1192	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1193}
1194
1195u32 tpm2_dam_parameters(struct udevice *dev, const char *pw,
1196			const ssize_t pw_sz, unsigned int max_tries,
1197			unsigned int recovery_time,
1198			unsigned int lockout_recovery)
1199{
1200	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1201		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
1202		tpm_u32(27 + pw_sz + 12),	/* Length */
1203		tpm_u32(TPM2_CC_DAM_PARAMETERS), /* Command code */
1204
1205		/* HANDLE */
1206		tpm_u32(TPM2_RH_LOCKOUT),	/* TPM resource handle */
1207
1208		/* AUTH_SESSION */
1209		tpm_u32(9 + pw_sz),		/* Authorization size */
1210		tpm_u32(TPM2_RS_PW),		/* Session handle */
1211		tpm_u16(0),			/* Size of <nonce> */
1212						/* <nonce> (if any) */
1213		0,				/* Attributes: Cont/Excl/Rst */
1214		tpm_u16(pw_sz),			/* Size of <hmac/password> */
1215		/* STRING(pw)			   <hmac/password> (if any) */
1216
1217		/* LOCKOUT PARAMETERS */
1218		/* tpm_u32(max_tries)		   Max tries (0, always lock) */
1219		/* tpm_u32(recovery_time)	   Recovery time (0, no lock) */
1220		/* tpm_u32(lockout_recovery)	   Lockout recovery */
1221	};
1222	unsigned int offset = 27;
1223	int ret;
1224
1225	/*
1226	 * Fill the command structure starting from the first buffer:
1227	 *     - the password (if any)
1228	 *     - max tries
1229	 *     - recovery time
1230	 *     - lockout recovery
1231	 */
1232	ret = pack_byte_string(command_v2, sizeof(command_v2), "sddd",
1233			       offset, pw, pw_sz,
1234			       offset + pw_sz, max_tries,
1235			       offset + pw_sz + 4, recovery_time,
1236			       offset + pw_sz + 8, lockout_recovery);
1237	offset += pw_sz + 12;
1238	if (ret)
1239		return TPM_LIB_ERROR;
1240
1241	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1242}
1243
1244int tpm2_change_auth(struct udevice *dev, u32 handle, const char *newpw,
1245		     const ssize_t newpw_sz, const char *oldpw,
1246		     const ssize_t oldpw_sz)
1247{
1248	unsigned int offset = 27;
1249	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1250		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
1251		tpm_u32(offset + oldpw_sz + 2 + newpw_sz), /* Length */
1252		tpm_u32(TPM2_CC_HIERCHANGEAUTH), /* Command code */
1253
1254		/* HANDLE */
1255		tpm_u32(handle),		/* TPM resource handle */
1256
1257		/* AUTH_SESSION */
1258		tpm_u32(9 + oldpw_sz),		/* Authorization size */
1259		tpm_u32(TPM2_RS_PW),		/* Session handle */
1260		tpm_u16(0),			/* Size of <nonce> */
1261						/* <nonce> (if any) */
1262		0,				/* Attributes: Cont/Excl/Rst */
1263		tpm_u16(oldpw_sz)		/* Size of <hmac/password> */
1264		/* STRING(oldpw)		   <hmac/password> (if any) */
1265
1266		/* TPM2B_AUTH (TPM2B_DIGEST) */
1267		/* tpm_u16(newpw_sz)		   Digest size, new pw length */
1268		/* STRING(newpw)		   Digest buffer, new pw */
1269	};
1270	int ret;
1271
1272	/*
1273	 * Fill the command structure starting from the first buffer:
1274	 *     - the old password (if any)
1275	 *     - size of the new password
1276	 *     - new password
1277	 */
1278	ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
1279			       offset, oldpw, oldpw_sz,
1280			       offset + oldpw_sz, newpw_sz,
1281			       offset + oldpw_sz + 2, newpw, newpw_sz);
1282	offset += oldpw_sz + 2 + newpw_sz;
1283	if (ret)
1284		return TPM_LIB_ERROR;
1285
1286	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1287}
1288
1289u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
1290			   const ssize_t pw_sz, u32 index, const char *key)
1291{
1292	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1293		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
1294		tpm_u32(35 + pw_sz + TPM2_DIGEST_LEN), /* Length */
1295		tpm_u32(TPM2_CC_PCR_SETAUTHPOL), /* Command code */
1296
1297		/* HANDLE */
1298		tpm_u32(TPM2_RH_PLATFORM),	/* TPM resource handle */
1299
1300		/* AUTH_SESSION */
1301		tpm_u32(9 + pw_sz),		/* Authorization size */
1302		tpm_u32(TPM2_RS_PW),		/* session handle */
1303		tpm_u16(0),			/* Size of <nonce> */
1304						/* <nonce> (if any) */
1305		0,				/* Attributes: Cont/Excl/Rst */
1306		tpm_u16(pw_sz)			/* Size of <hmac/password> */
1307		/* STRING(pw)			   <hmac/password> (if any) */
1308
1309		/* TPM2B_AUTH (TPM2B_DIGEST) */
1310		/* tpm_u16(TPM2_DIGEST_LEN)	   Digest size length */
1311		/* STRING(key)			   Digest buffer (PCR key) */
1312
1313		/* TPMI_ALG_HASH */
1314		/* tpm_u16(TPM2_ALG_SHA256)   Algorithm of the hash */
1315
1316		/* TPMI_DH_PCR */
1317		/* tpm_u32(index),		   PCR Index */
1318	};
1319	unsigned int offset = 27;
1320	int ret;
1321
1322	/*
1323	 * Fill the command structure starting from the first buffer:
1324	 *     - the password (if any)
1325	 *     - the PCR key length
1326	 *     - the PCR key
1327	 *     - the hash algorithm
1328	 *     - the PCR index
1329	 */
1330	ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd",
1331			       offset, pw, pw_sz,
1332			       offset + pw_sz, TPM2_DIGEST_LEN,
1333			       offset + pw_sz + 2, key, TPM2_DIGEST_LEN,
1334			       offset + pw_sz + 2 + TPM2_DIGEST_LEN,
1335			       TPM2_ALG_SHA256,
1336			       offset + pw_sz + 4 + TPM2_DIGEST_LEN, index);
1337	offset += pw_sz + 2 + TPM2_DIGEST_LEN + 2 + 4;
1338	if (ret)
1339		return TPM_LIB_ERROR;
1340
1341	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1342}
1343
1344u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
1345			  const ssize_t pw_sz, u32 index, const char *key,
1346			  const ssize_t key_sz)
1347{
1348	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1349		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
1350		tpm_u32(33 + pw_sz + TPM2_DIGEST_LEN), /* Length */
1351		tpm_u32(TPM2_CC_PCR_SETAUTHVAL), /* Command code */
1352
1353		/* HANDLE */
1354		tpm_u32(index),			/* Handle (PCR Index) */
1355
1356		/* AUTH_SESSION */
1357		tpm_u32(9 + pw_sz),		/* Authorization size */
1358		tpm_u32(TPM2_RS_PW),		/* session handle */
1359		tpm_u16(0),			/* Size of <nonce> */
1360						/* <nonce> (if any) */
1361		0,				/* Attributes: Cont/Excl/Rst */
1362		tpm_u16(pw_sz),			/* Size of <hmac/password> */
1363		/* STRING(pw)			   <hmac/password> (if any) */
1364
1365		/* TPM2B_DIGEST */
1366		/* tpm_u16(key_sz)		   Key length */
1367		/* STRING(key)			   Key */
1368	};
1369	unsigned int offset = 27;
1370	int ret;
1371
1372	/*
1373	 * Fill the command structure starting from the first buffer:
1374	 *     - the password (if any)
1375	 *     - the number of digests, 1 in our case
1376	 *     - the algorithm, sha256 in our case
1377	 *     - the digest (64 bytes)
1378	 */
1379	ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
1380			       offset, pw, pw_sz,
1381			       offset + pw_sz, key_sz,
1382			       offset + pw_sz + 2, key, key_sz);
1383	offset += pw_sz + 2 + key_sz;
1384	if (ret)
1385		return TPM_LIB_ERROR;
1386
1387	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1388}
1389
1390u32 tpm2_get_random(struct udevice *dev, void *data, u32 count)
1391{
1392	const u8 command_v2[10] = {
1393		tpm_u16(TPM2_ST_NO_SESSIONS),
1394		tpm_u32(12),
1395		tpm_u32(TPM2_CC_GET_RANDOM),
1396	};
1397	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
1398
1399	const size_t data_size_offset = 10;
1400	const size_t data_offset = 12;
1401	size_t response_length = sizeof(response);
1402	u32 data_size;
1403	u8 *out = data;
1404
1405	while (count > 0) {
1406		u32 this_bytes = min((size_t)count,
1407				     sizeof(response) - data_offset);
1408		u32 err;
1409
1410		if (pack_byte_string(buf, sizeof(buf), "sw",
1411				     0, command_v2, sizeof(command_v2),
1412				     sizeof(command_v2), this_bytes))
1413			return TPM_LIB_ERROR;
1414		err = tpm_sendrecv_command(dev, buf, response,
1415					   &response_length);
1416		if (err)
1417			return err;
1418		if (unpack_byte_string(response, response_length, "w",
1419				       data_size_offset, &data_size))
1420			return TPM_LIB_ERROR;
1421		if (data_size > this_bytes)
1422			return TPM_LIB_ERROR;
1423		if (unpack_byte_string(response, response_length, "s",
1424				       data_offset, out, data_size))
1425			return TPM_LIB_ERROR;
1426
1427		count -= data_size;
1428		out += data_size;
1429	}
1430
1431	return 0;
1432}
1433
1434u32 tpm2_write_lock(struct udevice *dev, u32 index)
1435{
1436	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1437		/* header 10 bytes */
1438		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
1439		tpm_u32(10 + 8 + 13), /* Length */
1440		tpm_u32(TPM2_CC_NV_WRITELOCK), /* Command code */
1441
1442		/* handles 8 bytes */
1443		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
1444		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
1445
1446		/* session header 9 bytes */
1447		tpm_u32(9),			/* Header size */
1448		tpm_u32(TPM2_RS_PW),		/* Password authorisation */
1449		tpm_u16(0),			/* nonce_size */
1450		0,				/* session_attrs */
1451		tpm_u16(0),			/* auth_size */
1452	};
1453
1454	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1455}
1456
1457u32 tpm2_disable_platform_hierarchy(struct udevice *dev)
1458{
1459	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
1460	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1461		/* header 10 bytes */
1462		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
1463		tpm_u32(10 + 4 + 13 + 5),	/* Length */
1464		tpm_u32(TPM2_CC_HIER_CONTROL),	/* Command code */
1465
1466		/* 4 bytes */
1467		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
1468
1469		/* session header 9 bytes */
1470		tpm_u32(9),			/* Header size */
1471		tpm_u32(TPM2_RS_PW),		/* Password authorisation */
1472		tpm_u16(0),			/* nonce_size */
1473		0,				/* session_attrs */
1474		tpm_u16(0),			/* auth_size */
1475
1476		/* payload 5 bytes */
1477		tpm_u32(TPM2_RH_PLATFORM),	/* Hierarchy to disable */
1478		0,				/* 0=disable */
1479	};
1480	int ret;
1481
1482	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1483	log_info("ret=%s, %x\n", dev->name, ret);
1484	if (ret)
1485		return ret;
1486
1487	priv->plat_hier_disabled = true;
1488
1489	return 0;
1490}
1491
1492u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
1493			u8 *recvbuf, size_t *recv_size)
1494{
1495	return tpm_sendrecv_command(dev, sendbuf, recvbuf, recv_size);
1496}
1497
1498u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
1499		      u8 *recvbuf, size_t *recv_size)
1500{
1501	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1502		/* header 10 bytes */
1503		tpm_u16(TPM2_ST_NO_SESSIONS),		/* TAG */
1504		tpm_u32(10 + 2),			/* Length */
1505		tpm_u32(vendor_cmd),	/* Command code */
1506
1507		tpm_u16(vendor_subcmd),
1508	};
1509	int ret;
1510
1511	ret = tpm_sendrecv_command(dev, command_v2, recvbuf, recv_size);
1512	log_debug("ret=%s, %x\n", dev->name, ret);
1513	if (ret)
1514		return ret;
1515	if (*recv_size < 12)
1516		return -ENODATA;
1517	*recv_size -= 12;
1518	memcpy(recvbuf, recvbuf + 12, *recv_size);
1519
1520	return 0;
1521}
1522
1523u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
1524			  uint vendor_subcmd)
1525{
1526	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1527		/* header 10 bytes */
1528		tpm_u16(TPM2_ST_NO_SESSIONS),		/* TAG */
1529		tpm_u32(10 + 2),			/* Length */
1530		tpm_u32(vendor_cmd),	/* Command code */
1531
1532		tpm_u16(vendor_subcmd),
1533	};
1534	int ret;
1535
1536	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1537	log_debug("ret=%s, %x\n", dev->name, ret);
1538	if (ret)
1539		return ret;
1540
1541	return 0;
1542}
1543
1544enum tpm2_algorithms tpm2_name_to_algorithm(const char *name)
1545{
1546	size_t i;
1547
1548	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
1549		if (!strcasecmp(name, hash_algo_list[i].hash_name))
1550			return hash_algo_list[i].hash_alg;
1551	}
1552	printf("%s: unsupported algorithm %s\n", __func__, name);
1553
1554	return -EINVAL;
1555}
1556
1557const char *tpm2_algorithm_name(enum tpm2_algorithms algo)
1558{
1559	size_t i;
1560
1561	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
1562		if (hash_algo_list[i].hash_alg == algo)
1563			return hash_algo_list[i].hash_name;
1564	}
1565
1566	return "";
1567}
1568
1569u32 tpm2_algorithm_to_mask(enum tpm2_algorithms algo)
1570{
1571	size_t i;
1572
1573	for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
1574		if (hash_algo_list[i].hash_alg == algo)
1575			return hash_algo_list[i].hash_mask;
1576	}
1577
1578	return 0;
1579}
1580