xref: /openbmc/linux/drivers/char/tpm/eventlog/tpm1.c (revision ba61bb17)
1 /*
2  * Copyright (C) 2005, 2012 IBM Corporation
3  *
4  * Authors:
5  *	Kent Yoder <key@linux.vnet.ibm.com>
6  *	Seiji Munetoh <munetoh@jp.ibm.com>
7  *	Stefan Berger <stefanb@us.ibm.com>
8  *	Reiner Sailer <sailer@watson.ibm.com>
9  *	Kylene Hall <kjhall@us.ibm.com>
10  *	Nayna Jain <nayna@linux.vnet.ibm.com>
11  *
12  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
13  *
14  * Access to the event log created by a system's firmware / BIOS
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version
19  * 2 of the License, or (at your option) any later version.
20  *
21  */
22 
23 #include <linux/seq_file.h>
24 #include <linux/efi.h>
25 #include <linux/fs.h>
26 #include <linux/security.h>
27 #include <linux/module.h>
28 #include <linux/slab.h>
29 #include <linux/tpm_eventlog.h>
30 
31 #include "../tpm.h"
32 #include "common.h"
33 
34 
35 static const char* tcpa_event_type_strings[] = {
36 	"PREBOOT",
37 	"POST CODE",
38 	"",
39 	"NO ACTION",
40 	"SEPARATOR",
41 	"ACTION",
42 	"EVENT TAG",
43 	"S-CRTM Contents",
44 	"S-CRTM Version",
45 	"CPU Microcode",
46 	"Platform Config Flags",
47 	"Table of Devices",
48 	"Compact Hash",
49 	"IPL",
50 	"IPL Partition Data",
51 	"Non-Host Code",
52 	"Non-Host Config",
53 	"Non-Host Info"
54 };
55 
56 static const char* tcpa_pc_event_id_strings[] = {
57 	"",
58 	"SMBIOS",
59 	"BIS Certificate",
60 	"POST BIOS ",
61 	"ESCD ",
62 	"CMOS",
63 	"NVRAM",
64 	"Option ROM",
65 	"Option ROM config",
66 	"",
67 	"Option ROM microcode ",
68 	"S-CRTM Version",
69 	"S-CRTM Contents ",
70 	"POST Contents ",
71 	"Table of Devices",
72 };
73 
74 /* returns pointer to start of pos. entry of tcg log */
75 static void *tpm1_bios_measurements_start(struct seq_file *m, loff_t *pos)
76 {
77 	loff_t i;
78 	struct tpm_chip *chip = m->private;
79 	struct tpm_bios_log *log = &chip->log;
80 	void *addr = log->bios_event_log;
81 	void *limit = log->bios_event_log_end;
82 	struct tcpa_event *event;
83 	u32 converted_event_size;
84 	u32 converted_event_type;
85 
86 
87 	/* read over *pos measurements */
88 	for (i = 0; i < *pos; i++) {
89 		event = addr;
90 
91 		converted_event_size =
92 		    do_endian_conversion(event->event_size);
93 		converted_event_type =
94 		    do_endian_conversion(event->event_type);
95 
96 		if ((addr + sizeof(struct tcpa_event)) < limit) {
97 			if ((converted_event_type == 0) &&
98 			    (converted_event_size == 0))
99 				return NULL;
100 			addr += (sizeof(struct tcpa_event) +
101 				 converted_event_size);
102 		}
103 	}
104 
105 	/* now check if current entry is valid */
106 	if ((addr + sizeof(struct tcpa_event)) >= limit)
107 		return NULL;
108 
109 	event = addr;
110 
111 	converted_event_size = do_endian_conversion(event->event_size);
112 	converted_event_type = do_endian_conversion(event->event_type);
113 
114 	if (((converted_event_type == 0) && (converted_event_size == 0))
115 	    || ((addr + sizeof(struct tcpa_event) + converted_event_size)
116 		>= limit))
117 		return NULL;
118 
119 	return addr;
120 }
121 
122 static void *tpm1_bios_measurements_next(struct seq_file *m, void *v,
123 					loff_t *pos)
124 {
125 	struct tcpa_event *event = v;
126 	struct tpm_chip *chip = m->private;
127 	struct tpm_bios_log *log = &chip->log;
128 	void *limit = log->bios_event_log_end;
129 	u32 converted_event_size;
130 	u32 converted_event_type;
131 
132 	converted_event_size = do_endian_conversion(event->event_size);
133 
134 	v += sizeof(struct tcpa_event) + converted_event_size;
135 
136 	/* now check if current entry is valid */
137 	if ((v + sizeof(struct tcpa_event)) >= limit)
138 		return NULL;
139 
140 	event = v;
141 
142 	converted_event_size = do_endian_conversion(event->event_size);
143 	converted_event_type = do_endian_conversion(event->event_type);
144 
145 	if (((converted_event_type == 0) && (converted_event_size == 0)) ||
146 	    ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit))
147 		return NULL;
148 
149 	(*pos)++;
150 	return v;
151 }
152 
153 static void tpm1_bios_measurements_stop(struct seq_file *m, void *v)
154 {
155 }
156 
157 static int get_event_name(char *dest, struct tcpa_event *event,
158 			unsigned char * event_entry)
159 {
160 	const char *name = "";
161 	/* 41 so there is room for 40 data and 1 nul */
162 	char data[41] = "";
163 	int i, n_len = 0, d_len = 0;
164 	struct tcpa_pc_event *pc_event;
165 
166 	switch (do_endian_conversion(event->event_type)) {
167 	case PREBOOT:
168 	case POST_CODE:
169 	case UNUSED:
170 	case NO_ACTION:
171 	case SCRTM_CONTENTS:
172 	case SCRTM_VERSION:
173 	case CPU_MICROCODE:
174 	case PLATFORM_CONFIG_FLAGS:
175 	case TABLE_OF_DEVICES:
176 	case COMPACT_HASH:
177 	case IPL:
178 	case IPL_PARTITION_DATA:
179 	case NONHOST_CODE:
180 	case NONHOST_CONFIG:
181 	case NONHOST_INFO:
182 		name = tcpa_event_type_strings[do_endian_conversion
183 						(event->event_type)];
184 		n_len = strlen(name);
185 		break;
186 	case SEPARATOR:
187 	case ACTION:
188 		if (MAX_TEXT_EVENT >
189 		    do_endian_conversion(event->event_size)) {
190 			name = event_entry;
191 			n_len = do_endian_conversion(event->event_size);
192 		}
193 		break;
194 	case EVENT_TAG:
195 		pc_event = (struct tcpa_pc_event *)event_entry;
196 
197 		/* ToDo Row data -> Base64 */
198 
199 		switch (do_endian_conversion(pc_event->event_id)) {
200 		case SMBIOS:
201 		case BIS_CERT:
202 		case CMOS:
203 		case NVRAM:
204 		case OPTION_ROM_EXEC:
205 		case OPTION_ROM_CONFIG:
206 		case S_CRTM_VERSION:
207 			name = tcpa_pc_event_id_strings[do_endian_conversion
208 							(pc_event->event_id)];
209 			n_len = strlen(name);
210 			break;
211 		/* hash data */
212 		case POST_BIOS_ROM:
213 		case ESCD:
214 		case OPTION_ROM_MICROCODE:
215 		case S_CRTM_CONTENTS:
216 		case POST_CONTENTS:
217 			name = tcpa_pc_event_id_strings[do_endian_conversion
218 							(pc_event->event_id)];
219 			n_len = strlen(name);
220 			for (i = 0; i < 20; i++)
221 				d_len += sprintf(&data[2*i], "%02x",
222 						pc_event->event_data[i]);
223 			break;
224 		default:
225 			break;
226 		}
227 	default:
228 		break;
229 	}
230 
231 	return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
232 			n_len, name, d_len, data);
233 
234 }
235 
236 static int tpm1_binary_bios_measurements_show(struct seq_file *m, void *v)
237 {
238 	struct tcpa_event *event = v;
239 	struct tcpa_event temp_event;
240 	char *temp_ptr;
241 	int i;
242 
243 	memcpy(&temp_event, event, sizeof(struct tcpa_event));
244 
245 	/* convert raw integers for endianness */
246 	temp_event.pcr_index = do_endian_conversion(event->pcr_index);
247 	temp_event.event_type = do_endian_conversion(event->event_type);
248 	temp_event.event_size = do_endian_conversion(event->event_size);
249 
250 	temp_ptr = (char *) &temp_event;
251 
252 	for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
253 		seq_putc(m, temp_ptr[i]);
254 
255 	temp_ptr = (char *) v;
256 
257 	for (i = (sizeof(struct tcpa_event) - 1);
258 	     i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
259 		seq_putc(m, temp_ptr[i]);
260 
261 	return 0;
262 
263 }
264 
265 static int tpm1_ascii_bios_measurements_show(struct seq_file *m, void *v)
266 {
267 	int len = 0;
268 	char *eventname;
269 	struct tcpa_event *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 -EFAULT;
278 	}
279 
280 	/* 1st: PCR */
281 	seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index));
282 
283 	/* 2nd: SHA1 */
284 	seq_printf(m, "%20phN", event->pcr_value);
285 
286 	/* 3rd: event type identifier */
287 	seq_printf(m, " %02x", do_endian_conversion(event->event_type));
288 
289 	len += get_event_name(eventname, event, event_entry);
290 
291 	/* 4th: eventname <= max + \'0' delimiter */
292 	seq_printf(m, " %s\n", eventname);
293 
294 	kfree(eventname);
295 	return 0;
296 }
297 
298 const struct seq_operations tpm1_ascii_b_measurements_seqops = {
299 	.start = tpm1_bios_measurements_start,
300 	.next = tpm1_bios_measurements_next,
301 	.stop = tpm1_bios_measurements_stop,
302 	.show = tpm1_ascii_bios_measurements_show,
303 };
304 
305 const struct seq_operations tpm1_binary_b_measurements_seqops = {
306 	.start = tpm1_bios_measurements_start,
307 	.next = tpm1_bios_measurements_next,
308 	.stop = tpm1_bios_measurements_stop,
309 	.show = tpm1_binary_bios_measurements_show,
310 };
311