Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
[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  * 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");