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