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