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