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. 2006
8  *
9  */
10 
11 /*
12  * biosem.c
13  *
14  * Routines for handling PCR events from the TCG Compliant BIOS
15  *
16  */
17 
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <limits.h>
26 #include <unistd.h>
27 
28 #include "trousers/tss.h"
29 #include "trousers_types.h"
30 #include "tcs_tsp.h"
31 #include "tcs_utils.h"
32 #include "tcs_int_literals.h"
33 #include "capabilities.h"
34 #include "tcsps.h"
35 #include "tcslog.h"
36 #include "tcsem.h"
37 
38 #ifdef EVLOG_SOURCE_BIOS
39 
40 struct ext_log_source bios_source = {
41 	bios_open,
42 	bios_get_entries_by_pcr,
43 	bios_get_entry,
44 	bios_close
45 };
46 
47 int
bios_open(void * source,FILE ** handle)48 bios_open(void *source, FILE **handle)
49 {
50 	FILE *fd;
51 
52 	if ((fd = fopen((char *)source, "r")) == NULL ) {
53 		LogError("Error opening BIOS Eventlog file %s: %s", (char *)source,
54 			 strerror(errno));
55 		return -1;
56 	}
57 
58 	*handle = fd;
59 
60 	return 0;
61 }
62 
63 TSS_RESULT
bios_get_entries_by_pcr(FILE * handle,UINT32 pcr_index,UINT32 first,UINT32 * count,TSS_PCR_EVENT ** events)64 bios_get_entries_by_pcr(FILE *handle, UINT32 pcr_index, UINT32 first,
65 			UINT32 *count, TSS_PCR_EVENT **events)
66 {
67 	char page[BIOS_READ_SIZE];
68 	int error_path = 1;
69 	UINT32 seen_indices = 0, copied_events = 0, i;
70 	struct event_wrapper *list = calloc(1, sizeof(struct event_wrapper));
71 	struct event_wrapper *cur = list;
72 	TSS_RESULT result = TSS_E_INTERNAL_ERROR;
73 	TCG_PCClientPCREventStruc *event = NULL;
74 	int num=0;
75 
76 	if (list == NULL) {
77 		LogError("malloc of %zd bytes failed.", sizeof(struct event_wrapper));
78 		return TSS_E_OUTOFMEMORY;
79 	}
80 
81 	if (*count == 0) {
82 		result = TSS_SUCCESS;
83 		goto free_list;
84 	}
85 
86 	while (1) {
87 		/* read event header from the file */
88 		if ((fread(page, 32, 1, handle)) <= 0) {
89 			goto copy_events;
90 		}
91 
92 		event = (TCG_PCClientPCREventStruc *)page;
93 
94 		/* if the index is the one we're looking for, grab the entry */
95 		if (pcr_index == event->pcrIndex) {
96 			if (seen_indices >= first) {
97 				/* grab this entry */
98 				cur->event.rgbPcrValue = malloc(20);
99 				if (cur->event.rgbPcrValue == NULL) {
100 					LogError("malloc of %d bytes failed.", 20);
101 					result = TSS_E_OUTOFMEMORY;
102 					goto free_list;
103 				}
104 
105 				cur->event.ulPcrIndex = pcr_index;
106 				cur->event.eventType = event->eventType;
107 				cur->event.ulPcrValueLength = 20;
108 
109 				/* copy the SHA1 XXX endianess ignored */
110 				memcpy(cur->event.rgbPcrValue, event->digest, 20);
111 
112 				/* copy the event name XXX endianess ignored */
113 				cur->event.ulEventLength = event->eventDataSize;
114 
115 				if (event->eventDataSize>0) {
116 					cur->event.rgbEvent = malloc(event->eventDataSize);
117 					if (cur->event.rgbEvent == NULL) {
118 						LogError("malloc of %d bytes failed.",
119 							 event->eventDataSize);
120 						free(cur->event.rgbPcrValue);
121 						result = TSS_E_OUTOFMEMORY;
122 						goto free_list;
123 					}
124 					if ((fread(cur->event.rgbEvent,
125 						   event->eventDataSize, 1, handle)) <= 0) {
126 						LogError("read from event source failed: %s",
127 							 strerror(errno));
128 						goto free_list;
129 					}
130 				} else {
131 					cur->event.rgbEvent = NULL;
132 				}
133 
134 				copied_events++;
135 				if (copied_events == *count)
136 					goto copy_events;
137 
138 				cur->next = calloc(1, sizeof(struct event_wrapper));
139 				if (cur->next == NULL) {
140 					LogError("malloc of %zd bytes failed.",
141 						 sizeof(struct event_wrapper));
142 					result = TSS_E_OUTOFMEMORY;
143 					goto free_list;
144 				}
145 				cur = cur->next;
146 			} else {
147 				/* skip */
148 				if (event->eventDataSize > 0)
149 					fseek(handle,event->eventDataSize,SEEK_CUR);
150 			}
151 			seen_indices++;
152 		} else {
153 			if (event->eventDataSize > 0)
154 				fseek(handle,event->eventDataSize,SEEK_CUR);
155 			}
156 		num++;
157 	}
158 
159 copy_events:
160 
161 	/* we've copied all the events we need to from this PCR, now
162 	 * copy them all into one contiguous memory block
163 	 */
164 	*events = calloc(copied_events, sizeof(TSS_PCR_EVENT));
165 	if (*events == NULL) {
166 		LogError("malloc of %zd bytes failed.", copied_events * sizeof(TSS_PCR_EVENT));
167 		result = TSS_E_OUTOFMEMORY;
168 		goto free_list;
169 	}
170 
171 	cur = list;
172 	for (i = 0; i < copied_events; i++) {
173 		memcpy(&((*events)[i]), &(cur->event), sizeof(TSS_PCR_EVENT));
174 		cur = cur->next;
175 	}
176 
177 	*count = copied_events;
178 	/* assume we're in an error path until we get here */
179 	error_path = 0;
180 	result = TSS_SUCCESS;
181 
182 free_list:
183 	cur = list->next;
184 	while (cur != NULL) {
185 		if (error_path) {
186 			free(cur->event.rgbEvent);
187 			free(cur->event.rgbPcrValue);
188 		}
189 		free(list);
190 		list = cur;
191 		cur = list->next;
192 	}
193 	free(list);
194 	return result;
195 }
196 
197 TSS_RESULT
bios_get_entry(FILE * handle,UINT32 pcr_index,UINT32 * num,TSS_PCR_EVENT ** ppEvent)198 bios_get_entry(FILE *handle, UINT32 pcr_index, UINT32 *num, TSS_PCR_EVENT **ppEvent)
199 {
200 	char page[BIOS_READ_SIZE];
201 	UINT32 seen_indices = 0;
202 	TSS_RESULT result = TSS_E_INTERNAL_ERROR;
203 	TSS_PCR_EVENT *e = NULL;
204 	TCG_PCClientPCREventStruc *event = NULL;
205 
206 	while (1) {
207 		/* read event header from the file */
208 		if ((fread(page, 32, 1, handle)) == 0) {
209 			goto done;
210 		}
211 
212 		event = (TCG_PCClientPCREventStruc *)page;
213 
214 		if (pcr_index == event->pcrIndex) {
215 			if (ppEvent && !*ppEvent && seen_indices == *num) {
216 				*ppEvent = calloc(1, sizeof(TSS_PCR_EVENT));
217 				if (*ppEvent == NULL) {
218 					LogError("malloc of %zd bytes failed.",
219 						 sizeof(TSS_PCR_EVENT));
220 					return TSS_E_INTERNAL_ERROR;
221 				}
222 
223 				e = *ppEvent;
224 
225 				e->rgbPcrValue = malloc(20);
226 				if (e->rgbPcrValue == NULL) {
227 					LogError("malloc of %d bytes failed.", 20);
228 					free(e);
229 					e = NULL;
230 					break;
231 				}
232 
233 				e->ulPcrIndex = pcr_index;
234 				e->eventType = event->eventType;
235 				e->ulPcrValueLength = 20;
236 
237 				/* copy the SHA1 XXX endianess ignored */
238 				memcpy(e->rgbPcrValue, event->digest, 20);
239 
240 				e->ulEventLength = event->eventDataSize;
241 
242 				if (event->eventDataSize>0) {
243 					e->rgbEvent = malloc(e->ulEventLength);
244 					if (e->rgbEvent == NULL) {
245 						LogError("malloc of %d bytes failed.",
246 							 e->ulEventLength);
247 						free(e->rgbPcrValue);
248 						free(e);
249 						e = NULL;
250 						break;
251 					}
252 					if ((fread(e->rgbEvent,
253 						   event->eventDataSize,
254 						   1, handle)) <= 0) {
255 						LogError("read from event source failed: %s",
256 							 strerror(errno));
257 						return result;
258 					}
259 				} else {
260 					e->rgbEvent = NULL;
261 				}
262 				result = TSS_SUCCESS;
263 
264 				break;
265 			} else {
266 				/* skip */
267 				if (event->eventDataSize > 0) {
268 					fseek(handle,event->eventDataSize,SEEK_CUR);
269 				}
270 			}
271 			seen_indices++;
272 		} else {
273 			/* skip */
274 			if (event->eventDataSize > 0) {
275 				fseek(handle,event->eventDataSize,SEEK_CUR);
276 			}
277 		}
278 	}
279 
280 done:
281 	if (!ppEvent) {
282 		*num = seen_indices;
283 		result = TSS_SUCCESS;
284 	} else if (e == NULL)
285 		*ppEvent = NULL;
286 
287 	return result;
288 }
289 
290 int
bios_close(FILE * handle)291 bios_close(FILE *handle)
292 {
293 	fclose(handle);
294 
295 	return 0;
296 }
297 
298 #endif
299