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