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