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