xref: /openbmc/linux/include/linux/tpm_eventlog.h (revision d3f45053)
1fd3ec366SThiebaud Weksteen /* SPDX-License-Identifier: GPL-2.0 */
2fd3ec366SThiebaud Weksteen 
3fd3ec366SThiebaud Weksteen #ifndef __LINUX_TPM_EVENTLOG_H__
4fd3ec366SThiebaud Weksteen #define __LINUX_TPM_EVENTLOG_H__
5fd3ec366SThiebaud Weksteen 
6aa042475SRoberto Sassu #include <linux/tpm.h>
7fd3ec366SThiebaud Weksteen 
8fd3ec366SThiebaud Weksteen #define TCG_EVENT_NAME_LEN_MAX	255
9fd3ec366SThiebaud Weksteen #define MAX_TEXT_EVENT		1000	/* Max event string length */
10fd3ec366SThiebaud Weksteen #define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
11fd3ec366SThiebaud Weksteen 
124d01d29dSThiebaud Weksteen #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x1
134d01d29dSThiebaud Weksteen #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2   0x2
144d01d29dSThiebaud Weksteen 
15fd3ec366SThiebaud Weksteen #ifdef CONFIG_PPC64
16fd3ec366SThiebaud Weksteen #define do_endian_conversion(x) be32_to_cpu(x)
17fd3ec366SThiebaud Weksteen #else
18fd3ec366SThiebaud Weksteen #define do_endian_conversion(x) x
19fd3ec366SThiebaud Weksteen #endif
20fd3ec366SThiebaud Weksteen 
21fd3ec366SThiebaud Weksteen enum bios_platform_class {
22fd3ec366SThiebaud Weksteen 	BIOS_CLIENT = 0x00,
23fd3ec366SThiebaud Weksteen 	BIOS_SERVER = 0x01,
24fd3ec366SThiebaud Weksteen };
25fd3ec366SThiebaud Weksteen 
26fd3ec366SThiebaud Weksteen struct tcpa_event {
27fd3ec366SThiebaud Weksteen 	u32 pcr_index;
28fd3ec366SThiebaud Weksteen 	u32 event_type;
29fd3ec366SThiebaud Weksteen 	u8 pcr_value[20];	/* SHA1 */
30fd3ec366SThiebaud Weksteen 	u32 event_size;
3106ccf63dSGustavo A. R. Silva 	u8 event_data[];
32fd3ec366SThiebaud Weksteen };
33fd3ec366SThiebaud Weksteen 
34fd3ec366SThiebaud Weksteen enum tcpa_event_types {
35fd3ec366SThiebaud Weksteen 	PREBOOT = 0,
36fd3ec366SThiebaud Weksteen 	POST_CODE,
37fd3ec366SThiebaud Weksteen 	UNUSED,
38fd3ec366SThiebaud Weksteen 	NO_ACTION,
39fd3ec366SThiebaud Weksteen 	SEPARATOR,
40fd3ec366SThiebaud Weksteen 	ACTION,
41fd3ec366SThiebaud Weksteen 	EVENT_TAG,
42fd3ec366SThiebaud Weksteen 	SCRTM_CONTENTS,
43fd3ec366SThiebaud Weksteen 	SCRTM_VERSION,
44fd3ec366SThiebaud Weksteen 	CPU_MICROCODE,
45fd3ec366SThiebaud Weksteen 	PLATFORM_CONFIG_FLAGS,
46fd3ec366SThiebaud Weksteen 	TABLE_OF_DEVICES,
47fd3ec366SThiebaud Weksteen 	COMPACT_HASH,
48fd3ec366SThiebaud Weksteen 	IPL,
49fd3ec366SThiebaud Weksteen 	IPL_PARTITION_DATA,
50fd3ec366SThiebaud Weksteen 	NONHOST_CODE,
51fd3ec366SThiebaud Weksteen 	NONHOST_CONFIG,
52fd3ec366SThiebaud Weksteen 	NONHOST_INFO,
53fd3ec366SThiebaud Weksteen };
54fd3ec366SThiebaud Weksteen 
55fd3ec366SThiebaud Weksteen struct tcpa_pc_event {
56fd3ec366SThiebaud Weksteen 	u32 event_id;
57fd3ec366SThiebaud Weksteen 	u32 event_size;
5806ccf63dSGustavo A. R. Silva 	u8 event_data[];
59fd3ec366SThiebaud Weksteen };
60fd3ec366SThiebaud Weksteen 
61fd3ec366SThiebaud Weksteen enum tcpa_pc_event_ids {
62fd3ec366SThiebaud Weksteen 	SMBIOS = 1,
63fd3ec366SThiebaud Weksteen 	BIS_CERT,
64fd3ec366SThiebaud Weksteen 	POST_BIOS_ROM,
65fd3ec366SThiebaud Weksteen 	ESCD,
66fd3ec366SThiebaud Weksteen 	CMOS,
67fd3ec366SThiebaud Weksteen 	NVRAM,
68fd3ec366SThiebaud Weksteen 	OPTION_ROM_EXEC,
69fd3ec366SThiebaud Weksteen 	OPTION_ROM_CONFIG,
70fd3ec366SThiebaud Weksteen 	OPTION_ROM_MICROCODE = 10,
71fd3ec366SThiebaud Weksteen 	S_CRTM_VERSION,
72fd3ec366SThiebaud Weksteen 	S_CRTM_CONTENTS,
73fd3ec366SThiebaud Weksteen 	POST_CONTENTS,
74fd3ec366SThiebaud Weksteen 	HOST_TABLE_OF_DEVICES,
75fd3ec366SThiebaud Weksteen };
76fd3ec366SThiebaud Weksteen 
77fd3ec366SThiebaud Weksteen /* http://www.trustedcomputinggroup.org/tcg-efi-protocol-specification/ */
78fd3ec366SThiebaud Weksteen 
79fd3ec366SThiebaud Weksteen struct tcg_efi_specid_event_algs {
80fd3ec366SThiebaud Weksteen 	u16 alg_id;
81fd3ec366SThiebaud Weksteen 	u16 digest_size;
82fd3ec366SThiebaud Weksteen } __packed;
83fd3ec366SThiebaud Weksteen 
847dfc06a0SFabian Vogt #define TCG_SPECID_SIG "Spec ID Event03"
857dfc06a0SFabian Vogt 
86c8faabfcSRoberto Sassu struct tcg_efi_specid_event_head {
87fd3ec366SThiebaud Weksteen 	u8 signature[16];
88fd3ec366SThiebaud Weksteen 	u32 platform_class;
89fd3ec366SThiebaud Weksteen 	u8 spec_version_minor;
90fd3ec366SThiebaud Weksteen 	u8 spec_version_major;
91fd3ec366SThiebaud Weksteen 	u8 spec_errata;
92fd3ec366SThiebaud Weksteen 	u8 uintnsize;
93fd3ec366SThiebaud Weksteen 	u32 num_algs;
94c8faabfcSRoberto Sassu 	struct tcg_efi_specid_event_algs digest_sizes[];
95fd3ec366SThiebaud Weksteen } __packed;
96fd3ec366SThiebaud Weksteen 
97fd3ec366SThiebaud Weksteen struct tcg_pcr_event {
98fd3ec366SThiebaud Weksteen 	u32 pcr_idx;
99fd3ec366SThiebaud Weksteen 	u32 event_type;
100fd3ec366SThiebaud Weksteen 	u8 digest[20];
101fd3ec366SThiebaud Weksteen 	u32 event_size;
102ab91c2a8SGustavo A. R. Silva 	u8 event[];
103fd3ec366SThiebaud Weksteen } __packed;
104fd3ec366SThiebaud Weksteen 
105fd3ec366SThiebaud Weksteen struct tcg_event_field {
106fd3ec366SThiebaud Weksteen 	u32 event_size;
10706ccf63dSGustavo A. R. Silva 	u8 event[];
108fd3ec366SThiebaud Weksteen } __packed;
109fd3ec366SThiebaud Weksteen 
110c8faabfcSRoberto Sassu struct tcg_pcr_event2_head {
111fd3ec366SThiebaud Weksteen 	u32 pcr_idx;
112fd3ec366SThiebaud Weksteen 	u32 event_type;
113fd3ec366SThiebaud Weksteen 	u32 count;
114aa042475SRoberto Sassu 	struct tpm_digest digests[];
115fd3ec366SThiebaud Weksteen } __packed;
116fd3ec366SThiebaud Weksteen 
117c46f3405SMatthew Garrett struct tcg_algorithm_size {
118c46f3405SMatthew Garrett 	u16 algorithm_id;
119c46f3405SMatthew Garrett 	u16 algorithm_size;
120c46f3405SMatthew Garrett };
121c46f3405SMatthew Garrett 
122c46f3405SMatthew Garrett struct tcg_algorithm_info {
123c46f3405SMatthew Garrett 	u8 signature[16];
124c46f3405SMatthew Garrett 	u32 platform_class;
125c46f3405SMatthew Garrett 	u8 spec_version_minor;
126c46f3405SMatthew Garrett 	u8 spec_version_major;
127c46f3405SMatthew Garrett 	u8 spec_errata;
128c46f3405SMatthew Garrett 	u8 uintn_size;
129c46f3405SMatthew Garrett 	u32 number_of_algorithms;
130c46f3405SMatthew Garrett 	struct tcg_algorithm_size digest_sizes[];
131c46f3405SMatthew Garrett };
132c46f3405SMatthew Garrett 
133c46f3405SMatthew Garrett #ifndef TPM_MEMREMAP
134c46f3405SMatthew Garrett #define TPM_MEMREMAP(start, size) NULL
135c46f3405SMatthew Garrett #endif
136c46f3405SMatthew Garrett 
137c46f3405SMatthew Garrett #ifndef TPM_MEMUNMAP
138c46f3405SMatthew Garrett #define TPM_MEMUNMAP(start, size) do{} while(0)
139c46f3405SMatthew Garrett #endif
140c46f3405SMatthew Garrett 
14144038bc5SMatthew Garrett /**
14244038bc5SMatthew Garrett  * __calc_tpm2_event_size - calculate the size of a TPM2 event log entry
14344038bc5SMatthew Garrett  * @event:        Pointer to the event whose size should be calculated
14444038bc5SMatthew Garrett  * @event_header: Pointer to the initial event containing the digest lengths
145c46f3405SMatthew Garrett  * @do_mapping:   Whether or not the event needs to be mapped
14644038bc5SMatthew Garrett  *
14744038bc5SMatthew Garrett  * The TPM2 event log format can contain multiple digests corresponding to
14844038bc5SMatthew Garrett  * separate PCR banks, and also contains a variable length of the data that
14944038bc5SMatthew Garrett  * was measured. This requires knowledge of how long each digest type is,
15044038bc5SMatthew Garrett  * and this information is contained within the first event in the log.
15144038bc5SMatthew Garrett  *
15244038bc5SMatthew Garrett  * We calculate the length by examining the number of events, and then looking
15344038bc5SMatthew Garrett  * at each event in turn to determine how much space is used for events in
15444038bc5SMatthew Garrett  * total. Once we've done this we know the offset of the data length field,
15544038bc5SMatthew Garrett  * and can calculate the total size of the event.
15644038bc5SMatthew Garrett  *
157e658c82bSJerry Snitselaar  * Return: size of the event on success, 0 on failure
15844038bc5SMatthew Garrett  */
15944038bc5SMatthew Garrett 
__calc_tpm2_event_size(struct tcg_pcr_event2_head * event,struct tcg_pcr_event * event_header,bool do_mapping)160bed45936SHuacai Chen static __always_inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
161c46f3405SMatthew Garrett 					 struct tcg_pcr_event *event_header,
162c46f3405SMatthew Garrett 					 bool do_mapping)
16344038bc5SMatthew Garrett {
16444038bc5SMatthew Garrett 	struct tcg_efi_specid_event_head *efispecid;
16544038bc5SMatthew Garrett 	struct tcg_event_field *event_field;
166c46f3405SMatthew Garrett 	void *mapping = NULL;
167c46f3405SMatthew Garrett 	int mapping_size;
16844038bc5SMatthew Garrett 	void *marker;
16944038bc5SMatthew Garrett 	void *marker_start;
17044038bc5SMatthew Garrett 	u32 halg_size;
17144038bc5SMatthew Garrett 	size_t size;
17244038bc5SMatthew Garrett 	u16 halg;
17344038bc5SMatthew Garrett 	int i;
17444038bc5SMatthew Garrett 	int j;
175047d50aeSPeter Jones 	u32 count, event_type;
1767dfc06a0SFabian Vogt 	const u8 zero_digest[sizeof(event_header->digest)] = {0};
17744038bc5SMatthew Garrett 
17844038bc5SMatthew Garrett 	marker = event;
17944038bc5SMatthew Garrett 	marker_start = marker;
18044038bc5SMatthew Garrett 	marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
18144038bc5SMatthew Garrett 		+ sizeof(event->count);
18244038bc5SMatthew Garrett 
183c46f3405SMatthew Garrett 	/* Map the event header */
184c46f3405SMatthew Garrett 	if (do_mapping) {
185c46f3405SMatthew Garrett 		mapping_size = marker - marker_start;
186c46f3405SMatthew Garrett 		mapping = TPM_MEMREMAP((unsigned long)marker_start,
187c46f3405SMatthew Garrett 				       mapping_size);
188c46f3405SMatthew Garrett 		if (!mapping) {
189c46f3405SMatthew Garrett 			size = 0;
190c46f3405SMatthew Garrett 			goto out;
191c46f3405SMatthew Garrett 		}
192c46f3405SMatthew Garrett 	} else {
193c46f3405SMatthew Garrett 		mapping = marker_start;
194c46f3405SMatthew Garrett 	}
195c46f3405SMatthew Garrett 
196c46f3405SMatthew Garrett 	event = (struct tcg_pcr_event2_head *)mapping;
197047d50aeSPeter Jones 	/*
198047d50aeSPeter Jones 	 * The loop below will unmap these fields if the log is larger than
199047d50aeSPeter Jones 	 * one page, so save them here for reference:
200047d50aeSPeter Jones 	 */
201*d3f45053SArd Biesheuvel 	count = event->count;
202*d3f45053SArd Biesheuvel 	event_type = event->event_type;
203c46f3405SMatthew Garrett 
2047dfc06a0SFabian Vogt 	/* Verify that it's the log header */
2057dfc06a0SFabian Vogt 	if (event_header->pcr_idx != 0 ||
2067dfc06a0SFabian Vogt 	    event_header->event_type != NO_ACTION ||
2077dfc06a0SFabian Vogt 	    memcmp(event_header->digest, zero_digest, sizeof(zero_digest))) {
2087dfc06a0SFabian Vogt 		size = 0;
2097dfc06a0SFabian Vogt 		goto out;
2107dfc06a0SFabian Vogt 	}
2117dfc06a0SFabian Vogt 
21244038bc5SMatthew Garrett 	efispecid = (struct tcg_efi_specid_event_head *)event_header->event;
21344038bc5SMatthew Garrett 
2147f3d176fSTyler Hicks 	/*
2157f3d176fSTyler Hicks 	 * Perform validation of the event in order to identify malformed
2167f3d176fSTyler Hicks 	 * events. This function may be asked to parse arbitrary byte sequences
2177f3d176fSTyler Hicks 	 * immediately following a valid event log. The caller expects this
2187f3d176fSTyler Hicks 	 * function to recognize that the byte sequence is not a valid event
2197f3d176fSTyler Hicks 	 * and to return an event size of 0.
2207f3d176fSTyler Hicks 	 */
2217dfc06a0SFabian Vogt 	if (memcmp(efispecid->signature, TCG_SPECID_SIG,
2227f3d176fSTyler Hicks 		   sizeof(TCG_SPECID_SIG)) ||
2237f3d176fSTyler Hicks 	    !efispecid->num_algs || count != efispecid->num_algs) {
224c46f3405SMatthew Garrett 		size = 0;
225c46f3405SMatthew Garrett 		goto out;
226c46f3405SMatthew Garrett 	}
22744038bc5SMatthew Garrett 
228047d50aeSPeter Jones 	for (i = 0; i < count; i++) {
22944038bc5SMatthew Garrett 		halg_size = sizeof(event->digests[i].alg_id);
230c46f3405SMatthew Garrett 
231c46f3405SMatthew Garrett 		/* Map the digest's algorithm identifier */
232c46f3405SMatthew Garrett 		if (do_mapping) {
233c46f3405SMatthew Garrett 			TPM_MEMUNMAP(mapping, mapping_size);
234c46f3405SMatthew Garrett 			mapping_size = halg_size;
235c46f3405SMatthew Garrett 			mapping = TPM_MEMREMAP((unsigned long)marker,
236c46f3405SMatthew Garrett 					     mapping_size);
237c46f3405SMatthew Garrett 			if (!mapping) {
238c46f3405SMatthew Garrett 				size = 0;
239c46f3405SMatthew Garrett 				goto out;
240c46f3405SMatthew Garrett 			}
241c46f3405SMatthew Garrett 		} else {
242c46f3405SMatthew Garrett 			mapping = marker;
243c46f3405SMatthew Garrett 		}
244c46f3405SMatthew Garrett 
245c46f3405SMatthew Garrett 		memcpy(&halg, mapping, halg_size);
24644038bc5SMatthew Garrett 		marker = marker + halg_size;
247c46f3405SMatthew Garrett 
24844038bc5SMatthew Garrett 		for (j = 0; j < efispecid->num_algs; j++) {
24944038bc5SMatthew Garrett 			if (halg == efispecid->digest_sizes[j].alg_id) {
25044038bc5SMatthew Garrett 				marker +=
25144038bc5SMatthew Garrett 					efispecid->digest_sizes[j].digest_size;
25244038bc5SMatthew Garrett 				break;
25344038bc5SMatthew Garrett 			}
25444038bc5SMatthew Garrett 		}
25544038bc5SMatthew Garrett 		/* Algorithm without known length. Such event is unparseable. */
256c46f3405SMatthew Garrett 		if (j == efispecid->num_algs) {
257c46f3405SMatthew Garrett 			size = 0;
258c46f3405SMatthew Garrett 			goto out;
259c46f3405SMatthew Garrett 		}
26044038bc5SMatthew Garrett 	}
26144038bc5SMatthew Garrett 
262c46f3405SMatthew Garrett 	/*
263c46f3405SMatthew Garrett 	 * Map the event size - we don't read from the event itself, so
264c46f3405SMatthew Garrett 	 * we don't need to map it
265c46f3405SMatthew Garrett 	 */
266c46f3405SMatthew Garrett 	if (do_mapping) {
267c46f3405SMatthew Garrett 		TPM_MEMUNMAP(mapping, mapping_size);
268c46f3405SMatthew Garrett 		mapping_size += sizeof(event_field->event_size);
269c46f3405SMatthew Garrett 		mapping = TPM_MEMREMAP((unsigned long)marker,
270c46f3405SMatthew Garrett 				       mapping_size);
271c46f3405SMatthew Garrett 		if (!mapping) {
272c46f3405SMatthew Garrett 			size = 0;
273c46f3405SMatthew Garrett 			goto out;
274c46f3405SMatthew Garrett 		}
275c46f3405SMatthew Garrett 	} else {
276c46f3405SMatthew Garrett 		mapping = marker;
277c46f3405SMatthew Garrett 	}
278c46f3405SMatthew Garrett 
279c46f3405SMatthew Garrett 	event_field = (struct tcg_event_field *)mapping;
280c46f3405SMatthew Garrett 
28144038bc5SMatthew Garrett 	marker = marker + sizeof(event_field->event_size)
28244038bc5SMatthew Garrett 		+ event_field->event_size;
28344038bc5SMatthew Garrett 	size = marker - marker_start;
28444038bc5SMatthew Garrett 
285047d50aeSPeter Jones 	if (event_type == 0 && event_field->event_size == 0)
286c46f3405SMatthew Garrett 		size = 0;
287047d50aeSPeter Jones 
288c46f3405SMatthew Garrett out:
289c46f3405SMatthew Garrett 	if (do_mapping)
290c46f3405SMatthew Garrett 		TPM_MEMUNMAP(mapping, mapping_size);
29144038bc5SMatthew Garrett 	return size;
29244038bc5SMatthew Garrett }
293c46f3405SMatthew Garrett 
294fd3ec366SThiebaud Weksteen #endif
295