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