Home | History | Annotate | Line # | Download | only in tcs
      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 (*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 
    320 TSS_RESULT
    321 TCS_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;
    390 error:
    391 	MUTEX_UNLOCK(tcs_event_log->lock);
    392 
    393 	return result;
    394 }
    395 
    396