Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-drm-fsl-dcu.git] / drivers / char / tpm / tpm_eventlog.c
1 /*
2  * Copyright (C) 2005, 2012 IBM Corporation
3  *
4  * Authors:
5  *      Kent Yoder <key@linux.vnet.ibm.com>
6  *      Seiji Munetoh <munetoh@jp.ibm.com>
7  *      Stefan Berger <stefanb@us.ibm.com>
8  *      Reiner Sailer <sailer@watson.ibm.com>
9  *      Kylene Hall <kjhall@us.ibm.com>
10  *
11  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
12  *
13  * Access to the eventlog created by a system's firmware / BIOS
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version
18  * 2 of the License, or (at your option) any later version.
19  *
20  */
21
22 #include <linux/seq_file.h>
23 #include <linux/fs.h>
24 #include <linux/security.h>
25 #include <linux/module.h>
26 #include <linux/slab.h>
27
28 #include "tpm.h"
29 #include "tpm_eventlog.h"
30
31
32 static const char* tcpa_event_type_strings[] = {
33         "PREBOOT",
34         "POST CODE",
35         "",
36         "NO ACTION",
37         "SEPARATOR",
38         "ACTION",
39         "EVENT TAG",
40         "S-CRTM Contents",
41         "S-CRTM Version",
42         "CPU Microcode",
43         "Platform Config Flags",
44         "Table of Devices",
45         "Compact Hash",
46         "IPL",
47         "IPL Partition Data",
48         "Non-Host Code",
49         "Non-Host Config",
50         "Non-Host Info"
51 };
52
53 static const char* tcpa_pc_event_id_strings[] = {
54         "",
55         "SMBIOS",
56         "BIS Certificate",
57         "POST BIOS ",
58         "ESCD ",
59         "CMOS",
60         "NVRAM",
61         "Option ROM",
62         "Option ROM config",
63         "",
64         "Option ROM microcode ",
65         "S-CRTM Version",
66         "S-CRTM Contents ",
67         "POST Contents ",
68         "Table of Devices",
69 };
70
71 /* returns pointer to start of pos. entry of tcg log */
72 static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
73 {
74         loff_t i;
75         struct tpm_bios_log *log = m->private;
76         void *addr = log->bios_event_log;
77         void *limit = log->bios_event_log_end;
78         struct tcpa_event *event;
79
80         /* read over *pos measurements */
81         for (i = 0; i < *pos; i++) {
82                 event = addr;
83
84                 if ((addr + sizeof(struct tcpa_event)) < limit) {
85                         if (event->event_type == 0 && event->event_size == 0)
86                                 return NULL;
87                         addr += sizeof(struct tcpa_event) + event->event_size;
88                 }
89         }
90
91         /* now check if current entry is valid */
92         if ((addr + sizeof(struct tcpa_event)) >= limit)
93                 return NULL;
94
95         event = addr;
96
97         if ((event->event_type == 0 && event->event_size == 0) ||
98             ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
99                 return NULL;
100
101         return addr;
102 }
103
104 static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
105                                         loff_t *pos)
106 {
107         struct tcpa_event *event = v;
108         struct tpm_bios_log *log = m->private;
109         void *limit = log->bios_event_log_end;
110
111         v += sizeof(struct tcpa_event) + event->event_size;
112
113         /* now check if current entry is valid */
114         if ((v + sizeof(struct tcpa_event)) >= limit)
115                 return NULL;
116
117         event = v;
118
119         if (event->event_type == 0 && event->event_size == 0)
120                 return NULL;
121
122         if ((event->event_type == 0 && event->event_size == 0) ||
123             ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
124                 return NULL;
125
126         (*pos)++;
127         return v;
128 }
129
130 static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
131 {
132 }
133
134 static int get_event_name(char *dest, struct tcpa_event *event,
135                         unsigned char * event_entry)
136 {
137         const char *name = "";
138         /* 41 so there is room for 40 data and 1 nul */
139         char data[41] = "";
140         int i, n_len = 0, d_len = 0;
141         struct tcpa_pc_event *pc_event;
142
143         switch(event->event_type) {
144         case PREBOOT:
145         case POST_CODE:
146         case UNUSED:
147         case NO_ACTION:
148         case SCRTM_CONTENTS:
149         case SCRTM_VERSION:
150         case CPU_MICROCODE:
151         case PLATFORM_CONFIG_FLAGS:
152         case TABLE_OF_DEVICES:
153         case COMPACT_HASH:
154         case IPL:
155         case IPL_PARTITION_DATA:
156         case NONHOST_CODE:
157         case NONHOST_CONFIG:
158         case NONHOST_INFO:
159                 name = tcpa_event_type_strings[event->event_type];
160                 n_len = strlen(name);
161                 break;
162         case SEPARATOR:
163         case ACTION:
164                 if (MAX_TEXT_EVENT > event->event_size) {
165                         name = event_entry;
166                         n_len = event->event_size;
167                 }
168                 break;
169         case EVENT_TAG:
170                 pc_event = (struct tcpa_pc_event *)event_entry;
171
172                 /* ToDo Row data -> Base64 */
173
174                 switch (pc_event->event_id) {
175                 case SMBIOS:
176                 case BIS_CERT:
177                 case CMOS:
178                 case NVRAM:
179                 case OPTION_ROM_EXEC:
180                 case OPTION_ROM_CONFIG:
181                 case S_CRTM_VERSION:
182                         name = tcpa_pc_event_id_strings[pc_event->event_id];
183                         n_len = strlen(name);
184                         break;
185                 /* hash data */
186                 case POST_BIOS_ROM:
187                 case ESCD:
188                 case OPTION_ROM_MICROCODE:
189                 case S_CRTM_CONTENTS:
190                 case POST_CONTENTS:
191                         name = tcpa_pc_event_id_strings[pc_event->event_id];
192                         n_len = strlen(name);
193                         for (i = 0; i < 20; i++)
194                                 d_len += sprintf(&data[2*i], "%02x",
195                                                 pc_event->event_data[i]);
196                         break;
197                 default:
198                         break;
199                 }
200         default:
201                 break;
202         }
203
204         return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
205                         n_len, name, d_len, data);
206
207 }
208
209 static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
210 {
211         struct tcpa_event *event = v;
212         char *data = v;
213         int i;
214
215         for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
216                 seq_putc(m, data[i]);
217
218         return 0;
219 }
220
221 static int tpm_bios_measurements_release(struct inode *inode,
222                                          struct file *file)
223 {
224         struct seq_file *seq = file->private_data;
225         struct tpm_bios_log *log = seq->private;
226
227         if (log) {
228                 kfree(log->bios_event_log);
229                 kfree(log);
230         }
231
232         return seq_release(inode, file);
233 }
234
235 static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
236 {
237         int len = 0;
238         int i;
239         char *eventname;
240         struct tcpa_event *event = v;
241         unsigned char *event_entry =
242             (unsigned char *) (v + sizeof(struct tcpa_event));
243
244         eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
245         if (!eventname) {
246                 printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
247                        __func__);
248                 return -EFAULT;
249         }
250
251         seq_printf(m, "%2d ", event->pcr_index);
252
253         /* 2nd: SHA1 */
254         for (i = 0; i < 20; i++)
255                 seq_printf(m, "%02x", event->pcr_value[i]);
256
257         /* 3rd: event type identifier */
258         seq_printf(m, " %02x", event->event_type);
259
260         len += get_event_name(eventname, event, event_entry);
261
262         /* 4th: eventname <= max + \'0' delimiter */
263         seq_printf(m, " %s\n", eventname);
264
265         kfree(eventname);
266         return 0;
267 }
268
269 static const struct seq_operations tpm_ascii_b_measurments_seqops = {
270         .start = tpm_bios_measurements_start,
271         .next = tpm_bios_measurements_next,
272         .stop = tpm_bios_measurements_stop,
273         .show = tpm_ascii_bios_measurements_show,
274 };
275
276 static const struct seq_operations tpm_binary_b_measurments_seqops = {
277         .start = tpm_bios_measurements_start,
278         .next = tpm_bios_measurements_next,
279         .stop = tpm_bios_measurements_stop,
280         .show = tpm_binary_bios_measurements_show,
281 };
282
283 static int tpm_ascii_bios_measurements_open(struct inode *inode,
284                                             struct file *file)
285 {
286         int err;
287         struct tpm_bios_log *log;
288         struct seq_file *seq;
289
290         log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
291         if (!log)
292                 return -ENOMEM;
293
294         if ((err = read_log(log)))
295                 goto out_free;
296
297         /* now register seq file */
298         err = seq_open(file, &tpm_ascii_b_measurments_seqops);
299         if (!err) {
300                 seq = file->private_data;
301                 seq->private = log;
302         } else {
303                 goto out_free;
304         }
305
306 out:
307         return err;
308 out_free:
309         kfree(log->bios_event_log);
310         kfree(log);
311         goto out;
312 }
313
314 static const struct file_operations tpm_ascii_bios_measurements_ops = {
315         .open = tpm_ascii_bios_measurements_open,
316         .read = seq_read,
317         .llseek = seq_lseek,
318         .release = tpm_bios_measurements_release,
319 };
320
321 static int tpm_binary_bios_measurements_open(struct inode *inode,
322                                              struct file *file)
323 {
324         int err;
325         struct tpm_bios_log *log;
326         struct seq_file *seq;
327
328         log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
329         if (!log)
330                 return -ENOMEM;
331
332         if ((err = read_log(log)))
333                 goto out_free;
334
335         /* now register seq file */
336         err = seq_open(file, &tpm_binary_b_measurments_seqops);
337         if (!err) {
338                 seq = file->private_data;
339                 seq->private = log;
340         } else {
341                 goto out_free;
342         }
343
344 out:
345         return err;
346 out_free:
347         kfree(log->bios_event_log);
348         kfree(log);
349         goto out;
350 }
351
352 static const struct file_operations tpm_binary_bios_measurements_ops = {
353         .open = tpm_binary_bios_measurements_open,
354         .read = seq_read,
355         .llseek = seq_lseek,
356         .release = tpm_bios_measurements_release,
357 };
358
359 static int is_bad(void *p)
360 {
361         if (!p)
362                 return 1;
363         if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
364                 return 1;
365         return 0;
366 }
367
368 struct dentry **tpm_bios_log_setup(char *name)
369 {
370         struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
371
372         tpm_dir = securityfs_create_dir(name, NULL);
373         if (is_bad(tpm_dir))
374                 goto out;
375
376         bin_file =
377             securityfs_create_file("binary_bios_measurements",
378                                    S_IRUSR | S_IRGRP, tpm_dir, NULL,
379                                    &tpm_binary_bios_measurements_ops);
380         if (is_bad(bin_file))
381                 goto out_tpm;
382
383         ascii_file =
384             securityfs_create_file("ascii_bios_measurements",
385                                    S_IRUSR | S_IRGRP, tpm_dir, NULL,
386                                    &tpm_ascii_bios_measurements_ops);
387         if (is_bad(ascii_file))
388                 goto out_bin;
389
390         ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
391         if (!ret)
392                 goto out_ascii;
393
394         ret[0] = ascii_file;
395         ret[1] = bin_file;
396         ret[2] = tpm_dir;
397
398         return ret;
399
400 out_ascii:
401         securityfs_remove(ascii_file);
402 out_bin:
403         securityfs_remove(bin_file);
404 out_tpm:
405         securityfs_remove(tpm_dir);
406 out:
407         return NULL;
408 }
409
410 void tpm_bios_log_teardown(struct dentry **lst)
411 {
412         int i;
413
414         for (i = 0; i < 3; i++)
415                 securityfs_remove(lst[i]);
416 }