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