xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tcs/tcs_evlog_imaem.c (revision 1023804e3833a0bd94414f2545512128f6502c74)
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-2006
8  *
9  */
10 
11 /*
12  * imaem.c
13  *
14  * Routines for handling PCR events from the Integrity Measurement
15  * Architecture.
16  *
17  * The external event source format used by IMA:
18  *
19  *     4 bytes PCR Index (bin)
20  *    20 bytes SHA1 template (bin)
21  *     4 bytes template name_len
22  * 1-255 bytes template name
23  *    20 bytes SHA1 IMA(bin)
24  *     4 bytes IMA name len
25  * 1-255 bytes eventname
26  *     1 byte  separator = '\0'
27  *
28  *
29  */
30 
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <limits.h>
39 #include <unistd.h>
40 
41 #include "trousers/tss.h"
42 #include "trousers_types.h"
43 #include "tcs_tsp.h"
44 #include "tcs_utils.h"
45 #include "tcs_int_literals.h"
46 #include "capabilities.h"
47 #include "tcsps.h"
48 #include "tcslog.h"
49 #include "tcsem.h"
50 
51 #ifdef EVLOG_SOURCE_IMA
52 
53 #define EVLOG_FILENAME_MAXSIZE 255
54 
55 struct ext_log_source ima_source = {
56 	ima_open,
57 	ima_get_entries_by_pcr,
58 	ima_get_entry,
59 	ima_close
60 };
61 
62 int
ima_open(void * source,FILE ** handle)63 ima_open(void *source, FILE **handle)
64 {
65  	FILE *fd;
66 
67 	if ((fd = fopen((char *)source, "r")) == NULL) {
68 		LogError("Error opening PCR log file %s: %s",
69 			(char *)source, strerror(errno));
70 		return -1;
71 	}
72 
73 	*handle =  fd;
74 	return 0;
75 }
76 
77 TSS_RESULT
ima_get_entries_by_pcr(FILE * handle,UINT32 pcr_index,UINT32 first,UINT32 * count,TSS_PCR_EVENT ** events)78 ima_get_entries_by_pcr(FILE *handle, UINT32 pcr_index, UINT32 first,
79 			UINT32 *count, TSS_PCR_EVENT **events)
80 {
81 	int pcr_value;
82 	char page[IMA_READ_SIZE];
83 	int error_path = 1, ptr = 0;
84 	UINT32 copied_events = 0, i;
85 	struct event_wrapper *list, *cur;
86 	TSS_RESULT result = TCSERR(TSS_E_INTERNAL_ERROR);
87 	FILE *fp = (FILE *) handle;
88 	uint len;
89 	char name[EVLOG_FILENAME_MAXSIZE];
90 
91 	if (!fp) {
92 		LogError("File handle is NULL!\n");
93 		return 1;
94 	}
95 
96 	if (*count == 0)
97 		return TSS_SUCCESS;
98 
99 	list = calloc(1, sizeof(struct event_wrapper));
100 	if (list == NULL) {
101 		LogError("malloc of %zd bytes failed.", sizeof(struct event_wrapper));
102 		return TCSERR(TSS_E_OUTOFMEMORY);
103 	}
104 	cur = list;
105 
106 	rewind(fp);
107 
108         while (fread(page, 24, 1, fp)) {
109 		/* copy the initial 4 bytes (PCR index) XXX endianess ignored */
110 		ptr = 0;
111 		memcpy(&pcr_value, &page[ptr], sizeof(int));
112 		cur->event.ulPcrIndex = pcr_value;
113 		ptr += sizeof(int);
114 
115 		/* grab this entry */
116 		cur->event.ulPcrValueLength = 20;
117 		cur->event.rgbPcrValue = malloc(cur->event.ulPcrValueLength);
118 		if (cur->event.rgbPcrValue == NULL) {
119 			LogError("malloc of %d bytes failed.", 20);
120 			result = TCSERR(TSS_E_OUTOFMEMORY);
121 			goto free_list;
122 		}
123 
124 		/* copy the template SHA1 XXX endianess ignored */
125 		memcpy(cur->event.rgbPcrValue, &page[ptr],
126 		       cur->event.ulPcrValueLength);
127 
128 /* Get the template name size, template name */
129 {
130 		char digest[20];
131 
132 		if (fread(&len, 1, sizeof(len), fp) != (sizeof(len))) {
133 			LogError("Failed to read event log file");
134 			result = TCSERR(TSS_E_INTERNAL_ERROR);
135 			goto free_list;
136 		}
137 		if (len > EVLOG_FILENAME_MAXSIZE) {
138 			LogError("Event log file name too big! Max size is %d", EVLOG_FILENAME_MAXSIZE);
139 			result = TCSERR(TSS_E_INTERNAL_ERROR);
140 			goto free_list;
141 		}
142 		memset(name, 0, EVLOG_FILENAME_MAXSIZE);
143 		if (fread(name, 1, len, fp) != len) {
144 			LogError("Failed to read event log file");
145 			result = TCSERR(TSS_E_INTERNAL_ERROR);
146 			goto free_list;
147 		}
148 		if (fread(digest, 1, sizeof digest, fp) != (sizeof(digest))) {
149 			LogError("Failed to read event log file");
150 			result = TCSERR(TSS_E_INTERNAL_ERROR);
151 			goto free_list;
152 		}
153 }
154 		/* Get the template data namelen and data */
155 		if (fread(&cur->event.ulEventLength, 1, sizeof(int), fp) != sizeof(int)) {
156 			LogError("Failed to read event log file");
157 			result = TCSERR(TSS_E_INTERNAL_ERROR);
158 			goto free_list;
159 		}
160 		cur->event.rgbEvent = malloc(cur->event.ulEventLength + 1);
161 		if (cur->event.rgbEvent == NULL) {
162 			free(cur->event.rgbPcrValue);
163 			LogError("malloc of %u bytes failed.",
164 				 cur->event.ulEventLength);
165 			result = TCSERR(TSS_E_OUTOFMEMORY);
166 			goto free_list;
167 		}
168 		memset(cur->event.rgbEvent, 0, cur->event.ulEventLength);
169 		if (fread(cur->event.rgbEvent, 1, cur->event.ulEventLength, fp) != cur->event.ulEventLength) {
170 			free(cur->event.rgbPcrValue);
171 			LogError("Failed to read event log file");
172 			result = TCSERR(TSS_E_INTERNAL_ERROR);
173 			goto free_list;
174 		}
175 
176 		copied_events++;
177 
178 		if (copied_events == *count)
179 			goto copy_events;
180 
181 		cur->next = calloc(1, sizeof(struct event_wrapper));
182 		if (cur->next == NULL) {
183 			LogError("malloc of %zd bytes failed.",
184 				 sizeof(struct event_wrapper));
185 			result = TCSERR(TSS_E_OUTOFMEMORY);
186 			goto free_list;
187 		}
188 		cur = cur->next;
189 	}
190 
191 copy_events:
192 	/* we've copied all the events we need to from this PCR, now
193 	 * copy them all into one contiguous memory block
194 	 */
195 	*events = calloc(copied_events, sizeof(TSS_PCR_EVENT));
196 	if (*events == NULL) {
197 		LogError("malloc of %zd bytes failed.", copied_events * sizeof(TSS_PCR_EVENT));
198 		result = TCSERR(TSS_E_OUTOFMEMORY);
199 		goto free_list;
200 	}
201 
202 	cur = list;
203 	for (i = 0; i < copied_events; i++) {
204 		memcpy(&((*events)[i]), &(cur->event), sizeof(TSS_PCR_EVENT));
205 		cur = cur->next;
206 	}
207 
208 	*count = copied_events;
209 	/* assume we're in an error path until we get here */
210 	error_path = 0;
211 	result = TSS_SUCCESS;
212 
213 free_list:
214 	cur = list->next;
215 	while (cur != NULL) {
216 		if (error_path) {
217 			free(cur->event.rgbEvent);
218 			free(cur->event.rgbPcrValue);
219 		}
220 		free(list);
221 		list = cur;
222 		cur = list->next;
223 	}
224 	free(list);
225 	return result;
226 }
227 
228 TSS_RESULT
ima_get_entry(FILE * handle,UINT32 pcr_index,UINT32 * num,TSS_PCR_EVENT ** ppEvent)229 ima_get_entry(FILE *handle, UINT32 pcr_index, UINT32 *num, TSS_PCR_EVENT **ppEvent)
230 {
231 	int pcr_value, ptr = 0;
232 	uint len;
233 	char page[IMA_READ_SIZE];
234 	UINT32 seen_indices = 0;
235 	TSS_RESULT result = TCSERR(TSS_E_INTERNAL_ERROR);
236 	TSS_PCR_EVENT *event = NULL;
237 	FILE *fp = (FILE *) handle;
238 	char name[EVLOG_FILENAME_MAXSIZE];
239 
240 	rewind(fp);
241 	while (fread(page, 24, 1, fp)) {
242 		/* copy the initial 4 bytes (PCR index) XXX endianess ignored */
243 		ptr = 0;
244 		memcpy(&pcr_value, &page[ptr], sizeof(int));
245 
246 		if (pcr_index == (UINT32)pcr_value) {
247 			ptr += sizeof(int);
248 			/* This is the case where we're looking for a specific event number in a
249 			 * specific PCR index. When we've reached the correct event, malloc
250 			 * space for it, copy it in, then break out of the while loop */
251 			if (ppEvent && seen_indices == *num) {
252 				/* grab this entry */
253 				event = calloc(1, sizeof(TSS_PCR_EVENT));
254 				event->ulPcrIndex = pcr_value;
255 				event->rgbPcrValue = NULL;
256 				event->rgbEvent = NULL;
257 				event->ulPcrValueLength = 20;
258 				event->rgbPcrValue = malloc(event->ulPcrValueLength);
259 				if (event->rgbPcrValue == NULL) {
260 					LogError("malloc of %d bytes failed.", 20);
261 					free(event);
262 					result = TCSERR(TSS_E_OUTOFMEMORY);
263 					goto done;
264 				}
265 
266 				/* copy the template SHA1 XXX endianess ignored */
267 				memcpy(event->rgbPcrValue, &page[ptr],
268 						event->ulPcrValueLength);
269 
270 				/* Get the template name size, template name */
271 				{
272 					char digest[20];
273 
274 					if (fread(&len, 1, sizeof(len), fp) != sizeof(len)) {
275 						LogError("Failed to read event log file");
276 						result = TCSERR(TSS_E_INTERNAL_ERROR);
277 						goto done;
278 					}
279 					if (len > EVLOG_FILENAME_MAXSIZE) {
280 						LogError("Event log file name too big! Max size is %d", EVLOG_FILENAME_MAXSIZE);
281 						result = TCSERR(TSS_E_INTERNAL_ERROR);
282 						goto done;
283 					}
284 					memset(name, 0, EVLOG_FILENAME_MAXSIZE);
285 					if (fread(name, 1, len, fp) != len) {
286 						LogError("Failed to read event log file");
287 						result = TCSERR(TSS_E_INTERNAL_ERROR);
288 						goto done;
289 					}
290 					if (fread(digest, 1, sizeof(digest), fp) != sizeof(digest)) {
291 						LogError("Failed to read event log file");
292 						result = TCSERR(TSS_E_INTERNAL_ERROR);
293 						goto done;
294 					}
295 				}
296 				/* Get the template data namelen and data */
297 				if (fread(&event->ulEventLength, 1, sizeof(int), fp) != sizeof(int)) {
298 					LogError("Failed to read event log file");
299 					result = TCSERR(TSS_E_INTERNAL_ERROR);
300 					goto done;
301 				}
302 				event->rgbEvent = malloc(event->ulEventLength + 1);
303 				if (event->rgbEvent == NULL) {
304 					LogError("malloc of %u bytes failed.",
305 							event->ulEventLength);
306 					result = TCSERR(TSS_E_OUTOFMEMORY);
307 					goto done;
308 				}
309 				memset(event->rgbEvent, 0, event->ulEventLength + 1);
310 				if (fread(event->rgbEvent, 1, event->ulEventLength, fp) != event->ulEventLength ) {
311 					LogError("Failed to read event log file");
312 					result = TCSERR(TSS_E_INTERNAL_ERROR);
313 					goto done;
314 				}
315 
316 				*ppEvent = event;
317 				result = TSS_SUCCESS;
318 				break;
319 			}
320 		}
321 		if (fread(&len, 1, sizeof(len), fp) != sizeof(len)) {
322 			LogError("Failed to read event log file");
323 			result = TCSERR(TSS_E_INTERNAL_ERROR);
324 			goto done;
325 		}
326 		fseek(fp, len + 20, SEEK_CUR);
327 		if (fread(&len, 1, sizeof(len), fp) != sizeof(len)) {
328 			LogError("Failed to read event log file");
329 			result = TCSERR(TSS_E_INTERNAL_ERROR);
330 			goto done;
331 		}
332 		fseek(fp, len, SEEK_CUR);
333 		seen_indices++;
334 	}
335 done:
336 	if (result != TSS_SUCCESS) {
337 		if (event != NULL) {
338 			free(event->rgbPcrValue);
339 			free(event->rgbEvent);
340 		}
341 		free(event);
342 		event = NULL;
343 	}
344 
345 	if (ppEvent == NULL)
346 		*num = seen_indices;
347 
348 	return result;
349 }
350 
351 int
ima_close(FILE * handle)352 ima_close(FILE *handle)
353 {
354 	fclose((FILE *)handle);
355 
356 	return 0;
357 }
358 #endif
359