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. 2004 8 * 9 */ 10 11 12 #include <stdlib.h> 13 #include <stdio.h> 14 #include <string.h> 15 #include <limits.h> 16 17 #include "trousers/tss.h" 18 #include "trousers_types.h" 19 #include "tcs_tsp.h" 20 #include "tcs_utils.h" 21 #include "tcs_int_literals.h" 22 #include "capabilities.h" 23 #include "tcsd_wrap.h" 24 #include "tcsd.h" 25 #include "tcslog.h" 26 #include "tcsem.h" 27 28 29 struct event_log *tcs_event_log = NULL; 30 31 TSS_RESULT 32 event_log_init() 33 { 34 if (tcs_event_log != NULL) 35 return TSS_SUCCESS; 36 37 tcs_event_log = calloc(1, sizeof(struct event_log)); 38 if (tcs_event_log == NULL) { 39 LogError("malloc of %zd bytes failed.", sizeof(struct event_log)); 40 return TCSERR(TSS_E_OUTOFMEMORY); 41 } 42 43 MUTEX_INIT(tcs_event_log->lock); 44 45 /* allocate as many event lists as there are PCR's */ 46 tcs_event_log->lists = calloc(tpm_metrics.num_pcrs, sizeof(struct event_wrapper *)); 47 if (tcs_event_log->lists == NULL) { 48 LogError("malloc of %zd bytes failed.", 49 tpm_metrics.num_pcrs * sizeof(struct event_wrapper *)); 50 free(tcs_event_log); 51 return TCSERR(TSS_E_OUTOFMEMORY); 52 } 53 54 /* assign external event log sources here */ 55 //tcs_event_log->firmware_source = EVLOG_IMA_SOURCE; 56 tcs_event_log->firmware_source = EVLOG_BIOS_SOURCE; 57 tcs_event_log->kernel_source = EVLOG_IMA_SOURCE; 58 59 return TSS_SUCCESS; 60 } 61 62 TSS_RESULT 63 event_log_final() 64 { 65 struct event_wrapper *cur, *next; 66 UINT32 i; 67 68 MUTEX_LOCK(tcs_event_log->lock); 69 70 for (i = 0; i < tpm_metrics.num_pcrs; i++) { 71 cur = tcs_event_log->lists[i]; 72 while (cur != NULL) { 73 next = cur->next; 74 free(cur->event.rgbPcrValue); 75 free(cur->event.rgbEvent); 76 free(cur); 77 cur = next; 78 } 79 } 80 81 MUTEX_UNLOCK(tcs_event_log->lock); 82 83 free(tcs_event_log->lists); 84 free(tcs_event_log); 85 86 return TSS_SUCCESS; 87 } 88 89 TSS_RESULT 90 copy_pcr_event(TSS_PCR_EVENT *dest, TSS_PCR_EVENT *source) 91 { 92 memcpy(dest, source, sizeof(TSS_PCR_EVENT)); 93 return TSS_SUCCESS; 94 } 95 96 TSS_RESULT 97 event_log_add(TSS_PCR_EVENT *event, UINT32 *pNumber) 98 { 99 struct event_wrapper *new, *tmp; 100 TSS_RESULT result; 101 UINT32 i; 102 103 MUTEX_LOCK(tcs_event_log->lock); 104 105 new = calloc(1, sizeof(struct event_wrapper)); 106 if (new == NULL) { 107 LogError("malloc of %zd bytes failed.", sizeof(struct event_wrapper)); 108 MUTEX_UNLOCK(tcs_event_log->lock); 109 return TCSERR(TSS_E_OUTOFMEMORY); 110 } 111 112 if ((result = copy_pcr_event(&(new->event), event))) { 113 free(new); 114 MUTEX_UNLOCK(tcs_event_log->lock); 115 return result; 116 } 117 118 /* go to the end of the list to add the element, so that they're in order */ 119 i = 0; 120 if (tcs_event_log->lists[event->ulPcrIndex] == NULL) { 121 tcs_event_log->lists[event->ulPcrIndex] = new; 122 } else { 123 i++; 124 tmp = tcs_event_log->lists[event->ulPcrIndex]; 125 while (tmp->next != NULL) { 126 i++; 127 tmp = tmp->next; 128 } 129 tmp->next = new; 130 } 131 132 *pNumber = ++i; 133 134 MUTEX_UNLOCK(tcs_event_log->lock); 135 136 return TSS_SUCCESS; 137 } 138 139 TSS_PCR_EVENT * 140 get_pcr_event(UINT32 pcrIndex, UINT32 eventNumber) 141 { 142 struct event_wrapper *tmp; 143 UINT32 counter = 0; 144 145 MUTEX_LOCK(tcs_event_log->lock); 146 147 tmp = tcs_event_log->lists[pcrIndex]; 148 for (; tmp; tmp = tmp->next) { 149 if (counter == eventNumber) { 150 break; 151 } 152 counter++; 153 } 154 155 MUTEX_UNLOCK(tcs_event_log->lock); 156 157 return (tmp ? &(tmp->event) : NULL); 158 } 159 160 /* the lock should be held before calling this function */ 161 UINT32 162 get_num_events(UINT32 pcrIndex) 163 { 164 struct event_wrapper *tmp; 165 UINT32 counter = 0; 166 167 tmp = tcs_event_log->lists[pcrIndex]; 168 for (; tmp; tmp = tmp->next) { 169 counter++; 170 } 171 172 return counter; 173 } 174 175 TSS_PCR_EVENT * 176 concat_pcr_events(TSS_PCR_EVENT **list_so_far, UINT32 list_size, TSS_PCR_EVENT *addition, 177 UINT32 addition_size) 178 { 179 TSS_PCR_EVENT *ret; 180 181 ret = realloc(*list_so_far, (list_size + addition_size) * sizeof(TSS_PCR_EVENT)); 182 if (ret == NULL) { 183 LogError("malloc of %zd bytes failed", 184 (list_size + addition_size) * sizeof(TSS_PCR_EVENT)); 185 return ret; 186 } 187 188 memcpy(&ret[list_size], addition, addition_size * sizeof(TSS_PCR_EVENT)); 189 return ret; 190 } 191 192 /* XXX make this a macro */ 193 UINT32 194 get_pcr_event_size(TSS_PCR_EVENT *e) 195 { 196 return (sizeof(TSS_PCR_EVENT) + e->ulEventLength + e->ulPcrValueLength); 197 } 198 199 void 200 free_external_events(UINT32 eventCount, TSS_PCR_EVENT *ppEvents) 201 { 202 UINT32 j; 203 204 if (!ppEvents) 205 return; 206 207 for (j = 0; j < eventCount; j++) { 208 /* This is a fairly heinous hack, but PCR event logs can get really large 209 * and without it, there is a real potential to exhaust memory by leaks. 210 * The PCR event logs that we pull out of securityfs have had their 211 * rgbPcrValue and rgbEvent pointers malloc'd dynamically as the 212 * securityfs log was parsed. The other event log lists that are 213 * maintained by the TCSD don't need to have this data free'd, since that 214 * will happen at shutdown time only. So, for each PCR index that's 215 * read from securityfs, we need to free its pointers after that data has 216 * been set in the packet to send back to the TSP. */ 217 if ((tcsd_options.kernel_pcrs & (1 << ppEvents[j].ulPcrIndex)) || 218 (tcsd_options.firmware_pcrs & (1 << ppEvents[j].ulPcrIndex))) { 219 free(ppEvents[j].rgbPcrValue); 220 free(ppEvents[j].rgbEvent); 221 } 222 } 223 } 224