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 29TSS_RESULT 30TCS_LogPcrEvent_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ 31 TSS_PCR_EVENT Event, /* in */ 32 UINT32 *pNumber) /* out */ 33{ 34 TSS_RESULT result; 35 36 if((result = ctx_verify_context(hContext))) 37 return result; 38 39 if(Event.ulPcrIndex >= tpm_metrics.num_pcrs) 40 return TCSERR(TSS_E_BAD_PARAMETER); 41 42 if (tcsd_options.kernel_pcrs & (1 << Event.ulPcrIndex)) { 43 LogInfo("PCR %d is configured to be kernel controlled. Event logging denied.", 44 Event.ulPcrIndex); 45 return TCSERR(TSS_E_FAIL); 46 } 47 48 if (tcsd_options.firmware_pcrs & (1 << Event.ulPcrIndex)) { 49 LogInfo("PCR %d is configured to be firmware controlled. Event logging denied.", 50 Event.ulPcrIndex); 51 return TCSERR(TSS_E_FAIL); 52 } 53 54 return event_log_add(&Event, pNumber); 55} 56 57/* This routine will handle creating the TSS_PCR_EVENT structures from log 58 * data produced by an external source. The external source in mind here 59 * is the log of PCR extends done by the kernel from beneath the TSS 60 * (via direct calls to the device driver). 61 */ 62TSS_RESULT 63TCS_GetExternalPcrEvent(UINT32 PcrIndex, /* in */ 64 UINT32 *pNumber, /* in, out */ 65 TSS_PCR_EVENT **ppEvent) /* out */ 66{ 67 FILE *log_handle; 68 char *source; 69 70 if (tcsd_options.kernel_pcrs & (1 << PcrIndex)) { 71 source = tcsd_options.kernel_log_file; 72 73 if (tcs_event_log->kernel_source != NULL) { 74 if (tcs_event_log->kernel_source->open((void *)source, 75 (FILE **) &log_handle)) 76 return TCSERR(TSS_E_INTERNAL_ERROR); 77 78 if (tcs_event_log->kernel_source->get_entry(log_handle, PcrIndex, 79 pNumber, ppEvent)) { 80 tcs_event_log->kernel_source->close(log_handle); 81 return TCSERR(TSS_E_INTERNAL_ERROR); 82 } 83 84 tcs_event_log->kernel_source->close(log_handle); 85 } else { 86 LogError("No source for externel kernel events was compiled in, but " 87 "the tcsd is configured to use one! (see %s)", 88 tcsd_config_file); 89 return TCSERR(TSS_E_INTERNAL_ERROR); 90 } 91 } else if (tcsd_options.firmware_pcrs & (1 << PcrIndex)) { 92 source = tcsd_options.firmware_log_file; 93 94 if (tcs_event_log->firmware_source != NULL) { 95 if (tcs_event_log->firmware_source->open((void *)source, &log_handle)) 96 return TCSERR(TSS_E_INTERNAL_ERROR); 97 98 if (tcs_event_log->firmware_source->get_entry(log_handle, PcrIndex, 99 pNumber, ppEvent)) { 100 tcs_event_log->firmware_source->close(log_handle); 101 return TCSERR(TSS_E_INTERNAL_ERROR); 102 } 103 104 tcs_event_log->firmware_source->close(log_handle); 105 } else { 106 LogError("No source for externel firmware events was compiled in, but " 107 "the tcsd is configured to use one! (see %s)", 108 tcsd_config_file); 109 return TCSERR(TSS_E_INTERNAL_ERROR); 110 } 111 } else { 112 LogError("PCR index %d not flagged as kernel or firmware controlled.", PcrIndex); 113 return TCSERR(TSS_E_INTERNAL_ERROR); 114 } 115 116 return TSS_SUCCESS; 117} 118 119TSS_RESULT 120TCS_GetPcrEvent_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ 121 UINT32 PcrIndex, /* in */ 122 UINT32 *pNumber, /* in, out */ 123 TSS_PCR_EVENT **ppEvent) /* out */ 124{ 125 TSS_RESULT result; 126 TSS_PCR_EVENT *event; 127 128 if ((result = ctx_verify_context(hContext))) 129 return result; 130 131 if(PcrIndex >= tpm_metrics.num_pcrs) 132 return TCSERR(TSS_E_BAD_PARAMETER); 133 134 /* if this is a kernel or firmware controlled PCR, call an external routine */ 135 if ((tcsd_options.kernel_pcrs & (1 << PcrIndex)) || 136 (tcsd_options.firmware_pcrs & (1 << PcrIndex))) { 137 MUTEX_LOCK(tcs_event_log->lock); 138 result = TCS_GetExternalPcrEvent(PcrIndex, pNumber, ppEvent); 139 MUTEX_UNLOCK(tcs_event_log->lock); 140 141 return result; 142 } 143 144 if (ppEvent == NULL) { 145 MUTEX_LOCK(tcs_event_log->lock); 146 147 *pNumber = get_num_events(PcrIndex); 148 149 MUTEX_UNLOCK(tcs_event_log->lock); 150 } else { 151 *ppEvent = calloc(1, sizeof(TSS_PCR_EVENT)); 152 if (*ppEvent == NULL) { 153 LogError("malloc of %zd bytes failed.", sizeof(TSS_PCR_EVENT)); 154 return TCSERR(TSS_E_OUTOFMEMORY); 155 } 156 157 event = get_pcr_event(PcrIndex, *pNumber); 158 if (event == NULL) { 159 free(*ppEvent); 160 return TCSERR(TSS_E_BAD_PARAMETER); 161 } 162 163 if ((result = copy_pcr_event(*ppEvent, event))) { 164 free(*ppEvent); 165 return result; 166 } 167 } 168 169 return TSS_SUCCESS; 170} 171 172/* This routine will handle creating the TSS_PCR_EVENT structures from log 173 * data produced by an external source. The external source in mind here 174 * is the log of PCR extends done by the kernel from beneath the TSS 175 * (via direct calls to the device driver). 176 */ 177TSS_RESULT 178TCS_GetExternalPcrEventsByPcr(UINT32 PcrIndex, /* in */ 179 UINT32 FirstEvent, /* in */ 180 UINT32 *pEventCount, /* in, out */ 181 TSS_PCR_EVENT **ppEvents) /* out */ 182{ 183 FILE *log_handle; 184 char *source; 185 186 if (tcsd_options.kernel_pcrs & (1 << PcrIndex)) { 187 source = tcsd_options.kernel_log_file; 188 189 if (tcs_event_log->kernel_source != NULL) { 190 if (tcs_event_log->kernel_source->open((void *)source, &log_handle)) 191 return TCSERR(TSS_E_INTERNAL_ERROR); 192 193 if (tcs_event_log->kernel_source->get_entries_by_pcr(log_handle, PcrIndex, 194 FirstEvent, pEventCount, ppEvents)) { 195 tcs_event_log->kernel_source->close(log_handle); 196 return TCSERR(TSS_E_INTERNAL_ERROR); 197 } 198 199 tcs_event_log->kernel_source->close(log_handle); 200 } else { 201 LogError("No source for externel kernel events was compiled in, but " 202 "the tcsd is configured to use one! (see %s)", 203 tcsd_config_file); 204 return TCSERR(TSS_E_INTERNAL_ERROR); 205 } 206 } else if (tcsd_options.firmware_pcrs & (1 << PcrIndex)) { 207 source = tcsd_options.firmware_log_file; 208 209 if (tcs_event_log->firmware_source != NULL) { 210 if (tcs_event_log->firmware_source->open((void *)source, &log_handle)) 211 return TCSERR(TSS_E_INTERNAL_ERROR); 212 213 if (tcs_event_log->firmware_source->get_entries_by_pcr(log_handle, PcrIndex, 214 FirstEvent, pEventCount, ppEvents)) { 215 tcs_event_log->firmware_source->close(log_handle); 216 return TCSERR(TSS_E_INTERNAL_ERROR); 217 } 218 219 tcs_event_log->firmware_source->close(log_handle); 220 } else { 221 LogError("No source for externel firmware events was compiled in, but " 222 "the tcsd is configured to use one! (see %s)", 223 tcsd_config_file); 224 return TCSERR(TSS_E_INTERNAL_ERROR); 225 } 226 } else { 227 LogError("PCR index %d not flagged as kernel or firmware controlled.", PcrIndex); 228 return TCSERR(TSS_E_INTERNAL_ERROR); 229 } 230 231 return TSS_SUCCESS; 232} 233 234TSS_RESULT 235TCS_GetPcrEventsByPcr_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ 236 UINT32 PcrIndex, /* in */ 237 UINT32 FirstEvent, /* in */ 238 UINT32 *pEventCount, /* in, out */ 239 TSS_PCR_EVENT **ppEvents) /* out */ 240{ 241 UINT32 lastEventNumber, i, eventIndex; 242 TSS_RESULT result; 243 struct event_wrapper *tmp; 244 245 if ((result = ctx_verify_context(hContext))) 246 return result; 247 248 if (PcrIndex >= tpm_metrics.num_pcrs) 249 return TCSERR(TSS_E_BAD_PARAMETER); 250 251 if (*pEventCount == 0) { 252 *ppEvents = NULL; 253 return TSS_SUCCESS; 254 } 255 256 /* if this is a kernel or firmware controlled PCR, call an external routine */ 257 if ((tcsd_options.kernel_pcrs & (1 << PcrIndex)) || 258 (tcsd_options.firmware_pcrs & (1 << PcrIndex))) { 259 MUTEX_LOCK(tcs_event_log->lock); 260 result = TCS_GetExternalPcrEventsByPcr(PcrIndex, FirstEvent, 261 pEventCount, ppEvents); 262 MUTEX_UNLOCK(tcs_event_log->lock); 263 264 return result; 265 } 266 267 MUTEX_LOCK(tcs_event_log->lock); 268 269 lastEventNumber = get_num_events(PcrIndex); 270 271 MUTEX_UNLOCK(tcs_event_log->lock); 272 273 /* if pEventCount is larger than the number of events to return, just return less. 274 * *pEventCount will be set to the number returned below. First, check for overflow. 275 */ 276 if ((FirstEvent + *pEventCount) >= FirstEvent && 277 (FirstEvent + *pEventCount) >= *pEventCount) 278 lastEventNumber = MIN(lastEventNumber, FirstEvent + *pEventCount); 279 280 if (FirstEvent > lastEventNumber) 281 return TCSERR(TSS_E_BAD_PARAMETER); 282 283 if (lastEventNumber == 0) { 284 *pEventCount = 0; 285 *ppEvents = NULL; 286 return TSS_SUCCESS; 287 } 288 289 /* FirstEvent is 0 indexed see TSS 1.1b spec section 4.7.2.2.3. That means that 290 * the following calculation is not off by one. :-) 291 */ 292 *ppEvents = calloc((lastEventNumber - FirstEvent), sizeof(TSS_PCR_EVENT)); 293 if (*ppEvents == NULL) { 294 LogError("malloc of %zd bytes failed.", 295 sizeof(TSS_PCR_EVENT) * (lastEventNumber - FirstEvent)); 296 return TCSERR(TSS_E_OUTOFMEMORY); 297 } 298 299 MUTEX_LOCK(tcs_event_log->lock); 300 301 tmp = tcs_event_log->lists[PcrIndex]; 302 303 /* move through the list until we get to the first event requested */ 304 for (i = 0; i < FirstEvent; i++) 305 tmp = tmp->next; 306 307 /* copy events from the first requested to the last requested */ 308 for (eventIndex = 0; i < lastEventNumber; eventIndex++, i++) { 309 copy_pcr_event(&((*ppEvents)[eventIndex]), &(tmp->event)); 310 tmp = tmp->next; 311 } 312 313 MUTEX_UNLOCK(tcs_event_log->lock); 314 315 *pEventCount = eventIndex; 316 317 return TSS_SUCCESS; 318} 319 320TSS_RESULT 321TCS_GetPcrEventLog_Internal(TCS_CONTEXT_HANDLE hContext,/* in */ 322 UINT32 *pEventCount, /* out */ 323 TSS_PCR_EVENT **ppEvents) /* out */ 324{ 325 TSS_RESULT result; 326 UINT32 i, j, event_count, aggregate_count = 0; 327 struct event_wrapper *tmp; 328 TSS_PCR_EVENT *event_list = NULL, *aggregate_list = NULL; 329 330 if ((result = ctx_verify_context(hContext))) 331 return result; 332 333 MUTEX_LOCK(tcs_event_log->lock); 334 335 /* for each PCR index, if its externally controlled, get the total number of events 336 * externally, else copy the events from the TCSD list. Then tack that list onto a 337 * master list to returned. */ 338 for (i = 0; i < tpm_metrics.num_pcrs; i++) { 339 if ((tcsd_options.kernel_pcrs & (1 << i)) || 340 (tcsd_options.firmware_pcrs & (1 << i))) { 341 /* A kernel or firmware controlled PCR event list */ 342 event_count = UINT_MAX; 343 if ((result = TCS_GetExternalPcrEventsByPcr(i, 0, &event_count, 344 &event_list))) { 345 LogDebug("Getting External event list for PCR %u failed", i); 346 free(aggregate_list); 347 goto error; 348 } 349 LogDebug("Retrieved %u events from PCR %u (external)", event_count, i); 350 } else { 351 /* A TCSD controlled PCR event list */ 352 event_count = get_num_events(i); 353 354 if (event_count == 0) 355 continue; 356 357 if ((event_list = calloc(event_count, sizeof(TSS_PCR_EVENT))) == NULL) { 358 LogError("malloc of %zd bytes failed", 359 event_count * sizeof(TSS_PCR_EVENT)); 360 result = TCSERR(TSS_E_OUTOFMEMORY); 361 free(aggregate_list); 362 goto error; 363 } 364 365 tmp = tcs_event_log->lists[i]; 366 for (j = 0; j < event_count; j++) { 367 copy_pcr_event(&event_list[j], &(tmp->event)); 368 tmp = tmp->next; 369 } 370 } 371 372 if (event_count == 0) 373 continue; 374 375 /* Tack the list onto the aggregate_list */ 376 aggregate_list = concat_pcr_events(&aggregate_list, aggregate_count, event_list, 377 event_count); 378 if (aggregate_list == NULL) { 379 free(event_list); 380 result = TCSERR(TSS_E_OUTOFMEMORY); 381 goto error; 382 } 383 aggregate_count += event_count; 384 free(event_list); 385 } 386 387 *ppEvents = aggregate_list; 388 *pEventCount = aggregate_count; 389 result = TSS_SUCCESS; 390error: 391 MUTEX_UNLOCK(tcs_event_log->lock); 392 393 return result; 394} 395 396