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