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