OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [tpm/] [tpm_bios.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Copyright (C) 2005 IBM Corporation
3
 *
4
 * Authors:
5
 *      Seiji Munetoh <munetoh@jp.ibm.com>
6
 *      Stefan Berger <stefanb@us.ibm.com>
7
 *      Reiner Sailer <sailer@watson.ibm.com>
8
 *      Kylene Hall <kjhall@us.ibm.com>
9
 *
10
 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
11
 *
12
 * Access to the eventlog extended by the TCG BIOS of PC platform
13
 *
14
 * This program is free software; you can redistribute it and/or
15
 * modify it under the terms of the GNU General Public License
16
 * as published by the Free Software Foundation; either version
17
 * 2 of the License, or (at your option) any later version.
18
 *
19
 */
20
 
21
#include <linux/seq_file.h>
22
#include <linux/fs.h>
23
#include <linux/security.h>
24
#include <linux/module.h>
25
#include <acpi/acpi.h>
26
#include <acpi/actypes.h>
27
#include <acpi/actbl.h>
28
#include "tpm.h"
29
 
30
#define TCG_EVENT_NAME_LEN_MAX  255
31
#define MAX_TEXT_EVENT          1000    /* Max event string length */
32
#define ACPI_TCPA_SIG           "TCPA"  /* 0x41504354 /'TCPA' */
33
 
34
enum bios_platform_class {
35
        BIOS_CLIENT = 0x00,
36
        BIOS_SERVER = 0x01,
37
};
38
 
39
struct tpm_bios_log {
40
        void *bios_event_log;
41
        void *bios_event_log_end;
42
};
43
 
44
struct acpi_tcpa {
45
        struct acpi_table_header hdr;
46
        u16 platform_class;
47
        union {
48
                struct client_hdr {
49
                        u32 log_max_len __attribute__ ((packed));
50
                        u64 log_start_addr __attribute__ ((packed));
51
                } client;
52
                struct server_hdr {
53
                        u16 reserved;
54
                        u64 log_max_len __attribute__ ((packed));
55
                        u64 log_start_addr __attribute__ ((packed));
56
                } server;
57
        };
58
};
59
 
60
struct tcpa_event {
61
        u32 pcr_index;
62
        u32 event_type;
63
        u8 pcr_value[20];       /* SHA1 */
64
        u32 event_size;
65
        u8 event_data[0];
66
};
67
 
68
enum tcpa_event_types {
69
        PREBOOT = 0,
70
        POST_CODE,
71
        UNUSED,
72
        NO_ACTION,
73
        SEPARATOR,
74
        ACTION,
75
        EVENT_TAG,
76
        SCRTM_CONTENTS,
77
        SCRTM_VERSION,
78
        CPU_MICROCODE,
79
        PLATFORM_CONFIG_FLAGS,
80
        TABLE_OF_DEVICES,
81
        COMPACT_HASH,
82
        IPL,
83
        IPL_PARTITION_DATA,
84
        NONHOST_CODE,
85
        NONHOST_CONFIG,
86
        NONHOST_INFO,
87
};
88
 
89
static const char* tcpa_event_type_strings[] = {
90
        "PREBOOT",
91
        "POST CODE",
92
        "",
93
        "NO ACTION",
94
        "SEPARATOR",
95
        "ACTION",
96
        "EVENT TAG",
97
        "S-CRTM Contents",
98
        "S-CRTM Version",
99
        "CPU Microcode",
100
        "Platform Config Flags",
101
        "Table of Devices",
102
        "Compact Hash",
103
        "IPL",
104
        "IPL Partition Data",
105
        "Non-Host Code",
106
        "Non-Host Config",
107
        "Non-Host Info"
108
};
109
 
110
struct tcpa_pc_event {
111
        u32 event_id;
112
        u32 event_size;
113
        u8 event_data[0];
114
};
115
 
116
enum tcpa_pc_event_ids {
117
        SMBIOS = 1,
118
        BIS_CERT,
119
        POST_BIOS_ROM,
120
        ESCD,
121
        CMOS,
122
        NVRAM,
123
        OPTION_ROM_EXEC,
124
        OPTION_ROM_CONFIG,
125
        OPTION_ROM_MICROCODE = 10,
126
        S_CRTM_VERSION,
127
        S_CRTM_CONTENTS,
128
        POST_CONTENTS,
129
        HOST_TABLE_OF_DEVICES,
130
};
131
 
132
static const char* tcpa_pc_event_id_strings[] = {
133
        "",
134
        "SMBIOS",
135
        "BIS Certificate",
136
        "POST BIOS ",
137
        "ESCD ",
138
        "CMOS",
139
        "NVRAM",
140
        "Option ROM",
141
        "Option ROM config",
142
        "",
143
        "Option ROM microcode ",
144
        "S-CRTM Version",
145
        "S-CRTM Contents ",
146
        "POST Contents ",
147
        "Table of Devices",
148
};
149
 
150
/* returns pointer to start of pos. entry of tcg log */
151
static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
152
{
153
        loff_t i;
154
        struct tpm_bios_log *log = m->private;
155
        void *addr = log->bios_event_log;
156
        void *limit = log->bios_event_log_end;
157
        struct tcpa_event *event;
158
 
159
        /* read over *pos measurements */
160
        for (i = 0; i < *pos; i++) {
161
                event = addr;
162
 
163
                if ((addr + sizeof(struct tcpa_event)) < limit) {
164
                        if (event->event_type == 0 && event->event_size == 0)
165
                                return NULL;
166
                        addr += sizeof(struct tcpa_event) + event->event_size;
167
                }
168
        }
169
 
170
        /* now check if current entry is valid */
171
        if ((addr + sizeof(struct tcpa_event)) >= limit)
172
                return NULL;
173
 
174
        event = addr;
175
 
176
        if ((event->event_type == 0 && event->event_size == 0) ||
177
            ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
178
                return NULL;
179
 
180
        return addr;
181
}
182
 
183
static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
184
                                        loff_t *pos)
185
{
186
        struct tcpa_event *event = v;
187
        struct tpm_bios_log *log = m->private;
188
        void *limit = log->bios_event_log_end;
189
 
190
        v += sizeof(struct tcpa_event) + event->event_size;
191
 
192
        /* now check if current entry is valid */
193
        if ((v + sizeof(struct tcpa_event)) >= limit)
194
                return NULL;
195
 
196
        event = v;
197
 
198
        if (event->event_type == 0 && event->event_size == 0)
199
                return NULL;
200
 
201
        if ((event->event_type == 0 && event->event_size == 0) ||
202
            ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
203
                return NULL;
204
 
205
        (*pos)++;
206
        return v;
207
}
208
 
209
static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
210
{
211
}
212
 
213
static int get_event_name(char *dest, struct tcpa_event *event,
214
                        unsigned char * event_entry)
215
{
216
        const char *name = "";
217
        char data[40] = "";
218
        int i, n_len = 0, d_len = 0;
219
        struct tcpa_pc_event *pc_event;
220
 
221
        switch(event->event_type) {
222
        case PREBOOT:
223
        case POST_CODE:
224
        case UNUSED:
225
        case NO_ACTION:
226
        case SCRTM_CONTENTS:
227
        case SCRTM_VERSION:
228
        case CPU_MICROCODE:
229
        case PLATFORM_CONFIG_FLAGS:
230
        case TABLE_OF_DEVICES:
231
        case COMPACT_HASH:
232
        case IPL:
233
        case IPL_PARTITION_DATA:
234
        case NONHOST_CODE:
235
        case NONHOST_CONFIG:
236
        case NONHOST_INFO:
237
                name = tcpa_event_type_strings[event->event_type];
238
                n_len = strlen(name);
239
                break;
240
        case SEPARATOR:
241
        case ACTION:
242
                if (MAX_TEXT_EVENT > event->event_size) {
243
                        name = event_entry;
244
                        n_len = event->event_size;
245
                }
246
                break;
247
        case EVENT_TAG:
248
                pc_event = (struct tcpa_pc_event *)event_entry;
249
 
250
                /* ToDo Row data -> Base64 */
251
 
252
                switch (pc_event->event_id) {
253
                case SMBIOS:
254
                case BIS_CERT:
255
                case CMOS:
256
                case NVRAM:
257
                case OPTION_ROM_EXEC:
258
                case OPTION_ROM_CONFIG:
259
                case S_CRTM_VERSION:
260
                        name = tcpa_pc_event_id_strings[pc_event->event_id];
261
                        n_len = strlen(name);
262
                        break;
263
                /* hash data */
264
                case POST_BIOS_ROM:
265
                case ESCD:
266
                case OPTION_ROM_MICROCODE:
267
                case S_CRTM_CONTENTS:
268
                case POST_CONTENTS:
269
                        name = tcpa_pc_event_id_strings[pc_event->event_id];
270
                        n_len = strlen(name);
271
                        for (i = 0; i < 20; i++)
272
                                d_len += sprintf(&data[2*i], "%02x",
273
                                                pc_event->event_data[i]);
274
                        break;
275
                default:
276
                        break;
277
                }
278
        default:
279
                break;
280
        }
281
 
282
        return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
283
                        n_len, name, d_len, data);
284
 
285
}
286
 
287
static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
288
{
289
        struct tcpa_event *event = v;
290
        char *data = v;
291
        int i;
292
 
293
        for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
294
                seq_putc(m, data[i]);
295
 
296
        return 0;
297
}
298
 
299
static int tpm_bios_measurements_release(struct inode *inode,
300
                                         struct file *file)
301
{
302
        struct seq_file *seq = file->private_data;
303
        struct tpm_bios_log *log = seq->private;
304
 
305
        if (log) {
306
                kfree(log->bios_event_log);
307
                kfree(log);
308
        }
309
 
310
        return seq_release(inode, file);
311
}
312
 
313
static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
314
{
315
        int len = 0;
316
        int i;
317
        char *eventname;
318
        struct tcpa_event *event = v;
319
        unsigned char *event_entry =
320
            (unsigned char *) (v + sizeof(struct tcpa_event));
321
 
322
        eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
323
        if (!eventname) {
324
                printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
325
                       __func__);
326
                return -EFAULT;
327
        }
328
 
329
        seq_printf(m, "%2d ", event->pcr_index);
330
 
331
        /* 2nd: SHA1 */
332
        for (i = 0; i < 20; i++)
333
                seq_printf(m, "%02x", event->pcr_value[i]);
334
 
335
        /* 3rd: event type identifier */
336
        seq_printf(m, " %02x", event->event_type);
337
 
338
        len += get_event_name(eventname, event, event_entry);
339
 
340
        /* 4th: eventname <= max + \'0' delimiter */
341
        seq_printf(m, " %s\n", eventname);
342
 
343
        kfree(eventname);
344
        return 0;
345
}
346
 
