linux/drivers/char/tpm/eventlog/tpm2.c
<<
>>
Prefs
   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 = sizeof(struct tcg_pcr_event) - sizeof(event_header->event)
  55                + event_header->event_size;
  56
  57        if (*pos == 0) {
  58                if (addr + size < limit) {
  59                        if ((event_header->event_type == 0) &&
  60                            (event_header->event_size == 0))
  61                                return NULL;
  62                        return SEQ_START_TOKEN;
  63                }
  64        }
  65
  66        if (*pos > 0) {
  67                addr += size;
  68                event = addr;
  69                size = calc_tpm2_event_size(event, event_header);
  70                if ((addr + size >=  limit) || (size == 0))
  71                        return NULL;
  72        }
  73
  74        for (i = 0; i < (*pos - 1); i++) {
  75                event = addr;
  76                size = calc_tpm2_event_size(event, event_header);
  77
  78                if ((addr + size >= limit) || (size == 0))
  79                        return NULL;
  80                addr += size;
  81        }
  82
  83        return addr;
  84}
  85
  86static void *tpm2_bios_measurements_next(struct seq_file *m, void *v,
  87                                         loff_t *pos)
  88{
  89        struct tcg_pcr_event *event_header;
  90        struct tcg_pcr_event2_head *event;
  91        struct tpm_chip *chip = m->private;
  92        struct tpm_bios_log *log = &chip->log;
  93        void *limit = log->bios_event_log_end;
  94        size_t event_size;
  95        void *marker;
  96
  97        event_header = log->bios_event_log;
  98
  99        if (v == SEQ_START_TOKEN) {
 100                event_size = sizeof(struct tcg_pcr_event) -
 101                        sizeof(event_header->event) + 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        (*pos)++;
 122        return v;
 123}
 124
 125static void tpm2_bios_measurements_stop(struct seq_file *m, void *v)
 126{
 127}
 128
 129static int tpm2_binary_bios_measurements_show(struct seq_file *m, void *v)
 130{
 131        struct tpm_chip *chip = m->private;
 132        struct tpm_bios_log *log = &chip->log;
 133        struct tcg_pcr_event *event_header = log->bios_event_log;
 134        struct tcg_pcr_event2_head *event = v;
 135        void *temp_ptr;
 136        size_t size;
 137
 138        if (v == SEQ_START_TOKEN) {
 139                size = sizeof(struct tcg_pcr_event) -
 140                        sizeof(event_header->event) + event_header->event_size;
 141
 142                temp_ptr = event_header;
 143
 144                if (size > 0)
 145                        seq_write(m, temp_ptr, size);
 146        } else {
 147                size = calc_tpm2_event_size(event, event_header);
 148                temp_ptr = event;
 149                if (size > 0)
 150                        seq_write(m, temp_ptr, size);
 151        }
 152
 153        return 0;
 154}
 155
 156const struct seq_operations tpm2_binary_b_measurements_seqops = {
 157        .start = tpm2_bios_measurements_start,
 158        .next = tpm2_bios_measurements_next,
 159        .stop = tpm2_bios_measurements_stop,
 160        .show = tpm2_binary_bios_measurements_show,
 161};
 162