xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tcs/tcsi_evlog.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
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