Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tpm_eventlog.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005, 2012 IBM Corporation
3  *
4  * Authors:
5  * Kent Yoder <[email protected]>
6  * Seiji Munetoh <[email protected]>
7  * Stefan Berger <[email protected]>
8  * Reiner Sailer <[email protected]>
9  * Kylene Hall <[email protected]>
10  *
11  * Maintained by: <[email protected]>
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:
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:
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 }
410 
411 void tpm_bios_log_teardown(struct dentry **lst)
412 {
413  int i;
414 
415  for (i = 0; i < 3; i++)
416  securityfs_remove(lst[i]);
417 }
419 MODULE_LICENSE("GPL");