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