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. 2004
      8  *
      9  */
     10 
     11 
     12 #include <time.h>
     13 #include <stdio.h>
     14 #include <string.h>
     15 #include <stdlib.h>
     16 
     17 #include "trousers/tss.h"
     18 #include "trousers_types.h"
     19 #include "tcs_context.h"
     20 #include "tcs_tsp.h"
     21 #include "tcs_utils.h"
     22 #include "tcs_int_literals.h"
     23 #include "capabilities.h"
     24 #include "tcslog.h"
     25 #include "tcsd_wrap.h"
     26 #include "tcsd.h"
     27 
     28 
     29 unsigned long nextContextHandle = 0xA0000000;
     30 struct tcs_context *tcs_context_table = NULL;
     31 
     32 MUTEX_DECLARE_INIT(tcs_ctx_lock);
     33 
     34 TCS_CONTEXT_HANDLE getNextHandle();
     35 struct tcs_context *create_tcs_context();
     36 struct tcs_context *get_context(TCS_CONTEXT_HANDLE);
     37 struct tcs_context *get_previous_context(TCS_CONTEXT_HANDLE);
     38 
     39 TSS_BOOL initContextHandle = 1;
     40 
     41 TCS_CONTEXT_HANDLE
     42 getNextHandle()
     43 {
     44 	UINT32 tempRand;
     45 	time_t currentTime;
     46 
     47 	if (initContextHandle) {
     48 		currentTime = time(NULL);
     49 		srand(currentTime);
     50 		tempRand = rand();
     51 		tempRand = tempRand << 16;
     52 		tempRand &= 0x00FF0000;
     53 		nextContextHandle |= tempRand;
     54 		initContextHandle = 0;
     55 	}
     56 	currentTime = time(NULL);
     57 	srand(currentTime + 1);
     58 	tempRand = rand();
     59 	tempRand = tempRand << 8;
     60 	tempRand &= 0x0000FF00;
     61 	if (nextContextHandle == 0)
     62 		return getNextHandle();
     63 	else
     64 		return ((nextContextHandle++) | tempRand);
     65 }
     66 
     67 struct tcs_context *
     68 create_tcs_context()
     69 {
     70 	struct tcs_context *ret = (struct tcs_context *)calloc(1, sizeof(struct tcs_context));
     71 
     72 	if (ret != NULL) {
     73 		ret->handle = getNextHandle();
     74 		COND_INIT(ret->cond);
     75 	}
     76 	return ret;
     77 }
     78 
     79 struct tcs_context *
     80 get_context(TCS_CONTEXT_HANDLE handle)
     81 {
     82 	struct tcs_context *index;
     83 	index = tcs_context_table;
     84 	while (index) {
     85 		if (index->handle == handle)
     86 			break;
     87 		index = index->next;
     88 	}
     89 
     90 	return index;
     91 }
     92 
     93 struct tcs_context *
     94 get_previous_context(TCS_CONTEXT_HANDLE handle)
     95 {
     96 	struct tcs_context *index;
     97 	index = tcs_context_table;
     98 	while (index) {
     99 		if (index->next) {
    100 			if (index->next->handle == handle)
    101 				return index;
    102 		}
    103 		index = index->next;
    104 	}
    105 
    106 	return 0;
    107 }
    108 
    109 void
    110 destroy_context(TCS_CONTEXT_HANDLE handle)
    111 {
    112 	struct tcs_context *toKill;
    113 	struct tcs_context *previous;
    114 
    115 	MUTEX_LOCK(tcs_ctx_lock);
    116 
    117 	toKill = get_context(handle);
    118 	previous = get_previous_context(handle);
    119 
    120 	if (!previous && tcs_context_table->handle == handle) {
    121 		/* this means that toKill is the first one */
    122 		tcs_context_table = tcs_context_table->next;
    123 	} else if (previous && toKill) {
    124 		/* both are found */
    125 		previous->next = toKill->next;
    126 	} else {
    127 		MUTEX_UNLOCK(tcs_ctx_lock);
    128 		return;
    129 	}
    130 
    131 	MUTEX_UNLOCK(tcs_ctx_lock);
    132 
    133 	CTX_ref_count_keys(toKill);
    134 
    135 #ifdef TSS_BUILD_TRANSPORT
    136 	/* Free existing transport session if necessary */
    137 	if (toKill != NULL && toKill->transHandle)
    138 		TCSP_FlushSpecific_Common(toKill->transHandle, TPM_RT_TRANS);
    139 #endif
    140 
    141 	free(toKill);
    142 }
    143 
    144 TCS_CONTEXT_HANDLE
    145 make_context()
    146 {
    147 	struct tcs_context *index;
    148 
    149 	MUTEX_LOCK(tcs_ctx_lock);
    150 
    151 	index = tcs_context_table;
    152 
    153 	if (!index) {
    154 		tcs_context_table = create_tcs_context();
    155 		if (tcs_context_table == NULL) {
    156 			LogError("Malloc Failure.");
    157 			MUTEX_UNLOCK(tcs_ctx_lock);
    158 			return 0;
    159 		}
    160 		index = tcs_context_table;
    161 	} else {
    162 		while (index->next) {
    163 			index = index->next;
    164 		}
    165 		index->next = create_tcs_context();
    166 		if (index->next == NULL) {
    167 			LogError("Malloc Failure.");
    168 			MUTEX_UNLOCK(tcs_ctx_lock);
    169 			return 0;
    170 		}
    171 		index = index->next;
    172 	}
    173 
    174 	MUTEX_UNLOCK(tcs_ctx_lock);
    175 
    176 	return index->handle;
    177 }
    178 
    179 
    180 TSS_RESULT
    181 ctx_verify_context(TCS_CONTEXT_HANDLE tcsContext)
    182 {
    183 	struct tcs_context *c;
    184 
    185 	MUTEX_LOCK(tcs_ctx_lock);
    186 
    187 	c = get_context(tcsContext);
    188 
    189 	MUTEX_UNLOCK(tcs_ctx_lock);
    190 
    191 	if (c == NULL) {
    192 		LogDebug("Fail: Context %x not found", tcsContext);
    193 		return TCSERR(TCS_E_INVALID_CONTEXTHANDLE);
    194 	}
    195 
    196 	return TSS_SUCCESS;
    197 }
    198 
    199 
    200 COND_VAR *
    201 ctx_get_cond_var(TCS_CONTEXT_HANDLE tcs_handle)
    202 {
    203 	struct tcs_context *c;
    204 	COND_VAR *ret = NULL;
    205 
    206 	MUTEX_LOCK(tcs_ctx_lock);
    207 
    208 	c = get_context(tcs_handle);
    209 
    210 	if (c != NULL)
    211 		ret = &c->cond;
    212 
    213 	MUTEX_UNLOCK(tcs_ctx_lock);
    214 
    215 	return ret;
    216 }
    217 
    218 /* the only transport flag at the TCS level is whether the session is exclusive or not. If the app
    219  * is requesting an exclusive transport session, check that no other exclusive sessions exist and
    220  * if not, flag this context as being the one. If so, return internal error. */
    221 TSS_RESULT
    222 ctx_req_exclusive_transport(TCS_CONTEXT_HANDLE tcsContext)
    223 {
    224 	TSS_RESULT result = TSS_SUCCESS;
    225 	struct tcs_context *tmp, *self = NULL;
    226 
    227 	/* If the daemon is configured to ignore apps that want an exclusive transport, just
    228 	 * return */
    229 	if (!tcsd_options.exclusive_transport)
    230 		return result;
    231 
    232 	MUTEX_LOCK(tcs_ctx_lock);
    233 
    234 	tmp = tcs_context_table;
    235 	while (tmp) {
    236 		if (tmp->flags & TSS_CONTEXT_FLAG_TRANSPORT_EXCLUSIVE) {
    237 			result = TCSERR(TSS_E_INTERNAL_ERROR);
    238 			goto done;
    239 		}
    240 
    241 		if (tmp->handle == tcsContext)
    242 			self = tmp;
    243 
    244 		tmp = tmp->next;
    245 	}
    246 
    247 	if (self)
    248 		self->flags |= TSS_CONTEXT_FLAG_TRANSPORT_EXCLUSIVE;
    249 	else
    250 		result = TCSERR(TCS_E_INVALID_CONTEXTHANDLE);
    251 done:
    252 	MUTEX_UNLOCK(tcs_ctx_lock);
    253 
    254 	return result;
    255 }
    256 
    257 TSS_RESULT
    258 ctx_set_transport_enabled(TCS_CONTEXT_HANDLE tcsContext, UINT32 hTransHandle)
    259 {
    260 	TSS_RESULT result = TSS_SUCCESS;
    261 	struct tcs_context *tmp, *self = NULL;
    262 
    263 	MUTEX_LOCK(tcs_ctx_lock);
    264 
    265 	tmp = tcs_context_table;
    266 	while (tmp) {
    267 		if (tmp->handle == tcsContext) {
    268 			self = tmp;
    269 			break;
    270 		}
    271 
    272 		tmp = tmp->next;
    273 	}
    274 
    275 	if (self) {
    276 		self->flags |= TSS_CONTEXT_FLAG_TRANSPORT_ENABLED;
    277 		self->transHandle = hTransHandle;
    278 	} else
    279 		result = TCSERR(TCS_E_INVALID_CONTEXTHANDLE);
    280 
    281 	MUTEX_UNLOCK(tcs_ctx_lock);
    282 
    283 	return result;
    284 }
    285 
    286 TSS_RESULT
    287 ctx_set_transport_disabled(TCS_CONTEXT_HANDLE tcsContext, TCS_HANDLE *transHandle)
    288 {
    289 	TSS_RESULT result = TSS_SUCCESS;
    290 	struct tcs_context *tmp, *self = NULL;
    291 
    292 	MUTEX_LOCK(tcs_ctx_lock);
    293 
    294 	tmp = tcs_context_table;
    295 	while (tmp) {
    296 		if (tmp->handle == tcsContext) {
    297 			self = tmp;
    298 			break;
    299 		}
    300 
    301 		tmp = tmp->next;
    302 	}
    303 
    304 	if (self) {
    305 		if (!transHandle || *transHandle == self->transHandle) {
    306 			self->transHandle = 0;
    307 			self->flags &= ~TSS_CONTEXT_FLAG_TRANSPORT_ENABLED;
    308 		}
    309 	} else
    310 		result = TCSERR(TCS_E_INVALID_CONTEXTHANDLE);
    311 
    312 	MUTEX_UNLOCK(tcs_ctx_lock);
    313 
    314 	return result;
    315 }
    316