~ubuntu-branches/ubuntu/precise/trousers/precise-proposed

« back to all changes in this revision

Viewing changes to src/tcs/imaem.c

  • Committer: Bazaar Package Importer
  • Author(s): William Lima
  • Date: 2007-04-18 16:39:38 UTC
  • Revision ID: james.westby@ubuntu.com-20070418163938-opscl2mvvi76jiec
Tags: upstream-0.2.9.1
ImportĀ upstreamĀ versionĀ 0.2.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 (bin)
 
21
 *     4 bytes event type (bin)
 
22
 * 1-255 bytes eventname
 
23
 *     1 byte  separator = '\0'
 
24
 *
 
25
 */
 
26
 
 
27
#include <stdlib.h>
 
28
#include <stdio.h>
 
29
#include <string.h>
 
30
#include <sys/types.h>
 
31
#include <sys/stat.h>
 
32
#include <fcntl.h>
 
33
#include <errno.h>
 
34
#include <limits.h>
 
35
#include <unistd.h>
 
36
#include <pthread.h>
 
37
 
 
38
#include "trousers/tss.h"
 
39
#include "spi_internal_types.h"
 
40
#include "tcs_internal_types.h"
 
41
#include "tcs_tsp.h"
 
42
#include "tcs_utils.h"
 
43
#include "tcs_int_literals.h"
 
44
#include "capabilities.h"
 
45
#include "tcsps.h"
 
46
#include "tcslog.h"
 
47
#include "tcsem.h"
 
48
 
 
49
#ifdef EVLOG_SOURCE_IMA
 
50
 
 
51
struct ext_log_source ima_source = {
 
52
        ima_open,
 
53
        ima_get_entries_by_pcr,
 
54
        ima_get_entry,
 
55
        ima_close
 
56
};
 
57
 
 
58
int
 
59
ima_open(void *source, int *handle)
 
60
{
 
61
        int fd;
 
62
 
 
63
        if ((fd = open((char *)source, O_RDONLY)) < 0) {
 
64
                LogError("Error opening PCR log file %s: %s", (char *)source, strerror(errno));
 
65
                return -1;
 
66
        }
 
67
 
 
68
        *handle = fd;
 
69
 
 
70
        return 0;
 
71
}
 
72
 
 
73
TSS_RESULT
 
74
ima_get_entries_by_pcr(int handle, UINT32 pcr_index, UINT32 first,
 
75
                        UINT32 *count, TSS_PCR_EVENT **events)
 
