xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tcs/tcsi_evlog.c (revision 1023804e3833a0bd94414f2545512128f6502c74)
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
TCS_LogPcrEvent_Internal(TCS_CONTEXT_HANDLE hContext,TSS_PCR_EVENT Event,UINT32 * pNumber)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
TCS_GetExternalPcrEvent(UINT32 PcrIndex,UINT32 * pNumber,TSS_PCR_EVENT ** ppEvent)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
TCS_GetPcrEvent_Internal(TCS_CONTEXT_HANDLE hContext,UINT32 PcrIndex,UINT32 * pNumber,TSS_PCR_EVENT ** ppEvent)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
TCS_GetExternalPcrEventsByPcr(UINT32 PcrIndex,UINT32 FirstEvent,UINT32 * pEventCount,TSS_PCR_EVENT ** ppEvents)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
TCS_GetPcrEventsByPcr_Internal(TCS_CONTEXT_HANDLE hContext,UINT32 PcrIndex,UINT32 FirstEvent,UINT32 * pEventCount,TSS_PCR_EVENT ** ppEvents)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
TCS_GetPcrEventLog_Internal(TCS_CONTEXT_HANDLE hContext,UINT32 * pEventCount,TSS_PCR_EVENT ** ppEvents)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