347
static struct seq_operations tpm_ascii_b_measurments_seqops = {
348
        .start = tpm_bios_measurements_start,
349
        .next = tpm_bios_measurements_next,
350
        .stop = tpm_bios_measurements_stop,
351
        .show = tpm_ascii_bios_measurements_show,
352
};
353
 
354
static struct seq_operations tpm_binary_b_measurments_seqops = {
355
        .start = tpm_bios_measurements_start,
356
        .next = tpm_bios_measurements_next,
357
        .stop = tpm_bios_measurements_stop,
358
        .show = tpm_binary_bios_measurements_show,
359
};
360
 
361
/* read binary bios log */
362
static int read_log(struct tpm_bios_log *log)
363
{
364
        struct acpi_tcpa *buff;
365
        acpi_status status;
366
        struct acpi_table_header *virt;
367
        u64 len, start;
368
 
369
        if (log->bios_event_log != NULL) {
370
                printk(KERN_ERR
371
                       "%s: ERROR - Eventlog already initialized\n",
372
                       __func__);
373
                return -EFAULT;
374
        }
375
 
376
        /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
377
        status = acpi_get_table(ACPI_SIG_TCPA, 1,
378
                                (struct acpi_table_header **)&buff);
379
 
380
        if (ACPI_FAILURE(status)) {
381
                printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
382
                       __func__);
383
                return -EIO;
384
        }
