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
53struct ext_log_source ima_source = {
54	ima_open,
55	ima_get_entries_by_pcr,
56	ima_get_entry,
57	ima_close
58};
59
60int
61ima_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
75TSS_RESULT
76ima_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++;
171printf("%d %s ", copied_events, name);
172
173printf("%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
187copy_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	 */
191printf("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
210free_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
225TSS_RESULT
226ima_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	}
338done:
339	if (ppEvent == NULL)
340		*num = seen_indices;
341
342	return result;
343}
344
345int
346ima_close(FILE *handle)
347{
348	fclose((FILE *)handle);
349
350	return 0;
351}
352#endif
353