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