3
* Licensed Materials - Property of IBM
5
* trousers - An open source TCG Software Stack
7
* (C) Copyright International Business Machines Corp. 2004-2006
18
#include "trousers/tss.h"
19
#include "trousers_types.h"
20
#include "trousers_types.h"
22
#include "tcs_utils.h"
23
#include "tcs_int_literals.h"
24
#include "capabilities.h"
29
#include "tcs_key_ps.h"
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.
35
MUTEX_DECLARE_INIT(mem_cache_lock);
38
* tcs_keyhandle_lock is only used to make TCS keyhandle generation atomic for all TCSD
41
static MUTEX_DECLARE_INIT(tcs_keyhandle_lock);
44
* timestamp_lock is only used to make TCS key timestamp generation atomic for all TCSD
47
static MUTEX_DECLARE_INIT(timestamp_lock);
52
static TCS_KEY_HANDLE NextTcsKeyHandle = 0x22330000;
55
MUTEX_LOCK(tcs_keyhandle_lock);
58
ret = NextTcsKeyHandle++;
59
} while (NextTcsKeyHandle == SRK_TPM_HANDLE || NextTcsKeyHandle == NULL_TCS_HANDLE);
61
MUTEX_UNLOCK(tcs_keyhandle_lock);
69
static UINT32 time_stamp = 1;
72
MUTEX_LOCK(timestamp_lock);
74
MUTEX_UNLOCK(timestamp_lock);
79
/* only called from load key paths, so no locking */
81
mc_get_pub_by_slot(TCPA_KEY_HANDLE tpm_handle)
83
struct key_mem_cache *tmp;
84
TCPA_STORE_PUBKEY *ret;
86
if (tpm_handle == NULL_TPM_HANDLE)
89
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
90
LogDebugFn("TCSD mem_cached handle: 0x%x",
92
if (tmp->tpm_handle == tpm_handle) {
93
ret = tmp->blob ? &tmp->blob->pubKey : NULL;
97
LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
101
/* only called from load key paths, so no locking */
103
mc_get_pub_by_handle(TCS_KEY_HANDLE tcs_handle)
105
struct key_mem_cache *tmp;
106
TCPA_STORE_PUBKEY *ret;
108
LogDebugFn("looking for 0x%x", tcs_handle);
110
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
111
LogDebugFn("TCSD mem_cached handle: 0x%x",
113
if (tmp->tcs_handle == tcs_handle) {
114
ret = tmp->blob ? &tmp->blob->pubKey : NULL;
119
LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
123
/* only called from load key paths, so no locking */
125
mc_set_parent_by_handle(TCS_KEY_HANDLE tcs_handle, TCS_KEY_HANDLE p_tcs_handle)
127
struct key_mem_cache *tmp, *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) {
138
/* didn't find parent */
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;
150
return TCSERR(TSS_E_FAIL);
154
ensureKeyIsLoaded(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE keyHandle, TCPA_KEY_HANDLE * keySlot)
156
TCPA_RESULT result = TSS_SUCCESS;
157
TCPA_STORE_PUBKEY *myPub;
159
LogDebugFn("0x%x", keyHandle);
161
if (!ctx_has_key_loaded(hContext, keyHandle))
162
return TCSERR(TCS_E_INVALID_KEY);
164
MUTEX_LOCK(mem_cache_lock);
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);
176
LogDebugFn("calling LoadKeyShim");
177
if ((result = LoadKeyShim(hContext, myPub, NULL, keySlot))) {
178
LogDebug("Failed shim");
182
if (*keySlot == NULL_TPM_HANDLE) {
183
LogDebug("Key slot is still invalid after ensureKeyIsLoaded");
184
result = TCSERR(TCS_E_KM_LOADFAILED);
188
mc_update_time_stamp(*keySlot);
191
MUTEX_UNLOCK(mem_cache_lock);
197
/* only called from load key paths, so no locking */
199
mc_get_uuid_by_pub(TCPA_STORE_PUBKEY *pub)
202
struct key_mem_cache *tmp;
204
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
205
LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
207
tmp->blob->pubKey.keyLength == pub->keyLength &&
208
!memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
218
mc_get_handles_by_uuid(TSS_UUID *uuid, TCS_KEY_HANDLE *tcsHandle, TCPA_KEY_HANDLE *slot)
220
struct key_mem_cache *tmp;
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;
230
return TCSERR(TSS_E_FAIL);
234
mc_get_handle_by_encdata(BYTE *encData)
236
struct key_mem_cache *tmp;
239
MUTEX_LOCK(mem_cache_lock);
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)
245
if (!memcmp(tmp->blob->encData, encData, tmp->blob->encSize)) {
246
ret = tmp->tcs_handle;
247
MUTEX_UNLOCK(mem_cache_lock);
251
MUTEX_UNLOCK(mem_cache_lock);
256
mc_update_encdata(BYTE *encData, BYTE *newEncData)
258
struct key_mem_cache *tmp;
261
MUTEX_LOCK(mem_cache_lock);
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)
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);
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);
282
MUTEX_UNLOCK(mem_cache_lock);
283
LogError("Couldn't find requested encdata in mem cache");
284
return TCSERR(TSS_E_INTERNAL_ERROR);
288
* only called from load key paths and the init (single thread time) path,
292
mc_add_entry(TCS_KEY_HANDLE tcs_handle,
293
TCPA_KEY_HANDLE tpm_handle,
296
struct key_mem_cache *entry, *tmp;
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) {
306
/* Not found - we need to create a new entry */
307
entry = (struct key_mem_cache *)calloc(1, sizeof(struct key_mem_cache));
309
LogError("malloc of %zd bytes failed.", sizeof(struct key_mem_cache));
310
return TCSERR(TSS_E_OUTOFMEMORY);
313
entry->tcs_handle = tcs_handle;
314
if (tpm_handle != NULL_TPM_HANDLE)
315
entry->time_stamp = getNextTimeStamp();
317
entry->tpm_handle = tpm_handle;
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));
327
return TCSERR(TSS_E_OUTOFMEMORY);
329
memcpy(entry->blob, key_blob, sizeof(TSS_KEY));
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);
338
return TCSERR(TSS_E_OUTOFMEMORY);
340
memcpy(tmp_parms, key_blob->algorithmParms.parms, key_blob->algorithmParms.parmSize);
341
entry->blob->algorithmParms.parms = tmp_parms;
343
entry->blob->algorithmParms.parmSize = key_blob->algorithmParms.parmSize;
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);
353
return TCSERR(TSS_E_OUTOFMEMORY);
355
memcpy(entry->blob->pubKey.key, key_blob->pubKey.key, key_blob->pubKey.keyLength);
357
entry->blob->pubKey.keyLength = key_blob->pubKey.keyLength;
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);
368
return TCSERR(TSS_E_OUTOFMEMORY);
370
memcpy(entry->blob->PCRInfo, key_blob->PCRInfo, key_blob->PCRInfoSize);
372
entry->blob->PCRInfoSize = key_blob->PCRInfoSize;
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);
384
return TCSERR(TSS_E_OUTOFMEMORY);
386
memcpy(entry->blob->encData, key_blob->encData, key_blob->encSize);
388
entry->blob->encSize = key_blob->encSize;
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. */
399
key_mem_cache_head->prev = entry;
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. */
405
key_mem_cache_head = entry;
410
/* caller must lock the mem cache before calling! */
412
mc_remove_entry(TCS_KEY_HANDLE tcs_handle)
414
struct key_mem_cache *cur;
416
for (cur = key_mem_cache_head; cur; cur = cur->next) {
417
if (cur->tcs_handle == tcs_handle) {
419
destroy_key_refs(cur->blob);
423
if (cur->prev != NULL)
424
cur->prev->next = cur->next;
425
if (cur->next != NULL)
426
cur->next->prev = cur->prev;
428
if (cur == key_mem_cache_head)
429
key_mem_cache_head = cur->next;
436
return TCSERR(TSS_E_FAIL);
440
mc_add_entry_init(TCS_KEY_HANDLE tcs_handle,
441
TCPA_KEY_HANDLE tpm_handle,
445
struct key_mem_cache *entry, *tmp;
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);
454
MUTEX_UNLOCK(mem_cache_lock);
456
/* Not found - we need to create a new entry */
457
entry = (struct key_mem_cache *)calloc(1, sizeof(struct key_mem_cache));
459
LogError("malloc of %zd bytes failed.", sizeof(struct key_mem_cache));
460
return TCSERR(TSS_E_OUTOFMEMORY);
463
entry->tcs_handle = tcs_handle;
464
if (tpm_handle != NULL_TPM_HANDLE)
465
entry->time_stamp = getNextTimeStamp();
467
entry->tpm_handle = tpm_handle;
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));
475
return TCSERR(TSS_E_OUTOFMEMORY);
478
memcpy(entry->blob, key_blob, sizeof(TSS_KEY));
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);
488
return TCSERR(TSS_E_OUTOFMEMORY);
490
memcpy(tmp_parms, key_blob->algorithmParms.parms,
491
key_blob->algorithmParms.parmSize);
492
entry->blob->algorithmParms.parms = tmp_parms;
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);
501
return TCSERR(TSS_E_OUTOFMEMORY);
503
memcpy(entry->blob->pubKey.key, key_blob->pubKey.key, key_blob->pubKey.keyLength);
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);
513
return TCSERR(TSS_E_OUTOFMEMORY);
515
memcpy(entry->blob->encData, key_blob->encData, key_blob->encSize);
517
entry->blob->encSize = key_blob->encSize;
520
memcpy(&entry->uuid, uuid, sizeof(TSS_UUID));
522
MUTEX_LOCK(mem_cache_lock);
524
entry->next = key_mem_cache_head;
525
if (key_mem_cache_head)
526
key_mem_cache_head->prev = entry;
529
key_mem_cache_head = entry;
530
MUTEX_UNLOCK(mem_cache_lock);
535
/* only called from evict key paths, so no locking */
537
mc_set_slot_by_slot(TCPA_KEY_HANDLE old_handle, TCPA_KEY_HANDLE new_handle)
539
struct key_mem_cache *tmp;
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)
549
tmp->time_stamp = getNextTimeStamp();
550
tmp->tpm_handle = new_handle;
555
return TCSERR(TSS_E_FAIL);
558
/* only called from load key paths, so no locking */
560
mc_set_slot_by_handle(TCS_KEY_HANDLE tcs_handle, TCPA_KEY_HANDLE tpm_handle)
562
struct key_mem_cache *tmp;
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)
570
tmp->time_stamp = getNextTimeStamp();
571
tmp->tpm_handle = tpm_handle;
576
return TCSERR(TSS_E_FAIL);
579
/* the beginnings of a key manager start here ;-) */
582
key_mgr_evict(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hKey)
584
TSS_RESULT result = TCS_SUCCESS;
586
if ((result = ctx_remove_key_loaded(hContext, hKey)))
589
if ((result = key_mgr_dec_ref_count(hKey)))
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)
604
MUTEX_LOCK(mem_cache_lock);
606
if (TPM_VERSION_IS(1,2)) {
607
result = TCSP_LoadKey2ByBlob_Internal(hContext, hUnwrappingKey, cWrappedKeyBlob,
608
rgbWrappedKeyBlob, pAuth, phKeyTCSI);
610
result = TCSP_LoadKeyByBlob_Internal(hContext, hUnwrappingKey, cWrappedKeyBlob,
611
rgbWrappedKeyBlob, pAuth, phKeyTCSI,
615
MUTEX_UNLOCK(mem_cache_lock);
620
/* create a reference to one key. This is called from the key_mgr_load_*
621
* functions only, so no locking is done.
624
key_mgr_inc_ref_count(TCS_KEY_HANDLE key_handle)
626
struct key_mem_cache *cur;
628
for (cur = key_mem_cache_head; cur; cur = cur->next) {
629
LogDebugFn("TCSD mem_cached handle: 0x%x", cur->tcs_handle);
630
if (cur->tcs_handle == key_handle) {
636
return TCSERR(TSS_E_FAIL);
639
/* de-reference one key. This is called by the context routines, so
640
* locking is necessary.
643
key_mgr_dec_ref_count(TCS_KEY_HANDLE key_handle)
645
struct key_mem_cache *cur;
647
MUTEX_LOCK(mem_cache_lock);
649
for (cur = key_mem_cache_head; cur; cur = cur->next) {
650
if (cur->tcs_handle == key_handle) {
652
LogDebugFn("decrementing ref cnt for key 0x%x",
654
MUTEX_UNLOCK(mem_cache_lock);
659
MUTEX_UNLOCK(mem_cache_lock);
660
return TCSERR(TSS_E_FAIL);
663
/* run through the global list and free any keys with reference counts of 0 */
667
struct key_mem_cache *tmp, *cur;
669
MUTEX_LOCK(mem_cache_lock);
671
for (cur = key_mem_cache_head; cur;) {
672
if (cur->ref_cnt == 0) {
673
if (cur->tpm_handle != NULL_TPM_HANDLE) {
674
LogDebugFn("Key 0x%x being freed from TPM", cur->tpm_handle);
675
internal_EvictByKeySlot(cur->tpm_handle);
677
LogDebugFn("Key 0x%x being freed", cur->tcs_handle);
679
destroy_key_refs(cur->blob);
682
if (cur->prev != NULL)
683
cur->prev->next = cur->next;
684
if (cur->next != NULL)
685
cur->next->prev = cur->prev;
688
if (cur == key_mem_cache_head)
689
key_mem_cache_head = cur->next;
697
MUTEX_UNLOCK(mem_cache_lock);
700
/* only called from load key paths, so no locking */
702
mc_get_slot_by_handle(TCS_KEY_HANDLE tcs_handle)
704
struct key_mem_cache *tmp;
707
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
708
LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
709
if (tmp->tcs_handle == tcs_handle) {
710
ret = tmp->tpm_handle;
715
LogDebugFn("returning NULL_TPM_HANDLE");
716
return NULL_TPM_HANDLE;
719
/* called from functions outside the load key path */
721
mc_get_slot_by_handle_lock(TCS_KEY_HANDLE tcs_handle)
723
struct key_mem_cache *tmp;
726
MUTEX_LOCK(mem_cache_lock);
728
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
729
LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
730
if (tmp->tcs_handle == tcs_handle) {
731
ret = tmp->tpm_handle;
732
MUTEX_UNLOCK(mem_cache_lock);
737
MUTEX_UNLOCK(mem_cache_lock);
738
LogDebugFn("returning NULL_TPM_HANDLE");
739
return NULL_TPM_HANDLE;
742
/* only called from load key paths, so no locking */
744
mc_get_slot_by_pub(TCPA_STORE_PUBKEY *pub)
746
struct key_mem_cache *tmp;
749
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
750
LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
752
!memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
753
ret = tmp->tpm_handle;
758
LogDebugFn("returning NULL_TPM_HANDLE");
759
return NULL_TPM_HANDLE;
762
/* Check the mem cache for a key with public key pub. If a parent TCS key handle
763
* is passed in, make sure the parent of the key find matches it, else return
765
/* only called from load key paths, so no locking */
767
mc_get_handle_by_pub(TCPA_STORE_PUBKEY *pub, TCS_KEY_HANDLE parent)
769
struct key_mem_cache *tmp;
771
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
772
LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
774
pub->keyLength == tmp->blob->pubKey.keyLength &&
775
!memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
779
if (parent == tmp->parent->tcs_handle)
780
return tmp->tcs_handle;
782
return tmp->tcs_handle;
786
LogDebugFn("returning NULL_TCS_HANDLE");
787
return NULL_TCS_HANDLE;
790
/* only called from load key paths, so no locking */
792
mc_get_parent_pub_by_pub(TCPA_STORE_PUBKEY *pub)
794
struct key_mem_cache *tmp;
795
TCPA_STORE_PUBKEY *ret = NULL;
797
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
798
LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
799
if (tmp->tcs_handle == TPM_KEYHND_SRK) {
800
LogDebugFn("skipping the SRK");
804
!memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
805
if (tmp->parent && tmp->parent->blob) {
806
ret = &tmp->parent->blob->pubKey;
807
LogDebugFn("Success");
809
LogError("parent pointer not set in key mem cache object w/ TCS "
810
"handle: 0x%x", tmp->tcs_handle);
816
LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
820
/* only called from load key paths, so no locking */
822
mc_get_blob_by_pub(TCPA_STORE_PUBKEY *pub, TSS_KEY **ret_key)
824
struct key_mem_cache *tmp;
826
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
827
LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
829
!memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
830
*ret_key = tmp->blob;
835
LogDebugFn("returning TSS_E_FAIL");
836
return TCSERR(TSS_E_FAIL);
839
/* only called from load key paths, so no locking */
841
mc_get_handle_by_slot(TCPA_KEY_HANDLE tpm_handle)
843
struct key_mem_cache *tmp;
846
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
847
LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
848
if (tmp->tpm_handle == tpm_handle) {
849
ret = tmp->tcs_handle;
854
return NULL_TCS_HANDLE;
857
/* only called from load key paths, so no locking */
859
mc_update_time_stamp(TCPA_KEY_HANDLE tpm_handle)
861
struct key_mem_cache *tmp;
862
TSS_RESULT ret = TCSERR(TSS_E_FAIL);
864
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
865
LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
866
if (tmp->tpm_handle == tpm_handle) {
867
tmp->time_stamp = getNextTimeStamp();
876
/* Right now this evicts the LRU key assuming it's not the parent */
878
evictFirstKey(TCS_KEY_HANDLE parent_tcs_handle)
880
struct key_mem_cache *tmp;
881
TCS_KEY_HANDLE tpm_handle_to_evict = NULL_TPM_HANDLE;
882
UINT32 smallestTimeStamp = ~(0U); /* largest */
886
/* First, see if there are any known keys worth evicting */
887
if ((result = clearUnknownKeys(InternalContext, &count)))
891
LogDebugFn("Evicted %u unknown keys", count);
895
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
896
if (tmp->tpm_handle != NULL_TPM_HANDLE && /* not already evicted */
897
tmp->tpm_handle != SRK_TPM_HANDLE && /* not the srk */
898
tmp->tcs_handle != parent_tcs_handle && /* not my parent */
899
tmp->time_stamp < smallestTimeStamp) { /* is the smallest time
901
tpm_handle_to_evict = tmp->tpm_handle;
902
smallestTimeStamp = tmp->time_stamp;
906
if (tpm_handle_to_evict != NULL_TCS_HANDLE) {
907
if ((result = internal_EvictByKeySlot(tpm_handle_to_evict)))
910
LogDebugFn("Evicted key w/ TPM handle 0x%x", tpm_handle_to_evict);
911
result = mc_set_slot_by_slot(tpm_handle_to_evict, NULL_TPM_HANDLE);
919
isKeyLoaded(TCPA_KEY_HANDLE keySlot)
923
TCPA_KEY_HANDLE_LIST keyList;
928
if (keySlot == SRK_TPM_HANDLE) {
932
if ((result = TCSP_GetCapability_Internal(InternalContext, TCPA_CAP_KEY_HANDLE, 0, NULL,
937
UnloadBlob_KEY_HANDLE_LIST(&offset, resp, &keyList);
939
for (i = 0; i < keyList.loaded; i++) {
940
LogDebugFn("loaded TPM key handle: 0x%x", keyList.handle[i]);
941
if (keyList.handle[i] == keySlot) {
942
free(keyList.handle);
947
free(keyList.handle);
950
LogDebugFn("Key is not loaded, changing slot");
951
mc_set_slot_by_slot(keySlot, NULL_TPM_HANDLE);
955
/* all calls to LoadKeyShim are inside locks */
957
LoadKeyShim(TCS_CONTEXT_HANDLE hContext, TCPA_STORE_PUBKEY *pubKey,
958
TSS_UUID *parentUuid, TCPA_KEY_HANDLE *slotOut)
961
TCPA_STORE_PUBKEY *parentPub;
963
TCPA_KEY_HANDLE keySlot;
964
TCPA_KEY_HANDLE parentSlot;
965
TCS_KEY_HANDLE tcsKeyHandle;
968
TCS_KEY_HANDLE parentHandle;
971
LogDebugFn("calling mc_get_slot_by_pub");
973
/* If I'm loaded, then no point being here. Get the slot and return */
974
keySlot = mc_get_slot_by_pub(pubKey);
975
if (keySlot != NULL_TPM_HANDLE && isKeyLoaded(keySlot)) {
981
* Before proceeding, the parent must be loaded.
982
* If the parent is registered, then it can be loaded by UUID.
983
* If not, then the shim will be called to load it's parent and then try
984
* to load it based on the persistent store.
987
LogDebugFn("calling mc_get_parent_pub_by_pub");
988
/* Check if the Key is in the memory cache */
989
if ((parentPub = mc_get_parent_pub_by_pub(pubKey)) == NULL) {
991
LogDebugFn("parentPub is NULL");
992
/* If parentUUID is not handed in, then this key was never loaded and isn't reg'd */
993
if (parentUuid == NULL)
994
return TCSERR(TCS_E_KM_LOADFAILED);
996
LogDebugFn("calling TCSP_LoadKeyByUUID_Internal");
997
/* This will try to load my parent by UUID */
998
if ((result = TCSP_LoadKeyByUUID_Internal(hContext, parentUuid, NULL, &parentSlot)))
1001
return TCSERR(TCS_E_KM_LOADFAILED);
1004
LogDebugFn("calling LoadKeyShim");
1005
if ((result = LoadKeyShim(hContext, parentPub, NULL, &parentSlot)))
1010
* Now that the parent is loaded, I can load myself.
1011
* If I'm registered, that's by UUID. If I'm not,
1012
* that's by blob. If there is no persistent storage data, then I cannot be
1013
* loaded by blob. The user must have some point loaded this key manually.
1016
/* check the mem cache */
1017
if (mc_get_blob_by_pub(pubKey, &myKey) == TSS_SUCCESS) {
1018
parentHandle = mc_get_handle_by_slot(parentSlot);
1019
if (parentHandle == 0)
1020
return TCSERR(TCS_E_KM_LOADFAILED);
1023
LoadBlob_TSS_KEY(&offset, keyBlob, myKey);
1024
if ((result = TCSP_LoadKeyByBlob_Internal(hContext, parentHandle, offset, keyBlob,
1025
NULL, &tcsKeyHandle, slotOut)))
1028
return ctx_mark_key_loaded(hContext, tcsKeyHandle);
1033
/* check registered */
1034
if (ps_is_pub_registered(pubKey) == FALSE)
1035
return TCSERR(TCS_E_KM_LOADFAILED);
1036
//uuid = mc_get_uuid_by_pub(pubKey); // XXX pub is not in MC
1037
if ((result = ps_get_uuid_by_pub(pubKey, &uuid)))
1040
if ((result = TCSP_LoadKeyByUUID_Internal(hContext, uuid, NULL, &tcsKeyHandle))) {
1045
*slotOut = mc_get_slot_by_handle(tcsKeyHandle);
1047
return ctx_mark_key_loaded(hContext, tcsKeyHandle);
1051
return TCSERR(TCS_E_KM_LOADFAILED);
1057
TSS_RESULT result = TSS_SUCCESS;
1058
TCPA_KEY_HANDLE_LIST keyList = { 0, NULL };
1059
BYTE *respData = NULL, ownerEvictCtr = 0;
1060
UINT32 respDataSize = 0, i;
1063
/* If we're a 1.1 TPM, we can exit immediately since only 1.2+ supports owner evict */
1064
if (TPM_VERSION_IS(1,1))
1067
if ((result = TCSP_GetCapability_Internal(InternalContext, TPM_CAP_KEY_HANDLE, 0, NULL,
1068
&respDataSize, &respData)))
1071
if ((result = UnloadBlob_KEY_HANDLE_LIST(&offset, respData, &keyList))) {
1077
for (i = 0; i < keyList.loaded; i++) {
1081
LoadBlob_UINT32(&offset, keyList.handle[i], (BYTE *)&keyHandle);
1082
/* get the ownerEvict flag for this key handle */
1083
if ((result = TCSP_GetCapability_Internal(InternalContext, TPM_CAP_KEY_STATUS,
1084
sizeof(UINT32), (BYTE *)&keyHandle,
1085
&respDataSize, &respData))) {
1086
free(keyList.handle);
1090
if (*(TPM_BOOL *)respData == TRUE) {
1091
TSS_UUID uuid = TSS_UUID_OWNEREVICT(ownerEvictCtr);
1093
LogDebugFn("Found an owner evict key, assigned uuid %hhu", ownerEvictCtr);
1094
if ((result = mc_add_entry_init(getNextTcsKeyHandle(), keyList.handle[i],
1096
free(keyList.handle);
1106
/* find next lowest OWNEREVICT uuid */
1108
mc_find_next_ownerevict_uuid(TSS_UUID *uuid)
1110
TCS_KEY_HANDLE tmpKey;
1111
TCPA_KEY_HANDLE tmpSlot;
1113
TSS_RESULT result = TCSERR(TSS_E_FAIL);
1115
MUTEX_LOCK(mem_cache_lock);
1117
for (seed = 0; seed <= 255; seed++) {
1118
TSS_UUID tmpUuid = TSS_UUID_OWNEREVICT(seed);
1120
/* if UUID is found, continue on, trying the next UUID */
1121
if (!mc_get_handles_by_uuid(&tmpUuid, &tmpKey, &tmpSlot))
1124
/* UUID is not found, so its the first one available */
1125
memcpy(uuid, &tmpUuid, sizeof(TSS_UUID));
1126
result = TSS_SUCCESS;
1130
MUTEX_UNLOCK(mem_cache_lock);
1135
mc_set_uuid(TCS_KEY_HANDLE tcs_handle, TSS_UUID *uuid)
1137
struct key_mem_cache *tmp;
1138
TSS_RESULT result = TCSERR(TSS_E_FAIL);
1140
MUTEX_LOCK(mem_cache_lock);
1142
LogDebugFn("looking for 0x%x", tcs_handle);
1144
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
1145
LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
1146
if (tmp->tcs_handle == tcs_handle) {
1147
LogDebugFn("Handle found, re-setting UUID");
1148
memcpy(&tmp->uuid, uuid, sizeof(TSS_UUID));
1149
result = TSS_SUCCESS;
1153
MUTEX_UNLOCK(mem_cache_lock);