297 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2005, 2012 IBM Corporation4 *5 * Authors:6 * Kent Yoder <key@linux.vnet.ibm.com>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>11 * Nayna Jain <nayna@linux.vnet.ibm.com>12 *13 * Maintained by: <tpmdd-devel@lists.sourceforge.net>14 *15 * Access to the event log created by a system's firmware / BIOS16 */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 30static 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 51static 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 */70static 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 108static 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 139static void tpm1_bios_measurements_stop(struct seq_file *m, void *v)140{141}142 143static 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_conversion169 (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_conversion194 (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_conversion204 (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 223static 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 252static 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 printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",262 __func__);263 return -EFAULT;264 }265 266 /* 1st: PCR */267 seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index));268 269 /* 2nd: SHA1 */270 seq_printf(m, "%20phN", event->pcr_value);271 272 /* 3rd: event type identifier */273 seq_printf(m, " %02x", do_endian_conversion(event->event_type));274 275 get_event_name(eventname, event, event_entry);276 277 /* 4th: eventname <= max + \'0' delimiter */278 seq_printf(m, " %s\n", eventname);279 280 kfree(eventname);281 return 0;282}283 284const 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,289};290 291const 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,296};297