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 TSS_RESULT 30 TCS_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 */ 62 TSS_RESULT 63 TCS_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 119 TSS_RESULT 120 TCS_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 */ 177 TSS_RESULT 178 TCS_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 234 TSS_RESULT 235 TCS_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 this is a kernel or firmware controlled PCR, call an external routine */ 252 if ((tcsd_options.kernel_pcrs & (1 << PcrIndex)) || 253 (tcsd_options.firmware_pcrs & (1 << PcrIndex))) { 254 MUTEX_LOCK(tcs_event_log->lock); 255 result = TCS_GetExternalPcrEventsByPcr(PcrIndex, FirstEvent, 256 pEventCount, ppEvents); 257 MUTEX_UNLOCK(tcs_event_log->lock); 258 259 return result; 260 } 261 262 MUTEX_LOCK(tcs_event_log->lock); 263 264 lastEventNumber = get_num_events(PcrIndex); 265 266 MUTEX_UNLOCK(tcs_event_log->lock); 267 268 /* if pEventCount is larger than the number of events to return, just return less. 269 * *pEventCount will be set to the number returned below. 270 */ 271 lastEventNumber = MIN(lastEventNumber, FirstEvent + *pEventCount); 272 273 if (FirstEvent > lastEventNumber) 274 return TCSERR(TSS_E_BAD_PARAMETER); 275 276 if (lastEventNumber == 0) { 277 *pEventCount = 0; 278 *ppEvents = NULL; 279 return TSS_SUCCESS; 280 } 281 282 /* FirstEvent is 0 indexed see TSS 1.1b spec section 4.7.2.2.3. That means that 283 * the following calculation is not off by one. :-) 284 */ 285 *ppEvents = calloc((lastEventNumber - FirstEvent), sizeof(TSS_PCR_EVENT)); 286 if (*ppEvents == NULL) { 287 LogError("malloc of %zd bytes failed.", 288 sizeof(TSS_PCR_EVENT) * (lastEventNumber - FirstEvent)); 289 return TCSERR(TSS_E_OUTOFMEMORY); 290 } 291 292 MUTEX_LOCK(tcs_event_log->lock); 293 294 tmp = tcs_event_log->lists[PcrIndex]; 295 296 /* move through the list until we get to the first event requested */ 297 for (i = 0; i < FirstEvent; i++) 298 tmp = tmp->next; 299 300 /* copy events from the first requested to the last requested */ 301 for (eventIndex = 0; i < lastEventNumber; eventIndex++, i++) { 302 copy_pcr_event(&((*ppEvents)[eventIndex]), &(tmp->event)); 303 tmp = tmp->next; 304 } 305 306 MUTEX_UNLOCK(tcs_event_log->lock); 307 308 *pEventCount = eventIndex; 309 310 return TSS_SUCCESS; 311 } 312 313 TSS_RESULT 314 TCS_GetPcrEventLog_Internal(TCS_CONTEXT_HANDLE hContext,/* in */ 315 UINT32 *pEventCount, /* out */ 316 TSS_PCR_EVENT **ppEvents) /* out */ 317 { 318 TSS_RESULT result; 319 UINT32 i, j, event_count, aggregate_count = 0; 320 struct event_wrapper *tmp; 321 TSS_PCR_EVENT *event_list = NULL, *aggregate_list = NULL; 322 323 if ((result = ctx_verify_context(hContext))) 324 return result; 325 326 MUTEX_LOCK(tcs_event_log->lock); 327 328 /* for each PCR index, if its externally controlled, get the total number of events 329 * externally, else copy the events from the TCSD list. Then tack that list onto a 330 * master list to returned. */ 331 for (i = 0; i < tpm_metrics.num_pcrs; i++) { 332 if ((tcsd_options.kernel_pcrs & (1 << i)) || 333 (tcsd_options.firmware_pcrs & (1 << i))) { 334 /* A kernel or firmware controlled PCR event list */ 335 event_count = UINT_MAX; 336 if ((result = TCS_GetExternalPcrEventsByPcr(i, 0, &event_count, 337 &event_list))) { 338 LogDebug("Getting External event list for PCR %u failed", i); 339 free(aggregate_list); 340 goto error; 341 } 342 LogDebug("Retrieved %u events from PCR %u (external)", event_count, i); 343 } else { 344 /* A TCSD controlled PCR event list */ 345 event_count = get_num_events(i); 346 347 if (event_count == 0) 348 continue; 349 350 if ((event_list = calloc(event_count, sizeof(TSS_PCR_EVENT))) == NULL) { 351 LogError("malloc of %zd bytes failed", 352 event_count * sizeof(TSS_PCR_EVENT)); 353 result = TCSERR(TSS_E_OUTOFMEMORY); 354 free(aggregate_list); 355 goto error; 356 } 357 358 tmp = tcs_event_log->lists[i]; 359 for (j = 0; j < event_count; j++) { 360 copy_pcr_event(&event_list[j], &(tmp->event)); 361 tmp = tmp->next; 362 } 363 } 364 365 if (event_count == 0) 366 continue; 367 368 /* Tack the list onto the aggregate_list */ 369 aggregate_list = concat_pcr_events(&aggregate_list, aggregate_count, event_list, 370 event_count); 371 if (aggregate_list == NULL) { 372 free(event_list); 373 result = TCSERR(TSS_E_OUTOFMEMORY); 374 goto error; 375 } 376 aggregate_count += event_count; 377 free(event_list); 378 } 379 380 *ppEvents = aggregate_list; 381 *pEventCount = aggregate_count; 382 result = TSS_SUCCESS; 383 error: 384 MUTEX_UNLOCK(tcs_event_log->lock); 385 386 return result; 387 } 388 389