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