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