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