cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tpm_eventlog.h (6699B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2
      3#ifndef __LINUX_TPM_EVENTLOG_H__
      4#define __LINUX_TPM_EVENTLOG_H__
      5
      6#include <linux/tpm.h>
      7
      8#define TCG_EVENT_NAME_LEN_MAX	255
      9#define MAX_TEXT_EVENT		1000	/* Max event string length */
     10#define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
     11
     12#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x1
     13#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2   0x2
     14
     15#ifdef CONFIG_PPC64
     16#define do_endian_conversion(x) be32_to_cpu(x)
     17#else
     18#define do_endian_conversion(x) x
     19#endif
     20
     21enum bios_platform_class {
     22	BIOS_CLIENT = 0x00,
     23	BIOS_SERVER = 0x01,
     24};
     25
     26struct tcpa_event {
     27	u32 pcr_index;
     28	u32 event_type;
     29	u8 pcr_value[20];	/* SHA1 */
     30	u32 event_size;
     31	u8 event_data[];
     32};
     33
     34enum tcpa_event_types {
     35	PREBOOT = 0,
     36	POST_CODE,
     37	UNUSED,
     38	NO_ACTION,
     39	SEPARATOR,
     40	ACTION,
     41	EVENT_TAG,
     42	SCRTM_CONTENTS,
     43	SCRTM_VERSION,
     44	CPU_MICROCODE,
     45	PLATFORM_CONFIG_FLAGS,
     46	TABLE_OF_DEVICES,
     47	COMPACT_HASH,
     48	IPL,
     49	IPL_PARTITION_DATA,
     50	NONHOST_CODE,
     51	NONHOST_CONFIG,
     52	NONHOST_INFO,
     53};
     54
     55struct tcpa_pc_event {
     56	u32 event_id;
     57	u32 event_size;
     58	u8 event_data[];
     59};
     60
     61enum tcpa_pc_event_ids {
     62	SMBIOS = 1,
     63	BIS_CERT,
     64	POST_BIOS_ROM,
     65	ESCD,
     66	CMOS,
     67	NVRAM,
     68	OPTION_ROM_EXEC,
     69	OPTION_ROM_CONFIG,
     70	OPTION_ROM_MICROCODE = 10,
     71	S_CRTM_VERSION,
     72	S_CRTM_CONTENTS,
     73	POST_CONTENTS,
     74	HOST_TABLE_OF_DEVICES,
     75};
     76
     77/* http://www.trustedcomputinggroup.org/tcg-efi-protocol-specification/ */
     78
     79struct tcg_efi_specid_event_algs {
     80	u16 alg_id;
     81	u16 digest_size;
     82} __packed;
     83
     84#define TCG_SPECID_SIG "Spec ID Event03"
     85
     86struct tcg_efi_specid_event_head {
     87	u8 signature[16];
     88	u32 platform_class;
     89	u8 spec_version_minor;
     90	u8 spec_version_major;
     91	u8 spec_errata;
     92	u8 uintnsize;
     93	u32 num_algs;
     94	struct tcg_efi_specid_event_algs digest_sizes[];
     95} __packed;
     96
     97struct tcg_pcr_event {
     98	u32 pcr_idx;
     99	u32 event_type;
    100	u8 digest[20];
    101	u32 event_size;
    102	u8 event[];
    103} __packed;
    104
    105struct tcg_event_field {
    106	u32 event_size;
    107	u8 event[];
    108} __packed;
    109
    110struct tcg_pcr_event2_head {
    111	u32 pcr_idx;
    112	u32 event_type;
    113	u32 count;
    114	struct tpm_digest digests[];
    115} __packed;
    116
    117struct tcg_algorithm_size {
    118	u16 algorithm_id;
    119	u16 algorithm_size;
    120};
    121
    122struct tcg_algorithm_info {
    123	u8 signature[16];
    124	u32 platform_class;
    125	u8 spec_version_minor;
    126	u8 spec_version_major;
    127	u8 spec_errata;
    128	u8 uintn_size;
    129	u32 number_of_algorithms;
    130	struct tcg_algorithm_size digest_sizes[];
    131};
    132
    133#ifndef TPM_MEMREMAP
    134#define TPM_MEMREMAP(start, size) NULL
    135#endif
    136
    137#ifndef TPM_MEMUNMAP
    138#define TPM_MEMUNMAP(start, size) do{} while(0)
    139#endif
    140
    141/**
    142 * __calc_tpm2_event_size - calculate the size of a TPM2 event log entry
    143 * @event:        Pointer to the event whose size should be calculated
    144 * @event_header: Pointer to the initial event containing the digest lengths
    145 * @do_mapping:   Whether or not the event needs to be mapped
    146 *
    147 * The TPM2 event log format can contain multiple digests corresponding to
    148 * separate PCR banks, and also contains a variable length of the data that
    149 * was measured. This requires knowledge of how long each digest type is,
    150 * and this information is contained within the first event in the log.
    151 *
    152 * We calculate the length by examining the number of events, and then looking
    153 * at each event in turn to determine how much space is used for events in
    154 * total. Once we've done this we know the offset of the data length field,
    155 * and can calculate the total size of the event.
    156 *
    157 * Return: size of the event on success, 0 on failure
    158 */
    159
    160static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
    161					 struct tcg_pcr_event *event_header,
    162					 bool do_mapping)
    163{
    164	struct tcg_efi_specid_event_head *efispecid;
    165	struct tcg_event_field *event_field;
    166	void *mapping = NULL;
    167	int mapping_size;
    168	void *marker;
    169	void *marker_start;
    170	u32 halg_size;
    171	size_t size;
    172	u16 halg;
    173	int i;
    174	int j;
    175	u32 count, event_type;
    176	const u8 zero_digest[sizeof(event_header->digest)] = {0};
    177
    178	marker = event;
    179	marker_start = marker;
    180	marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
    181		+ sizeof(event->count);
    182
    183	/* Map the event header */
    184	if (do_mapping) {
    185		mapping_size = marker - marker_start;
    186		mapping = TPM_MEMREMAP((unsigned long)marker_start,
    187				       mapping_size);
    188		if (!mapping) {
    189			size = 0;
    190			goto out;
    191		}
    192	} else {
    193		mapping = marker_start;
    194	}
    195
    196	event = (struct tcg_pcr_event2_head *)mapping;
    197	/*
    198	 * The loop below will unmap these fields if the log is larger than
    199	 * one page, so save them here for reference:
    200	 */
    201	count = READ_ONCE(event->count);
    202	event_type = READ_ONCE(event->event_type);
    203
    204	/* Verify that it's the log header */
    205	if (event_header->pcr_idx != 0 ||
    206	    event_header->event_type != NO_ACTION ||
    207	    memcmp(event_header->digest, zero_digest, sizeof(zero_digest))) {
    208		size = 0;
    209		goto out;
    210	}
    211
    212	efispecid = (struct tcg_efi_specid_event_head *)event_header->event;
    213
    214	/*
    215	 * Perform validation of the event in order to identify malformed
    216	 * events. This function may be asked to parse arbitrary byte sequences
    217	 * immediately following a valid event log. The caller expects this
    218	 * function to recognize that the byte sequence is not a valid event
    219	 * and to return an event size of 0.
    220	 */
    221	if (memcmp(efispecid->signature, TCG_SPECID_SIG,
    222		   sizeof(TCG_SPECID_SIG)) ||
    223	    !efispecid->num_algs || count != efispecid->num_algs) {
    224		size = 0;
    225		goto out;
    226	}
    227
    228	for (i = 0; i < count; i++) {
    229		halg_size = sizeof(event->digests[i].alg_id);
    230
    231		/* Map the digest's algorithm identifier */
    232		if (do_mapping) {
    233			TPM_MEMUNMAP(mapping, mapping_size);
    234			mapping_size = halg_size;
    235			mapping = TPM_MEMREMAP((unsigned long)marker,
    236					     mapping_size);
    237			if (!mapping) {
    238				size = 0;
    239				goto out;
    240			}
    241		} else {
    242			mapping = marker;
    243		}
    244
    245		memcpy(&halg, mapping, halg_size);
    246		marker = marker + halg_size;
    247
    248		for (j = 0; j < efispecid->num_algs; j++) {
    249			if (halg == efispecid->digest_sizes[j].alg_id) {
    250				marker +=
    251					efispecid->digest_sizes[j].digest_size;
    252				break;
    253			}
    254		}
    255		/* Algorithm without known length. Such event is unparseable. */
    256		if (j == efispecid->num_algs) {
    257			size = 0;
    258			goto out;
    259		}
    260	}
    261
    262	/*
    263	 * Map the event size - we don't read from the event itself, so
    264	 * we don't need to map it
    265	 */
    266	if (do_mapping) {
    267		TPM_MEMUNMAP(mapping, mapping_size);
    268		mapping_size += sizeof(event_field->event_size);
    269		mapping = TPM_MEMREMAP((unsigned long)marker,
    270				       mapping_size);
    271		if (!mapping) {
    272			size = 0;
    273			goto out;
    274		}
    275	} else {
    276		mapping = marker;
    277	}
    278
    279	event_field = (struct tcg_event_field *)mapping;
    280
    281	marker = marker + sizeof(event_field->event_size)
    282		+ event_field->event_size;
    283	size = marker - marker_start;
    284
    285	if (event_type == 0 && event_field->event_size == 0)
    286		size = 0;
    287
    288out:
    289	if (do_mapping)
    290		TPM_MEMUNMAP(mapping, mapping_size);
    291	return size;
    292}
    293
    294#endif