385
 
386
        switch(buff->platform_class) {
387
        case BIOS_SERVER:
388
                len = buff->server.log_max_len;
389
                start = buff->server.log_start_addr;
390
                break;
391
        case BIOS_CLIENT:
392
        default:
393
                len = buff->client.log_max_len;
394
                start = buff->client.log_start_addr;
395
                break;
396
        }
397
        if (!len) {
398
                printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
399
                return -EIO;
400
        }
401
 
402
        /* malloc EventLog space */
403
        log->bios_event_log = kmalloc(len, GFP_KERNEL);
404
        if (!log->bios_event_log) {
405
                printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
406
                        __func__);
407
                return -ENOMEM;
408
        }
409
 
410
        log->bios_event_log_end = log->bios_event_log + len;
411
 
412
        virt = acpi_os_map_memory(start, len);
413
 
414
        memcpy(log->bios_event_log, virt, len);
415
 
416
        acpi_os_unmap_memory(virt, len);
417
        return 0;
418
}
419
 
420
static int tpm_ascii_bios_measurements_open(struct inode *inode,
421
                                            struct file *file)
422
{
423
        int err;
424
        struct tpm_bios_log *log;
425
        struct seq_file *seq;
426
 
427
        log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
428
        if (!log)
429
                return -ENOMEM;
430
 
431
        if ((err = read_log(log)))
432
                goto out_free;
433
 
434
        /* now register seq file */
435
        err = seq_open(file, &tpm_ascii_b_measurments_seqops);
436
        if (!err) {
437
                seq = file->private_data;
438
                seq->private = log;
439
        } else {
440
                goto out_free;
441
        }
442
 
443
out:
444
        return err;
445
out_free:
446
        kfree(log->bios_event_log);
447
        kfree(log);
448
        goto out;
449
}
450
 
