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