1 // Implementation of the TCG BIOS extension according to the specification
2 // described in specs found at
3 // http://www.trustedcomputinggroup.org/resources/pc_client_work_group_specific_implementation_specification_for_conventional_bios
4 //
5 // Copyright (C) 2006-2011, 2014, 2015 IBM Corporation
6 //
7 // Authors:
8 // Stefan Berger <stefanb@linux.vnet.ibm.com>
9 //
10 // This file may be distributed under the terms of the GNU LGPLv3 license.
11
12 #include "bregs.h" // struct bregs
13 #include "byteorder.h" // cpu_to_*
14 #include "config.h" // CONFIG_TCGBIOS
15 #include "farptr.h" // MAKE_FLATPTR
16 #include "fw/paravirt.h" // runningOnXen
17 #include "hw/tpm_drivers.h" // tpm_drivers[]
18 #include "output.h" // dprintf
19 #include "sha.h" // sha1, sha256, ...
20 #include "std/acpi.h" // RSDP_SIGNATURE, rsdt_descriptor
21 #include "std/smbios.h" // struct smbios_entry_point
22 #include "std/tcg.h" // TCG_PC_LOGOVERFLOW
23 #include "string.h" // checksum
24 #include "tcgbios.h"// tpm_*, prototypes
25 #include "util.h" // printf, get_keystroke
26 #include "stacks.h" // wait_threads, reset
27 #include "malloc.h" // malloc_high
28
29
30 /****************************************************************
31 * ACPI TCPA table interface
32 ****************************************************************/
33
34 struct {
35 /* length of the TCPA log buffer */
36 u32 log_area_minimum_length;
37
38 /* start address of TCPA log buffer */
39 u8 * log_area_start_address;
40
41 /* number of log entries written */
42 u32 entry_count;
43
44 /* address to write next log entry to */
45 u8 * log_area_next_entry;
46
47 /* address of last entry written (need for TCG_StatusCheck) */
48 u8 * log_area_last_entry;
49 } tpm_state VARLOW;
50
tpm_set_log_area(u8 * log_area_start_address,u32 log_area_minimum_length)51 static int tpm_set_log_area(u8 *log_area_start_address,
52 u32 log_area_minimum_length)
53 {
54 if (!log_area_start_address || !log_area_minimum_length)
55 return -1;
56
57 memset(log_area_start_address, 0, log_area_minimum_length);
58 tpm_state.log_area_start_address = log_area_start_address;
59 tpm_state.log_area_minimum_length = log_area_minimum_length;
60 tpm_state.log_area_next_entry = log_area_start_address;
61 tpm_state.log_area_last_entry = NULL;
62 tpm_state.entry_count = 0;
63 return 0;
64 }
65
66 static int
tpm_tcpa_probe(void)67 tpm_tcpa_probe(void)
68 {
69 struct tcpa_descriptor_rev2 *tcpa = find_acpi_table(TCPA_SIGNATURE);
70 if (!tcpa)
71 return -1;
72
73 dprintf(DEBUG_tcg, "TCGBIOS: TCPA: LASA = %p, LAML = %u\n",
74 (u8 *)(long)tcpa->log_area_start_address,
75 tcpa->log_area_minimum_length);
76
77 return tpm_set_log_area((u8*)(long)tcpa->log_area_start_address,
78 tcpa->log_area_minimum_length);
79 }
80
81 static int
tpm_tpm2_probe(void)82 tpm_tpm2_probe(void)
83 {
84 struct tpm2_descriptor_rev2 *tpm2 = find_acpi_table(TPM2_SIGNATURE);
85 if (!tpm2)
86 return -1;
87
88 if (tpm2->length < 76)
89 return -1;
90
91 dprintf(DEBUG_tcg, "TCGBIOS: TPM2: LASA = %p, LAML = %u\n",
92 (u8 *)(long)tpm2->log_area_start_address,
93 tpm2->log_area_minimum_length);
94
95 return tpm_set_log_area((u8*)(long)tpm2->log_area_start_address,
96 tpm2->log_area_minimum_length);
97 }
98
99 /*
100 * Extend the ACPI log with the given entry by copying the
101 * entry data into the log.
102 * Input
103 * entry : The header data to use (including the variable length digest)
104 * digest_len : Length of the digest in 'entry'
105 * event : Pointer to the event body to be copied into the log
106 * event_len : Length of 'event'
107 *
108 * Output:
109 * Returns an error code in case of faiure, 0 in case of success
110 */
111 static int
tpm_log_event(struct tpm_log_header * entry,int digest_len,const void * event,int event_len)112 tpm_log_event(struct tpm_log_header *entry, int digest_len
113 , const void *event, int event_len)
114 {
115 dprintf(DEBUG_tcg, "TCGBIOS: LASA = %p, next entry = %p\n",
116 tpm_state.log_area_start_address, tpm_state.log_area_next_entry);
117
118 if (tpm_state.log_area_next_entry == NULL)
119 return -1;
120
121 u32 size = (sizeof(*entry) + digest_len
122 + sizeof(struct tpm_log_trailer) + event_len);
123 u32 logsize = (tpm_state.log_area_next_entry + size
124 - tpm_state.log_area_start_address);
125 if (logsize > tpm_state.log_area_minimum_length) {
126 dprintf(DEBUG_tcg, "TCGBIOS: LOG OVERFLOW: size = %d\n", size);
127 return -1;
128 }
129
130 void *dest = tpm_state.log_area_next_entry;
131 memcpy(dest, entry, sizeof(*entry) + digest_len);
132 struct tpm_log_trailer *t = dest + sizeof(*entry) + digest_len;
133 t->eventdatasize = event_len;
134 memcpy(t->event, event, event_len);
135
136 tpm_state.log_area_last_entry = tpm_state.log_area_next_entry;
137 tpm_state.log_area_next_entry += size;
138 tpm_state.entry_count++;
139
140 return 0;
141 }
142
143
144 /****************************************************************
145 * Digest formatting
146 ****************************************************************/
147
148 static TPMVersion TPM_version;
149 static u32 tpm20_pcr_selection_size;
150 static struct tpml_pcr_selection *tpm20_pcr_selection;
151
152 // A 'struct tpm_log_entry' is a local data structure containing a
153 // 'tpm_log_header' followed by space for the maximum supported
154 // digest. (The digest is a sha1 hash on tpm1.2 or a series of
155 // tpm2_digest_value structs on tpm2.0)
156 struct tpm_log_entry {
157 struct tpm_log_header hdr;
158 u8 pad[sizeof(struct tpm2_digest_values)
159 + 8 * sizeof(struct tpm2_digest_value)
160 + SHA1_BUFSIZE + SHA256_BUFSIZE + SHA384_BUFSIZE
161 + SHA512_BUFSIZE + SM3_256_BUFSIZE + SHA3_256_BUFSIZE
162 + SHA3_384_BUFSIZE + SHA3_512_BUFSIZE];
163 } PACKED;
164
165 static const struct hash_parameters {
166 u16 hashalg;
167 u8 hashalg_flag;
168 u8 hash_buffersize;
169 const char *name;
170 void (*hashfunc)(const u8 *data, u32 length, u8 *hash);
171 } hash_parameters[] = {
172 {
173 .hashalg = TPM2_ALG_SHA1,
174 .hashalg_flag = TPM2_ALG_SHA1_FLAG,
175 .hash_buffersize = SHA1_BUFSIZE,
176 .name = "SHA1",
177 .hashfunc = sha1,
178 }, {
179 .hashalg = TPM2_ALG_SHA256,
180 .hashalg_flag = TPM2_ALG_SHA256_FLAG,
181 .hash_buffersize = SHA256_BUFSIZE,
182 .name = "SHA256",
183 .hashfunc = sha256,
184 }, {
185 .hashalg = TPM2_ALG_SHA384,
186 .hashalg_flag = TPM2_ALG_SHA384_FLAG,
187 .hash_buffersize = SHA384_BUFSIZE,
188 .name = "SHA384",
189 .hashfunc = sha384,
190 }, {
191 .hashalg = TPM2_ALG_SHA512,
192 .hashalg_flag = TPM2_ALG_SHA512_FLAG,
193 .hash_buffersize = SHA512_BUFSIZE,
194 .name = "SHA512",
195 .hashfunc = sha512,
196 }, {
197 .hashalg = TPM2_ALG_SM3_256,
198 .hashalg_flag = TPM2_ALG_SM3_256_FLAG,
199 .hash_buffersize = SM3_256_BUFSIZE,
200 .name = "SM3-256",
201 }, {
202 .hashalg = TPM2_ALG_SHA3_256,
203 .hashalg_flag = TPM2_ALG_SHA3_256_FLAG,
204 .hash_buffersize = SHA3_256_BUFSIZE,
205 .name = "SHA3-256",
206 }, {
207 .hashalg = TPM2_ALG_SHA3_384,
208 .hashalg_flag = TPM2_ALG_SHA3_384_FLAG,
209 .hash_buffersize = SHA3_384_BUFSIZE,
210 .name = "SHA3-384",
211 }, {
212 .hashalg = TPM2_ALG_SHA3_512,
213 .hashalg_flag = TPM2_ALG_SHA3_512_FLAG,
214 .hash_buffersize = SHA3_512_BUFSIZE,
215 .name = "SHA3-512",
216 }
217 };
218
219 static int
tpm20_get_hash_buffersize(u16 hashAlg)220 tpm20_get_hash_buffersize(u16 hashAlg)
221 {
222 unsigned i;
223
224 for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) {
225 if (hash_parameters[i].hashalg == hashAlg)
226 return hash_parameters[i].hash_buffersize;
227 }
228 return -1;
229 }
230
231 static u8
tpm20_hashalg_to_flag(u16 hashAlg)232 tpm20_hashalg_to_flag(u16 hashAlg)
233 {
234 unsigned i;
235
236 for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) {
237 if (hash_parameters[i].hashalg == hashAlg)
238 return hash_parameters[i].hashalg_flag;
239 }
240 return 0;
241 }
242
243 static u16
tpm20_hashalg_flag_to_hashalg(u8 hashalg_flag)244 tpm20_hashalg_flag_to_hashalg(u8 hashalg_flag)
245 {
246 unsigned i;
247
248 for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) {
249 if (hash_parameters[i].hashalg_flag == hashalg_flag)
250 return hash_parameters[i].hashalg;
251 }
252 return 0;
253 }
254
255 static const char *
tpm20_hashalg_flag_to_name(u8 hashalg_flag)256 tpm20_hashalg_flag_to_name(u8 hashalg_flag)
257 {
258 unsigned i;
259
260 for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) {
261 if (hash_parameters[i].hashalg_flag == hashalg_flag)
262 return hash_parameters[i].name;
263 }
264 return NULL;
265 }
266
tpm2_hash_data(u16 hashAlg,const u8 * data,u32 data_len,u8 * hash)267 static void tpm2_hash_data(u16 hashAlg, const u8 *data, u32 data_len, u8 *hash)
268 {
269 unsigned i;
270
271 for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) {
272 if (hash_parameters[i].hashalg == hashAlg) {
273 if (hash_parameters[i].hashfunc) {
274 hash_parameters[i].hashfunc(data, data_len, hash);
275 } else {
276 memset(hash, 0xff, hash_parameters[i].hash_buffersize);
277 }
278 }
279 }
280 }
281
282 // Add an entry at the start of the log describing digest formats
283 static int
tpm20_write_EfiSpecIdEventStruct(void)284 tpm20_write_EfiSpecIdEventStruct(void)
285 {
286 if (!tpm20_pcr_selection)
287 return -1;
288
289 struct {
290 struct TCG_EfiSpecIdEventStruct hdr;
291 u8 pad[sizeof(struct tpm_log_entry) + sizeof(u8)];
292 } event = {
293 .hdr.signature = "Spec ID Event03",
294 .hdr.platformClass = TPM_TCPA_ACPI_CLASS_CLIENT,
295 .hdr.specVersionMinor = 0,
296 .hdr.specVersionMajor = 2,
297 .hdr.specErrata = 2,
298 .hdr.uintnSize = 2,
299 };
300
301 struct tpms_pcr_selection *sel = tpm20_pcr_selection->selections;
302 void *nsel, *end = (void*)tpm20_pcr_selection + tpm20_pcr_selection_size;
303
304 u32 count, numAlgs = 0;
305 for (count = 0; count < be32_to_cpu(tpm20_pcr_selection->count); count++) {
306 u8 sizeOfSelect = sel->sizeOfSelect;
307
308 nsel = (void*)sel + sizeof(*sel) + sizeOfSelect;
309 if (nsel > end)
310 break;
311
312 if (!sizeOfSelect || sel->pcrSelect[0] == 0) {
313 sel = nsel;
314 continue;
315 }
316
317 int hsize = tpm20_get_hash_buffersize(be16_to_cpu(sel->hashAlg));
318 if (hsize < 0) {
319 dprintf(DEBUG_tcg, "TPM is using an unsupported hash: %d\n",
320 be16_to_cpu(sel->hashAlg));
321 return -1;
322 }
323
324 int event_size = offsetof(struct TCG_EfiSpecIdEventStruct
325 , digestSizes[count+1]);
326 if (event_size > sizeof(event) - sizeof(u8)) {
327 dprintf(DEBUG_tcg, "EfiSpecIdEventStruct pad too small\n");
328 return -1;
329 }
330
331 event.hdr.digestSizes[numAlgs].algorithmId = be16_to_cpu(sel->hashAlg);
332 event.hdr.digestSizes[numAlgs].digestSize = hsize;
333 numAlgs++;
334
335 sel = nsel;
336 }
337
338 if (sel != end) {
339 dprintf(DEBUG_tcg, "Malformed pcr selection structure fron TPM\n");
340 return -1;
341 }
342
343 event.hdr.numberOfAlgorithms = numAlgs;
344 int event_size = offsetof(struct TCG_EfiSpecIdEventStruct
345 , digestSizes[numAlgs]);
346 u8 *vendorInfoSize = (void*)&event + event_size;
347 *vendorInfoSize = 0;
348 event_size += sizeof(*vendorInfoSize);
349
350 struct tpm_log_entry le = {
351 .hdr.eventtype = EV_NO_ACTION,
352 };
353 return tpm_log_event(&le.hdr, SHA1_BUFSIZE, &event, event_size);
354 }
355
356 /*
357 * Build the TPM2 tpm2_digest_values data structure from the given hash.
358 * Follow the PCR bank configuration of the TPM and write the same hash
359 * in either truncated or zero-padded form in the areas of all the other
360 * hashes. For example, write the sha1 hash in the area of the sha256
361 * hash and fill the remaining bytes with zeros. Or truncate the sha256
362 * hash when writing it in the area of the sha1 hash.
363 *
364 * le: the log entry to build the digest in
365 * hashdata: the data to hash
366 * hashdata_len: the length of the hashdata
367 * bigEndian: whether to build in big endian format for the TPM or
368 * little endian for the log
369 *
370 * Returns the digest size; -1 on fatal error
371 */
372 static int
tpm20_build_digest(struct tpm_log_entry * le,const u8 * hashdata,u32 hashdata_len,int bigEndian)373 tpm20_build_digest(struct tpm_log_entry *le,
374 const u8 *hashdata, u32 hashdata_len, int bigEndian)
375 {
376 if (!tpm20_pcr_selection)
377 return -1;
378
379 struct tpms_pcr_selection *sel = tpm20_pcr_selection->selections;
380 void *nsel, *end = (void*)tpm20_pcr_selection + tpm20_pcr_selection_size;
381 void *dest = le->hdr.digest + sizeof(struct tpm2_digest_values);
382
383 u32 count, numAlgs = 0;
384 for (count = 0; count < be32_to_cpu(tpm20_pcr_selection->count); count++) {
385 u8 sizeOfSelect = sel->sizeOfSelect;
386
387 nsel = (void*)sel + sizeof(*sel) + sizeOfSelect;
388 if (nsel > end)
389 break;
390
391 /* PCR 0-7 unused? -- skip */
392 if (!sizeOfSelect || sel->pcrSelect[0] == 0) {
393 sel = nsel;
394 continue;
395 }
396
397 int hsize = tpm20_get_hash_buffersize(be16_to_cpu(sel->hashAlg));
398 if (hsize < 0) {
399 dprintf(DEBUG_tcg, "TPM is using an unsupported hash: %d\n",
400 be16_to_cpu(sel->hashAlg));
401 return -1;
402 }
403
404 /* buffer size sanity check before writing */
405 struct tpm2_digest_value *v = dest;
406 if (dest + sizeof(*v) + hsize > (void*)le + sizeof(*le)) {
407 dprintf(DEBUG_tcg, "tpm_log_entry is too small\n");
408 return -1;
409 }
410
411 if (bigEndian)
412 v->hashAlg = sel->hashAlg;
413 else
414 v->hashAlg = be16_to_cpu(sel->hashAlg);
415
416 tpm2_hash_data(be16_to_cpu(sel->hashAlg), hashdata, hashdata_len,
417 v->hash);
418
419 dest += sizeof(*v) + hsize;
420 sel = nsel;
421
422 numAlgs++;
423 }
424
425 if (sel != end) {
426 dprintf(DEBUG_tcg, "Malformed pcr selection structure fron TPM\n");
427 return -1;
428 }
429
430 struct tpm2_digest_values *v = (void*)le->hdr.digest;
431 if (bigEndian)
432 v->count = cpu_to_be32(numAlgs);
433 else
434 v->count = numAlgs;
435
436 return dest - (void*)le->hdr.digest;
437 }
438
439 static int
tpm12_build_digest(struct tpm_log_entry * le,const u8 * hashdata,u32 hashdata_len)440 tpm12_build_digest(struct tpm_log_entry *le,
441 const u8 *hashdata, u32 hashdata_len)
442 {
443 sha1(hashdata, hashdata_len, le->hdr.digest);
444 return SHA1_BUFSIZE;
445 }
446
447 static int
tpm12_build_digest_direct(struct tpm_log_entry * le,const u8 * sha1)448 tpm12_build_digest_direct(struct tpm_log_entry *le, const u8 *sha1)
449 {
450 // On TPM 1.2 the digest contains just the SHA1 hash
451 memcpy(le->hdr.digest, sha1, SHA1_BUFSIZE);
452 return SHA1_BUFSIZE;
453 }
454
455 static int
tpm_build_digest(struct tpm_log_entry * le,const u8 * hashdata,u32 hashdata_len,int bigEndian)456 tpm_build_digest(struct tpm_log_entry *le, const u8 *hashdata, u32 hashdata_len
457 , int bigEndian)
458 {
459 switch (TPM_version) {
460 case TPM_VERSION_1_2:
461 return tpm12_build_digest(le, hashdata, hashdata_len);
462 case TPM_VERSION_2:
463 return tpm20_build_digest(le, hashdata, hashdata_len, bigEndian);
464 }
465 return -1;
466 }
467
468
469 /****************************************************************
470 * TPM hardware command wrappers
471 ****************************************************************/
472
473 // Helper function for sending tpm commands that take a single
474 // optional parameter (0, 1, or 2 bytes) and have no special response.
475 static int
tpm_simple_cmd(u8 locty,u32 ordinal,int param_size,u16 param,enum tpmDurationType to_t)476 tpm_simple_cmd(u8 locty, u32 ordinal
477 , int param_size, u16 param, enum tpmDurationType to_t)
478 {
479 struct {
480 struct tpm_req_header trqh;
481 u16 param;
482 } PACKED req = {
483 .trqh.totlen = cpu_to_be32(sizeof(req.trqh) + param_size),
484 .trqh.ordinal = cpu_to_be32(ordinal),
485 .param = param_size == 2 ? cpu_to_be16(param) : param,
486 };
487 switch (TPM_version) {
488 case TPM_VERSION_1_2:
489 req.trqh.tag = cpu_to_be16(TPM_TAG_RQU_CMD);
490 break;
491 case TPM_VERSION_2:
492 req.trqh.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
493 break;
494 }
495
496 u8 obuffer[64];
497 struct tpm_rsp_header *trsh = (void*)obuffer;
498 u32 obuffer_len = sizeof(obuffer);
499 memset(obuffer, 0x0, sizeof(obuffer));
500
501 int ret = tpmhw_transmit(locty, &req.trqh, obuffer, &obuffer_len, to_t);
502 ret = ret ? -1 : be32_to_cpu(trsh->errcode);
503 dprintf(DEBUG_tcg, "Return from tpm_simple_cmd(%x, %x) = %x\n",
504 ordinal, param, ret);
505 return ret;
506 }
507
508 static int
tpm20_getcapability(u32 capability,u32 property,u32 count,struct tpm_rsp_header * rsp,u32 rsize)509 tpm20_getcapability(u32 capability, u32 property, u32 count,
510 struct tpm_rsp_header *rsp, u32 rsize)
511 {
512 struct tpm2_req_getcapability trg = {
513 .hdr.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
514 .hdr.totlen = cpu_to_be32(sizeof(trg)),
515 .hdr.ordinal = cpu_to_be32(TPM2_CC_GetCapability),
516 .capability = cpu_to_be32(capability),
517 .property = cpu_to_be32(property),
518 .propertycount = cpu_to_be32(count),
519 };
520
521 u32 resp_size = rsize;
522 int ret = tpmhw_transmit(0, &trg.hdr, rsp, &resp_size,
523 TPM_DURATION_TYPE_SHORT);
524 ret = (ret ||
525 rsize < be32_to_cpu(rsp->totlen)) ? -1 : be32_to_cpu(rsp->errcode);
526
527 dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_GetCapability = 0x%08x\n",
528 ret);
529
530 return ret;
531 }
532
533 static int
tpm20_get_pcrbanks(void)534 tpm20_get_pcrbanks(void)
535 {
536 u8 buffer[128];
537 struct tpm2_res_getcapability *trg =
538 (struct tpm2_res_getcapability *)&buffer;
539
540 int ret = tpm20_getcapability(TPM2_CAP_PCRS, 0, 8, &trg->hdr,
541 sizeof(buffer));
542 if (ret)
543 return ret;
544
545 /* defend against (broken) TPM sending packets that are too short */
546 u32 resplen = be32_to_cpu(trg->hdr.totlen);
547 if (resplen <= offsetof(struct tpm2_res_getcapability, data))
548 return -1;
549
550 u32 size = resplen - offsetof(struct tpm2_res_getcapability, data);
551 /* we need a valid tpml_pcr_selection up to and including sizeOfSelect */
552 if (size < offsetof(struct tpml_pcr_selection, selections) +
553 offsetof(struct tpms_pcr_selection, pcrSelect))
554 return -1;
555
556 tpm20_pcr_selection = malloc_high(size);
557 if (tpm20_pcr_selection) {
558 memcpy(tpm20_pcr_selection, &trg->data, size);
559 tpm20_pcr_selection_size = size;
560 } else {
561 warn_noalloc();
562 ret = -1;
563 }
564
565 return ret;
566 }
567
568 static int
tpm20_get_suppt_pcrbanks(u8 * suppt_pcrbanks,u8 * active_pcrbanks)569 tpm20_get_suppt_pcrbanks(u8 *suppt_pcrbanks, u8 *active_pcrbanks)
570 {
571 *suppt_pcrbanks = 0;
572 *active_pcrbanks = 0;
573
574 if (!tpm20_pcr_selection)
575 return -1;
576
577 struct tpms_pcr_selection *sel = tpm20_pcr_selection->selections;
578 void *end = (void*)tpm20_pcr_selection + tpm20_pcr_selection_size;
579
580 while (1) {
581 u8 sizeOfSelect = sel->sizeOfSelect;
582 void *nsel = (void*)sel + sizeof(*sel) + sizeOfSelect;
583 if (nsel > end)
584 return 0;
585
586 u16 hashalg = be16_to_cpu(sel->hashAlg);
587 u8 hashalg_flag = tpm20_hashalg_to_flag(hashalg);
588
589 *suppt_pcrbanks |= hashalg_flag;
590
591 unsigned i;
592 for (i = 0; i < sizeOfSelect; i++) {
593 if (sel->pcrSelect[i]) {
594 *active_pcrbanks |= hashalg_flag;
595 break;
596 }
597 }
598
599 sel = nsel;
600 }
601 }
602
603 static int
tpm20_set_pcrbanks(u32 active_banks)604 tpm20_set_pcrbanks(u32 active_banks)
605 {
606 struct tpm2_req_pcr_allocate trpa = {
607 .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS),
608 .hdr.ordinal = cpu_to_be32(TPM2_CC_PCR_Allocate),
609 .authhandle = cpu_to_be32(TPM2_RH_PLATFORM),
610 .authblocksize = cpu_to_be32(sizeof(trpa.authblock)),
611 .authblock = {
612 .handle = cpu_to_be32(TPM2_RS_PW),
613 .noncesize = cpu_to_be16(0),
614 .contsession = TPM2_YES,
615 .pwdsize = cpu_to_be16(0),
616 },
617 };
618 struct tpms_pcr_selection3 {
619 u16 hashAlg;
620 u8 sizeOfSelect;
621 u8 pcrSelect[3];
622 } tps[ARRAY_SIZE(trpa.tpms_pcr_selections)];
623 int i = 0;
624 u8 hashalg_flag = TPM2_ALG_SHA1_FLAG;
625 u8 dontcare, suppt_banks;
626
627 tpm20_get_suppt_pcrbanks(&suppt_banks, &dontcare);
628
629 while (hashalg_flag) {
630 if ((hashalg_flag & suppt_banks)) {
631 u16 hashalg = tpm20_hashalg_flag_to_hashalg(hashalg_flag);
632
633 if (hashalg) {
634 u8 mask = 0;
635 tps[i].hashAlg = cpu_to_be16(hashalg);
636 tps[i].sizeOfSelect = 3;
637
638 if (active_banks & hashalg_flag)
639 mask = 0xff;
640
641 tps[i].pcrSelect[0] = mask;
642 tps[i].pcrSelect[1] = mask;
643 tps[i].pcrSelect[2] = mask;
644 i++;
645 }
646 }
647 hashalg_flag <<= 1;
648 }
649
650 trpa.count = cpu_to_be32(i);
651 memcpy(trpa.tpms_pcr_selections, tps, i * sizeof(tps[0]));
652 trpa.hdr.totlen = cpu_to_be32(offsetof(struct tpm2_req_pcr_allocate,
653 tpms_pcr_selections) +
654 i * sizeof(tps[0]));
655
656 struct tpm_rsp_header rsp;
657 u32 resp_length = sizeof(rsp);
658
659 int ret = tpmhw_transmit(0, &trpa.hdr, &rsp, &resp_length,
660 TPM_DURATION_TYPE_SHORT);
661 ret = ret ? -1 : be32_to_cpu(rsp.errcode);
662
663 return ret;
664 }
665
tpm20_activate_pcrbanks(u32 active_banks)666 static int tpm20_activate_pcrbanks(u32 active_banks)
667 {
668 int ret = tpm20_set_pcrbanks(active_banks);
669 if (!ret)
670 ret = tpm_simple_cmd(0, TPM2_CC_Shutdown,
671 2, TPM2_SU_CLEAR, TPM_DURATION_TYPE_SHORT);
672 if (!ret)
673 reset();
674 return ret;
675 }
676
677 static int
tpm12_get_capability(u32 cap,u32 subcap,struct tpm_rsp_header * rsp,u32 rsize)678 tpm12_get_capability(u32 cap, u32 subcap, struct tpm_rsp_header *rsp, u32 rsize)
679 {
680 struct tpm_req_getcap trgc = {
681 .hdr.tag = cpu_to_be16(TPM_TAG_RQU_CMD),
682 .hdr.totlen = cpu_to_be32(sizeof(trgc)),
683 .hdr.ordinal = cpu_to_be32(TPM_ORD_GetCapability),
684 .capArea = cpu_to_be32(cap),
685 .subCapSize = cpu_to_be32(sizeof(trgc.subCap)),
686 .subCap = cpu_to_be32(subcap)
687 };
688 u32 resp_size = rsize;
689 int ret = tpmhw_transmit(0, &trgc.hdr, rsp, &resp_size,
690 TPM_DURATION_TYPE_SHORT);
691 ret = (ret || resp_size != rsize) ? -1 : be32_to_cpu(rsp->errcode);
692 dprintf(DEBUG_tcg, "TCGBIOS: Return code from TPM_GetCapability(%d, %d)"
693 " = %x\n", cap, subcap, ret);
694 return ret;
695 }
696
697 static int
tpm12_read_permanent_flags(char * buf,int buf_len)698 tpm12_read_permanent_flags(char *buf, int buf_len)
699 {
700 memset(buf, 0, buf_len);
701
702 struct tpm_res_getcap_perm_flags pf;
703 int ret = tpm12_get_capability(TPM_CAP_FLAG, TPM_CAP_FLAG_PERMANENT
704 , &pf.hdr, sizeof(pf));
705 if (ret)
706 return -1;
707
708 memcpy(buf, &pf.perm_flags, buf_len);
709
710 return 0;
711 }
712
713 static int
tpm12_determine_timeouts(void)714 tpm12_determine_timeouts(void)
715 {
716 struct tpm_res_getcap_timeouts timeouts;
717 int ret = tpm12_get_capability(TPM_CAP_PROPERTY, TPM_CAP_PROP_TIS_TIMEOUT
718 , &timeouts.hdr, sizeof(timeouts));
719 if (ret)
720 return ret;
721
722 struct tpm_res_getcap_durations durations;
723 ret = tpm12_get_capability(TPM_CAP_PROPERTY, TPM_CAP_PROP_DURATION
724 , &durations.hdr, sizeof(durations));
725 if (ret)
726 return ret;
727
728 int i;
729 for (i = 0; i < 3; i++)
730 durations.durations[i] = be32_to_cpu(durations.durations[i]);
731
732 for (i = 0; i < 4; i++)
733 timeouts.timeouts[i] = be32_to_cpu(timeouts.timeouts[i]);
734
735 dprintf(DEBUG_tcg, "TCGBIOS: timeouts: %u %u %u %u\n",
736 timeouts.timeouts[0],
737 timeouts.timeouts[1],
738 timeouts.timeouts[2],
739 timeouts.timeouts[3]);
740
741 dprintf(DEBUG_tcg, "TCGBIOS: durations: %u %u %u\n",
742 durations.durations[0],
743 durations.durations[1],
744 durations.durations[2]);
745
746 tpmhw_set_timeouts(timeouts.timeouts, durations.durations);
747
748 return 0;
749 }
750
751 static void
tpm20_set_timeouts(void)752 tpm20_set_timeouts(void)
753 {
754 u32 durations[3] = {
755 TPM2_DEFAULT_DURATION_SHORT,
756 TPM2_DEFAULT_DURATION_MEDIUM,
757 TPM2_DEFAULT_DURATION_LONG,
758 };
759 u32 timeouts[4] = {
760 TIS2_DEFAULT_TIMEOUT_A,
761 TIS2_DEFAULT_TIMEOUT_B,
762 TIS2_DEFAULT_TIMEOUT_C,
763 TIS2_DEFAULT_TIMEOUT_D,
764 };
765
766 tpmhw_set_timeouts(timeouts, durations);
767 }
768
769 static int
tpm12_extend(struct tpm_log_entry * le,int digest_len)770 tpm12_extend(struct tpm_log_entry *le, int digest_len)
771 {
772 struct tpm_req_extend tre = {
773 .hdr.tag = cpu_to_be16(TPM_TAG_RQU_CMD),
774 .hdr.totlen = cpu_to_be32(sizeof(tre)),
775 .hdr.ordinal = cpu_to_be32(TPM_ORD_Extend),
776 .pcrindex = cpu_to_be32(le->hdr.pcrindex),
777 };
778 memcpy(tre.digest, le->hdr.digest, sizeof(tre.digest));
779
780 struct tpm_rsp_extend rsp;
781 u32 resp_length = sizeof(rsp);
782 int ret = tpmhw_transmit(0, &tre.hdr, &rsp, &resp_length,
783 TPM_DURATION_TYPE_SHORT);
784 if (ret || resp_length != sizeof(rsp) || rsp.hdr.errcode)
785 return -1;
786
787 return 0;
788 }
789
tpm20_extend(struct tpm_log_entry * le,int digest_len)790 static int tpm20_extend(struct tpm_log_entry *le, int digest_len)
791 {
792 struct tpm2_req_extend tmp_tre = {
793 .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS),
794 .hdr.totlen = cpu_to_be32(0),
795 .hdr.ordinal = cpu_to_be32(TPM2_CC_PCR_Extend),
796 .pcrindex = cpu_to_be32(le->hdr.pcrindex),
797 .authblocksize = cpu_to_be32(sizeof(tmp_tre.authblock)),
798 .authblock = {
799 .handle = cpu_to_be32(TPM2_RS_PW),
800 .noncesize = cpu_to_be16(0),
801 .contsession = TPM2_YES,
802 .pwdsize = cpu_to_be16(0),
803 },
804 };
805 u8 buffer[sizeof(tmp_tre) + sizeof(le->pad)];
806 struct tpm2_req_extend *tre = (struct tpm2_req_extend *)buffer;
807
808 memcpy(tre, &tmp_tre, sizeof(tmp_tre));
809 memcpy(&tre->digest[0], le->hdr.digest, digest_len);
810
811 tre->hdr.totlen = cpu_to_be32(sizeof(tmp_tre) + digest_len);
812
813 struct tpm_rsp_header rsp;
814 u32 resp_length = sizeof(rsp);
815 int ret = tpmhw_transmit(0, &tre->hdr, &rsp, &resp_length,
816 TPM_DURATION_TYPE_SHORT);
817 if (ret || resp_length != sizeof(rsp) || rsp.errcode)
818 return -1;
819
820 return 0;
821 }
822
823 static int
tpm_extend(struct tpm_log_entry * le,int digest_len)824 tpm_extend(struct tpm_log_entry *le, int digest_len)
825 {
826 switch (TPM_version) {
827 case TPM_VERSION_1_2:
828 return tpm12_extend(le, digest_len);
829 case TPM_VERSION_2:
830 return tpm20_extend(le, digest_len);
831 }
832 return -1;
833 }
834
835 static int
tpm20_stirrandom(void)836 tpm20_stirrandom(void)
837 {
838 struct tpm2_req_stirrandom stir = {
839 .hdr.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
840 .hdr.totlen = cpu_to_be32(sizeof(stir)),
841 .hdr.ordinal = cpu_to_be32(TPM2_CC_StirRandom),
842 .size = cpu_to_be16(sizeof(stir.stir)),
843 .stir = rdtscll(),
844 };
845 /* set more bits to stir with */
846 stir.stir += swab64(rdtscll());
847
848 struct tpm_rsp_header rsp;
849 u32 resp_length = sizeof(rsp);
850 int ret = tpmhw_transmit(0, &stir.hdr, &rsp, &resp_length,
851 TPM_DURATION_TYPE_SHORT);
852 if (ret || resp_length != sizeof(rsp) || rsp.errcode)
853 ret = -1;
854
855 dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_StirRandom = 0x%08x\n",
856 ret);
857
858 return ret;
859 }
860
861 static int
tpm20_getrandom(u8 * buf,u16 buf_len)862 tpm20_getrandom(u8 *buf, u16 buf_len)
863 {
864 struct tpm2_res_getrandom rsp;
865
866 if (buf_len > sizeof(rsp.rnd.buffer))
867 return -1;
868
869 struct tpm2_req_getrandom trgr = {
870 .hdr.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
871 .hdr.totlen = cpu_to_be32(sizeof(trgr)),
872 .hdr.ordinal = cpu_to_be32(TPM2_CC_GetRandom),
873 .bytesRequested = cpu_to_be16(buf_len),
874 };
875 u32 resp_length = sizeof(rsp);
876
877 int ret = tpmhw_transmit(0, &trgr.hdr, &rsp, &resp_length,
878 TPM_DURATION_TYPE_MEDIUM);
879 if (ret || resp_length != sizeof(rsp) || rsp.hdr.errcode)
880 ret = -1;
881 else
882 memcpy(buf, rsp.rnd.buffer, buf_len);
883
884 dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_GetRandom = 0x%08x\n",
885 ret);
886
887 return ret;
888 }
889
890 static int
tpm20_hierarchycontrol(u32 hierarchy,u8 state)891 tpm20_hierarchycontrol(u32 hierarchy, u8 state)
892 {
893 /* we will try to deactivate the TPM now - ignoring all errors */
894 struct tpm2_req_hierarchycontrol trh = {
895 .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS),
896 .hdr.totlen = cpu_to_be32(sizeof(trh)),
897 .hdr.ordinal = cpu_to_be32(TPM2_CC_HierarchyControl),
898 .authhandle = cpu_to_be32(TPM2_RH_PLATFORM),
899 .authblocksize = cpu_to_be32(sizeof(trh.authblock)),
900 .authblock = {
901 .handle = cpu_to_be32(TPM2_RS_PW),
902 .noncesize = cpu_to_be16(0),
903 .contsession = TPM2_YES,
904 .pwdsize = cpu_to_be16(0),
905 },
906 .enable = cpu_to_be32(hierarchy),
907 .state = state,
908 };
909 struct tpm_rsp_header rsp;
910 u32 resp_length = sizeof(rsp);
911 int ret = tpmhw_transmit(0, &trh.hdr, &rsp, &resp_length,
912 TPM_DURATION_TYPE_MEDIUM);
913 if (ret || resp_length != sizeof(rsp) || rsp.errcode)
914 ret = -1;
915
916 dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_HierarchyControl = 0x%08x\n",
917 ret);
918
919 return ret;
920 }
921
922 static int
tpm20_hierarchychangeauth(u8 auth[20])923 tpm20_hierarchychangeauth(u8 auth[20])
924 {
925 struct tpm2_req_hierarchychangeauth trhca = {
926 .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS),
927 .hdr.totlen = cpu_to_be32(sizeof(trhca)),
928 .hdr.ordinal = cpu_to_be32(TPM2_CC_HierarchyChangeAuth),
929 .authhandle = cpu_to_be32(TPM2_RH_PLATFORM),
930 .authblocksize = cpu_to_be32(sizeof(trhca.authblock)),
931 .authblock = {
932 .handle = cpu_to_be32(TPM2_RS_PW),
933 .noncesize = cpu_to_be16(0),
934 .contsession = TPM2_YES,
935 .pwdsize = cpu_to_be16(0),
936 },
937 .newAuth = {
938 .size = cpu_to_be16(sizeof(trhca.newAuth.buffer)),
939 },
940 };
941 memcpy(trhca.newAuth.buffer, auth, sizeof(trhca.newAuth.buffer));
942
943 struct tpm_rsp_header rsp;
944 u32 resp_length = sizeof(rsp);
945 int ret = tpmhw_transmit(0, &trhca.hdr, &rsp, &resp_length,
946 TPM_DURATION_TYPE_MEDIUM);
947 if (ret || resp_length != sizeof(rsp) || rsp.errcode)
948 ret = -1;
949
950 dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_HierarchyChangeAuth = 0x%08x\n",
951 ret);
952
953 return ret;
954 }
955
956
957 /****************************************************************
958 * Setup and Measurements
959 ****************************************************************/
960
961 static int TPM_has_physical_presence;
962 u8 TPM_working VARLOW;
963
964 static int
tpm_is_working(void)965 tpm_is_working(void)
966 {
967 return CONFIG_TCGBIOS && TPM_working;
968 }
969
970 static void
tpm_set_failure(void)971 tpm_set_failure(void)
972 {
973 switch (TPM_version) {
974 case TPM_VERSION_1_2:
975 /*
976 * We will try to deactivate the TPM now - ignoring all errors
977 * Physical presence is asserted.
978 */
979
980 tpm_simple_cmd(0, TPM_ORD_SetTempDeactivated,
981 0, 0, TPM_DURATION_TYPE_SHORT);
982 break;
983 case TPM_VERSION_2:
984 tpm20_hierarchycontrol(TPM2_RH_ENDORSEMENT, TPM2_NO);
985 tpm20_hierarchycontrol(TPM2_RH_OWNER, TPM2_NO);
986 tpm20_hierarchycontrol(TPM2_RH_PLATFORM, TPM2_NO);
987 break;
988 }
989
990 TPM_working = 0;
991 }
992
993 /*
994 * Add a measurement to the log; the data at data_seg:data/length are
995 * appended to the TCG_PCClientPCREventStruct
996 *
997 * Input parameters:
998 * pcrindex : which PCR to extend
999 * event_type : type of event; specs section on 'Event Types'
1000 * event : pointer to info (e.g., string) to be added to log as-is
1001 * event_length: length of the event
1002 * hashdata : pointer to the data to be hashed
1003 * hashdata_length: length of the data to be hashed
1004 */
1005 static void
tpm_add_measurement_to_log(u32 pcrindex,u32 event_type,const char * event,u32 event_length,const u8 * hashdata,u32 hashdata_length)1006 tpm_add_measurement_to_log(u32 pcrindex, u32 event_type,
1007 const char *event, u32 event_length,
1008 const u8 *hashdata, u32 hashdata_length)
1009 {
1010 if (!tpm_is_working())
1011 return;
1012
1013 struct tpm_log_entry le = {
1014 .hdr.pcrindex = pcrindex,
1015 .hdr.eventtype = event_type,
1016 };
1017 int digest_len = tpm_build_digest(&le, hashdata, hashdata_length, 1);
1018 if (digest_len < 0)
1019 return;
1020 int ret = tpm_extend(&le, digest_len);
1021 if (ret) {
1022 tpm_set_failure();
1023 return;
1024 }
1025 tpm_build_digest(&le, hashdata, hashdata_length, 0);
1026 tpm_log_event(&le.hdr, digest_len, event, event_length);
1027 }
1028
1029 // Add an EV_ACTION measurement to the list of measurements
1030 static void
tpm_add_action(u32 pcrIndex,const char * string)1031 tpm_add_action(u32 pcrIndex, const char *string)
1032 {
1033 u32 len = strlen(string);
1034 tpm_add_measurement_to_log(pcrIndex, EV_ACTION,
1035 string, len, (u8 *)string, len);
1036 }
1037
1038 /*
1039 * Add event separators for PCRs 0 to 7; specs on 'Measuring Boot Events'
1040 */
1041 static void
tpm_add_event_separators(void)1042 tpm_add_event_separators(void)
1043 {
1044 static const u8 evt_separator[] = {0xff,0xff,0xff,0xff};
1045 u32 pcrIndex;
1046 for (pcrIndex = 0; pcrIndex <= 7; pcrIndex++)
1047 tpm_add_measurement_to_log(pcrIndex, EV_SEPARATOR,
1048 (const char *)evt_separator,
1049 sizeof(evt_separator),
1050 evt_separator,
1051 sizeof(evt_separator));
1052 }
1053
1054 static void
tpm_smbios_measure(void)1055 tpm_smbios_measure(void)
1056 {
1057 struct pcctes pcctes = {
1058 .eventid = 1,
1059 .eventdatasize = SHA1_BUFSIZE,
1060 };
1061 struct smbios_entry_point *sep = SMBiosAddr;
1062
1063 dprintf(DEBUG_tcg, "TCGBIOS: SMBIOS at %p\n", sep);
1064
1065 if (!sep)
1066 return;
1067
1068 sha1((const u8 *)sep->structure_table_address,
1069 sep->structure_table_length, pcctes.digest);
1070 tpm_add_measurement_to_log(1,
1071 EV_EVENT_TAG,
1072 (const char *)&pcctes, sizeof(pcctes),
1073 (u8 *)&pcctes, sizeof(pcctes));
1074 }
1075
1076 static int
tpm12_assert_physical_presence(void)1077 tpm12_assert_physical_presence(void)
1078 {
1079 int ret = tpm_simple_cmd(0, TPM_ORD_PhysicalPresence,
1080 2, TPM_PP_PRESENT, TPM_DURATION_TYPE_SHORT);
1081 if (!ret)
1082 return 0;
1083
1084 struct tpm_permanent_flags pf;
1085 ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf));
1086 if (ret)
1087 return -1;
1088
1089 /* check if hardware physical presence is supported */
1090 if (pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE]) {
1091 /* HW phys. presence may not be asserted... */
1092 return 0;
1093 }
1094
1095 if (!pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK]
1096 && !pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE]) {
1097 tpm_simple_cmd(0, TPM_ORD_PhysicalPresence,
1098 2, TPM_PP_CMD_ENABLE, TPM_DURATION_TYPE_SHORT);
1099
1100 return tpm_simple_cmd(0, TPM_ORD_PhysicalPresence,
1101 2, TPM_PP_PRESENT, TPM_DURATION_TYPE_SHORT);
1102 }
1103 return -1;
1104 }
1105
1106 static int
tpm12_startup(void)1107 tpm12_startup(void)
1108 {
1109 dprintf(DEBUG_tcg, "TCGBIOS: Starting with TPM_Startup(ST_CLEAR)\n");
1110 int ret = tpm_simple_cmd(0, TPM_ORD_Startup,
1111 2, TPM_ST_CLEAR, TPM_DURATION_TYPE_SHORT);
1112 if (CONFIG_COREBOOT && ret == TPM_INVALID_POSTINIT)
1113 /* with other firmware on the system the TPM may already have been
1114 * initialized
1115 */
1116 ret = 0;
1117 if (ret)
1118 goto err_exit;
1119
1120 /* assertion of physical presence is only possible after startup */
1121 ret = tpm12_assert_physical_presence();
1122 if (!ret)
1123 TPM_has_physical_presence = 1;
1124
1125 ret = tpm12_determine_timeouts();
1126 if (ret)
1127 goto err_exit;
1128
1129 ret = tpm_simple_cmd(0, TPM_ORD_SelfTestFull,
1130 0, 0, TPM_DURATION_TYPE_LONG);
1131 if (ret)
1132 goto err_exit;
1133
1134 ret = tpm_simple_cmd(3, TSC_ORD_ResetEstablishmentBit,
1135 0, 0, TPM_DURATION_TYPE_SHORT);
1136 if (ret && ret != TPM_BAD_LOCALITY)
1137 goto err_exit;
1138
1139 return 0;
1140
1141 err_exit:
1142 dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
1143
1144 tpm_set_failure();
1145 return -1;
1146 }
1147
1148 static int
tpm20_startup(void)1149 tpm20_startup(void)
1150 {
1151 tpm20_set_timeouts();
1152
1153 int ret = tpm_simple_cmd(0, TPM2_CC_Startup,
1154 2, TPM2_SU_CLEAR, TPM_DURATION_TYPE_SHORT);
1155
1156 dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_Startup(SU_CLEAR) = 0x%08x\n",
1157 ret);
1158
1159 if (CONFIG_COREBOOT && ret == TPM2_RC_INITIALIZE)
1160 /* with other firmware on the system the TPM may already have been
1161 * initialized
1162 */
1163 ret = 0;
1164
1165 if (ret)
1166 goto err_exit;
1167
1168 ret = tpm_simple_cmd(0, TPM2_CC_SelfTest,
1169 1, TPM2_YES, TPM_DURATION_TYPE_LONG);
1170
1171 dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_SelfTest = 0x%08x\n",
1172 ret);
1173
1174 if (ret)
1175 goto err_exit;
1176
1177 ret = tpm20_get_pcrbanks();
1178 if (ret)
1179 goto err_exit;
1180
1181 ret = tpm20_write_EfiSpecIdEventStruct();
1182 if (ret)
1183 goto err_exit;
1184
1185 return 0;
1186
1187 err_exit:
1188 dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
1189
1190 tpm_set_failure();
1191 return -1;
1192 }
1193
1194 static int
tpm_startup(void)1195 tpm_startup(void)
1196 {
1197 switch (TPM_version) {
1198 case TPM_VERSION_1_2:
1199 return tpm12_startup();
1200 case TPM_VERSION_2:
1201 return tpm20_startup();
1202 }
1203 return -1;
1204 }
1205
1206 void
tpm_setup(void)1207 tpm_setup(void)
1208 {
1209 if (!CONFIG_TCGBIOS)
1210 return;
1211
1212 int ret = tpm_tpm2_probe();
1213 if (ret) {
1214 ret = tpm_tcpa_probe();
1215 if (ret)
1216 return;
1217 }
1218
1219 TPM_version = tpmhw_probe();
1220 if (TPM_version == TPM_VERSION_NONE)
1221 return;
1222
1223 dprintf(DEBUG_tcg,
1224 "TCGBIOS: Detected a TPM %s.\n",
1225 (TPM_version == TPM_VERSION_1_2) ? "1.2" : "2");
1226
1227 TPM_working = 1;
1228
1229 if (runningOnXen())
1230 return;
1231
1232 ret = tpm_startup();
1233 if (ret)
1234 return;
1235
1236 tpm_smbios_measure();
1237 tpm_add_action(2, "Start Option ROM Scan");
1238 }
1239
1240 static void
tpm20_prepboot(void)1241 tpm20_prepboot(void)
1242 {
1243 int ret = tpm20_stirrandom();
1244 if (ret)
1245 goto err_exit;
1246
1247 u8 auth[20];
1248 ret = tpm20_getrandom(&auth[0], sizeof(auth));
1249 if (ret)
1250 goto err_exit;
1251
1252 ret = tpm20_hierarchychangeauth(auth);
1253 if (ret)
1254 goto err_exit;
1255
1256 return;
1257
1258 err_exit:
1259 dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
1260
1261 tpm_set_failure();
1262 }
1263
1264 void
tpm_prepboot(void)1265 tpm_prepboot(void)
1266 {
1267 if (!CONFIG_TCGBIOS)
1268 return;
1269
1270 switch (TPM_version) {
1271 case TPM_VERSION_1_2:
1272 if (TPM_has_physical_presence)
1273 tpm_simple_cmd(0, TPM_ORD_PhysicalPresence,
1274 2, TPM_PP_NOT_PRESENT_LOCK, TPM_DURATION_TYPE_SHORT);
1275 break;
1276 case TPM_VERSION_2:
1277 tpm20_prepboot();
1278 break;
1279 }
1280
1281 tpm_add_action(4, "Calling INT 19h");
1282 tpm_add_event_separators();
1283 }
1284
1285 /*
1286 * Add measurement to the log about an option rom
1287 */
1288 void
tpm_option_rom(const void * addr,u32 len)1289 tpm_option_rom(const void *addr, u32 len)
1290 {
1291 if (!tpm_is_working())
1292 return;
1293
1294 struct pcctes_romex pcctes = {
1295 .eventid = 7,
1296 .eventdatasize = sizeof(u16) + sizeof(u16) + SHA1_BUFSIZE,
1297 };
1298 sha1((const u8 *)addr, len, pcctes.digest);
1299 tpm_add_measurement_to_log(2,
1300 EV_EVENT_TAG,
1301 (const char *)&pcctes, sizeof(pcctes),
1302 (u8 *)&pcctes, sizeof(pcctes));
1303 }
1304
1305 void
tpm_add_bcv(u32 bootdrv,const u8 * addr,u32 length)1306 tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length)
1307 {
1308 if (!tpm_is_working())
1309 return;
1310
1311 if (length < 0x200)
1312 return;
1313
1314 const char *string = "Booting BCV device 00h (Floppy)";
1315 if (bootdrv == 0x80)
1316 string = "Booting BCV device 80h (HDD)";
1317 tpm_add_action(4, string);
1318
1319 /* specs: see section 'Hard Disk Device or Hard Disk-Like Devices' */
1320 /* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */
1321 string = "MBR";
1322 tpm_add_measurement_to_log(4, EV_IPL,
1323 string, strlen(string),
1324 addr, 0x1b8);
1325
1326 /* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */
1327 string = "MBR PARTITION_TABLE";
1328 tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA,
1329 string, strlen(string),
1330 addr + 0x1b8, 0x48);
1331 }
1332
1333 void
tpm_add_cdrom(u32 bootdrv,const u8 * addr,u32 length)1334 tpm_add_cdrom(u32 bootdrv, const u8 *addr, u32 length)
1335 {
1336 if (!tpm_is_working())
1337 return;
1338
1339 tpm_add_action(4, "Booting from CD ROM device");
1340
1341 /* specs: see section 'El Torito' */
1342 const char *string = "EL TORITO IPL";
1343 tpm_add_measurement_to_log(4, EV_IPL,
1344 string, strlen(string),
1345 addr, length);
1346 }
1347
1348 void
tpm_add_cdrom_catalog(const u8 * addr,u32 length)1349 tpm_add_cdrom_catalog(const u8 *addr, u32 length)
1350 {
1351 if (!tpm_is_working())
1352 return;
1353
1354 tpm_add_action(4, "Booting from CD ROM device");
1355
1356 /* specs: see section 'El Torito' */
1357 const char *string = "BOOT CATALOG";
1358 tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA,
1359 string, strlen(string),
1360 addr, length);
1361 }
1362
1363 void
tpm_s3_resume(void)1364 tpm_s3_resume(void)
1365 {
1366 if (!tpm_is_working())
1367 return;
1368
1369 dprintf(DEBUG_tcg, "TCGBIOS: Resuming with TPM_Startup(ST_STATE)\n");
1370
1371 int ret = -1;
1372
1373 switch (TPM_version) {
1374 case TPM_VERSION_1_2:
1375 ret = tpm_simple_cmd(0, TPM_ORD_Startup,
1376 2, TPM_ST_STATE, TPM_DURATION_TYPE_SHORT);
1377 break;
1378 case TPM_VERSION_2:
1379 ret = tpm_simple_cmd(0, TPM2_CC_Startup,
1380 2, TPM2_SU_STATE, TPM_DURATION_TYPE_SHORT);
1381
1382 dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_Startup(SU_STATE) = 0x%08x\n",
1383 ret);
1384
1385 if (ret)
1386 goto err_exit;
1387
1388
1389 ret = tpm_simple_cmd(0, TPM2_CC_SelfTest,
1390 1, TPM2_YES, TPM_DURATION_TYPE_LONG);
1391
1392 dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_SelfTest() = 0x%08x\n",
1393 ret);
1394
1395 break;
1396 }
1397
1398 if (ret)
1399 goto err_exit;
1400
1401 return;
1402
1403 err_exit:
1404 dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
1405
1406 tpm_set_failure();
1407 }
1408
1409
1410 /****************************************************************
1411 * BIOS interface
1412 ****************************************************************/
1413
1414 u8 TPM_interface_shutdown VARLOW;
1415
input_buf32(struct bregs * regs)1416 static inline void *input_buf32(struct bregs *regs)
1417 {
1418 return MAKE_FLATPTR(regs->es, regs->di);
1419 }
1420
output_buf32(struct bregs * regs)1421 static inline void *output_buf32(struct bregs *regs)
1422 {
1423 return MAKE_FLATPTR(regs->ds, regs->si);
1424 }
1425
1426 static u32
hash_log_extend(struct pcpes * pcpes,const void * hashdata,u32 hashdata_length,void * event,int extend)1427 hash_log_extend(struct pcpes *pcpes, const void *hashdata, u32 hashdata_length
1428 , void *event, int extend)
1429 {
1430 if (pcpes->pcrindex >= 24)
1431 return TCG_INVALID_INPUT_PARA;
1432 if (hashdata)
1433 sha1(hashdata, hashdata_length, pcpes->digest);
1434
1435 struct tpm_log_entry le = {
1436 .hdr.pcrindex = pcpes->pcrindex,
1437 .hdr.eventtype = pcpes->eventtype,
1438 };
1439 int digest_len = tpm12_build_digest_direct(&le, pcpes->digest);
1440 if (digest_len < 0)
1441 return TCG_GENERAL_ERROR;
1442 if (extend) {
1443 int ret = tpm_extend(&le, digest_len);
1444 if (ret)
1445 return TCG_TCG_COMMAND_ERROR;
1446 }
1447 tpm12_build_digest_direct(&le, pcpes->digest);
1448 int ret = tpm_log_event(&le.hdr, digest_len
1449 , pcpes->event, pcpes->eventdatasize);
1450 if (ret)
1451 return TCG_PC_LOGOVERFLOW;
1452 return 0;
1453 }
1454
1455 static u32
hash_log_extend_event_int(const struct hleei_short * hleei_s,struct hleeo * hleeo)1456 hash_log_extend_event_int(const struct hleei_short *hleei_s,
1457 struct hleeo *hleeo)
1458 {
1459 u32 rc = 0;
1460 struct hleei_long *hleei_l = (struct hleei_long *)hleei_s;
1461 const void *logdataptr;
1462 u32 logdatalen;
1463 struct pcpes *pcpes;
1464 u32 pcrindex;
1465
1466 /* short or long version? */
1467 switch (hleei_s->ipblength) {
1468 case sizeof(struct hleei_short):
1469 /* short */
1470 logdataptr = hleei_s->logdataptr;
1471 logdatalen = hleei_s->logdatalen;
1472 pcrindex = hleei_s->pcrindex;
1473 break;
1474
1475 case sizeof(struct hleei_long):
1476 /* long */
1477 logdataptr = hleei_l->logdataptr;
1478 logdatalen = hleei_l->logdatalen;
1479 pcrindex = hleei_l->pcrindex;
1480 break;
1481
1482 default:
1483 /* bad input block */
1484 rc = TCG_INVALID_INPUT_PARA;
1485 goto err_exit;
1486 }
1487
1488 pcpes = (struct pcpes *)logdataptr;
1489
1490 if (pcpes->pcrindex != pcrindex
1491 || logdatalen != sizeof(*pcpes) + pcpes->eventdatasize) {
1492 rc = TCG_INVALID_INPUT_PARA;
1493 goto err_exit;
1494 }
1495 rc = hash_log_extend(pcpes, hleei_s->hashdataptr, hleei_s->hashdatalen
1496 , pcpes->event, 1);
1497 if (rc)
1498 goto err_exit;
1499
1500 hleeo->opblength = sizeof(struct hleeo);
1501 hleeo->reserved = 0;
1502 hleeo->eventnumber = tpm_state.entry_count;
1503 memcpy(hleeo->digest, pcpes->digest, sizeof(hleeo->digest));
1504
1505 err_exit:
1506 if (rc != 0) {
1507 hleeo->opblength = 4;
1508 hleeo->reserved = 0;
1509 }
1510
1511 return rc;
1512 }
1513
1514 static u32
pass_through_to_tpm_int(struct pttti * pttti,struct pttto * pttto)1515 pass_through_to_tpm_int(struct pttti *pttti, struct pttto *pttto)
1516 {
1517 u32 rc = 0;
1518 struct tpm_req_header *trh = (void*)pttti->tpmopin;
1519
1520 if (pttti->ipblength < sizeof(struct pttti) + sizeof(*trh)
1521 || pttti->ipblength != sizeof(struct pttti) + be32_to_cpu(trh->totlen)
1522 || pttti->opblength < sizeof(struct pttto)) {
1523 rc = TCG_INVALID_INPUT_PARA;
1524 goto err_exit;
1525 }
1526
1527 u16 tag = be16_to_cpu(trh->tag);
1528
1529 switch (TPM_version) {
1530 case TPM_VERSION_1_2:
1531 if (tag != TPM_TAG_RQU_CMD && tag != TPM_TAG_RQU_AUTH1_CMD
1532 && tag != TPM_TAG_RQU_AUTH2_CMD) {
1533 rc = TCG_INVALID_INPUT_PARA;
1534 goto err_exit;
1535 }
1536 break;
1537 case TPM_VERSION_2:
1538 if (tag != TPM2_ST_NO_SESSIONS && tag != TPM2_ST_SESSIONS) {
1539 rc = TCG_INVALID_INPUT_PARA;
1540 goto err_exit;
1541 }
1542 }
1543
1544 u32 resbuflen = pttti->opblength - offsetof(struct pttto, tpmopout);
1545 int ret = tpmhw_transmit(0, trh, pttto->tpmopout, &resbuflen,
1546 TPM_DURATION_TYPE_LONG /* worst case */);
1547 if (ret) {
1548 rc = TCG_FATAL_COM_ERROR;
1549 goto err_exit;
1550 }
1551
1552 pttto->opblength = offsetof(struct pttto, tpmopout) + resbuflen;
1553 pttto->reserved = 0;
1554
1555 err_exit:
1556 if (rc != 0) {
1557 pttto->opblength = 4;
1558 pttto->reserved = 0;
1559 }
1560
1561 return rc;
1562 }
1563
1564 static u32
shutdown_preboot_interface(void)1565 shutdown_preboot_interface(void)
1566 {
1567 TPM_interface_shutdown = 1;
1568 return 0;
1569 }
1570
1571 static u32
hash_log_event_int(const struct hlei * hlei,struct hleo * hleo)1572 hash_log_event_int(const struct hlei *hlei, struct hleo *hleo)
1573 {
1574 u32 rc = 0;
1575 u16 size;
1576 struct pcpes *pcpes;
1577
1578 size = hlei->ipblength;
1579 if (size != sizeof(*hlei)) {
1580 rc = TCG_INVALID_INPUT_PARA;
1581 goto err_exit;
1582 }
1583
1584 pcpes = (struct pcpes *)hlei->logdataptr;
1585
1586 if (pcpes->pcrindex != hlei->pcrindex
1587 || pcpes->eventtype != hlei->logeventtype
1588 || hlei->logdatalen != sizeof(*pcpes) + pcpes->eventdatasize) {
1589 rc = TCG_INVALID_INPUT_PARA;
1590 goto err_exit;
1591 }
1592 rc = hash_log_extend(pcpes, hlei->hashdataptr, hlei->hashdatalen
1593 , pcpes->event, 0);
1594 if (rc)
1595 goto err_exit;
1596
1597 /* updating the log was fine */
1598 hleo->opblength = sizeof(struct hleo);
1599 hleo->reserved = 0;
1600 hleo->eventnumber = tpm_state.entry_count;
1601
1602 err_exit:
1603 if (rc != 0) {
1604 hleo->opblength = 2;
1605 hleo->reserved = 0;
1606 }
1607
1608 return rc;
1609 }
1610
1611 static u32
hash_all_int(const struct hai * hai,u8 * hash)1612 hash_all_int(const struct hai *hai, u8 *hash)
1613 {
1614 if (hai->ipblength != sizeof(struct hai) ||
1615 hai->hashdataptr == 0 ||
1616 hai->hashdatalen == 0 ||
1617 hai->algorithmid != TPM_ALG_SHA)
1618 return TCG_INVALID_INPUT_PARA;
1619
1620 sha1((const u8 *)hai->hashdataptr, hai->hashdatalen, hash);
1621 return 0;
1622 }
1623
1624 static u32
tss_int(struct ti * ti,struct to * to)1625 tss_int(struct ti *ti, struct to *to)
1626 {
1627 to->opblength = sizeof(struct to);
1628 to->reserved = 0;
1629
1630 return TCG_PC_UNSUPPORTED;
1631 }
1632
1633 static u32
compact_hash_log_extend_event_int(u8 * buffer,u32 info,u32 length,u32 pcrindex,u32 * edx_ptr)1634 compact_hash_log_extend_event_int(u8 *buffer,
1635 u32 info,
1636 u32 length,
1637 u32 pcrindex,
1638 u32 *edx_ptr)
1639 {
1640 struct pcpes pcpes = {
1641 .pcrindex = pcrindex,
1642 .eventtype = EV_COMPACT_HASH,
1643 .eventdatasize = sizeof(info),
1644 };
1645 u32 rc = hash_log_extend(&pcpes, buffer, length, &info, 1);
1646 if (rc)
1647 return rc;
1648
1649 *edx_ptr = tpm_state.entry_count;
1650 return 0;
1651 }
1652
1653 void VISIBLE32FLAT
tpm_interrupt_handler32(struct bregs * regs)1654 tpm_interrupt_handler32(struct bregs *regs)
1655 {
1656 if (!CONFIG_TCGBIOS)
1657 return;
1658
1659 set_cf(regs, 0);
1660
1661 if (TPM_interface_shutdown && regs->al) {
1662 regs->eax = TCG_INTERFACE_SHUTDOWN;
1663 return;
1664 }
1665
1666 switch ((enum irq_ids)regs->al) {
1667 case TCG_StatusCheck:
1668 if (!tpmhw_is_present()) {
1669 /* no TPM available */
1670 regs->eax = TCG_PC_TPM_NOT_PRESENT;
1671 } else {
1672 regs->eax = 0;
1673 regs->ebx = TCG_MAGIC;
1674 regs->ch = TCG_VERSION_MAJOR;
1675 regs->cl = TCG_VERSION_MINOR;
1676 regs->edx = 0x0;
1677 regs->esi = (u32)tpm_state.log_area_start_address;
1678 regs->edi = (u32)tpm_state.log_area_last_entry;
1679 }
1680 break;
1681
1682 case TCG_HashLogExtendEvent:
1683 regs->eax =
1684 hash_log_extend_event_int(
1685 (struct hleei_short *)input_buf32(regs),
1686 (struct hleeo *)output_buf32(regs));
1687 break;
1688
1689 case TCG_PassThroughToTPM:
1690 regs->eax =
1691 pass_through_to_tpm_int((struct pttti *)input_buf32(regs),
1692 (struct pttto *)output_buf32(regs));
1693 break;
1694
1695 case TCG_ShutdownPreBootInterface:
1696 regs->eax = shutdown_preboot_interface();
1697 break;
1698
1699 case TCG_HashLogEvent:
1700 regs->eax = hash_log_event_int((struct hlei*)input_buf32(regs),
1701 (struct hleo*)output_buf32(regs));
1702 break;
1703
1704 case TCG_HashAll:
1705 regs->eax =
1706 hash_all_int((struct hai*)input_buf32(regs),
1707 (u8 *)output_buf32(regs));
1708 break;
1709
1710 case TCG_TSS:
1711 regs->eax = tss_int((struct ti*)input_buf32(regs),
1712 (struct to*)output_buf32(regs));
1713 break;
1714
1715 case TCG_CompactHashLogExtendEvent:
1716 regs->eax =
1717 compact_hash_log_extend_event_int((u8 *)input_buf32(regs),
1718 regs->esi,
1719 regs->ecx,
1720 regs->edx,
1721 ®s->edx);
1722 break;
1723
1724 default:
1725 set_cf(regs, 1);
1726 }
1727
1728 return;
1729 }
1730
1731
1732 /****************************************************************
1733 * TPM Configuration Menu
1734 ****************************************************************/
1735
1736 typedef u8 tpm_ppi_code;
1737
1738 static int
tpm12_read_has_owner(int * has_owner)1739 tpm12_read_has_owner(int *has_owner)
1740 {
1741 struct tpm_res_getcap_ownerauth oauth;
1742 int ret = tpm12_get_capability(TPM_CAP_PROPERTY, TPM_CAP_PROP_OWNER
1743 , &oauth.hdr, sizeof(oauth));
1744 if (ret)
1745 return -1;
1746
1747 *has_owner = oauth.flag;
1748
1749 return 0;
1750 }
1751
1752 static int
tpm12_enable_tpm(int enable,int verbose)1753 tpm12_enable_tpm(int enable, int verbose)
1754 {
1755 struct tpm_permanent_flags pf;
1756 int ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf));
1757 if (ret)
1758 return -1;
1759
1760 if (pf.flags[PERM_FLAG_IDX_DISABLE] && !enable)
1761 return 0;
1762
1763 ret = tpm_simple_cmd(0, enable ? TPM_ORD_PhysicalEnable
1764 : TPM_ORD_PhysicalDisable,
1765 0, 0, TPM_DURATION_TYPE_SHORT);
1766 if (ret) {
1767 if (enable)
1768 dprintf(DEBUG_tcg, "TCGBIOS: Enabling the TPM failed.\n");
1769 else
1770 dprintf(DEBUG_tcg, "TCGBIOS: Disabling the TPM failed.\n");
1771 }
1772 return ret;
1773 }
1774
1775 static int
tpm12_activate_tpm(int activate,int allow_reset,int verbose)1776 tpm12_activate_tpm(int activate, int allow_reset, int verbose)
1777 {
1778 struct tpm_permanent_flags pf;
1779 int ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf));
1780 if (ret)
1781 return -1;
1782
1783 if (pf.flags[PERM_FLAG_IDX_DEACTIVATED] && !activate)
1784 return 0;
1785
1786 if (pf.flags[PERM_FLAG_IDX_DISABLE])
1787 return 0;
1788
1789 ret = tpm_simple_cmd(0, TPM_ORD_PhysicalSetDeactivated,
1790 1, activate ? 0x00 : 0x01, TPM_DURATION_TYPE_SHORT);
1791 if (ret)
1792 return ret;
1793
1794 if (activate && allow_reset) {
1795 if (verbose) {
1796 printf("Requiring a reboot to activate the TPM.\n");
1797
1798 msleep(2000);
1799 }
1800 reset();
1801 }
1802
1803 return 0;
1804 }
1805
1806 static int
tpm12_enable_activate(int allow_reset,int verbose)1807 tpm12_enable_activate(int allow_reset, int verbose)
1808 {
1809 int ret = tpm12_enable_tpm(1, verbose);
1810 if (ret)
1811 return ret;
1812
1813 return tpm12_activate_tpm(1, allow_reset, verbose);
1814 }
1815
1816 static int
tpm12_force_clear(int enable_activate_before,int enable_activate_after,int verbose)1817 tpm12_force_clear(int enable_activate_before, int enable_activate_after,
1818 int verbose)
1819 {
1820 int has_owner;
1821 int ret = tpm12_read_has_owner(&has_owner);
1822 if (ret)
1823 return -1;
1824 if (!has_owner) {
1825 if (verbose)
1826 printf("TPM does not have an owner.\n");
1827 return 0;
1828 }
1829
1830 if (enable_activate_before) {
1831 ret = tpm12_enable_activate(0, verbose);
1832 if (ret) {
1833 dprintf(DEBUG_tcg,
1834 "TCGBIOS: Enabling/activating the TPM failed.\n");
1835 return ret;
1836 }
1837 }
1838
1839 ret = tpm_simple_cmd(0, TPM_ORD_ForceClear,
1840 0, 0, TPM_DURATION_TYPE_SHORT);
1841 if (ret)
1842 return ret;
1843
1844 if (!enable_activate_after) {
1845 if (verbose)
1846 printf("Owner successfully cleared.\n"
1847 "You will need to enable/activate the TPM again.\n\n");
1848 return 0;
1849 }
1850
1851 return tpm12_enable_activate(1, verbose);
1852 }
1853
1854 static int
tpm12_set_owner_install(int allow,int verbose)1855 tpm12_set_owner_install(int allow, int verbose)
1856 {
1857 int has_owner;
1858 int ret = tpm12_read_has_owner(&has_owner);
1859 if (ret)
1860 return -1;
1861 if (has_owner) {
1862 if (verbose)
1863 printf("Must first remove owner.\n");
1864 return 0;
1865 }
1866
1867 struct tpm_permanent_flags pf;
1868 ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf));
1869 if (ret)
1870 return -1;
1871
1872 if (pf.flags[PERM_FLAG_IDX_DISABLE]) {
1873 if (verbose)
1874 printf("TPM must first be enable.\n");
1875 return 0;
1876 }
1877
1878 ret = tpm_simple_cmd(0, TPM_ORD_SetOwnerInstall,
1879 1, allow ? 0x01 : 0x00, TPM_DURATION_TYPE_SHORT);
1880 if (ret)
1881 return ret;
1882
1883 if (verbose)
1884 printf("Installation of owner %s.\n", allow ? "enabled" : "disabled");
1885
1886 return 0;
1887 }
1888
1889 static int
tpm12_process_cfg(tpm_ppi_code msgCode,int verbose)1890 tpm12_process_cfg(tpm_ppi_code msgCode, int verbose)
1891 {
1892 int ret = 0;
1893
1894 switch (msgCode) {
1895 case TPM_PPI_OP_NOOP: /* no-op */
1896 break;
1897
1898 case TPM_PPI_OP_ENABLE:
1899 ret = tpm12_enable_tpm(1, verbose);
1900 break;
1901
1902 case TPM_PPI_OP_DISABLE:
1903 ret = tpm12_enable_tpm(0, verbose);
1904 break;
1905
1906 case TPM_PPI_OP_ACTIVATE:
1907 ret = tpm12_activate_tpm(1, 1, verbose);
1908 break;
1909
1910 case TPM_PPI_OP_DEACTIVATE:
1911 ret = tpm12_activate_tpm(0, 1, verbose);
1912 break;
1913
1914 case TPM_PPI_OP_CLEAR:
1915 ret = tpm12_force_clear(1, 0, verbose);
1916 break;
1917
1918 case TPM_PPI_OP_SET_OWNERINSTALL_TRUE:
1919 ret = tpm12_set_owner_install(1, verbose);
1920 break;
1921
1922 case TPM_PPI_OP_SET_OWNERINSTALL_FALSE:
1923 ret = tpm12_set_owner_install(0, verbose);
1924 break;
1925
1926 default:
1927 break;
1928 }
1929
1930 if (ret)
1931 printf("Op %d: An error occurred: 0x%x\n", msgCode, ret);
1932
1933 return ret;
1934 }
1935
1936 static int
tpm20_clearcontrol(u8 disable,int verbose)1937 tpm20_clearcontrol(u8 disable, int verbose)
1938 {
1939 struct tpm2_req_clearcontrol trc = {
1940 .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS),
1941 .hdr.totlen = cpu_to_be32(sizeof(trc)),
1942 .hdr.ordinal = cpu_to_be32(TPM2_CC_ClearControl),
1943 .authhandle = cpu_to_be32(TPM2_RH_PLATFORM),
1944 .authblocksize = cpu_to_be32(sizeof(trc.authblock)),
1945 .authblock = {
1946 .handle = cpu_to_be32(TPM2_RS_PW),
1947 .noncesize = cpu_to_be16(0),
1948 .contsession = TPM2_YES,
1949 .pwdsize = cpu_to_be16(0),
1950 },
1951 .disable = disable,
1952 };
1953 struct tpm_rsp_header rsp;
1954 u32 resp_length = sizeof(rsp);
1955 int ret = tpmhw_transmit(0, &trc.hdr, &rsp, &resp_length,
1956 TPM_DURATION_TYPE_SHORT);
1957 if (ret || resp_length != sizeof(rsp) || rsp.errcode)
1958 ret = -1;
1959
1960 dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_ClearControl = 0x%08x\n",
1961 ret);
1962
1963 return ret;
1964 }
1965
1966 static int
tpm20_clear(void)1967 tpm20_clear(void)
1968 {
1969 struct tpm2_req_clear trq = {
1970 .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS),
1971 .hdr.totlen = cpu_to_be32(sizeof(trq)),
1972 .hdr.ordinal = cpu_to_be32(TPM2_CC_Clear),
1973 .authhandle = cpu_to_be32(TPM2_RH_PLATFORM),
1974 .authblocksize = cpu_to_be32(sizeof(trq.authblock)),
1975 .authblock = {
1976 .handle = cpu_to_be32(TPM2_RS_PW),
1977 .noncesize = cpu_to_be16(0),
1978 .contsession = TPM2_YES,
1979 .pwdsize = cpu_to_be16(0),
1980 },
1981 };
1982 struct tpm_rsp_header rsp;
1983 u32 resp_length = sizeof(rsp);
1984 int ret = tpmhw_transmit(0, &trq.hdr, &rsp, &resp_length,
1985 TPM_DURATION_TYPE_MEDIUM);
1986 if (ret || resp_length != sizeof(rsp) || rsp.errcode)
1987 ret = -1;
1988
1989 dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_Clear = 0x%08x\n",
1990 ret);
1991
1992 return ret;
1993 }
1994
1995 static int
tpm20_process_cfg(tpm_ppi_code msgCode,int verbose)1996 tpm20_process_cfg(tpm_ppi_code msgCode, int verbose)
1997 {
1998 int ret = 0;
1999
2000 switch (msgCode) {
2001 case TPM_PPI_OP_NOOP: /* no-op */
2002 break;
2003
2004 case TPM_PPI_OP_CLEAR:
2005 ret = tpm20_clearcontrol(0, verbose);
2006 if (!ret)
2007 ret = tpm20_clear();
2008 break;
2009 }
2010
2011 if (ret)
2012 printf("Op %d: An error occurred: 0x%x\n", msgCode, ret);
2013
2014 return ret;
2015 }
2016
2017 static int
tpm12_get_tpm_state(void)2018 tpm12_get_tpm_state(void)
2019 {
2020 int state = 0;
2021 struct tpm_permanent_flags pf;
2022 int has_owner;
2023
2024 if (tpm12_read_permanent_flags((char *)&pf, sizeof(pf)) ||
2025 tpm12_read_has_owner(&has_owner))
2026 return ~0;
2027
2028 if (!pf.flags[PERM_FLAG_IDX_DISABLE])
2029 state |= TPM_STATE_ENABLED;
2030
2031 if (!pf.flags[PERM_FLAG_IDX_DEACTIVATED])
2032 state |= TPM_STATE_ACTIVE;
2033
2034 if (has_owner) {
2035 state |= TPM_STATE_OWNED;
2036 } else {
2037 if (pf.flags[PERM_FLAG_IDX_OWNERSHIP])
2038 state |= TPM_STATE_OWNERINSTALL;
2039 }
2040
2041 return state;
2042 }
2043
2044 static void
tpm12_show_tpm_menu(int state,int next_scancodes[7])2045 tpm12_show_tpm_menu(int state, int next_scancodes[7])
2046 {
2047 int i = 0;
2048
2049 printf("\nThe current state of the TPM is:\n");
2050
2051 if (state & TPM_STATE_ENABLED)
2052 printf(" Enabled");
2053 else
2054 printf(" Disabled");
2055
2056 if (state & TPM_STATE_ACTIVE)
2057 printf(" and active\n");
2058 else
2059 printf(" and deactivated\n");
2060
2061 if (state & TPM_STATE_OWNED)
2062 printf(" Ownership has been taken\n");
2063 else {
2064 printf(" Ownership has not been taken\n");
2065 if (state & TPM_STATE_OWNERINSTALL)
2066 printf(" A user can take ownership of the TPM\n");
2067 else
2068 printf(" Taking ownership of the TPM has been disabled\n");
2069 }
2070
2071 if ((state & (TPM_STATE_ENABLED | TPM_STATE_ACTIVE)) !=
2072 (TPM_STATE_ENABLED | TPM_STATE_ACTIVE)) {
2073 printf("\nNote: To make use of all functionality, the TPM must be "
2074 "enabled and active.\n");
2075 }
2076
2077 printf("\nAvailable options are:\n");
2078 if (state & TPM_STATE_ENABLED) {
2079 printf(" d. Disable the TPM\n");
2080 next_scancodes[i++] = 32;
2081
2082 if (state & TPM_STATE_ACTIVE) {
2083 printf(" v. Deactivate the TPM\n");
2084 next_scancodes[i++] = 47;
2085
2086 if (state & TPM_STATE_OWNERINSTALL) {
2087 printf(" p. Prevent installation of an owner\n");
2088 next_scancodes[i++] = 25;
2089 } else {
2090 printf(" s. Allow installation of an owner\n");
2091 next_scancodes[i++] = 31;
2092 }
2093 } else {
2094 printf(" a. Activate the TPM\n");
2095 next_scancodes[i++] = 30;
2096 }
2097
2098 } else {
2099 printf(" e. Enable the TPM\n");
2100 next_scancodes[i++] = 18;
2101 }
2102
2103 if (state & TPM_STATE_OWNED) {
2104 printf(" c. Clear ownership\n");
2105 next_scancodes[i++] = 46;
2106 }
2107
2108 next_scancodes[i++] = 0;
2109 }
2110
2111 static void
tpm12_menu(void)2112 tpm12_menu(void)
2113 {
2114 int scancode, next_scancodes[7];
2115 tpm_ppi_code msgCode;
2116 int state = 0, i;
2117 int waitkey;
2118
2119 printf("The Trusted Platform Module (TPM) is a hardware device in "
2120 "this machine.\n"
2121 "It can help verify the integrity of system software.\n\n");
2122
2123 for (;;) {
2124 if ((state = tpm12_get_tpm_state()) != ~0) {
2125 tpm12_show_tpm_menu(state, next_scancodes);
2126 } else {
2127 printf("TPM is not working correctly.\n");
2128 return;
2129 }
2130
2131 printf("\nIf no change is desired or if this menu was reached by "
2132 "mistake, press ESC to\n"
2133 "reboot the machine.\n");
2134
2135 msgCode = TPM_PPI_OP_NOOP;
2136
2137 waitkey = 1;
2138
2139 while (waitkey) {
2140 while ((scancode = get_keystroke(1000)) == ~0)
2141 ;
2142
2143 switch (scancode) {
2144 case 1:
2145 // ESC
2146 reset();
2147 break;
2148 case 18: /* e. enable */
2149 msgCode = TPM_PPI_OP_ENABLE;
2150 break;
2151 case 32: /* d. disable */
2152 msgCode = TPM_PPI_OP_DISABLE;
2153 break;
2154 case 30: /* a. activate */
2155 msgCode = TPM_PPI_OP_ACTIVATE;
2156 break;
2157 case 47: /* v. deactivate */
2158 msgCode = TPM_PPI_OP_DEACTIVATE;
2159 break;
2160 case 46: /* c. clear owner */
2161 msgCode = TPM_PPI_OP_CLEAR;
2162 break;
2163 case 25: /* p. prevent ownerinstall */
2164 msgCode = TPM_PPI_OP_SET_OWNERINSTALL_FALSE;
2165 break;
2166 case 31: /* s. allow ownerinstall */
2167 msgCode = TPM_PPI_OP_SET_OWNERINSTALL_TRUE;
2168 break;
2169 default:
2170 continue;
2171 }
2172
2173 /*
2174 * Using the next_scancodes array, check whether the
2175 * pressed key is currently a valid option.
2176 */
2177 for (i = 0; i < sizeof(next_scancodes); i++) {
2178 if (next_scancodes[i] == 0)
2179 break;
2180
2181 if (next_scancodes[i] == scancode) {
2182 tpm12_process_cfg(msgCode, 1);
2183 waitkey = 0;
2184 break;
2185 }
2186 }
2187 }
2188 }
2189 }
2190
2191 static int
tpm20_menu_change_active_pcrbanks(void)2192 tpm20_menu_change_active_pcrbanks(void)
2193 {
2194 u8 active_banks, suppt_banks;
2195
2196 tpm20_get_suppt_pcrbanks(&suppt_banks, &active_banks);
2197
2198 u8 activate_banks = active_banks;
2199
2200 while (1) {
2201 u8 hashalg_flag = TPM2_ALG_SHA1_FLAG;
2202 u8 i = 0;
2203
2204 printf("\nToggle active PCR banks by pressing number key\n\n");
2205
2206 while (hashalg_flag) {
2207 u8 flag = hashalg_flag & suppt_banks;
2208 const char *hashname = tpm20_hashalg_flag_to_name(flag);
2209
2210 i++;
2211 if (hashname) {
2212 printf(" %d: %s", i, hashname);
2213 if (activate_banks & hashalg_flag)
2214 printf(" (enabled)");
2215 printf("\n");
2216 }
2217
2218 hashalg_flag <<= 1;
2219 }
2220 printf("\n"
2221 "ESC: return to previous menu without changes\n");
2222 if (activate_banks)
2223 printf("A : activate selection\n");
2224
2225 u8 flagnum;
2226 int show = 0;
2227 while (!show) {
2228 int scancode = get_keystroke(1000);
2229
2230 switch (scancode) {
2231 case ~0:
2232 continue;
2233 case 1: /* ESC */
2234 printf("\n");
2235 return -1;
2236 case 2 ... 6: /* keys 1 .. 5 */
2237 flagnum = scancode - 1;
2238 if (flagnum > i)
2239 continue;
2240 if (suppt_banks & (1 << (flagnum - 1))) {
2241 activate_banks ^= 1 << (flagnum - 1);
2242 show = 1;
2243 }
2244 break;
2245 case 30: /* a */
2246 if (activate_banks)
2247 tpm20_activate_pcrbanks(activate_banks);
2248 }
2249 }
2250 }
2251 }
2252
2253 static void
tpm20_menu(void)2254 tpm20_menu(void)
2255 {
2256 int scan_code;
2257 tpm_ppi_code msgCode;
2258
2259 for (;;) {
2260 printf("1. Clear TPM\n");
2261 printf("2. Change active PCR banks\n");
2262
2263 printf("\nIf no change is desired or if this menu was reached by "
2264 "mistake, press ESC to\n"
2265 "reboot the machine.\n");
2266
2267 msgCode = TPM_PPI_OP_NOOP;
2268
2269 while ((scan_code = get_keystroke(1000)) == ~0)
2270 ;
2271
2272 switch (scan_code) {
2273 case 1:
2274 // ESC
2275 reset();
2276 break;
2277 case 2:
2278 msgCode = TPM_PPI_OP_CLEAR;
2279 break;
2280 case 3:
2281 tpm20_menu_change_active_pcrbanks();
2282 continue;
2283 default:
2284 continue;
2285 }
2286
2287 tpm20_process_cfg(msgCode, 0);
2288 }
2289 }
2290
2291 void
tpm_menu(void)2292 tpm_menu(void)
2293 {
2294 if (!CONFIG_TCGBIOS)
2295 return;
2296
2297 while (get_keystroke(0) >= 0)
2298 ;
2299 wait_threads();
2300
2301 switch (TPM_version) {
2302 case TPM_VERSION_1_2:
2303 tpm12_menu();
2304 break;
2305 case TPM_VERSION_2:
2306 tpm20_menu();
2307 break;
2308 }
2309 }
2310
2311 int
tpm_can_show_menu(void)2312 tpm_can_show_menu(void)
2313 {
2314 switch (TPM_version) {
2315 case TPM_VERSION_1_2:
2316 return tpm_is_working() && TPM_has_physical_presence;
2317 case TPM_VERSION_2:
2318 return tpm_is_working();
2319 }
2320 return 0;
2321 }
2322