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 <string.h> 13 14 #include "trousers/tss.h" 15 #include "trousers_types.h" 16 #include "req_mgr.h" 17 #include "tcs_tsp.h" 18 #include "tcslog.h" 19 #include "tcs_utils.h" 20 #include "tcs_int_literals.h" 21 22 struct key_mem_cache *key_mem_cache_head = NULL; 23 24 TSS_UUID NULL_UUID = { 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0 } }; 25 26 27 TSS_RESULT 28 add_cache_entry(TCS_CONTEXT_HANDLE hContext, 29 BYTE* blob, 30 TCS_KEY_HANDLE hParent, 31 TPM_KEY_HANDLE hSlot, 32 TCS_KEY_HANDLE* new) 33 { 34 UINT64 offset; 35 TSS_RESULT result; 36 TCS_KEY_HANDLE tcsHandle; 37 TSS_KEY key, *pKey; 38 39 if (!blob) { 40 pKey = NULL; 41 } else { 42 offset = 0; 43 if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key))) 44 return result; 45 46 if ((tcsHandle = mc_get_handle_by_pub(&key.pubKey, hParent)) == NULL_TCS_HANDLE) { 47 pKey = &key; 48 } else { 49 mc_set_slot_by_handle(tcsHandle, hSlot); 50 *new = tcsHandle; 51 goto done; 52 } 53 } 54 55 LogDebugFn("No existing key handle for this key, creating new one..."); 56 /* Get a new TCS Key Handle */ 57 tcsHandle = getNextTcsKeyHandle(); 58 LogDebugFn("calling mc_add_entry, TCS handle: 0x%x, TPM handle 0x%x", tcsHandle, hSlot); 59 60 if ((result = mc_add_entry(tcsHandle, hSlot, pKey))) 61 goto done; 62 63 LogDebugFn("ctx_mark_key_loaded"); 64 if (ctx_mark_key_loaded(hContext, tcsHandle)) { 65 LogError("Error marking key as loaded"); 66 result = TCSERR(TSS_E_INTERNAL_ERROR); 67 goto done; 68 } 69 70 if ((result = mc_set_parent_by_handle(tcsHandle, hParent))) { 71 LogError("mc_set_parent_by_handle failed."); 72 goto done; 73 } 74 75 *new = tcsHandle; 76 done: 77 if (blob) 78 destroy_key_refs(&key); 79 return result; 80 } 81 82 /* Check that the context has this key loaded and return the associated slot. Do not search PS if 83 * the key is not found */ 84 TSS_RESULT 85 get_slot_lite(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hKey, TPM_KEY_HANDLE *out) 86 { 87 if (ctx_has_key_loaded(hContext, hKey)) { 88 if ((*out = mc_get_slot_by_handle(hKey)) == NULL_TPM_HANDLE) 89 return TCSERR(TCS_E_INVALID_KEY); 90 91 return TSS_SUCCESS; 92 } 93 94 return TCSERR(TCS_E_INVALID_KEY); 95 } 96 97 /* XXX Can get_slot be merged with ensureKeyIsLoaded? */ 98 99 /* Given a handle, get_slot searches the mem cache for a mapping to a TPM handle. If there is no 100 * mapping, it looks up the pub key of the handle and attempts to load it by finding its pub key 101 * in the persistent store. If that's not found, return error. */ 102 TSS_RESULT 103 get_slot(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hKey, TPM_KEY_HANDLE *out) 104 { 105 TSS_RESULT result = TSS_SUCCESS; 106 TPM_STORE_PUBKEY *pub = NULL; 107 TPM_KEY_HANDLE slot; 108 109 LogDebugFn("calling mc_get_slot_by_handle"); 110 if ((slot = mc_get_slot_by_handle(hKey)) == NULL_TPM_HANDLE) { 111 LogDebugFn("calling mc_get_pub_by_slot"); 112 if ((pub = mc_get_pub_by_slot(hKey)) == NULL) 113 return TCSERR(TCS_E_KM_LOADFAILED); 114 115 LogDebugFn("calling LoadKeyShim"); 116 /* Otherwise, try to load it using the shim */ 117 result = LoadKeyShim(hContext, pub, NULL, &slot); 118 } 119 120 if (!result) 121 *out = slot; 122 123 return result; 124 } 125 126 /* load_key_init is the common entry point for all load key requests to the TCSD. These can come in 127 * as straight load or load2 requests, or through a transport session. 128 * 129 * We'll always attempt to load the key if 130 * A) It requires auth (load should fail if auth is bad, even when its already been loaded by 131 * another thread) 132 * B) Its in a transport session (the key blob is encrypted) 133 * 134 * Otherwise if the key is already loaded by another thread and it doesn't require auth, then we 135 * will just set *load_key to FALSE, telling the caller that there's no need to send anything to 136 * the TPM. 137 */ 138 TSS_RESULT 139 load_key_init(TPM_COMMAND_CODE ord, 140 TCS_CONTEXT_HANDLE hContext, 141 TCS_KEY_HANDLE parent_handle, 142 UINT32 blob_size, 143 BYTE* blob, 144 TSS_BOOL encrypted, 145 TPM_AUTH* auth, 146 TSS_BOOL* load_key, 147 UINT64* out_len, 148 BYTE* out, 149 TCS_KEY_HANDLE* handle, 150 TPM_KEY_HANDLE* slot) 151 { 152 TSS_RESULT result = TSS_SUCCESS; 153 TSS_KEY key; 154 UINT64 offset; 155 TPM_KEY_HANDLE tpm_slot; 156 TCS_KEY_HANDLE tcs_handle; 157 TSS_BOOL canLoad; 158 159 160 if (!encrypted) { 161 offset = 0; 162 memset(&key, 0, sizeof(TSS_KEY)); 163 if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key))) 164 return result; 165 } 166 167 if (!auth && !encrypted) { 168 LogDebugFn("Checking if LoadKeyByBlob can be avoided by using existing key"); 169 170 if ((tcs_handle = mc_get_handle_by_pub(&key.pubKey, parent_handle))) { 171 LogDebugFn("tcs key handle exists"); 172 173 tpm_slot = mc_get_slot_by_handle(tcs_handle); 174 if (tpm_slot && (isKeyLoaded(tpm_slot) == TRUE)) { 175 LogDebugFn("Don't need to reload this key."); 176 *handle = tcs_handle; 177 *slot = tpm_slot; 178 *load_key = FALSE; 179 goto done; 180 } 181 } 182 } 183 *load_key = TRUE; 184 185 LogDebugFn("calling canILoadThisKey"); 186 if (!encrypted) { 187 if ((result = canILoadThisKey(&(key.algorithmParms), &canLoad))) 188 goto error; 189 190 if (canLoad == FALSE) { 191 LogDebugFn("calling evictFirstKey"); 192 /* Evict a key that isn't the parent */ 193 if ((result = evictFirstKey(parent_handle))) 194 goto error; 195 } 196 } 197 198 error: 199 if (!encrypted) 200 destroy_key_refs(&key); 201 done: 202 return result; 203 } 204 205 TSS_RESULT 206 load_key_final(TCS_CONTEXT_HANDLE hContext, 207 TCS_KEY_HANDLE parent_handle, 208 TCS_KEY_HANDLE* tcs_handle, 209 BYTE* blob, 210 TPM_KEY_HANDLE slot) 211 { 212 if (*tcs_handle == NULL_TCS_HANDLE) 213 return add_cache_entry(hContext, blob, parent_handle, slot, tcs_handle); 214 else 215 return mc_set_slot_by_handle(*tcs_handle, slot); 216 } 217 218 TSS_RESULT 219 canILoadThisKey(TCPA_KEY_PARMS *parms, TSS_BOOL *b) 220 { 221 UINT16 subCapLength; 222 UINT64 offset; 223 BYTE subCap[100]; 224 TCPA_RESULT result; 225 UINT32 respDataLength; 226 BYTE *respData; 227 228 offset = 0; 229 LoadBlob_KEY_PARMS(&offset, subCap, parms); 230 subCapLength = offset; 231 232 if ((result = TCSP_GetCapability_Internal(InternalContext, TCPA_CAP_CHECK_LOADED, 233 subCapLength, subCap, &respDataLength, 234 &respData))) { 235 *b = FALSE; 236 LogDebugFn("NO"); 237 return result; 238 } 239 240 *b = respData[0]; 241 free(respData); 242 LogDebugFn("%s", *b ? "YES" : "NO"); 243 244 return TSS_SUCCESS; 245 } 246 247 TCPA_RESULT 248 internal_EvictByKeySlot(TCPA_KEY_HANDLE slot) 249 { 250 TCPA_RESULT result; 251 UINT32 paramSize; 252 UINT64 offset; 253 BYTE txBlob[TSS_TPM_TXBLOB_SIZE]; 254 255 LogDebug("Entering Evict Key"); 256 257 #ifdef TSS_BUILD_TSS12 258 if (TPM_VERSION_IS(1,2)) { 259 LogDebugFn("Evicting key using FlushSpecific for TPM 1.2"); 260 261 return TCSP_FlushSpecific_Common(slot, TPM_RT_KEY); 262 } 263 #endif 264 265 offset = 10; 266 LoadBlob_UINT32(&offset, slot, txBlob); 267 LoadBlob_Header(TPM_TAG_RQU_COMMAND, offset, TPM_ORD_EvictKey, txBlob); 268 269 if ((result = req_mgr_submit_req(txBlob))) 270 return result; 271 272 result = UnloadBlob_Header(txBlob, ¶mSize); 273 274 LogResult("Evict Key", result); 275 return result; 276 } 277 278 TSS_RESULT 279 clearUnknownKeys(TCS_CONTEXT_HANDLE hContext, UINT32 *cleared) 280 { 281 TSS_RESULT result = TSS_SUCCESS; 282 TCPA_KEY_HANDLE_LIST keyList = { 0, NULL }; 283 int i; 284 BYTE *respData = NULL; 285 UINT32 respDataSize = 0, count = 0; 286 TCPA_CAPABILITY_AREA capArea = -1; 287 UINT64 offset = 0; 288 TSS_BOOL found = FALSE; 289 struct key_mem_cache *tmp; 290 291 capArea = TCPA_CAP_KEY_HANDLE; 292 293 if ((result = TCSP_GetCapability_Internal(hContext, capArea, 0, NULL, &respDataSize, 294 &respData))) 295 return result; 296 297 if ((result = UnloadBlob_KEY_HANDLE_LIST(&offset, respData, &keyList))) 298 goto done; 299 300 #ifdef TSS_DEBUG 301 LogDebug("Loaded TPM key handles:"); 302 for (i = 0; i < keyList.loaded; i++) { 303 LogDebugFn("%d: %x", i, keyList.handle[i]); 304 } 305 306 LogDebug("Loaded TCSD key handles:"); 307 i=0; 308 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) { 309 LogDebugFn("%d: 0x%x -> 0x%x", i++, tmp->tpm_handle, 310 tmp->tcs_handle); 311 } 312 #endif 313 314 for (i = 0; i < keyList.loaded; i++) { 315 /* as long as we're only called from evictFirstKey(), we don't 316 * need to lock here */ 317 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) { 318 if (tmp->tpm_handle == keyList.handle[i]) { 319 found = TRUE; 320 break; 321 } 322 } 323 if (found) 324 found = FALSE; 325 else { 326 if ((result = internal_EvictByKeySlot(keyList.handle[i]))) 327 goto done; 328 else 329 count++; 330 } 331 } 332 333 *cleared = count; 334 done: 335 free(keyList.handle); 336 free(respData); 337 338 return TSS_SUCCESS; 339 } 340 341 #if 0 342 TCPA_RESULT 343 clearKeysFromChip(TCS_CONTEXT_HANDLE hContext) 344 { 345 TCPA_RESULT result; 346 TCPA_KEY_HANDLE_LIST keyList; 347 UINT32 i; 348 BYTE *respData = 0; 349 UINT32 respDataSize = 0; 350 TCPA_CAPABILITY_AREA capArea = -1; 351 UINT64 offset = 0; 352 353 capArea = TCPA_CAP_KEY_HANDLE; 354 355 if ((result = TCSP_GetCapability_Internal(hContext, capArea, 0, NULL, 356 &respDataSize, &respData))) 357 return result; 358 359 if ((result = UnloadBlob_KEY_HANDLE_LIST(&offset, respData, &keyList))) 360 return result; 361 for (i = 0; i < keyList.loaded; i++) { 362 if (keyList.handle[i] == SRK_TPM_HANDLE || /*can't evict SRK */ 363 keyList.handle[i] == EK_TPM_HANDLE) /*can't evict EK */ 364 continue; 365 if ((result = internal_EvictByKeySlot(keyList.handle[i]))) 366 return result; 367 } 368 return TSS_SUCCESS; 369 } 370 #endif 371 372 void 373 LoadBlob_KEY_PARMS(UINT64 *offset, BYTE *blob, TCPA_KEY_PARMS *keyInfo) 374 { 375 LoadBlob_UINT32(offset, keyInfo->algorithmID, blob); 376 LoadBlob_UINT16(offset, keyInfo->encScheme, blob); 377 LoadBlob_UINT16(offset, keyInfo->sigScheme, blob); 378 LoadBlob_UINT32(offset, keyInfo->parmSize, blob); 379 LoadBlob(offset, keyInfo->parmSize, blob, keyInfo->parms); 380 } 381 382 TSS_RESULT 383 UnloadBlob_STORE_PUBKEY(UINT64 *offset, BYTE *blob, TCPA_STORE_PUBKEY *store) 384 { 385 if (!store) { 386 UINT32 keyLength; 387 388 UnloadBlob_UINT32(offset, &keyLength, blob); 389 390 if (keyLength > 0) 391 UnloadBlob(offset, keyLength, blob, NULL); 392 393 return TSS_SUCCESS; 394 } 395 396 UnloadBlob_UINT32(offset, &store->keyLength, blob); 397 398 if (store->keyLength == 0) { 399 store->key = NULL; 400 LogWarn("Unloading a public key of size 0!"); 401 } else { 402 store->key = (BYTE *)malloc(store->keyLength); 403 if (store->key == NULL) { 404 LogError("malloc of %u bytes failed.", store->keyLength); 405 store->keyLength = 0; 406 return TCSERR(TSS_E_OUTOFMEMORY); 407 } 408 409 UnloadBlob(offset, store->keyLength, blob, store->key); 410 } 411 412 return TSS_SUCCESS; 413 } 414 415 void 416 LoadBlob_STORE_PUBKEY(UINT64 *offset, BYTE * blob, TCPA_STORE_PUBKEY * store) 417 { 418 LoadBlob_UINT32(offset, store->keyLength, blob); 419 LoadBlob(offset, store->keyLength, blob, store->key); 420 } 421 422 TSS_RESULT 423 UnloadBlob_TSS_KEY(UINT64 *offset, BYTE *blob, TSS_KEY *key) 424 { 425 TSS_RESULT rc; 426 427 if (!key) { 428 UINT32 size; 429 430 /* TPM_KEY's ver and TPM_KEY12's tag/file are 431 the same size, so... */ 432 UnloadBlob_VERSION(offset, blob, NULL); 433 UnloadBlob_UINT16(offset, NULL, blob); 434 UnloadBlob_KEY_FLAGS(offset, blob, NULL); 435 UnloadBlob_BOOL(offset, NULL, blob); 436 if ((rc = UnloadBlob_KEY_PARMS(offset, blob, NULL))) 437 return rc; 438 UnloadBlob_UINT32(offset, &size, blob); 439 440 if (size > 0) 441 UnloadBlob(offset, size, blob, NULL); 442 443 if ((rc = UnloadBlob_STORE_PUBKEY(offset, blob, NULL))) 444 return rc; 445 446 UnloadBlob_UINT32(offset, &size, blob); 447 448 if (size > 0) 449 UnloadBlob(offset, size, blob, NULL); 450 451 return TSS_SUCCESS; 452 } 453 454 if (key->hdr.key12.tag == TPM_TAG_KEY12) { 455 UnloadBlob_UINT16(offset, &key->hdr.key12.tag, blob); 456 UnloadBlob_UINT16(offset, &key->hdr.key12.fill, blob); 457 } else 458 UnloadBlob_TCPA_VERSION(offset, blob, &key->hdr.key11.ver); 459 UnloadBlob_UINT16(offset, &key->keyUsage, blob); 460 UnloadBlob_KEY_FLAGS(offset, blob, &key->keyFlags); 461 UnloadBlob_BOOL(offset, (TSS_BOOL *)&key->authDataUsage, blob); 462 if ((rc = UnloadBlob_KEY_PARMS(offset, blob, &key->algorithmParms))) 463 return rc; 464 UnloadBlob_UINT32(offset, &key->PCRInfoSize, blob); 465 466 if (key->PCRInfoSize == 0) 467 key->PCRInfo = NULL; 468 else { 469 key->PCRInfo = malloc(key->PCRInfoSize); 470 if (key->PCRInfo == NULL) { 471 LogError("malloc of %u bytes failed.", key->PCRInfoSize); 472 key->PCRInfoSize = 0; 473 free(key->algorithmParms.parms); 474 key->algorithmParms.parms = NULL; 475 key->algorithmParms.parmSize = 0; 476 return TCSERR(TSS_E_OUTOFMEMORY); 477 } 478 UnloadBlob(offset, key->PCRInfoSize, blob, key->PCRInfo); 479 } 480 481 if ((rc = UnloadBlob_STORE_PUBKEY(offset, blob, &key->pubKey))) { 482 free(key->PCRInfo); 483 key->PCRInfo = NULL; 484 key->PCRInfoSize = 0; 485 free(key->algorithmParms.parms); 486 key->algorithmParms.parms = NULL; 487 key->algorithmParms.parmSize = 0; 488 return rc; 489 } 490 UnloadBlob_UINT32(offset, &key->encSize, blob); 491 492 if (key->encSize == 0) 493 key->encData = NULL; 494 else { 495 key->encData = (BYTE *)malloc(key->encSize); 496 if (key->encData == NULL) { 497 LogError("malloc of %d bytes failed.", key->encSize); 498 key->encSize = 0; 499 free(key->algorithmParms.parms); 500 key->algorithmParms.parms = NULL; 501 key->algorithmParms.parmSize = 0; 502 free(key->PCRInfo); 503 key->PCRInfo = NULL; 504 key->PCRInfoSize = 0; 505 free(key->pubKey.key); 506 key->pubKey.key = NULL; 507 key->pubKey.keyLength = 0; 508 return TCSERR(TSS_E_OUTOFMEMORY); 509 } 510 UnloadBlob(offset, key->encSize, blob, key->encData); 511 } 512 513 return TSS_SUCCESS; 514 } 515 516 void 517 LoadBlob_TSS_KEY(UINT64 *offset, BYTE * blob, TSS_KEY * key) 518 { 519 if (key->hdr.key12.tag == TPM_TAG_KEY12) { 520 LoadBlob_UINT16(offset, key->hdr.key12.tag, blob); 521 LoadBlob_UINT16(offset, key->hdr.key12.fill, blob); 522 } else 523 LoadBlob_TCPA_VERSION(offset, blob, &key->hdr.key11.ver); 524 LoadBlob_UINT16(offset, key->keyUsage, blob); 525 LoadBlob_KEY_FLAGS(offset, blob, &key->keyFlags); 526 LoadBlob_BOOL(offset, key->authDataUsage, blob); 527 LoadBlob_KEY_PARMS(offset, blob, &key->algorithmParms); 528 LoadBlob_UINT32(offset, key->PCRInfoSize, blob); 529 LoadBlob(offset, key->PCRInfoSize, blob, key->PCRInfo); 530 LoadBlob_STORE_PUBKEY(offset, blob, &key->pubKey); 531 LoadBlob_UINT32(offset, key->encSize, blob); 532 LoadBlob(offset, key->encSize, blob, key->encData); 533 } 534 535 void 536 LoadBlob_PUBKEY(UINT64 *offset, BYTE * blob, TCPA_PUBKEY * key) 537 { 538 LoadBlob_KEY_PARMS(offset, blob, &(key->algorithmParms)); 539 LoadBlob_STORE_PUBKEY(offset, blob, &(key->pubKey)); 540 } 541 542 TSS_RESULT 543 UnloadBlob_PUBKEY(UINT64 *offset, BYTE *blob, TCPA_PUBKEY *key) 544 { 545 TSS_RESULT rc; 546 547 if (!key) { 548 if ((rc = UnloadBlob_KEY_PARMS(offset, blob, NULL))) 549 return rc; 550 return UnloadBlob_STORE_PUBKEY(offset, blob, NULL); 551 } 552 553 if ((rc = UnloadBlob_KEY_PARMS(offset, blob, &key->algorithmParms))) 554 return rc; 555 if ((rc = UnloadBlob_STORE_PUBKEY(offset, blob, &key->pubKey))) { 556 free(key->algorithmParms.parms); 557 key->algorithmParms.parms = NULL; 558 key->algorithmParms.parmSize = 0; 559 } 560 561 return rc; 562 } 563 564 void 565 LoadBlob_KEY_FLAGS(UINT64 *offset, BYTE * blob, TCPA_KEY_FLAGS * flags) 566 { 567 LoadBlob_UINT32(offset, *flags, blob); 568 } 569 570 void 571 destroy_key_refs(TSS_KEY *key) 572 { 573 free(key->algorithmParms.parms); 574 key->algorithmParms.parms = NULL; 575 key->algorithmParms.parmSize = 0; 576 577 free(key->pubKey.key); 578 key->pubKey.key = NULL; 579 key->pubKey.keyLength = 0; 580 581 free(key->encData); 582 key->encData = NULL; 583 key->encSize = 0; 584 585 free(key->PCRInfo); 586 key->PCRInfo = NULL; 587 key->PCRInfoSize = 0; 588 } 589