Home | History | Annotate | Line # | Download | only in tcs
      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-2006
      8  *
      9  */
     10 
     11 
     12 #include <stdlib.h>
     13 #include <stdio.h>
     14 #include <string.h>
     15 #include <unistd.h>
     16 #include <errno.h>
     17 
     18 #include "trousers/tss.h"
     19 #include "trousers_types.h"
     20 #include "trousers_types.h"
     21 #include "tcs_tsp.h"
     22 #include "tcs_utils.h"
     23 #include "tcs_int_literals.h"
     24 #include "capabilities.h"
     25 #include "tcslog.h"
     26 #include "tcsps.h"
     27 #include "req_mgr.h"
     28 
     29 #include "tcs_key_ps.h"
     30 
     31 /*
     32  * mem_cache_lock will be responsible for protecting the key_mem_cache_head list. This is a
     33  * TCSD global linked list of all keys which have been loaded into the TPM at some time.
     34  */
     35 MUTEX_DECLARE_INIT(mem_cache_lock);
     36 
     37 /*
     38  * tcs_keyhandle_lock is only used to make TCS keyhandle generation atomic for all TCSD
     39  * threads.
     40  */
     41 static MUTEX_DECLARE_INIT(tcs_keyhandle_lock);
     42 
     43 /*
     44  * timestamp_lock is only used to make TCS key timestamp generation atomic for all TCSD
     45  * threads.
     46  */
     47 static MUTEX_DECLARE_INIT(timestamp_lock);
     48 
     49 TCS_KEY_HANDLE
     50 getNextTcsKeyHandle()
     51 {
     52 	static TCS_KEY_HANDLE NextTcsKeyHandle = 0x22330000;
     53 	TCS_KEY_HANDLE ret;
     54 
     55 	MUTEX_LOCK(tcs_keyhandle_lock);
     56 
     57 	do {
     58 		ret = NextTcsKeyHandle++;
     59 	} while (NextTcsKeyHandle == SRK_TPM_HANDLE || NextTcsKeyHandle == NULL_TCS_HANDLE);
     60 
     61 	MUTEX_UNLOCK(tcs_keyhandle_lock);
     62 
     63 	return ret;
     64 }
     65 
     66 UINT32
     67 getNextTimeStamp()
     68 {
     69 	static UINT32 time_stamp = 1;
     70 	UINT32 ret;
     71 
     72 	MUTEX_LOCK(timestamp_lock);
     73 	ret = time_stamp++;
     74 	MUTEX_UNLOCK(timestamp_lock);
     75 
     76 	return ret;
     77 }
     78 
     79 /* only called from load key paths, so no locking */
     80 TCPA_STORE_PUBKEY *
     81 mc_get_pub_by_slot(TCPA_KEY_HANDLE tpm_handle)
     82 {
     83 	struct key_mem_cache *tmp;
     84 	TCPA_STORE_PUBKEY *ret;
     85 
     86 	if (tpm_handle == NULL_TPM_HANDLE)
     87 		return NULL;
     88 
     89 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
     90 		LogDebugFn("TCSD mem_cached handle: 0x%x",
     91 			   tmp->tcs_handle);
     92 		if (tmp->tpm_handle == tpm_handle) {
     93 			ret = tmp->blob ? &tmp->blob->pubKey : NULL;
     94 			return ret;
     95 		}
     96 	}
     97 	LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
     98 	return NULL;
     99 }
    100 
    101 /* only called from load key paths, so no locking */
    102 TCPA_STORE_PUBKEY *
    103 mc_get_pub_by_handle(TCS_KEY_HANDLE tcs_handle)
    104 {
    105 	struct key_mem_cache *tmp;
    106 	TCPA_STORE_PUBKEY *ret;
    107 
    108 	LogDebugFn("looking for 0x%x", tcs_handle);
    109 
    110 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    111 		LogDebugFn("TCSD mem_cached handle: 0x%x",
    112 			 tmp->tcs_handle);
    113 		if (tmp->tcs_handle == tcs_handle) {
    114 			ret = tmp->blob ? &tmp->blob->pubKey : NULL;
    115 			return ret;
    116 		}
    117 	}
    118 
    119 	LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
    120 	return NULL;
    121 }
    122 
    123 /* only called from load key paths, so no locking */
    124 TSS_RESULT
    125 mc_set_parent_by_handle(TCS_KEY_HANDLE tcs_handle, TCS_KEY_HANDLE p_tcs_handle)
    126 {
    127 	struct key_mem_cache *tmp, *parent;
    128 
    129 	/* find parent */
    130 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    131 		LogDebug("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    132 		if (tmp->tcs_handle == p_tcs_handle) {
    133 			parent = tmp;
    134 			break;
    135 		}
    136 	}
    137 
    138 	/* didn't find parent */
    139 	if (tmp == NULL)
    140 		goto done;
    141 
    142 	/* set parent blob in child */
    143 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    144 		if (tmp->tcs_handle == tcs_handle) {
    145 			tmp->parent = parent;
    146 			return TSS_SUCCESS;
    147 		}
    148 	}
    149 done:
    150 	return TCSERR(TSS_E_FAIL);
    151 }
    152 
    153 TCPA_RESULT
    154 ensureKeyIsLoaded(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE keyHandle, TCPA_KEY_HANDLE * keySlot)
    155 {
    156 	TCPA_RESULT result = TSS_SUCCESS;
    157 	TCPA_STORE_PUBKEY *myPub;
    158 
    159 	LogDebugFn("0x%x", keyHandle);
    160 
    161 	if (!ctx_has_key_loaded(hContext, keyHandle))
    162 		return TCSERR(TCS_E_INVALID_KEY);
    163 
    164 	MUTEX_LOCK(mem_cache_lock);
    165 
    166 	*keySlot = mc_get_slot_by_handle(keyHandle);
    167 	LogDebug("keySlot is %08X", *keySlot);
    168 	if (*keySlot == NULL_TPM_HANDLE || isKeyLoaded(*keySlot) == FALSE) {
    169 		LogDebug("calling mc_get_pub_by_handle");
    170 		if ((myPub = mc_get_pub_by_handle(keyHandle)) == NULL) {
    171 			LogDebug("Failed to find pub by handle");
    172 			result = TCSERR(TCS_E_KM_LOADFAILED);
    173 			goto done;
    174 		}
    175 
    176 		LogDebugFn("calling LoadKeyShim");
    177 		if ((result = LoadKeyShim(hContext, myPub, NULL, keySlot))) {
    178 			LogDebug("Failed shim");
    179 			goto done;
    180 		}
    181 
    182 		if (*keySlot == NULL_TPM_HANDLE) {
    183 			LogDebug("Key slot is still invalid after ensureKeyIsLoaded");
    184 			result = TCSERR(TCS_E_KM_LOADFAILED);
    185 			goto done;
    186 		}
    187 	}
    188 	mc_update_time_stamp(*keySlot);
    189 
    190 done:
    191 	MUTEX_UNLOCK(mem_cache_lock);
    192 	LogDebugFn("Exit");
    193 	return result;
    194 }
    195 
    196 
    197 /* only called from load key paths, so no locking */
    198 TSS_UUID *
    199 mc_get_uuid_by_pub(TCPA_STORE_PUBKEY *pub)
    200 {
    201 	TSS_UUID *ret;
    202 	struct key_mem_cache *tmp;
    203 
    204 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    205 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    206 		if (tmp->blob &&
    207 		    tmp->blob->pubKey.keyLength == pub->keyLength &&
    208 		    !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
    209 			ret = &tmp->uuid;
    210 			return ret;
    211 		}
    212 	}
    213 
    214 	return NULL;
    215 }
    216 
    217 TSS_RESULT
    218 mc_get_handles_by_uuid(TSS_UUID *uuid, TCS_KEY_HANDLE *tcsHandle, TCPA_KEY_HANDLE *slot)
    219 {
    220 	struct key_mem_cache *tmp;
    221 
    222 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    223 		if (!memcmp(&tmp->uuid, uuid, sizeof(TSS_UUID))) {
    224 			*tcsHandle = tmp->tcs_handle;
    225 			*slot = tmp->tpm_handle;
    226 			return TSS_SUCCESS;
    227 		}
    228 	}
    229 
    230 	return TCSERR(TSS_E_FAIL);
    231 }
    232 
    233 TCS_KEY_HANDLE
    234 mc_get_handle_by_encdata(BYTE *encData)
    235 {
    236 	struct key_mem_cache *tmp;
    237 	TCS_KEY_HANDLE ret;
    238 
    239 	MUTEX_LOCK(mem_cache_lock);
    240 
    241 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    242 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    243 		if (!tmp->blob || tmp->blob->encSize == 0)
    244 			continue;
    245 		if (!memcmp(tmp->blob->encData, encData, tmp->blob->encSize)) {
    246 			ret = tmp->tcs_handle;
    247 			MUTEX_UNLOCK(mem_cache_lock);
    248 			return ret;
    249 		}
    250 	}
    251 	MUTEX_UNLOCK(mem_cache_lock);
    252 	return 0;
    253 }
    254 
    255 TSS_RESULT
    256 mc_update_encdata(BYTE *encData, BYTE *newEncData)
    257 {
    258 	struct key_mem_cache *tmp;
    259 	BYTE *tmp_enc_data;
    260 
    261 	MUTEX_LOCK(mem_cache_lock);
    262 
    263 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    264 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    265 		if (!tmp->blob || tmp->blob->encSize == 0)
    266 			continue;
    267 		if (!memcmp(tmp->blob->encData, encData, tmp->blob->encSize)) {
    268 			tmp_enc_data = (BYTE *)malloc(tmp->blob->encSize);
    269 			if (tmp_enc_data == NULL) {
    270 				LogError("malloc of %u bytes failed.", tmp->blob->encSize);
    271 				MUTEX_UNLOCK(mem_cache_lock);
    272 				return TCSERR(TSS_E_OUTOFMEMORY);
    273 			}
    274 
    275 			memcpy(tmp_enc_data, newEncData, tmp->blob->encSize);
    276 			free(tmp->blob->encData);
    277 			tmp->blob->encData = tmp_enc_data;
    278 			MUTEX_UNLOCK(mem_cache_lock);
    279 			return TSS_SUCCESS;
    280 		}
    281 	}
    282 	MUTEX_UNLOCK(mem_cache_lock);
    283 	LogError("Couldn't find requested encdata in mem cache");
    284 	return TCSERR(TSS_E_INTERNAL_ERROR);
    285 }
    286 
    287 /*
    288  * only called from load key paths and the init (single thread time) path,
    289  * so no locking
    290  */
    291 TSS_RESULT
    292 mc_add_entry(TCS_KEY_HANDLE tcs_handle,
    293 	     TCPA_KEY_HANDLE tpm_handle,
    294 	     TSS_KEY *key_blob)
    295 {
    296 	struct key_mem_cache *entry, *tmp;
    297 
    298 	/* Make sure the cache doesn't already have an entry for this key */
    299 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    300 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    301 		if (tcs_handle == tmp->tcs_handle) {
    302 			return TSS_SUCCESS;
    303 		}
    304 	}
    305 
    306 	/* Not found - we need to create a new entry */
    307 	entry = (struct key_mem_cache *)calloc(1, sizeof(struct key_mem_cache));
    308 	if (entry == NULL) {
    309 		LogError("malloc of %zd bytes failed.", sizeof(struct key_mem_cache));
    310 		return TCSERR(TSS_E_OUTOFMEMORY);
    311 	}
    312 
    313 	entry->tcs_handle = tcs_handle;
    314 	if (tpm_handle != NULL_TPM_HANDLE)
    315 		entry->time_stamp = getNextTimeStamp();
    316 
    317 	entry->tpm_handle = tpm_handle;
    318 
    319 	if (!key_blob)
    320 		goto add;
    321 
    322 	/* allocate space for the blob */
    323 	entry->blob = calloc(1, sizeof(TSS_KEY));
    324 	if (entry->blob == NULL) {
    325 		LogError("malloc of %zd bytes failed.", sizeof(TSS_KEY));
    326 		free(entry);
    327 		return TCSERR(TSS_E_OUTOFMEMORY);
    328 	}
    329 	memcpy(entry->blob, key_blob, sizeof(TSS_KEY));
    330 
    331 	/* allocate space for the key parameters if necessary */
    332 	if (key_blob->algorithmParms.parmSize) {
    333 		BYTE *tmp_parms = (BYTE *)malloc(key_blob->algorithmParms.parmSize);
    334 		if (tmp_parms == NULL) {
    335 			LogError("malloc of %u bytes failed.", key_blob->algorithmParms.parmSize);
    336 			free(entry->blob);
    337 			free(entry);
    338 			return TCSERR(TSS_E_OUTOFMEMORY);
    339 		}
    340 		memcpy(tmp_parms, key_blob->algorithmParms.parms, key_blob->algorithmParms.parmSize);
    341 		entry->blob->algorithmParms.parms = tmp_parms;
    342 	}
    343 	entry->blob->algorithmParms.parmSize = key_blob->algorithmParms.parmSize;
    344 
    345 	/* allocate space for the public key */
    346 	if (key_blob->pubKey.keyLength > 0) {
    347 		entry->blob->pubKey.key = (BYTE *)malloc(key_blob->pubKey.keyLength);
    348 		if (entry->blob->pubKey.key == NULL) {
    349 			LogError("malloc of %u bytes failed.", key_blob->pubKey.keyLength);
    350 			free(entry->blob->algorithmParms.parms);
    351 			free(entry->blob);
    352 			free(entry);
    353 			return TCSERR(TSS_E_OUTOFMEMORY);
    354 		}
    355 		memcpy(entry->blob->pubKey.key, key_blob->pubKey.key, key_blob->pubKey.keyLength);
    356 	}
    357 	entry->blob->pubKey.keyLength = key_blob->pubKey.keyLength;
    358 
    359 	/* allocate space for the PCR info */
    360 	if (key_blob->PCRInfoSize > 0) {
    361 		entry->blob->PCRInfo = (BYTE *)malloc(key_blob->PCRInfoSize);
    362 		if (entry->blob->PCRInfo == NULL) {
    363 			LogError("malloc of %u bytes failed.", key_blob->PCRInfoSize);
    364 			free(entry->blob->pubKey.key);
    365 			free(entry->blob->algorithmParms.parms);
    366 			free(entry->blob);
    367 			free(entry);
    368 			return TCSERR(TSS_E_OUTOFMEMORY);
    369 		}
    370 		memcpy(entry->blob->PCRInfo, key_blob->PCRInfo, key_blob->PCRInfoSize);
    371 	}
    372 	entry->blob->PCRInfoSize = key_blob->PCRInfoSize;
    373 
    374 	/* allocate space for the encData if necessary */
    375 	if (key_blob->encSize > 0) {
    376 		entry->blob->encData = (BYTE *)malloc(key_blob->encSize);
    377 		if (entry->blob->encData == NULL) {
    378 			LogError("malloc of %u bytes failed.", key_blob->encSize);
    379 			free(entry->blob->PCRInfo);
    380 			free(entry->blob->pubKey.key);
    381 			free(entry->blob->algorithmParms.parms);
    382 			free(entry->blob);
    383 			free(entry);
    384 			return TCSERR(TSS_E_OUTOFMEMORY);
    385 		}
    386 		memcpy(entry->blob->encData, key_blob->encData, key_blob->encSize);
    387 	}
    388 	entry->blob->encSize = key_blob->encSize;
    389 add:
    390 	/* add to the front of the list */
    391 	entry->next = key_mem_cache_head;
    392 	if (key_mem_cache_head) {
    393 		/* set the reference count to 0 initially for all keys not being the SRK. Up
    394 		 * the call chain, a reference to this mem cache entry will be set in the
    395 		 * context object of the calling context and this reference count will be
    396 		 * incremented there. */
    397 		entry->ref_cnt = 0;
    398 
    399 		key_mem_cache_head->prev = entry;
    400 	} else {
    401 		/* if we are the SRK, initially set the reference count to 1, so that it is
    402 		 * always seen as loaded in the TPM. */
    403 		entry->ref_cnt = 1;
    404 	}
    405 	key_mem_cache_head = entry;
    406 
    407 	return TSS_SUCCESS;
    408 }
    409 
    410 /* caller must lock the mem cache before calling! */
    411 TSS_RESULT
    412 mc_remove_entry(TCS_KEY_HANDLE tcs_handle)
    413 {
    414 	struct key_mem_cache *cur;
    415 
    416 	for (cur = key_mem_cache_head; cur; cur = cur->next) {
    417 		if (cur->tcs_handle == tcs_handle) {
    418 			if (cur->blob) {
    419 				destroy_key_refs(cur->blob);
    420 				free(cur->blob);
    421 			}
    422 
    423 			if (cur->prev != NULL)
    424 				cur->prev->next = cur->next;
    425 			if (cur->next != NULL)
    426 				cur->next->prev = cur->prev;
    427 
    428 			if (cur == key_mem_cache_head)
    429 				key_mem_cache_head = cur->next;
    430 			free(cur);
    431 
    432 			return TSS_SUCCESS;
    433 		}
    434 	}
    435 
    436 	return TCSERR(TSS_E_FAIL);
    437 }
    438 
    439 TSS_RESULT
    440 mc_add_entry_init(TCS_KEY_HANDLE tcs_handle,
    441 		  TCPA_KEY_HANDLE tpm_handle,
    442 		  TSS_KEY *key_blob,
    443 		  TSS_UUID *uuid)
    444 {
    445 	struct key_mem_cache *entry, *tmp;
    446 
    447 	/* Make sure the cache doesn't already have an entry for this key */
    448 	MUTEX_LOCK(mem_cache_lock);
    449 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    450 		if (tcs_handle == tmp->tcs_handle) {
    451 			mc_remove_entry(tcs_handle);
    452 		}
    453 	}
    454 	MUTEX_UNLOCK(mem_cache_lock);
    455 
    456 	/* Not found - we need to create a new entry */
    457 	entry = (struct key_mem_cache *)calloc(1, sizeof(struct key_mem_cache));
    458 	if (entry == NULL) {
    459 		LogError("malloc of %zd bytes failed.", sizeof(struct key_mem_cache));
    460 		return TCSERR(TSS_E_OUTOFMEMORY);
    461 	}
    462 
    463 	entry->tcs_handle = tcs_handle;
    464 	if (tpm_handle != NULL_TPM_HANDLE)
    465 		entry->time_stamp = getNextTimeStamp();
    466 
    467 	entry->tpm_handle = tpm_handle;
    468 
    469 	if (key_blob) {
    470 		/* allocate space for the blob */
    471 		entry->blob = malloc(sizeof(TSS_KEY));
    472 		if (entry->blob == NULL) {
    473 			LogError("malloc of %zd bytes failed.", sizeof(TSS_KEY));
    474 			free(entry);
    475 			return TCSERR(TSS_E_OUTOFMEMORY);
    476 		}
    477 
    478 		memcpy(entry->blob, key_blob, sizeof(TSS_KEY));
    479 
    480 		/* allocate space for the key parameters if necessary */
    481 		if (key_blob->algorithmParms.parmSize) {
    482 			BYTE *tmp_parms = (BYTE *)malloc(key_blob->algorithmParms.parmSize);
    483 			if (tmp_parms == NULL) {
    484 				LogError("malloc of %u bytes failed.",
    485 					 key_blob->algorithmParms.parmSize);
    486 				free(entry->blob);
    487 				free(entry);
    488 				return TCSERR(TSS_E_OUTOFMEMORY);
    489 			}
    490 			memcpy(tmp_parms, key_blob->algorithmParms.parms,
    491 			       key_blob->algorithmParms.parmSize);
    492 			entry->blob->algorithmParms.parms = tmp_parms;
    493 		}
    494 
    495 		/* allocate space for the public key */
    496 		entry->blob->pubKey.key = (BYTE *)malloc(key_blob->pubKey.keyLength);
    497 		if (entry->blob->pubKey.key == NULL) {
    498 			LogError("malloc of %u bytes failed.", key_blob->pubKey.keyLength);
    499 			free(entry->blob);
    500 			free(entry);
    501 			return TCSERR(TSS_E_OUTOFMEMORY);
    502 		}
    503 		memcpy(entry->blob->pubKey.key, key_blob->pubKey.key, key_blob->pubKey.keyLength);
    504 
    505 		/* allocate space for the encData if necessary */
    506 		if (key_blob->encSize != 0) {
    507 			entry->blob->encData = (BYTE *)malloc(key_blob->encSize);
    508 			if (entry->blob->encData == NULL) {
    509 				LogError("malloc of %u bytes failed.", key_blob->encSize);
    510 				free(entry->blob->pubKey.key);
    511 				free(entry->blob);
    512 				free(entry);
    513 				return TCSERR(TSS_E_OUTOFMEMORY);
    514 			}
    515 			memcpy(entry->blob->encData, key_blob->encData, key_blob->encSize);
    516 		}
    517 		entry->blob->encSize = key_blob->encSize;
    518 	}
    519 
    520 	memcpy(&entry->uuid, uuid, sizeof(TSS_UUID));
    521 
    522 	MUTEX_LOCK(mem_cache_lock);
    523 
    524 	entry->next = key_mem_cache_head;
    525 	if (key_mem_cache_head)
    526 		key_mem_cache_head->prev = entry;
    527 
    528 	entry->ref_cnt = 1;
    529 	key_mem_cache_head = entry;
    530 	MUTEX_UNLOCK(mem_cache_lock);
    531 
    532 	return TSS_SUCCESS;
    533 }
    534 
    535 /* only called from evict key paths, so no locking */
    536 TSS_RESULT
    537 mc_set_slot_by_slot(TCPA_KEY_HANDLE old_handle, TCPA_KEY_HANDLE new_handle)
    538 {
    539 	struct key_mem_cache *tmp;
    540 
    541 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    542 		if (tmp->tpm_handle == old_handle) {
    543 			LogDebugFn("Set TCS key 0x%x, old TPM handle: 0x%x "
    544 				   "new TPM handle: 0x%x", tmp->tcs_handle,
    545 				   old_handle, new_handle);
    546 			if (new_handle == NULL_TPM_HANDLE)
    547 				tmp->time_stamp = 0;
    548 			else
    549 				tmp->time_stamp = getNextTimeStamp();
    550 			tmp->tpm_handle = new_handle;
    551 			return TSS_SUCCESS;
    552 		}
    553 	}
    554 
    555 	return TCSERR(TSS_E_FAIL);
    556 }
    557 
    558 /* only called from load key paths, so no locking */
    559 TSS_RESULT
    560 mc_set_slot_by_handle(TCS_KEY_HANDLE tcs_handle, TCPA_KEY_HANDLE tpm_handle)
    561 {
    562 	struct key_mem_cache *tmp;
    563 
    564 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    565 		LogDebug("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    566 		if (tmp->tcs_handle == tcs_handle) {
    567 			if (tpm_handle == NULL_TPM_HANDLE)
    568 				tmp->time_stamp = 0;
    569 			else
    570 				tmp->time_stamp = getNextTimeStamp();
    571 			tmp->tpm_handle = tpm_handle;
    572 			return TSS_SUCCESS;
    573 		}
    574 	}
    575 
    576 	return TCSERR(TSS_E_FAIL);
    577 }
    578 
    579 /* the beginnings of a key manager start here ;-) */
    580 
    581 TSS_RESULT
    582 key_mgr_evict(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hKey)
    583 {
    584 	TSS_RESULT result = TCS_SUCCESS;
    585 
    586 	if ((result = ctx_remove_key_loaded(hContext, hKey)))
    587 		return result;
    588 
    589 	if ((result = key_mgr_dec_ref_count(hKey)))
    590 		return result;
    591 
    592 	key_mgr_ref_count();
    593 
    594 	return result;
    595 }
    596 
    597 TSS_RESULT
    598 key_mgr_load_by_blob(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hUnwrappingKey,
    599 		     UINT32 cWrappedKeyBlob, BYTE *rgbWrappedKeyBlob,
    600 		     TPM_AUTH *pAuth, TCS_KEY_HANDLE *phKeyTCSI, TCS_KEY_HANDLE *phKeyHMAC)
    601 {
    602 	TSS_RESULT result;
    603 
    604 	/* Check that auth for the parent key is loaded outside the mem_cache_lock. We have to do
    605 	 * this here because if the TPM can't process this request right now, the thread could be
    606 	 * put to sleep while holding the mem_cache_lock, which would result in a deadlock */
    607 	if (pAuth) {
    608 		if ((result = auth_mgr_check(hContext, &pAuth->AuthHandle)))
    609 			return result;
    610 	}
    611 
    612 	MUTEX_LOCK(mem_cache_lock);
    613 
    614 	if (TPM_VERSION_IS(1,2)) {
    615 		result = TCSP_LoadKey2ByBlob_Internal(hContext, hUnwrappingKey, cWrappedKeyBlob,
    616 						      rgbWrappedKeyBlob, pAuth, phKeyTCSI);
    617 	} else {
    618 		result = TCSP_LoadKeyByBlob_Internal(hContext, hUnwrappingKey, cWrappedKeyBlob,
    619 						     rgbWrappedKeyBlob, pAuth, phKeyTCSI,
    620 						     phKeyHMAC);
    621 	}
    622 
    623 	MUTEX_UNLOCK(mem_cache_lock);
    624 
    625 	return result;
    626 }
    627 
    628 /* create a reference to one key. This is called from the key_mgr_load_*
    629  * functions only, so no locking is done.
    630  */
    631 TSS_RESULT
    632 key_mgr_inc_ref_count(TCS_KEY_HANDLE key_handle)
    633 {
    634 	struct key_mem_cache *cur;
    635 
    636 	for (cur = key_mem_cache_head; cur; cur = cur->next) {
    637 		LogDebugFn("TCSD mem_cached handle: 0x%x", cur->tcs_handle);
    638 		if (cur->tcs_handle == key_handle) {
    639 			cur->ref_cnt++;
    640 			return TSS_SUCCESS;
    641 		}
    642 	}
    643 
    644 	return TCSERR(TSS_E_FAIL);
    645 }
    646 
    647 /* de-reference one key.  This is called by the context routines, so
    648  * locking is necessary.
    649  */
    650 TSS_RESULT
    651 key_mgr_dec_ref_count(TCS_KEY_HANDLE key_handle)
    652 {
    653 	struct key_mem_cache *cur;
    654 
    655 	MUTEX_LOCK(mem_cache_lock);
    656 
    657 	for (cur = key_mem_cache_head; cur; cur = cur->next) {
    658 		if (cur->tcs_handle == key_handle) {
    659 			cur->ref_cnt--;
    660 			LogDebugFn("decrementing ref cnt for key 0x%x",
    661 				   key_handle);
    662 			MUTEX_UNLOCK(mem_cache_lock);
    663 			return TSS_SUCCESS;
    664 		}
    665 	}
    666 
    667 	MUTEX_UNLOCK(mem_cache_lock);
    668 	return TCSERR(TSS_E_FAIL);
    669 }
    670 
    671 /* run through the global list and free any keys with reference counts of 0 */
    672 void
    673 key_mgr_ref_count()
    674 {
    675 	struct key_mem_cache *tmp, *cur;
    676 
    677 	MUTEX_LOCK(mem_cache_lock);
    678 
    679 	for (cur = key_mem_cache_head; cur;) {
    680 		if (cur->ref_cnt == 0) {
    681 			if (cur->tpm_handle != NULL_TPM_HANDLE) {
    682 				LogDebugFn("Key 0x%x being freed from TPM", cur->tpm_handle);
    683 				internal_EvictByKeySlot(cur->tpm_handle);
    684 			}
    685 			LogDebugFn("Key 0x%x being freed", cur->tcs_handle);
    686 			if (cur->blob) {
    687 				destroy_key_refs(cur->blob);
    688 				free(cur->blob);
    689 			}
    690 			if (cur->prev != NULL)
    691 				cur->prev->next = cur->next;
    692 			if (cur->next != NULL)
    693 				cur->next->prev = cur->prev;
    694 
    695 			tmp = cur;
    696 			if (cur == key_mem_cache_head)
    697 				key_mem_cache_head = cur->next;
    698 			cur = cur->next;
    699 			free(tmp);
    700 		} else {
    701 			cur = cur->next;
    702 		}
    703 	}
    704 
    705 	MUTEX_UNLOCK(mem_cache_lock);
    706 }
    707 
    708 /* only called from load key paths, so no locking */
    709 TCPA_KEY_HANDLE
    710 mc_get_slot_by_handle(TCS_KEY_HANDLE tcs_handle)
    711 {
    712 	struct key_mem_cache *tmp;
    713 	TCS_KEY_HANDLE ret;
    714 
    715 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    716 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    717 		if (tmp->tcs_handle == tcs_handle) {
    718 			ret = tmp->tpm_handle;
    719 			return ret;
    720 		}
    721 	}
    722 
    723 	LogDebugFn("returning NULL_TPM_HANDLE");
    724 	return NULL_TPM_HANDLE;
    725 }
    726 
    727 /* called from functions outside the load key path */
    728 TCPA_KEY_HANDLE
    729 mc_get_slot_by_handle_lock(TCS_KEY_HANDLE tcs_handle)
    730 {
    731 	struct key_mem_cache *tmp;
    732 	TCS_KEY_HANDLE ret;
    733 
    734 	MUTEX_LOCK(mem_cache_lock);
    735 
    736 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    737 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    738 		if (tmp->tcs_handle == tcs_handle) {
    739 			ret = tmp->tpm_handle;
    740 			MUTEX_UNLOCK(mem_cache_lock);
    741 			return ret;
    742 		}
    743 	}
    744 
    745 	MUTEX_UNLOCK(mem_cache_lock);
    746 	LogDebugFn("returning NULL_TPM_HANDLE");
    747 	return NULL_TPM_HANDLE;
    748 }
    749 
    750 /* only called from load key paths, so no locking */
    751 TCPA_KEY_HANDLE
    752 mc_get_slot_by_pub(TCPA_STORE_PUBKEY *pub)
    753 {
    754 	struct key_mem_cache *tmp;
    755 	TCPA_KEY_HANDLE ret;
    756 
    757 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    758 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    759 		if (tmp->blob &&
    760 		    !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
    761 			ret = tmp->tpm_handle;
    762 			return ret;
    763 		}
    764 	}
    765 
    766 	LogDebugFn("returning NULL_TPM_HANDLE");
    767 	return NULL_TPM_HANDLE;
    768 }
    769 
    770 /* Check the mem cache for a key with public key pub. If a parent TCS key handle
    771  * is passed in, make sure the parent of the key find matches it, else return
    772  * key not found */
    773 /* only called from load key paths, so no locking */
    774 TCS_KEY_HANDLE
    775 mc_get_handle_by_pub(TCPA_STORE_PUBKEY *pub, TCS_KEY_HANDLE parent)
    776 {
    777 	struct key_mem_cache *tmp;
    778 
    779 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    780 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    781 		if (tmp->blob &&
    782 		    pub->keyLength == tmp->blob->pubKey.keyLength &&
    783 		    !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
    784 			if (parent) {
    785 				if (!tmp->parent)
    786 					continue;
    787 				if (parent == tmp->parent->tcs_handle)
    788 					return tmp->tcs_handle;
    789 			} else
    790 				return tmp->tcs_handle;
    791 		}
    792 	}
    793 
    794 	LogDebugFn("returning NULL_TCS_HANDLE");
    795 	return NULL_TCS_HANDLE;
    796 }
    797 
    798 /* only called from load key paths, so no locking */
    799 TCPA_STORE_PUBKEY *
    800 mc_get_parent_pub_by_pub(TCPA_STORE_PUBKEY *pub)
    801 {
    802 	struct key_mem_cache *tmp;
    803 	TCPA_STORE_PUBKEY *ret = NULL;
    804 
    805 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    806 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    807 		if (tmp->tcs_handle == TPM_KEYHND_SRK) {
    808 			LogDebugFn("skipping the SRK");
    809 			continue;
    810 		}
    811 		if (tmp->blob &&
    812 		    !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
    813 			if (tmp->parent && tmp->parent->blob) {
    814 				ret = &tmp->parent->blob->pubKey;
    815 				LogDebugFn("Success");
    816 			} else {
    817 				LogError("parent pointer not set in key mem cache object w/ TCS "
    818 					 "handle: 0x%x", tmp->tcs_handle);
    819 			}
    820 			return ret;
    821 		}
    822 	}
    823 
    824 	LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
    825 	return NULL;
    826 }
    827 
    828 /* only called from load key paths, so no locking */
    829 TSS_RESULT
    830 mc_get_blob_by_pub(TCPA_STORE_PUBKEY *pub, TSS_KEY **ret_key)
    831 {
    832 	struct key_mem_cache *tmp;
    833 
    834 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    835 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    836 		if (tmp->blob &&
    837 		    !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
    838 			*ret_key = tmp->blob;
    839 			return TSS_SUCCESS;
    840 		}
    841 	}
    842 
    843 	LogDebugFn("returning TSS_E_FAIL");
    844 	return TCSERR(TSS_E_FAIL);
    845 }
    846 
    847 /* only called from load key paths, so no locking */
    848 TCS_KEY_HANDLE
    849 mc_get_handle_by_slot(TCPA_KEY_HANDLE tpm_handle)
    850 {
    851 	struct key_mem_cache *tmp;
    852 	TCS_KEY_HANDLE ret;
    853 
    854 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    855 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    856 		if (tmp->tpm_handle == tpm_handle) {
    857 			ret = tmp->tcs_handle;
    858 			return ret;
    859 		}
    860 	}
    861 
    862 	return NULL_TCS_HANDLE;
    863 }
    864 
    865 /* only called from load key paths, so no locking */
    866 TSS_RESULT
    867 mc_update_time_stamp(TCPA_KEY_HANDLE tpm_handle)
    868 {
    869 	struct key_mem_cache *tmp;
    870 
    871 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    872 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
    873 		if (tmp->tpm_handle == tpm_handle) {
    874 			tmp->time_stamp = getNextTimeStamp();
    875 			return TSS_SUCCESS;
    876 		}
    877 	}
    878 
    879 	return TCSERR(TSS_E_FAIL);
    880 }
    881 
    882 /* Right now this evicts the LRU key assuming it's not the parent */
    883 TSS_RESULT
    884 evictFirstKey(TCS_KEY_HANDLE parent_tcs_handle)
    885 {
    886 	struct key_mem_cache *tmp;
    887 	TCS_KEY_HANDLE tpm_handle_to_evict = NULL_TPM_HANDLE;
    888 	UINT32 smallestTimeStamp = ~(0U);	/* largest */
    889 	TSS_RESULT result;
    890 	UINT32 count;
    891 
    892 	/* First, see if there are any known keys worth evicting */
    893 	if ((result = clearUnknownKeys(InternalContext, &count)))
    894 		return result;
    895 
    896 	if (count > 0) {
    897 		LogDebugFn("Evicted %u unknown keys", count);
    898 		return TSS_SUCCESS;
    899 	}
    900 
    901 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
    902 		if (tmp->tpm_handle != NULL_TPM_HANDLE &&	/* not already evicted */
    903 		    tmp->tpm_handle != SRK_TPM_HANDLE &&	/* not the srk */
    904 		    tmp->tcs_handle != parent_tcs_handle &&	/* not my parent */
    905 		    tmp->time_stamp < smallestTimeStamp) {	/* is the smallest time
    906 								   stamp so far */
    907 			tpm_handle_to_evict = tmp->tpm_handle;
    908 			smallestTimeStamp = tmp->time_stamp;
    909 		}
    910 	}
    911 
    912 	if (tpm_handle_to_evict != NULL_TCS_HANDLE) {
    913 		if ((result = internal_EvictByKeySlot(tpm_handle_to_evict)))
    914 			return result;
    915 
    916 		LogDebugFn("Evicted key w/ TPM handle 0x%x", tpm_handle_to_evict);
    917 		result = mc_set_slot_by_slot(tpm_handle_to_evict, NULL_TPM_HANDLE);
    918 	} else
    919 		return TSS_SUCCESS;
    920 
    921 	return result;
    922 }
    923 
    924 TSS_BOOL
    925 isKeyLoaded(TCPA_KEY_HANDLE keySlot)
    926 {
    927 	UINT64 offset;
    928 	UINT32 i;
    929 	TCPA_KEY_HANDLE_LIST keyList;
    930 	UINT32 respSize;
    931 	BYTE *resp;
    932 	TSS_RESULT result;
    933 
    934 	if (keySlot == SRK_TPM_HANDLE) {
    935 		return TRUE;
    936 	}
    937 
    938 	if ((result = TCSP_GetCapability_Internal(InternalContext, TCPA_CAP_KEY_HANDLE, 0, NULL,
    939 						  &respSize, &resp)))
    940 		goto not_loaded;
    941 
    942 	offset = 0;
    943 	UnloadBlob_KEY_HANDLE_LIST(&offset, resp, &keyList);
    944 	free(resp);
    945 	for (i = 0; i < keyList.loaded; i++) {
    946 		LogDebugFn("loaded TPM key handle: 0x%x", keyList.handle[i]);
    947 		if (keyList.handle[i] == keySlot) {
    948 			free(keyList.handle);
    949 			return TRUE;
    950 		}
    951 	}
    952 
    953 	free(keyList.handle);
    954 
    955 not_loaded:
    956 	LogDebugFn("Key is not loaded, changing slot");
    957 	mc_set_slot_by_slot(keySlot, NULL_TPM_HANDLE);
    958 	return FALSE;
    959 }
    960 
    961 /* all calls to LoadKeyShim are inside locks */
    962 TSS_RESULT
    963 LoadKeyShim(TCS_CONTEXT_HANDLE hContext, TCPA_STORE_PUBKEY *pubKey,
    964 	    TSS_UUID *parentUuid, TCPA_KEY_HANDLE *slotOut)
    965 {
    966 
    967 	TCPA_STORE_PUBKEY *parentPub;
    968 	UINT32 result;
    969 	TCPA_KEY_HANDLE keySlot;
    970 	TCPA_KEY_HANDLE parentSlot;
    971 	TCS_KEY_HANDLE tcsKeyHandle;
    972 	TSS_KEY *myKey;
    973 	UINT64 offset;
    974 	TCS_KEY_HANDLE parentHandle;
    975 	BYTE keyBlob[1024];
    976 
    977 	LogDebugFn("calling mc_get_slot_by_pub");
    978 
    979 	/* If I'm loaded, then no point being here.  Get the slot and return */
    980 	keySlot = mc_get_slot_by_pub(pubKey);
    981 	if (keySlot != NULL_TPM_HANDLE && isKeyLoaded(keySlot)) {
    982 		*slotOut = keySlot;
    983 		return TSS_SUCCESS;
    984 	}
    985 
    986 	/*
    987 	 * Before proceeding, the parent must be loaded.
    988 	 * If the parent is registered, then it can be loaded by UUID.
    989 	 * If not, then the shim will be called to load it's parent and then try
    990 	 * to load it based on the persistent store.
    991 	 */
    992 
    993 	LogDebugFn("calling mc_get_parent_pub_by_pub");
    994 	/* Check if the Key is in the memory cache */
    995 	if ((parentPub = mc_get_parent_pub_by_pub(pubKey)) == NULL) {
    996 #if 0
    997 		LogDebugFn("parentPub is NULL");
    998 		/* If parentUUID is not handed in, then this key was never loaded and isn't reg'd */
    999 		if (parentUuid == NULL)
   1000 			return TCSERR(TCS_E_KM_LOADFAILED);
   1001 
   1002 		LogDebugFn("calling TCSP_LoadKeyByUUID_Internal");
   1003 		/* This will try to load my parent by UUID */
   1004 		if ((result = TCSP_LoadKeyByUUID_Internal(hContext, parentUuid, NULL, &parentSlot)))
   1005 			return result;
   1006 #else
   1007 		return TCSERR(TCS_E_KM_LOADFAILED);
   1008 #endif
   1009 	} else {
   1010 		LogDebugFn("calling LoadKeyShim");
   1011 		if ((result = LoadKeyShim(hContext, parentPub, NULL, &parentSlot)))
   1012 			return result;
   1013 	}
   1014 
   1015 	/*
   1016 	 * Now that the parent is loaded, I can load myself.
   1017 	 * If I'm registered, that's by UUID.  If I'm not,
   1018 	 * that's by blob.  If there is no persistent storage data, then I cannot be
   1019 	 * loaded by blob. The user must have some point loaded this key manually.
   1020 	 */
   1021 
   1022 	/* check the mem cache */
   1023 	if (mc_get_blob_by_pub(pubKey, &myKey) == TSS_SUCCESS) {
   1024 		parentHandle = mc_get_handle_by_slot(parentSlot);
   1025 		if (parentHandle == 0)
   1026 			return TCSERR(TCS_E_KM_LOADFAILED);
   1027 
   1028 		offset = 0;
   1029 		LoadBlob_TSS_KEY(&offset, keyBlob, myKey);
   1030 		if (TPM_VERSION_IS(1,2))
   1031 			result = TCSP_LoadKey2ByBlob_Internal(hContext,
   1032 							      parentHandle, offset,
   1033 							      keyBlob, NULL,
   1034 							      &tcsKeyHandle);
   1035 		else
   1036 			result = TCSP_LoadKeyByBlob_Internal(hContext,
   1037 							     parentHandle, offset,
   1038 							     keyBlob, NULL,
   1039 							     &tcsKeyHandle, slotOut);
   1040 		if (result)
   1041 			return result;
   1042 
   1043 		return ctx_mark_key_loaded(hContext, tcsKeyHandle);
   1044 #if TSS_BUILD_PS
   1045 	} else {
   1046 		TSS_UUID *uuid;
   1047 
   1048 		/* check registered */
   1049 		if (ps_is_pub_registered(pubKey) == FALSE)
   1050 			return TCSERR(TCS_E_KM_LOADFAILED);
   1051 		//uuid = mc_get_uuid_by_pub(pubKey); // XXX pub is not in MC
   1052 		if ((result = ps_get_uuid_by_pub(pubKey, &uuid)))
   1053 			return result;
   1054 
   1055 		if ((result = TCSP_LoadKeyByUUID_Internal(hContext, uuid, NULL, &tcsKeyHandle))) {
   1056 			free(uuid);
   1057 			return result;
   1058 		}
   1059 		free(uuid);
   1060 		*slotOut = mc_get_slot_by_handle(tcsKeyHandle);
   1061 
   1062 		return ctx_mark_key_loaded(hContext, tcsKeyHandle);
   1063 #endif
   1064 	}
   1065 
   1066 	return TCSERR(TCS_E_KM_LOADFAILED);
   1067 }
   1068 
   1069 TSS_RESULT
   1070 owner_evict_init()
   1071 {
   1072 	TSS_RESULT result = TSS_SUCCESS;
   1073 	TCPA_KEY_HANDLE_LIST keyList = { 0, NULL };
   1074 	BYTE *respData = NULL, ownerEvictCtr = 0;
   1075 	UINT32 respDataSize = 0, i;
   1076 	UINT64 offset = 0;
   1077 
   1078 	/* If we're a 1.1 TPM, we can exit immediately since only 1.2+ supports owner evict */
   1079 	if (TPM_VERSION_IS(1,1))
   1080 		return TSS_SUCCESS;
   1081 
   1082 	if ((result = TCSP_GetCapability_Internal(InternalContext, TPM_CAP_KEY_HANDLE, 0, NULL,
   1083 						  &respDataSize, &respData)))
   1084 		return result;
   1085 
   1086 	if ((result = UnloadBlob_KEY_HANDLE_LIST(&offset, respData, &keyList))) {
   1087 		free(respData);
   1088 		return result;
   1089 	}
   1090 
   1091 	free(respData);
   1092 	for (i = 0; i < keyList.loaded; i++) {
   1093 		UINT64 offset = 0;
   1094 		UINT32 keyHandle;
   1095 
   1096 		LoadBlob_UINT32(&offset, keyList.handle[i], (BYTE *)&keyHandle);
   1097 		/* get the ownerEvict flag for this key handle */
   1098 		result = TCSP_GetCapability_Internal(InternalContext, TPM_CAP_KEY_STATUS,
   1099 							  sizeof(UINT32), (BYTE *)&keyHandle,
   1100 							  &respDataSize, &respData);
   1101 		/* special case, invalid keys are automatically evicted later */
   1102 		if (result == TPM_E_INVALID_KEYHANDLE) {
   1103 			result = TSS_SUCCESS;
   1104 			continue;
   1105 		}
   1106 
   1107 		if (result != TSS_SUCCESS) {
   1108 			free(keyList.handle);
   1109 			return result;
   1110 		}
   1111 
   1112 		if (*(TPM_BOOL *)respData == TRUE) {
   1113 			TSS_UUID uuid = TSS_UUID_OWNEREVICT(ownerEvictCtr);
   1114 
   1115 			LogDebugFn("Found an owner evict key, assigned uuid %hhu", ownerEvictCtr);
   1116 			if ((result = mc_add_entry_init(getNextTcsKeyHandle(), keyList.handle[i],
   1117 							NULL, &uuid))) {
   1118 				free(keyList.handle);
   1119 				return result;
   1120 			}
   1121 			ownerEvictCtr++;
   1122 		}
   1123 	}
   1124 
   1125 	return result;
   1126 }
   1127 
   1128 /* find next lowest OWNEREVICT uuid */
   1129 TSS_RESULT
   1130 mc_find_next_ownerevict_uuid(TSS_UUID *uuid)
   1131 {
   1132 	TCS_KEY_HANDLE tmpKey;
   1133 	TCPA_KEY_HANDLE tmpSlot;
   1134 	UINT16 seed = 0;
   1135 	TSS_RESULT result = TCSERR(TSS_E_FAIL);
   1136 
   1137 	MUTEX_LOCK(mem_cache_lock);
   1138 
   1139 	for (seed = 0; seed <= 255; seed++) {
   1140 		TSS_UUID tmpUuid = TSS_UUID_OWNEREVICT(seed);
   1141 
   1142 		/* if UUID is found, continue on, trying the next UUID */
   1143 		if (!mc_get_handles_by_uuid(&tmpUuid, &tmpKey, &tmpSlot))
   1144 			continue;
   1145 
   1146 		/* UUID is not found, so its the first one available */
   1147 		memcpy(uuid, &tmpUuid, sizeof(TSS_UUID));
   1148 		result = TSS_SUCCESS;
   1149 		break;
   1150 	}
   1151 
   1152 	MUTEX_UNLOCK(mem_cache_lock);
   1153 	return result;
   1154 }
   1155 
   1156 TSS_RESULT
   1157 mc_set_uuid(TCS_KEY_HANDLE tcs_handle, TSS_UUID *uuid)
   1158 {
   1159 	struct key_mem_cache *tmp;
   1160 	TSS_RESULT result = TCSERR(TSS_E_FAIL);
   1161 
   1162 	MUTEX_LOCK(mem_cache_lock);
   1163 
   1164 	LogDebugFn("looking for 0x%x", tcs_handle);
   1165 
   1166 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
   1167 		LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
   1168 		if (tmp->tcs_handle == tcs_handle) {
   1169 			LogDebugFn("Handle found, re-setting UUID");
   1170 			memcpy(&tmp->uuid, uuid, sizeof(TSS_UUID));
   1171 			result = TSS_SUCCESS;
   1172 			break;
   1173 		}
   1174 	}
   1175 	MUTEX_UNLOCK(mem_cache_lock);
   1176 
   1177 	return result;
   1178 }
   1179