Home | History | Annotate | Line # | Download | only in tcs
      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
     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
     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
    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
    291 bios_close(FILE *handle)
    292 {
    293 	fclose(handle);
    294 
    295 	return 0;
    296 }
    297 
    298 #endif
    299