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->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 if (tcsContext == InternalContext) { 186 LogDebug("Success: %x is an Internal Context", tcsContext); 187 return TSS_SUCCESS; 188 } 189 190 MUTEX_LOCK(tcs_ctx_lock); 191 192 c = get_context(tcsContext); 193 194 MUTEX_UNLOCK(tcs_ctx_lock); 195 196 if (c == NULL) { 197 LogDebug("Fail: Context %x not found", tcsContext); 198 return TCSERR(TCS_E_INVALID_CONTEXTHANDLE); 199 } 200 201 return TSS_SUCCESS; 202 } 203 204 205 COND_VAR * 206 ctx_get_cond_var(TCS_CONTEXT_HANDLE tcs_handle) 207 { 208 struct tcs_context *c; 209 COND_VAR *ret = NULL; 210 211 MUTEX_LOCK(tcs_ctx_lock); 212 213 c = get_context(tcs_handle); 214 215 if (c != NULL) 216 ret = &c->cond; 217 218 MUTEX_UNLOCK(tcs_ctx_lock); 219 220 return ret; 221 } 222 223 /* the only transport flag at the TCS level is whether the session is exclusive or not. If the app 224 * is requesting an exclusive transport session, check that no other exclusive sessions exist and 225 * if not, flag this context as being the one. If so, return internal error. */ 226 TSS_RESULT 227 ctx_req_exclusive_transport(TCS_CONTEXT_HANDLE tcsContext) 228 { 229 TSS_RESULT result = TSS_SUCCESS; 230 struct tcs_context *tmp, *self = NULL; 231 232 /* If the daemon is configured to ignore apps that want an exclusive transport, just 233 * return */ 234 if (!tcsd_options.exclusive_transport) 235 return result; 236 237 MUTEX_LOCK(tcs_ctx_lock); 238 239 tmp = tcs_context_table; 240 while (tmp) { 241 if (tmp->flags & TSS_CONTEXT_FLAG_TRANSPORT_EXCLUSIVE) { 242 result = TCSERR(TSS_E_INTERNAL_ERROR); 243 goto done; 244 } 245 246 if (tmp->handle == tcsContext) 247 self = tmp; 248 249 tmp = tmp->next; 250 } 251 252 if (self) 253 self->flags |= TSS_CONTEXT_FLAG_TRANSPORT_EXCLUSIVE; 254 else 255 result = TCSERR(TCS_E_INVALID_CONTEXTHANDLE); 256 done: 257 MUTEX_UNLOCK(tcs_ctx_lock); 258 259 return result; 260 } 261 262 TSS_RESULT 263 ctx_set_transport_enabled(TCS_CONTEXT_HANDLE tcsContext, UINT32 hTransHandle) 264 { 265 TSS_RESULT result = TSS_SUCCESS; 266 struct tcs_context *tmp, *self = NULL; 267 268 MUTEX_LOCK(tcs_ctx_lock); 269 270 tmp = tcs_context_table; 271 while (tmp) { 272 if (tmp->handle == tcsContext) { 273 self = tmp; 274 break; 275 } 276 277 tmp = tmp->next; 278 } 279 280 if (self) { 281 self->flags |= TSS_CONTEXT_FLAG_TRANSPORT_ENABLED; 282 self->transHandle = hTransHandle; 283 } else 284 result = TCSERR(TCS_E_INVALID_CONTEXTHANDLE); 285 286 MUTEX_UNLOCK(tcs_ctx_lock); 287 288 return result; 289 } 290 291 TSS_RESULT 292 ctx_set_transport_disabled(TCS_CONTEXT_HANDLE tcsContext, TCS_HANDLE *transHandle) 293 { 294 TSS_RESULT result = TSS_SUCCESS; 295 struct tcs_context *tmp, *self = NULL; 296 297 MUTEX_LOCK(tcs_ctx_lock); 298 299 tmp = tcs_context_table; 300 while (tmp) { 301 if (tmp->handle == tcsContext) { 302 self = tmp; 303 break; 304 } 305 306 tmp = tmp->next; 307 } 308 309 if (self) { 310 if (!transHandle || *transHandle == self->transHandle) { 311 self->transHandle = 0; 312 self->flags &= ~TSS_CONTEXT_FLAG_TRANSPORT_ENABLED; 313 } 314 } else 315 result = TCSERR(TCS_E_INVALID_CONTEXTHANDLE); 316 317 MUTEX_UNLOCK(tcs_ctx_lock); 318 319 return result; 320 } 321