summaryrefslogtreecommitdiff
path: root/src/tcs/tcsi_evlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tcs/tcsi_evlog.c')
-rw-r--r--src/tcs/tcsi_evlog.c388
1 files changed, 388 insertions, 0 deletions
diff --git a/src/tcs/tcsi_evlog.c b/src/tcs/tcsi_evlog.c
new file mode 100644
index 0000000..7d49600
--- /dev/null
+++ b/src/tcs/tcsi_evlog.c
@@ -0,0 +1,388 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2004
+ *
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.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 "tcsd_wrap.h"
+#include "tcsd.h"
+#include "tcslog.h"
+#include "tcsem.h"
+
+
+TSS_RESULT
+TCS_LogPcrEvent_Internal(TCS_CONTEXT_HANDLE hContext, /* in */
+ TSS_PCR_EVENT Event, /* in */
+ UINT32 *pNumber) /* out */
+{
+ TSS_RESULT result;
+
+ if((result = ctx_verify_context(hContext)))
+ return result;
+
+ if(Event.ulPcrIndex >= tpm_metrics.num_pcrs)
+ return TCSERR(TSS_E_BAD_PARAMETER);
+
+ if (tcsd_options.kernel_pcrs & (1 << Event.ulPcrIndex)) {
+ LogInfo("PCR %d is configured to be kernel controlled. Event logging denied.",
+ Event.ulPcrIndex);
+ return TCSERR(TSS_E_FAIL);
+ }
+
+ if (tcsd_options.firmware_pcrs & (1 << Event.ulPcrIndex)) {
+ LogInfo("PCR %d is configured to be firmware controlled. Event logging denied.",
+ Event.ulPcrIndex);
+ return TCSERR(TSS_E_FAIL);
+ }
+
+ return event_log_add(&Event, pNumber);
+}
+
+/* This routine will handle creating the TSS_PCR_EVENT structures from log
+ * data produced by an external source. The external source in mind here
+ * is the log of PCR extends done by the kernel from beneath the TSS
+ * (via direct calls to the device driver).
+ */
+TSS_RESULT
+TCS_GetExternalPcrEvent(UINT32 PcrIndex, /* in */
+ UINT32 *pNumber, /* in, out */
+ TSS_PCR_EVENT **ppEvent) /* out */
+{
+ FILE *log_handle;
+ char *source;
+
+ if (tcsd_options.kernel_pcrs & (1 << PcrIndex)) {
+ source = tcsd_options.kernel_log_file;
+
+ if (tcs_event_log->kernel_source != NULL) {
+ if (tcs_event_log->kernel_source->open((void *)source,
+ (FILE **) &log_handle))
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+
+ if (tcs_event_log->kernel_source->get_entry(log_handle, PcrIndex,
+ pNumber, ppEvent)) {
+ tcs_event_log->kernel_source->close(log_handle);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ tcs_event_log->kernel_source->close(log_handle);
+ } else {
+ LogError("No source for externel kernel events was compiled in, but "
+ "the tcsd is configured to use one! (see %s)",
+ tcsd_config_file);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ } else if (tcsd_options.firmware_pcrs & (1 << PcrIndex)) {
+ source = tcsd_options.firmware_log_file;
+
+ if (tcs_event_log->firmware_source != NULL) {
+ if (tcs_event_log->firmware_source->open((void *)source, &log_handle))
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+
+ if (tcs_event_log->firmware_source->get_entry(log_handle, PcrIndex,
+ pNumber, ppEvent)) {
+ tcs_event_log->firmware_source->close(log_handle);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ tcs_event_log->firmware_source->close(log_handle);
+ } else {
+ LogError("No source for externel firmware events was compiled in, but "
+ "the tcsd is configured to use one! (see %s)",
+ tcsd_config_file);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ } else {
+ LogError("PCR index %d not flagged as kernel or firmware controlled.", PcrIndex);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+TCS_GetPcrEvent_Internal(TCS_CONTEXT_HANDLE hContext, /* in */
+ UINT32 PcrIndex, /* in */
+ UINT32 *pNumber, /* in, out */
+ TSS_PCR_EVENT **ppEvent) /* out */
+{
+ TSS_RESULT result;
+ TSS_PCR_EVENT *event;
+
+ if ((result = ctx_verify_context(hContext)))
+ return result;
+
+ if(PcrIndex >= tpm_metrics.num_pcrs)
+ return TCSERR(TSS_E_BAD_PARAMETER);
+
+ /* if this is a kernel or firmware controlled PCR, call an external routine */
+ if ((tcsd_options.kernel_pcrs & (1 << PcrIndex)) ||
+ (tcsd_options.firmware_pcrs & (1 << PcrIndex))) {
+ MUTEX_LOCK(tcs_event_log->lock);
+ result = TCS_GetExternalPcrEvent(PcrIndex, pNumber, ppEvent);
+ MUTEX_UNLOCK(tcs_event_log->lock);
+
+ return result;
+ }
+
+ if (ppEvent == NULL) {
+ MUTEX_LOCK(tcs_event_log->lock);
+
+ *pNumber = get_num_events(PcrIndex);
+
+ MUTEX_UNLOCK(tcs_event_log->lock);
+ } else {
+ *ppEvent = calloc(1, sizeof(TSS_PCR_EVENT));
+ if (*ppEvent == NULL) {
+ LogError("malloc of %zd bytes failed.", sizeof(TSS_PCR_EVENT));
+ return TCSERR(TSS_E_OUTOFMEMORY);
+ }
+
+ event = get_pcr_event(PcrIndex, *pNumber);
+ if (event == NULL) {
+ free(*ppEvent);
+ return TCSERR(TSS_E_BAD_PARAMETER);
+ }
+
+ if ((result = copy_pcr_event(*ppEvent, event))) {
+ free(*ppEvent);
+ return result;
+ }
+ }
+
+ return TSS_SUCCESS;
+}
+
+/* This routine will handle creating the TSS_PCR_EVENT structures from log
+ * data produced by an external source. The external source in mind here
+ * is the log of PCR extends done by the kernel from beneath the TSS
+ * (via direct calls to the device driver).
+ */
+TSS_RESULT
+TCS_GetExternalPcrEventsByPcr(UINT32 PcrIndex, /* in */
+ UINT32 FirstEvent, /* in */
+ UINT32 *pEventCount, /* in, out */
+ TSS_PCR_EVENT **ppEvents) /* out */
+{
+ FILE *log_handle;
+ char *source;
+
+ if (tcsd_options.kernel_pcrs & (1 << PcrIndex)) {
+ source = tcsd_options.kernel_log_file;
+
+ if (tcs_event_log->kernel_source != NULL) {
+ if (tcs_event_log->kernel_source->open((void *)source, &log_handle))
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+
+ if (tcs_event_log->kernel_source->get_entries_by_pcr(log_handle, PcrIndex,
+ FirstEvent, pEventCount, ppEvents)) {
+ tcs_event_log->kernel_source->close(log_handle);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ tcs_event_log->kernel_source->close(log_handle);
+ } else {
+ LogError("No source for externel kernel events was compiled in, but "
+ "the tcsd is configured to use one! (see %s)",
+ tcsd_config_file);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ } else if (tcsd_options.firmware_pcrs & (1 << PcrIndex)) {
+ source = tcsd_options.firmware_log_file;
+
+ if (tcs_event_log->firmware_source != NULL) {
+ if (tcs_event_log->firmware_source->open((void *)source, &log_handle))
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+
+ if (tcs_event_log->firmware_source->get_entries_by_pcr(log_handle, PcrIndex,
+ FirstEvent, pEventCount, ppEvents)) {
+ tcs_event_log->firmware_source->close(log_handle);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ tcs_event_log->firmware_source->close(log_handle);
+ } else {
+ LogError("No source for externel firmware events was compiled in, but "
+ "the tcsd is configured to use one! (see %s)",
+ tcsd_config_file);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ } else {
+ LogError("PCR index %d not flagged as kernel or firmware controlled.", PcrIndex);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+TCS_GetPcrEventsByPcr_Internal(TCS_CONTEXT_HANDLE hContext, /* in */
+ UINT32 PcrIndex, /* in */
+ UINT32 FirstEvent, /* in */
+ UINT32 *pEventCount, /* in, out */
+ TSS_PCR_EVENT **ppEvents) /* out */
+{
+ UINT32 lastEventNumber, i, eventIndex;
+ TSS_RESULT result;
+ struct event_wrapper *tmp;
+
+ if ((result = ctx_verify_context(hContext)))
+ return result;
+
+ if (PcrIndex >= tpm_metrics.num_pcrs)
+ return TCSERR(TSS_E_BAD_PARAMETER);
+
+ /* if this is a kernel or firmware controlled PCR, call an external routine */
+ if ((tcsd_options.kernel_pcrs & (1 << PcrIndex)) ||
+ (tcsd_options.firmware_pcrs & (1 << PcrIndex))) {
+ MUTEX_LOCK(tcs_event_log->lock);
+ result = TCS_GetExternalPcrEventsByPcr(PcrIndex, FirstEvent,
+ pEventCount, ppEvents);
+ MUTEX_UNLOCK(tcs_event_log->lock);
+
+ return result;
+ }
+
+ MUTEX_LOCK(tcs_event_log->lock);
+
+ lastEventNumber = get_num_events(PcrIndex);
+
+ MUTEX_UNLOCK(tcs_event_log->lock);
+
+ /* if pEventCount is larger than the number of events to return, just return less.
+ * *pEventCount will be set to the number returned below.
+ */
+ lastEventNumber = MIN(lastEventNumber, FirstEvent + *pEventCount);
+
+ if (FirstEvent > lastEventNumber)
+ return TCSERR(TSS_E_BAD_PARAMETER);
+
+ if (lastEventNumber == 0) {
+ *pEventCount = 0;
+ *ppEvents = NULL;
+ return TSS_SUCCESS;
+ }
+
+ /* FirstEvent is 0 indexed see TSS 1.1b spec section 4.7.2.2.3. That means that
+ * the following calculation is not off by one. :-)
+ */
+ *ppEvents = calloc((lastEventNumber - FirstEvent), sizeof(TSS_PCR_EVENT));
+ if (*ppEvents == NULL) {
+ LogError("malloc of %zd bytes failed.",
+ sizeof(TSS_PCR_EVENT) * (lastEventNumber - FirstEvent));
+ return TCSERR(TSS_E_OUTOFMEMORY);
+ }
+
+ MUTEX_LOCK(tcs_event_log->lock);
+
+ tmp = tcs_event_log->lists[PcrIndex];
+
+ /* move through the list until we get to the first event requested */
+ for (i = 0; i < FirstEvent; i++)
+ tmp = tmp->next;
+
+ /* copy events from the first requested to the last requested */
+ for (eventIndex = 0; i < lastEventNumber; eventIndex++, i++) {
+ copy_pcr_event(&((*ppEvents)[eventIndex]), &(tmp->event));
+ tmp = tmp->next;
+ }
+
+ MUTEX_UNLOCK(tcs_event_log->lock);
+
+ *pEventCount = eventIndex;
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+TCS_GetPcrEventLog_Internal(TCS_CONTEXT_HANDLE hContext,/* in */
+ UINT32 *pEventCount, /* out */
+ TSS_PCR_EVENT **ppEvents) /* out */
+{
+ TSS_RESULT result;
+ UINT32 i, j, event_count, aggregate_count = 0;
+ struct event_wrapper *tmp;
+ TSS_PCR_EVENT *event_list = NULL, *aggregate_list = NULL;
+
+ if ((result = ctx_verify_context(hContext)))
+ return result;
+
+ MUTEX_LOCK(tcs_event_log->lock);
+
+ /* for each PCR index, if its externally controlled, get the total number of events
+ * externally, else copy the events from the TCSD list. Then tack that list onto a
+ * master list to returned. */
+ for (i = 0; i < tpm_metrics.num_pcrs; i++) {
+ if ((tcsd_options.kernel_pcrs & (1 << i)) ||
+ (tcsd_options.firmware_pcrs & (1 << i))) {
+ /* A kernel or firmware controlled PCR event list */
+ event_count = UINT_MAX;
+ if ((result = TCS_GetExternalPcrEventsByPcr(i, 0, &event_count,
+ &event_list))) {
+ LogDebug("Getting External event list for PCR %u failed", i);
+ free(aggregate_list);
+ goto error;
+ }
+ LogDebug("Retrieved %u events from PCR %u (external)", event_count, i);
+ } else {
+ /* A TCSD controlled PCR event list */
+ event_count = get_num_events(i);
+
+ if (event_count == 0)
+ continue;
+
+ if ((event_list = calloc(event_count, sizeof(TSS_PCR_EVENT))) == NULL) {
+ LogError("malloc of %zd bytes failed",
+ event_count * sizeof(TSS_PCR_EVENT));
+ result = TCSERR(TSS_E_OUTOFMEMORY);
+ free(aggregate_list);
+ goto error;
+ }
+
+ tmp = tcs_event_log->lists[i];
+ for (j = 0; j < event_count; j++) {
+ copy_pcr_event(&event_list[j], &(tmp->event));
+ tmp = tmp->next;
+ }
+ }
+
+ if (event_count == 0)
+ continue;
+
+ /* Tack the list onto the aggregate_list */
+ aggregate_list = concat_pcr_events(&aggregate_list, aggregate_count, event_list,
+ event_count);
+ if (aggregate_list == NULL) {
+ free(event_list);
+ result = TCSERR(TSS_E_OUTOFMEMORY);
+ goto error;
+ }
+ aggregate_count += event_count;
+ free(event_list);
+ }
+
+ *ppEvents = aggregate_list;
+ *pEventCount = aggregate_count;
+ result = TSS_SUCCESS;
+error:
+ MUTEX_UNLOCK(tcs_event_log->lock);
+
+ return result;
+}
+