76
{
 
77
        int pcr_value;
 
78
        char page[IMA_READ_SIZE];
 
79
        int error_path = 1, bytes_read, bytes_left, ptr = 0, tmp_ptr;
 
80
        UINT32 seen_indices = 0, copied_events = 0, i;
 
81
        struct event_wrapper *list = calloc(1, sizeof(struct event_wrapper));
 
82
        struct event_wrapper *cur = list;
 
83
        TSS_RESULT result = TCSERR(TSS_E_INTERNAL_ERROR);
 
84
 
 
85
        if (list == NULL) {
 
86
                LogError("malloc of %zd bytes failed.", sizeof(struct event_wrapper));
 
87
                return TCSERR(TSS_E_OUTOFMEMORY);
 
88
        }
 
89
 
 
90
        if (*count == 0) {
 
91
                result = TSS_SUCCESS;
 
92
                goto free_list;
 
93
        }
 
94
 
 
95
        /* make the initial read from the file */
 
96
        if ((bytes_read = read(handle, page, IMA_READ_SIZE)) <= 0) {
 
97
                LogError("read from event source failed: %s", strerror(errno));
 
98
                free(list);
 
99
                return result;
 
100
        }
 
101
 
 
102
        while (1) {
 
103
                bytes_left = bytes_read - ptr;
 
104
                if (bytes_left < IMA_MIN_EVENT_SIZE) {
 
105
                        /* We need to do another read from the file to get the next complete
 
106
                         * log entry
 
107
                         */
 
108
                        memcpy(page, &page[ptr], bytes_left);
 
109
 
 
110
                        if ((bytes_read = read(handle, &page[bytes_left],
 
111
                                                        IMA_READ_SIZE - bytes_left)) < 0) {
 
112
                                if (bytes_left == 0)
 
113
                                        goto copy_events;
 
114
 
 
115
                                LogError("read from event source failed: %s", strerror(errno));
 
116
                                goto free_list;
 
117
                        }
 
118
 
 
119
                        /* if we *still* haven't read out one more entry from the file,
 
120
                         * just exit. Hopefully we've processed the entire file.
 
121
                         */
 
122
                        if (bytes_read + bytes_left < IMA_MIN_EVENT_SIZE)
 
123
                                break;
 
124
 
 
125
                        /* page has new data in it now, so reset ptr to read the fresh data */
 
126
                        ptr = 0;
 
127
                } else if (bytes_left < IMA_MAX_EVENT_SIZE) {
 
128
                        /* if the last byte of the read data is not a zero, we're not looking
 
129
                         * at a complete log entry. Read more data to get the next complete
 
130
                         * entry.
 
131
                         */
 
132
                        if (page[bytes_read - 1] != '\0') {
 
133
                                memcpy(page, &page[ptr], bytes_left);
 
134
 
 
135
                                if ((bytes_read = read(handle, &page[bytes_left],
 
136
                                                        IMA_READ_SIZE - bytes_left)) < 0) {
 
137
                                        LogError("read from event source failed: %s", strerror(errno));
 
138
                                        goto free_list;
 
139
                                }
 
140
 
 
141
                                /* page has new data in it now, so reset ptr to read the
 
142
                                 * fresh data.
 
143
                                 */
 
144
                                ptr = 0;
 
145
                        }
 
146
                }
 
147
 
 
148
                /* copy the initial 4 bytes (PCR index) XXX endianess ignored */
 
149
                memcpy(&pcr_value, &page[ptr], sizeof(int));
 
150
                ptr += sizeof(int);
 
151
 
 
152
                /* if the index is the one we're looking for, grab the entry */
 
153
                if (pcr_index == (UINT32)pcr_value) {
 
154
                        if (seen_indices >= first) {
 
155
                                /* grab this entry */
 
156
                                cur->event.rgbPcrValue = malloc(20);
 
157
                                if (cur->event.rgbPcrValue == NULL) {
 
158
                                        LogError("malloc of %d bytes failed.", 20);
 
159
                                        result = TCSERR(TSS_E_OUTOFMEMORY);
 
160
                                        goto free_list;
 
161
                                }
 
162
 
 
163
                                cur->event.ulPcrIndex = pcr_index;
 
164
                                cur->event.ulPcrValueLength = 20;
 
165
 
 
166
                                /* copy the SHA1 XXX endianess ignored */
 
167
                                memcpy(cur->event.rgbPcrValue, &page[ptr], 20);
 
168
                                ptr += 20;
 
169
 
 
170
                                /* copy the 4 bytes of event type XXX endianess ignored */
 
171
                                memcpy(&cur->event.eventType, &page[ptr], sizeof(int));
 
172
                                ptr += sizeof(int);
 
173
 
 
174
                                /* copy the event name XXX endianess ignored */
 
175
                                tmp_ptr = ptr;
 
176
                                while (page[ptr] != '\0')
 
177
                                        ptr++;
 
178
                                cur->event.ulEventLength = ptr - tmp_ptr + 1; //add the terminator
 
179
 
 
180
                                cur->event.rgbEvent = malloc(cur->event.ulEventLength);
 
181
                                if (cur->event.rgbEvent == NULL) {
 
182
                                        free(cur->event.rgbPcrValue);
 
183
                                        LogError("malloc of %u bytes failed.",
 
184
                                                 cur->event.ulEventLength);
 
185
                                        result = TCSERR(TSS_E_OUTOFMEMORY);
 
186
                                        goto free_list;
 
187
                                }
 
188
 
 
189
                                memcpy(cur->event.rgbEvent, &page[tmp_ptr],
 
190
                                       cur->event.ulEventLength);
 
191
                                /* add 1 to skip over the '\0' */
 
192
                                ptr++;
 
193
 
 
194
                                copied_events++;
 
195
                                if (copied_events == *count)
 
196
                                        goto copy_events;
 
197
 
 
198
                                cur->next = calloc(1, sizeof(struct event_wrapper));
 
199
                                if (cur->next == NULL) {
 
200
                                        LogError("malloc of %zd bytes failed.",
 
201
                                                 sizeof(struct event_wrapper));
 
202
                                        result = TCSERR(TSS_E_OUTOFMEMORY);
 
203
                                        goto free_list;
 
204
                                }
 
205
                                cur = cur->next;
 
206
                        }
 
207
                        seen_indices++;
 
208
                        continue;
 
209
                }
 
210
 
 
211
                /* move the data pointer through the 20 bytes of SHA1 +
 
212
                 * event type + event name + '\0' */
 
213
                ptr += 20 + sizeof(UINT32);
 
214
                while (page[ptr] != '\0')
 
215
                        ptr++;
 
216
                ptr++;
 
217
        }
 
218
 
 
219
copy_events:
 
220
        /* we've copied all the events we need to from this PCR, now
 
221
         * copy them all into one contiguous memory block
 
222
         */
 
223
        *events = calloc(copied_events, sizeof(TSS_PCR_EVENT));
 
224
        if (*events == NULL) {
 
225
                LogError("malloc of %zd bytes failed.", copied_events * sizeof(TSS_PCR_EVENT));
 
226
                result = TCSERR(TSS_E_OUTOFMEMORY);
 
227
                goto free_list;
 
228
        }
 
229
 
 
230
        cur = list;
 
231
        for (i = 0; i < copied_events; i++) {
 
232
                memcpy(&((*events)[i]), &(cur->event), sizeof(TSS_PCR_EVENT));
 
233
                cur = cur->next;
 
234
        }
 
235
 
 
236
        *count = copied_events;
 
237
        /* assume we're in an error path until we get here */
 
238
        error_path = 0;
 
239
        result = TSS_SUCCESS;
 
240
 
 
241
free_list:
 
242
        cur = list->next;
 
243
        while (cur != NULL) {
 
244
                if (error_path) {
 
245
                        free(cur->event.rgbEvent);
 
246
                        free(cur->event.rgbPcrValue);
 
247
                }
 
248
                free(list);
 
249
                list = cur;
 
250
                cur = list->next;
 
251
        }
 
252
        free(list);
 
253
        return result;
 
254
}
 
