cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tpm2.c (3972B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2016 IBM Corporation
      4 *
      5 * Authors:
      6 *      Nayna Jain <nayna@linux.vnet.ibm.com>
      7 *
      8 * Access to TPM 2.0 event log as written by Firmware.
      9 * It assumes that writer of event log has followed TCG Specification
     10 * for Family "2.0" and written the event data in little endian.
     11 * With that, it doesn't need any endian conversion for structure
     12 * content.
     13 */
     14
     15#include <linux/seq_file.h>
     16#include <linux/fs.h>
     17#include <linux/security.h>
     18#include <linux/module.h>
     19#include <linux/slab.h>
     20#include <linux/tpm_eventlog.h>
     21
     22#include "../tpm.h"
     23#include "common.h"
     24
     25/*
     26 * calc_tpm2_event_size() - calculate the event size, where event
     27 * is an entry in the TPM 2.0 event log. The event is of type Crypto
     28 * Agile Log Entry Format as defined in TCG EFI Protocol Specification
     29 * Family "2.0".
     30
     31 * @event: event whose size is to be calculated.
     32 * @event_header: the first event in the event log.
     33 *
     34 * Returns size of the event. If it is an invalid event, returns 0.
     35 */
     36static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
     37				   struct tcg_pcr_event *event_header)
     38{
     39	return __calc_tpm2_event_size(event, event_header, false);
     40}
     41
     42static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
     43{
     44	struct tpm_chip *chip = m->private;
     45	struct tpm_bios_log *log = &chip->log;
     46	void *addr = log->bios_event_log;
     47	void *limit = log->bios_event_log_end;
     48	struct tcg_pcr_event *event_header;
     49	struct tcg_pcr_event2_head *event;
     50	size_t size;
     51	int i;
     52
     53	event_header = addr;
     54	size = struct_size(event_header, event, event_header->event_size);
     55
     56	if (*pos == 0) {
     57		if (addr + size < limit) {
     58			if ((event_header->event_type == 0) &&
     59			    (event_header->event_size == 0))
     60				return NULL;
     61			return SEQ_START_TOKEN;
     62		}
     63	}
     64
     65	if (*pos > 0) {
     66		addr += size;
     67		event = addr;
     68		size = calc_tpm2_event_size(event, event_header);
     69		if ((addr + size >=  limit) || (size == 0))
     70			return NULL;
     71	}
     72
     73	for (i = 0; i < (*pos - 1); i++) {
     74		event = addr;
     75		size = calc_tpm2_event_size(event, event_header);
     76
     77		if ((addr + size >= limit) || (size == 0))
     78			return NULL;
     79		addr += size;
     80	}
     81
     82	return addr;
     83}
     84
     85static void *tpm2_bios_measurements_next(struct seq_file *m, void *v,
     86					 loff_t *pos)
     87{
     88	struct tcg_pcr_event *event_header;
     89	struct tcg_pcr_event2_head *event;
     90	struct tpm_chip *chip = m->private;
     91	struct tpm_bios_log *log = &chip->log;
     92	void *limit = log->bios_event_log_end;
     93	size_t event_size;
     94	void *marker;
     95
     96	(*pos)++;
     97	event_header = log->bios_event_log;
     98
     99	if (v == SEQ_START_TOKEN) {
    100		event_size = struct_size(event_header, event,
    101					 event_header->event_size);
    102		marker = event_header;
    103	} else {
    104		event = v;
    105		event_size = calc_tpm2_event_size(event, event_header);
    106		if (event_size == 0)
    107			return NULL;
    108		marker = event;
    109	}
    110
    111	marker = marker + event_size;
    112	if (marker >= limit)
    113		return NULL;
    114	v = marker;
    115	event = v;
    116
    117	event_size = calc_tpm2_event_size(event, event_header);
    118	if (((v + event_size) >= limit) || (event_size == 0))
    119		return NULL;
    120
    121	return v;
    122}
    123
    124static void tpm2_bios_measurements_stop(struct seq_file *m, void *v)
    125{
    126}
    127
    128static int tpm2_binary_bios_measurements_show(struct seq_file *m, void *v)
    129{
    130	struct tpm_chip *chip = m->private;
    131	struct tpm_bios_log *log = &chip->log;
    132	struct tcg_pcr_event *event_header = log->bios_event_log;
    133	struct tcg_pcr_event2_head *event = v;
    134	void *temp_ptr;
    135	size_t size;
    136
    137	if (v == SEQ_START_TOKEN) {
    138		size = struct_size(event_header, event,
    139				   event_header->event_size);
    140		temp_ptr = event_header;
    141
    142		if (size > 0)
    143			seq_write(m, temp_ptr, size);
    144	} else {
    145		size = calc_tpm2_event_size(event, event_header);
    146		temp_ptr = event;
    147		if (size > 0)
    148			seq_write(m, temp_ptr, size);
    149	}
    150
    151	return 0;
    152}
    153
    154const struct seq_operations tpm2_binary_b_measurements_seqops = {
    155	.start = tpm2_bios_measurements_start,
    156	.next = tpm2_bios_measurements_next,
    157	.stop = tpm2_bios_measurements_stop,
    158	.show = tpm2_binary_bios_measurements_show,
    159};