xref: /linux/drivers/char/tpm/eventlog/tpm1.c (revision 9b01b53566298812cb38a2e72d034ac8131c20d6)
10bfb2374SThiebaud Weksteen /*
20bfb2374SThiebaud Weksteen  * Copyright (C) 2005, 2012 IBM Corporation
30bfb2374SThiebaud Weksteen  *
40bfb2374SThiebaud Weksteen  * Authors:
50bfb2374SThiebaud Weksteen  *	Kent Yoder <key@linux.vnet.ibm.com>
60bfb2374SThiebaud Weksteen  *	Seiji Munetoh <munetoh@jp.ibm.com>
70bfb2374SThiebaud Weksteen  *	Stefan Berger <stefanb@us.ibm.com>
80bfb2374SThiebaud Weksteen  *	Reiner Sailer <sailer@watson.ibm.com>
90bfb2374SThiebaud Weksteen  *	Kylene Hall <kjhall@us.ibm.com>
100bfb2374SThiebaud Weksteen  *	Nayna Jain <nayna@linux.vnet.ibm.com>
110bfb2374SThiebaud Weksteen  *
120bfb2374SThiebaud Weksteen  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
130bfb2374SThiebaud Weksteen  *
140bfb2374SThiebaud Weksteen  * Access to the event log created by a system's firmware / BIOS
150bfb2374SThiebaud Weksteen  *
160bfb2374SThiebaud Weksteen  * This program is free software; you can redistribute it and/or
170bfb2374SThiebaud Weksteen  * modify it under the terms of the GNU General Public License
180bfb2374SThiebaud Weksteen  * as published by the Free Software Foundation; either version
190bfb2374SThiebaud Weksteen  * 2 of the License, or (at your option) any later version.
200bfb2374SThiebaud Weksteen  *
210bfb2374SThiebaud Weksteen  */
220bfb2374SThiebaud Weksteen 
230bfb2374SThiebaud Weksteen #include <linux/seq_file.h>
240bfb2374SThiebaud Weksteen #include <linux/efi.h>
250bfb2374SThiebaud Weksteen #include <linux/fs.h>
260bfb2374SThiebaud Weksteen #include <linux/security.h>
270bfb2374SThiebaud Weksteen #include <linux/module.h>
280bfb2374SThiebaud Weksteen #include <linux/slab.h>
290bfb2374SThiebaud Weksteen #include <linux/tpm_eventlog.h>
300bfb2374SThiebaud Weksteen 
310bfb2374SThiebaud Weksteen #include "../tpm.h"
320bfb2374SThiebaud Weksteen 
330bfb2374SThiebaud Weksteen 
340bfb2374SThiebaud Weksteen static const char* tcpa_event_type_strings[] = {
350bfb2374SThiebaud Weksteen 	"PREBOOT",
360bfb2374SThiebaud Weksteen 	"POST CODE",
370bfb2374SThiebaud Weksteen 	"",
380bfb2374SThiebaud Weksteen 	"NO ACTION",
390bfb2374SThiebaud Weksteen 	"SEPARATOR",
400bfb2374SThiebaud Weksteen 	"ACTION",
410bfb2374SThiebaud Weksteen 	"EVENT TAG",
420bfb2374SThiebaud Weksteen 	"S-CRTM Contents",
430bfb2374SThiebaud Weksteen 	"S-CRTM Version",
440bfb2374SThiebaud Weksteen 	"CPU Microcode",
450bfb2374SThiebaud Weksteen 	"Platform Config Flags",
460bfb2374SThiebaud Weksteen 	"Table of Devices",
470bfb2374SThiebaud Weksteen 	"Compact Hash",
480bfb2374SThiebaud Weksteen 	"IPL",
490bfb2374SThiebaud Weksteen 	"IPL Partition Data",
500bfb2374SThiebaud Weksteen 	"Non-Host Code",
510bfb2374SThiebaud Weksteen 	"Non-Host Config",
520bfb2374SThiebaud Weksteen 	"Non-Host Info"
530bfb2374SThiebaud Weksteen };
540bfb2374SThiebaud Weksteen 
550bfb2374SThiebaud Weksteen static const char* tcpa_pc_event_id_strings[] = {
560bfb2374SThiebaud Weksteen 	"",
570bfb2374SThiebaud Weksteen 	"SMBIOS",
580bfb2374SThiebaud Weksteen 	"BIS Certificate",
590bfb2374SThiebaud Weksteen 	"POST BIOS ",
600bfb2374SThiebaud Weksteen 	"ESCD ",
610bfb2374SThiebaud Weksteen 	"CMOS",
620bfb2374SThiebaud Weksteen 	"NVRAM",
630bfb2374SThiebaud Weksteen 	"Option ROM",
640bfb2374SThiebaud Weksteen 	"Option ROM config",
650bfb2374SThiebaud Weksteen 	"",
660bfb2374SThiebaud Weksteen 	"Option ROM microcode ",
670bfb2374SThiebaud Weksteen 	"S-CRTM Version",
680bfb2374SThiebaud Weksteen 	"S-CRTM Contents ",
690bfb2374SThiebaud Weksteen 	"POST Contents ",
700bfb2374SThiebaud Weksteen 	"Table of Devices",
710bfb2374SThiebaud Weksteen };
720bfb2374SThiebaud Weksteen 
730bfb2374SThiebaud Weksteen /* returns pointer to start of pos. entry of tcg log */
74*9b01b535SThiebaud Weksteen static void *tpm1_bios_measurements_start(struct seq_file *m, loff_t *pos)
750bfb2374SThiebaud Weksteen {
760bfb2374SThiebaud Weksteen 	loff_t i;
770bfb2374SThiebaud Weksteen 	struct tpm_chip *chip = m->private;
780bfb2374SThiebaud Weksteen 	struct tpm_bios_log *log = &chip->log;
790bfb2374SThiebaud Weksteen 	void *addr = log->bios_event_log;
800bfb2374SThiebaud Weksteen 	void *limit = log->bios_event_log_end;
810bfb2374SThiebaud Weksteen 	struct tcpa_event *event;
820bfb2374SThiebaud Weksteen 	u32 converted_event_size;
830bfb2374SThiebaud Weksteen 	u32 converted_event_type;
840bfb2374SThiebaud Weksteen 
850bfb2374SThiebaud Weksteen 
860bfb2374SThiebaud Weksteen 	/* read over *pos measurements */
870bfb2374SThiebaud Weksteen 	for (i = 0; i < *pos; i++) {
880bfb2374SThiebaud Weksteen 		event = addr;
890bfb2374SThiebaud Weksteen 
900bfb2374SThiebaud Weksteen 		converted_event_size =
910bfb2374SThiebaud Weksteen 		    do_endian_conversion(event->event_size);
920bfb2374SThiebaud Weksteen 		converted_event_type =
930bfb2374SThiebaud Weksteen 		    do_endian_conversion(event->event_type);
940bfb2374SThiebaud Weksteen 
950bfb2374SThiebaud Weksteen 		if ((addr + sizeof(struct tcpa_event)) < limit) {
960bfb2374SThiebaud Weksteen 			if ((converted_event_type == 0) &&
970bfb2374SThiebaud Weksteen 			    (converted_event_size == 0))
980bfb2374SThiebaud Weksteen 				return NULL;
990bfb2374SThiebaud Weksteen 			addr += (sizeof(struct tcpa_event) +
1000bfb2374SThiebaud Weksteen 				 converted_event_size);
1010bfb2374SThiebaud Weksteen 		}
1020bfb2374SThiebaud Weksteen 	}
1030bfb2374SThiebaud Weksteen 
1040bfb2374SThiebaud Weksteen 	/* now check if current entry is valid */
1050bfb2374SThiebaud Weksteen 	if ((addr + sizeof(struct tcpa_event)) >= limit)
1060bfb2374SThiebaud Weksteen 		return NULL;
1070bfb2374SThiebaud Weksteen 
1080bfb2374SThiebaud Weksteen 	event = addr;
1090bfb2374SThiebaud Weksteen 
1100bfb2374SThiebaud Weksteen 	converted_event_size = do_endian_conversion(event->event_size);
1110bfb2374SThiebaud Weksteen 	converted_event_type = do_endian_conversion(event->event_type);
1120bfb2374SThiebaud Weksteen 
1130bfb2374SThiebaud Weksteen 	if (((converted_event_type == 0) && (converted_event_size == 0))
1140bfb2374SThiebaud Weksteen 	    || ((addr + sizeof(struct tcpa_event) + converted_event_size)
1150bfb2374SThiebaud Weksteen 		>= limit))
1160bfb2374SThiebaud Weksteen 		return NULL;
1170bfb2374SThiebaud Weksteen 
1180bfb2374SThiebaud Weksteen 	return addr;
1190bfb2374SThiebaud Weksteen }
1200bfb2374SThiebaud Weksteen 
121*9b01b535SThiebaud Weksteen static void *tpm1_bios_measurements_next(struct seq_file *m, void *v,
1220bfb2374SThiebaud Weksteen 					loff_t *pos)
1230bfb2374SThiebaud Weksteen {
1240bfb2374SThiebaud Weksteen 	struct tcpa_event *event = v;
1250bfb2374SThiebaud Weksteen 	struct tpm_chip *chip = m->private;
1260bfb2374SThiebaud Weksteen 	struct tpm_bios_log *log = &chip->log;
1270bfb2374SThiebaud Weksteen 	void *limit = log->bios_event_log_end;
1280bfb2374SThiebaud Weksteen 	u32 converted_event_size;
1290bfb2374SThiebaud Weksteen 	u32 converted_event_type;
1300bfb2374SThiebaud Weksteen 
1310bfb2374SThiebaud Weksteen 	converted_event_size = do_endian_conversion(event->event_size);
1320bfb2374SThiebaud Weksteen 
1330bfb2374SThiebaud Weksteen 	v += sizeof(struct tcpa_event) + converted_event_size;
1340bfb2374SThiebaud Weksteen 
1350bfb2374SThiebaud Weksteen 	/* now check if current entry is valid */
1360bfb2374SThiebaud Weksteen 	if ((v + sizeof(struct tcpa_event)) >= limit)
1370bfb2374SThiebaud Weksteen 		return NULL;
1380bfb2374SThiebaud Weksteen 
1390bfb2374SThiebaud Weksteen 	event = v;
1400bfb2374SThiebaud Weksteen 
1410bfb2374SThiebaud Weksteen 	converted_event_size = do_endian_conversion(event->event_size);
1420bfb2374SThiebaud Weksteen 	converted_event_type = do_endian_conversion(event->event_type);
1430bfb2374SThiebaud Weksteen 
1440bfb2374SThiebaud Weksteen 	if (((converted_event_type == 0) && (converted_event_size == 0)) ||
1450bfb2374SThiebaud Weksteen 	    ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit))
1460bfb2374SThiebaud Weksteen 		return NULL;
1470bfb2374SThiebaud Weksteen 
1480bfb2374SThiebaud Weksteen 	(*pos)++;
1490bfb2374SThiebaud Weksteen 	return v;
1500bfb2374SThiebaud Weksteen }
1510bfb2374SThiebaud Weksteen 
152*9b01b535SThiebaud Weksteen static void tpm1_bios_measurements_stop(struct seq_file *m, void *v)
1530bfb2374SThiebaud Weksteen {
1540bfb2374SThiebaud Weksteen }
1550bfb2374SThiebaud Weksteen 
1560bfb2374SThiebaud Weksteen static int get_event_name(char *dest, struct tcpa_event *event,
1570bfb2374SThiebaud Weksteen 			unsigned char * event_entry)
1580bfb2374SThiebaud Weksteen {
1590bfb2374SThiebaud Weksteen 	const char *name = "";
1600bfb2374SThiebaud Weksteen 	/* 41 so there is room for 40 data and 1 nul */
1610bfb2374SThiebaud Weksteen 	char data[41] = "";
1620bfb2374SThiebaud Weksteen 	int i, n_len = 0, d_len = 0;
1630bfb2374SThiebaud Weksteen 	struct tcpa_pc_event *pc_event;
1640bfb2374SThiebaud Weksteen 
1650bfb2374SThiebaud Weksteen 	switch (do_endian_conversion(event->event_type)) {
1660bfb2374SThiebaud Weksteen 	case PREBOOT:
1670bfb2374SThiebaud Weksteen 	case POST_CODE:
1680bfb2374SThiebaud Weksteen 	case UNUSED:
1690bfb2374SThiebaud Weksteen 	case NO_ACTION:
1700bfb2374SThiebaud Weksteen 	case SCRTM_CONTENTS:
1710bfb2374SThiebaud Weksteen 	case SCRTM_VERSION:
1720bfb2374SThiebaud Weksteen 	case CPU_MICROCODE:
1730bfb2374SThiebaud Weksteen 	case PLATFORM_CONFIG_FLAGS:
1740bfb2374SThiebaud Weksteen 	case TABLE_OF_DEVICES:
1750bfb2374SThiebaud Weksteen 	case COMPACT_HASH:
1760bfb2374SThiebaud Weksteen 	case IPL:
1770bfb2374SThiebaud Weksteen 	case IPL_PARTITION_DATA:
1780bfb2374SThiebaud Weksteen 	case NONHOST_CODE:
1790bfb2374SThiebaud Weksteen 	case NONHOST_CONFIG:
1800bfb2374SThiebaud Weksteen 	case NONHOST_INFO:
1810bfb2374SThiebaud Weksteen 		name = tcpa_event_type_strings[do_endian_conversion
1820bfb2374SThiebaud Weksteen 						(event->event_type)];
1830bfb2374SThiebaud Weksteen 		n_len = strlen(name);
1840bfb2374SThiebaud Weksteen 		break;
1850bfb2374SThiebaud Weksteen 	case SEPARATOR:
1860bfb2374SThiebaud Weksteen 	case ACTION:
1870bfb2374SThiebaud Weksteen 		if (MAX_TEXT_EVENT >
1880bfb2374SThiebaud Weksteen 		    do_endian_conversion(event->event_size)) {
1890bfb2374SThiebaud Weksteen 			name = event_entry;
1900bfb2374SThiebaud Weksteen 			n_len = do_endian_conversion(event->event_size);
1910bfb2374SThiebaud Weksteen 		}
1920bfb2374SThiebaud Weksteen 		break;
1930bfb2374SThiebaud Weksteen 	case EVENT_TAG:
1940bfb2374SThiebaud Weksteen 		pc_event = (struct tcpa_pc_event *)event_entry;
1950bfb2374SThiebaud Weksteen 
1960bfb2374SThiebaud Weksteen 		/* ToDo Row data -> Base64 */
1970bfb2374SThiebaud Weksteen 
1980bfb2374SThiebaud Weksteen 		switch (do_endian_conversion(pc_event->event_id)) {
1990bfb2374SThiebaud Weksteen 		case SMBIOS:
2000bfb2374SThiebaud Weksteen 		case BIS_CERT:
2010bfb2374SThiebaud Weksteen 		case CMOS:
2020bfb2374SThiebaud Weksteen 		case NVRAM:
2030bfb2374SThiebaud Weksteen 		case OPTION_ROM_EXEC:
2040bfb2374SThiebaud Weksteen 		case OPTION_ROM_CONFIG:
2050bfb2374SThiebaud Weksteen 		case S_CRTM_VERSION:
2060bfb2374SThiebaud Weksteen 			name = tcpa_pc_event_id_strings[do_endian_conversion
2070bfb2374SThiebaud Weksteen 							(pc_event->event_id)];
2080bfb2374SThiebaud Weksteen 			n_len = strlen(name);
2090bfb2374SThiebaud Weksteen 			break;
2100bfb2374SThiebaud Weksteen 		/* hash data */
2110bfb2374SThiebaud Weksteen 		case POST_BIOS_ROM:
2120bfb2374SThiebaud Weksteen 		case ESCD:
2130bfb2374SThiebaud Weksteen 		case OPTION_ROM_MICROCODE:
2140bfb2374SThiebaud Weksteen 		case S_CRTM_CONTENTS:
2150bfb2374SThiebaud Weksteen 		case POST_CONTENTS:
2160bfb2374SThiebaud Weksteen 			name = tcpa_pc_event_id_strings[do_endian_conversion
2170bfb2374SThiebaud Weksteen 							(pc_event->event_id)];
2180bfb2374SThiebaud Weksteen 			n_len = strlen(name);
2190bfb2374SThiebaud Weksteen 			for (i = 0; i < 20; i++)
2200bfb2374SThiebaud Weksteen 				d_len += sprintf(&data[2*i], "%02x",
2210bfb2374SThiebaud Weksteen 						pc_event->event_data[i]);
2220bfb2374SThiebaud Weksteen 			break;
2230bfb2374SThiebaud Weksteen 		default:
2240bfb2374SThiebaud Weksteen 			break;
2250bfb2374SThiebaud Weksteen 		}
2260bfb2374SThiebaud Weksteen 	default:
2270bfb2374SThiebaud Weksteen 		break;
2280bfb2374SThiebaud Weksteen 	}
2290bfb2374SThiebaud Weksteen 
2300bfb2374SThiebaud Weksteen 	return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
2310bfb2374SThiebaud Weksteen 			n_len, name, d_len, data);
2320bfb2374SThiebaud Weksteen 
2330bfb2374SThiebaud Weksteen }
2340bfb2374SThiebaud Weksteen 
235*9b01b535SThiebaud Weksteen static int tpm1_binary_bios_measurements_show(struct seq_file *m, void *v)
2360bfb2374SThiebaud Weksteen {
2370bfb2374SThiebaud Weksteen 	struct tcpa_event *event = v;
2380bfb2374SThiebaud Weksteen 	struct tcpa_event temp_event;
2390bfb2374SThiebaud Weksteen 	char *temp_ptr;
2400bfb2374SThiebaud Weksteen 	int i;
2410bfb2374SThiebaud Weksteen 
2420bfb2374SThiebaud Weksteen 	memcpy(&temp_event, event, sizeof(struct tcpa_event));
2430bfb2374SThiebaud Weksteen 
2440bfb2374SThiebaud Weksteen 	/* convert raw integers for endianness */
2450bfb2374SThiebaud Weksteen 	temp_event.pcr_index = do_endian_conversion(event->pcr_index);
2460bfb2374SThiebaud Weksteen 	temp_event.event_type = do_endian_conversion(event->event_type);
2470bfb2374SThiebaud Weksteen 	temp_event.event_size = do_endian_conversion(event->event_size);
2480bfb2374SThiebaud Weksteen 
2490bfb2374SThiebaud Weksteen 	temp_ptr = (char *) &temp_event;
2500bfb2374SThiebaud Weksteen 
2510bfb2374SThiebaud Weksteen 	for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
2520bfb2374SThiebaud Weksteen 		seq_putc(m, temp_ptr[i]);
2530bfb2374SThiebaud Weksteen 
2540bfb2374SThiebaud Weksteen 	temp_ptr = (char *) v;
2550bfb2374SThiebaud Weksteen 
2560bfb2374SThiebaud Weksteen 	for (i = (sizeof(struct tcpa_event) - 1);
2570bfb2374SThiebaud Weksteen 	     i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
2580bfb2374SThiebaud Weksteen 		seq_putc(m, temp_ptr[i]);
2590bfb2374SThiebaud Weksteen 
2600bfb2374SThiebaud Weksteen 	return 0;
2610bfb2374SThiebaud Weksteen 
2620bfb2374SThiebaud Weksteen }
2630bfb2374SThiebaud Weksteen 
264*9b01b535SThiebaud Weksteen static int tpm1_ascii_bios_measurements_show(struct seq_file *m, void *v)
2650bfb2374SThiebaud Weksteen {
2660bfb2374SThiebaud Weksteen 	int len = 0;
2670bfb2374SThiebaud Weksteen 	char *eventname;
2680bfb2374SThiebaud Weksteen 	struct tcpa_event *event = v;
2690bfb2374SThiebaud Weksteen 	unsigned char *event_entry =
2700bfb2374SThiebaud Weksteen 	    (unsigned char *)(v + sizeof(struct tcpa_event));
2710bfb2374SThiebaud Weksteen 
2720bfb2374SThiebaud Weksteen 	eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
2730bfb2374SThiebaud Weksteen 	if (!eventname) {
2740bfb2374SThiebaud Weksteen 		printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
2750bfb2374SThiebaud Weksteen 		       __func__);
2760bfb2374SThiebaud Weksteen 		return -EFAULT;
2770bfb2374SThiebaud Weksteen 	}
2780bfb2374SThiebaud Weksteen 
2790bfb2374SThiebaud Weksteen 	/* 1st: PCR */
2800bfb2374SThiebaud Weksteen 	seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index));
2810bfb2374SThiebaud Weksteen 
2820bfb2374SThiebaud Weksteen 	/* 2nd: SHA1 */
2830bfb2374SThiebaud Weksteen 	seq_printf(m, "%20phN", event->pcr_value);
2840bfb2374SThiebaud Weksteen 
2850bfb2374SThiebaud Weksteen 	/* 3rd: event type identifier */
2860bfb2374SThiebaud Weksteen 	seq_printf(m, " %02x", do_endian_conversion(event->event_type));
2870bfb2374SThiebaud Weksteen 
2880bfb2374SThiebaud Weksteen 	len += get_event_name(eventname, event, event_entry);
2890bfb2374SThiebaud Weksteen 
2900bfb2374SThiebaud Weksteen 	/* 4th: eventname <= max + \'0' delimiter */
2910bfb2374SThiebaud Weksteen 	seq_printf(m, " %s\n", eventname);
2920bfb2374SThiebaud Weksteen 
2930bfb2374SThiebaud Weksteen 	kfree(eventname);
2940bfb2374SThiebaud Weksteen 	return 0;
2950bfb2374SThiebaud Weksteen }
2960bfb2374SThiebaud Weksteen 
297*9b01b535SThiebaud Weksteen const struct seq_operations tpm1_ascii_b_measurements_seqops = {
298*9b01b535SThiebaud Weksteen 	.start = tpm1_bios_measurements_start,
299*9b01b535SThiebaud Weksteen 	.next = tpm1_bios_measurements_next,
300*9b01b535SThiebaud Weksteen 	.stop = tpm1_bios_measurements_stop,
301*9b01b535SThiebaud Weksteen 	.show = tpm1_ascii_bios_measurements_show,
3020bfb2374SThiebaud Weksteen };
3030bfb2374SThiebaud Weksteen 
304*9b01b535SThiebaud Weksteen const struct seq_operations tpm1_binary_b_measurements_seqops = {
305*9b01b535SThiebaud Weksteen 	.start = tpm1_bios_measurements_start,
306*9b01b535SThiebaud Weksteen 	.next = tpm1_bios_measurements_next,
307*9b01b535SThiebaud Weksteen 	.stop = tpm1_bios_measurements_stop,
308*9b01b535SThiebaud Weksteen 	.show = tpm1_binary_bios_measurements_show,
3090bfb2374SThiebaud Weksteen };
310