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
getNextTcsKeyHandle()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
getNextTimeStamp()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 *
mc_get_pub_by_slot(TCPA_KEY_HANDLE tpm_handle)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 *
mc_get_pub_by_handle(TCS_KEY_HANDLE tcs_handle)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
mc_set_parent_by_handle(TCS_KEY_HANDLE tcs_handle,TCS_KEY_HANDLE p_tcs_handle)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
ensureKeyIsLoaded(TCS_CONTEXT_HANDLE hContext,TCS_KEY_HANDLE keyHandle,TCPA_KEY_HANDLE * keySlot)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 *
mc_get_uuid_by_pub(TCPA_STORE_PUBKEY * pub)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
mc_get_handles_by_uuid(TSS_UUID * uuid,TCS_KEY_HANDLE * tcsHandle,TCPA_KEY_HANDLE * slot)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
mc_get_handle_by_encdata(BYTE * encData)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
mc_update_encdata(BYTE * encData,BYTE * newEncData)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
mc_add_entry(TCS_KEY_HANDLE tcs_handle,TCPA_KEY_HANDLE tpm_handle,TSS_KEY * key_blob)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
mc_remove_entry(TCS_KEY_HANDLE tcs_handle)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
mc_add_entry_init(TCS_KEY_HANDLE tcs_handle,TCPA_KEY_HANDLE tpm_handle,TSS_KEY * key_blob,TSS_UUID * uuid)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
mc_set_slot_by_slot(TCPA_KEY_HANDLE old_handle,TCPA_KEY_HANDLE new_handle)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
mc_set_slot_by_handle(TCS_KEY_HANDLE tcs_handle,TCPA_KEY_HANDLE tpm_handle)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
key_mgr_evict(TCS_CONTEXT_HANDLE hContext,TCS_KEY_HANDLE hKey)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
key_mgr_load_by_blob(TCS_CONTEXT_HANDLE hContext,TCS_KEY_HANDLE hUnwrappingKey,UINT32 cWrappedKeyBlob,BYTE * rgbWrappedKeyBlob,TPM_AUTH * pAuth,TCS_KEY_HANDLE * phKeyTCSI,TCS_KEY_HANDLE * phKeyHMAC)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
key_mgr_inc_ref_count(TCS_KEY_HANDLE key_handle)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
key_mgr_dec_ref_count(TCS_KEY_HANDLE key_handle)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
key_mgr_ref_count()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
mc_get_slot_by_handle(TCS_KEY_HANDLE tcs_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
mc_get_slot_by_handle_lock(TCS_KEY_HANDLE tcs_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
mc_get_slot_by_pub(TCPA_STORE_PUBKEY * pub)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
mc_get_handle_by_pub(TCPA_STORE_PUBKEY * pub,TCS_KEY_HANDLE parent)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 *
mc_get_parent_pub_by_pub(TCPA_STORE_PUBKEY * pub)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
mc_get_blob_by_pub(TCPA_STORE_PUBKEY * pub,TSS_KEY ** ret_key)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
mc_get_handle_by_slot(TCPA_KEY_HANDLE tpm_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
mc_update_time_stamp(TCPA_KEY_HANDLE tpm_handle)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
evictFirstKey(TCS_KEY_HANDLE parent_tcs_handle)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
isKeyLoaded(TCPA_KEY_HANDLE keySlot)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
LoadKeyShim(TCS_CONTEXT_HANDLE hContext,TCPA_STORE_PUBKEY * pubKey,TSS_UUID * parentUuid,TCPA_KEY_HANDLE * slotOut)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
owner_evict_init()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
mc_find_next_ownerevict_uuid(TSS_UUID * uuid)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
mc_set_uuid(TCS_KEY_HANDLE tcs_handle,TSS_UUID * uuid)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