Skip to content

Commit 4d23cc3

Browse files
naynajainJarkko Sakkinen
authored andcommitted
tpm: add securityfs support for TPM 2.0 firmware event log
Unlike the device driver support for TPM 1.2, the TPM 2.0 does not support the securityfs pseudo files for displaying the firmware event log. This patch enables support for providing the TPM 2.0 event log in binary form. TPM 2.0 event log supports a crypto agile format that records multiple digests, which is different from TPM 1.2. This patch enables the tpm_bios_log_setup for TPM 2.0 and adds the event log parser which understand the TPM 2.0 crypto agile format. Signed-off-by: Nayna Jain <nayna@linux.vnet.ibm.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Tested-by: Kenneth Goldman <kgold@linux.vnet.ibm.com> Tested-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
1 parent e46e22f commit 4d23cc3

File tree

6 files changed

+279
-22
lines changed

6 files changed

+279
-22
lines changed

drivers/char/tpm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#
44
obj-$(CONFIG_TCG_TPM) += tpm.o
55
tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
6-
tpm_eventlog.o
6+
tpm1_eventlog.o tpm2_eventlog.o
77
tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
88
tpm-$(CONFIG_OF) += tpm_of.o
99
obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o

drivers/char/tpm/tpm.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636
#include <linux/highmem.h>
3737
#include <crypto/hash_info.h>
3838