451
const struct file_operations tpm_ascii_bios_measurements_ops = {
452
        .open = tpm_ascii_bios_measurements_open,
453
        .read = seq_read,
454
        .llseek = seq_lseek,
455
        .release = tpm_bios_measurements_release,
456
};
457
 
458
static int tpm_binary_bios_measurements_open(struct inode *inode,
459
                                             struct file *file)
460
{
461
        int err;
462
        struct tpm_bios_log *log;
463
        struct seq_file *seq;
464
 
465
        log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
466
        if (!log)
467
                return -ENOMEM;
468
 
469
        if ((err = read_log(log)))
470
                goto out_free;
471
 
472
        /* now register seq file */
473
        err = seq_open(file, &tpm_binary_b_measurments_seqops);
474
        if (!err) {
475
                seq = file->private_data;
476
                seq->private = log;
477
        } else {
478
                goto out_free;
479
        }
480
 
481
out:
482
        return err;
483
out_free:
484
        kfree(log->bios_event_log);
485
        kfree(log);
486
        goto out;
487
}
488
 
489
const struct file_operations tpm_binary_bios_measurements_ops = {
490
        .open = tpm_binary_bios_measurements_open,
491
        .read = seq_read,
492
        .llseek = seq_lseek,
493
        .release = tpm_bios_measurements_release,
494
};
495
 
496
static int is_bad(void *p)
497
{
498
        if (!p)
499
                return 1;
500
        if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
501
                return 1;
502
        return 0;
503
}
504
 
505
struct dentry **tpm_bios_log_setup(char *name)
506
{
507
        struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
508
 
509
        tpm_dir = securityfs_create_dir(name, NULL);
510
        if (is_bad(tpm_dir))
511
                goto out;
512
 
513
        bin_file =
514
            securityfs_create_file("binary_bios_measurements",
515
                                   S_IRUSR | S_IRGRP, tpm_dir, NULL,
516
                                   &tpm_binary_bios_measurements_ops);
517
        if (is_bad(bin_file))
518
                goto out_tpm;
519
 
520
        ascii_file =
521
            securityfs_create_file("ascii_bios_measurements",
522
                                   S_IRUSR | S_IRGRP, tpm_dir, NULL,
523
                                   &tpm_ascii_bios_measurements_ops);
524
        if (is_bad(ascii_file))
525
                goto out_bin;
526
 
527
        ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
528
        if (!ret)
529
                goto out_ascii;
530
 
531
        ret[0] = ascii_file;
532
        ret[1] = bin_file;
533
        ret[2] = tpm_dir;
534
 
535
        return ret;
536
 
537
out_ascii:
538
        securityfs_remove(ascii_file);
539
out_bin:
540
        securityfs_remove(bin_file);
541
out_tpm:
542
        securityfs_remove(tpm_dir);
543
out:
544
        return NULL;
545
}
546
EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
547
 
548
void tpm_bios_log_teardown(struct dentry **lst)
549
{
550
        int i;
551
 
552
        for (i = 0; i < 3; i++)
553
                securityfs_remove(lst[i]);
554
}
555
EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
556
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.