summaryrefslogtreecommitdiff
path: root/src/tcs/tcs_evlog_biosem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tcs/tcs_evlog_biosem.c')
-rw-r--r--src/tcs/tcs_evlog_biosem.c298
1 files changed, 298 insertions, 0 deletions
diff --git a/src/tcs/tcs_evlog_biosem.c b/src/tcs/tcs_evlog_biosem.c
new file mode 100644
index 0000000..7065e12
--- /dev/null
+++ b/src/tcs/tcs_evlog_biosem.c
@@ -0,0 +1,298 @@
+
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+
+#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