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