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 ®s->u.r32.edx);
1520 CLEAR_CF();
1521 break;
1522 default:
1523 SET_CF();
1524 }
1525
1526 return 0;
1527 }
1528