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