1 2/* 3 * Licensed Materials - Property of IBM 4 * 5 * trousers - An open source TCG Software Stack 6 * 7 * (C) Copyright International Business Machines Corp. 2006 8 * 9 */ 10 11/* 12 * biosem.c 13 * 14 * Routines for handling PCR events from the TCG Compliant BIOS 15 * 16 */ 17 18#include <stdlib.h> 19#include <stdio.h> 20#include <string.h> 21#include <sys/types.h> 22#include <sys/stat.h> 23#include <fcntl.h> 24#include <errno.h> 25#include <limits.h> 26#include <unistd.h> 27 28#include "trousers/tss.h" 29#include "trousers_types.h" 30#include "tcs_tsp.h" 31#include "tcs_utils.h" 32#include "tcs_int_literals.h" 33#include "capabilities.h" 34#include "tcsps.h" 35#include "tcslog.h" 36#include "tcsem.h" 37 38#ifdef EVLOG_SOURCE_BIOS 39 40struct ext_log_source bios_source = { 41 bios_open, 42 bios_get_entries_by_pcr, 43 bios_get_entry, 44 bios_close 45}; 46 47int 48bios_open(void *source, FILE **handle) 49{ 50 FILE *fd; 51 52 if ((fd = fopen((char *)source, "r")) == NULL ) { 53 LogError("Error opening BIOS Eventlog file %s: %s", (char *)source, 54 strerror(errno)); 55 return -1; 56 } 57 58 *handle = fd; 59 60 return 0; 61} 62 63TSS_RESULT 64bios_get_entries_by_pcr(FILE *handle, UINT32 pcr_index, UINT32 first, 65 UINT32 *count, TSS_PCR_EVENT **events) 66{ 67 char page[BIOS_READ_SIZE]; 68 int error_path = 1; 69 UINT32 seen_indices = 0, copied_events = 0, i; 70 struct event_wrapper *list = calloc(1, sizeof(struct event_wrapper)); 71 struct event_wrapper *cur = list; 72 TSS_RESULT result = TSS_E_INTERNAL_ERROR; 73 TCG_PCClientPCREventStruc *event = NULL; 74 int num=0; 75 76 if (list == NULL) { 77 LogError("malloc of %zd bytes failed.", sizeof(struct event_wrapper)); 78 return TSS_E_OUTOFMEMORY; 79 } 80 81 if (*count == 0) { 82 result = TSS_SUCCESS; 83 goto free_list; 84 } 85 86 while (1) { 87 /* read event header from the file */ 88 if ((fread(page, 32, 1, handle)) <= 0) { 89 goto copy_events; 90 } 91 92 event = (TCG_PCClientPCREventStruc *)page; 93 94 /* if the index is the one we're looking for, grab the entry */ 95 if (pcr_index == event->pcrIndex) { 96 if (seen_indices >= first) { 97 /* grab this entry */ 98 cur->event.rgbPcrValue = malloc(20); 99 if (cur->event.rgbPcrValue == NULL) { 100 LogError("malloc of %d bytes failed.", 20); 101 result = TSS_E_OUTOFMEMORY; 102 goto free_list; 103 } 104 105 cur->event.ulPcrIndex = pcr_index; 106 cur->event.eventType = event->eventType; 107 cur->event.ulPcrValueLength = 20; 108 109 /* copy the SHA1 XXX endianess ignored */ 110 memcpy(cur->event.rgbPcrValue, event->digest, 20); 111 112 /* copy the event name XXX endianess ignored */ 113 cur->event.ulEventLength = event->eventDataSize; 114 115 if (event->eventDataSize>0) { 116 cur->event.rgbEvent = malloc(event->eventDataSize); 117 if (cur->event.rgbEvent == NULL) { 118 LogError("malloc of %d bytes failed.", 119 event->eventDataSize); 120 free(cur->event.rgbPcrValue); 121 result = TSS_E_OUTOFMEMORY; 122 goto free_list; 123 } 124 if ((fread(cur->event.rgbEvent, 125 event->eventDataSize, 1, handle)) <= 0) { 126 LogError("read from event source failed: %s", 127 strerror(errno)); 128 return result; 129 } 130 } else { 131 cur->event.rgbEvent = NULL; 132 } 133 134 copied_events++; 135 if (copied_events == *count) 136 goto copy_events; 137 138 cur->next = calloc(1, sizeof(struct event_wrapper)); 139 if (cur->next == NULL) { 140 LogError("malloc of %zd bytes failed.", 141 sizeof(struct event_wrapper)); 142 result = TSS_E_OUTOFMEMORY; 143 goto free_list; 144 } 145 cur = cur->next; 146 } else { 147 /* skip */ 148 if (event->eventDataSize > 0) 149 fseek(handle,event->eventDataSize,SEEK_CUR); 150 } 151 seen_indices++; 152 } else { 153 if (event->eventDataSize > 0) 154 fseek(handle,event->eventDataSize,SEEK_CUR); 155 } 156 num++; 157 } 158 159copy_events: 160 161 /* we've copied all the events we need to from this PCR, now 162 * copy them all into one contiguous memory block 163 */ 164 *events = calloc(copied_events, sizeof(TSS_PCR_EVENT)); 165 if (*events == NULL) { 166 LogError("malloc of %zd bytes failed.", copied_events * sizeof(TSS_PCR_EVENT)); 167 result = TSS_E_OUTOFMEMORY; 168 goto free_list; 169 } 170 171 cur = list; 172 for (i = 0; i < copied_events; i++) { 173 memcpy(&((*events)[i]), &(cur->event), sizeof(TSS_PCR_EVENT)); 174 cur = cur->next; 175 } 176 177 *count = copied_events; 178 /* assume we're in an error path until we get here */ 179 error_path = 0; 180 result = TSS_SUCCESS; 181 182free_list: 183 cur = list->next; 184 while (cur != NULL) { 185 if (error_path) { 186 free(cur->event.rgbEvent); 187 free(cur->event.rgbPcrValue); 188 } 189 free(list); 190 list = cur; 191 cur = list->next; 192 } 193 free(list); 194 return result; 195} 196 197TSS_RESULT 198bios_get_entry(FILE *handle, UINT32 pcr_index, UINT32 *num, TSS_PCR_EVENT **ppEvent) 199{ 200 char page[BIOS_READ_SIZE]; 201 UINT32 seen_indices = 0; 202 TSS_RESULT result = TSS_E_INTERNAL_ERROR; 203 TSS_PCR_EVENT *e = NULL; 204 TCG_PCClientPCREventStruc *event = NULL; 205 206 while (1) { 207 /* read event header from the file */ 208 if ((fread(page, 32, 1, handle)) == 0) { 209 goto done; 210 } 211 212 event = (TCG_PCClientPCREventStruc *)page; 213 214 if (pcr_index == event->pcrIndex) { 215 if (ppEvent && !*ppEvent && seen_indices == *num) { 216 *ppEvent = calloc(1, sizeof(TSS_PCR_EVENT)); 217 if (*ppEvent == NULL) { 218 LogError("malloc of %zd bytes failed.", 219 sizeof(TSS_PCR_EVENT)); 220 return TSS_E_INTERNAL_ERROR; 221 } 222 223 e = *ppEvent; 224 225 e->rgbPcrValue = malloc(20); 226 if (e->rgbPcrValue == NULL) { 227 LogError("malloc of %d bytes failed.", 20); 228 free(e); 229 e = NULL; 230 break; 231 } 232 233 e->ulPcrIndex = pcr_index; 234 e->eventType = event->eventType; 235 e->ulPcrValueLength = 20; 236 237 /* copy the SHA1 XXX endianess ignored */ 238 memcpy(e->rgbPcrValue, event->digest, 20); 239 240 e->ulEventLength = event->eventDataSize; 241 242 if (event->eventDataSize>0) { 243 e->rgbEvent = malloc(e->ulEventLength); 244 if (e->rgbEvent == NULL) { 245 LogError("malloc of %d bytes failed.", 246 e->ulEventLength); 247 free(e->rgbPcrValue); 248 free(e); 249 e = NULL; 250 break; 251 } 252 if ((fread(e->rgbEvent, 253 event->eventDataSize, 254 1, handle)) <= 0) { 255 LogError("read from event source failed: %s", 256 strerror(errno)); 257 return result; 258 } 259 } else { 260 e->rgbEvent = NULL; 261 } 262 result = TSS_SUCCESS; 263 264 break; 265 } else { 266 /* skip */ 267 if (event->eventDataSize > 0) { 268 fseek(handle,event->eventDataSize,SEEK_CUR); 269 } 270 } 271 seen_indices++; 272 } else { 273 /* skip */ 274 if (event->eventDataSize > 0) { 275 fseek(handle,event->eventDataSize,SEEK_CUR); 276 } 277 } 278 } 279 280done: 281 if (!ppEvent) { 282 *num = seen_indices; 283 result = TSS_SUCCESS; 284 } else if (e == NULL) 285 *ppEvent = NULL; 286 287 return result; 288} 289 290int 291bios_close(FILE *handle) 292{ 293 fclose(handle); 294 295 return 0; 296} 297 298#endif 299