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 struct event_log *tcs_event_log = NULL;
30 
31 TSS_RESULT
event_log_init()32 event_log_init()
33 {
34           if (tcs_event_log != NULL)
35                     return TSS_SUCCESS;
36 
37           tcs_event_log = calloc(1, sizeof(struct event_log));
38           if (tcs_event_log == NULL) {
39                     LogError("malloc of %zd bytes failed.", sizeof(struct event_log));
40                     return TCSERR(TSS_E_OUTOFMEMORY);
41           }
42 
43           MUTEX_INIT(tcs_event_log->lock);
44 
45           /* allocate as many event lists as there are PCR's */
46           tcs_event_log->lists = calloc(tpm_metrics.num_pcrs, sizeof(struct event_wrapper *));
47           if (tcs_event_log->lists == NULL) {
48                     LogError("malloc of %zd bytes failed.",
49                                         tpm_metrics.num_pcrs * sizeof(struct event_wrapper *));
50                     free(tcs_event_log);
51                     return TCSERR(TSS_E_OUTOFMEMORY);
52           }
53 
54           /* assign external event log sources here */
55           //tcs_event_log->firmware_source = EVLOG_IMA_SOURCE;
56           tcs_event_log->firmware_source = EVLOG_BIOS_SOURCE;
57           tcs_event_log->kernel_source = EVLOG_IMA_SOURCE;
58 
59           return TSS_SUCCESS;
60 }
61 
62 TSS_RESULT
event_log_final()63 event_log_final()
64 {
65           struct event_wrapper *cur, *next;
66           UINT32 i;
67 
68           MUTEX_LOCK(tcs_event_log->lock);
69 
70           for (i = 0; i < tpm_metrics.num_pcrs; i++) {
71                     cur = tcs_event_log->lists[i];
72                     while (cur != NULL) {
73                               next = cur->next;
74                               free(cur->event.rgbPcrValue);
75                               free(cur->event.rgbEvent);
76                               free(cur);
77                               cur = next;
78                     }
79           }
80 
81           MUTEX_UNLOCK(tcs_event_log->lock);
82 
83           free(tcs_event_log->lists);
84           free(tcs_event_log);
85 
86           return TSS_SUCCESS;
87 }
88 
89 TSS_RESULT
copy_pcr_event(TSS_PCR_EVENT * dest,TSS_PCR_EVENT * source)90 copy_pcr_event(TSS_PCR_EVENT *dest, TSS_PCR_EVENT *source)
91 {
92           memcpy(dest, source, sizeof(TSS_PCR_EVENT));
93           return TSS_SUCCESS;
94 }
95 
96 TSS_RESULT
event_log_add(TSS_PCR_EVENT * event,UINT32 * pNumber)97 event_log_add(TSS_PCR_EVENT *event, UINT32 *pNumber)
98 {
99           struct event_wrapper *new, *tmp;
100           TSS_RESULT result;
101           UINT32 i;
102 
103           MUTEX_LOCK(tcs_event_log->lock);
104 
105           new = calloc(1, sizeof(struct event_wrapper));
106           if (new == NULL) {
107                     LogError("malloc of %zd bytes failed.", sizeof(struct event_wrapper));
108                     MUTEX_UNLOCK(tcs_event_log->lock);
109                     return TCSERR(TSS_E_OUTOFMEMORY);
110           }
111 
112           if ((result = copy_pcr_event(&(new->event), event))) {
113                     free(new);
114                     MUTEX_UNLOCK(tcs_event_log->lock);
115                     return result;
116           }
117 
118           /* go to the end of the list to add the element, so that they're in order */
119           i = 0;
120           if (tcs_event_log->lists[event->ulPcrIndex] == NULL) {
121                     tcs_event_log->lists[event->ulPcrIndex] = new;
122           } else {
123                     i++;
124                     tmp = tcs_event_log->lists[event->ulPcrIndex];
125                     while (tmp->next != NULL) {
126                               i++;
127                               tmp = tmp->next;
128                     }
129                     tmp->next = new;
130           }
131 
132           *pNumber = ++i;
133 
134           MUTEX_UNLOCK(tcs_event_log->lock);
135 
136           return TSS_SUCCESS;
137 }
138 
139 TSS_PCR_EVENT *
get_pcr_event(UINT32 pcrIndex,UINT32 eventNumber)140 get_pcr_event(UINT32 pcrIndex, UINT32 eventNumber)
141 {
142           struct event_wrapper *tmp;
143           UINT32 counter = 0;
144 
145           MUTEX_LOCK(tcs_event_log->lock);
146 
147           tmp = tcs_event_log->lists[pcrIndex];
148           for (; tmp; tmp = tmp->next) {
149                     if (counter == eventNumber) {
150                               break;
151                     }
152                     counter++;
153           }
154 
155           MUTEX_UNLOCK(tcs_event_log->lock);
156 
157           return (tmp ? &(tmp->event) : NULL);
158 }
159 
160 /* the lock should be held before calling this function */
161 UINT32
get_num_events(UINT32 pcrIndex)162 get_num_events(UINT32 pcrIndex)
163 {
164           struct event_wrapper *tmp;
165           UINT32 counter = 0;
166 
167           tmp = tcs_event_log->lists[pcrIndex];
168           for (; tmp; tmp = tmp->next) {
169                     counter++;
170           }
171 
172           return counter;
173 }
174 
175 TSS_PCR_EVENT *
concat_pcr_events(TSS_PCR_EVENT ** list_so_far,UINT32 list_size,TSS_PCR_EVENT * addition,UINT32 addition_size)176 concat_pcr_events(TSS_PCR_EVENT **list_so_far, UINT32 list_size, TSS_PCR_EVENT *addition,
177                       UINT32 addition_size)
178 {
179           TSS_PCR_EVENT *ret;
180 
181           ret = realloc(*list_so_far, (list_size + addition_size) * sizeof(TSS_PCR_EVENT));
182           if (ret == NULL) {
183                     LogError("malloc of %zd bytes failed",
184                                (list_size + addition_size) * sizeof(TSS_PCR_EVENT));
185                     return ret;
186           }
187 
188           memcpy(&ret[list_size], addition, addition_size * sizeof(TSS_PCR_EVENT));
189           return ret;
190 }
191 
192 /* XXX make this a macro */
193 UINT32
get_pcr_event_size(TSS_PCR_EVENT * e)194 get_pcr_event_size(TSS_PCR_EVENT *e)
195 {
196           return (sizeof(TSS_PCR_EVENT) + e->ulEventLength + e->ulPcrValueLength);
197 }
198 
199 void
free_external_events(UINT32 eventCount,TSS_PCR_EVENT * ppEvents)200 free_external_events(UINT32 eventCount, TSS_PCR_EVENT *ppEvents)
201 {
202           UINT32 j;
203 
204           if (!ppEvents)
205                     return;
206 
207           for (j = 0; j < eventCount; j++) {
208                     /* This is a fairly heinous hack, but PCR event logs can get really large
209                      * and without it, there is a real potential to exhaust memory by leaks.
210                      * The PCR event logs that we pull out of securityfs have had their
211                      * rgbPcrValue and rgbEvent pointers malloc'd dynamically as the
212                      * securityfs log was parsed. The other event log lists that are
213                      * maintained by the TCSD don't need to have this data free'd, since that
214                      * will happen at shutdown time only. So, for each PCR index that's
215                      * read from securityfs, we need to free its pointers after that data has
216                      * been set in the packet to send back to the TSP. */
217                     if ((tcsd_options.kernel_pcrs & (1 << ppEvents[j].ulPcrIndex)) ||
218                         (tcsd_options.firmware_pcrs & (1 << ppEvents[j].ulPcrIndex))) {
219                               free(ppEvents[j].rgbPcrValue);
220                               free(ppEvents[j].rgbEvent);
221                     }
222           }
223 }
224