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