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