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
25const enum tpm2_algorithms tpm2_supported_algorithms[4] = {
26	TPM2_ALG_SHA1,
27	TPM2_ALG_SHA256,
28	TPM2_ALG_SHA384,
29	TPM2_ALG_SHA512,
30};
31
32int tcg2_get_active_pcr_banks(struct udevice *dev, u32 *active_pcr_banks)
33{
34	u32 supported = 0;
35	u32 pcr_banks = 0;
36	u32 active = 0;
37	int rc;
38
39	rc = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
40	if (rc)
41		return rc;
42
43	*active_pcr_banks = active;
44
45	return 0;
46}
47
48u32 tcg2_event_get_size(struct tpml_digest_values *digest_list)
49{
50	u32 len;
51	size_t i;
52
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);
57
58		if (!l)
59			continue;
60
61		len += l + offsetof(struct tpmt_ha, digest);
62	}
63	len += sizeof(u32);
64
65	return len;
66}
67
68int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
69		       struct tpml_digest_values *digest_list)
70{
71	u8 final[sizeof(union tpmu_ha)];
72	sha256_context ctx_256;
73	sha512_context ctx_512;
74	sha1_context ctx;
75	u32 active;
76	size_t i;
77	u32 len;
78	int rc;
79
80	rc = tcg2_get_active_pcr_banks(dev, &active);
81	if (rc)
82		return rc;
83
84	digest_list->count = 0;
85	for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
86		u32 mask =
87			tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
88
89		if (!(active & mask))
90			continue;
91
92		switch (tpm2_supported_algorithms[i]) {
93		case TPM2_ALG_SHA1:
94			sha1_starts(&ctx);
95			sha1_update(&ctx, input, length);
96			sha1_finish(&ctx, final);
97			len = TPM2_SHA1_DIGEST_SIZE;
98			break;
99		case TPM2_ALG_SHA256:
100			sha256_starts(&ctx_256);
101			sha256_update(&ctx_256, input, length);
102			sha256_finish(&ctx_256, final);
103			len = TPM2_SHA256_DIGEST_SIZE;
104			break;
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;
110			break;
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;
116			break;
117		default:
118			printf("%s: unsupported algorithm %x\n", __func__,
119			       tpm2_supported_algorithms[i]);
120			continue;
121		}
122
123		digest_list->digests[digest_list->count].hash_alg =
124			tpm2_supported_algorithms[i];
125		memcpy(&digest_list->digests[digest_list->count].digest, final,
126		       len);
127		digest_list->count++;
128	}
129
130	return 0;
131}
132
133void tcg2_log_append(u32 pcr_index, u32 event_type,
134		     struct tpml_digest_values *digest_list, u32 size,
135		     const u8 *event, u8 *log)
136{
137	size_t len;
138	size_t pos;
139	u32 i;
140
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);
148
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;
153
154		len = tpm2_algorithm_to_len(hash_alg);
155		if (!len)
156			continue;
157
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);
162		pos += len;
163	}
164
165	put_unaligned_le32(size, log + pos);
166	pos += sizeof(u32);
167	memcpy(log + pos, event, size);
168}
169
170static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index,
171				 u32 event_type,
172				 struct tpml_digest_values *digest_list,
173				 u32 size, const u8 *event)
174{
175	u32 event_size;
176	u8 *log;
177
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);
182		return -ENOBUFS;
183	}
184
185	log = elog->log + elog->log_position;
186	elog->log_position += event_size;
187
188	tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
189
190	return 0;
191}
192
193static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog)
194{
195	struct tcg_efi_spec_id_event *ev;
196	struct tcg_pcr_event *log;
197	u32 event_size;
198	u32 count = 0;
199	u32 log_size;
200	u32 active;
201	u32 mask;
202	size_t i;
203	u16 len;
204	int rc;
205
206	rc = tcg2_get_active_pcr_banks(dev, &active);
207	if (rc)
208		return rc;
209
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]);
213
214		if (!(active & mask))
215			continue;
216
217		switch (tpm2_supported_algorithms[i]) {
218		case TPM2_ALG_SHA1:
219		case TPM2_ALG_SHA256:
220		case TPM2_ALG_SHA384:
221		case TPM2_ALG_SHA512:
222			count++;
223			break;
224		default:
225			continue;
226		}
227	}
228
229	event_size += 1 +
230		(sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count);
231	log_size = offsetof(struct tcg_pcr_event, event) + event_size;
232
233	if (log_size > elog->log_size) {
234		printf("%s: log too large: %u > %u\n", __func__, log_size,
235		       elog->log_size);
236		return -ENOBUFS;
237	}
238
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);
244
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);
254
255	count = 0;
256	for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
257		mask = tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
258
259		if (!(active & mask))
260			continue;
261
262		len = tpm2_algorithm_to_len(tpm2_supported_algorithms[i]);
263		if (!len)
264			continue;
265
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);
269		count++;
270	}
271
272	*((u8 *)ev + (event_size - 1)) = 0;
273	elog->log_position = log_size;
274
275	return 0;
276}
277
278static int tcg2_replay_eventlog(struct tcg2_event_log *elog,
279				struct udevice *dev,
280				struct tpml_digest_values *digest_list,
281				u32 log_position)
282{
283	const u32 offset = offsetof(struct tcg_pcr_event2, digests) +
284		offsetof(struct tpml_digest_values, digests);
285	u32 event_size;
286	u32 count;
287	u16 algo;
288	u32 pcr;
289	u32 pos;
290	u16 len;
291	u8 *log;
292	int rc;
293	u32 i;
294
295	while (log_position + offset < elog->log_size) {
296		log = elog->log + log_position;
297
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))
302			return 0;
303
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))
309			return 0;
310
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)
316				return 0;
317
318			algo = get_unaligned_le16(log + pos);
319			pos += offsetof(struct tpmt_ha, digest);
320			switch (algo) {
321			case TPM2_ALG_SHA1:
322			case TPM2_ALG_SHA256:
323			case TPM2_ALG_SHA384:
324			case TPM2_ALG_SHA512:
325				len = tpm2_algorithm_to_len(algo);
326				break;
327			default:
328				return 0;
329			}
330
331			if (digest_list->count) {
332				if (algo != digest_list->digests[i].hash_alg ||
333				    log_position + pos + len >= elog->log_size)
334					return 0;
335
336				memcpy(digest_list->digests[i].digest.sha512,
337				       log + pos, len);
338			}
339
340			pos += len;
341		}
342
343		if (log_position + pos + sizeof(u32) >= elog->log_size)
344			return 0;
345
346		event_size = get_unaligned_le32(log + pos);
347		pos += event_size + sizeof(u32);
348		if (log_position + pos > elog->log_size)
349			return 0;
350
351		if (digest_list->count) {
352			rc = tcg2_pcr_extend(dev, pcr, digest_list);
353			if (rc)
354				return rc;
355		}
356
357		log_position += pos;
358	}
359
360	elog->log_position = log_position;
361	elog->found = true;
362	return 0;
363}
364
365static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
366{
367	struct tpml_digest_values digest_list;
368	struct tcg_efi_spec_id_event *event;
369	struct tcg_pcr_event *log;
370	u32 log_active;
371	u32 calc_size;
372	u32 active;
373	u32 count;
374	u32 evsz;
375	u32 mask;
376	u16 algo;
377	u16 len;
378	int rc;
379	u32 i;
380	u16 j;
381
382	if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
383		return 0;
384
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)
388		return 0;
389
390	for (i = 0; i < sizeof(log->digest); i++) {
391		if (log->digest[i])
392			return 0;
393	}
394
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)
398		return 0;
399
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)))
403		return 0;
404
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)
407		return 0;
408
409	count = get_unaligned_le32(&event->number_of_algorithms);
410	if (count > ARRAY_SIZE(tpm2_supported_algorithms))
411		return 0;
412
413	calc_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
414		(sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count) +
415		1;
416	if (evsz != calc_size)
417		return 0;
418
419	rc = tcg2_get_active_pcr_banks(dev, &active);
420	if (rc)
421		return rc;
422
423	digest_list.count = 0;
424	log_active = 0;
425
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);
429
430		if (!(active & mask))
431			return 0;
432
433		switch (algo) {
434		case TPM2_ALG_SHA1:
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)
440				return 0;
441			digest_list.digests[digest_list.count++].hash_alg = algo;
442			break;
443		default:
444			return 0;
445		}
446
447		log_active |= mask;
448	}
449
450	/* Ensure the previous firmware extended all the PCRs. */
451	if (log_active != active)
452		return 0;
453
454	/* Read PCR0 to check if previous firmware extended the PCRs or not. */
455	rc = tcg2_pcr_read(dev, 0, &digest_list);
456	if (rc)
457		return rc;
458
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])
463				break;
464		}
465
466		/* PCR is non-zero; it has been extended, so skip extending. */
467		if (j != len) {
468			digest_list.count = 0;
469			break;
470		}
471	}
472
473	return tcg2_replay_eventlog(elog, dev, &digest_list,
474				    offsetof(struct tcg_pcr_event, event) +
475				    evsz);
476}
477
478int tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
479		    struct tpml_digest_values *digest_list)
480{
481	u32 rc;
482	u32 i;
483
484	for (i = 0; i < digest_list->count; i++) {
485		u32 alg = digest_list->digests[i].hash_alg;
486
487		rc = tpm2_pcr_extend(dev, pcr_index, alg,
488				     (u8 *)&digest_list->digests[i].digest,
489				     tpm2_algorithm_to_len(alg));
490		if (rc) {
491			printf("%s: error pcr:%u alg:%08x\n", __func__,
492			       pcr_index, alg);
493			return rc;
494		}
495	}
496
497	return 0;
498}
499
500int tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
501		  struct tpml_digest_values *digest_list)
502{
503	struct tpm_chip_priv *priv;
504	u32 rc;
505	u32 i;
506
507	priv = dev_get_uclass_priv(dev);
508	if (!priv)
509		return -ENODEV;
510
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;
514
515		rc = tpm2_pcr_read(dev, pcr_index, priv->pcr_select_min, alg,
516				   digest, tpm2_algorithm_to_len(alg), NULL);
517		if (rc) {
518			printf("%s: error pcr:%u alg:%08x\n", __func__,
519			       pcr_index, alg);
520			return rc;
521		}
522	}
523
524	return 0;
525}
526
527int 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)
530{
531	struct tpml_digest_values digest_list;
532	int rc;
533
534	if (data)
535		rc = tcg2_create_digest(dev, data, size, &digest_list);
536	else
537		rc = tcg2_create_digest(dev, event, event_size, &digest_list);
538	if (rc)
539		return rc;
540
541	rc = tcg2_pcr_extend(dev, pcr_index, &digest_list);
542	if (rc)
543		return rc;
544
545	return tcg2_log_append_check(elog, pcr_index, event_type, &digest_list,
546				     event_size, event);
547}
548
549int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
550			    bool ignore_existing_log)
551{
552	struct tcg2_event_log log;
553	int rc;
554
555	elog->log_position = 0;
556	elog->found = false;
557
558	rc = tcg2_platform_get_log(dev, (void **)&log.log, &log.log_size);
559	if (!rc) {
560		log.log_position = 0;
561		log.found = false;
562
563		if (!ignore_existing_log) {
564			rc = tcg2_log_parse(dev, &log);
565			if (rc)
566				return rc;
567		}
568
569		if (elog->log_size) {
570			if (log.found) {
571				if (elog->log_size < log.log_position)
572					return -ENOSPC;
573
574				/*
575				 * Copy the discovered log into the user buffer
576				 * if there's enough space.
577				 */
578				memcpy(elog->log, log.log, log.log_position);
579			}
580
581			unmap_physmem(log.log, MAP_NOCACHE);
582		} else {
583			elog->log = log.log;
584			elog->log_size = log.log_size;
585		}
586
587		elog->log_position = log.log_position;
588		elog->found = log.found;
589	}
590
591	/*
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.
595	 */
596	if (!elog->found && elog->log_size)
597		rc = tcg2_log_init(dev, elog);
598
599	return rc;
600}
601
602int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog,
603			  bool ignore_existing_log)
604{
605	int rc;
606
607	rc = tcg2_platform_get_tpm2(dev);
608	if (rc)
609		return rc;
610
611	rc = tpm_auto_start(*dev);
612	if (rc)
613		return rc;
614
615	rc = tcg2_log_prepare_buffer(*dev, elog, ignore_existing_log);
616	if (rc) {
617		tcg2_measurement_term(*dev, elog, true);
618		return rc;
619	}
620
621	rc = tcg2_measure_event(*dev, elog, 0, EV_S_CRTM_VERSION,
622				strlen(version_string) + 1,
623				(u8 *)version_string);
624	if (rc) {
625		tcg2_measurement_term(*dev, elog, true);
626		return rc;
627	}
628
629	return 0;
630}
631
632void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
633			   bool error)
634{
635	u32 event = error ? 0x1 : 0xffffffff;
636	int i;
637
638	for (i = 0; i < 8; ++i)
639		tcg2_measure_event(dev, elog, i, EV_SEPARATOR, sizeof(event),
640				   (const u8 *)&event);
641
642	if (elog->log)
643		unmap_physmem(elog->log, MAP_NOCACHE);
644}
645
646__weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
647{
648	const __be32 *addr_prop;
649	const __be32 *size_prop;
650	int asize;
651	int ssize;
652
653	*addr = NULL;
654	*size = 0;
655
656	addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize);
657	if (!addr_prop)
658		addr_prop = dev_read_prop(dev, "linux,sml-base", &asize);
659
660	size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize);
661	if (!size_prop)
662		size_prop = dev_read_prop(dev, "linux,sml-size", &ssize);
663
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));
667
668		*addr = map_physmem(a, s, MAP_NOCACHE);
669		*size = (u32)s;
670	} else {
671		struct ofnode_phandle_args args;
672		phys_addr_t a;
673		fdt_size_t s;
674
675		if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
676					       0, &args))
677			return -ENODEV;
678
679		a = ofnode_get_addr_size(args.node, "reg", &s);
680		if (a == FDT_ADDR_T_NONE)
681			return -ENOMEM;
682
683		*addr = map_physmem(a, s, MAP_NOCACHE);
684		*size = (u32)s;
685	}
686
687	return 0;
688}
689
690__weak int tcg2_platform_get_tpm2(struct udevice **dev)
691{
692	for_each_tpm_device(*dev) {
693		if (tpm_get_version(*dev) == TPM_V2)
694			return 0;
695	}
696
697	return -ENODEV;
698}
699
700__weak void tcg2_platform_startup_error(struct udevice *dev, int rc) {}
701
702u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
703{
704	const u8 command_v2[12] = {
705		tpm_u16(TPM2_ST_NO_SESSIONS),
706		tpm_u32(12),
707		tpm_u32(TPM2_CC_STARTUP),
708		tpm_u16(mode),
709	};
710	int ret;
711
712	/*
713	 * Note TPM2_Startup command will return RC_SUCCESS the first time,
714	 * but will return RC_INITIALIZE otherwise.
715	 */
716	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
717	if (ret && ret != TPM2_RC_INITIALIZE)
718		return ret;
719
720	return 0;
721}
722
723u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
724{
725	const u8 command_v2[12] = {
726		tpm_u16(TPM2_ST_NO_SESSIONS),
727		tpm_u32(11),
728		tpm_u32(TPM2_CC_SELF_TEST),
729		full_test,
730	};
731
732	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
733}
734
735u32 tpm2_auto_start(struct udevice *dev)
736{
737	u32 rc;
738
739	rc = tpm2_self_test(dev, TPMI_YES);
740
741	if (rc == TPM2_RC_INITIALIZE) {
742		rc = tpm2_startup(dev, TPM2_SU_CLEAR);
743		if (rc)
744			return rc;
745
746		rc = tpm2_self_test(dev, TPMI_YES);
747	}
748
749	return rc;
750}
751
752u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
753	       const ssize_t pw_sz)
754{
755	/* Length of the message header, up to start of password */
756	uint offset = 27;
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 */
761
762		/* HANDLE */
763		tpm_u32(handle),		/* TPM resource handle */
764
765		/* AUTH_SESSION */
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) */
773	};
774	int ret;
775
776	/*
777	 * Fill the command structure starting from the first buffer:
778	 *     - the password (if any)
779	 */
780	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
781			       offset, pw, pw_sz);
782	offset += pw_sz;
783	if (ret)
784		return TPM_LIB_ERROR;
785
786	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
787}
788
789u32 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)
792{
793	/*
794	 * Calculate the offset of the nv_policy piece by adding each of the
795	 * chunks below.
796	 */
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 +
801		message_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 */
807
808		/* handles 4 bytes */
809		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
810
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 */
817
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),
824		/*
825		 * nv_policy
826		 * space_size
827		 */
828	};
829	int ret;
830
831	/*
832	 * Fill the command structure starting from the first buffer:
833	 *     - the password (if any)
834	 */
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);
838	if (ret)
839		return TPM_LIB_ERROR;
840
841	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
842}
843
844u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
845		    const u8 *digest, u32 digest_len)
846{
847	/* Length of the message header, up to start of digest */
848	uint offset = 33;
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 */
853
854		/* HANDLE */
855		tpm_u32(index),			/* Handle (PCR Index) */
856
857		/* AUTH_SESSION */
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) */
865
866		/* hashes */
867		tpm_u32(1),			/* Count (number of hashes) */
868		tpm_u16(algorithm),	/* Algorithm of the hash */
869		/* STRING(digest)		   Digest */
870	};
871	int ret;
872
873	if (!digest)
874		return -EINVAL;
875	/*
876	 * Fill the command structure starting from the first buffer:
877	 *     - the digest
878	 */
879	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
880			       offset, digest, digest_len);
881	if (ret)
882		return TPM_LIB_ERROR;
883
884	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
885}
886
887u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
888{
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 */
894
895		/* handles 8 bytes */
896		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
897		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
898
899		/* AUTH_SESSION */
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) */
907
908		tpm_u16(count),			/* Number of bytes */
909		tpm_u16(0),			/* Offset */
910	};
911	size_t response_len = COMMAND_BUFFER_SIZE;
912	u8 response[COMMAND_BUFFER_SIZE];
913	int ret;
914	u16 tag;
915	u32 size, code;
916
917	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
918	if (ret)
919		return log_msg_ret("read", ret);
920	if (unpack_byte_string(response, response_len, "wdds",
921			       0, &tag, 2, &size, 6, &code,
922			       16, data, count))
923		return TPM_LIB_ERROR;
924
925	return 0;
926}
927
928u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
929			u32 count)
930{
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 :
936		TPM2_RH_PLATFORM;
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 */
942
943		/* handles 8 bytes */
944		tpm_u32(auth),			/* Primary platform seed */
945		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
946
947		/* AUTH_SESSION */
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) */
955
956		tpm_u16(count),
957	};
958	size_t response_len = COMMAND_BUFFER_SIZE;
959	u8 response[COMMAND_BUFFER_SIZE];
960	int ret;
961
962	ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
963			       offset, data, count,
964			       offset + count, 0);
965	if (ret)
966		return TPM_LIB_ERROR;
967
968	return tpm_sendrecv_command(dev, command_v2, response, &response_len);
969}
970
971u32 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)
974{
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 */
980
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 */
986	};
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;
992	int ret;
993
994	if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b",
995			     17 + pcr_sel_idx, pcr_sel_bit))
996		return TPM_LIB_ERROR;
997
998	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
999	if (ret)
1000		return ret;
1001
1002	if (digest_len > response_len)
1003		return TPM_LIB_ERROR;
1004
1005	if (unpack_byte_string(response, response_len, "ds",
1006			       10, &counter,
1007			       response_len - digest_len, data,
1008			       digest_len))
1009		return TPM_LIB_ERROR;
1010
1011	if (updates)
1012		*updates = counter;
1013
1014	return 0;
1015}
1016
1017u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
1018			void *buf, size_t prop_count)
1019{
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 */
1024
1025		tpm_u32(capability),			/* Capability */
1026		tpm_u32(property),			/* Property */
1027		tpm_u32(prop_count),			/* Property count */
1028	};
1029	u8 response[COMMAND_BUFFER_SIZE];
1030	size_t response_len = COMMAND_BUFFER_SIZE;
1031	unsigned int properties_off;
1032	int ret;
1033
1034	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
1035	if (ret)
1036		return ret;
1037
1038	/*
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).
1042	 */
1043	properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
1044			 sizeof(u8) + sizeof(u32);
1045	memcpy(buf, &response[properties_off], response_len - properties_off);
1046
1047	return 0;
1048}
1049
1050static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
1051{
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);
1057	u32 ret;
1058
1059	memset(response, 0, sizeof(response));
1060	ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
1061				  TPM2_PT_PCR_COUNT, response, 1);
1062	if (ret)
1063		return ret;
1064
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);
1068		return -E2BIG;
1069	}
1070
1071	return 0;
1072}
1073
1074static bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
1075{
1076	int i;
1077
1078	/*
1079	 * check the pcr_select. If at least one of the PCRs supports the
1080	 * algorithm add it on the active ones
1081	 */
1082	for (i = 0; i < selection->size_of_select; i++) {
1083		if (selection->pcr_select[i])
1084			return true;
1085	}
1086
1087	return false;
1088}
1089
1090int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
1091		      u32 *pcr_banks)
1092{
1093	u8 response[(sizeof(struct tpms_capability_data) -
1094		offsetof(struct tpms_capability_data, data))];
1095	struct tpml_pcr_selection pcrs;
1096	u32 num_pcr;
1097	size_t i;
1098	u32 ret;
1099
1100	*supported_pcr = 0;
1101	*active_pcr = 0;
1102	*pcr_banks = 0;
1103	memset(response, 0, sizeof(response));
1104	ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
1105	if (ret)
1106		return ret;
1107
1108	pcrs.count = get_unaligned_be32(response);
1109	/*
1110	 * We only support 5 algorithms for now so check against that
1111	 * instead of TPM2_NUM_PCR_BANKS
1112	 */
1113	if (pcrs.count > ARRAY_SIZE(tpm2_supported_algorithms) ||
1114	    pcrs.count < 1) {
1115		printf("%s: too many pcrs: %u\n", __func__, pcrs.count);
1116		return -EMSGSIZE;
1117	}
1118
1119	ret = tpm2_get_num_pcr(dev, &num_pcr);
1120	if (ret)
1121		return ret;
1122
1123	for (i = 0; i < pcrs.count; i++) {
1124		/*
1125		 * Definition of TPMS_PCR_SELECTION Structure
1126		 * hash: u16
1127		 * size_of_select: u8
1128		 * pcr_select: u8 array
1129		 *
1130		 * The offsets depend on the number of the device PCRs
1131		 * so we have to calculate them based on that
1132		 */
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,
1138					       size_of_select);
1139		u32 pcr_select_offset =
1140			hash_offset + offsetof(struct tpms_pcr_selection,
1141					       pcr_select);
1142
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);
1150			return -ENOBUFS;
1151		}
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);
1155	}
1156
1157	for (i = 0; i < pcrs.count; i++) {
1158		u32 hash_mask = tpm2_algorithm_to_mask(pcrs.selection[i].hash);
1159
1160		if (hash_mask) {
1161			*supported_pcr |= hash_mask;
1162			if (tpm2_is_active_pcr(&pcrs.selection[i]))
1163				*active_pcr |= hash_mask;
1164		} else {
1165			printf("%s: unknown algorithm %x\n", __func__,
1166			       pcrs.selection[i].hash);
1167		}
1168	}
1169
1170	*pcr_banks = pcrs.count;
1171
1172	return 0;
1173}
1174
1175u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
1176{
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 */
1181
1182		/* HANDLE */
1183		tpm_u32(TPM2_RH_LOCKOUT),	/* TPM resource handle */
1184
1185		/* AUTH_SESSION */
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) */
1193	};
1194	unsigned int offset = 27;
1195	int ret;
1196
1197	/*
1198	 * Fill the command structure starting from the first buffer:
1199	 *     - the password (if any)
1200	 */
1201	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
1202			       offset, pw, pw_sz);
1203	offset += pw_sz;
1204	if (ret)
1205		return TPM_LIB_ERROR;
1206
1207	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1208}
1209
1210u32 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)
1214{
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 */
1219
1220		/* HANDLE */
1221		tpm_u32(TPM2_RH_LOCKOUT),	/* TPM resource handle */
1222
1223		/* AUTH_SESSION */
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) */
1231
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 */
1236	};
1237	unsigned int offset = 27;
1238	int ret;
1239
1240	/*
1241	 * Fill the command structure starting from the first buffer:
1242	 *     - the password (if any)
1243	 *     - max tries
1244	 *     - recovery time
1245	 *     - lockout recovery
1246	 */
1247	ret = pack_byte_string(command_v2, sizeof(command_v2), "sddd",
1248			       offset, pw, pw_sz,
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;
1253	if (ret)
1254		return TPM_LIB_ERROR;
1255
1256	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1257}
1258
1259int 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)
1262{
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 */
1268
1269		/* HANDLE */
1270		tpm_u32(handle),		/* TPM resource handle */
1271
1272		/* AUTH_SESSION */
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) */
1280
1281		/* TPM2B_AUTH (TPM2B_DIGEST) */
1282		/* tpm_u16(newpw_sz)		   Digest size, new pw length */
1283		/* STRING(newpw)		   Digest buffer, new pw */
1284	};
1285	int ret;
1286
1287	/*
1288	 * Fill the command structure starting from the first buffer:
1289	 *     - the old password (if any)
1290	 *     - size of the new password
1291	 *     - new password
1292	 */
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;
1298	if (ret)
1299		return TPM_LIB_ERROR;
1300
1301	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1302}
1303
1304u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
1305			   const ssize_t pw_sz, u32 index, const char *key)
1306{
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 */
1311
1312		/* HANDLE */
1313		tpm_u32(TPM2_RH_PLATFORM),	/* TPM resource handle */
1314
1315		/* AUTH_SESSION */
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) */
1323
1324		/* TPM2B_AUTH (TPM2B_DIGEST) */
1325		/* tpm_u16(TPM2_DIGEST_LEN)	   Digest size length */
1326		/* STRING(key)			   Digest buffer (PCR key) */
1327
1328		/* TPMI_ALG_HASH */
1329		/* tpm_u16(TPM2_ALG_SHA256)   Algorithm of the hash */
1330
1331		/* TPMI_DH_PCR */
1332		/* tpm_u32(index),		   PCR Index */
1333	};
1334	unsigned int offset = 27;
1335	int ret;
1336
1337	/*
1338	 * Fill the command structure starting from the first buffer:
1339	 *     - the password (if any)
1340	 *     - the PCR key length
1341	 *     - the PCR key
1342	 *     - the hash algorithm
1343	 *     - the PCR index
1344	 */
1345	ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd",
1346			       offset, pw, pw_sz,
1347			       offset + pw_sz, TPM2_DIGEST_LEN,
1348			       offset + pw_sz + 2, key, TPM2_DIGEST_LEN,
1349			       offset + pw_sz + 2 + TPM2_DIGEST_LEN,
1350			       TPM2_ALG_SHA256,
1351			       offset + pw_sz + 4 + TPM2_DIGEST_LEN, index);
1352	offset += pw_sz + 2 + TPM2_DIGEST_LEN + 2 + 4;
1353	if (ret)
1354		return TPM_LIB_ERROR;
1355
1356	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1357}
1358
1359u32 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)
1362{
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 */
1367
1368		/* HANDLE */
1369		tpm_u32(index),			/* Handle (PCR Index) */
1370
1371		/* AUTH_SESSION */
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) */
1379
1380		/* TPM2B_DIGEST */
1381		/* tpm_u16(key_sz)		   Key length */
1382		/* STRING(key)			   Key */
1383	};
1384	unsigned int offset = 27;
1385	int ret;
1386
1387	/*
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)
1393	 */
1394	ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
1395			       offset, pw, pw_sz,
1396			       offset + pw_sz, key_sz,
1397			       offset + pw_sz + 2, key, key_sz);
1398	offset += pw_sz + 2 + key_sz;
1399	if (ret)
1400		return TPM_LIB_ERROR;
1401
1402	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1403}
1404
1405u32 tpm2_get_random(struct udevice *dev, void *data, u32 count)
1406{
1407	const u8 command_v2[10] = {
1408		tpm_u16(TPM2_ST_NO_SESSIONS),
1409		tpm_u32(12),
1410		tpm_u32(TPM2_CC_GET_RANDOM),
1411	};
1412	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
1413
1414	const size_t data_size_offset = 10;
1415	const size_t data_offset = 12;
1416	size_t response_length = sizeof(response);
1417	u32 data_size;
1418	u8 *out = data;
1419
1420	while (count > 0) {
1421		u32 this_bytes = min((size_t)count,
1422				     sizeof(response) - data_offset);
1423		u32 err;
1424
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,
1430					   &response_length);
1431		if (err)
1432			return err;
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;
1441
1442		count -= data_size;
1443		out += data_size;
1444	}
1445
1446	return 0;
1447}
1448
1449u32 tpm2_write_lock(struct udevice *dev, u32 index)
1450{
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 */
1456
1457		/* handles 8 bytes */
1458		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
1459		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
1460
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 */
1467	};
1468
1469	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1470}
1471
1472u32 tpm2_disable_platform_hierarchy(struct udevice *dev)
1473{
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 */
1480
1481		/* 4 bytes */
1482		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
1483
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 */
1490
1491		/* payload 5 bytes */
1492		tpm_u32(TPM2_RH_PLATFORM),	/* Hierarchy to disable */
1493		0,				/* 0=disable */
1494	};
1495	int ret;
1496
1497	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1498	log_info("ret=%s, %x\n", dev->name, ret);
1499	if (ret)
1500		return ret;
1501
1502	priv->plat_hier_disabled = true;
1503
1504	return 0;
1505}
1506
1507u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
1508			u8 *recvbuf, size_t *recv_size)
1509{
1510	return tpm_sendrecv_command(dev, sendbuf, recvbuf, recv_size);
1511}
1512
1513u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
1514		      u8 *recvbuf, size_t *recv_size)
1515{
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 */
1521
1522		tpm_u16(vendor_subcmd),
1523	};
1524	int ret;
1525
1526	ret = tpm_sendrecv_command(dev, command_v2, recvbuf, recv_size);
1527	log_debug("ret=%s, %x\n", dev->name, ret);
1528	if (ret)
1529		return ret;
1530	if (*recv_size < 12)
1531		return -ENODATA;
1532	*recv_size -= 12;
1533	memcpy(recvbuf, recvbuf + 12, *recv_size);
1534
1535	return 0;
1536}
1537
1538u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
1539			  uint vendor_subcmd)
1540{
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 */
1546
1547		tpm_u16(vendor_subcmd),
1548	};
1549	int ret;
1550
1551	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1552	log_debug("ret=%s, %x\n", dev->name, ret);
1553	if (ret)
1554		return ret;
1555
1556	return 0;
1557}
1558