Merge tag 'nfs-for-3.18-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[deliverable/linux.git] / drivers / char / tpm / tpm_eventlog.c
CommitLineData
55a82ab3 1/*
e5dcd87f 2 * Copyright (C) 2005, 2012 IBM Corporation
55a82ab3
KJH
3 *
4 * Authors:
e5dcd87f 5 * Kent Yoder <key@linux.vnet.ibm.com>
55a82ab3
KJH
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 *
8e81cc13
KY
11 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
12 *
e5dcd87f 13 * Access to the eventlog created by a system's firmware / BIOS
55a82ab3
KJH
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>
5a0e3ad6 26#include <linux/slab.h>
55a82ab3 27
e5dcd87f
KY
28#include "tpm.h"
29#include "tpm_eventlog.h"
55a82ab3 30
55a82ab3
KJH
31
32static 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
55a82ab3 53static const char* tcpa_pc_event_id_strings[] = {
de66a695 54 "",
55a82ab3
KJH
55 "SMBIOS",
56 "BIS Certificate",
57 "POST BIOS ",
58 "ESCD ",
59 "CMOS",
60 "NVRAM",
61 "Option ROM",
62 "Option ROM config",
de66a695
SM
63 "",
64 "Option ROM microcode ",
55a82ab3 65 "S-CRTM Version",
de66a695
SM
66 "S-CRTM Contents ",
67 "POST Contents ",
68 "Table of Devices",
55a82ab3
KJH
69};
70
55a82ab3
KJH
71/* returns pointer to start of pos. entry of tcg log */
72static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
73{
74 loff_t i;
d09cf7d7
KJH
75 struct tpm_bios_log *log = m->private;
76 void *addr = log->bios_event_log;
77 void *limit = log->bios_event_log_end;
55a82ab3
KJH
78 struct tcpa_event *event;
79
80 /* read over *pos measurements */
81 for (i = 0; i < *pos; i++) {
82 event = addr;
83
d09cf7d7 84 if ((addr + sizeof(struct tcpa_event)) < limit) {
55a82ab3
KJH
85 if (event->event_type == 0 && event->event_size == 0)
86 return NULL;
d09cf7d7 87 addr += sizeof(struct tcpa_event) + event->event_size;
55a82ab3
KJH
88 }
89 }
90
91 /* now check if current entry is valid */
d09cf7d7 92 if ((addr + sizeof(struct tcpa_event)) >= limit)
55a82ab3
KJH
93 return NULL;
94
95 event = addr;
96
97 if ((event->event_type == 0 && event->event_size == 0) ||
d09cf7d7 98 ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
55a82ab3
KJH
99 return NULL;
100
101 return addr;
102}
103
104static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
105 loff_t *pos)
106{
107 struct tcpa_event *event = v;
d09cf7d7
KJH
108 struct tpm_bios_log *log = m->private;
109 void *limit = log->bios_event_log_end;
55a82ab3
KJH
110
111 v += sizeof(struct tcpa_event) + event->event_size;
112
113 /* now check if current entry is valid */
d09cf7d7 114 if ((v + sizeof(struct tcpa_event)) >= limit)
55a82ab3
KJH
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) ||
d09cf7d7 123 ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
55a82ab3
KJH
124 return NULL;
125
126 (*pos)++;
127 return v;
128}
129
130static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
131{
132}
133
134static int get_event_name(char *dest, struct tcpa_event *event,
135 unsigned char * event_entry)
136{
137 const char *name = "";
fbaa5869
EP
138 /* 41 so there is room for 40 data and 1 nul */
139 char data[41] = "";
55a82ab3 140 int i, n_len = 0, d_len = 0;
de66a695 141 struct tcpa_pc_event *pc_event;
55a82ab3
KJH
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:
de66a695 170 pc_event = (struct tcpa_pc_event *)event_entry;
55a82ab3
KJH
171
172 /* ToDo Row data -> Base64 */
173
de66a695 174 switch (pc_event->event_id) {
55a82ab3
KJH
175 case SMBIOS:
176 case BIS_CERT:
177 case CMOS:
178 case NVRAM:
179 case OPTION_ROM_EXEC:
180 case OPTION_ROM_CONFIG:
55a82ab3 181 case S_CRTM_VERSION:
de66a695 182 name = tcpa_pc_event_id_strings[pc_event->event_id];
55a82ab3
KJH
183 n_len = strlen(name);
184 break;
de66a695 185 /* hash data */
55a82ab3
KJH
186 case POST_BIOS_ROM:
187 case ESCD:
de66a695
SM
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];
55a82ab3
KJH
192 n_len = strlen(name);
193 for (i = 0; i < 20; i++)
de66a695
SM
194 d_len += sprintf(&data[2*i], "%02x",
195 pc_event->event_data[i]);
55a82ab3
KJH
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
209static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
210{
44d7aff0
SM
211 struct tcpa_event *event = v;
212 char *data = v;
213 int i;
55a82ab3 214
44d7aff0 215 for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
55a82ab3
KJH
216 seq_putc(m, data[i]);
217
55a82ab3
KJH
218 return 0;
219}
220
221static int tpm_bios_measurements_release(struct inode *inode,
222 struct file *file)
223{
d09cf7d7
KJH
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);
55a82ab3 230 }
d09cf7d7 231
55a82ab3
KJH
232 return seq_release(inode, file);
233}
234
235static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
236{
237 int len = 0;
55a82ab3
KJH
238 char *eventname;
239 struct tcpa_event *event = v;
240 unsigned char *event_entry =
241 (unsigned char *) (v + sizeof(struct tcpa_event));
242
243 eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
244 if (!eventname) {
245 printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
246 __func__);
247 return -EFAULT;
248 }
249
250 seq_printf(m, "%2d ", event->pcr_index);
251
252 /* 2nd: SHA1 */
a3d64df8 253 seq_printf(m, "%20phN", event->pcr_value);
55a82ab3
KJH
254
255 /* 3rd: event type identifier */
256 seq_printf(m, " %02x", event->event_type);
257
258 len += get_event_name(eventname, event, event_entry);
259
260 /* 4th: eventname <= max + \'0' delimiter */
261 seq_printf(m, " %s\n", eventname);
262
59e89f3a 263 kfree(eventname);
55a82ab3
KJH
264 return 0;
265}
266
88e9d34c 267static const struct seq_operations tpm_ascii_b_measurments_seqops = {
55a82ab3
KJH
268 .start = tpm_bios_measurements_start,
269 .next = tpm_bios_measurements_next,
270 .stop = tpm_bios_measurements_stop,
271 .show = tpm_ascii_bios_measurements_show,
272};
273
88e9d34c 274static const struct seq_operations tpm_binary_b_measurments_seqops = {
55a82ab3
KJH
275 .start = tpm_bios_measurements_start,
276 .next = tpm_bios_measurements_next,
277 .stop = tpm_bios_measurements_stop,
278 .show = tpm_binary_bios_measurements_show,
279};
280
55a82ab3
KJH
281static int tpm_ascii_bios_measurements_open(struct inode *inode,
282 struct file *file)
283{
284 int err;
d09cf7d7
KJH
285 struct tpm_bios_log *log;
286 struct seq_file *seq;
55a82ab3 287
d09cf7d7
KJH
288 log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
289 if (!log)
290 return -ENOMEM;
291
292 if ((err = read_log(log)))
178554ae 293 goto out_free;
55a82ab3
KJH
294
295 /* now register seq file */
d09cf7d7
KJH
296 err = seq_open(file, &tpm_ascii_b_measurments_seqops);
297 if (!err) {
298 seq = file->private_data;
299 seq->private = log;
300 } else {
178554ae 301 goto out_free;
d09cf7d7 302 }
178554ae
JJ
303
304out:
d09cf7d7 305 return err;
178554ae
JJ
306out_free:
307 kfree(log->bios_event_log);
308 kfree(log);
309 goto out;
55a82ab3
KJH
310}
311
3bd60464 312static const struct file_operations tpm_ascii_bios_measurements_ops = {
55a82ab3
KJH
313 .open = tpm_ascii_bios_measurements_open,
314 .read = seq_read,
315 .llseek = seq_lseek,
316 .release = tpm_bios_measurements_release,
317};
318
319static int tpm_binary_bios_measurements_open(struct inode *inode,
320 struct file *file)
321{
322 int err;
d09cf7d7
KJH
323 struct tpm_bios_log *log;
324 struct seq_file *seq;
55a82ab3 325
d09cf7d7
KJH
326 log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
327 if (!log)
328 return -ENOMEM;
329
330 if ((err = read_log(log)))
03ce1104 331 goto out_free;
55a82ab3
KJH
332
333 /* now register seq file */
d09cf7d7
KJH
334 err = seq_open(file, &tpm_binary_b_measurments_seqops);
335 if (!err) {
336 seq = file->private_data;
337 seq->private = log;
338 } else {
03ce1104 339 goto out_free;
d09cf7d7 340 }
03ce1104
RS
341
342out:
d09cf7d7 343 return err;
03ce1104
RS
344out_free:
345 kfree(log->bios_event_log);
346 kfree(log);
347 goto out;
55a82ab3
KJH
348}
349
3bd60464 350static const struct file_operations tpm_binary_bios_measurements_ops = {
55a82ab3
KJH
351 .open = tpm_binary_bios_measurements_open,
352 .read = seq_read,
353 .llseek = seq_lseek,
354 .release = tpm_bios_measurements_release,
355};
356
ca4a031f
AM
357static int is_bad(void *p)
358{
359 if (!p)
360 return 1;
361 if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
362 return 1;
363 return 0;
364}
365
55a82ab3
KJH
366struct dentry **tpm_bios_log_setup(char *name)
367{
368 struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
369
370 tpm_dir = securityfs_create_dir(name, NULL);
ca4a031f 371 if (is_bad(tpm_dir))
55a82ab3
KJH
372 goto out;
373
374 bin_file =
375 securityfs_create_file("binary_bios_measurements",
376 S_IRUSR | S_IRGRP, tpm_dir, NULL,
377 &tpm_binary_bios_measurements_ops);
ca4a031f 378 if (is_bad(bin_file))
55a82ab3
KJH
379 goto out_tpm;
380
381 ascii_file =
382 securityfs_create_file("ascii_bios_measurements",
383 S_IRUSR | S_IRGRP, tpm_dir, NULL,
384 &tpm_ascii_bios_measurements_ops);
ca4a031f 385 if (is_bad(ascii_file))
55a82ab3
KJH
386 goto out_bin;
387
388 ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
389 if (!ret)
390 goto out_ascii;
391
392 ret[0] = ascii_file;
393 ret[1] = bin_file;
394 ret[2] = tpm_dir;
395
396 return ret;
397
398out_ascii:
399 securityfs_remove(ascii_file);
400out_bin:
401 securityfs_remove(bin_file);
402out_tpm:
403 securityfs_remove(tpm_dir);
404out:
405 return NULL;
406}
55a82ab3
KJH
407
408void tpm_bios_log_teardown(struct dentry **lst)
409{
410 int i;
411
412 for (i = 0; i < 3; i++)
413 securityfs_remove(lst[i]);
414}
This page took 2.602513 seconds and 5 git commands to generate.