2
* Implementation of the TCG BIOS extension according to the specification
4
* https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf
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.
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.
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
* Copyright (C) IBM Corporation, 2006
22
* Author: Stefan Berger <stefanb@us.ibm.com>
24
#include "rombios_compat.h"
25
#include "tpm_drivers.h"
30
/* local structure and variables */
36
uint8_t tpmoperandin[18];
37
} __attribute__((packed));
39
struct ptti_cust CMD_TPM_Startup_0x01_IPB = {
40
0x8+0xc, 0x00, 4+10, 0x00,
41
{ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x99, 0x00, 0x01 },
44
struct ptti_cust CMD_TSC_PhysicalPresence_0x20_IPB = {
45
0x8+0xc, 0x00, 4+10, 0x00,
46
{ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x20 },
49
struct ptti_cust CMD_TSC_PhysicalPresence_0x08_IPB = {
50
0x8+0xc, 0x00, 4+10, 0x00,
51
{ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x08 },
54
struct ptti_cust CMD_TSC_PhysicalPresence_0x100_IPB = {
55
0x8+0xc, 0x00, 4+10, 0x00,
56
{ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x01, 0x00 },
59
struct ptti_cust CMD_TSC_PhysicalPresence_0x10_IPB = {
60
0x8+0xc, 0x00, 4+10, 0x00,
61
{ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x10 },
64
struct ptti_cust CMD_TPM_PhysicalEnable_IPB = {
65
0x8+0xa, 0x00, 4+10, 0x00,
66
{ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x6f },
69
struct ptti_cust CMD_TPM_PhysicalSetDeactivated_0x00_IPB = {
70
0x8+0xb, 0x00, 4+10, 0x00,
71
{ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x72, 0x00 }
73
struct ptti_cust CMD_TPM_SHA1Start_IPB = {
74
0x8+0xa, 0x00, 4+10, 0x00,
75
{ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa0 },
78
struct ptti_cust CMD_TPM_GetCap_Version_IPB = {
79
0x8+0x12, 0x00, 4+18, 0x00,
80
{0x00, 0xc1, 0x00, 0x00, 0x00, 0x12,
81
0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00 },
84
struct ptti_cust *TCG_CommandList[] = {
85
&CMD_TPM_Startup_0x01_IPB,
86
&CMD_TSC_PhysicalPresence_0x20_IPB,
87
&CMD_TSC_PhysicalPresence_0x08_IPB,
88
&CMD_TSC_PhysicalPresence_0x100_IPB,
89
&CMD_TSC_PhysicalPresence_0x10_IPB,
90
&CMD_TPM_PhysicalEnable_IPB,
91
&CMD_TPM_PhysicalSetDeactivated_0x00_IPB,
92
&CMD_TPM_SHA1Start_IPB,
95
/* local function prototypes */
96
static void sha1(const unsigned char *data, uint32_t length,
98
static uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx);
99
static uint32_t HashAll32(struct hai *hai, unsigned char *hash,
100
uint32_t magic, uint32_t ecx, uint32_t edx);
101
static uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s,
103
uint32_t magic, uint32_t ecx,
105
static uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
106
uint32_t ebx, uint32_t ecx, uint32_t edx);
107
static uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto,
108
uint32_t magic, uint32_t ecx, uint32_t edx);
109
static uint32_t MA_Transmit(unsigned char *cmdbuffer,
110
unsigned char *respbuffer,
111
uint32_t respbufferlen);
113
static unsigned char *tcpa_get_lasa_last_ptr(void);
114
static unsigned char *tcpa_get_lasa_base_ptr(void);
115
static void tcpa_reset_acpi_log(void);
116
static uint32_t tcpa_get_laml(void);
119
extern struct tpm_driver tpm_drivers[];
121
/* utility functions */
123
static inline uint32_t bswap(uint32_t a)
125
return ( ( a >> 24 ) & 0x000000ff) |
126
( ( a >> 8 ) & 0x0000ff00) |
127
( ( a << 8 ) & 0x00ff0000) |
128
( ( a << 24 ) & 0xff000000);
131
/********************************************************
132
Extensions for TCG-enabled BIOS
133
*******************************************************/
136
struct acpi_20_tcpa_clisrv *tcpa_ptr;
137
unsigned char *lasa_last_ptr;
138
uint16_t entry_count;
142
static tcpa_acpi_t tcpa_acpi;
145
/* low level driver implementation */
146
static int tpm_driver_to_use = TPM_INVALID_DRIVER;
149
uint32_t MA_IsTPMPresent(void)
153
for (i = 0; i < TPM_NUM_DRIVERS; i++) {
154
struct tpm_driver *td = &tpm_drivers[i];
155
if (td->probe(td->baseaddr) != 0) {
156
tpm_driver_to_use = i;
165
uint32_t MA_InitTPM(uint16_t startupcode)
168
/* low-level initialize the TPM */
169
unsigned char command[sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin)];
170
unsigned char response[10];
171
uint32_t response_size = sizeof(response);
174
CMD_TPM_Startup_0x01_IPB.tpmoperandin,
175
sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin));
176
command[10] = (startupcode >> 8) & 0xff;
177
command[11] = (startupcode >> 0) & 0xff;
178
rc = MA_Transmit(command, response, response_size);
184
uint32_t MA_Transmit(unsigned char *cmdbuffer, unsigned char *respbuffer,
185
uint32_t respbufferlen)
189
struct tpm_driver *td;
191
if (tpm_driver_to_use == TPM_INVALID_DRIVER)
192
return TCG_FATAL_COM_ERROR;
194
td = &tpm_drivers[tpm_driver_to_use];
197
irc = td->activate(td->baseaddr);
199
/* tpm could not be activated */
200
rc = TCG_FATAL_COM_ERROR;
205
uint32_t *tmp = (uint32_t *)&cmdbuffer[2];
206
uint32_t len = bswap(*tmp);
207
irc = td->senddata(td->baseaddr,
211
rc = TCG_FATAL_COM_ERROR;
216
irc = td->waitdatavalid(td->baseaddr);
218
rc = TCG_FATAL_COM_ERROR;
223
irc = td->waitrespready(td->baseaddr, 2000);
225
rc = TCG_FATAL_COM_ERROR;
230
irc = td->readresp(td->baseaddr,
234
rc = TCG_FATAL_COM_ERROR;
239
irc = td->ready(td->baseaddr);
247
uint8_t acpi_validate_entry(struct acpi_header *hdr)
250
unsigned int length = hdr->length;
252
unsigned char *addr = (unsigned char *)hdr;
254
for (ctr = 0; ctr < length; ctr++)
262
initialize the TCPA ACPI subsystem; find the ACPI tables and determine
263
where the TCPA table is.
265
void tcpa_acpi_init(void)
267
struct acpi_20_rsdt *rsdt;
268
struct acpi_20_tcpa_clisrv *tcpa = (void *)0;
269
struct acpi_20_rsdp *rsdp;
274
if (MA_IsTPMPresent() == 0)
280
/* get RSDT from RSDP */
281
rsdt = (struct acpi_20_rsdt *)rsdp->rsdt_address;
282
length = rsdt->header.length;
284
while ((off + 3) < length) {
285
/* try all pointers to structures */
286
tcpa = (struct acpi_20_tcpa_clisrv *)rsdt->entry[ctr];
287
/* valid TCPA ACPI table ? */
288
if (ACPI_2_0_TCPA_SIGNATURE == tcpa->header.signature
289
&& acpi_validate_entry(&tcpa->header) == 0) {
299
printf("TCPA ACPI was NOT found!\n");
303
tcpa_acpi.tcpa_ptr = tcpa;
304
tcpa_acpi.lasa_last_ptr = 0;
305
tcpa_acpi.entry_count = 0;
307
tcpa_reset_acpi_log();
310
/* clear the ACPI log */
311
static void tcpa_reset_acpi_log(void)
313
unsigned char *lasa = tcpa_get_lasa_base_ptr();
315
memset(lasa, 0x0, tcpa_get_laml());
320
* Extend the ACPI log with the given entry by copying the
321
* entry data into the log.
323
* Pointer to the structure to be copied into the log
326
* lower 16 bits of return code contain entry number
327
* if entry number is '0', then upper 16 bits contain error code.
329
uint32_t tcpa_extend_acpi_log(uint32_t entry_ptr)
332
unsigned char *lasa_last = tcpa_get_lasa_last_ptr();
333
unsigned char *lasa_base = tcpa_get_lasa_base_ptr();
335
uint16_t entry_count = tcpa_acpi.entry_count;
336
struct pcpes *pcpes = (struct pcpes *)entry_ptr;
338
if (lasa_last == 0) {
339
lasa_last = lasa_base;
341
struct pcpes *pcpes = (struct pcpes *)lasa_last;
342
/* skip the last entry in the log */
343
size = pcpes->eventdatasize;
348
if (lasa_last == 0) {
349
res = ((uint32_t)TCG_PC_LOGOVERFLOW << 16);
353
uint32_t laml = tcpa_get_laml();
354
size = pcpes->eventdatasize;
356
if ((lasa_last + size - lasa_base) > laml) {
357
res = (TCG_PC_LOGOVERFLOW << 16);
362
/* copy the log entry into the ACPI log */
363
memcpy((char *)lasa_last, (char *)entry_ptr, size);
365
* update the pointers and entry counter that were modified
366
* due to the new entry in the log
368
tcpa_acpi.lasa_last_ptr = lasa_last;
370
tcpa_acpi.entry_count = entry_count;
378
unsigned char *tcpa_get_lasa_last_ptr(void)
380
return tcpa_acpi.lasa_last_ptr;
384
unsigned char *tcpa_get_lasa_base_ptr(void)
386
unsigned char *lasa = 0;
387
struct acpi_20_tcpa_clisrv *tcpa = tcpa_acpi.tcpa_ptr;
389
uint32_t class = tcpa->platform_class;
390
if (class == TCPA_ACPI_CLASS_CLIENT) {
392
lasa = (unsigned char *)(long)tcpa->u.client.lasa;
393
} else if (class == TCPA_ACPI_CLASS_SERVER) {
395
lasa = (unsigned char *)(long)tcpa->u.server.lasa;
402
uint32_t tcpa_get_laml(void)
405
struct acpi_20_tcpa_clisrv *tcpa = tcpa_acpi.tcpa_ptr;
407
uint32_t class = tcpa->platform_class;
408
if (class == TCPA_ACPI_CLASS_CLIENT) {
410
laml = tcpa->u.client.laml;
411
} else if (class == TCPA_ACPI_CLASS_SERVER) {
412
laml = tcpa->u.server.laml;
421
* Add a measurement to the log; the data at data_seg:data/length are
422
* appended to the TCG_PCClientPCREventStruct
425
* pcrIndex : which PCR to extend
426
* event_type : type of event; specs 10.4.1
427
* event_id : (unused)
428
* data : pointer to the data (i.e., string) to be added to the log
429
* length : length of the data
432
tcpa_add_measurement_to_log(uint32_t pcrIndex,
435
const char *data_ptr,
439
struct hleei_short hleei;
441
uint8_t _pcpes[32+400];
442
struct pcpes *pcpes = (struct pcpes *)_pcpes;
443
uint8_t *data = (uint8_t *)data_ptr;
445
if (length < sizeof(_pcpes)-32) {
446
memset(pcpes, 0x0, 32);
447
pcpes->pcrindex = pcrIndex;
448
pcpes->eventtype = event_type;
449
pcpes->eventdatasize = length;
450
memcpy(&_pcpes[32], data, length);
452
hleei.ipblength = 0x18;
453
hleei.reserved = 0x0;
454
hleei.hashdataptr = (uint32_t)&_pcpes[32];
455
hleei.hashdatalen = length;
456
hleei.pcrindex = pcrIndex;
457
hleei.logdataptr = (uint32_t)_pcpes;
458
hleei.logdatalen = length + 32;
459
rc = HashLogExtendEvent32(&hleei,
465
rc = (TCG_PC_TPMERROR |
466
((uint32_t)TCG_GENERAL_ERROR << 16));
473
uint16_t tcpa_add_pcpes_to_log(struct pcpes *pcpes)
476
struct hleei_short hleei;
479
hleei.ipblength = 0x18;
480
hleei.reserved = 0x0;
481
hleei.hashdataptr = 0;
482
hleei.hashdatalen = 0;
483
hleei.pcrindex = pcpes->pcrindex;
484
hleei.logdataptr = (uint32_t)pcpes;
485
hleei.logdatalen = sizeof(pcpes);
487
rc = HashLogExtendEvent32(&hleei,
498
* Add a measurement to the log; further description of the data
499
* that are to be hashed are NOT appended to the TCG_PCClientPCREventStruc.
501
* pcrIndex : PCR to extend
502
* event_type : type of event; specs 10.4.1
503
* ptr : 32 bit pointer to the data to be hashed
504
* length : length of the data to be hashed
506
* Returns lower 16 bit of return code of TCG_HashLogExtendEvent. '0' means
507
* success, otherwise an error is indicated.
510
uint16_t tcpa_add_measurement_to_log_simple(uint32_t pcrIndex,
512
uint8_t *ptr, uint32_t length)
515
struct hleei_short hleei;
519
memset(&pcpes, 0x0, sizeof(pcpes));
520
pcpes.pcrindex = pcrIndex;
521
pcpes.eventtype = event_type;
522
/* specs: 10.4.1, EV_IPL eventfield should not contain the code.*/
523
pcpes.eventdatasize = 0;
525
hleei.ipblength = 0x18;
526
hleei.reserved = 0x0;
527
hleei.hashdataptr = (uint32_t)ptr;
528
hleei.hashdatalen = length;
529
hleei.pcrindex = pcrIndex;
530
hleei.logdataptr = (uint32_t)&pcpes;
531
hleei.logdatalen = 32;
533
rc = HashLogExtendEvent32(&hleei,
541
/* table of event types according to 10.4.1 / table 11 */
542
static const char ev_action[][23] = {
543
/* 0 */ "Calling INT 19h",
545
"Returned via INT 18h",
557
"Start Option ROM Scan"
560
static char evt_separator[] = {0xff,0xff,0xff,0xff};
561
static char wake_event_1[] = "Wake Event 1";
564
* Add a measurement to the list of measurements
565
* pcrIndex : PCR to be extended
566
* event_type : type of event; specs 10.4.1
567
* data : additional parameter; used as parameter for 10.4.3
570
static void tcpa_add_measurement(uint32_t pcrIndex,
576
switch (event_type) {
578
tcpa_add_measurement_to_log_simple(pcrIndex,
580
(uint8_t *)evt_separator,
584
string = ev_action[data /* event_id */];
585
tcpa_add_measurement_to_log(pcrIndex,
597
* Add measurement to log about call of int 19h
599
void tcpa_calling_int19h()
601
tcpa_add_measurement(4, EV_ACTION, 0);
605
* Add measurement to log about retuning from int 19h
607
void tcpa_returned_int19h()
609
tcpa_add_measurement(4, EV_ACTION, 1);
613
* Add event separators for PCRs 0 to 7; specs 8.2.3
615
void tcpa_add_event_separators()
617
uint32_t pcrIndex = 0;
618
while (pcrIndex <= 7) {
619
tcpa_add_measurement(pcrIndex, EV_SEPARATOR, 0);
626
* Add a wake event to the log
628
void tcpa_wake_event()
630
tcpa_add_measurement_to_log(6,
634
strlen(wake_event_1));
638
* Add a measurement regarding the boot device (CDRom, Floppy, HDD) to
639
* the list of measurements.
641
void tcpa_add_bootdevice(uint32_t bootcd, uint32_t bootdrv)
646
string = "Booting BCV device 00h (Floppy)";
647
} else if (bootdrv == 0x80) {
648
string = "Booting BCV device 80h (HDD)";
650
string = "Booting unknown device";
653
string = "Booting from CD ROM device";
655
tcpa_add_measurement_to_log(4, 5, 0,
656
string, strlen(string));
660
* Add measurement to the log about option rom scan
663
void tcpa_start_option_rom_scan()
665
tcpa_add_measurement(2, EV_ACTION, 14);
670
* Add measurement to the log about an option rom
672
void tcpa_option_rom(uint32_t seg)
674
uint32_t len = read_byte(seg, 2) << 9;
675
uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,0);
676
char append[32]; /* TCG_PCClientTaggedEventStruct and
677
OptionROMExecuteStructure; specs 10.4.2.1 */
678
struct hai hai; /* HashAll Input Block; specs 12.10 */
680
memset(append, 0x0, sizeof(append));
682
append[0] = 7; /* Option ROM Execute */
683
append[4] = 24;/* size of OptionROMExecute Structure */
684
/* leave the rest to '0' */
687
hai.ipblength = 0x10;
689
hai.hashdataptr = (uint32_t)addr;
690
hai.hashdatalen = len;
691
hai.algorithmid = TPM_ALG_SHA;
694
(unsigned char *)append+12,
699
tcpa_add_measurement_to_log(2,
707
* Add a measurement to the log in support of 8.2.5.3
708
* Creates two log entries
711
* bootcd : 0: MBR of hdd, 1: boot image, 2: boot catalog of El Torito
712
* seg : segment where the IPL data are located
713
* off : offset where the IPL data are located
714
* count : length in bytes
716
void tcpa_ipl(Bit32u bootcd,Bit32u seg,Bit32u off,Bit32u count)
718
uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,off);
720
/* specs: 8.2.5.6 El Torito */
721
tcpa_add_measurement_to_log_simple(4,
726
else if (bootcd == 2) { /* Boot Catalog */
728
/* specs: 8.2.5.6 El Torito */
729
tcpa_add_measurement_to_log_simple(5,
730
EV_IPL_PARTITION_DATA,
736
/* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */
737
tcpa_add_measurement_to_log_simple(4,
743
/* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */
744
tcpa_add_measurement_to_log_simple(5,
745
EV_IPL_PARTITION_DATA,
751
void tcpa_measure_post(Bit32u from, Bit32u to)
753
struct pcpes pcpes; /* PCClientPCREventStruc */
755
memset(&pcpes, 0x0, sizeof(pcpes));
758
sha1((unsigned char *)from,
760
(unsigned char *)&pcpes.digest);
762
pcpes.eventtype = EV_POST_CODE;
763
pcpes.eventdatasize = 0;
765
tcpa_add_pcpes_to_log(&pcpes);
770
uint32_t SendCommand32(uint32_t idx, struct pttto *pttto, uint32_t size_ptto)
773
struct pttti *pttti = (struct pttti *)TCG_CommandList[idx];
776
if (size_ptto > 0 && size_ptto < 14) {
777
rc = (TCG_PC_TPMERROR |
778
((uint32_t)TCG_INVALID_INPUT_PARA << 16));
782
if (size_ptto == 0) {
783
pttto = (struct pttto *)_pttto;
784
size_ptto = sizeof(_pttto);
786
pttti->opblength = size_ptto;
790
if (pttti->opblength > size_ptto) {
791
rc = (TCG_PC_TPMERROR |
792
((uint32_t)TCG_OUTPUT_BUFFER_TOO_SHORT << 16));
797
rc = PassThroughToTPM32(pttti,
808
uint32_t tcpa_initialize_tpm(uint32_t physpres)
812
struct pttto *pttto = (struct pttto *)_pttto;
813
uint32_t pttto_size = sizeof(_pttto);
816
rc = SendCommand32(IDX_CMD_TPM_Startup_0x01, pttto,
820
if (rc == 0 && physpres != 0) {
821
rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x20,
825
if (rc == 0 && physpres != 0) {
826
rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x08,
830
if (rc == 0 && physpres != 0) {
831
rc = SendCommand32(IDX_CMD_TPM_PhysicalEnable,
835
if (rc == 0 && physpres != 0) {
836
rc = SendCommand32(IDX_CMD_TPM_PhysicalSetDeactivated_0x00,
841
rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x100,
846
rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x10,
853
static uint16_t TCG_IsShutdownPreBootInterface(void)
855
return tcpa_acpi.flags & STATUS_FLAG_SHUTDOWN;
860
uint32_t _TCG_TPM_Extend(unsigned char *hash, uint32_t pcrindex)
863
uint8_t _pttti[8+34];
864
uint8_t _pttto[4+30];
865
struct pttti *pttti = (struct pttti*)&_pttti;
866
struct pttto *pttto = (struct pttto*)&_pttto;
868
pttti->ipblength = 8 + 34;
870
pttti->opblength = 4 + 30;
871
pttti->reserved2 = 0;
874
_pttti[8 + 1] = 0xc1;
875
*(uint32_t *)&_pttti[8 + 2] = bswap(34);
876
*(uint32_t *)&_pttti[8 + 6] = bswap(0x14);
877
*(uint32_t *)&_pttti[8 + 10]= bswap(pcrindex);
878
memcpy(&_pttti[8+14], hash, 20);
880
rc = PassThroughToTPM32(pttti,
885
/* sanity check of result */
886
if (_pttto[4] != 0x00 || _pttto[5] != 0xc4) {
887
rc = (TCG_PC_TPMERROR |
888
((uint32_t)TCG_FATAL_COM_ERROR << 16));
893
Invalidate the log since system did not process this
896
tcpa_reset_acpi_log();
897
memset(&tcpa_acpi, 0x0, sizeof(tcpa_acpi));
898
TCG_ShutdownPreBootInterface(0);
905
uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s, struct hleeo *hleeo,
906
uint32_t magic, uint32_t ecx, uint32_t edx)
910
struct hlei hlei ; /* HashLogEventInput block */
911
struct hleo hleo; /* HashLogEventOutput block */
912
struct hleei_long *hleei_l = (struct hleei_long *)hleei_s;
916
if (TCG_IsShutdownPreBootInterface() != 0) {
917
rc = (TCG_PC_TPMERROR |
918
((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
922
/* short or long version? */
923
size = hleei_s->ipblength;
927
} else if (size == 0x1c) {
931
/* bad input block */
932
rc = TCG_PC_TPMERROR |
933
((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
938
uint32_t hashdataptr;
939
uint32_t hashdatalen;
941
uint32_t logeventtype;
943
uint32_t eventnumber;
947
hashdataptr = hleei_s->hashdataptr;
948
hashdatalen = hleei_s->hashdatalen;
949
pcrindex = hleei_s->pcrindex;
951
logdataptr = hleei_s->logdataptr;
952
logdatalen = hleei_s->logdatalen;
954
logdataptr = hleei_l->logdataptr;
955
logdatalen = hleei_l->logdatalen;
958
pcpes = (struct pcpes *)logdataptr;
959
logeventtype = pcpes->eventtype;
961
/* fill out HashLogEventInput block 'hlie' */
962
hlei.ipblength = 0x1c;
964
hlei.hashdataptr = hashdataptr;
965
hlei.hashdatalen = hashdatalen;
966
hlei.pcrindex = pcrindex;
967
hlei.logeventtype= logeventtype;
968
hlei.logdataptr = logdataptr;
969
hlei.logdatalen = logdatalen;
971
rc = HashLogEvent32(&hlei,
976
eventnumber = hleo.eventnumber;
978
hleeo->opblength = 8 + 20;
980
hleeo->eventnumber = eventnumber;
982
memcpy(hash, (unsigned char *)logdataptr + 0x8, 20);
983
_TCG_TPM_Extend(hash, pcrindex);
987
hleeo->opblength = 4;
996
uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto,
997
uint32_t magic, uint32_t ecx, uint32_t edx)
1001
uint32_t resbuflen = 0;
1003
if (TCG_IsShutdownPreBootInterface() != 0) {
1004
rc = (TCG_PC_TPMERROR |
1005
((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1009
if (pttti->ipblength < 0x8 + 10) {
1010
rc = TCG_PC_TPMERROR |
1011
((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
1016
if (pttti->opblength < 0x4) {
1017
rc = TCG_PC_TPMERROR |
1018
((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
1025
cmd32 = &pttti->tpmoperandin[0];
1026
resbuflen = pttti->opblength - 4;
1027
resbuf32 = &pttto->tpmoperandout[0];
1029
rc = MA_Transmit(cmd32, resbuf32, resbuflen);
1033
pttto->opblength = resbuflen+4;
1034
pttto->reserved = 0;
1038
pttto->opblength = 0;
1039
pttto->reserved = 0;
1047
uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx)
1050
if (TCG_IsShutdownPreBootInterface() == 0) {
1051
tcpa_acpi.flags |= STATUS_FLAG_SHUTDOWN;
1053
rc = (TCG_PC_TPMERROR |
1054
((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1061
uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
1062
uint32_t ebx, uint32_t ecx, uint32_t edx)
1066
uint32_t logdataptr;
1067
uint32_t logdatalen;
1068
uint32_t hashdataptr;
1069
uint32_t hashdatalen;
1071
if (TCG_IsShutdownPreBootInterface() != 0) {
1072
rc = (TCG_PC_TPMERROR |
1073
((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1077
size = hlei->ipblength;
1079
rc = (TCG_PC_TPMERROR |
1080
((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1085
struct pcpes *pcpes;
1086
logdataptr = hlei->logdataptr;
1087
logdatalen = hlei->logdatalen;
1088
pcpes = (struct pcpes *)logdataptr;
1089
if (pcpes->pcrindex != hlei->pcrindex) {
1090
rc = (TCG_PC_TPMERROR |
1091
((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1096
struct pcpes *pcpes= (struct pcpes *)logdataptr;
1097
if (pcpes->eventtype != hlei->logeventtype) {
1098
rc = (TCG_PC_TPMERROR |
1099
((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1105
hashdataptr = hlei->hashdataptr;
1106
hashdatalen = hlei->hashdatalen;
1108
if ((hashdataptr != 0) | (hashdatalen != 0)) {
1110
struct hai hai; /* HashAll Input Block */
1111
hai.ipblength = 0x10;
1113
hai.hashdataptr = hashdataptr;
1114
hai.hashdatalen = hashdatalen;
1115
hai.algorithmid = TPM_ALG_SHA;
1116
rc = HashAll32(&hai,
1123
/* hashing was done ok */
1124
memcpy((unsigned char *)logdataptr + 8,
1131
/* extend the log with this event */
1132
entry = tcpa_extend_acpi_log(logdataptr);
1133
if ((uint16_t)entry == 0) {
1134
/* upper 16 bits hold error code */
1140
/* updating the log was fine */
1141
hleo->opblength = 8;
1143
hleo->eventnumber = entry;
1148
hleo->opblength = 2;
1156
uint32_t HashAll32(struct hai *hai, unsigned char *hash,
1157
uint32_t magic, uint32_t ecx, uint32_t edx)
1161
if (TCG_IsShutdownPreBootInterface() != 0) {
1162
rc = (TCG_PC_TPMERROR |
1163
((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1167
if (hai->ipblength != 0x10) {
1168
rc = (TCG_PC_TPMERROR |
1169
((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1174
if (hai->algorithmid != TPM_ALG_SHA) {
1175
rc = (TCG_PC_TPMERROR |
1176
((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1181
uint8_t *hashdataptr32;
1182
uint32_t hashdatalen32;
1184
hashdataptr32 = (uint8_t *)hai->hashdataptr;
1185
hashdatalen32 = hai->hashdatalen;
1197
uint32_t TSS32(struct ti *ti, struct to *to,
1198
uint32_t ebx, uint32_t ecx, uint32_t edx)
1201
if (TCG_IsShutdownPreBootInterface() == 0) {
1202
rc = TCG_PC_UNSUPPORTED;
1204
rc = (TCG_PC_TPMERROR |
1205
((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1217
uint32_t CompactHashLogExtendEvent32(unsigned char *buffer,
1227
if (TCG_IsShutdownPreBootInterface() != 0) {
1228
rc = (TCG_PC_TPMERROR |
1229
((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1233
rc = (TCG_PC_TPMERROR |
1234
((uint32_t)TCG_INVALID_INPUT_PARA << 16));
1238
struct hleei_short hleei;
1240
uint8_t *logdataptr;
1241
uint8_t *hashdataptr;
1243
logdataptr = (uint8_t*)&pcpes;
1244
hashdataptr = buffer;
1246
hleei.ipblength = 0x18;
1247
hleei.reserved = 0x0;
1248
hleei.hashdataptr = (uint32_t)hashdataptr;
1249
hleei.hashdatalen = length;
1250
hleei.pcrindex = pcrindex;
1251
hleei.logdataptr = (uint32_t)logdataptr;
1252
hleei.logdatalen = 32;
1254
memset(&pcpes, 0x0, 32);
1255
pcpes.pcrindex = pcrindex;
1256
pcpes.eventtype = 12; /* EV_COMPACT_HASH */
1257
pcpes.eventdatasize = 4;
1260
rc = HashLogExtendEvent32(&hleei,
1268
*edx_ptr = hleeo.eventnumber;
1276
/*******************************************************************
1277
Calculation of SHA1 in SW
1279
See: RFC3174, Wikipedia's SHA1 alogrithm description
1280
******************************************************************/
1281
typedef struct _sha1_ctx {
1286
static inline uint32_t rol(uint32_t val, uint16_t rol)
1288
return (val << rol) | (val >> (32 - rol));
1291
static const uint32_t sha_ko[4] = { 0x5a827999,
1297
static void sha1_block(uint32_t *w, sha1_ctx *ctx)
1300
uint32_t a,b,c,d,e,f;
1304
/* change endianess of given data */
1305
for (i = 0; i < 16; i++) {
1309
for (i = 16; i <= 79; i++) {
1310
tmp = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
1320
for (i = 0; i <= 79; i++) {
1322
f = (b & c) | ((b ^ 0xffffffff) & d);
1324
} else if (i <= 39) {
1327
} else if (i <= 59) {
1328
f = (b & c) | (b & d) | (c & d);
1355
void sha1_do(sha1_ctx *ctx, const unsigned char *data32, uint32_t length)
1363
/* treat data in 64-byte chunks */
1364
for (offset = 0; length - offset >= 64; offset += 64) {
1365
memcpy(w, data32 + offset, 64);
1366
sha1_block((uint32_t *)w, ctx);
1370
/* last block with less than 64 bytes */
1371
num = length - offset;
1375
memcpy(w, data32 + offset, num);
1376
((uint8_t *)w)[num] = 0x80;
1379
/* cannot append number of bits here */
1380
sha1_block((uint32_t *)w, ctx);
1384
/* write number of bits to end of block */
1386
memcpy(&w[15], &tmp, 4);
1390
/* need to switch result's endianess */
1391
for (num = 0; num < 5; num++)
1392
ctx->h[num] = bswap(ctx->h[num]);
1395
/* sha1 initialization constants */
1396
static const uint32_t sha_const[5] = {
1405
void sha1(const unsigned char *data, uint32_t length, unsigned char *hash)
1409
memcpy(&ctx.h[0], sha_const, 20);
1410
sha1_do(&ctx, data, length);
1411
memcpy(hash, &ctx.h[0], 20);
1415
uint32_t TCGInterruptHandler(pushad_regs_t *regs, uint32_t esds,
1418
uint16_t DS = esds >> 16;
1419
uint16_t ES = esds & 0xffff;
1420
uint16_t *FLAGS = (uint16_t *)flags_ptr;
1422
switch(regs->u.r8.al) {
1424
if (MA_IsTPMPresent() == 0) {
1425
/* no TPM available */
1426
regs->u.r32.eax = TCG_PC_TPMERROR |
1427
((uint32_t)(TCG_PC_TPM_NOT_PRESENT) << 16);
1429
regs->u.r32.eax = MA_InitTPM(TPM_ST_CLEAR);
1430
if (regs->u.r32.eax == 0) {
1431
regs->u.r32.ebx = TCG_MAGIC;
1432
regs->u.r8.ch = TCG_VERSION_MAJOR;
1433
regs->u.r8.cl = TCG_VERSION_MINOR;
1434
regs->u.r32.edx = 0x0;
1436
(Bit32u)tcpa_get_lasa_base_ptr();
1438
(Bit32u)tcpa_get_lasa_last_ptr();
1445
HashLogExtendEvent32((struct hleei_short*)
1446
ADDR_FROM_SEG_OFF(ES,
1449
ADDR_FROM_SEG_OFF(DS,
1458
PassThroughToTPM32((struct pttti *)
1459
ADDR_FROM_SEG_OFF(ES,
1462
ADDR_FROM_SEG_OFF(DS,
1471
TCG_ShutdownPreBootInterface(regs->u.r32.ebx);
1476
HashLogEvent32((struct hlei*)
1477
ADDR_FROM_SEG_OFF(ES,
1480
ADDR_FROM_SEG_OFF(DS,
1489
HashAll32((struct hai*)
1490
ADDR_FROM_SEG_OFF(ES,
1493
ADDR_FROM_SEG_OFF(DS,
1502
TSS32((struct ti*)ADDR_FROM_SEG_OFF(ES,
1504
(struct to*)ADDR_FROM_SEG_OFF(DS,
1513
CompactHashLogExtendEvent32((unsigned char *)
1514
ADDR_FROM_SEG_OFF(ES,