/* * Licensed Materials - Property of IBM * * trousers - An open source TCG Software Stack * * (C) Copyright International Business Machines Corp. 2006 * */ /* * biosem.c * * Routines for handling PCR events from the TCG Compliant BIOS * */ #include #include #include #include #include #include #include #include #include #include "trousers/tss.h" #include "trousers_types.h" #include "tcs_tsp.h" #include "tcs_utils.h" #include "tcs_int_literals.h" #include "capabilities.h" #include "tcsps.h" #include "tcslog.h" #include "tcsem.h" #ifdef EVLOG_SOURCE_BIOS struct ext_log_source bios_source = { bios_open, bios_get_entries_by_pcr, bios_get_entry, bios_close }; int bios_open(void *source, FILE **handle) { FILE *fd; if ((fd = fopen((char *)source, "r")) == NULL ) { LogError("Error opening BIOS Eventlog file %s: %s", (char *)source, strerror(errno)); return -1; } *handle = fd; return 0; } TSS_RESULT bios_get_entries_by_pcr(FILE *handle, UINT32 pcr_index, UINT32 first, UINT32 *count, TSS_PCR_EVENT **events) { char page[BIOS_READ_SIZE]; int error_path = 1; UINT32 seen_indices = 0, copied_events = 0, i; struct event_wrapper *list = calloc(1, sizeof(struct event_wrapper)); struct event_wrapper *cur = list; TSS_RESULT result = TSS_E_INTERNAL_ERROR; TCG_PCClientPCREventStruc *event = NULL; int num=0; if (list == NULL) { LogError("malloc of %zd bytes failed.", sizeof(struct event_wrapper)); return TSS_E_OUTOFMEMORY; } if (*count == 0) { result = TSS_SUCCESS; goto free_list; } while (1) { /* read event header from the file */ if ((fread(page, 32, 1, handle)) <= 0) { goto copy_events; } event = (TCG_PCClientPCREventStruc *)page; /* if the index is the one we're looking for, grab the entry */ if (pcr_index == event->pcrIndex) { if (seen_indices >= first) { /* grab this entry */ cur->event.rgbPcrValue = malloc(20); if (cur->event.rgbPcrValue == NULL) { LogError("malloc of %d bytes failed.", 20); result = TSS_E_OUTOFMEMORY; goto free_list; } cur->event.ulPcrIndex = pcr_index; cur->event.eventType = event->eventType; cur->event.ulPcrValueLength = 20; /* copy the SHA1 XXX endianess ignored */ memcpy(cur->event.rgbPcrValue, event->digest, 20); /* copy the event name XXX endianess ignored */ cur->event.ulEventLength = event->eventDataSize; if (event->eventDataSize>0) { cur->event.rgbEvent = malloc(event->eventDataSize); if (cur->event.rgbEvent == NULL) { LogError("malloc of %d bytes failed.", event->eventDataSize); free(cur->event.rgbPcrValue); result = TSS_E_OUTOFMEMORY; goto free_list; } if ((fread(cur->event.rgbEvent, event->eventDataSize, 1, handle)) <= 0) { LogError("read from event source failed: %s", strerror(errno)); return result; } } else { cur->event.rgbEvent = NULL; } copied_events++; if (copied_events == *count) goto copy_events; cur->next = calloc(1, sizeof(struct event_wrapper)); if (cur->next == NULL) { LogError("malloc of %zd bytes failed.", sizeof(struct event_wrapper)); result = TSS_E_OUTOFMEMORY; goto free_list; } cur = cur->next; } else { /* skip */ if (event->eventDataSize > 0) fseek(handle,event->eventDataSize,SEEK_CUR); } seen_indices++; } else { if (event->eventDataSize > 0) fseek(handle,event->eventDataSize,SEEK_CUR); } num++; } copy_events: /* we've copied all the events we need to from this PCR, now * copy them all into one contiguous memory block */ *events = calloc(copied_events, sizeof(TSS_PCR_EVENT)); if (*events == NULL) { LogError("malloc of %zd bytes failed.", copied_events * sizeof(TSS_PCR_EVENT)); result = TSS_E_OUTOFMEMORY; goto free_list; } cur = list; for (i = 0; i < copied_events; i++) { memcpy(&((*events)[i]), &(cur->event), sizeof(TSS_PCR_EVENT)); cur = cur->next; } *count = copied_events; /* assume we're in an error path until we get here */ error_path = 0; result = TSS_SUCCESS; free_list: cur = list->next; while (cur != NULL) { if (error_path) { free(cur->event.rgbEvent); free(cur->event.rgbPcrValue); } free(list); list = cur; cur = list->next; } free(list); return result; } TSS_RESULT bios_get_entry(FILE *handle, UINT32 pcr_index, UINT32 *num, TSS_PCR_EVENT **ppEvent) { char page[BIOS_READ_SIZE]; UINT32 seen_indices = 0; TSS_RESULT result = TSS_E_INTERNAL_ERROR; TSS_PCR_EVENT *e = NULL; TCG_PCClientPCREventStruc *event = NULL; while (1) { /* read event header from the file */ if ((fread(page, 32, 1, handle)) == 0) { goto done; } event = (TCG_PCClientPCREventStruc *)page; if (pcr_index == event->pcrIndex) { if (ppEvent && !*ppEvent && seen_indices == *num) { *ppEvent = calloc(1, sizeof(TSS_PCR_EVENT)); if (*ppEvent == NULL) { LogError("malloc of %zd bytes failed.", sizeof(TSS_PCR_EVENT)); return TSS_E_INTERNAL_ERROR; } e = *ppEvent; e->rgbPcrValue = malloc(20); if (e->rgbPcrValue == NULL) { LogError("malloc of %d bytes failed.", 20); free(e); e = NULL; break; } e->ulPcrIndex = pcr_index; e->eventType = event->eventType; e->ulPcrValueLength = 20; /* copy the SHA1 XXX endianess ignored */ memcpy(e->rgbPcrValue, event->digest, 20); e->ulEventLength = event->eventDataSize; if (event->eventDataSize>0) { e->rgbEvent = malloc(e->ulEventLength); if (e->rgbEvent == NULL) { LogError("malloc of %d bytes failed.", e->ulEventLength); free(e->rgbPcrValue); free(e); e = NULL; break; } if ((fread(e->rgbEvent, event->eventDataSize, 1, handle)) <= 0) { LogError("read from event source failed: %s", strerror(errno)); return result; } } else { e->rgbEvent = NULL; } result = TSS_SUCCESS; break; } else { /* skip */ if (event->eventDataSize > 0) { fseek(handle,event->eventDataSize,SEEK_CUR); } } seen_indices++; } else { /* skip */ if (event->eventDataSize > 0) { fseek(handle,event->eventDataSize,SEEK_CUR); } } } done: if (!ppEvent) { *num = seen_indices; result = TSS_SUCCESS; } else if (e == NULL) *ppEvent = NULL; return result; } int bios_close(FILE *handle) { fclose(handle); return 0; } #endif