Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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/fs.h>
 25#include <linux/security.h>
 26#include <linux/module.h>
 27#include <linux/slab.h>
 28
 29#include "tpm.h"
 30#include "tpm_eventlog.h"
 31
 32
 33static const char* tcpa_event_type_strings[] = {
 34	"PREBOOT",
 35	"POST CODE",
 36	"",
 37	"NO ACTION",
 38	"SEPARATOR",
 39	"ACTION",
 40	"EVENT TAG",
 41	"S-CRTM Contents",
 42	"S-CRTM Version",
 43	"CPU Microcode",
 44	"Platform Config Flags",
 45	"Table of Devices",
 46	"Compact Hash",
 47	"IPL",
 48	"IPL Partition Data",
 49	"Non-Host Code",
 50	"Non-Host Config",
 51	"Non-Host Info"
 52};
 53
 54static const char* tcpa_pc_event_id_strings[] = {
 55	"",
 56	"SMBIOS",
 57	"BIS Certificate",
 58	"POST BIOS ",
 59	"ESCD ",
 60	"CMOS",
 61	"NVRAM",
 62	"Option ROM",
 63	"Option ROM config",
 64	"",
 65	"Option ROM microcode ",
 66	"S-CRTM Version",
 67	"S-CRTM Contents ",
 68	"POST Contents ",
 69	"Table of Devices",
 70};
 71
 72/* returns pointer to start of pos. entry of tcg log */
 73static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
 74{
 75	loff_t i;
 76	struct tpm_chip *chip = m->private;
 77	struct tpm_bios_log *log = &chip->log;
 78	void *addr = log->bios_event_log;
 79	void *limit = log->bios_event_log_end;
 80	struct tcpa_event *event;
 81	u32 converted_event_size;
 82	u32 converted_event_type;
 83
 84
 85	/* read over *pos measurements */
 86	for (i = 0; i < *pos; i++) {
 87		event = addr;
 88
 89		converted_event_size =
 90		    do_endian_conversion(event->event_size);
 91		converted_event_type =
 92		    do_endian_conversion(event->event_type);
 93
 94		if ((addr + sizeof(struct tcpa_event)) < limit) {
 95			if ((converted_event_type == 0) &&
 96			    (converted_event_size == 0))
 97				return NULL;
 98			addr += (sizeof(struct tcpa_event) +
 99				 converted_event_size);
100		}
101	}
102
103	/* now check if current entry is valid */
104	if ((addr + sizeof(struct tcpa_event)) >= limit)
105		return NULL;
106
107	event = addr;
108
109	converted_event_size = do_endian_conversion(event->event_size);
110	converted_event_type = do_endian_conversion(event->event_type);
111
112	if (((converted_event_type == 0) && (converted_event_size == 0))
113	    || ((addr + sizeof(struct tcpa_event) + converted_event_size)
114		>= limit))
115		return NULL;
116
117	return addr;
118}
119
120static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
121					loff_t *pos)
122{
123	struct tcpa_event *event = v;
124	struct tpm_chip *chip = m->private;
125	struct tpm_bios_log *log = &chip->log;
126	void *limit = log->bios_event_log_end;
127	u32 converted_event_size;
128	u32 converted_event_type;
129
130	converted_event_size = do_endian_conversion(event->event_size);
131
132	v += sizeof(struct tcpa_event) + converted_event_size;
133
134	/* now check if current entry is valid */
135	if ((v + sizeof(struct tcpa_event)) >= limit)
136		return NULL;
137
138	event = v;
139
140	converted_event_size = do_endian_conversion(event->event_size);
141	converted_event_type = do_endian_conversion(event->event_type);
142
143	if (((converted_event_type == 0) && (converted_event_size == 0)) ||
144	    ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit))
145		return NULL;
146
147	(*pos)++;
148	return v;
149}
150
151static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
152{
153}
154
155static int get_event_name(char *dest, struct tcpa_event *event,
156			unsigned char * event_entry)
157{
158	const char *name = "";
159	/* 41 so there is room for 40 data and 1 nul */
160	char data[41] = "";
161	int i, n_len = 0, d_len = 0;
162	struct tcpa_pc_event *pc_event;
163
164	switch (do_endian_conversion(event->event_type)) {
165	case PREBOOT:
166	case POST_CODE:
167	case UNUSED:
168	case NO_ACTION:
169	case SCRTM_CONTENTS:
170	case SCRTM_VERSION:
171	case CPU_MICROCODE:
172	case PLATFORM_CONFIG_FLAGS:
173	case TABLE_OF_DEVICES:
174	case COMPACT_HASH:
175	case IPL:
176	case IPL_PARTITION_DATA:
177	case NONHOST_CODE:
178	case NONHOST_CONFIG:
179	case NONHOST_INFO:
180		name = tcpa_event_type_strings[do_endian_conversion
181						(event->event_type)];
182		n_len = strlen(name);
183		break;
184	case SEPARATOR:
185	case ACTION:
186		if (MAX_TEXT_EVENT >
187		    do_endian_conversion(event->event_size)) {
188			name = event_entry;
189			n_len = do_endian_conversion(event->event_size);
190		}
191		break;
192	case EVENT_TAG:
193		pc_event = (struct tcpa_pc_event *)event_entry;
194
195		/* ToDo Row data -> Base64 */
196
197		switch (do_endian_conversion(pc_event->event_id)) {
198		case SMBIOS:
199		case BIS_CERT:
200		case CMOS:
201		case NVRAM:
202		case OPTION_ROM_EXEC:
203		case OPTION_ROM_CONFIG:
204		case S_CRTM_VERSION:
205			name = tcpa_pc_event_id_strings[do_endian_conversion
206							(pc_event->event_id)];
207			n_len = strlen(name);
208			break;
209		/* hash data */
210		case POST_BIOS_ROM:
211		case ESCD:
212		case OPTION_ROM_MICROCODE:
213		case S_CRTM_CONTENTS:
214		case POST_CONTENTS:
215			name = tcpa_pc_event_id_strings[do_endian_conversion
216							(pc_event->event_id)];
217			n_len = strlen(name);
218			for (i = 0; i < 20; i++)
219				d_len += sprintf(&data[2*i], "%02x",
220						pc_event->event_data[i]);
221			break;
222		default:
223			break;
224		}
225	default:
226		break;
227	}
228
229	return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
230			n_len, name, d_len, data);
231
232}
233
234static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
235{
236	struct tcpa_event *event = v;
237	struct tcpa_event temp_event;
238	char *temp_ptr;
239	int i;
240
241	memcpy(&temp_event, event, sizeof(struct tcpa_event));
242
243	/* convert raw integers for endianness */
244	temp_event.pcr_index = do_endian_conversion(event->pcr_index);
245	temp_event.event_type = do_endian_conversion(event->event_type);
246	temp_event.event_size = do_endian_conversion(event->event_size);
247
248	temp_ptr = (char *) &temp_event;
249
250	for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
251		seq_putc(m, temp_ptr[i]);
252
253	temp_ptr = (char *) v;
254
255	for (i = (sizeof(struct tcpa_event) - 1);
256	     i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
257		seq_putc(m, temp_ptr[i]);
258
259	return 0;
260
261}
262
263static int tpm_bios_measurements_release(struct inode *inode,
264					 struct file *file)
265{
266	struct seq_file *seq = (struct seq_file *)file->private_data;
267	struct tpm_chip *chip = (struct tpm_chip *)seq->private;
268
269	put_device(&chip->dev);
270
271	return seq_release(inode, file);
272}
273
274static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
275{
276	int len = 0;
277	char *eventname;
278	struct tcpa_event *event = v;
279	unsigned char *event_entry =
280	    (unsigned char *)(v + sizeof(struct tcpa_event));
281
282	eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
283	if (!eventname) {
284		printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
285		       __func__);
286		return -EFAULT;
287	}
288
289	/* 1st: PCR */
290	seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index));
291
292	/* 2nd: SHA1 */
293	seq_printf(m, "%20phN", event->pcr_value);
294
295	/* 3rd: event type identifier */
296	seq_printf(m, " %02x", do_endian_conversion(event->event_type));
297
298	len += get_event_name(eventname, event, event_entry);
299
300	/* 4th: eventname <= max + \'0' delimiter */
301	seq_printf(m, " %s\n", eventname);
302
303	kfree(eventname);
304	return 0;
305}
306
307static const struct seq_operations tpm_ascii_b_measurements_seqops = {
308	.start = tpm_bios_measurements_start,
309	.next = tpm_bios_measurements_next,
310	.stop = tpm_bios_measurements_stop,
311	.show = tpm_ascii_bios_measurements_show,
312};
313
314static const struct seq_operations tpm_binary_b_measurements_seqops = {
315	.start = tpm_bios_measurements_start,
316	.next = tpm_bios_measurements_next,
317	.stop = tpm_bios_measurements_stop,
318	.show = tpm_binary_bios_measurements_show,
319};
320
321static int tpm_bios_measurements_open(struct inode *inode,
322					    struct file *file)
323{
324	int err;
325	struct seq_file *seq;
326	struct tpm_chip_seqops *chip_seqops;
327	const struct seq_operations *seqops;
328	struct tpm_chip *chip;
329
330	inode_lock(inode);
331	if (!inode->i_private) {
332		inode_unlock(inode);
333		return -ENODEV;
334	}
335	chip_seqops = (struct tpm_chip_seqops *)inode->i_private;
336	seqops = chip_seqops->seqops;
337	chip = chip_seqops->chip;
338	get_device(&chip->dev);
339	inode_unlock(inode);
340
341	/* now register seq file */
342	err = seq_open(file, seqops);
343	if (!err) {
344		seq = file->private_data;
345		seq->private = chip;
346	}
347
348	return err;
349}
350
351static const struct file_operations tpm_bios_measurements_ops = {
352	.owner = THIS_MODULE,
353	.open = tpm_bios_measurements_open,
354	.read = seq_read,
355	.llseek = seq_lseek,
356	.release = tpm_bios_measurements_release,
357};
358
359static int tpm_read_log(struct tpm_chip *chip)
360{
361	int rc;
362
363	if (chip->log.bios_event_log != NULL) {
364		dev_dbg(&chip->dev,
365			"%s: ERROR - event log already initialized\n",
366			__func__);
367		return -EFAULT;
368	}
369
370	rc = tpm_read_log_acpi(chip);
371	if (rc != -ENODEV)
372		return rc;
373
374	return tpm_read_log_of(chip);
375}
376
377/*
378 * tpm_bios_log_setup() - Read the event log from the firmware
379 * @chip: TPM chip to use.
380 *
381 * If an event log is found then the securityfs files are setup to
382 * export it to userspace, otherwise nothing is done.
383 *
384 * Returns -ENODEV if the firmware has no event log or securityfs is not
385 * supported.
386 */
387int tpm_bios_log_setup(struct tpm_chip *chip)
388{
389	const char *name = dev_name(&chip->dev);
390	unsigned int cnt;
391	int rc = 0;
392
393	if (chip->flags & TPM_CHIP_FLAG_TPM2)
394		return 0;
395
396	rc = tpm_read_log(chip);
397	if (rc)
398		return rc;
399
400	cnt = 0;
401	chip->bios_dir[cnt] = securityfs_create_dir(name, NULL);
402	/* NOTE: securityfs_create_dir can return ENODEV if securityfs is
403	 * compiled out. The caller should ignore the ENODEV return code.
404	 */
405	if (IS_ERR(chip->bios_dir[cnt]))
406		goto err;
407	cnt++;
408
409	chip->bin_log_seqops.chip = chip;
410	chip->bin_log_seqops.seqops = &tpm_binary_b_measurements_seqops;
411
412	chip->bios_dir[cnt] =
413	    securityfs_create_file("binary_bios_measurements",
414				   0440, chip->bios_dir[0],
415				   (void *)&chip->bin_log_seqops,
416				   &tpm_bios_measurements_ops);
417	if (IS_ERR(chip->bios_dir[cnt]))
418		goto err;
419	cnt++;
420
421	chip->ascii_log_seqops.chip = chip;
422	chip->ascii_log_seqops.seqops = &tpm_ascii_b_measurements_seqops;
423
424	chip->bios_dir[cnt] =
425	    securityfs_create_file("ascii_bios_measurements",
426				   0440, chip->bios_dir[0],
427				   (void *)&chip->ascii_log_seqops,
428				   &tpm_bios_measurements_ops);
429	if (IS_ERR(chip->bios_dir[cnt]))
430		goto err;
431	cnt++;
432
433	return 0;
434
435err:
436	rc = PTR_ERR(chip->bios_dir[cnt]);
437	chip->bios_dir[cnt] = NULL;
438	tpm_bios_log_teardown(chip);
439	return rc;
440}
441
442void tpm_bios_log_teardown(struct tpm_chip *chip)
443{
444	int i;
445	struct inode *inode;
446
447	/* securityfs_remove currently doesn't take care of handling sync
448	 * between removal and opening of pseudo files. To handle this, a
449	 * workaround is added by making i_private = NULL here during removal
450	 * and to check it during open(), both within inode_lock()/unlock().
451	 * This design ensures that open() either safely gets kref or fails.
452	 */
453	for (i = (TPM_NUM_EVENT_LOG_FILES - 1); i >= 0; i--) {
454		if (chip->bios_dir[i]) {
455			inode = d_inode(chip->bios_dir[i]);
456			inode_lock(inode);
457			inode->i_private = NULL;
458			inode_unlock(inode);
459			securityfs_remove(chip->bios_dir[i]);
460		}
461	}
462}