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 = 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 85 static 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 124 static void tpm2_bios_measurements_stop(struct seq_file *m, void *v) 125 { 126 } 127 128 static 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 154 const 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 }; 160