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