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 */ 36 static 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 42 static 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 86 static 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 (*pos)++; 98 event_header = log->bios_event_log; 99 100 if (v == SEQ_START_TOKEN) { 101 event_size = sizeof(struct tcg_pcr_event) - 102 sizeof(event_header->event) + event_header->event_size; 103 marker = event_header; 104 } else { 105 event = v; 106 event_size = calc_tpm2_event_size(event, event_header); 107 if (event_size == 0) 108 return NULL; 109 marker = event; 110 } 111 112 marker = marker + event_size; 113 if (marker >= limit) 114 return NULL; 115 v = marker; 116 event = v; 117 118 event_size = calc_tpm2_event_size(event, event_header); 119 if (((v + event_size) >= limit) || (event_size == 0)) 120 return NULL; 121 122 return v; 123 } 124 125 static void tpm2_bios_measurements_stop(struct seq_file *m, void *v) 126 { 127 } 128 129 static 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 156 const 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