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                                             &regs->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