3
* Licensed Materials - Property of IBM
5
* trousers - An open source TCG Software Stack
7
* (C) Copyright International Business Machines Corp. 2004-2006
14
* Routines for handling PCR events from the Integrity Measurement
17
* The external event source format used by IMA:
19
* 4 bytes PCR Index (bin)
21
* 4 bytes event type (bin)
22
* 1-255 bytes eventname
23
* 1 byte separator = '\0'
30
#include <sys/types.h>
38
#include "trousers/tss.h"
39
#include "spi_internal_types.h"
40
#include "tcs_internal_types.h"
42
#include "tcs_utils.h"
43
#include "tcs_int_literals.h"
44
#include "capabilities.h"
49
#ifdef EVLOG_SOURCE_IMA
51
struct ext_log_source ima_source = {
53
ima_get_entries_by_pcr,
59
ima_open(void *source, int *handle)
63
if ((fd = open((char *)source, O_RDONLY)) < 0) {
64
LogError("Error opening PCR log file %s: %s", (char *)source, strerror(errno));
74
ima_get_entries_by_pcr(int handle, UINT32 pcr_index, UINT32 first,
75
UINT32 *count, TSS_PCR_EVENT **events)
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);
86
LogError("malloc of %zd bytes failed.", sizeof(struct event_wrapper));
87
return TCSERR(TSS_E_OUTOFMEMORY);
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));
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
108
memcpy(page, &page[ptr], bytes_left);
110
if ((bytes_read = read(handle, &page[bytes_left],
111
IMA_READ_SIZE - bytes_left)) < 0) {
115
LogError("read from event source failed: %s", strerror(errno));
119
/* if we *still* haven't read out one more entry from the file,
120
* just exit. Hopefully we've processed the entire file.
122
if (bytes_read + bytes_left < IMA_MIN_EVENT_SIZE)
125
/* page has new data in it now, so reset ptr to read the fresh data */
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
132
if (page[bytes_read - 1] != '\0') {
133
memcpy(page, &page[ptr], bytes_left);
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));
141
/* page has new data in it now, so reset ptr to read the
148
/* copy the initial 4 bytes (PCR index) XXX endianess ignored */
149
memcpy(&pcr_value, &page[ptr], sizeof(int));
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);
163
cur->event.ulPcrIndex = pcr_index;
164
cur->event.ulPcrValueLength = 20;
166
/* copy the SHA1 XXX endianess ignored */
167
memcpy(cur->event.rgbPcrValue, &page[ptr], 20);
170
/* copy the 4 bytes of event type XXX endianess ignored */
171
memcpy(&cur->event.eventType, &page[ptr], sizeof(int));
174
/* copy the event name XXX endianess ignored */
176
while (page[ptr] != '\0')
178
cur->event.ulEventLength = ptr - tmp_ptr + 1; //add the terminator
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);
189
memcpy(cur->event.rgbEvent, &page[tmp_ptr],
190
cur->event.ulEventLength);
191
/* add 1 to skip over the '\0' */
195
if (copied_events == *count)
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);
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')
220
/* we've copied all the events we need to from this PCR, now
221
* copy them all into one contiguous memory block
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);
231
for (i = 0; i < copied_events; i++) {
232
memcpy(&((*events)[i]), &(cur->event), sizeof(TSS_PCR_EVENT));
236
*count = copied_events;
237
/* assume we're in an error path until we get here */
239
result = TSS_SUCCESS;
243
while (cur != NULL) {
245
free(cur->event.rgbEvent);
246
free(cur->event.rgbPcrValue);
257
ima_get_entry(int handle, UINT32 pcr_index, UINT32 *num, TSS_PCR_EVENT **ppEvent)
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;
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));
272
bytes_left = bytes_read - ptr;
273
if (bytes_left < IMA_MIN_EVENT_SIZE) {
274
memcpy(page, &page[ptr], bytes_left);
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));
282
/* if we *still* haven't read out one more entry from the file,
283
* just exit. Hopefully we've processed the entire file.
285
if (bytes_read + bytes_left < IMA_MIN_EVENT_SIZE)
288
/* page has new data in it now, so reset ptr to read the fresh data */
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
295
if (page[bytes_read - 1] != '\0') {
296
memcpy(page, &page[ptr], bytes_left);
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));
304
/* page has new data in it now, so reset ptr to read the
311
/* copy the initial 4 bytes (PCR index) XXX endianess ignored */
312
memcpy(&pcr_value, &page[ptr], sizeof(int));
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);
329
e->rgbPcrValue = malloc(20);
330
if (e->rgbPcrValue == NULL) {
331
LogError("malloc of %d bytes failed.", 20);
337
e->ulPcrIndex = pcr_index;
338
e->ulPcrValueLength = 20;
340
/* copy the SHA1 XXX endianess ignored */
341
memcpy(e->rgbPcrValue, &page[ptr], 20);
344
/* copy the 4 bytes of event type XXX endianess ignored */
345
memcpy(&e->eventType, &page[ptr], sizeof(int));
348
/* copy the event name XXX endianess ignored */
350
while (page[ptr] != '\0')
352
e->ulEventLength = ptr - tmp_ptr + 1; // add the terminator
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);
363
e->rgbEvent = malloc(e->ulEventLength);
364
if (e->rgbEvent == NULL) {
365
LogError("malloc of %d bytes failed.", e->ulEventLength);
366
free(e->rgbPcrValue);
372
memcpy(e->rgbEvent, &page[tmp_ptr], e->ulEventLength);
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')
387
result = TSS_SUCCESS;
398
ima_close(int handle)