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