]>
Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
55a82ab3 | 2 | /* |
e5dcd87f | 3 | * Copyright (C) 2005, 2012 IBM Corporation |
55a82ab3 KJH |
4 | * |
5 | * Authors: | |
e5dcd87f | 6 | * Kent Yoder <key@linux.vnet.ibm.com> |
55a82ab3 KJH |
7 | * Seiji Munetoh <munetoh@jp.ibm.com> |
8 | * Stefan Berger <stefanb@us.ibm.com> | |
9 | * Reiner Sailer <sailer@watson.ibm.com> | |
10 | * Kylene Hall <kjhall@us.ibm.com> | |
2528a646 | 11 | * Nayna Jain <nayna@linux.vnet.ibm.com> |
55a82ab3 | 12 | * |
8e81cc13 KY |
13 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> |
14 | * | |
748935ee | 15 | * Access to the event log created by a system's firmware / BIOS |
55a82ab3 KJH |
16 | */ |
17 | ||
18 | #include <linux/seq_file.h> | |
58cc1e4f | 19 | #include <linux/efi.h> |
55a82ab3 KJH |
20 | #include <linux/fs.h> |
21 | #include <linux/security.h> | |
22 | #include <linux/module.h> | |
5a0e3ad6 | 23 | #include <linux/slab.h> |
fd3ec366 | 24 | #include <linux/tpm_eventlog.h> |
55a82ab3 | 25 | |
0bfb2374 | 26 | #include "../tpm.h" |
75d647f5 | 27 | #include "common.h" |
55a82ab3 | 28 | |
55a82ab3 KJH |
29 | |
30 | static const char* tcpa_event_type_strings[] = { | |
31 | "PREBOOT", | |
32 | "POST CODE", | |
33 | "", | |
34 | "NO ACTION", | |
35 | "SEPARATOR", | |
36 | "ACTION", | |
37 | "EVENT TAG", | |
38 | "S-CRTM Contents", | |
39 | "S-CRTM Version", | |
40 | "CPU Microcode", | |
41 | "Platform Config Flags", | |
42 | "Table of Devices", | |
43 | "Compact Hash", | |
44 | "IPL", | |
45 | "IPL Partition Data", | |
46 | "Non-Host Code", | |
47 | "Non-Host Config", | |
48 | "Non-Host Info" | |
49 | }; | |
50 | ||
55a82ab3 | 51 | static const char* tcpa_pc_event_id_strings[] = { |
de66a695 | 52 | "", |
55a82ab3 KJH |
53 | "SMBIOS", |
54 | "BIS Certificate", | |
55 | "POST BIOS ", | |
56 | "ESCD ", | |
57 | "CMOS", | |
58 | "NVRAM", | |
59 | "Option ROM", | |
60 | "Option ROM config", | |
de66a695 SM |
61 | "", |
62 | "Option ROM microcode ", | |
55a82ab3 | 63 | "S-CRTM Version", |
de66a695 SM |
64 | "S-CRTM Contents ", |
65 | "POST Contents ", | |
66 | "Table of Devices", | |
55a82ab3 KJH |
67 | }; |
68 | ||
55a82ab3 | 69 | /* returns pointer to start of pos. entry of tcg log */ |
9b01b535 | 70 | static void *tpm1_bios_measurements_start(struct seq_file *m, loff_t *pos) |
55a82ab3 | 71 | { |
bb3b6b0f | 72 | loff_t i = 0; |
748935ee NJ |
73 | struct tpm_chip *chip = m->private; |
74 | struct tpm_bios_log *log = &chip->log; | |
d09cf7d7 KJH |
75 | void *addr = log->bios_event_log; |
76 | void *limit = log->bios_event_log_end; | |
55a82ab3 | 77 | struct tcpa_event *event; |
0cc698af HCVL |
78 | u32 converted_event_size; |
79 | u32 converted_event_type; | |
80 | ||
55a82ab3 | 81 | /* read over *pos measurements */ |
bb3b6b0f | 82 | do { |
55a82ab3 KJH |
83 | event = addr; |
84 | ||
bb3b6b0f | 85 | /* check if current entry is valid */ |
64494d39 | 86 | if (addr + sizeof(struct tcpa_event) > limit) |
bb3b6b0f JZ |
87 | return NULL; |
88 | ||
0cc698af HCVL |
89 | converted_event_size = |
90 | do_endian_conversion(event->event_size); | |
91 | converted_event_type = | |
92 | do_endian_conversion(event->event_type); | |
93 | ||
bb3b6b0f JZ |
94 | if (((converted_event_type == 0) && (converted_event_size == 0)) |
95 | || ((addr + sizeof(struct tcpa_event) + converted_event_size) | |
64494d39 | 96 | > limit)) |
bb3b6b0f | 97 | return NULL; |
55a82ab3 | 98 | |
bb3b6b0f JZ |
99 | if (i++ == *pos) |
100 | break; | |
55a82ab3 | 101 | |
bb3b6b0f JZ |
102 | addr += (sizeof(struct tcpa_event) + converted_event_size); |
103 | } while (1); | |
55a82ab3 KJH |
104 | |
105 | return addr; | |
106 | } | |
107 | ||
9b01b535 | 108 | static void *tpm1_bios_measurements_next(struct seq_file *m, void *v, |
55a82ab3 KJH |
109 | loff_t *pos) |
110 | { | |
111 | struct tcpa_event *event = v; | |
748935ee NJ |
112 | struct tpm_chip *chip = m->private; |
113 | struct tpm_bios_log *log = &chip->log; | |
d09cf7d7 | 114 | void *limit = log->bios_event_log_end; |
0cc698af HCVL |
115 | u32 converted_event_size; |
116 | u32 converted_event_type; | |
55a82ab3 | 117 | |
0cc698af HCVL |
118 | converted_event_size = do_endian_conversion(event->event_size); |
119 | ||
120 | v += sizeof(struct tcpa_event) + converted_event_size; | |
55a82ab3 KJH |
121 | |
122 | /* now check if current entry is valid */ | |
64494d39 | 123 | if ((v + sizeof(struct tcpa_event)) > limit) |
55a82ab3 KJH |
124 | return NULL; |
125 | ||
126 | event = v; | |
127 | ||
0cc698af HCVL |
128 | converted_event_size = do_endian_conversion(event->event_size); |
129 | converted_event_type = do_endian_conversion(event->event_type); | |
55a82ab3 | 130 | |
0cc698af | 131 | if (((converted_event_type == 0) && (converted_event_size == 0)) || |
64494d39 | 132 | ((v + sizeof(struct tcpa_event) + converted_event_size) > limit)) |
55a82ab3 KJH |
133 | return NULL; |
134 | ||
135 | (*pos)++; | |
136 | return v; | |
137 | } | |
138 | ||
9b01b535 | 139 | static void tpm1_bios_measurements_stop(struct seq_file *m, void *v) |
55a82ab3 KJH |
140 | { |
141 | } | |
142 | ||
143 | static int get_event_name(char *dest, struct tcpa_event *event, | |
144 | unsigned char * event_entry) | |
145 | { | |
146 | const char *name = ""; | |
fbaa5869 EP |
147 | /* 41 so there is room for 40 data and 1 nul */ |
148 | char data[41] = ""; | |
55a82ab3 | 149 | int i, n_len = 0, d_len = 0; |
de66a695 | 150 | struct tcpa_pc_event *pc_event; |
55a82ab3 | 151 | |
0cc698af | 152 | switch (do_endian_conversion(event->event_type)) { |
55a82ab3 KJH |
153 | case PREBOOT: |
154 | case POST_CODE: | |
155 | case UNUSED: | |
156 | case NO_ACTION: | |
157 | case SCRTM_CONTENTS: | |
158 | case SCRTM_VERSION: | |
159 | case CPU_MICROCODE: | |
160 | case PLATFORM_CONFIG_FLAGS: | |
161 | case TABLE_OF_DEVICES: | |
162 | case COMPACT_HASH: | |
163 | case IPL: | |
164 | case IPL_PARTITION_DATA: | |
165 | case NONHOST_CODE: | |
166 | case NONHOST_CONFIG: | |
167 | case NONHOST_INFO: | |
0cc698af HCVL |
168 | name = tcpa_event_type_strings[do_endian_conversion |
169 | (event->event_type)]; | |
55a82ab3 KJH |
170 | n_len = strlen(name); |
171 | break; | |
172 | case SEPARATOR: | |
173 | case ACTION: | |
0cc698af HCVL |
174 | if (MAX_TEXT_EVENT > |
175 | do_endian_conversion(event->event_size)) { | |
55a82ab3 | 176 | name = event_entry; |
0cc698af | 177 | n_len = do_endian_conversion(event->event_size); |
55a82ab3 KJH |
178 | } |
179 | break; | |
180 | case EVENT_TAG: | |
de66a695 | 181 | pc_event = (struct tcpa_pc_event *)event_entry; |
55a82ab3 KJH |
182 | |
183 | /* ToDo Row data -> Base64 */ | |
184 | ||
0cc698af | 185 | switch (do_endian_conversion(pc_event->event_id)) { |
55a82ab3 KJH |
186 | case SMBIOS: |
187 | case BIS_CERT: | |
188 | case CMOS: | |
189 | case NVRAM: | |
190 | case OPTION_ROM_EXEC: | |
191 | case OPTION_ROM_CONFIG: | |
55a82ab3 | 192 | case S_CRTM_VERSION: |
0cc698af HCVL |
193 | name = tcpa_pc_event_id_strings[do_endian_conversion |
194 | (pc_event->event_id)]; | |
55a82ab3 KJH |
195 | n_len = strlen(name); |
196 | break; | |
de66a695 | 197 | /* hash data */ |
55a82ab3 KJH |
198 | case POST_BIOS_ROM: |
199 | case ESCD: | |
de66a695 SM |
200 | case OPTION_ROM_MICROCODE: |
201 | case S_CRTM_CONTENTS: | |
202 | case POST_CONTENTS: | |
0cc698af HCVL |
203 | name = tcpa_pc_event_id_strings[do_endian_conversion |
204 | (pc_event->event_id)]; | |
55a82ab3 KJH |
205 | n_len = strlen(name); |
206 | for (i = 0; i < 20; i++) | |
de66a695 SM |
207 | d_len += sprintf(&data[2*i], "%02x", |
208 | pc_event->event_data[i]); | |
55a82ab3 KJH |
209 | break; |
210 | default: | |
211 | break; | |
212 | } | |
213 | default: | |
214 | break; | |
215 | } | |
216 | ||
217 | return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]", | |
218 | n_len, name, d_len, data); | |
219 | ||
220 | } | |
221 | ||
9b01b535 | 222 | static int tpm1_binary_bios_measurements_show(struct seq_file *m, void *v) |
55a82ab3 | 223 | { |
44d7aff0 | 224 | struct tcpa_event *event = v; |
0cc698af | 225 | struct tcpa_event temp_event; |
186d124f | 226 | char *temp_ptr; |
44d7aff0 | 227 | int i; |
55a82ab3 | 228 | |
0cc698af HCVL |
229 | memcpy(&temp_event, event, sizeof(struct tcpa_event)); |
230 | ||
231 | /* convert raw integers for endianness */ | |
232 | temp_event.pcr_index = do_endian_conversion(event->pcr_index); | |
233 | temp_event.event_type = do_endian_conversion(event->event_type); | |
234 | temp_event.event_size = do_endian_conversion(event->event_size); | |
235 | ||
186d124f | 236 | temp_ptr = (char *) &temp_event; |
0cc698af | 237 | |
186d124f HH |
238 | for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++) |
239 | seq_putc(m, temp_ptr[i]); | |
240 | ||
241 | temp_ptr = (char *) v; | |
242 | ||
243 | for (i = (sizeof(struct tcpa_event) - 1); | |
244 | i < (sizeof(struct tcpa_event) + temp_event.event_size); i++) | |
245 | seq_putc(m, temp_ptr[i]); | |
55a82ab3 | 246 | |
55a82ab3 | 247 | return 0; |
0cc698af | 248 | |
55a82ab3 KJH |
249 | } |
250 | ||
9b01b535 | 251 | static int tpm1_ascii_bios_measurements_show(struct seq_file *m, void *v) |
55a82ab3 KJH |
252 | { |
253 | int len = 0; | |
55a82ab3 KJH |
254 | char *eventname; |
255 | struct tcpa_event *event = v; | |
256 | unsigned char *event_entry = | |
0cc698af | 257 | (unsigned char *)(v + sizeof(struct tcpa_event)); |
55a82ab3 KJH |
258 | |
259 | eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); | |
260 | if (!eventname) { | |
261 | printk(KERN_ERR "%s: ERROR - No Memory for event name\n ", | |
262 | __func__); | |
263 | return -EFAULT; | |
264 | } | |
265 | ||
0cc698af HCVL |
266 | /* 1st: PCR */ |
267 | seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index)); | |
55a82ab3 KJH |
268 | |
269 | /* 2nd: SHA1 */ | |
a3d64df8 | 270 | seq_printf(m, "%20phN", event->pcr_value); |
55a82ab3 KJH |
271 | |
272 | /* 3rd: event type identifier */ | |
0cc698af | 273 | seq_printf(m, " %02x", do_endian_conversion(event->event_type)); |
55a82ab3 KJH |
274 | |
275 | len += get_event_name(eventname, event, event_entry); | |
276 | ||
277 | /* 4th: eventname <= max + \'0' delimiter */ | |
278 | seq_printf(m, " %s\n", eventname); | |
279 | ||
59e89f3a | 280 | kfree(eventname); |
55a82ab3 KJH |
281 | return 0; |
282 | } | |
283 | ||
9b01b535 TW |
284 | const struct seq_operations tpm1_ascii_b_measurements_seqops = { |
285 | .start = tpm1_bios_measurements_start, | |
286 | .next = tpm1_bios_measurements_next, | |
287 | .stop = tpm1_bios_measurements_stop, | |
288 | .show = tpm1_ascii_bios_measurements_show, | |
55a82ab3 KJH |
289 | }; |
290 | ||
9b01b535 TW |
291 | const struct seq_operations tpm1_binary_b_measurements_seqops = { |
292 | .start = tpm1_bios_measurements_start, | |
293 | .next = tpm1_bios_measurements_next, | |
294 | .stop = tpm1_bios_measurements_stop, | |
295 | .show = tpm1_binary_bios_measurements_show, | |
55a82ab3 | 296 | }; |