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