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