]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/char/tpm/tpm_eventlog.c
HID: usbhid: Add HID_QUIRK_NOGET for Aten CS-1758 KVM switch
[mirror_ubuntu-artful-kernel.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>
2528a646 10 * Nayna Jain <nayna@linux.vnet.ibm.com>
55a82ab3 11 *
8e81cc13
KY
12 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
13 *
748935ee 14 * Access to the event log created by a system's firmware / BIOS
55a82ab3
KJH
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version
19 * 2 of the License, or (at your option) any later version.
20 *
21 */
22
23#include <linux/seq_file.h>
24#include <linux/fs.h>
25#include <linux/security.h>
26#include <linux/module.h>
5a0e3ad6 27#include <linux/slab.h>
55a82ab3 28
e5dcd87f
KY
29#include "tpm.h"
30#include "tpm_eventlog.h"
55a82ab3 31
55a82ab3
KJH
32
33static const char* tcpa_event_type_strings[] = {
34 "PREBOOT",
35 "POST CODE",
36 "",
37 "NO ACTION",
38 "SEPARATOR",
39 "ACTION",
40 "EVENT TAG",
41 "S-CRTM Contents",
42 "S-CRTM Version",
43 "CPU Microcode",
44 "Platform Config Flags",
45 "Table of Devices",
46 "Compact Hash",
47 "IPL",
48 "IPL Partition Data",
49 "Non-Host Code",
50 "Non-Host Config",
51 "Non-Host Info"
52};
53
55a82ab3 54static const char* tcpa_pc_event_id_strings[] = {
de66a695 55 "",
55a82ab3
KJH
56 "SMBIOS",
57 "BIS Certificate",
58 "POST BIOS ",
59 "ESCD ",
60 "CMOS",
61 "NVRAM",
62 "Option ROM",
63 "Option ROM config",
de66a695
SM
64 "",
65 "Option ROM microcode ",
55a82ab3 66 "S-CRTM Version",
de66a695
SM
67 "S-CRTM Contents ",
68 "POST Contents ",
69 "Table of Devices",
55a82ab3
KJH
70};
71
55a82ab3
KJH
72/* returns pointer to start of pos. entry of tcg log */
73static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
74{
75 loff_t i;
748935ee
NJ
76 struct tpm_chip *chip = m->private;
77 struct tpm_bios_log *log = &chip->log;
d09cf7d7
KJH
78 void *addr = log->bios_event_log;
79 void *limit = log->bios_event_log_end;
55a82ab3 80 struct tcpa_event *event;
0cc698af
HCVL
81 u32 converted_event_size;
82 u32 converted_event_type;
83
55a82ab3
KJH
84
85 /* read over *pos measurements */
86 for (i = 0; i < *pos; i++) {
87 event = addr;
88
0cc698af
HCVL
89 converted_event_size =
90 do_endian_conversion(event->event_size);
91 converted_event_type =
92 do_endian_conversion(event->event_type);
93
d09cf7d7 94 if ((addr + sizeof(struct tcpa_event)) < limit) {
0cc698af
HCVL
95 if ((converted_event_type == 0) &&
96 (converted_event_size == 0))
55a82ab3 97 return NULL;
0cc698af
HCVL
98 addr += (sizeof(struct tcpa_event) +
99 converted_event_size);
55a82ab3
KJH
100 }
101 }
102
103 /* now check if current entry is valid */
d09cf7d7 104 if ((addr + sizeof(struct tcpa_event)) >= limit)
55a82ab3
KJH
105 return NULL;
106
107 event = addr;
108
0cc698af
HCVL
109 converted_event_size = do_endian_conversion(event->event_size);
110 converted_event_type = do_endian_conversion(event->event_type);
111
112 if (((converted_event_type == 0) && (converted_event_size == 0))
113 || ((addr + sizeof(struct tcpa_event) + converted_event_size)
114 >= limit))
55a82ab3
KJH
115 return NULL;
116
117 return addr;
118}
119
120static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
121 loff_t *pos)
122{
123 struct tcpa_event *event = v;
748935ee
NJ
124 struct tpm_chip *chip = m->private;
125 struct tpm_bios_log *log = &chip->log;
d09cf7d7 126 void *limit = log->bios_event_log_end;
0cc698af
HCVL
127 u32 converted_event_size;
128 u32 converted_event_type;
55a82ab3 129
0cc698af
HCVL
130 converted_event_size = do_endian_conversion(event->event_size);
131
132 v += sizeof(struct tcpa_event) + converted_event_size;
55a82ab3
KJH
133
134 /* now check if current entry is valid */
d09cf7d7 135 if ((v + sizeof(struct tcpa_event)) >= limit)
55a82ab3
KJH
136 return NULL;
137
138 event = v;
139
0cc698af
HCVL
140 converted_event_size = do_endian_conversion(event->event_size);
141 converted_event_type = do_endian_conversion(event->event_type);
55a82ab3 142
0cc698af
HCVL
143 if (((converted_event_type == 0) && (converted_event_size == 0)) ||
144 ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit))
55a82ab3
KJH
145 return NULL;
146
147 (*pos)++;
148 return v;
149}
150
151static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
152{
153}
154
155static int get_event_name(char *dest, struct tcpa_event *event,
156 unsigned char * event_entry)
157{
158 const char *name = "";
fbaa5869
EP
159 /* 41 so there is room for 40 data and 1 nul */
160 char data[41] = "";
55a82ab3 161 int i, n_len = 0, d_len = 0;
de66a695 162 struct tcpa_pc_event *pc_event;
55a82ab3 163
0cc698af 164 switch (do_endian_conversion(event->event_type)) {
55a82ab3
KJH
165 case PREBOOT:
166 case POST_CODE:
167 case UNUSED:
168 case NO_ACTION:
169 case SCRTM_CONTENTS:
170 case SCRTM_VERSION:
171 case CPU_MICROCODE:
172 case PLATFORM_CONFIG_FLAGS:
173 case TABLE_OF_DEVICES:
174 case COMPACT_HASH:
175 case IPL:
176 case IPL_PARTITION_DATA:
177 case NONHOST_CODE:
178 case NONHOST_CONFIG:
179 case NONHOST_INFO:
0cc698af
HCVL
180 name = tcpa_event_type_strings[do_endian_conversion
181 (event->event_type)];
55a82ab3
KJH
182 n_len = strlen(name);
183 break;
184 case SEPARATOR:
185 case ACTION:
0cc698af
HCVL
186 if (MAX_TEXT_EVENT >
187 do_endian_conversion(event->event_size)) {
55a82ab3 188 name = event_entry;
0cc698af 189 n_len = do_endian_conversion(event->event_size);
55a82ab3
KJH
190 }
191 break;
192 case EVENT_TAG:
de66a695 193 pc_event = (struct tcpa_pc_event *)event_entry;
55a82ab3
KJH
194
195 /* ToDo Row data -> Base64 */
196
0cc698af 197 switch (do_endian_conversion(pc_event->event_id)) {
55a82ab3
KJH
198 case SMBIOS:
199 case BIS_CERT:
200 case CMOS:
201 case NVRAM:
202 case OPTION_ROM_EXEC:
203 case OPTION_ROM_CONFIG:
55a82ab3 204 case S_CRTM_VERSION:
0cc698af
HCVL
205 name = tcpa_pc_event_id_strings[do_endian_conversion
206 (pc_event->event_id)];
55a82ab3
KJH
207 n_len = strlen(name);
208 break;
de66a695 209 /* hash data */
55a82ab3
KJH
210 case POST_BIOS_ROM:
211 case ESCD:
de66a695
SM
212 case OPTION_ROM_MICROCODE:
213 case S_CRTM_CONTENTS:
214 case POST_CONTENTS:
0cc698af
HCVL
215 name = tcpa_pc_event_id_strings[do_endian_conversion
216 (pc_event->event_id)];
55a82ab3
KJH
217 n_len = strlen(name);
218 for (i = 0; i < 20; i++)
de66a695
SM
219 d_len += sprintf(&data[2*i], "%02x",
220 pc_event->event_data[i]);
55a82ab3
KJH
221 break;
222 default:
223 break;
224 }
225 default:
226 break;
227 }
228
229 return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
230 n_len, name, d_len, data);
231
232}
233
234static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
235{
44d7aff0 236 struct tcpa_event *event = v;
0cc698af 237 struct tcpa_event temp_event;
186d124f 238 char *temp_ptr;
44d7aff0 239 int i;
55a82ab3 240
0cc698af
HCVL
241 memcpy(&temp_event, event, sizeof(struct tcpa_event));
242
243 /* convert raw integers for endianness */
244 temp_event.pcr_index = do_endian_conversion(event->pcr_index);
245 temp_event.event_type = do_endian_conversion(event->event_type);
246 temp_event.event_size = do_endian_conversion(event->event_size);
247
186d124f 248 temp_ptr = (char *) &temp_event;
0cc698af 249
186d124f
HH
250 for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
251 seq_putc(m, temp_ptr[i]);
252
253 temp_ptr = (char *) v;
254
255 for (i = (sizeof(struct tcpa_event) - 1);
256 i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
257 seq_putc(m, temp_ptr[i]);
55a82ab3 258
55a82ab3 259 return 0;
0cc698af 260
55a82ab3
KJH
261}
262
263static int tpm_bios_measurements_release(struct inode *inode,
264 struct file *file)
265{
748935ee
NJ
266 struct seq_file *seq = (struct seq_file *)file->private_data;
267 struct tpm_chip *chip = (struct tpm_chip *)seq->private;
d09cf7d7 268
748935ee 269 put_device(&chip->dev);
d09cf7d7 270
55a82ab3
KJH
271 return seq_release(inode, file);
272}
273
274static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
275{
276 int len = 0;
55a82ab3
KJH
277 char *eventname;
278 struct tcpa_event *event = v;
279 unsigned char *event_entry =
0cc698af 280 (unsigned char *)(v + sizeof(struct tcpa_event));
55a82ab3
KJH
281
282 eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
283 if (!eventname) {
284 printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
285 __func__);
286 return -EFAULT;
287 }
288
0cc698af
HCVL
289 /* 1st: PCR */
290 seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index));
55a82ab3
KJH
291
292 /* 2nd: SHA1 */
a3d64df8 293 seq_printf(m, "%20phN", event->pcr_value);
55a82ab3
KJH
294
295 /* 3rd: event type identifier */
0cc698af 296 seq_printf(m, " %02x", do_endian_conversion(event->event_type));
55a82ab3
KJH
297
298 len += get_event_name(eventname, event, event_entry);
299
300 /* 4th: eventname <= max + \'0' delimiter */
301 seq_printf(m, " %s\n", eventname);
302
59e89f3a 303 kfree(eventname);
55a82ab3
KJH
304 return 0;
305}
306
2528a646 307static const struct seq_operations tpm_ascii_b_measurements_seqops = {
55a82ab3
KJH
308 .start = tpm_bios_measurements_start,
309 .next = tpm_bios_measurements_next,
310 .stop = tpm_bios_measurements_stop,
311 .show = tpm_ascii_bios_measurements_show,
312};
313
2528a646 314static const struct seq_operations tpm_binary_b_measurements_seqops = {
55a82ab3
KJH
315 .start = tpm_bios_measurements_start,
316 .next = tpm_bios_measurements_next,
317 .stop = tpm_bios_measurements_stop,
318 .show = tpm_binary_bios_measurements_show,
319};
320
2528a646 321static int tpm_bios_measurements_open(struct inode *inode,
55a82ab3
KJH
322 struct file *file)
323{
324 int err;
d09cf7d7 325 struct seq_file *seq;
748935ee
NJ
326 struct tpm_chip_seqops *chip_seqops;
327 const struct seq_operations *seqops;
328 struct tpm_chip *chip;
329
330 inode_lock(inode);
331 if (!inode->i_private) {
332 inode_unlock(inode);
333 return -ENODEV;
334 }
335 chip_seqops = (struct tpm_chip_seqops *)inode->i_private;
336 seqops = chip_seqops->seqops;
337 chip = chip_seqops->chip;
338 get_device(&chip->dev);
339 inode_unlock(inode);
55a82ab3
KJH
340
341 /* now register seq file */
2528a646 342 err = seq_open(file, seqops);
d09cf7d7
KJH
343 if (!err) {
344 seq = file->private_data;
748935ee 345 seq->private = chip;
d09cf7d7 346 }
178554ae 347
d09cf7d7 348 return err;
55a82ab3
KJH
349}
350
2528a646 351static const struct file_operations tpm_bios_measurements_ops = {
f40e68ef 352 .owner = THIS_MODULE,
2528a646 353 .open = tpm_bios_measurements_open,
55a82ab3
KJH
354 .read = seq_read,
355 .llseek = seq_lseek,
356 .release = tpm_bios_measurements_release,
357};
358
02ae1382
NJ
359static int tpm_read_log(struct tpm_chip *chip)
360{
361 int rc;
362
363 if (chip->log.bios_event_log != NULL) {
364 dev_dbg(&chip->dev,
365 "%s: ERROR - event log already initialized\n",
366 __func__);
367 return -EFAULT;
368 }
369
370 rc = tpm_read_log_acpi(chip);
0cf577a0 371 if (rc != -ENODEV)
02ae1382
NJ
372 return rc;
373
0cf577a0 374 return tpm_read_log_of(chip);
02ae1382
NJ
375}
376
0cf577a0
JG
377/*
378 * tpm_bios_log_setup() - Read the event log from the firmware
379 * @chip: TPM chip to use.
380 *
381 * If an event log is found then the securityfs files are setup to
382 * export it to userspace, otherwise nothing is done.
383 *
9430066a
JG
384 * Returns -ENODEV if the firmware has no event log or securityfs is not
385 * supported.
0cf577a0 386 */
cd9b7631 387int tpm_bios_log_setup(struct tpm_chip *chip)
ca4a031f 388{
cd9b7631
JS
389 const char *name = dev_name(&chip->dev);
390 unsigned int cnt;
748935ee 391 int rc = 0;
cd9b7631 392
7518a21a
JS
393 if (chip->flags & TPM_CHIP_FLAG_TPM2)
394 return 0;
395
02ae1382 396 rc = tpm_read_log(chip);
0cf577a0
JG
397 if (rc)
398 return rc;
748935ee 399
cd9b7631
JS
400 cnt = 0;
401 chip->bios_dir[cnt] = securityfs_create_dir(name, NULL);
402 /* NOTE: securityfs_create_dir can return ENODEV if securityfs is
403 * compiled out. The caller should ignore the ENODEV return code.
404 */
405 if (IS_ERR(chip->bios_dir[cnt]))
406 goto err;
407 cnt++;
408
748935ee
NJ
409 chip->bin_log_seqops.chip = chip;
410 chip->bin_log_seqops.seqops = &tpm_binary_b_measurements_seqops;
411
cd9b7631 412 chip->bios_dir[cnt] =
55a82ab3 413 securityfs_create_file("binary_bios_measurements",
cd9b7631 414 0440, chip->bios_dir[0],
748935ee 415 (void *)&chip->bin_log_seqops,
2528a646 416 &tpm_bios_measurements_ops);
cd9b7631
JS
417 if (IS_ERR(chip->bios_dir[cnt]))
418 goto err;
419 cnt++;
55a82ab3 420
748935ee
NJ
421 chip->ascii_log_seqops.chip = chip;
422 chip->ascii_log_seqops.seqops = &tpm_ascii_b_measurements_seqops;
423
cd9b7631 424 chip->bios_dir[cnt] =
55a82ab3 425 securityfs_create_file("ascii_bios_measurements",
cd9b7631 426 0440, chip->bios_dir[0],
748935ee 427 (void *)&chip->ascii_log_seqops,
2528a646 428 &tpm_bios_measurements_ops);
cd9b7631
JS
429 if (IS_ERR(chip->bios_dir[cnt]))
430 goto err;
431 cnt++;
55a82ab3 432
cd9b7631 433 return 0;
55a82ab3 434
cd9b7631 435err:
9430066a 436 rc = PTR_ERR(chip->bios_dir[cnt]);
cd9b7631
JS
437 chip->bios_dir[cnt] = NULL;
438 tpm_bios_log_teardown(chip);
9430066a 439 return rc;
55a82ab3 440}
55a82ab3 441
cd9b7631 442void tpm_bios_log_teardown(struct tpm_chip *chip)
55a82ab3
KJH
443{
444 int i;
748935ee 445 struct inode *inode;
55a82ab3 446
748935ee
NJ
447 /* securityfs_remove currently doesn't take care of handling sync
448 * between removal and opening of pseudo files. To handle this, a
449 * workaround is added by making i_private = NULL here during removal
450 * and to check it during open(), both within inode_lock()/unlock().
451 * This design ensures that open() either safely gets kref or fails.
452 */
453 for (i = (TPM_NUM_EVENT_LOG_FILES - 1); i >= 0; i--) {
005451d4
SB
454 if (chip->bios_dir[i]) {
455 inode = d_inode(chip->bios_dir[i]);
456 inode_lock(inode);
457 inode->i_private = NULL;
458 inode_unlock(inode);
459 securityfs_remove(chip->bios_dir[i]);
460 }
748935ee 461 }
55a82ab3 462}