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