[PATCH] tpm: tpm_bios fix sparse warnings
[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, event_data_size;
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                 event_data_size = be32_to_cpu(((u32 *)event_entry)[1]);
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         return 0;
311 }
312
313 static int tpm_bios_measurements_release(struct inode *inode,
314                                          struct file *file)
315 {
316         struct seq_file *seq = file->private_data;
317         struct tpm_bios_log *log = seq->private;
318
319         if (log) {
320                 kfree(log->bios_event_log);
321                 kfree(log);
322         }
323
324         return seq_release(inode, file);
325 }
326
327 static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
328 {
329         int len = 0;
330         int i;
331         char *eventname;
332         struct tcpa_event *event = v;
333         unsigned char *event_entry =
334             (unsigned char *) (v + sizeof(struct tcpa_event));
335
336         eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
337         if (!eventname) {
338                 printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
339                        __func__);
340                 return -EFAULT;
341         }
342
343         seq_printf(m, "%2d ", event->pcr_index);
344
345         /* 2nd: SHA1 */
346         for (i = 0; i < 20; i++)
347                 seq_printf(m, "%02x", event->pcr_value[i]);
348
349         /* 3rd: event type identifier */
350         seq_printf(m, " %02x", event->event_type);
351
352         len += get_event_name(eventname, event, event_entry);
353
354         /* 4th: eventname <= max + \'0' delimiter */
355         seq_printf(m, " %s\n", eventname);
356
357         return 0;
358 }
359
360 static struct seq_operations tpm_ascii_b_measurments_seqops = {
361         .start = tpm_bios_measurements_start,
362         .next = tpm_bios_measurements_next,
363         .stop = tpm_bios_measurements_stop,
364         .show = tpm_ascii_bios_measurements_show,
365 };
366
367 static struct seq_operations tpm_binary_b_measurments_seqops = {
368         .start = tpm_bios_measurements_start,
369         .next = tpm_bios_measurements_next,
370         .stop = tpm_bios_measurements_stop,
371         .show = tpm_binary_bios_measurements_show,
372 };
373
374 /* read binary bios log */
375 static int read_log(struct tpm_bios_log *log)
376 {
377         struct acpi_tcpa *buff;
378         acpi_status status;
379         struct acpi_table_header *virt;
380
381         if (log->bios_event_log != NULL) {
382                 printk(KERN_ERR
383                        "%s: ERROR - Eventlog already initialized\n",
384                        __func__);
385                 return -EFAULT;
386         }
387
388         /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
389         status = acpi_get_firmware_table(ACPI_TCPA_SIG, 1,
390                                          ACPI_LOGICAL_ADDRESSING,
391                                          (struct acpi_table_header **)
392                                          &buff);
393
394         if (ACPI_FAILURE(status)) {
395                 printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
396                        __func__);
397                 return -EIO;
398         }
399
400         if (buff->log_max_len == 0) {
401                 printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
402                 return -EIO;
403         }
404
405         /* malloc EventLog space */
406         log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
407         if (!log->bios_event_log) {
408                 printk
409                     ("%s: ERROR - Not enough  Memory for BIOS measurements\n",
410                      __func__);
411                 return -ENOMEM;
412         }
413
414         log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
415
416         acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt);
417
418         memcpy(log->bios_event_log, virt, buff->log_max_len);
419
420         acpi_os_unmap_memory(virt, buff->log_max_len);
421         return 0;
422 }
423
424 static int tpm_ascii_bios_measurements_open(struct inode *inode,
425                                             struct file *file)
426 {
427         int err;
428         struct tpm_bios_log *log;
429         struct seq_file *seq;
430
431         log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
432         if (!log)
433                 return -ENOMEM;
434
435         if ((err = read_log(log)))
436                 return err;
437
438         /* now register seq file */
439         err = seq_open(file, &tpm_ascii_b_measurments_seqops);
440         if (!err) {
441                 seq = file->private_data;
442                 seq->private = log;
443         } else {
444                 kfree(log->bios_event_log);
445                 kfree(log);
446         }
447         return err;
448 }
449
450 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                 return err;
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                 kfree(log->bios_event_log);
478                 kfree(log);
479         }
480         return err;
481 }
482
483 struct file_operations tpm_binary_bios_measurements_ops = {
484         .open = tpm_binary_bios_measurements_open,
485         .read = seq_read,
486         .llseek = seq_lseek,
487         .release = tpm_bios_measurements_release,
488 };
489
490 static int is_bad(void *p)
491 {
492         if (!p)
493                 return 1;
494         if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
495                 return 1;
496         return 0;
497 }
498
499 struct dentry **tpm_bios_log_setup(char *name)
500 {
501         struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
502
503         tpm_dir = securityfs_create_dir(name, NULL);
504         if (is_bad(tpm_dir))
505                 goto out;
506
507         bin_file =
508             securityfs_create_file("binary_bios_measurements",
509                                    S_IRUSR | S_IRGRP, tpm_dir, NULL,
510                                    &tpm_binary_bios_measurements_ops);
511         if (is_bad(bin_file))
512                 goto out_tpm;
513
514         ascii_file =
515             securityfs_create_file("ascii_bios_measurements",
516                                    S_IRUSR | S_IRGRP, tpm_dir, NULL,
517                                    &tpm_ascii_bios_measurements_ops);
518         if (is_bad(ascii_file))
519                 goto out_bin;
520
521         ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
522         if (!ret)
523                 goto out_ascii;
524
525         ret[0] = ascii_file;
526         ret[1] = bin_file;
527         ret[2] = tpm_dir;
528
529         return ret;
530
531 out_ascii:
532         securityfs_remove(ascii_file);
533 out_bin:
534         securityfs_remove(bin_file);
535 out_tpm:
536         securityfs_remove(tpm_dir);
537 out:
538         return NULL;
539 }
540 EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
541
542 void tpm_bios_log_teardown(struct dentry **lst)
543 {
544         int i;
545
546         for (i = 0; i < 3; i++)
547                 securityfs_remove(lst[i]);
548 }
549 EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
550 MODULE_LICENSE("GPL");