Merge branch 'for-linus-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
[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 78 struct tcpa_event *event;
0cc698af
HCVL
79 u32 converted_event_size;
80 u32 converted_event_type;
81
55a82ab3
KJH
82
83 /* read over *pos measurements */
84 for (i = 0; i < *pos; i++) {
85 event = addr;
86
0cc698af
HCVL
87 converted_event_size =
88 do_endian_conversion(event->event_size);
89 converted_event_type =
90 do_endian_conversion(event->event_type);
91
d09cf7d7 92 if ((addr + sizeof(struct tcpa_event)) < limit) {
0cc698af
HCVL
93 if ((converted_event_type == 0) &&
94 (converted_event_size == 0))
55a82ab3 95 return NULL;
0cc698af
HCVL
96 addr += (sizeof(struct tcpa_event) +
97 converted_event_size);
55a82ab3
KJH
98 }
99 }
100
101 /* now check if current entry is valid */
d09cf7d7 102 if ((addr + sizeof(struct tcpa_event)) >= limit)
55a82ab3
KJH
103 return NULL;
104
105 event = addr;
106
0cc698af
HCVL
107 converted_event_size = do_endian_conversion(event->event_size);
108 converted_event_type = do_endian_conversion(event->event_type);
109
110 if (((converted_event_type == 0) && (converted_event_size == 0))
111 || ((addr + sizeof(struct tcpa_event) + converted_event_size)
112 >= limit))
55a82ab3
KJH
113 return NULL;
114
115 return addr;
116}
117
118static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
119 loff_t *pos)
120{
121 struct tcpa_event *event = v;
d09cf7d7
KJH
122 struct tpm_bios_log *log = m->private;
123 void *limit = log->bios_event_log_end;
0cc698af
HCVL
124 u32 converted_event_size;
125 u32 converted_event_type;
55a82ab3 126
0cc698af
HCVL
127 converted_event_size = do_endian_conversion(event->event_size);
128
129 v += sizeof(struct tcpa_event) + converted_event_size;
55a82ab3
KJH
130
131 /* now check if current entry is valid */
d09cf7d7 132 if ((v + sizeof(struct tcpa_event)) >= limit)
55a82ab3
KJH
133 return NULL;
134
135 event = v;
136
0cc698af
HCVL
137 converted_event_size = do_endian_conversion(event->event_size);
138 converted_event_type = do_endian_conversion(event->event_type);
55a82ab3 139
0cc698af
HCVL
140 if (((converted_event_type == 0) && (converted_event_size == 0)) ||
141 ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit))
55a82ab3
KJH
142 return NULL;
143
144 (*pos)++;
145 return v;
146}
147
148static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
149{
150}
151
152static int get_event_name(char *dest, struct tcpa_event *event,
153 unsigned char * event_entry)
154{
155 const char *name = "";
fbaa5869
EP
156 /* 41 so there is room for 40 data and 1 nul */
157 char data[41] = "";
55a82ab3 158 int i, n_len = 0, d_len = 0;
de66a695 159 struct tcpa_pc_event *pc_event;
55a82ab3 160
0cc698af 161 switch (do_endian_conversion(event->event_type)) {
55a82ab3
KJH
162 case PREBOOT:
163 case POST_CODE:
164 case UNUSED:
165 case NO_ACTION:
166 case SCRTM_CONTENTS:
167 case SCRTM_VERSION:
168 case CPU_MICROCODE:
169 case PLATFORM_CONFIG_FLAGS:
170 case TABLE_OF_DEVICES:
171 case COMPACT_HASH:
172 case IPL:
173 case IPL_PARTITION_DATA:
174 case NONHOST_CODE:
175 case NONHOST_CONFIG:
176 case NONHOST_INFO:
0cc698af
HCVL
177 name = tcpa_event_type_strings[do_endian_conversion
178 (event->event_type)];
55a82ab3
KJH
179 n_len = strlen(name);
180 break;
181 case SEPARATOR:
182 case ACTION:
0cc698af
HCVL
183 if (MAX_TEXT_EVENT >
184 do_endian_conversion(event->event_size)) {
55a82ab3 185 name = event_entry;
0cc698af 186 n_len = do_endian_conversion(event->event_size);
55a82ab3
KJH
187 }
188 break;
189 case EVENT_TAG:
de66a695 190 pc_event = (struct tcpa_pc_event *)event_entry;
55a82ab3
KJH
191
192 /* ToDo Row data -> Base64 */
193
0cc698af 194 switch (do_endian_conversion(pc_event->event_id)) {
55a82ab3
KJH
195 case SMBIOS:
196 case BIS_CERT:
197 case CMOS:
198 case NVRAM:
199 case OPTION_ROM_EXEC:
200 case OPTION_ROM_CONFIG:
55a82ab3 201 case S_CRTM_VERSION:
0cc698af
HCVL
202 name = tcpa_pc_event_id_strings[do_endian_conversion
203 (pc_event->event_id)];
55a82ab3
KJH
204 n_len = strlen(name);
205 break;
de66a695 206 /* hash data */
55a82ab3
KJH
207 case POST_BIOS_ROM:
208 case ESCD:
de66a695
SM
209 case OPTION_ROM_MICROCODE:
210 case S_CRTM_CONTENTS:
211 case POST_CONTENTS:
0cc698af
HCVL
212 name = tcpa_pc_event_id_strings[do_endian_conversion
213 (pc_event->event_id)];
55a82ab3
KJH
214 n_len = strlen(name);
215 for (i = 0; i < 20; i++)
de66a695
SM
216 d_len += sprintf(&data[2*i], "%02x",
217 pc_event->event_data[i]);
55a82ab3
KJH
218 break;
219 default:
220 break;
221 }
222 default:
223 break;
224 }
225
226 return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
227 n_len, name, d_len, data);
228
229}
230
231static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
232{
44d7aff0 233 struct tcpa_event *event = v;
0cc698af
HCVL
234 struct tcpa_event temp_event;
235 char *tempPtr;
44d7aff0 236 int i;
55a82ab3 237
0cc698af
HCVL
238 memcpy(&temp_event, event, sizeof(struct tcpa_event));
239
240 /* convert raw integers for endianness */
241 temp_event.pcr_index = do_endian_conversion(event->pcr_index);
242 temp_event.event_type = do_endian_conversion(event->event_type);
243 temp_event.event_size = do_endian_conversion(event->event_size);
244
245 tempPtr = (char *)&temp_event;
246
247 for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++)
248 seq_putc(m, tempPtr[i]);
55a82ab3 249
55a82ab3 250 return 0;
0cc698af 251
55a82ab3
KJH
252}
253
254static int tpm_bios_measurements_release(struct inode *inode,
255 struct file *file)
256{
d09cf7d7
KJH
257 struct seq_file *seq = file->private_data;
258 struct tpm_bios_log *log = seq->private;
259
260 if (log) {
261 kfree(log->bios_event_log);
262 kfree(log);
55a82ab3 263 }
d09cf7d7 264
55a82ab3
KJH
265 return seq_release(inode, file);
266}
267
268static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
269{
270 int len = 0;
55a82ab3
KJH
271 char *eventname;
272 struct tcpa_event *event = v;
273 unsigned char *event_entry =
0cc698af 274 (unsigned char *)(v + sizeof(struct tcpa_event));
55a82ab3
KJH
275
276 eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
277 if (!eventname) {
278 printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
279 __func__);
280 return -EFAULT;
281 }
282
0cc698af
HCVL
283 /* 1st: PCR */
284 seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index));
55a82ab3
KJH
285
286 /* 2nd: SHA1 */
a3d64df8 287 seq_printf(m, "%20phN", event->pcr_value);
55a82ab3
KJH
288
289 /* 3rd: event type identifier */
0cc698af 290 seq_printf(m, " %02x", do_endian_conversion(event->event_type));
55a82ab3
KJH
291
292 len += get_event_name(eventname, event, event_entry);
293
294 /* 4th: eventname <= max + \'0' delimiter */
295 seq_printf(m, " %s\n", eventname);
296
59e89f3a 297 kfree(eventname);
55a82ab3
KJH
298 return 0;
299}
300
88e9d34c 301static const struct seq_operations tpm_ascii_b_measurments_seqops = {
55a82ab3
KJH
302 .start = tpm_bios_measurements_start,
303 .next = tpm_bios_measurements_next,
304 .stop = tpm_bios_measurements_stop,
305 .show = tpm_ascii_bios_measurements_show,
306};
307
88e9d34c 308static const struct seq_operations tpm_binary_b_measurments_seqops = {
55a82ab3
KJH
309 .start = tpm_bios_measurements_start,
310 .next = tpm_bios_measurements_next,
311 .stop = tpm_bios_measurements_stop,
312 .show = tpm_binary_bios_measurements_show,
313};
314
55a82ab3
KJH
315static int tpm_ascii_bios_measurements_open(struct inode *inode,
316 struct file *file)
317{
318 int err;
d09cf7d7
KJH
319 struct tpm_bios_log *log;
320 struct seq_file *seq;
55a82ab3 321
d09cf7d7
KJH
322 log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
323 if (!log)
324 return -ENOMEM;
325
326 if ((err = read_log(log)))
178554ae 327 goto out_free;
55a82ab3
KJH
328
329 /* now register seq file */
d09cf7d7
KJH
330 err = seq_open(file, &tpm_ascii_b_measurments_seqops);
331 if (!err) {
332 seq = file->private_data;
333 seq->private = log;
334 } else {
178554ae 335 goto out_free;
d09cf7d7 336 }
178554ae
JJ
337
338out:
d09cf7d7 339 return err;
178554ae
JJ
340out_free:
341 kfree(log->bios_event_log);
342 kfree(log);
343 goto out;
55a82ab3
KJH
344}
345
3bd60464 346static const struct file_operations tpm_ascii_bios_measurements_ops = {
55a82ab3
KJH
347 .open = tpm_ascii_bios_measurements_open,
348 .read = seq_read,
349 .llseek = seq_lseek,
350 .release = tpm_bios_measurements_release,
351};
352
353static int tpm_binary_bios_measurements_open(struct inode *inode,
354 struct file *file)
355{
356 int err;
d09cf7d7
KJH
357 struct tpm_bios_log *log;
358 struct seq_file *seq;
55a82ab3 359
d09cf7d7
KJH
360 log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
361 if (!log)
362 return -ENOMEM;
363
364 if ((err = read_log(log)))
03ce1104 365 goto out_free;
55a82ab3
KJH
366
367 /* now register seq file */
d09cf7d7
KJH
368 err = seq_open(file, &tpm_binary_b_measurments_seqops);
369 if (!err) {
370 seq = file->private_data;
371 seq->private = log;
372 } else {
03ce1104 373 goto out_free;
d09cf7d7 374 }
03ce1104
RS
375
376out:
d09cf7d7 377 return err;
03ce1104
RS
378out_free:
379 kfree(log->bios_event_log);
380 kfree(log);
381 goto out;
55a82ab3
KJH
382}
383
3bd60464 384static const struct file_operations tpm_binary_bios_measurements_ops = {
55a82ab3
KJH
385 .open = tpm_binary_bios_measurements_open,
386 .read = seq_read,
387 .llseek = seq_lseek,
388 .release = tpm_bios_measurements_release,
389};
390
ca4a031f
AM
391static int is_bad(void *p)
392{
393 if (!p)
394 return 1;
395 if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
396 return 1;
397 return 0;
398}
399
55a82ab3
KJH
400struct dentry **tpm_bios_log_setup(char *name)
401{
402 struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
403
404 tpm_dir = securityfs_create_dir(name, NULL);
ca4a031f 405 if (is_bad(tpm_dir))
55a82ab3
KJH
406 goto out;
407
408 bin_file =
409 securityfs_create_file("binary_bios_measurements",
410 S_IRUSR | S_IRGRP, tpm_dir, NULL,
411 &tpm_binary_bios_measurements_ops);
ca4a031f 412 if (is_bad(bin_file))
55a82ab3
KJH
413 goto out_tpm;
414
415 ascii_file =
416 securityfs_create_file("ascii_bios_measurements",
417 S_IRUSR | S_IRGRP, tpm_dir, NULL,
418 &tpm_ascii_bios_measurements_ops);
ca4a031f 419 if (is_bad(ascii_file))
55a82ab3
KJH
420 goto out_bin;
421
422 ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
423 if (!ret)
424 goto out_ascii;
425
426 ret[0] = ascii_file;
427 ret[1] = bin_file;
428 ret[2] = tpm_dir;
429
430 return ret;
431
432out_ascii:
433 securityfs_remove(ascii_file);
434out_bin:
435 securityfs_remove(bin_file);
436out_tpm:
437 securityfs_remove(tpm_dir);
438out:
439 return NULL;
440}
55a82ab3
KJH
441
442void tpm_bios_log_teardown(struct dentry **lst)
443{
444 int i;
445
446 for (i = 0; i < 3; i++)
447 securityfs_remove(lst[i]);
448}
This page took 0.805663 seconds and 5 git commands to generate.