Merge branch 'topic/hda' into for-linus
[pandora-kernel.git] / 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  * 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 "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         /* 41 so there is room for 40 data and 1 nul */
216         char data[41] = "";
217         int i, n_len = 0, d_len = 0;
218         struct tcpa_pc_event *pc_event;
219
220         switch(event->event_type) {
221         case PREBOOT:
222         case POST_CODE:
223         case UNUSED:
224         case NO_ACTION:
225         case SCRTM_CONTENTS:
226         case SCRTM_VERSION:
227         case CPU_MICROCODE:
228         case PLATFORM_CONFIG_FLAGS:
229         case TABLE_OF_DEVICES:
230         case COMPACT_HASH:
231         case IPL:
232         case IPL_PARTITION_DATA:
233         case NONHOST_CODE:
234         case NONHOST_CONFIG:
235         case NONHOST_INFO:
236                 name = tcpa_event_type_strings[event->event_type];
237                 n_len = strlen(name);
238                 break;
239         case SEPARATOR:
240         case ACTION:
241                 if (MAX_TEXT_EVENT > event->event_size) {
242                         name = event_entry;
243                         n_len = event->event_size;
244                 }
245                 break;
246         case EVENT_TAG:
247                 pc_event = (struct tcpa_pc_event *)event_entry;
248
249                 /* ToDo Row data -> Base64 */
250
251                 switch (pc_event->event_id) {
252                 case SMBIOS:
253                 case BIS_CERT:
254                 case CMOS:
255                 case NVRAM:
256                 case OPTION_ROM_EXEC:
257                 case OPTION_ROM_CONFIG:
258                 case S_CRTM_VERSION:
259                         name = tcpa_pc_event_id_strings[pc_event->event_id];
260                         n_len = strlen(name);
261                         break;
262                 /* hash data */
263                 case POST_BIOS_ROM:
264                 case ESCD:
265                 case OPTION_ROM_MICROCODE:
266                 case S_CRTM_CONTENTS:
267                 case POST_CONTENTS:
268                         name = tcpa_pc_event_id_strings[pc_event->event_id];
269                         n_len = strlen(name);
270                         for (i = 0; i < 20; i++)
271                                 d_len += sprintf(&data[2*i], "%02x",
272                                                 pc_event->event_data[i]);
273                         break;
274                 default:
275                         break;
276                 }
277         default:
278                 break;
279         }
280
281         return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
282                         n_len, name, d_len, data);
283
284 }
285
286 static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
287 {
288         struct tcpa_event *event = v;
289         char *data = v;
290         int i;
291
292         for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
293                 seq_putc(m, data[i]);
294
295         return 0;
296 }
297
298 static int tpm_bios_measurements_release(struct inode *inode,
299                                          struct file *file)
300 {
301         struct seq_file *seq = file->private_data;
302         struct tpm_bios_log *log = seq->private;
303
304         if (log) {
305                 kfree(log->bios_event_log);
306                 kfree(log);
307         }
308
309         return seq_release(inode, file);
310 }
311
312 static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
313 {
314         int len = 0;
315         int i;
316         char *eventname;
317         struct tcpa_event *event = v;
318         unsigned char *event_entry =
319             (unsigned char *) (v + sizeof(struct tcpa_event));
320
321         eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
322         if (!eventname) {
323                 printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
324                        __func__);
325                 return -EFAULT;
326         }
327
328         seq_printf(m, "%2d ", event->pcr_index);
329
330         /* 2nd: SHA1 */
331         for (i = 0; i < 20; i++)
332                 seq_printf(m, "%02x", event->pcr_value[i]);
333
334         /* 3rd: event type identifier */
335         seq_printf(m, " %02x", event->event_type);
336
337         len += get_event_name(eventname, event, event_entry);
338
339         /* 4th: eventname <= max + \'0' delimiter */
340         seq_printf(m, " %s\n", eventname);
341
342         kfree(eventname);
343         return 0;
344 }
345
346 static struct seq_operations tpm_ascii_b_measurments_seqops = {
347         .start = tpm_bios_measurements_start,
348         .next = tpm_bios_measurements_next,
349         .stop = tpm_bios_measurements_stop,
350         .show = tpm_ascii_bios_measurements_show,
351 };
352
353 static struct seq_operations tpm_binary_b_measurments_seqops = {
354         .start = tpm_bios_measurements_start,
355         .next = tpm_bios_measurements_next,
356         .stop = tpm_bios_measurements_stop,
357         .show = tpm_binary_bios_measurements_show,
358 };
359
360 /* read binary bios log */
361 static int read_log(struct tpm_bios_log *log)
362 {
363         struct acpi_tcpa *buff;
364         acpi_status status;
365         struct acpi_table_header *virt;
366         u64 len, start;
367
368         if (log->bios_event_log != NULL) {
369                 printk(KERN_ERR
370                        "%s: ERROR - Eventlog already initialized\n",
371                        __func__);
372                 return -EFAULT;
373         }
374
375         /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
376         status = acpi_get_table(ACPI_SIG_TCPA, 1,
377                                 (struct acpi_table_header **)&buff);
378
379         if (ACPI_FAILURE(status)) {
380                 printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
381                        __func__);
382                 return -EIO;
383         }
384
385         switch(buff->platform_class) {
386         case BIOS_SERVER:
387                 len = buff->server.log_max_len;
388                 start = buff->server.log_start_addr;
389                 break;
390         case BIOS_CLIENT:
391         default:
392                 len = buff->client.log_max_len;
393                 start = buff->client.log_start_addr;
394                 break;
395         }
396         if (!len) {
397                 printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
398                 return -EIO;
399         }
400
401         /* malloc EventLog space */
402         log->bios_event_log = kmalloc(len, GFP_KERNEL);
403         if (!log->bios_event_log) {
404                 printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
405                         __func__);
406                 return -ENOMEM;
407         }
408
409         log->bios_event_log_end = log->bios_event_log + len;
410
411         virt = acpi_os_map_memory(start, len);
412
413         memcpy(log->bios_event_log, virt, len);
414
415         acpi_os_unmap_memory(virt, len);
416         return 0;
417 }
418
419 static int tpm_ascii_bios_measurements_open(struct inode *inode,
420                                             struct file *file)
421 {
422         int err;
423         struct tpm_bios_log *log;
424         struct seq_file *seq;
425
426         log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
427         if (!log)
428                 return -ENOMEM;
429
430         if ((err = read_log(log)))
431                 goto out_free;
432
433         /* now register seq file */
434         err = seq_open(file, &tpm_ascii_b_measurments_seqops);
435         if (!err) {
436                 seq = file->private_data;
437                 seq->private = log;
438         } else {
439                 goto out_free;
440         }
441
442 out:
443         return err;
444 out_free:
445         kfree(log->bios_event_log);
446         kfree(log);
447         goto out;
448 }
449
450 static const struct file_operations tpm_ascii_bios_measurements_ops = {
451         .open = tpm_ascii_bios_measurements_open,
452         .read = seq_read,
453         .llseek = seq_lseek,
454         .release = tpm_bios_measurements_release,
455 };
456
457 static int tpm_binary_bios_measurements_open(struct inode *inode,
458                                              struct file *file)
459 {
460         int err;
461         struct tpm_bios_log *log;
462         struct seq_file *seq;
463
464         log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
465         if (!log)
466                 return -ENOMEM;
467
468         if ((err = read_log(log)))
469                 goto out_free;
470
471         /* now register seq file */
472         err = seq_open(file, &tpm_binary_b_measurments_seqops);
473         if (!err) {
474                 seq = file->private_data;
475                 seq->private = log;
476         } else {
477                 goto out_free;
478         }
479
480 out:
481         return err;
482 out_free:
483         kfree(log->bios_event_log);
484         kfree(log);
485         goto out;
486 }
487
488 static const struct file_operations tpm_binary_bios_measurements_ops = {
489         .open = tpm_binary_bios_measurements_open,
490         .read = seq_read,
491         .llseek = seq_lseek,
492         .release = tpm_bios_measurements_release,
493 };
494
495 static int is_bad(void *p)
496 {
497         if (!p)
498                 return 1;
499         if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
500                 return 1;
501         return 0;
502 }
503
504 struct dentry **tpm_bios_log_setup(char *name)
505 {
506         struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
507
508         tpm_dir = securityfs_create_dir(name, NULL);
509         if (is_bad(tpm_dir))
510                 goto out;
511
512         bin_file =
513             securityfs_create_file("binary_bios_measurements",
514                                    S_IRUSR | S_IRGRP, tpm_dir, NULL,
515                                    &tpm_binary_bios_measurements_ops);
516         if (is_bad(bin_file))
517                 goto out_tpm;
518
519         ascii_file =
520             securityfs_create_file("ascii_bios_measurements",
521                                    S_IRUSR | S_IRGRP, tpm_dir, NULL,
522                                    &tpm_ascii_bios_measurements_ops);
523         if (is_bad(ascii_file))
524                 goto out_bin;
525
526         ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
527         if (!ret)
528                 goto out_ascii;
529
530         ret[0] = ascii_file;
531         ret[1] = bin_file;
532         ret[2] = tpm_dir;
533
534         return ret;
535
536 out_ascii:
537         securityfs_remove(ascii_file);
538 out_bin:
539         securityfs_remove(bin_file);
540 out_tpm:
541         securityfs_remove(tpm_dir);
542 out:
543         return NULL;
544 }
545 EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
546
547 void tpm_bios_log_teardown(struct dentry **lst)
548 {
549         int i;
550
551         for (i = 0; i < 3; i++)
552                 securityfs_remove(lst[i]);
553 }
554 EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
555 MODULE_LICENSE("GPL");