39-
#include "tpm_eventlog.h"
40-
4139
enum tpm_const {
4240
TPM_MINOR = 224, /* officially assigned */
4341
TPM_BUFSIZE = 4096,
@@ -151,6 +149,11 @@ enum tpm_chip_flags {
151149
TPM_CHIP_FLAG_HAVE_TIMEOUTS = BIT(4),
152150
};
153151

152+
struct tpm_bios_log {
153+
void *bios_event_log;
154+
void *bios_event_log_end;
155+
};
156+
154157
struct tpm_chip_seqops {
155158
struct tpm_chip *chip;
156159
const struct seq_operations *seqops;

drivers/char/tpm/tpm_eventlog.c renamed to drivers/char/tpm/tpm1_eventlog.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -390,9 +390,6 @@ int tpm_bios_log_setup(struct tpm_chip *chip)
390390
unsigned int cnt;
391391
int rc = 0;
392392

393-
if (chip->flags & TPM_CHIP_FLAG_TPM2)
394-
return 0;
395-
396393
rc = tpm_read_log(chip);
397394
if (rc)
398395
return rc;
@@ -407,7 +404,13 @@ int tpm_bios_log_setup(struct tpm_chip *chip)
407404
cnt++;
408405

409406
chip->bin_log_seqops.chip = chip;
410-
chip->bin_log_seqops.seqops = &tpm_binary_b_measurements_seqops;
407+
if (chip->flags & TPM_CHIP_FLAG_TPM2)
408+
chip->bin_log_seqops.seqops =
409+
&tpm2_binary_b_measurements_seqops;
410+
else
411+
chip->bin_log_seqops.seqops =
412+
&tpm_binary_b_measurements_seqops;
413+
411414

412415
chip->bios_dir[cnt] =
413416
securityfs_create_file("binary_bios_measurements",
@@ -418,17 +421,21 @@ int tpm_bios_log_setup(struct tpm_chip *chip)
418421
goto err;
419422
cnt++;
420423

421-
chip->ascii_log_seqops.chip = chip;
422-
chip->ascii_log_seqops.seqops = &tpm_ascii_b_measurements_seqops;
424+
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
423425

424-
chip->bios_dir[cnt] =
425-
securityfs_create_file("ascii_bios_measurements",
426-
0440, chip->bios_dir[0],
427-
(void *)&chip->ascii_log_seqops,
428-
&tpm_bios_measurements_ops);
429-
if (IS_ERR(chip->bios_dir[cnt]))
430-
goto err;
431-
cnt++;
426+
chip->ascii_log_seqops.chip = chip;
427+
chip->ascii_log_seqops.seqops =
428+
&tpm_ascii_b_measurements_seqops;
429+
430+
chip->bios_dir[cnt] =
431+
securityfs_create_file("ascii_bios_measurements",
432+
0440, chip->bios_dir[0],
433+
(void *)&chip->ascii_log_seqops,
434+
&tpm_bios_measurements_ops);
435+
if (IS_ERR(chip->bios_dir[cnt]))
436+
goto err;
437+
cnt++;
438+
}
432439

433440
return 0;
434441

drivers/char/tpm/tpm2_eventlog.c

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/*
2+
* Copyright (C) 2016 IBM Corporation
3+
*
4+
* Authors:
5+
* Nayna Jain <nayna@linux.vnet.ibm.com>
6+
*
7+
* Access to TPM 2.0 event log as written by Firmware.
8+
* It assumes that writer of event log has followed TCG Specification
9+
* for Family "2.0" and written the event data in little endian.
10+
* With that, it doesn't need any endian conversion for structure
11+
* content.
12+
*
13+
* This program is free software; you can redistribute it and/or
14+
* modify it under the terms of the GNU General Public License
15+
* as published by the Free Software Foundation; either version
16+
* 2 of the License, or (at your option) any later version.
17+
*/
18+
19+
#include <linux/seq_file.h>
20+
#include <linux/fs.h>
21+
#include <linux/security.h>
22+
#include <linux/module.h>
23+
#include <linux/slab.h>
24+
25+
#include "tpm.h"
26+
#include "tpm_eventlog.h"
27+
28+
/*
29+
* calc_tpm2_event_size() - calculate the event size, where event
30+
* is an entry in the TPM 2.0 event log. The event is of type Crypto
31+
* Agile Log Entry Format as defined in TCG EFI Protocol Specification
32+
* Family "2.0".
33+
34+
* @event: event whose size is to be calculated.
35+
* @event_header: the first event in the event log.
36+
*
37+
* Returns size of the event. If it is an invalid event, returns 0.
38+
*/
39+
static int calc_tpm2_event_size(struct tcg_pcr_event2 *event,
40+
struct tcg_pcr_event *event_header)
41+
{
42+
struct tcg_efi_specid_event *efispecid;
43+
struct tcg_event_field *event_field;
44+
void *marker;
45+
void *marker_start;
46+
u32 halg_size;
47+
size_t size;
48+
u16 halg;
49+
int i;
50+
int j;
51+
52+
marker = event;
53+
marker_start = marker;
54+
marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
55+
+ sizeof(event->count);
56+
57+
efispecid = (struct tcg_efi_specid_event *)event_header->event;
58+
59+
for (i = 0; (i < event->count) && (i < TPM2_ACTIVE_PCR_BANKS);
60+
i++) {
61+
halg_size = sizeof(event->digests[i].alg_id);
62+
memcpy(&halg, marker, halg_size);
63+
marker = marker + halg_size;
64+
for (j = 0; (j < efispecid->num_algs); j++) {
65+
if (halg == efispecid->digest_sizes[j].alg_id) {
66+
marker = marker +
67+
efispecid->digest_sizes[j].digest_size;
68+
break;
69+
}
70+
}
71+
}
72+
73+
event_field = (struct tcg_event_field *)marker;
74+
marker = marker + sizeof(event_field->event_size)
75+
+ event_field->event_size;
76+
size = marker - marker_start;
77+
78+
if ((event->event_type == 0) && (event_field->event_size == 0))
79+
return 0;
80+
81+
return size;
82+
}
83+
84+
static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
85+
{
86+
struct tpm_chip *chip = m->private;
87+
struct tpm_bios_log *log = &chip->log;
88+
void *addr = log->bios_event_log;
89+
void *limit = log->bios_event_log_end;
90+
struct tcg_pcr_event *event_header;
91+
struct tcg_pcr_event2 *event;
92+
size_t size;
93+
int i;
94+
95+
event_header = addr;
96+
size = sizeof(struct tcg_pcr_event) - sizeof(event_header->event)
97+
+ event_header->event_size;
98+
99+
if (*pos == 0) {
100+
if (addr + size < limit) {
101+
if ((event_header->event_type == 0) &&
102+
(event_header->event_size == 0))
103+
return NULL;
104+
return SEQ_START_TOKEN;
105+
}
106+
}
107+
108+
if (*pos > 0) {
109+
addr += size;
110+
event = addr;
111+
size = calc_tpm2_event_size(event, event_header);
112+
if ((addr + size >= limit) || (size == 0))
113+
return NULL;
114+
}
115+
116+
for (i = 0; i < (*pos - 1); i++) {
117+
event = addr;
118+
size = calc_tpm2_event_size(event, event_header);
119+
120+
if ((addr + size >= limit) || (size == 0))
121+
return NULL;
122+
addr += size;
123+
}
124+
125+
return addr;
126+
}
127+
128+
static void *tpm2_bios_measurements_next(struct seq_file *m, void *v,
129+
loff_t *pos)
130+
{
131+
struct tcg_pcr_event *event_header;
132+
struct tcg_pcr_event2 *event;
133+
struct tpm_chip *chip = m->private;
134+
struct tpm_bios_log *log = &chip->log;
135+
void *limit = log->bios_event_log_end;
136+
size_t event_size;
137+
void *marker;
138+
139+
event_header = log->bios_event_log;
140+
141+
if (v == SEQ_START_TOKEN) {
142+
event_size = sizeof(struct tcg_pcr_event) -
143+
sizeof(event_header->event) + event_header->event_size;
144+
marker = event_header;
145+
} else {
146+
event = v;
147+
event_size = calc_tpm2_event_size(event, event_header);
148+
if (event_size == 0)
149+
return NULL;
150+
marker = event;
151+
}
152+
153+
marker = marker + event_size;
154+
if (marker >= limit)
155+
return NULL;
156+
v = marker;
157+
event = v;
158+
159+
event_size = calc_tpm2_event_size(event, event_header);
160+
if (((v + event_size) >= limit) || (event_size == 0))
161+
return NULL;
162+
163+
(*pos)++;
164+
return v;
165+
}
166+
167+
static void tpm2_bios_measurements_stop(struct seq_file *m, void *v)
168+
{
169+
}
170+
171+
static int tpm2_binary_bios_measurements_show(struct seq_file *m, void *v)
172+
{
173+
struct tpm_chip *chip = m->private;
174+
struct tpm_bios_log *log = &chip->log;
175+
struct tcg_pcr_event *event_header = log->bios_event_log;
176+
struct tcg_pcr_event2 *event = v;
177+
void *temp_ptr;
178+
size_t size;
179+
180+
if (v == SEQ_START_TOKEN) {
181+
size = sizeof(struct tcg_pcr_event) -
182+
sizeof(event_header->event) + event_header->event_size;
183+
184+
temp_ptr = event_header;
185+
186+
if (size > 0)
187+
seq_write(m, temp_ptr, size);
188+
} else {
189+
size = calc_tpm2_event_size(event, event_header);
190+
temp_ptr = event;
191+
if (size > 0)
192+
seq_write(m, temp_ptr, size);
193+
}
194+
195+
return 0;
196+
}
197+
198+
const struct seq_operations tpm2_binary_b_measurements_seqops = {
199+
.start = tpm2_bios_measurements_start,
200+
.next = tpm2_bios_measurements_next,
201+
.stop = tpm2_bios_measurements_stop,
202+
.show = tpm2_binary_bios_measurements_show,
203+
};

drivers/char/tpm/tpm_acpi.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
5454
u64 len, start;
5555
struct tpm_bios_log *log;
5656

57+
if (chip->flags & TPM_CHIP_FLAG_TPM2)
58+
return -ENODEV;
59+
5760
log = &chip->log;
5861

5962
/* Unfortuntely ACPI does not associate the event log with a specific

drivers/char/tpm/tpm_eventlog.h

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
#ifndef __TPM_EVENTLOG_H__
33
#define __TPM_EVENTLOG_H__
44

5+
#include <crypto/hash_info.h>
6+
57
#define TCG_EVENT_NAME_LEN_MAX 255
68
#define MAX_TEXT_EVENT 1000 /* Max event string length */
79
#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
10+
#define TPM2_ACTIVE_PCR_BANKS 3
811

912
#ifdef CONFIG_PPC64
1013
#define do_endian_conversion(x) be32_to_cpu(x)
@@ -17,11 +20,6 @@ enum bios_platform_class {
1720
BIOS_SERVER = 0x01,
1821
};
1922

20-
struct tpm_bios_log {
21-
void *bios_event_log;
22-
void *bios_event_log_end;
23-
};
24-
2523
struct tcpa_event {
2624
u32 pcr_index;
2725
u32 event_type;
@@ -73,6 +71,49 @@ enum tcpa_pc_event_ids {
7371
HOST_TABLE_OF_DEVICES,
7472
};
7573

74+
/* http://www.trustedcomputinggroup.org/tcg-efi-protocol-specification/ */
75+
76+
struct tcg_efi_specid_event_algs {
77+
u16 alg_id;
78+
u16 digest_size;
79+
} __packed;
80+
81+
struct tcg_efi_specid_event {
82+
u8 signature[16];
83+
u32 platform_class;
84+
u8 spec_version_minor;
85+
u8 spec_version_major;
86+
u8 spec_errata;
87+
u8 uintnsize;
88+
u32 num_algs;
89+
struct tcg_efi_specid_event_algs digest_sizes[TPM2_ACTIVE_PCR_BANKS];
90+
u8 vendor_info_size;
91+
u8 vendor_info[0];
92+
} __packed;
93+
94+
struct tcg_pcr_event {
95+
u32 pcr_idx;
96+
u32 event_type;
97+
u8 digest[20];
98+
u32 event_size;
99+
u8 event[0];
100+
} __packed;
101+
102+
struct tcg_event_field {
103+
u32 event_size;
104+
u8 event[0];
105+
} __packed;
106+
107+
struct tcg_pcr_event2 {
108+
u32 pcr_idx;
109+
u32 event_type;
110+
u32 count;
111+
struct tpm2_digest digests[TPM2_ACTIVE_PCR_BANKS];
112+
struct tcg_event_field event;
113+
} __packed;
114+
115+
extern const struct seq_operations tpm2_binary_b_measurements_seqops;
116+
76117
#if defined(CONFIG_ACPI)
77118
int tpm_read_log_acpi(struct tpm_chip *chip);
78119
#else

0 commit comments

Comments
 (0)