1 /*
2  *  Implementation of the TCG BIOS extension according to the specification
3  *  described in
4  *  https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Copyright (C) IBM Corporation, 2006
20  *
21  * Author: Stefan Berger <stefanb@us.ibm.com>
22  */
23 #include "rombios_compat.h"
24 #include "tpm_drivers.h"
25 
26 #include "util.h"
27 #include "tcgbios.h"
28 
29 /* local structure and variables */
30 struct ptti_cust {
31 	uint16_t    ipblength;
32 	uint16_t    reserved;
33 	uint16_t    opblength;
34 	uint16_t    reserved2;
35 	uint8_t     tpmoperandin[18];
36 } __attribute__((packed));
37 
38 struct ptti_cust CMD_TPM_Startup_0x01_IPB = {
39     0x8+0xc, 0x00, 4+10, 0x00,
40     { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x99, 0x00, 0x01 },
41 };
42 
43 struct ptti_cust CMD_TSC_PhysicalPresence_0x20_IPB = {
44     0x8+0xc, 0x00, 4+10, 0x00,
45     { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x20 },
46 };
47 
48 struct ptti_cust CMD_TSC_PhysicalPresence_0x08_IPB = {
49     0x8+0xc, 0x00, 4+10, 0x00,
50     { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x08 },
51 };
52 
53 struct ptti_cust CMD_TSC_PhysicalPresence_0x100_IPB = {
54     0x8+0xc, 0x00, 4+10, 0x00,
55     { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x01, 0x00 },
56 };
57 
58 struct ptti_cust CMD_TSC_PhysicalPresence_0x10_IPB = {
59     0x8+0xc, 0x00, 4+10, 0x00,
60     { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x10 },
61 };
62 
63 struct ptti_cust CMD_TPM_PhysicalEnable_IPB = {
64     0x8+0xa, 0x00, 4+10, 0x00,
65     { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x6f },
66 };
67 
68 struct ptti_cust CMD_TPM_PhysicalSetDeactivated_0x00_IPB = {
69     0x8+0xb, 0x00, 4+10, 0x00,
70     { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x72, 0x00 }
71 };
72 struct ptti_cust CMD_TPM_SHA1Start_IPB = {
73     0x8+0xa, 0x00, 4+10, 0x00,
74     { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa0 },
75 };
76 
77 struct ptti_cust CMD_TPM_GetCap_Version_IPB = {
78     0x8+0x12, 0x00, 4+18, 0x00,
79     {0x00, 0xc1, 0x00, 0x00, 0x00, 0x12,
80      0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00 },
81 };
82 
83 struct ptti_cust *TCG_CommandList[] = {
84 	&CMD_TPM_Startup_0x01_IPB,
85 	&CMD_TSC_PhysicalPresence_0x20_IPB,
86 	&CMD_TSC_PhysicalPresence_0x08_IPB,
87 	&CMD_TSC_PhysicalPresence_0x100_IPB,
88 	&CMD_TSC_PhysicalPresence_0x10_IPB,
89 	&CMD_TPM_PhysicalEnable_IPB,
90 	&CMD_TPM_PhysicalSetDeactivated_0x00_IPB,
91 	&CMD_TPM_SHA1Start_IPB,
92 };
93 
94 /* local function prototypes */
95 static void sha1(const unsigned char *data, uint32_t length,
96                  unsigned char *hash);
97 static uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx);
98 static uint32_t HashAll32(struct hai *hai, unsigned char *hash,
99                           uint32_t magic, uint32_t ecx, uint32_t edx);
100 static uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s,
101                                      struct hleeo *hleeo,
102                                      uint32_t magic, uint32_t ecx,
103                                      uint32_t edx);
104 static uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
105                                uint32_t ebx, uint32_t ecx, uint32_t edx);
106 static uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto,
107                                    uint32_t magic, uint32_t ecx, uint32_t edx);
108 static uint32_t MA_Transmit(unsigned char *cmdbuffer,
109                             unsigned char *respbuffer,
110                             uint32_t respbufferlen);
111 
112 static unsigned char *tcpa_get_lasa_last_ptr(void);
113 static unsigned char *tcpa_get_lasa_base_ptr(void);
114 static void tcpa_reset_acpi_log(void);
115 static uint32_t tcpa_get_laml(void);
116 
117 
118 extern struct tpm_driver tpm_drivers[];
119 
120 /* utility functions */
121 
bswap(uint32_t a)122 static inline uint32_t bswap(uint32_t a)
123 {
124 	return ( ( a >> 24 ) & 0x000000ff) |
125 	       ( ( a >> 8  ) & 0x0000ff00) |
126 	       ( ( a << 8  ) & 0x00ff0000) |
127 	       ( ( a << 24 ) & 0xff000000);
128 }
129 
130 /********************************************************
131   Extensions for TCG-enabled BIOS
132  *******************************************************/
133 
134 typedef struct {
135 	struct acpi_20_tcpa_clisrv *tcpa_ptr;
136 	unsigned char       *lasa_last_ptr;
137 	uint16_t            entry_count;
138 	uint16_t            flags;
139 } tcpa_acpi_t;
140 
141 static tcpa_acpi_t tcpa_acpi;
142 
143 
144 /* low level driver implementation */
145 static int tpm_driver_to_use = TPM_INVALID_DRIVER;
146 
147 static
MA_IsTPMPresent(void)148 uint32_t MA_IsTPMPresent(void)
149 {
150 	uint32_t rc = 0;
151 	unsigned int i;
152 	for (i = 0; i < TPM_NUM_DRIVERS; i++) {
153 		struct tpm_driver *td = &tpm_drivers[i];
154 		if (td->probe(td->baseaddr) != 0) {
155 			tpm_driver_to_use = i;
156 			rc = 1;
157 			break;
158 		}
159 	}
160 	return rc;
161 }
162 
163 static
MA_InitTPM(uint16_t startupcode)164 uint32_t MA_InitTPM(uint16_t startupcode)
165 {
166 	uint32_t rc = 0;
167 	/* low-level initialize the TPM */
168 	unsigned char command[sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin)];
169 	unsigned char response[10];
170 	uint32_t response_size = sizeof(response);
171 
172 	memcpy(command,
173 	       CMD_TPM_Startup_0x01_IPB.tpmoperandin,
174 	       sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin));
175 	command[10] = (startupcode >> 8) & 0xff;
176 	command[11] = (startupcode >> 0) & 0xff;
177 	rc = MA_Transmit(command, response, response_size);
178 
179 	return rc;
180 }
181 
182 static
MA_Transmit(unsigned char * cmdbuffer,unsigned char * respbuffer,uint32_t respbufferlen)183 uint32_t MA_Transmit(unsigned char *cmdbuffer, unsigned char *respbuffer,
184                      uint32_t respbufferlen)
185 {
186 	uint32_t rc = 0;
187 	uint32_t irc;
188 	struct tpm_driver *td;
189 
190 	if (tpm_driver_to_use == TPM_INVALID_DRIVER)
191 		return TCG_FATAL_COM_ERROR;
192 
193 	td = &tpm_drivers[tpm_driver_to_use];
194 
195 	if (rc == 0) {
196 		irc = td->activate(td->baseaddr);
197 		if (irc == 0) {
198 			/* tpm could not be activated */
199 			rc = TCG_FATAL_COM_ERROR;
200 		}
201 	}
202 
203 	if (rc == 0) {
204 		uint32_t *tmp = (uint32_t *)&cmdbuffer[2];
205 		uint32_t len = bswap(*tmp);
206 		irc = td->senddata(td->baseaddr,
207 		                   cmdbuffer,
208 		                   len);
209 		if (irc != 0) {
210 			rc = TCG_FATAL_COM_ERROR;
211 		}
212 	}
213 
214 	if (rc == 0) {
215 		irc = td->waitdatavalid(td->baseaddr);
216 		if (irc != 0) {
217 			rc = TCG_FATAL_COM_ERROR;
218 		}
219 	}
220 
221 	if (rc == 0) {
222 		irc = td->waitrespready(td->baseaddr, 2000);
223 		if (irc != 0) {
224 			rc = TCG_FATAL_COM_ERROR;
225 		}
226 	}
227 
228 	if (rc == 0) {
229 		irc = td->readresp(td->baseaddr,
230 		                   respbuffer,
231 		                   respbufferlen);
232 		if (irc != 0) {
233 			rc = TCG_FATAL_COM_ERROR;
234 		}
235 	}
236 
237 	if (rc == 0) {
238 		irc = td->ready(td->baseaddr);
239 	}
240 
241 	return rc;
242 }
243 
244 
245 static
acpi_validate_entry(struct acpi_header * hdr)246 uint8_t acpi_validate_entry(struct acpi_header *hdr)
247 {
248 	uint8_t sum = 0;
249 	unsigned int length = hdr->length;
250 	unsigned int ctr;
251 	unsigned char *addr = (unsigned char *)hdr;
252 
253 	for (ctr = 0; ctr < length; ctr++)
254 		sum += addr[ctr];
255 
256 	return sum;
257 }
258 
259 
260 /*
261    initialize the TCPA ACPI subsystem; find the ACPI tables and determine
262    where the TCPA table is.
263  */
tcpa_acpi_init(void)264 void tcpa_acpi_init(void)
265 {
266 	struct acpi_20_rsdt *rsdt;
267 	struct acpi_20_tcpa_clisrv *tcpa = (void *)0;
268 	struct acpi_20_rsdp *rsdp;
269 	uint32_t length;
270 	uint16_t off;
271 	int found = 0;
272 
273 	if (MA_IsTPMPresent() == 0)
274 		return;
275 
276 	rsdp = find_rsdp();
277 	if (rsdp) {
278 		uint32_t ctr = 0;
279 		/* get RSDT from RSDP */
280 		rsdt   = (struct acpi_20_rsdt *)rsdp->rsdt_address;
281 		length = rsdt->header.length;
282 		off = 36;
283 		while ((off + 3) < length) {
284 			/* try all pointers to structures */
285 			tcpa = (struct acpi_20_tcpa_clisrv *)rsdt->entry[ctr];
286 			/* valid TCPA ACPI table ? */
287 			if (ACPI_2_0_TCPA_SIGNATURE == tcpa->header.signature
288 			    && acpi_validate_entry(&tcpa->header) == 0) {
289 				found = 1;
290 				break;
291 			}
292 			off += 4;
293 			ctr++;
294 		}
295 	}
296 
297 	if (found == 0) {
298 		printf("TCPA ACPI was NOT found!\n");
299 		tcpa = 0;
300 	}
301 
302 	tcpa_acpi.tcpa_ptr = tcpa;
303 	tcpa_acpi.lasa_last_ptr = 0;
304 	tcpa_acpi.entry_count = 0;
305 	tcpa_acpi.flags = 0;
306 	tcpa_reset_acpi_log();
307 }
308 
309 /* clear the ACPI log */
tcpa_reset_acpi_log(void)310 static void tcpa_reset_acpi_log(void)
311 {
312 	unsigned char *lasa = tcpa_get_lasa_base_ptr();
313 	if (lasa)
314 		memset(lasa, 0x0, tcpa_get_laml());
315 }
316 
317 
318 /*
319  * Extend the ACPI log with the given entry by copying the
320  * entry data into the log.
321  * Input
322  *  Pointer to the structure to be copied into the log
323  *
324  * Output:
325  *  lower 16 bits of return code contain entry number
326  *  if entry number is '0', then upper 16 bits contain error code.
327  */
tcpa_extend_acpi_log(uint32_t entry_ptr)328 uint32_t tcpa_extend_acpi_log(uint32_t entry_ptr)
329 {
330 	uint32_t res = 0;
331 	unsigned char *lasa_last = tcpa_get_lasa_last_ptr();
332 	unsigned char *lasa_base = tcpa_get_lasa_base_ptr();
333 	uint32_t size = 0;
334 	uint16_t entry_count = tcpa_acpi.entry_count;
335 	struct pcpes *pcpes = (struct pcpes *)entry_ptr;
336 
337 	if (lasa_last == 0) {
338 		lasa_last = lasa_base;
339 	} else {
340 		struct pcpes *pcpes = (struct pcpes *)lasa_last;
341 		/* skip the last entry in the log */
342 		size = pcpes->eventdatasize;
343 		size += 32;
344 		lasa_last += size;
345 	}
346 
347 	if (lasa_last == 0) {
348 		res = ((uint32_t)TCG_PC_LOGOVERFLOW << 16);
349 	}
350 
351 	if (res == 0) {
352 		uint32_t laml = tcpa_get_laml();
353 		size = pcpes->eventdatasize;
354 		size += 32;
355 		if ((lasa_last + size - lasa_base) > laml) {
356 			res = (TCG_PC_LOGOVERFLOW << 16);
357 		}
358 	}
359 
360 	if (res == 0) {
361 		/* copy the log entry into the ACPI log */
362 		memcpy((char *)lasa_last, (char *)entry_ptr, size);
363 		/*
364 		 * update the pointers and entry counter that were modified
365 		 * due to the new entry in the log
366 		 */
367 		tcpa_acpi.lasa_last_ptr = lasa_last;
368 		entry_count++;
369 		tcpa_acpi.entry_count = entry_count;
370 
371 		res = entry_count;
372 	}
373 	return res;
374 }
375 
376 static
tcpa_get_lasa_last_ptr(void)377 unsigned char *tcpa_get_lasa_last_ptr(void)
378 {
379 	return tcpa_acpi.lasa_last_ptr;
380 }
381 
382 static
tcpa_get_lasa_base_ptr(void)383 unsigned char *tcpa_get_lasa_base_ptr(void)
384 {
385 	unsigned char *lasa = 0;
386 	struct acpi_20_tcpa_clisrv *tcpa = tcpa_acpi.tcpa_ptr;
387 	if (tcpa != 0) {
388 		uint32_t class = tcpa->platform_class;
389 		if (class == TCPA_ACPI_CLASS_CLIENT) {
390 			/* client type */
391 			lasa = (unsigned char *)(long)tcpa->u.client.lasa;
392 		} else if (class == TCPA_ACPI_CLASS_SERVER) {
393 			/* server type */
394 			lasa = (unsigned char *)(long)tcpa->u.server.lasa;
395 		}
396 	}
397 	return lasa;
398 }
399 
400 static
tcpa_get_laml(void)401 uint32_t tcpa_get_laml(void)
402 {
403 	uint32_t laml = 0;
404 	struct acpi_20_tcpa_clisrv *tcpa = tcpa_acpi.tcpa_ptr;
405 	if (tcpa != 0) {
406 		uint32_t class = tcpa->platform_class;
407 		if (class == TCPA_ACPI_CLASS_CLIENT) {
408 			/* client type */
409 			laml = tcpa->u.client.laml;
410 		} else if (class == TCPA_ACPI_CLASS_SERVER) {
411 			laml = tcpa->u.server.laml;
412 		}
413 	}
414 	return laml;
415 }
416 
417 
418 
419 /*
420  * Add a measurement to the log; the data at data_seg:data/length are
421  * appended to the TCG_PCClientPCREventStruct
422  *
423  * Input parameters:
424  *  pcrIndex   : which PCR to extend
425  *  event_type : type of event; specs 10.4.1
426  *  event_id   : (unused)
427  *  data       : pointer to the data (i.e., string) to be added to the log
428  *  length     : length of the data
429  */
430 static uint32_t
tcpa_add_measurement_to_log(uint32_t pcrIndex,uint32_t event_type,uint32_t event_id,const char * data_ptr,uint32_t length)431 tcpa_add_measurement_to_log(uint32_t pcrIndex,
432                             uint32_t event_type,
433                             uint32_t event_id,
434                             const char *data_ptr,
435                             uint32_t length)
436 {
437 	uint32_t rc = 0;
438 	struct hleei_short hleei;
439 	struct hleeo hleeo;
440 	uint8_t _pcpes[32+400];
441 	struct pcpes *pcpes = (struct pcpes *)_pcpes;
442 	uint8_t *data = (uint8_t *)data_ptr;
443 
444 	if (length < sizeof(_pcpes)-32) {
445 		memset(pcpes, 0x0, 32);
446 		pcpes->pcrindex   = pcrIndex;
447 		pcpes->eventtype = event_type;
448 		pcpes->eventdatasize = length;
449 		memcpy(&_pcpes[32], data, length);
450 
451 		hleei.ipblength = 0x18;
452 		hleei.reserved  = 0x0;
453 		hleei.hashdataptr = (uint32_t)&_pcpes[32];
454 		hleei.hashdatalen = length;
455 		hleei.pcrindex    = pcrIndex;
456 		hleei.logdataptr  = (uint32_t)_pcpes;
457 		hleei.logdatalen  = length + 32;
458 		rc = HashLogExtendEvent32(&hleei,
459 		                          &hleeo,
460 			                  TCG_MAGIC,
461 		                          0x0,
462 		                          0x0);
463 	} else {
464 		rc = (TCG_PC_TPMERROR |
465 		      ((uint32_t)TCG_GENERAL_ERROR << 16));
466 	}
467 
468 	return rc;
469 }
470 
471 static
tcpa_add_pcpes_to_log(struct pcpes * pcpes)472 uint16_t tcpa_add_pcpes_to_log(struct pcpes *pcpes)
473 {
474 	uint32_t rc = 0;
475 	struct hleei_short hleei;
476 	struct hleeo hleeo;
477 
478 	hleei.ipblength = 0x18;
479 	hleei.reserved  = 0x0;
480 	hleei.hashdataptr = 0;
481 	hleei.hashdatalen = 0;
482 	hleei.pcrindex    = pcpes->pcrindex;
483 	hleei.logdataptr  = (uint32_t)pcpes;
484 	hleei.logdatalen  = sizeof(pcpes);
485 
486 	rc = HashLogExtendEvent32(&hleei,
487 	                          &hleeo,
488 		                  TCG_MAGIC,
489 	                          0x0,
490 	                          0x0);
491 
492 	return rc;
493 }
494 
495 
496 /*
497  * Add a measurement to the log; further description of the data
498  * that are to be hashed are NOT appended to the TCG_PCClientPCREventStruc.
499  * Input parameters:
500  *  pcrIndex   : PCR to extend
501  *  event_type : type of event; specs 10.4.1
502  *  ptr        : 32 bit pointer to the data to be hashed
503  *  length     : length of the data to be hashed
504  *
505  * Returns lower 16 bit of return code of TCG_HashLogExtendEvent. '0' means
506  * success, otherwise an error is indicated.
507  */
508 static
tcpa_add_measurement_to_log_simple(uint32_t pcrIndex,uint16_t event_type,uint8_t * ptr,uint32_t length)509 uint16_t tcpa_add_measurement_to_log_simple(uint32_t pcrIndex,
510                                             uint16_t event_type,
511                                             uint8_t *ptr, uint32_t length)
512 {
513 	uint32_t rc = 0;
514 	struct hleei_short hleei;
515 	struct hleeo hleeo;
516 	struct pcpes pcpes;
517 
518 	memset(&pcpes, 0x0, sizeof(pcpes));
519 	pcpes.pcrindex = pcrIndex;
520 	pcpes.eventtype = event_type;
521 	/* specs: 10.4.1, EV_IPL eventfield should not contain the code.*/
522 	pcpes.eventdatasize = 0;
523 
524 	hleei.ipblength = 0x18;
525 	hleei.reserved  = 0x0;
526 	hleei.hashdataptr = (uint32_t)ptr;
527 	hleei.hashdatalen = length;
528 	hleei.pcrindex = pcrIndex;
529 	hleei.logdataptr = (uint32_t)&pcpes;
530 	hleei.logdatalen = 32;
531 
532 	rc = HashLogExtendEvent32(&hleei,
533 	                          &hleeo,
534 	                          TCG_MAGIC,
535 	                          0x0,
536 	                          0x0);
537 	return rc;
538 }
539 
540 /* table of event types according to 10.4.1 / table 11 */
541 static const char ev_action[][23] = {
542   /*  0 */ "Calling INT 19h",
543            "Returned INT 19h",
544            "Returned via INT 18h",
545            "",
546            "",
547   /*  5 */ "",
548            "",
549            "",
550            "",
551            "",
552   /* 10 */ "",
553            "",
554            "",
555            "",
556            "Start Option ROM Scan"
557 };
558 
559 static char evt_separator[] = {0xff,0xff,0xff,0xff};
560 static char wake_event_1[]    = "Wake Event 1";
561 
562 /*
563  * Add a measurement to the list of measurements
564  * pcrIndex   : PCR to be extended
565  * event_type : type of event; specs 10.4.1
566  * data       : additional parameter; used as parameter for 10.4.3
567  *              'action index'
568  */
tcpa_add_measurement(uint32_t pcrIndex,uint16_t event_type,uint32_t data)569 static void tcpa_add_measurement(uint32_t pcrIndex,
570                           uint16_t event_type,
571                           uint32_t data)
572 {
573 	const char *string;
574 
575 	switch (event_type) {
576 	case EV_SEPARATOR:
577 		tcpa_add_measurement_to_log_simple(pcrIndex,
578 		                            event_type,
579 		                            (uint8_t *)evt_separator,
580 		                            4);
581 	break;
582 	case EV_ACTION:
583 		string = ev_action[data /* event_id */];
584 		tcpa_add_measurement_to_log(pcrIndex,
585 		                            event_type,
586 		                            data,
587 		                            string,
588 		                            strlen(string));
589 
590 	break;
591 	}
592 }
593 
594 
595 /*
596  * Add measurement to log about call of int 19h
597  */
tcpa_calling_int19h()598 void tcpa_calling_int19h()
599 {
600 	tcpa_add_measurement(4, EV_ACTION, 0);
601 }
602 
603 /*
604  * Add measurement to log about retuning from int 19h
605  */
tcpa_returned_int19h()606 void tcpa_returned_int19h()
607 {
608 	tcpa_add_measurement(4, EV_ACTION, 1);
609 }
610 
611 /*
612  * Add event separators for PCRs 0 to 7; specs 8.2.3
613  */
tcpa_add_event_separators()614 void tcpa_add_event_separators()
615 {
616 	uint32_t pcrIndex = 0;
617 	while (pcrIndex <= 7) {
618 		tcpa_add_measurement(pcrIndex, EV_SEPARATOR, 0);
619 		pcrIndex ++;
620 	}
621 }
622 
623 
624 /*
625  * Add a wake event to the log
626  */
tcpa_wake_event()627 void tcpa_wake_event()
628 {
629 	tcpa_add_measurement_to_log(6,
630 	                            EV_ACTION,
631 	                            10,
632 	                            wake_event_1,
633 	                            strlen(wake_event_1));
634 }
635 
636 /*
637  * Add a measurement regarding the boot device (CDRom, Floppy, HDD) to
638  * the list of measurements.
639  */
tcpa_add_bootdevice(uint32_t bootcd,uint32_t bootdrv)640 void tcpa_add_bootdevice(uint32_t bootcd, uint32_t bootdrv)
641 {
642 	char *string;
643 	if (bootcd == 0) {
644 		if (bootdrv == 0) {
645 			string = "Booting BCV device 00h (Floppy)";
646 		} else if (bootdrv == 0x80) {
647 			string = "Booting BCV device 80h (HDD)";
648 		} else {
649 			string = "Booting unknown device";
650 		}
651 	} else {
652 		string = "Booting from CD ROM device";
653 	}
654 	tcpa_add_measurement_to_log(4, 5, 0,
655 	                            string, strlen(string));
656 }
657 
658 /*
659  * Add measurement to the log about option rom scan
660  * 10.4.3 : action 14
661  */
tcpa_start_option_rom_scan()662 void tcpa_start_option_rom_scan()
663 {
664 	tcpa_add_measurement(2, EV_ACTION, 14);
665 }
666 
667 
668 /*
669  * Add measurement to the log about an option rom
670  */
tcpa_option_rom(uint32_t seg)671 void tcpa_option_rom(uint32_t seg)
672 {
673 	uint32_t len = read_byte(seg, 2) << 9;
674 	uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,0);
675 	char append[32]; /* TCG_PCClientTaggedEventStruct and
676 	                     OptionROMExecuteStructure; specs 10.4.2.1 */
677 	struct hai hai;   /* HashAll Input Block; specs 12.10 */
678 
679 	memset(append, 0x0, sizeof(append));
680 
681 	append[0] = 7; /* Option ROM Execute */
682 	append[4] = 24;/* size of OptionROMExecute Structure */
683 	/* leave the rest to '0' */
684 
685 	/* 12.10 table 21 */
686 	hai.ipblength   = 0x10;
687 	hai.reserved    = 0;
688 	hai.hashdataptr = (uint32_t)addr;
689 	hai.hashdatalen = len;
690 	hai.algorithmid = TPM_ALG_SHA;
691 
692 	HashAll32(&hai,
693 	          (unsigned char *)append+12,
694 	          TCG_MAGIC,
695 	          0,
696 	          0);
697 
698 	tcpa_add_measurement_to_log(2,
699 	                            EV_EVENT_TAG,
700 	                            0,
701 	                            append,
702 	                            32);
703 }
704 
705 /*
706  * Add a measurement to the log in support of 8.2.5.3
707  * Creates two log entries
708  *
709  * Input parameter:
710  *  bootcd : 0: MBR of hdd, 1: boot image, 2: boot catalog of El Torito
711  *  seg    : segment where the IPL data are located
712  *  off    : offset where the IPL data are located
713  *  count  : length in bytes
714  */
tcpa_ipl(Bit32u bootcd,Bit32u seg,Bit32u off,Bit32u count)715 void tcpa_ipl(Bit32u bootcd,Bit32u seg,Bit32u off,Bit32u count)
716 {
717 	uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,off);
718 	if (bootcd == 1) {
719 		/* specs: 8.2.5.6 El Torito */
720 		tcpa_add_measurement_to_log_simple(4,
721 						   EV_IPL,
722 						   addr,
723 						   count);
724 	}
725 	else if (bootcd == 2) { /* Boot Catalog */
726 
727 		/* specs: 8.2.5.6 El Torito */
728 		tcpa_add_measurement_to_log_simple(5,
729 						   EV_IPL_PARTITION_DATA,
730 						   addr,
731 						   count);
732 	}
733 	else {
734 		/* specs: 8.2.5.3 */
735 		/* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */
736 		tcpa_add_measurement_to_log_simple(4,
737 						   EV_IPL,
738 						   addr,
739 		                                   0x1b8);
740 
741 
742 		/* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */
743 		tcpa_add_measurement_to_log_simple(5,
744 						   EV_IPL_PARTITION_DATA,
745 						   addr + 0x1b8,
746 						   0x48);
747 	}
748 }
749 
tcpa_measure_post(Bit32u from,Bit32u to)750 void tcpa_measure_post(Bit32u from, Bit32u to)
751 {
752 	struct pcpes pcpes; /* PCClientPCREventStruc */
753 	int len = to - from;
754 	memset(&pcpes, 0x0, sizeof(pcpes));
755 
756 	if (len > 0) {
757 		sha1((unsigned char *)from,
758 		     to-from,
759 		     (unsigned char *)&pcpes.digest);
760 
761 		pcpes.eventtype = EV_POST_CODE;
762 		pcpes.eventdatasize = 0;
763 		pcpes.pcrindex = 0;
764 		tcpa_add_pcpes_to_log(&pcpes);
765 	}
766 }
767 
768 static
SendCommand32(uint32_t idx,struct pttto * pttto,uint32_t size_ptto)769 uint32_t SendCommand32(uint32_t idx, struct pttto *pttto, uint32_t size_ptto)
770 {
771 	uint32_t rc = 0;
772 	struct pttti *pttti = (struct pttti *)TCG_CommandList[idx];
773 	uint8_t _pttto[30];
774 
775 	if (size_ptto > 0 && size_ptto < 14) {
776 		rc = (TCG_PC_TPMERROR |
777 		      ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
778 	}
779 
780 	if (rc == 0) {
781 		if (size_ptto == 0) {
782 			pttto = (struct pttto *)_pttto;
783 			size_ptto = sizeof(_pttto);
784 		}
785 		pttti->opblength = size_ptto;
786 	}
787 
788 	if (rc == 0) {
789 		if (pttti->opblength > size_ptto) {
790 			rc = (TCG_PC_TPMERROR |
791 			      ((uint32_t)TCG_OUTPUT_BUFFER_TOO_SHORT << 16));
792 		}
793 	}
794 
795 	if (rc == 0) {
796 		rc = PassThroughToTPM32(pttti,
797 		                        pttto,
798 		                        TCG_MAGIC,
799 		                        0x0,
800 		                        0x0);
801 	}
802 
803 	return rc;
804 }
805 
806 
tcpa_initialize_tpm(uint32_t physpres)807 uint32_t tcpa_initialize_tpm(uint32_t physpres)
808 {
809 	uint32_t rc = 0;
810 	uint8_t _pttto[40];
811 	struct pttto *pttto = (struct pttto *)_pttto;
812 	uint32_t pttto_size = sizeof(_pttto);
813 
814 	if (rc == 0) {
815 		rc = SendCommand32(IDX_CMD_TPM_Startup_0x01, pttto,
816 		                   pttto_size);
817 	}
818 
819 	if (rc == 0 && physpres != 0) {
820 		rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x20,
821 		                   pttto, pttto_size);
822 	}
823 
824 	if (rc == 0 && physpres != 0) {
825 		rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x08,
826 		                   pttto, pttto_size);
827 	}
828 
829 	if (rc == 0 && physpres != 0) {
830 		rc = SendCommand32(IDX_CMD_TPM_PhysicalEnable,
831 		                   pttto, pttto_size);
832 	}
833 
834 	if (rc == 0 && physpres != 0) {
835 		rc = SendCommand32(IDX_CMD_TPM_PhysicalSetDeactivated_0x00,
836 		                   pttto, pttto_size);
837 	}
838 
839 	if (rc == 0) {
840 		rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x100,
841 		                   pttto, pttto_size);
842 	}
843 
844 	if (rc == 0) {
845 		rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x10,
846 		                   pttto, pttto_size);
847 	}
848 	return rc;
849 }
850 
851 
TCG_IsShutdownPreBootInterface(void)852 static uint16_t TCG_IsShutdownPreBootInterface(void)
853 {
854 	return tcpa_acpi.flags & STATUS_FLAG_SHUTDOWN;
855 }
856 
857 
858 static
_TCG_TPM_Extend(unsigned char * hash,uint32_t pcrindex)859 uint32_t _TCG_TPM_Extend(unsigned char *hash, uint32_t pcrindex)
860 {
861 	uint32_t rc;
862 	uint8_t _pttti[8+34];
863 	uint8_t _pttto[4+30];
864 	struct pttti *pttti = (struct pttti*)&_pttti;
865 	struct pttto *pttto = (struct pttto*)&_pttto;
866 
867 	pttti->ipblength = 8 + 34;
868 	pttti->reserved  = 0;
869 	pttti->opblength = 4 + 30;
870 	pttti->reserved2 = 0;
871 
872 	_pttti[8 + 0] = 0x0;
873 	_pttti[8 + 1] = 0xc1;
874 	*(uint32_t *)&_pttti[8 + 2] = bswap(34);
875 	*(uint32_t *)&_pttti[8 + 6] = bswap(0x14);
876 	*(uint32_t *)&_pttti[8 + 10]= bswap(pcrindex);
877 	memcpy(&_pttti[8+14], hash, 20);
878 
879 	rc = PassThroughToTPM32(pttti,
880 	                        pttto,
881 	                        TCG_MAGIC,
882 	                        0x0,
883 	                        0x0);
884 	/* sanity check of result */
885 	if (_pttto[4] != 0x00 || _pttto[5] != 0xc4) {
886 		rc = (TCG_PC_TPMERROR |
887 		      ((uint32_t)TCG_FATAL_COM_ERROR << 16));
888 	}
889 
890 	if (rc != 0) {
891 		/*
892 		   Invalidate the log since system did not process this
893 		   extend properly.
894 		 */
895 		tcpa_reset_acpi_log();
896 		memset(&tcpa_acpi, 0x0, sizeof(tcpa_acpi));
897 		TCG_ShutdownPreBootInterface(0);
898 	}
899 	return rc;
900 }
901 
902 
903 static
HashLogExtendEvent32(struct hleei_short * hleei_s,struct hleeo * hleeo,uint32_t magic,uint32_t ecx,uint32_t edx)904 uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s, struct hleeo *hleeo,
905                               uint32_t magic, uint32_t ecx, uint32_t edx)
906 {
907 	uint32_t rc = 0;
908 	uint16_t size;
909 	struct hlei hlei ; /* HashLogEventInput block */
910 	struct hleo hleo;  /* HashLogEventOutput block */
911 	struct hleei_long *hleei_l = (struct hleei_long *)hleei_s;
912 	int sh = 0;
913 	uint32_t logdataptr;
914 
915 	if (TCG_IsShutdownPreBootInterface() != 0) {
916 		rc = (TCG_PC_TPMERROR |
917 		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
918 	}
919 
920 	if (rc == 0) {
921 		/* short or long version? */
922 		size = hleei_s->ipblength;
923 		if (size == 0x18) {
924 			/* short */
925 			sh = 1;
926 		} else if (size == 0x1c) {
927 			/* long */
928 			sh = 0;
929 		} else {
930 			/* bad input block */
931 			rc = TCG_PC_TPMERROR |
932 			     ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
933 		}
934 	}
935 
936 	if (rc == 0) {
937 		uint32_t hashdataptr;
938 		uint32_t hashdatalen;
939 		uint32_t pcrindex;
940 		uint32_t logeventtype;
941 		uint32_t logdatalen;
942 		uint32_t eventnumber;
943 		uint8_t hash[20];
944 		struct pcpes *pcpes;
945 
946 		hashdataptr = hleei_s->hashdataptr;
947 		hashdatalen = hleei_s->hashdatalen;
948 		pcrindex    = hleei_s->pcrindex;
949 		if (sh) {
950 			logdataptr = hleei_s->logdataptr;
951 			logdatalen = hleei_s->logdatalen;
952 		} else {
953 			logdataptr = hleei_l->logdataptr;
954 			logdatalen = hleei_l->logdatalen;
955 		}
956 
957 		pcpes = (struct pcpes *)logdataptr;
958 		logeventtype = pcpes->eventtype;
959 
960 		/* fill out HashLogEventInput block 'hlie' */
961 		hlei.ipblength = 0x1c;
962 		hlei.reserved = 0;
963 		hlei.hashdataptr = hashdataptr;
964 		hlei.hashdatalen = hashdatalen;
965 		hlei.pcrindex    = pcrindex;
966 		hlei.logeventtype= logeventtype;
967 		hlei.logdataptr  = logdataptr;
968 		hlei.logdatalen  = logdatalen;
969 
970 		rc = HashLogEvent32(&hlei,
971 		                    &hleo,
972 		                    TCG_MAGIC,
973 		                    0x0,
974 		                    0x0);
975 		eventnumber = hleo.eventnumber;
976 
977 		hleeo->opblength = 8 + 20;
978 		hleeo->reserved  = 0;
979 		hleeo->eventnumber = eventnumber;
980 
981 		memcpy(hash, (unsigned char *)logdataptr + 0x8, 20);
982 		_TCG_TPM_Extend(hash, pcrindex);
983 	}
984 
985 	if (rc != 0) {
986 		hleeo->opblength = 4;
987 		hleeo->reserved  = 0;
988 	}
989 	return rc;
990 
991 }
992 
993 
994 static
PassThroughToTPM32(struct pttti * pttti,struct pttto * pttto,uint32_t magic,uint32_t ecx,uint32_t edx)995 uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto,
996                             uint32_t magic, uint32_t ecx, uint32_t edx)
997 {
998 	uint32_t rc = 0;
999 	uint8_t *cmd32;
1000 	uint32_t resbuflen = 0;
1001 
1002 	if (TCG_IsShutdownPreBootInterface() != 0) {
1003 		rc = (TCG_PC_TPMERROR |
1004 		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1005 	}
1006 
1007 	if (rc == 0) {
1008 		if (pttti->ipblength < 0x8 + 10) {
1009 			rc = TCG_PC_TPMERROR |
1010 			     ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
1011 		}
1012 	}
1013 
1014 	if (rc == 0) {
1015 		if (pttti->opblength < 0x4) {
1016 			rc = TCG_PC_TPMERROR |
1017 			     ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
1018 		}
1019 	}
1020 
1021 	if (rc == 0) {
1022 		uint8_t *resbuf32;
1023 
1024 		cmd32 = &pttti->tpmoperandin[0];
1025 		resbuflen = pttti->opblength - 4;
1026 		resbuf32  = &pttto->tpmoperandout[0];
1027 
1028 		rc = MA_Transmit(cmd32, resbuf32, resbuflen);
1029 	}
1030 
1031 	if (rc == 0) {
1032 		pttto->opblength = resbuflen+4;
1033 		pttto->reserved  = 0;
1034 	}
1035 
1036 	if (rc != 0) {
1037 		pttto->opblength = 0;
1038 		pttto->reserved = 0;
1039 	}
1040 
1041 	return rc;
1042 }
1043 
1044 
1045 static
TCG_ShutdownPreBootInterface(uint32_t ebx)1046 uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx)
1047 {
1048 	uint32_t rc = 0;
1049 	if (TCG_IsShutdownPreBootInterface() == 0) {
1050 		tcpa_acpi.flags |= STATUS_FLAG_SHUTDOWN;
1051 	} else {
1052 		rc = (TCG_PC_TPMERROR |
1053 		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1054 	}
1055 	return rc;
1056 }
1057 
1058 
1059 static
HashLogEvent32(struct hlei * hlei,struct hleo * hleo,uint32_t ebx,uint32_t ecx,uint32_t edx)1060 uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
1061                         uint32_t ebx, uint32_t ecx, uint32_t edx)
1062 {
1063 	uint32_t rc = 0;
1064 	uint16_t size;
1065 	uint32_t logdataptr = 0;
1066 	uint32_t logdatalen;
1067 	uint32_t hashdataptr;
1068 	uint32_t hashdatalen;
1069 
1070 	if (TCG_IsShutdownPreBootInterface() != 0) {
1071 		rc = (TCG_PC_TPMERROR |
1072 		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1073 	}
1074 
1075 	if (rc == 0) {
1076 		size = hlei->ipblength;
1077 		if (size != 0x1c) {
1078 			rc = (TCG_PC_TPMERROR |
1079 			      ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1080 		}
1081 	}
1082 
1083 	if (rc == 0) {
1084 		struct pcpes *pcpes;
1085 		logdataptr = hlei->logdataptr;
1086 		logdatalen = hlei->logdatalen;
1087 		pcpes = (struct pcpes *)logdataptr;
1088 		if (pcpes->pcrindex != hlei->pcrindex) {
1089 			rc = (TCG_PC_TPMERROR |
1090 			      ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1091 		}
1092 	}
1093 
1094 	if (rc == 0) {
1095 		struct pcpes *pcpes= (struct pcpes *)logdataptr;
1096 		if (pcpes->eventtype != hlei->logeventtype) {
1097 			rc = (TCG_PC_TPMERROR |
1098 			      ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1099 		}
1100 	}
1101 
1102 	if (rc == 0) {
1103 		uint32_t entry = 0;
1104 		hashdataptr = hlei->hashdataptr;
1105 		hashdatalen = hlei->hashdatalen;
1106 
1107 		if ((hashdataptr != 0) | (hashdatalen != 0)) {
1108 			uint8_t hash[20];
1109 			struct hai hai; /* HashAll Input Block */
1110 			hai.ipblength = 0x10;
1111 			hai.reserved  = 0x0;
1112 			hai.hashdataptr = hashdataptr;
1113 			hai.hashdatalen = hashdatalen;
1114 			hai.algorithmid = TPM_ALG_SHA;
1115 			rc = HashAll32(&hai,
1116 				       hash,
1117 			               TCG_MAGIC,
1118 			               0x0,
1119 			               0x0);
1120 
1121 			if (rc == 0) {
1122 				/* hashing was done ok */
1123 				memcpy((unsigned char *)logdataptr + 8,
1124 				       hash,
1125 				       20);
1126 			}
1127 		}
1128 
1129 		if (rc == 0) {
1130 			/* extend the log with this event */
1131 			entry = tcpa_extend_acpi_log(logdataptr);
1132 			if ((uint16_t)entry == 0) {
1133 				/* upper 16 bits hold error code */
1134 				rc = (entry >> 16);
1135 			}
1136 		}
1137 
1138 		if (rc == 0) {
1139 			/* updating the log was fine */
1140 			hleo->opblength = 8;
1141 			hleo->reserved  = 0;
1142 			hleo->eventnumber = entry;
1143 		}
1144 	}
1145 
1146 	if (rc != 0) {
1147 		hleo->opblength = 2;
1148 		hleo->reserved = 0;
1149 	}
1150 
1151 	return rc;
1152 }
1153 
1154 static
HashAll32(struct hai * hai,unsigned char * hash,uint32_t magic,uint32_t ecx,uint32_t edx)1155 uint32_t HashAll32(struct hai *hai, unsigned char *hash,
1156                    uint32_t magic, uint32_t ecx, uint32_t edx)
1157 {
1158 	uint32_t rc = 0;
1159 
1160 	if (TCG_IsShutdownPreBootInterface() != 0) {
1161 		rc = (TCG_PC_TPMERROR |
1162 		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1163 	}
1164 
1165 	if (rc == 0) {
1166 		if (hai->ipblength != 0x10) {
1167 			rc = (TCG_PC_TPMERROR |
1168 			      ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1169 		}
1170 	}
1171 
1172 	if (rc == 0) {
1173 		if (hai->algorithmid != TPM_ALG_SHA) {
1174 			rc = (TCG_PC_TPMERROR |
1175 			     ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1176 		}
1177 	}
1178 
1179 	if (rc == 0) {
1180 		uint8_t *hashdataptr32;
1181 		uint32_t hashdatalen32;
1182 
1183 		hashdataptr32 = (uint8_t *)hai->hashdataptr;
1184 		hashdatalen32 = hai->hashdatalen;
1185 
1186 		sha1(hashdataptr32,
1187 		     hashdatalen32,
1188 		     hash);
1189 	}
1190 
1191 	return rc;
1192 }
1193 
1194 
1195 static
TSS32(struct ti * ti,struct to * to,uint32_t ebx,uint32_t ecx,uint32_t edx)1196 uint32_t TSS32(struct ti *ti, struct to *to,
1197                uint32_t ebx, uint32_t ecx, uint32_t edx)
1198 {
1199 	uint32_t rc = 0;
1200 	if (TCG_IsShutdownPreBootInterface() == 0) {
1201 		rc = TCG_PC_UNSUPPORTED;
1202 	} else {
1203 		rc = (TCG_PC_TPMERROR |
1204 		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1205 	}
1206 
1207 	if (rc != 0) {
1208 		to->opblength = 4;
1209 		to->reserved  = 0;
1210 	}
1211 
1212 	return rc;
1213 }
1214 
1215 static
CompactHashLogExtendEvent32(unsigned char * buffer,uint32_t info,uint32_t magic,uint32_t length,uint32_t pcrindex,uint32_t * edx_ptr)1216 uint32_t CompactHashLogExtendEvent32(unsigned char *buffer,
1217                                      uint32_t info,
1218                                      uint32_t magic,
1219                                      uint32_t length,
1220                                      uint32_t pcrindex,
1221                                      uint32_t *edx_ptr)
1222 {
1223 	uint32_t rc = 0;
1224 	struct hleeo hleeo;
1225 
1226 	if (TCG_IsShutdownPreBootInterface() != 0) {
1227 		rc = (TCG_PC_TPMERROR |
1228 		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1229 	}
1230 
1231 	if (buffer == 0) {
1232 		rc = (TCG_PC_TPMERROR |
1233 		      ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
1234 	}
1235 
1236 	if (rc == 0) {
1237 		struct hleei_short hleei;
1238 		struct pcpes pcpes;
1239 		uint8_t *logdataptr;
1240 		uint8_t *hashdataptr;
1241 
1242 		logdataptr = (uint8_t*)&pcpes;
1243 		hashdataptr = buffer;
1244 
1245 		hleei.ipblength = 0x18;
1246 		hleei.reserved  = 0x0;
1247 		hleei.hashdataptr = (uint32_t)hashdataptr;
1248 		hleei.hashdatalen = length;
1249 		hleei.pcrindex = pcrindex;
1250 		hleei.logdataptr = (uint32_t)logdataptr;
1251 		hleei.logdatalen = 32;
1252 
1253 		memset(&pcpes, 0x0, 32);
1254 		pcpes.pcrindex = pcrindex;
1255 		pcpes.eventtype = 12; /* EV_COMPACT_HASH */
1256 		pcpes.eventdatasize = 4;
1257 		pcpes.event = info;
1258 
1259 		rc = HashLogExtendEvent32(&hleei,
1260 		                          &hleeo,
1261 		                          TCG_MAGIC,
1262 		                          0x0,
1263 		                          0x0);
1264 	}
1265 
1266 	if (rc == 0) {
1267 		*edx_ptr = hleeo.eventnumber;
1268 	}
1269 
1270 	return rc;
1271 }
1272 
1273 
1274 
1275 /*******************************************************************
1276   Calculation of SHA1 in SW
1277 
1278   See: RFC3174, Wikipedia's SHA1 alogrithm description
1279  ******************************************************************/
1280 typedef struct _sha1_ctx {
1281 	uint32_t h[5];
1282 } sha1_ctx;
1283 
1284 
rol(uint32_t val,uint16_t rol)1285 static inline uint32_t rol(uint32_t val, uint16_t rol)
1286 {
1287 	return (val << rol) | (val >> (32 - rol));
1288 }
1289 
1290 static const uint32_t sha_ko[4] = { 0x5a827999,
1291                                     0x6ed9eba1,
1292                                     0x8f1bbcdc,
1293                                     0xca62c1d6 };
1294 
1295 
sha1_block(uint32_t * w,sha1_ctx * ctx)1296 static void sha1_block(uint32_t *w, sha1_ctx *ctx)
1297 {
1298 	uint32_t i;
1299 	uint32_t a,b,c,d,e,f;
1300 	uint32_t tmp;
1301 	uint32_t idx;
1302 
1303 	/* change endianess of given data */
1304 	for (i = 0; i < 16; i++) {
1305 		w[i] = bswap(w[i]);
1306 	}
1307 
1308 	for (i = 16; i <= 79; i++) {
1309 		tmp = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
1310 		w[i] = rol(tmp,1);
1311 	}
1312 
1313 	a = ctx->h[0];
1314 	b = ctx->h[1];
1315 	c = ctx->h[2];
1316 	d = ctx->h[3];
1317 	e = ctx->h[4];
1318 
1319 	for (i = 0; i <= 79; i++) {
1320 		if (i <= 19) {
1321 			f = (b & c) | ((b ^ 0xffffffff) & d);
1322 			idx = 0;
1323 		} else if (i <= 39) {
1324 			f = b ^ c ^ d;
1325 			idx = 1;
1326 		} else if (i <= 59) {
1327 			f = (b & c) | (b & d) | (c & d);
1328 			idx = 2;
1329 		} else {
1330 			f = b ^ c ^ d;
1331 			idx = 3;
1332 		}
1333 
1334 		tmp = rol(a, 5) +
1335 		      f +
1336 		      e +
1337 		      sha_ko[idx] +
1338 		      w[i];
1339 		e = d;
1340 		d = c;
1341 		c = rol(b, 30);
1342 		b = a;
1343 		a = tmp;
1344 	}
1345 
1346 	ctx->h[0] += a;
1347 	ctx->h[1] += b;
1348 	ctx->h[2] += c;
1349 	ctx->h[3] += d;
1350 	ctx->h[4] += e;
1351 }
1352 
1353 static
sha1_do(sha1_ctx * ctx,const unsigned char * data32,uint32_t length)1354 void sha1_do(sha1_ctx *ctx, const unsigned char *data32, uint32_t length)
1355 {
1356 	uint32_t offset;
1357 	uint16_t num;
1358 	uint32_t bits = 0;
1359 	uint32_t w[80];
1360 	uint32_t tmp;
1361 
1362 	/* treat data in 64-byte chunks */
1363 	for (offset = 0; length - offset >= 64; offset += 64) {
1364 		memcpy(w, data32 + offset, 64);
1365 		sha1_block((uint32_t *)w, ctx);
1366 		bits += (64 * 8);
1367 	}
1368 
1369 	/* last block with less than 64 bytes */
1370 	num = length - offset;
1371 	bits += (num << 3);
1372 
1373 	memset(w, 0x0, 64);
1374 	memcpy(w, data32 + offset, num);
1375 	((uint8_t *)w)[num] = 0x80;
1376 
1377 	if (num >= 56) {
1378 		/* cannot append number of bits here */
1379 		sha1_block((uint32_t *)w, ctx);
1380 		memset(w, 0x0, 60);
1381 	}
1382 
1383 	/* write number of bits to end of block */
1384 	tmp = bswap(bits);
1385 	memcpy(&w[15], &tmp, 4);
1386 
1387 	sha1_block(w, ctx);
1388 
1389 	/* need to switch result's endianess */
1390 	for (num = 0; num < 5; num++)
1391 		ctx->h[num] = bswap(ctx->h[num]);
1392 }
1393 
1394 /* sha1 initialization constants */
1395 static const uint32_t sha_const[5] = {
1396 	0x67452301,
1397 	0xefcdab89,
1398 	0x98badcfe,
1399 	0x10325476,
1400 	0xc3d2e1f0
1401 };
1402 
1403 static
sha1(const unsigned char * data,uint32_t length,unsigned char * hash)1404 void sha1(const unsigned char *data, uint32_t length, unsigned char *hash)
1405 {
1406 	sha1_ctx ctx;
1407 
1408 	memcpy(&ctx.h[0], sha_const, 20);
1409 	sha1_do(&ctx, data, length);
1410 	memcpy(hash, &ctx.h[0], 20);
1411 }
1412 
1413 
TCGInterruptHandler(pushad_regs_t * regs,uint32_t esds,uint32_t flags_ptr)1414 uint32_t TCGInterruptHandler(pushad_regs_t *regs, uint32_t esds,
1415                              uint32_t flags_ptr)
1416 {
1417 	uint16_t DS = esds >> 16;
1418 	uint16_t ES = esds & 0xffff;
1419 	uint16_t *FLAGS = (uint16_t *)flags_ptr;
1420 
1421 	switch(regs->u.r8.al) {
1422 	case 0x00:
1423 		if (MA_IsTPMPresent() == 0) {
1424 			/* no TPM available */
1425 			regs->u.r32.eax = TCG_PC_TPMERROR |
1426 			     ((uint32_t)(TCG_PC_TPM_NOT_PRESENT) << 16);
1427 		} else {
1428 			regs->u.r32.eax = MA_InitTPM(TPM_ST_CLEAR);
1429 			if (regs->u.r32.eax == 0) {
1430 				regs->u.r32.ebx = TCG_MAGIC;
1431 				regs->u.r8.ch = TCG_VERSION_MAJOR;
1432 				regs->u.r8.cl = TCG_VERSION_MINOR;
1433 				regs->u.r32.edx = 0x0;
1434 				regs->u.r32.esi =
1435 				             (Bit32u)tcpa_get_lasa_base_ptr();
1436 				regs->u.r32.edi =
1437 				             (Bit32u)tcpa_get_lasa_last_ptr();
1438 				CLEAR_CF();
1439 			}
1440 		}
1441 		break;
1442 	case 0x01:
1443 		regs->u.r32.eax =
1444 			HashLogExtendEvent32((struct hleei_short*)
1445 			                        ADDR_FROM_SEG_OFF(ES,
1446 			                              regs->u.r16.di),
1447 			                    (struct hleeo*)
1448 			                        ADDR_FROM_SEG_OFF(DS,
1449 			                              regs->u.r16.si),
1450 			                    regs->u.r32.ebx,
1451 			                    regs->u.r32.ecx,
1452 			                    regs->u.r32.edx);
1453 		CLEAR_CF();
1454 		break;
1455 	case 0x02:
1456 		regs->u.r32.eax =
1457 			PassThroughToTPM32((struct pttti *)
1458 			                        ADDR_FROM_SEG_OFF(ES,
1459 			                              regs->u.r16.di),
1460 			                   (struct pttto *)
1461 			                        ADDR_FROM_SEG_OFF(DS,
1462 			                              regs->u.r16.si),
1463 			                   regs->u.r32.ebx,
1464 			                   regs->u.r32.ecx,
1465 			                   regs->u.r32.edx);
1466 		CLEAR_CF();
1467 		break;
1468 	case 0x03:
1469 		regs->u.r32.eax =
1470 			TCG_ShutdownPreBootInterface(regs->u.r32.ebx);
1471 		CLEAR_CF();
1472 		break;
1473 	case 0x04:
1474 		regs->u.r32.eax =
1475 			HashLogEvent32((struct hlei*)
1476 			                        ADDR_FROM_SEG_OFF(ES,
1477 					              regs->u.r16.di),
1478 		                       (struct hleo*)
1479 			                        ADDR_FROM_SEG_OFF(DS,
1480 			                              regs->u.r16.si),
1481 			                   regs->u.r32.ebx,
1482 			                   regs->u.r32.ecx,
1483 			                   regs->u.r32.edx);
1484 		CLEAR_CF();
1485 		break;
1486 	case 0x05:
1487 		regs->u.r32.eax =
1488 			HashAll32((struct hai*)
1489 					ADDR_FROM_SEG_OFF(ES,
1490 			                                  regs->u.r16.di),
1491 			         (unsigned char *)
1492 			                ADDR_FROM_SEG_OFF(DS,
1493 			                                  regs->u.r16.si),
1494 			           regs->u.r32.ebx,
1495 			           regs->u.r32.ecx,
1496 			           regs->u.r32.edx);
1497 		CLEAR_CF();
1498 		break;
1499 	case 0x06:
1500 		regs->u.r32.eax =
1501 			TSS32((struct ti*)ADDR_FROM_SEG_OFF(ES,
1502 			                                    regs->u.r16.di),
1503 			      (struct to*)ADDR_FROM_SEG_OFF(DS,
1504 			                                    regs->u.r16.si),
1505 			      regs->u.r32.ebx,
1506 			      regs->u.r32.ecx,
1507 			      regs->u.r32.edx);
1508 		CLEAR_CF();
1509 		break;
1510 	case 0x07:
1511 		regs->u.r32.eax =
1512 		  CompactHashLogExtendEvent32((unsigned char *)
1513 		                                  ADDR_FROM_SEG_OFF(ES,
1514 		                                        regs->u.r16.di),
1515 		                              regs->u.r32.esi,
1516 		                              regs->u.r32.ebx,
1517 		                              regs->u.r32.ecx,
1518 		                              regs->u.r32.edx,
1519 		                              &regs->u.r32.edx);
1520 		CLEAR_CF();
1521 		break;
1522 	default:
1523 		SET_CF();
1524 	}
1525 
1526 	return 0;
1527 }
1528