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