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
getNextHandle()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 *
create_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 *
get_context(TCS_CONTEXT_HANDLE handle)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 *
get_previous_context(TCS_CONTEXT_HANDLE handle)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
destroy_context(TCS_CONTEXT_HANDLE handle)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
make_context()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
ctx_verify_context(TCS_CONTEXT_HANDLE tcsContext)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 *
ctx_get_cond_var(TCS_CONTEXT_HANDLE tcs_handle)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
ctx_req_exclusive_transport(TCS_CONTEXT_HANDLE tcsContext)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
ctx_set_transport_enabled(TCS_CONTEXT_HANDLE tcsContext,UINT32 hTransHandle)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
ctx_set_transport_disabled(TCS_CONTEXT_HANDLE tcsContext,TCS_HANDLE * transHandle)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