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