255
 
 
256
TSS_RESULT
 
257
ima_get_entry(int handle, UINT32 pcr_index, UINT32 *num, TSS_PCR_EVENT **ppEvent)
 
258
{
 
259
        int pcr_value, bytes_read, bytes_left, tmp_ptr, ptr = 0;
 
260
        char page[IMA_READ_SIZE];
 
261
        UINT32 seen_indices = 0;
 
262
        TSS_RESULT result = TCSERR(TSS_E_INTERNAL_ERROR);
 
263
        TSS_PCR_EVENT *e = NULL;
 
264
 
 
265
        /* make the initial read from the file */
 
266
        if ((bytes_read = read(handle, page, IMA_READ_SIZE)) <= 0) {
 
267
                LogError("read from event source failed: %s", strerror(errno));
 
268
                return result;
 
269
        }
 
270
 
 
271
        while (1) {
 
272
                bytes_left = bytes_read - ptr;
 
273
                if (bytes_left < IMA_MIN_EVENT_SIZE) {
 
274
                        memcpy(page, &page[ptr], bytes_left);
 
275
 
 
276
                        if ((bytes_read = read(handle, &page[bytes_left],
 
277
                                                        IMA_READ_SIZE - bytes_left)) < 0) {
 
278
                                LogError("read from event source failed: %s", strerror(errno));
 
279
                                goto done;
 
280
                        }
 
281
 
 
282
                        /* if we *still* haven't read out one more entry from the file,
 
283
                         * just exit. Hopefully we've processed the entire file.
 
284
                         */
 
285
                        if (bytes_read + bytes_left < IMA_MIN_EVENT_SIZE)
 
286
                                break;
 
287
 
 
288
                        /* page has new data in it now, so reset ptr to read the fresh data */
 
289
                        ptr = 0;
 
290
                } else if (bytes_left < IMA_MAX_EVENT_SIZE) {
 
291
                        /* if the last byte of the read data is not a zero, we're not looking
 
292
                         * at a complete log entry. Read more data to get the next complete
 
293
                         * entry.
 
294
                         */
 
295
                        if (page[bytes_read - 1] != '\0') {
 
296
                                memcpy(page, &page[ptr], bytes_left);
 
297
 
 
298
                                if ((bytes_read = read(handle, &page[bytes_left],
 
299
                                                        IMA_READ_SIZE - bytes_left)) < 0) {
 
300
                                        LogError("read from event source failed: %s", strerror(errno));
 
301
                                        goto done;
 
302
                                }
 
303
 
 
304
                                /* page has new data in it now, so reset ptr to read the
 
305
                                 * fresh data.
 
306
                                 */
 
307
                                ptr = 0;
 
308
                        }
 
309
                }
 
310
 
 
311
                /* copy the initial 4 bytes (PCR index) XXX endianess ignored */
 
312
                memcpy(&pcr_value, &page[ptr], sizeof(int));
 
313
                ptr += sizeof(int);
 
314
 
 
315
                if (pcr_index == (UINT32)pcr_value) {
 
316
                        /* This is the case where we're looking for a specific event number in a
 
317
                         * specific PCR index. When we've reached the correct event, malloc
 
318
                         * space for it, copy it in, then break out of the while loop */
 
319
                        if (ppEvent && seen_indices == *num) {
 
320
                                *ppEvent = calloc(1, sizeof(TSS_PCR_EVENT));
 
321
                                if (*ppEvent == NULL) {
 
322
                                        LogError("malloc of %zd bytes failed.",
 
323
                                                 sizeof(TSS_PCR_EVENT));
 
324
                                        return TCSERR(TSS_E_OUTOFMEMORY);
 
325
                                }
 
326
 
 
327
                                e = *ppEvent;
 
328
 
 
329
                                e->rgbPcrValue = malloc(20);
 
330
                                if (e->rgbPcrValue == NULL) {
 
331
                                        LogError("malloc of %d bytes failed.", 20);
 
332
                                        free(e);
 
333
                                        e = NULL;
 
334
                                        goto done;
 
335
                                }
 
336
 
 
337
                                e->ulPcrIndex = pcr_index;
 
338
                                e->ulPcrValueLength = 20;
 
339
 
 
340
                                /* copy the SHA1 XXX endianess ignored */
 
341
                                memcpy(e->rgbPcrValue, &page[ptr], 20);
 
342
                                ptr += 20;
 
343
 
 
344
                                /* copy the 4 bytes of event type XXX endianess ignored */
 
345
                                memcpy(&e->eventType, &page[ptr], sizeof(int));
 
346
                                ptr += sizeof(int);
 
347
 
 
348
                                /* copy the event name XXX endianess ignored */
 
349
                                tmp_ptr = ptr;
 
350
                                while (page[ptr] != '\0')
 
351
                                        ptr++;
 
352
                                e->ulEventLength = ptr - tmp_ptr + 1; // add the terminator
 
353
 
 
354
                                if (e->ulEventLength > 41) {
 
355
                                        LogError("Error parsing IMA PCR Log event structure, event "
 
356
                                                 "length is %u", e->ulEventLength);
 
357
                                        free(e->rgbPcrValue);
 
358
                                        free(e);
 
359
                                        e = NULL;
 
360
                                        goto done;
 
361
                                }
 
362
 
 
363
                                e->rgbEvent = malloc(e->ulEventLength);
 
364
                                if (e->rgbEvent == NULL) {
 
365
                                        LogError("malloc of %d bytes failed.", e->ulEventLength);
 
366
                                        free(e->rgbPcrValue);
 
367
                                        free(e);
 
368
                                        e = NULL;
 
369
                                        goto done;
 
370
                                }
 
371
 
 
372
                                memcpy(e->rgbEvent, &page[tmp_ptr], e->ulEventLength);
 
373
 
 
374
                                break;
 
375
                        }
 
376
                        seen_indices++;
 
377
                }
 
378
 
 
379
                /* move the data pointer through the 20 bytes of SHA1 +
 
380
                 * event type + event name + '\0' */
 
381
                ptr += 20 + sizeof(UINT32);
 
382
                while (page[ptr] != '\0')
 
383
                        ptr++;
 
384
                ptr++;
 
385
        }
 
386
 
 
387
        result = TSS_SUCCESS;
 
388
done:
 
389
        if (ppEvent == NULL)
 
390
                *num = seen_indices;
 
391
        else if (e == NULL)
 
392
                *ppEvent = NULL;
 
393
 
 
394
        return result;
 
395
}
 
396
 
 
397
int
 
398
ima_close(int handle)
 
399
{
 
400
        close(handle);
 
401
 
 
402
        return 0;
 
403
}
 
404
 
 
405
#endif