Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/char/tpm/eventlog/tpm1.c
26292 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (C) 2005, 2012 IBM Corporation
4
*
5
* Authors:
6
* Kent Yoder <[email protected]>
7
* Seiji Munetoh <[email protected]>
8
* Stefan Berger <[email protected]>
9
* Reiner Sailer <[email protected]>
10
* Kylene Hall <[email protected]>
11
* Nayna Jain <[email protected]>
12
*
13
* Maintained by: <[email protected]>
14
*
15
* Access to the event log created by a system's firmware / BIOS
16
*/
17
18
#include <linux/seq_file.h>
19
#include <linux/efi.h>
20
#include <linux/fs.h>
21
#include <linux/security.h>
22
#include <linux/module.h>
23
#include <linux/slab.h>
24
#include <linux/tpm_eventlog.h>
25
26
#include "../tpm.h"
27
#include "common.h"
28
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
51
static const char* tcpa_pc_event_id_strings[] = {
52
"",
53
"SMBIOS",
54
"BIS Certificate",
55
"POST BIOS ",
56
"ESCD ",
57
"CMOS",
58
"NVRAM",
59
"Option ROM",
60
"Option ROM config",
61
"",
62
"Option ROM microcode ",
63
"S-CRTM Version",
64
"S-CRTM Contents ",
65
"POST Contents ",
66
"Table of Devices",
67
};
68
69
/* returns pointer to start of pos. entry of tcg log */
70
static void *tpm1_bios_measurements_start(struct seq_file *m, loff_t *pos)
71
{
72
loff_t i = 0;
73
struct tpm_chip *chip = m->private;
74
struct tpm_bios_log *log = &chip->log;
75
void *addr = log->bios_event_log;
76
void *limit = log->bios_event_log_end;
77
struct tcpa_event *event;
78
u32 converted_event_size;
79
u32 converted_event_type;
80
81
/* read over *pos measurements */
82
do {
83
event = addr;
84
85
/* check if current entry is valid */
86
if (addr + sizeof(struct tcpa_event) > limit)
87
return NULL;
88
89
converted_event_size =
90
do_endian_conversion(event->event_size);
91
converted_event_type =
92
do_endian_conversion(event->event_type);
93
94
if (((converted_event_type == 0) && (converted_event_size == 0))
95
|| ((addr + sizeof(struct tcpa_event) + converted_event_size)
96
> limit))
97
return NULL;
98
99
if (i++ == *pos)
100
break;
101
102
addr += (sizeof(struct tcpa_event) + converted_event_size);
103
} while (1);
104
105
return addr;
106
}
107
108
static void *tpm1_bios_measurements_next(struct seq_file *m, void *v,
109
loff_t *pos)
110
{
111
struct tcpa_event *event = v;
112
struct tpm_chip *chip = m->private;
113
struct tpm_bios_log *log = &chip->log;
114
void *limit = log->bios_event_log_end;
115
u32 converted_event_size;
116
u32 converted_event_type;
117
118
(*pos)++;
119
converted_event_size = do_endian_conversion(event->event_size);
120
121
v += sizeof(struct tcpa_event) + converted_event_size;
122
123
/* now check if current entry is valid */
124
if ((v + sizeof(struct tcpa_event)) > limit)
125
return NULL;
126
127
event = v;
128
129
converted_event_size = do_endian_conversion(event->event_size);
130
converted_event_type = do_endian_conversion(event->event_type);
131
132
if (((converted_event_type == 0) && (converted_event_size == 0)) ||
133
((v + sizeof(struct tcpa_event) + converted_event_size) > limit))
134
return NULL;
135
136
return v;
137
}
138
139
static void tpm1_bios_measurements_stop(struct seq_file *m, void *v)
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 = "";
147
/* 41 so there is room for 40 data and 1 nul */
148
char data[41] = "";
149
int i, n_len = 0, d_len = 0;
150
struct tcpa_pc_event *pc_event;
151
152
switch (do_endian_conversion(event->event_type)) {
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:
168
name = tcpa_event_type_strings[do_endian_conversion
169
(event->event_type)];
170
n_len = strlen(name);
171
break;
172
case SEPARATOR:
173
case ACTION:
174
if (MAX_TEXT_EVENT >
175
do_endian_conversion(event->event_size)) {
176
name = event_entry;
177
n_len = do_endian_conversion(event->event_size);
178
}
179
break;
180
case EVENT_TAG:
181
pc_event = (struct tcpa_pc_event *)event_entry;
182
183
/* ToDo Row data -> Base64 */
184
185
switch (do_endian_conversion(pc_event->event_id)) {
186
case SMBIOS:
187
case BIS_CERT:
188
case CMOS:
189
case NVRAM:
190
case OPTION_ROM_EXEC:
191
case OPTION_ROM_CONFIG:
192
case S_CRTM_VERSION:
193
name = tcpa_pc_event_id_strings[do_endian_conversion
194
(pc_event->event_id)];
195
n_len = strlen(name);
196
break;
197
/* hash data */
198
case POST_BIOS_ROM:
199
case ESCD:
200
case OPTION_ROM_MICROCODE:
201
case S_CRTM_CONTENTS:
202
case POST_CONTENTS:
203
name = tcpa_pc_event_id_strings[do_endian_conversion
204
(pc_event->event_id)];
205
n_len = strlen(name);
206
for (i = 0; i < 20; i++)
207
d_len += sprintf(&data[2*i], "%02x",
208
pc_event->event_data[i]);
209
break;
210
default:
211
break;
212
}
213
break;
214
default:
215
break;
216
}
217
218
return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
219
n_len, name, d_len, data);
220
221
}
222
223
static int tpm1_binary_bios_measurements_show(struct seq_file *m, void *v)
224
{
225
struct tcpa_event *event = v;
226
struct tcpa_event temp_event;
227
char *temp_ptr;
228
int i;
229
230
memcpy(&temp_event, event, sizeof(struct tcpa_event));
231
232
/* convert raw integers for endianness */
233
temp_event.pcr_index = do_endian_conversion(event->pcr_index);
234
temp_event.event_type = do_endian_conversion(event->event_type);
235
temp_event.event_size = do_endian_conversion(event->event_size);
236
237
temp_ptr = (char *) &temp_event;
238
239
for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
240
seq_putc(m, temp_ptr[i]);
241
242
temp_ptr = (char *) v;
243
244
for (i = (sizeof(struct tcpa_event) - 1);
245
i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
246
seq_putc(m, temp_ptr[i]);
247
248
return 0;
249
250
}
251
252
static int tpm1_ascii_bios_measurements_show(struct seq_file *m, void *v)
253
{
254
char *eventname;
255
struct tcpa_event *event = v;
256
unsigned char *event_entry =
257
(unsigned char *)(v + sizeof(struct tcpa_event));
258
259
eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
260
if (!eventname)
261
return -ENOMEM;
262
263
/* 1st: PCR */
264
seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index));
265
266
/* 2nd: SHA1 */
267
seq_printf(m, "%20phN", event->pcr_value);
268
269
/* 3rd: event type identifier */
270
seq_printf(m, " %02x", do_endian_conversion(event->event_type));
271
272
get_event_name(eventname, event, event_entry);
273
274
/* 4th: eventname <= max + \'0' delimiter */
275
seq_printf(m, " %s\n", eventname);
276
277
kfree(eventname);
278
return 0;
279
}
280
281
const struct seq_operations tpm1_ascii_b_measurements_seqops = {
282
.start = tpm1_bios_measurements_start,
283
.next = tpm1_bios_measurements_next,
284
.stop = tpm1_bios_measurements_stop,
285
.show = tpm1_ascii_bios_measurements_show,
286
};
287
288
const struct seq_operations tpm1_binary_b_measurements_seqops = {
289
.start = tpm1_bios_measurements_start,
290
.next = tpm1_bios_measurements_next,
291
.stop = tpm1_bios_measurements_stop,
292
.show = tpm1_binary_bios_measurements_show,
293
};
294
295