~ressu/+junk/xen-ubuntu

« back to all changes in this revision

Viewing changes to tools/firmware/rombios/32bit/tcgbios/tcgbios.c

  • Committer: sami at haahtinen
  • Author(s): Bastian Blank
  • Date: 2010-09-03 15:14:28 UTC
  • Revision ID: sami@haahtinen.name-20100903151428-f88eg54n2fdnak41
Tags: upstream-4.0.1
ImportĀ upstreamĀ versionĀ 4.0.1

Show diffs side-by-side

added added

removed removed

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