3
* Licensed Materials - Property of IBM
5
* trousers - An open source TCG Software Stack
7
* (C) Copyright International Business Machines Corp. 2004
18
#include "trousers/tss.h"
19
#include "spi_internal_types.h"
20
#include "tcs_internal_types.h"
22
#include "tcs_utils.h"
23
#include "tcs_int_literals.h"
24
#include "capabilities.h"
25
#include "tcsd_wrap.h"
31
TCS_CONTEXT_HANDLE InternalContext = 0x30000000;
33
struct event_log *tcs_event_log = NULL;
38
if (tcs_event_log != NULL)
41
tcs_event_log = calloc(1, sizeof(struct event_log));
42
if (tcs_event_log == NULL) {
43
LogError("malloc of %zd bytes failed.", sizeof(struct event_log));
44
return TCSERR(TSS_E_OUTOFMEMORY);
47
pthread_mutex_init(&(tcs_event_log->lock), NULL);
49
/* allocate as many event lists as there are PCR's */
50
tcs_event_log->lists = calloc(tpm_metrics.num_pcrs, sizeof(struct event_wrapper *));
51
if (tcs_event_log->lists == NULL) {
52
LogError("malloc of %zd bytes failed.",
53
tpm_metrics.num_pcrs * sizeof(struct event_wrapper *));
55
return TCSERR(TSS_E_OUTOFMEMORY);
58
/* assign external event log sources here */
59
tcs_event_log->firmware_source = EVLOG_BIOS_SOURCE;
60
tcs_event_log->kernel_source = EVLOG_BIOS_SOURCE;
68
struct event_wrapper *cur, *next;
71
pthread_mutex_lock(&(tcs_event_log->lock));
73
for (i = 0; i < tpm_metrics.num_pcrs; i++) {
74
cur = tcs_event_log->lists[i];
77
free(cur->event.rgbPcrValue);
78
free(cur->event.rgbEvent);
84
pthread_mutex_unlock(&(tcs_event_log->lock));
86
free(tcs_event_log->lists);
93
copy_pcr_event(TSS_PCR_EVENT *dest, TSS_PCR_EVENT *source)
95
memcpy(dest, source, sizeof(TSS_PCR_EVENT));
100
event_log_add(TSS_PCR_EVENT *event, UINT32 *pNumber)
102
struct event_wrapper *new, *tmp;
106
pthread_mutex_lock(&(tcs_event_log->lock));
108
new = calloc(1, sizeof(struct event_wrapper));
110
LogError("malloc of %zd bytes failed.", sizeof(struct event_wrapper));
111
pthread_mutex_unlock(&(tcs_event_log->lock));
112
return TCSERR(TSS_E_OUTOFMEMORY);
115
if ((result = copy_pcr_event(&(new->event), event))) {
117
pthread_mutex_unlock(&(tcs_event_log->lock));
121
/* go to the end of the list to add the element, so that they're in order */
123
if (tcs_event_log->lists[event->ulPcrIndex] == NULL) {
124
tcs_event_log->lists[event->ulPcrIndex] = new;
127
tmp = tcs_event_log->lists[event->ulPcrIndex];
128
while (tmp->next != NULL) {
137
pthread_mutex_unlock(&(tcs_event_log->lock));
143
get_pcr_event(UINT32 pcrIndex, UINT32 eventNumber)
145
struct event_wrapper *tmp;
148
pthread_mutex_lock(&(tcs_event_log->lock));
150
tmp = tcs_event_log->lists[pcrIndex];
151
for (; tmp; tmp = tmp->next) {
152
if (counter == eventNumber) {
158
pthread_mutex_unlock(&(tcs_event_log->lock));
160
return (tmp ? &(tmp->event) : NULL);
163
/* the lock should be held before calling this function */
165
get_num_events(UINT32 pcrIndex)
167
struct event_wrapper *tmp;
170
tmp = tcs_event_log->lists[pcrIndex];
171
for (; tmp; tmp = tmp->next) {
179
TCS_LogPcrEvent_Internal(TCS_CONTEXT_HANDLE hContext, /* in */
180
TSS_PCR_EVENT Event, /* in */
181
UINT32 *pNumber) /* out */
185
if((result = ctx_verify_context(hContext)))
188
if(Event.ulPcrIndex >= tpm_metrics.num_pcrs)
189
return TCSERR(TSS_E_BAD_PARAMETER);
191
if (tcsd_options.kernel_pcrs & (1 << Event.ulPcrIndex)) {
192
LogInfo("PCR %d is configured to be kernel controlled. Event logging denied.",
194
return TCSERR(TSS_E_FAIL);
197
if (tcsd_options.firmware_pcrs & (1 << Event.ulPcrIndex)) {
198
LogInfo("PCR %d is configured to be firmware controlled. Event logging denied.",
200
return TCSERR(TSS_E_FAIL);
203
return event_log_add(&Event, pNumber);
206
/* This routine will handle creating the TSS_PCR_EVENT structures from log
207
* data produced by an external source. The external source in mind here
208
* is the log of PCR extends done by the kernel from beneath the TSS
209
* (via direct calls to the device driver).
212
TCS_GetExternalPcrEvent(UINT32 PcrIndex, /* in */
213
UINT32 *pNumber, /* in, out */
214
TSS_PCR_EVENT **ppEvent) /* out */
219
if (tcsd_options.kernel_pcrs & (1 << PcrIndex)) {
220
source = tcsd_options.kernel_log_file;
222
if (tcs_event_log->kernel_source != NULL) {
223
if (tcs_event_log->kernel_source->open((void *)source, &log_handle))
224
return TCSERR(TSS_E_INTERNAL_ERROR);
226
if (tcs_event_log->kernel_source->get_entry(log_handle, PcrIndex,
228
tcs_event_log->kernel_source->close(log_handle);
229
return TCSERR(TSS_E_INTERNAL_ERROR);
232
tcs_event_log->kernel_source->close(log_handle);
234
LogError("No source for externel kernel events was compiled in, but "
235
"the tcsd is configured to use one! (see %s)",
237
return TCSERR(TSS_E_INTERNAL_ERROR);
239
} else if (tcsd_options.firmware_pcrs & (1 << PcrIndex)) {
240
source = tcsd_options.firmware_log_file;
242
if (tcs_event_log->firmware_source != NULL) {
243
if (tcs_event_log->firmware_source->open((void *)source, &log_handle))
244
return TCSERR(TSS_E_INTERNAL_ERROR);
246
if (tcs_event_log->firmware_source->get_entry(log_handle, PcrIndex,
248
tcs_event_log->firmware_source->close(log_handle);
249
return TCSERR(TSS_E_INTERNAL_ERROR);
252
tcs_event_log->firmware_source->close(log_handle);
254
LogError("No source for externel firmware events was compiled in, but "
255
"the tcsd is configured to use one! (see %s)",
257
return TCSERR(TSS_E_INTERNAL_ERROR);
260
LogError("PCR index %d not flagged as kernel or firmware controlled.", PcrIndex);
261
return TCSERR(TSS_E_INTERNAL_ERROR);
268
TCS_GetPcrEvent_Internal(TCS_CONTEXT_HANDLE hContext, /* in */
269
UINT32 PcrIndex, /* in */
270
UINT32 *pNumber, /* in, out */
271
TSS_PCR_EVENT **ppEvent) /* out */
274
TSS_PCR_EVENT *event;
276
if ((result = ctx_verify_context(hContext)))
279
if(PcrIndex >= tpm_metrics.num_pcrs)
280
return TCSERR(TSS_E_BAD_PARAMETER);
282
/* if this is a kernel or firmware controlled PCR, call an external routine */
283
if ((tcsd_options.kernel_pcrs & (1 << PcrIndex)) ||
284
(tcsd_options.firmware_pcrs & (1 << PcrIndex))) {
285
pthread_mutex_lock(&(tcs_event_log->lock));
286
result = TCS_GetExternalPcrEvent(PcrIndex, pNumber, ppEvent);
287
pthread_mutex_unlock(&(tcs_event_log->lock));
292
if (ppEvent == NULL) {
293
pthread_mutex_lock(&(tcs_event_log->lock));
295
*pNumber = get_num_events(PcrIndex);
297
pthread_mutex_unlock(&(tcs_event_log->lock));
299
*ppEvent = calloc(1, sizeof(TSS_PCR_EVENT));
300
if (*ppEvent == NULL) {
301
LogError("malloc of %zd bytes failed.", sizeof(TSS_PCR_EVENT));
302
return TCSERR(TSS_E_OUTOFMEMORY);
305
event = get_pcr_event(PcrIndex, *pNumber);
308
return TCSERR(TSS_E_BAD_PARAMETER);
311
if ((result = copy_pcr_event(*ppEvent, event))) {
320
/* This routine will handle creating the TSS_PCR_EVENT structures from log
321
* data produced by an external source. The external source in mind here
322
* is the log of PCR extends done by the kernel from beneath the TSS
323
* (via direct calls to the device driver).
326
TCS_GetExternalPcrEventsByPcr(UINT32 PcrIndex, /* in */
327
UINT32 FirstEvent, /* in */
328
UINT32 *pEventCount, /* in, out */
329
TSS_PCR_EVENT **ppEvents) /* out */
334
if (tcsd_options.kernel_pcrs & (1 << PcrIndex)) {
335
source = tcsd_options.kernel_log_file;
337
if (tcs_event_log->kernel_source != NULL) {
338
if (tcs_event_log->kernel_source->open((void *)source, &log_handle))
339
return TCSERR(TSS_E_INTERNAL_ERROR);
341
if (tcs_event_log->kernel_source->get_entries_by_pcr(log_handle, PcrIndex,
342
FirstEvent, pEventCount, ppEvents)) {
343
tcs_event_log->kernel_source->close(log_handle);
344
return TCSERR(TSS_E_INTERNAL_ERROR);
347
tcs_event_log->kernel_source->close(log_handle);
349
LogError("No source for externel kernel events was compiled in, but "
350
"the tcsd is configured to use one! (see %s)",
352
return TCSERR(TSS_E_INTERNAL_ERROR);
354
} else if (tcsd_options.firmware_pcrs & (1 << PcrIndex)) {
355
source = tcsd_options.firmware_log_file;
357
if (tcs_event_log->firmware_source != NULL) {
358
if (tcs_event_log->firmware_source->open((void *)source, &log_handle))
359
return TCSERR(TSS_E_INTERNAL_ERROR);
361
if (tcs_event_log->firmware_source->get_entries_by_pcr(log_handle, PcrIndex,
362
FirstEvent, pEventCount, ppEvents)) {
363
tcs_event_log->firmware_source->close(log_handle);
364
return TCSERR(TSS_E_INTERNAL_ERROR);
367
tcs_event_log->firmware_source->close(log_handle);
369
LogError("No source for externel firmware events was compiled in, but "
370
"the tcsd is configured to use one! (see %s)",
372
return TCSERR(TSS_E_INTERNAL_ERROR);
375
LogError("PCR index %d not flagged as kernel or firmware controlled.", PcrIndex);
376
return TCSERR(TSS_E_INTERNAL_ERROR);
383
TCS_GetPcrEventsByPcr_Internal(TCS_CONTEXT_HANDLE hContext, /* in */
384
UINT32 PcrIndex, /* in */
385
UINT32 FirstEvent, /* in */
386
UINT32 *pEventCount, /* in, out */
387
TSS_PCR_EVENT **ppEvents) /* out */
389
UINT32 lastEventNumber, i, eventIndex;
391
struct event_wrapper *tmp;
393
if ((result = ctx_verify_context(hContext)))
396
if (PcrIndex >= tpm_metrics.num_pcrs)
397
return TCSERR(TSS_E_BAD_PARAMETER);
399
/* if this is a kernel or firmware controlled PCR, call an external routine */
400
if ((tcsd_options.kernel_pcrs & (1 << PcrIndex)) ||
401
(tcsd_options.firmware_pcrs & (1 << PcrIndex))) {
402
pthread_mutex_lock(&(tcs_event_log->lock));
403
result = TCS_GetExternalPcrEventsByPcr(PcrIndex, FirstEvent,
404
pEventCount, ppEvents);
405
pthread_mutex_unlock(&(tcs_event_log->lock));
410
pthread_mutex_lock(&(tcs_event_log->lock));
412
lastEventNumber = get_num_events(PcrIndex);
414
pthread_mutex_unlock(&(tcs_event_log->lock));
416
/* if pEventCount is larger than the number of events to return, just return less.
417
* *pEventCount will be set to the number returned below.
419
lastEventNumber = MIN(lastEventNumber, FirstEvent + *pEventCount);
421
if (FirstEvent > lastEventNumber)
422
return TCSERR(TSS_E_BAD_PARAMETER);
424
if (lastEventNumber == 0) {
430
/* FirstEvent is 0 indexed see TSS 1.1b spec section 4.7.2.2.3. That means that
431
* the following calculation is not off by one. :-)
433
*ppEvents = calloc((lastEventNumber - FirstEvent), sizeof(TSS_PCR_EVENT));
434
if (*ppEvents == NULL) {
435
LogError("malloc of %zd bytes failed.",
436
sizeof(TSS_PCR_EVENT) * (lastEventNumber - FirstEvent));
437
return TCSERR(TSS_E_OUTOFMEMORY);
440
pthread_mutex_lock(&(tcs_event_log->lock));
442
tmp = tcs_event_log->lists[PcrIndex];
444
/* move through the list until we get to the first event requested */
445
for (i = 0; i < FirstEvent; i++)
448
/* copy events from the first requested to the last requested */
449
for (eventIndex = 0; i < lastEventNumber; eventIndex++, i++) {
450
copy_pcr_event(&((*ppEvents)[eventIndex]), &(tmp->event));
454
pthread_mutex_unlock(&(tcs_event_log->lock));
456
*pEventCount = eventIndex;
462
concat_pcr_events(TSS_PCR_EVENT **list_so_far, UINT32 list_size, TSS_PCR_EVENT *addition,
463
UINT32 addition_size)
467
ret = realloc(*list_so_far, (list_size + addition_size) * sizeof(TSS_PCR_EVENT));
469
LogError("malloc of %zd bytes failed",
470
(list_size + addition_size) * sizeof(TSS_PCR_EVENT));
474
memcpy(&ret[list_size], addition, addition_size * sizeof(TSS_PCR_EVENT));
479
TCS_GetPcrEventLog_Internal(TCS_CONTEXT_HANDLE hContext,/* in */
480
UINT32 *pEventCount, /* out */
481
TSS_PCR_EVENT **ppEvents) /* out */
484
UINT32 i, j, event_count, aggregate_count = 0;
485
struct event_wrapper *tmp;
486
TSS_PCR_EVENT *event_list = NULL, *aggregate_list = NULL;
488
if ((result = ctx_verify_context(hContext)))
491
pthread_mutex_lock(&(tcs_event_log->lock));
493
/* for each PCR index, if its externally controlled, get the total number of events
494
* externally, else copy the events from the TCSD list. Then tack that list onto a
495
* master list to returned. */
496
for (i = 0; i < tpm_metrics.num_pcrs; i++) {
497
if ((tcsd_options.kernel_pcrs & (1 << i)) ||
498
(tcsd_options.firmware_pcrs & (1 << i))) {
499
/* A kernel or firmware controlled PCR event list */
500
event_count = UINT_MAX;
501
if ((result = TCS_GetExternalPcrEventsByPcr(i, 0, &event_count,
503
LogDebug("Getting External event list for PCR %u failed", i);
504
free(aggregate_list);
507
LogDebug("Retrieved %u events from PCR %u (external)", event_count, i);
509
/* A TCSD controlled PCR event list */
510
event_count = get_num_events(i);
512
if (event_count == 0)
515
if ((event_list = calloc(event_count, sizeof(TSS_PCR_EVENT))) == NULL) {
516
LogError("malloc of %zd bytes failed",
517
event_count * sizeof(TSS_PCR_EVENT));
518
result = TCSERR(TSS_E_OUTOFMEMORY);
519
free(aggregate_list);
523
tmp = tcs_event_log->lists[i];
524
for (j = 0; j < event_count; j++) {
525
copy_pcr_event(&event_list[j], &(tmp->event));
530
if (event_count == 0)
533
/* Tack the list onto the aggregate_list */
534
aggregate_list = concat_pcr_events(&aggregate_list, aggregate_count, event_list,
536
if (aggregate_list == NULL) {
538
result = TCSERR(TSS_E_OUTOFMEMORY);
541
aggregate_count += event_count;
545
*ppEvents = aggregate_list;
546
*pEventCount = aggregate_count;
547
result = TSS_SUCCESS;
549
pthread_mutex_unlock(&(tcs_event_log->lock));