diff options
Diffstat (limited to 'src/tcs/tcs_evlog.c')
-rw-r--r-- | src/tcs/tcs_evlog.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/src/tcs/tcs_evlog.c b/src/tcs/tcs_evlog.c new file mode 100644 index 0000000..f854e4e --- /dev/null +++ b/src/tcs/tcs_evlog.c @@ -0,0 +1,223 @@ + +/* + * 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" + + +struct event_log *tcs_event_log = NULL; + +TSS_RESULT +event_log_init() +{ + if (tcs_event_log != NULL) + return TSS_SUCCESS; + + tcs_event_log = calloc(1, sizeof(struct event_log)); + if (tcs_event_log == NULL) { + LogError("malloc of %zd bytes failed.", sizeof(struct event_log)); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + MUTEX_INIT(tcs_event_log->lock); + + /* allocate as many event lists as there are PCR's */ + tcs_event_log->lists = calloc(tpm_metrics.num_pcrs, sizeof(struct event_wrapper *)); + if (tcs_event_log->lists == NULL) { + LogError("malloc of %zd bytes failed.", + tpm_metrics.num_pcrs * sizeof(struct event_wrapper *)); + free(tcs_event_log); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + /* assign external event log sources here */ + //tcs_event_log->firmware_source = EVLOG_IMA_SOURCE; + tcs_event_log->firmware_source = EVLOG_BIOS_SOURCE; + tcs_event_log->kernel_source = EVLOG_IMA_SOURCE; + + return TSS_SUCCESS; +} + +TSS_RESULT +event_log_final() +{ + struct event_wrapper *cur, *next; + UINT32 i; + + MUTEX_LOCK(tcs_event_log->lock); + + for (i = 0; i < tpm_metrics.num_pcrs; i++) { + cur = tcs_event_log->lists[i]; + while (cur != NULL) { + next = cur->next; + free(cur->event.rgbPcrValue); + free(cur->event.rgbEvent); + free(cur); + cur = next; + } + } + + MUTEX_UNLOCK(tcs_event_log->lock); + + free(tcs_event_log->lists); + free(tcs_event_log); + + return TSS_SUCCESS; +} + +TSS_RESULT +copy_pcr_event(TSS_PCR_EVENT *dest, TSS_PCR_EVENT *source) +{ + memcpy(dest, source, sizeof(TSS_PCR_EVENT)); + return TSS_SUCCESS; +} + +TSS_RESULT +event_log_add(TSS_PCR_EVENT *event, UINT32 *pNumber) +{ + struct event_wrapper *new, *tmp; + TSS_RESULT result; + UINT32 i; + + MUTEX_LOCK(tcs_event_log->lock); + + new = calloc(1, sizeof(struct event_wrapper)); + if (new == NULL) { + LogError("malloc of %zd bytes failed.", sizeof(struct event_wrapper)); + MUTEX_UNLOCK(tcs_event_log->lock); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + if ((result = copy_pcr_event(&(new->event), event))) { + free(new); + MUTEX_UNLOCK(tcs_event_log->lock); + return result; + } + + /* go to the end of the list to add the element, so that they're in order */ + i = 0; + if (tcs_event_log->lists[event->ulPcrIndex] == NULL) { + tcs_event_log->lists[event->ulPcrIndex] = new; + } else { + i++; + tmp = tcs_event_log->lists[event->ulPcrIndex]; + while (tmp->next != NULL) { + i++; + tmp = tmp->next; + } + tmp->next = new; + } + + *pNumber = ++i; + + MUTEX_UNLOCK(tcs_event_log->lock); + + return TSS_SUCCESS; +} + +TSS_PCR_EVENT * +get_pcr_event(UINT32 pcrIndex, UINT32 eventNumber) +{ + struct event_wrapper *tmp; + UINT32 counter = 0; + + MUTEX_LOCK(tcs_event_log->lock); + + tmp = tcs_event_log->lists[pcrIndex]; + for (; tmp; tmp = tmp->next) { + if (counter == eventNumber) { + break; + } + counter++; + } + + MUTEX_UNLOCK(tcs_event_log->lock); + + return (tmp ? &(tmp->event) : NULL); +} + +/* the lock should be held before calling this function */ +UINT32 +get_num_events(UINT32 pcrIndex) +{ + struct event_wrapper *tmp; + UINT32 counter = 0; + + tmp = tcs_event_log->lists[pcrIndex]; + for (; tmp; tmp = tmp->next) { + counter++; + } + + return counter; +} + +TSS_PCR_EVENT * +concat_pcr_events(TSS_PCR_EVENT **list_so_far, UINT32 list_size, TSS_PCR_EVENT *addition, + UINT32 addition_size) +{ + TSS_PCR_EVENT *ret; + + ret = realloc(*list_so_far, (list_size + addition_size) * sizeof(TSS_PCR_EVENT)); + if (ret == NULL) { + LogError("malloc of %zd bytes failed", + (list_size + addition_size) * sizeof(TSS_PCR_EVENT)); + return ret; + } + + memcpy(&ret[list_size], addition, addition_size * sizeof(TSS_PCR_EVENT)); + return ret; +} + +/* XXX make this a macro */ +UINT32 +get_pcr_event_size(TSS_PCR_EVENT *e) +{ + return (sizeof(TSS_PCR_EVENT) + e->ulEventLength + e->ulPcrValueLength); +} + +void +free_external_events(UINT32 eventCount, TSS_PCR_EVENT *ppEvents) +{ + UINT32 j; + + if (!ppEvents) + return; + + for (j = 0; j < eventCount; j++) { + /* This is a fairly heinous hack, but PCR event logs can get really large + * and without it, there is a real potential to exhaust memory by leaks. + * The PCR event logs that we pull out of securityfs have had their + * rgbPcrValue and rgbEvent pointers malloc'd dynamically as the + * securityfs log was parsed. The other event log lists that are + * maintained by the TCSD don't need to have this data free'd, since that + * will happen at shutdown time only. So, for each PCR index that's + * read from securityfs, we need to free its pointers after that data has + * been set in the packet to send back to the TSP. */ + if ((tcsd_options.kernel_pcrs & (1 << ppEvents[j].ulPcrIndex)) || + (tcsd_options.firmware_pcrs & (1 << ppEvents[j].ulPcrIndex))) { + free(ppEvents[j].rgbPcrValue); + free(ppEvents[j].rgbEvent); + } + } +} |