[PATCH] mark struct file_operations const 3
[deliverable/linux.git] / drivers / char / tpm / tpm_bios.c
1 /*
2 * Copyright (C) 2005 IBM Corporation
3 *
4 * Authors:
5 * Seiji Munetoh <munetoh@jp.ibm.com>
6 * Stefan Berger <stefanb@us.ibm.com>
7 * Reiner Sailer <sailer@watson.ibm.com>
8 * Kylene Hall <kjhall@us.ibm.com>
9 *
10 * Access to the eventlog extended by the TCG BIOS of PC platform
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 */
18
19 #include <linux/seq_file.h>
20 #include <linux/fs.h>
21 #include <linux/security.h>
22 #include <linux/module.h>
23 #include <acpi/acpi.h>
24 #include <acpi/actypes.h>
25 #include <acpi/actbl.h>
26 #include "tpm.h"
27
28 #define TCG_EVENT_NAME_LEN_MAX 255
29 #define MAX_TEXT_EVENT 1000 /* Max event string length */
30 #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
31
32 enum bios_platform_class {
33 BIOS_CLIENT = 0x00,
34 BIOS_SERVER = 0x01,
35 };
36
37 struct tpm_bios_log {
38 void *bios_event_log;
39 void *bios_event_log_end;
40 };
41
42 struct acpi_tcpa {
43 struct acpi_table_header hdr;
44 u16 platform_class;
45 union {
46 struct client_hdr {
47 u32 log_max_len __attribute__ ((packed));
48 u64 log_start_addr __attribute__ ((packed));
49 } client;
50 struct server_hdr {
51 u16 reserved;
52 u64 log_max_len __attribute__ ((packed));
53 u64 log_start_addr __attribute__ ((packed));
54 } server;
55 };
56 };
57
58 struct tcpa_event {
59 u32 pcr_index;
60 u32 event_type;
61 u8 pcr_value[20]; /* SHA1 */
62 u32 event_size;
63 u8 event_data[0];
64 };
65
66 enum tcpa_event_types {
67 PREBOOT = 0,
68 POST_CODE,
69 UNUSED,
70 NO_ACTION,
71 SEPARATOR,
72 ACTION,
73 EVENT_TAG,
74 SCRTM_CONTENTS,
75 SCRTM_VERSION,
76 CPU_MICROCODE,
77 PLATFORM_CONFIG_FLAGS,
78 TABLE_OF_DEVICES,
79 COMPACT_HASH,
80 IPL,
81 IPL_PARTITION_DATA,
82 NONHOST_CODE,
83 NONHOST_CONFIG,
84 NONHOST_INFO,
85 };
86
87 static const char* tcpa_event_type_strings[] = {
88 "PREBOOT",
89 "POST CODE",
90 "",
91 "NO ACTION",
92 "SEPARATOR",
93 "ACTION",
94 "EVENT TAG",
95 "S-CRTM Contents",
96 "S-CRTM Version",
97 "CPU Microcode",
98 "Platform Config Flags",
99 "Table of Devices",
100 "Compact Hash",
101 "IPL",
102 "IPL Partition Data",
103 "Non-Host Code",
104 "Non-Host Config",
105 "Non-Host Info"
106 };
107
108 struct tcpa_pc_event {
109 u32 event_id;
110 u32 event_size;
111 u8 event_data[0];
112 };
113
114 enum tcpa_pc_event_ids {
115 SMBIOS = 1,
116 BIS_CERT,
117 POST_BIOS_ROM,
118 ESCD,
119 CMOS,
120 NVRAM,
121 OPTION_ROM_EXEC,
122 OPTION_ROM_CONFIG,
123 OPTION_ROM_MICROCODE = 10,
124 S_CRTM_VERSION,
125 S_CRTM_CONTENTS,
126 POST_CONTENTS,
127 HOST_TABLE_OF_DEVICES,
128 };
129
130 static const char* tcpa_pc_event_id_strings[] = {
131 "",
132 "SMBIOS",
133 "BIS Certificate",
134 "POST BIOS ",
135 "ESCD ",
136 "CMOS",
137 "NVRAM",
138 "Option ROM",
139 "Option ROM config",
140 "",
141 "Option ROM microcode ",
142 "S-CRTM Version",
143 "S-CRTM Contents ",
144 "POST Contents ",
145 "Table of Devices",
146 };
147
148 /* returns pointer to start of pos. entry of tcg log */
149 static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
150 {
151 loff_t i;
152 struct tpm_bios_log *log = m->private;
153 void *addr = log->bios_event_log;
154 void *limit = log->bios_event_log_end;
155 struct tcpa_event *event;
156
157 /* read over *pos measurements */
158 for (i = 0; i < *pos; i++) {
159 event = addr;
160
161 if ((addr + sizeof(struct tcpa_event)) < limit) {
162 if (event->event_type == 0 && event->event_size == 0)
163 return NULL;
164 addr += sizeof(struct tcpa_event) + event->event_size;
165 }
166 }
167
168 /* now check if current entry is valid */
169 if ((addr + sizeof(struct tcpa_event)) >= limit)
170 return NULL;
171
172 event = addr;
173
174 if ((event->event_type == 0 && event->event_size == 0) ||
175 ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
176 return NULL;
177
178 return addr;
179 }
180
181 static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
182 loff_t *pos)
183 {
184 struct tcpa_event *event = v;
185 struct tpm_bios_log *log = m->private;
186 void *limit = log->bios_event_log_end;
187
188 v += sizeof(struct tcpa_event) + event->event_size;
189
190 /* now check if current entry is valid */
191 if ((v + sizeof(struct tcpa_event)) >= limit)
192 return NULL;
193
194 event = v;
195
196 if (event->event_type == 0 && event->event_size == 0)
197 return NULL;
198
199 if ((event->event_type == 0 && event->event_size == 0) ||
200 ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
201 return NULL;
202
203 (*pos)++;
204 return v;
205 }
206
207 static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
208 {
209 }
210
211 static int get_event_name(char *dest, struct tcpa_event *event,
212 unsigned char * event_entry)
213 {
214 const char *name = "";
215 char data[40] = "";
216 int i, n_len = 0, d_len = 0;
217 struct tcpa_pc_event *pc_event;
218
219 switch(event->event_type) {
220 case PREBOOT:
221 case POST_CODE:
222 case UNUSED:
223 case NO_ACTION:
224 case SCRTM_CONTENTS:
225 case SCRTM_VERSION:
226 case CPU_MICROCODE:
227 case PLATFORM_CONFIG_FLAGS:
228 case TABLE_OF_DEVICES:
229 case COMPACT_HASH:
230 case IPL:
231 case IPL_PARTITION_DATA:
232 case NONHOST_CODE:
233 case NONHOST_CONFIG:
234 case NONHOST_INFO:
235 name = tcpa_event_type_strings[event->event_type];
236 n_len = strlen(name);
237 break;
238 case SEPARATOR:
239 case ACTION:
240 if (MAX_TEXT_EVENT > event->event_size) {
241 name = event_entry;
242 n_len = event->event_size;
243 }
244 break;
245 case EVENT_TAG:
246 pc_event = (struct tcpa_pc_event *)event_entry;
247
248 /* ToDo Row data -> Base64 */
249
250 switch (pc_event->event_id) {
251 case SMBIOS:
252 case BIS_CERT:
253 case CMOS:
254 case NVRAM:
255 case OPTION_ROM_EXEC:
256 case OPTION_ROM_CONFIG:
257 case S_CRTM_VERSION:
258 name = tcpa_pc_event_id_strings[pc_event->event_id];
259 n_len = strlen(name);
260 break;
261 /* hash data */
262 case POST_BIOS_ROM:
263 case ESCD:
264 case OPTION_ROM_MICROCODE:
265 case S_CRTM_CONTENTS:
266 case POST_CONTENTS:
267 name = tcpa_pc_event_id_strings[pc_event->event_id];
268 n_len = strlen(name);
269 for (i = 0; i < 20; i++)
270 d_len += sprintf(&data[2*i], "%02x",
271 pc_event->event_data[i]);
272 break;
273 default:
274 break;
275 }
276 default:
277 break;
278 }
279
280 return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
281 n_len, name, d_len, data);
282
283 }
284
285 static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
286 {
287 struct tcpa_event *event = v;
288 char *data = v;
289 int i;
290
291 for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
292 seq_putc(m, data[i]);
293
294 return 0;
295 }
296
297 static int tpm_bios_measurements_release(struct inode *inode,
298 struct file *file)
299 {
300 struct seq_file *seq = file->private_data;
301 struct tpm_bios_log *log = seq->private;
302
303 if (log) {
304 kfree(log->bios_event_log);
305 kfree(log);
306 }
307
308 return seq_release(inode, file);
309 }
310
311 static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
312 {
313 int len = 0;
314 int i;
315 char *eventname;
316 struct tcpa_event *event = v;
317 unsigned char *event_entry =
318 (unsigned char *) (v + sizeof(struct tcpa_event));
319
320 eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
321 if (!eventname) {
322 printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
323 __func__);
324 return -EFAULT;
325 }
326
327 seq_printf(m, "%2d ", event->pcr_index);
328
329 /* 2nd: SHA1 */
330 for (i = 0; i < 20; i++)
331 seq_printf(m, "%02x", event->pcr_value[i]);
332
333 /* 3rd: event type identifier */
334 seq_printf(m, " %02x", event->event_type);
335
336 len += get_event_name(eventname, event, event_entry);
337
338 /* 4th: eventname <= max + \'0' delimiter */
339 seq_printf(m, " %s\n", eventname);
340
341 kfree(eventname);
342 return 0;
343 }
344
345 static struct seq_operations tpm_ascii_b_measurments_seqops = {
346 .start = tpm_bios_measurements_start,
347 .next = tpm_bios_measurements_next,
348 .stop = tpm_bios_measurements_stop,
349 .show = tpm_ascii_bios_measurements_show,
350 };
351
352 static struct seq_operations tpm_binary_b_measurments_seqops = {
353 .start = tpm_bios_measurements_start,
354 .next = tpm_bios_measurements_next,
355 .stop = tpm_bios_measurements_stop,
356 .show = tpm_binary_bios_measurements_show,
357 };
358
359 /* read binary bios log */
360 static int read_log(struct tpm_bios_log *log)
361 {
362 struct acpi_tcpa *buff;
363 acpi_status status;
364 struct acpi_table_header *virt;
365 u64 len, start;
366
367 if (log->bios_event_log != NULL) {
368 printk(KERN_ERR
369 "%s: ERROR - Eventlog already initialized\n",
370 __func__);
371 return -EFAULT;
372 }
373
374 /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
375 status = acpi_get_table(ACPI_SIG_TCPA, 1,
376 (struct acpi_table_header **)&buff);
377
378 if (ACPI_FAILURE(status)) {
379 printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
380 __func__);
381 return -EIO;
382 }
383
384 switch(buff->platform_class) {
385 case BIOS_SERVER:
386 len = buff->server.log_max_len;
387 start = buff->server.log_start_addr;
388 break;
389 case BIOS_CLIENT:
390 default:
391 len = buff->client.log_max_len;
392 start = buff->client.log_start_addr;
393 break;
394 }
395 if (!len) {
396 printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
397 return -EIO;
398 }
399
400 /* malloc EventLog space */
401 log->bios_event_log = kmalloc(len, GFP_KERNEL);
402 if (!log->bios_event_log) {
403 printk("%s: ERROR - Not enough Memory for BIOS measurements\n",
404 __func__);
405 return -ENOMEM;
406 }
407
408 log->bios_event_log_end = log->bios_event_log + len;
409
410 virt = acpi_os_map_memory(start, len);
411
412 memcpy(log->bios_event_log, virt, len);
413
414 acpi_os_unmap_memory(virt, len);
415 return 0;
416 }
417
418 static int tpm_ascii_bios_measurements_open(struct inode *inode,
419 struct file *file)
420 {
421 int err;
422 struct tpm_bios_log *log;
423 struct seq_file *seq;
424
425 log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
426 if (!log)
427 return -ENOMEM;
428
429 if ((err = read_log(log)))
430 return err;
431
432 /* now register seq file */
433 err = seq_open(file, &tpm_ascii_b_measurments_seqops);
434 if (!err) {
435 seq = file->private_data;
436 seq->private = log;
437 } else {
438 kfree(log->bios_event_log);
439 kfree(log);
440 }
441 return err;
442 }
443
444 const struct file_operations tpm_ascii_bios_measurements_ops = {
445 .open = tpm_ascii_bios_measurements_open,
446 .read = seq_read,
447 .llseek = seq_lseek,
448 .release = tpm_bios_measurements_release,
449 };
450
451 static int tpm_binary_bios_measurements_open(struct inode *inode,
452 struct file *file)
453 {
454 int err;
455 struct tpm_bios_log *log;
456 struct seq_file *seq;
457
458 log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
459 if (!log)
460 return -ENOMEM;
461
462 if ((err = read_log(log)))
463 return err;
464
465 /* now register seq file */
466 err = seq_open(file, &tpm_binary_b_measurments_seqops);
467 if (!err) {
468 seq = file->private_data;
469 seq->private = log;
470 } else {
471 kfree(log->bios_event_log);
472 kfree(log);
473 }
474 return err;
475 }
476
477 const struct file_operations tpm_binary_bios_measurements_ops = {
478 .open = tpm_binary_bios_measurements_open,
479 .read = seq_read,
480 .llseek = seq_lseek,
481 .release = tpm_bios_measurements_release,
482 };
483
484 static int is_bad(void *p)
485 {
486 if (!p)
487 return 1;
488 if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
489 return 1;
490 return 0;
491 }
492
493 struct dentry **tpm_bios_log_setup(char *name)
494 {
495 struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
496
497 tpm_dir = securityfs_create_dir(name, NULL);
498 if (is_bad(tpm_dir))
499 goto out;
500
501 bin_file =
502 securityfs_create_file("binary_bios_measurements",
503 S_IRUSR | S_IRGRP, tpm_dir, NULL,
504 &tpm_binary_bios_measurements_ops);
505 if (is_bad(bin_file))
506 goto out_tpm;
507
508 ascii_file =
509 securityfs_create_file("ascii_bios_measurements",
510 S_IRUSR | S_IRGRP, tpm_dir, NULL,
511 &tpm_ascii_bios_measurements_ops);
512 if (is_bad(ascii_file))
513 goto out_bin;
514
515 ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
516 if (!ret)
517 goto out_ascii;
518
519 ret[0] = ascii_file;
520 ret[1] = bin_file;
521 ret[2] = tpm_dir;
522
523 return ret;
524
525 out_ascii:
526 securityfs_remove(ascii_file);
527 out_bin:
528 securityfs_remove(bin_file);
529 out_tpm:
530 securityfs_remove(tpm_dir);
531 out:
532 return NULL;
533 }
534 EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
535
536 void tpm_bios_log_teardown(struct dentry **lst)
537 {
538 int i;
539
540 for (i = 0; i < 3; i++)
541 securityfs_remove(lst[i]);
542 }
543 EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
544 MODULE_LICENSE("GPL");
This page took 0.052782 seconds and 5 git commands to generate.