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