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