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. 2005, 2007 8 * 9 */ 10 11 12 #include <stdlib.h> 13 #include <stdio.h> 14 #include <errno.h> 15 #include <string.h> 16 #include <assert.h> 17 18 #include "trousers/tss.h" 19 #include "trousers/trousers.h" 20 #include "tcs_tsp.h" 21 #include "trousers_types.h" 22 #include "spi_utils.h" 23 #include "capabilities.h" 24 #include "tsplog.h" 25 #include "obj.h" 26 27 28 TSS_RESULT 29 obj_context_add(TSS_HOBJECT *phObject) 30 { 31 TSS_RESULT result; 32 struct tr_context_obj *context = calloc(1, sizeof(struct tr_context_obj)); 33 unsigned len = strlen(TSS_LOCALHOST_STRING) + 1; 34 35 if (context == NULL) { 36 LogError("malloc of %zd bytes failed.", sizeof(struct tr_context_obj)); 37 return TSPERR(TSS_E_OUTOFMEMORY); 38 } 39 40 #ifndef TSS_NO_GUI 41 context->silentMode = TSS_TSPATTRIB_CONTEXT_NOT_SILENT; 42 #else 43 context->silentMode = TSS_TSPATTRIB_CONTEXT_SILENT; 44 #endif 45 if ((context->machineName = calloc(1, len)) == NULL) { 46 LogError("malloc of %u bytes failed", len); 47 free(context); 48 return TSPERR(TSS_E_OUTOFMEMORY); 49 } 50 memcpy(context->machineName, TSS_LOCALHOST_STRING, len); 51 context->machineNameLength = len; 52 53 context->hashMode = TSS_TSPATTRIB_HASH_MODE_NOT_NULL; 54 context->connection_policy = TSS_TSPATTRIB_CONTEXT_VERSION_V1_1; 55 56 if ((result = obj_list_add(&context_list, NULL_HCONTEXT, 0, context, phObject))) { 57 free(context->machineName); 58 free(context); 59 return result; 60 } 61 62 /* Add the default policy */ 63 if ((result = obj_policy_add(*phObject, TSS_POLICY_USAGE, &context->policy))) { 64 obj_list_remove(&context_list, &__tspi_obj_context_free, *phObject, *phObject); 65 return result; 66 } 67 68 context->tcs_api = &tcs_normal_api; 69 70 return TSS_SUCCESS; 71 } 72 73 struct tcs_api_table * 74 obj_context_get_tcs_api(TSS_HCONTEXT tspContext) 75 { 76 struct tsp_object *obj; 77 struct tr_context_obj *context; 78 struct tcs_api_table *t; 79 80 /* If the object cannot be found with the given handle, return a safe value, the normal TCS 81 * API pointer. Since the handle is bad, the RPC_ function will barf in looking up the 82 * corresponding TCS context handle and an invalid handle error will be returned. */ 83 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 84 return &tcs_normal_api; 85 86 context = (struct tr_context_obj *)obj->data; 87 88 /* Return the current API set we're using, either the normal API, or the transport encrypted 89 * API. The context->tcs_api variable is switched back and forth between the two sets by 90 * the obj_context_transport_set_control function through a set attrib. */ 91 t = context->tcs_api; 92 93 obj_list_put(&context_list); 94 95 return t; 96 } 97 98 void 99 __tspi_obj_context_free(void *data) 100 { 101 struct tr_context_obj *context = (struct tr_context_obj *)data; 102 103 free(context->machineName); 104 free(context); 105 } 106 107 TSS_BOOL 108 obj_is_context(TSS_HOBJECT hObject) 109 { 110 TSS_BOOL answer = FALSE; 111 112 if ((obj_list_get_obj(&context_list, hObject))) { 113 answer = TRUE; 114 obj_list_put(&context_list); 115 } 116 117 return answer; 118 } 119 120 /* Clean up transport session if necessary. */ 121 void 122 obj_context_close(TSS_HCONTEXT tspContext) 123 { 124 struct tsp_object *obj; 125 struct tr_context_obj *context; 126 127 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 128 return; 129 130 context = (struct tr_context_obj *)obj->data; 131 132 #ifdef TSS_BUILD_TRANSPORT 133 if (context->transAuth.AuthHandle) { 134 RPC_FlushSpecific(tspContext, context->transAuth.AuthHandle, TPM_RT_TRANS); 135 136 memset(&context->transPub, 0, sizeof(TPM_TRANSPORT_PUBLIC)); 137 memset(&context->transMod, 0, sizeof(TPM_MODIFIER_INDICATOR)); 138 memset(&context->transSecret, 0, sizeof(TPM_TRANSPORT_AUTH)); 139 memset(&context->transAuth, 0, sizeof(TPM_AUTH)); 140 memset(&context->transLogIn, 0, sizeof(TPM_TRANSPORT_LOG_IN)); 141 memset(&context->transLogOut, 0, sizeof(TPM_TRANSPORT_LOG_OUT)); 142 memset(&context->transLogDigest, 0, sizeof(TPM_DIGEST)); 143 } 144 #endif 145 146 obj_list_put(&context_list); 147 } 148 149 TSS_RESULT 150 obj_context_get_policy(TSS_HCONTEXT tspContext, UINT32 policyType, TSS_HPOLICY *phPolicy) 151 { 152 struct tsp_object *obj; 153 struct tr_context_obj *context; 154 TSS_RESULT result = TSS_SUCCESS; 155 156 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 157 return TSPERR(TSS_E_INVALID_HANDLE); 158 159 context = (struct tr_context_obj *)obj->data; 160 161 switch (policyType) { 162 case TSS_POLICY_USAGE: 163 *phPolicy = context->policy; 164 break; 165 default: 166 result = TSPERR(TSS_E_BAD_PARAMETER); 167 } 168 169 obj_list_put(&context_list); 170 171 return result; 172 } 173 174 TSS_RESULT 175 obj_context_get_machine_name(TSS_HCONTEXT tspContext, UINT32 *size, BYTE **data) 176 { 177 struct tsp_object *obj; 178 struct tr_context_obj *context; 179 TSS_RESULT result; 180 181 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 182 return TSPERR(TSS_E_INVALID_HANDLE); 183 184 context = (struct tr_context_obj *)obj->data; 185 186 if (context->machineNameLength == 0) { 187 *data = NULL; 188 *size = 0; 189 } else { 190 /* 191 * Don't use calloc_tspi because this memory is 192 * not freed using "free_tspi" 193 */ 194 *data = calloc(1, context->machineNameLength); 195 if (*data == NULL) { 196 LogError("malloc of %u bytes failed.", 197 context->machineNameLength); 198 result = TSPERR(TSS_E_OUTOFMEMORY); 199 goto done; 200 } 201 *size = context->machineNameLength; 202 memcpy(*data, context->machineName, *size); 203 } 204 205 result = TSS_SUCCESS; 206 207 done: 208 obj_list_put(&context_list); 209 210 return result; 211 } 212 213 /* This function converts the machine name to a TSS_UNICODE string before 214 * returning it, as Tspi_GetAttribData would like. We could do the conversion 215 * in Tspi_GetAttribData, but we don't have access to the TSP context there */ 216 TSS_RESULT 217 obj_context_get_machine_name_attrib(TSS_HCONTEXT tspContext, UINT32 *size, BYTE **data) 218 { 219 struct tsp_object *obj; 220 struct tr_context_obj *context; 221 BYTE *utf_string; 222 UINT32 utf_size; 223 TSS_RESULT result; 224 225 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 226 return TSPERR(TSS_E_INVALID_HANDLE); 227 228 context = (struct tr_context_obj *)obj->data; 229 230 if (context->machineNameLength == 0) { 231 *data = NULL; 232 *size = 0; 233 } else { 234 utf_size = context->machineNameLength; 235 utf_string = Trspi_Native_To_UNICODE(context->machineName, 236 &utf_size); 237 if (utf_string == NULL) { 238 result = TSPERR(TSS_E_INTERNAL_ERROR); 239 goto done; 240 } 241 242 *data = calloc_tspi(obj->tspContext, utf_size); 243 if (*data == NULL) { 244 free(utf_string); 245 LogError("malloc of %u bytes failed.", utf_size); 246 result = TSPERR(TSS_E_OUTOFMEMORY); 247 goto done; 248 } 249 *size = utf_size; 250 memcpy(*data, utf_string, utf_size); 251 free(utf_string); 252 } 253 254 result = TSS_SUCCESS; 255 256 done: 257 obj_list_put(&context_list); 258 259 return result; 260 } 261 262 TSS_RESULT 263 obj_context_set_machine_name(TSS_HCONTEXT tspContext, BYTE *name, UINT32 len) 264 { 265 struct tsp_object *obj; 266 struct tr_context_obj *context; 267 268 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 269 return TSPERR(TSS_E_INVALID_HANDLE); 270 271 context = (struct tr_context_obj *)obj->data; 272 273 free(context->machineName); 274 context->machineName = name; 275 context->machineNameLength = len; 276 277 obj_list_put(&context_list); 278 279 return TSS_SUCCESS; 280 } 281 282 TSS_BOOL 283 obj_context_is_silent(TSS_HCONTEXT tspContext) 284 { 285 struct tsp_object *obj; 286 struct tr_context_obj *context; 287 TSS_BOOL silent = FALSE; 288 289 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 290 return FALSE; 291 292 context = (struct tr_context_obj *)obj->data; 293 if (context->silentMode == TSS_TSPATTRIB_CONTEXT_SILENT) 294 silent = TRUE; 295 296 obj_list_put(&context_list); 297 298 return silent; 299 } 300 301 TSS_RESULT 302 obj_context_get_mode(TSS_HCONTEXT tspContext, UINT32 *mode) 303 { 304 struct tsp_object *obj; 305 struct tr_context_obj *context; 306 307 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 308 return TSPERR(TSS_E_INVALID_HANDLE); 309 310 context = (struct tr_context_obj *)obj->data; 311 *mode = context->silentMode; 312 313 obj_list_put(&context_list); 314 315 return TSS_SUCCESS; 316 } 317 318 TSS_RESULT 319 obj_context_set_mode(TSS_HCONTEXT tspContext, UINT32 mode) 320 { 321 struct tsp_object *obj; 322 struct tr_context_obj *context; 323 324 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 325 return TSPERR(TSS_E_INVALID_HANDLE); 326 327 context = (struct tr_context_obj *)obj->data; 328 context->silentMode = mode; 329 330 obj_list_put(&context_list); 331 332 return TSS_SUCCESS; 333 } 334 335 /* search the list of all policies bound to context @tspContext. If 336 * one is found of type popup, return TRUE, else return FALSE. */ 337 TSS_BOOL 338 obj_context_has_popups(TSS_HCONTEXT tspContext) 339 { 340 struct tsp_object *obj; 341 struct tr_policy_obj *policy; 342 struct obj_list *list = &policy_list; 343 TSS_BOOL ret = FALSE; 344 345 MUTEX_LOCK(list->lock); 346 347 for (obj = list->head; obj; obj = obj->next) { 348 if (obj->tspContext == tspContext) { 349 policy = (struct tr_policy_obj *)obj->data; 350 if (policy->SecretMode == TSS_SECRET_MODE_POPUP) 351 ret = TRUE; 352 break; 353 } 354 } 355 356 MUTEX_UNLOCK(list->lock); 357 358 return ret; 359 } 360 361 TSS_RESULT 362 obj_context_get_hash_mode(TSS_HCONTEXT tspContext, UINT32 *mode) 363 { 364 struct tsp_object *obj; 365 struct tr_context_obj *context; 366 367 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 368 return TSPERR(TSS_E_INVALID_HANDLE); 369 370 context = (struct tr_context_obj *)obj->data; 371 *mode = context->hashMode; 372 373 obj_list_put(&context_list); 374 375 return TSS_SUCCESS; 376 } 377 378 TSS_RESULT 379 obj_context_set_hash_mode(TSS_HCONTEXT tspContext, UINT32 mode) 380 { 381 struct tsp_object *obj; 382 struct tr_context_obj *context; 383 384 switch (mode) { 385 case TSS_TSPATTRIB_HASH_MODE_NULL: 386 case TSS_TSPATTRIB_HASH_MODE_NOT_NULL: 387 break; 388 default: 389 return TSPERR(TSS_E_INVALID_ATTRIB_DATA); 390 } 391 392 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 393 return TSPERR(TSS_E_INVALID_HANDLE); 394 395 context = (struct tr_context_obj *)obj->data; 396 context->hashMode = mode; 397 398 obj_list_put(&context_list); 399 400 return TSS_SUCCESS; 401 } 402 403 TSS_RESULT 404 obj_context_get_connection_version(TSS_HCONTEXT tspContext, UINT32 *version) 405 { 406 struct tsp_object *obj; 407 struct tr_context_obj *context; 408 409 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 410 return TSPERR(TSS_E_INVALID_HANDLE); 411 412 context = (struct tr_context_obj *)obj->data; 413 414 *version = context->current_connection; 415 416 obj_list_put(&context_list); 417 418 return TSS_SUCCESS; 419 } 420 421 TSS_RESULT 422 obj_context_set_connection_policy(TSS_HCONTEXT tspContext, UINT32 policy) 423 { 424 struct tsp_object *obj; 425 struct tr_context_obj *context; 426 427 switch (policy) { 428 case TSS_TSPATTRIB_CONTEXT_VERSION_V1_1: 429 case TSS_TSPATTRIB_CONTEXT_VERSION_V1_2: 430 case TSS_TSPATTRIB_CONTEXT_VERSION_AUTO: 431 break; 432 default: 433 return TSPERR(TSS_E_INVALID_ATTRIB_DATA); 434 } 435 436 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 437 return TSPERR(TSS_E_INVALID_HANDLE); 438 439 context = (struct tr_context_obj *)obj->data; 440 441 context->connection_policy = policy; 442 443 obj_list_put(&context_list); 444 445 return TSS_SUCCESS; 446 } 447 448 #ifdef TSS_BUILD_TRANSPORT 449 TSS_RESULT 450 obj_context_set_transport_key(TSS_HCONTEXT tspContext, TSS_HKEY hKey) 451 { 452 struct tsp_object *obj; 453 struct tr_context_obj *context; 454 455 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 456 return TSPERR(TSS_E_INVALID_HANDLE); 457 458 context = (struct tr_context_obj *)obj->data; 459 460 context->transKey = hKey; 461 462 obj_list_put(&context_list); 463 464 return TSS_SUCCESS; 465 } 466 467 TSS_RESULT 468 obj_context_transport_get_mode(TSS_HCONTEXT tspContext, UINT32 value, UINT32 *out) 469 { 470 TSS_RESULT result = TSS_SUCCESS; 471 struct tsp_object *obj; 472 struct tr_context_obj *context; 473 474 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 475 return TSPERR(TSS_E_INVALID_HANDLE); 476 477 context = (struct tr_context_obj *)obj->data; 478 479 switch (value) { 480 case TSS_TSPATTRIB_TRANSPORT_NO_DEFAULT_ENCRYPTION: 481 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT ? 482 FALSE : TRUE; 483 break; 484 case TSS_TSPATTRIB_TRANSPORT_DEFAULT_ENCRYPTION: 485 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT ? 486 TRUE : FALSE; 487 break; 488 case TSS_TSPATTRIB_TRANSPORT_AUTHENTIC_CHANNEL: 489 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC ? 490 TRUE : FALSE; 491 break; 492 case TSS_TSPATTRIB_TRANSPORT_EXCLUSIVE: 493 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_EXCLUSIVE ? 494 TRUE : FALSE; 495 break; 496 case TSS_TSPATTRIB_TRANSPORT_STATIC_AUTH: 497 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_STATIC_AUTH ? 498 TRUE : FALSE; 499 break; 500 default: 501 LogError("Invalid attribute subflag: 0x%x", value); 502 result = TSPERR(TSS_E_INVALID_ATTRIB_SUBFLAG); 503 break; 504 } 505 506 obj_list_put(&context_list); 507 508 return result; 509 } 510 511 TSS_RESULT 512 obj_context_transport_get_control(TSS_HCONTEXT tspContext, UINT32 value, UINT32 *out) 513 { 514 TSS_RESULT result = TSS_SUCCESS; 515 struct tsp_object *obj; 516 struct tr_context_obj *context; 517 518 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 519 return TSPERR(TSS_E_INVALID_HANDLE); 520 521 context = (struct tr_context_obj *)obj->data; 522 523 switch (value) { 524 case TSS_TSPATTRIB_DISABLE_TRANSPORT: 525 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED ? FALSE : TRUE; 526 break; 527 case TSS_TSPATTRIB_ENABLE_TRANSPORT: 528 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED ? TRUE : FALSE; 529 break; 530 default: 531 LogError("Invalid attribute subflag: 0x%x", value); 532 result = TSPERR(TSS_E_INVALID_ATTRIB_SUBFLAG); 533 break; 534 } 535 536 obj_list_put(&context_list); 537 538 return result; 539 } 540 541 TSS_RESULT 542 obj_context_transport_set_control(TSS_HCONTEXT tspContext, UINT32 value) 543 { 544 TSS_RESULT result = TSS_SUCCESS; 545 struct tsp_object *obj; 546 struct tr_context_obj *context; 547 548 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 549 return TSPERR(TSS_E_INVALID_HANDLE); 550 551 context = (struct tr_context_obj *)obj->data; 552 553 switch (value) { 554 case TSS_TSPATTRIB_ENABLE_TRANSPORT: 555 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED; 556 context->tcs_api = &tcs_transport_api; 557 break; 558 case TSS_TSPATTRIB_DISABLE_TRANSPORT: 559 context->flags &= ~TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED; 560 context->tcs_api = &tcs_normal_api; 561 break; 562 default: 563 LogError("Invalid attribute subflag: 0x%x", value); 564 result = TSPERR(TSS_E_INTERNAL_ERROR); 565 break; 566 } 567 568 obj_list_put(&context_list); 569 570 return result; 571 } 572 573 TSS_RESULT 574 obj_context_transport_set_mode(TSS_HCONTEXT tspContext, UINT32 value) 575 { 576 TSS_RESULT result = TSS_SUCCESS; 577 struct tsp_object *obj; 578 struct tr_context_obj *context; 579 580 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 581 return TSPERR(TSS_E_INVALID_HANDLE); 582 583 context = (struct tr_context_obj *)obj->data; 584 585 switch (value) { 586 case TSS_TSPATTRIB_TRANSPORT_NO_DEFAULT_ENCRYPTION: 587 context->flags &= ~TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT; 588 break; 589 case TSS_TSPATTRIB_TRANSPORT_DEFAULT_ENCRYPTION: 590 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT; 591 break; 592 case TSS_TSPATTRIB_TRANSPORT_AUTHENTIC_CHANNEL: 593 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC; 594 break; 595 case TSS_TSPATTRIB_TRANSPORT_EXCLUSIVE: 596 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_EXCLUSIVE; 597 break; 598 case TSS_TSPATTRIB_TRANSPORT_STATIC_AUTH: 599 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_STATIC_AUTH; 600 break; 601 default: 602 LogError("Invalid attribute subflag: 0x%x", value); 603 result = TSPERR(TSS_E_INTERNAL_ERROR); 604 break; 605 } 606 607 obj_list_put(&context_list); 608 609 return result; 610 } 611 612 #if 0 613 TSS_RESULT 614 get_trans_props(TSS_HCONTEXT tspContext, UINT32 *alg, UINT16 *enc) 615 { 616 TSS_RESULT result; 617 UINT32 algs[] = { TPM_ALG_MGF1, TPM_ALG_AES128, 0 }, a = 0; 618 UINT16 encs[] = { TPM_ES_SYM_OFB, TPM_ES_SYM_CNT, TPM_ES_SYM_CBC_PKCS5PAD, 0 }, e = 0; 619 BYTE *respData; 620 UINT32 respLen, tcsSubCap32; 621 UINT16 tcsSubCap16; 622 623 if (*alg) 624 goto check_es; 625 626 for (a = 0; algs[a]; a++) { 627 tcsSubCap32 = endian32(algs[a]); 628 629 if ((result = RPC_GetTPMCapability(tspContext, TPM_CAP_TRANS_ALG, sizeof(UINT32), 630 (BYTE *)&tcsSubCap32, &respLen, &respData))) 631 return result; 632 633 if (*(TSS_BOOL *)respData == TRUE) { 634 free(respData); 635 break; 636 } 637 free(respData); 638 } 639 640 if (!algs[a]) { 641 LogError("TPM reports no usable sym algorithms for transport session"); 642 return TSPERR(TSS_E_INTERNAL_ERROR); 643 } 644 645 check_es: 646 if (*enc || algs[a] == TPM_ALG_MGF1) 647 goto done; 648 649 for (e = 0; encs[e]; e++) { 650 tcsSubCap16 = endian16(encs[e]); 651 652 if ((result = RPC_GetTPMCapability(tspContext, TPM_CAP_TRANS_ES, sizeof(UINT16), 653 (BYTE *)&tcsSubCap16, &respLen, &respData))) 654 return result; 655 656 if (*(TSS_BOOL *)respData == TRUE) { 657 free(respData); 658 break; 659 } 660 free(respData); 661 } 662 663 if (!encs[e]) { 664 LogError("TPM reports no usable sym modes for transport session"); 665 return TSPERR(TSS_E_INTERNAL_ERROR); 666 } 667 668 *alg = algs[a]; 669 *enc = encs[e]; 670 done: 671 return TSS_SUCCESS; 672 } 673 #endif 674 675 /* called before each TCSP_ExecuteTransport call */ 676 TSS_RESULT 677 obj_context_transport_init(TSS_HCONTEXT tspContext) 678 { 679 TSS_RESULT result = TSS_SUCCESS; 680 struct tsp_object *obj; 681 struct tr_context_obj *context; 682 683 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 684 return TSPERR(TSS_E_INVALID_HANDLE); 685 686 context = (struct tr_context_obj *)obj->data; 687 688 /* return immediately if we're not in a transport session */ 689 if (!(context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED)) { 690 result = TSPERR(TSS_E_INTERNAL_ERROR); 691 goto done; 692 } 693 694 /* if the session is not yet established, setup and call EstablishTransport */ 695 if (!(context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_ESTABLISHED)) { 696 if ((result = obj_context_transport_establish(tspContext, context))) 697 goto done; 698 } 699 700 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_ESTABLISHED; 701 702 result = TSS_SUCCESS; 703 done: 704 obj_list_put(&context_list); 705 706 return result; 707 } 708 709 TSS_RESULT 710 obj_context_transport_establish(TSS_HCONTEXT tspContext, struct tr_context_obj *context) 711 { 712 TSS_RESULT result; 713 UINT32 tickLen, secretLen, transPubLen, exclusive = TSS_TCSATTRIB_TRANSPORT_DEFAULT; 714 BYTE *ticks, *secret; 715 UINT64 offset; 716 Trspi_HashCtx hashCtx; 717 TPM_DIGEST digest; 718 TSS_HPOLICY hTransKeyPolicy; 719 TPM_AUTH auth, *pAuth, *pTransAuth; 720 TCS_KEY_HANDLE tcsTransKey; 721 TSS_BOOL usesAuth = FALSE; 722 UINT32 encKeyLen; 723 BYTE encKey[256]; 724 BYTE transPubBlob[sizeof(TPM_TRANSPORT_PUBLIC)]; 725 BYTE transAuthBlob[sizeof(TPM_TRANSPORT_AUTH)]; 726 727 728 context->transPub.tag = TPM_TAG_TRANSPORT_PUBLIC; 729 context->transSecret.tag = TPM_TAG_TRANSPORT_AUTH; 730 731 if ((result = get_local_random(tspContext, FALSE, TPM_SHA1_160_HASH_LEN, 732 (BYTE **)context->transSecret.authData.authdata))) 733 return result; 734 735 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_STATIC_AUTH) 736 context->transKey = TPM_KH_TRANSPORT; 737 738 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC) 739 context->transPub.transAttributes |= TPM_TRANSPORT_LOG; 740 741 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_EXCLUSIVE) { 742 context->transPub.transAttributes |= TPM_TRANSPORT_EXCLUSIVE; 743 exclusive = TSS_TCSATTRIB_TRANSPORT_EXCLUSIVE; 744 } 745 746 /* XXX implement AES128+CTR (Winbond, Infineon), then AES256+CTR (Atmel) */ 747 context->transPub.algId = TPM_ALG_MGF1; 748 context->transPub.encScheme = TPM_ES_NONE; 749 750 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT) { 751 context->transPub.transAttributes |= TPM_TRANSPORT_ENCRYPT; 752 753 if (context->transKey == TPM_KH_TRANSPORT) { 754 LogError("No transport key handle has been set yet. Use " 755 "Tspi_Context_SetTransEncryptionKey to set this handle"); 756 return TSPERR(TSS_E_INTERNAL_ERROR); 757 } 758 } 759 760 if (context->transKey == TPM_KH_TRANSPORT) { 761 secret = context->transSecret.authData.authdata; 762 secretLen = TPM_SHA1_160_HASH_LEN; 763 } else { 764 offset = 0; 765 Trspi_LoadBlob_TRANSPORT_AUTH(&offset, transAuthBlob, &context->transSecret); 766 secretLen = offset; 767 768 /* encrypt the sym key with the wrapping RSA key */ 769 encKeyLen = sizeof(encKey); 770 if ((result = __tspi_rsa_encrypt(context->transKey, secretLen, transAuthBlob, &encKeyLen, 771 encKey))) 772 return result; 773 774 secret = encKey; 775 secretLen = encKeyLen; 776 } 777 778 offset = 0; 779 Trspi_LoadBlob_TRANSPORT_PUBLIC(&offset, transPubBlob, &context->transPub); 780 transPubLen = offset; 781 782 if (context->transKey != TPM_KH_TRANSPORT) { 783 if ((result = obj_rsakey_get_tcs_handle(context->transKey, &tcsTransKey))) 784 return result; 785 786 if ((result = obj_rsakey_get_policy(context->transKey, TSS_POLICY_USAGE, 787 &hTransKeyPolicy, &usesAuth))) 788 return result; 789 790 if (!usesAuth) { 791 LogError("Key used to establish a transport session must use auth"); 792 return TSPERR(TSS_E_TSP_TRANS_AUTHREQUIRED); 793 } 794 } else 795 tcsTransKey = TPM_KH_TRANSPORT; 796 797 /* If logging is on, do TPM commands spec rev106 step 8.a */ 798 memset(context->transLogDigest.digest, 0, sizeof(TPM_DIGEST)); 799 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC) { 800 context->transLogIn.tag = TPM_TAG_TRANSPORT_LOG_IN; 801 802 /* step 8.a, i */ 803 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 804 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_EstablishTransport); 805 result |= Trspi_HashUpdate(&hashCtx, transPubLen, transPubBlob); 806 result |= Trspi_Hash_UINT32(&hashCtx, secretLen); 807 result |= Trspi_HashUpdate(&hashCtx, secretLen, secret); 808 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogIn.parameters.digest))) 809 return result; 810 811 /* step 8.a, ii */ 812 memset(context->transLogIn.pubKeyHash.digest, 0, sizeof(TPM_DIGEST)); 813 814 /* step 8.a, iii */ 815 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 816 result |= Trspi_Hash_DIGEST(&hashCtx, context->transLogDigest.digest); 817 result |= Trspi_Hash_TRANSPORT_LOG_IN(&hashCtx, &context->transLogIn); 818 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogDigest.digest))) 819 return result; 820 } 821 822 if (usesAuth) { 823 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 824 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_EstablishTransport); 825 result |= Trspi_HashUpdate(&hashCtx, (UINT32)offset, (BYTE *)transPubBlob); 826 result |= Trspi_Hash_UINT32(&hashCtx, secretLen); 827 result |= Trspi_HashUpdate(&hashCtx, secretLen, secret); 828 if ((result |= Trspi_HashFinal(&hashCtx, (BYTE *)&digest))) 829 return result; 830 831 /* open OIAP session with continueAuthSession = TRUE */ 832 if ((result = secret_PerformAuth_OIAP(context->transKey, TPM_ORD_EstablishTransport, 833 hTransKeyPolicy, TRUE, &digest, &auth))) 834 return result; 835 836 pAuth = &auth; 837 } else 838 pAuth = NULL; 839 840 result = RPC_EstablishTransport(tspContext, exclusive, tcsTransKey, transPubLen, 841 transPubBlob, secretLen, secret, pAuth, &context->transMod, 842 &context->transAuth.AuthHandle, &tickLen, &ticks, 843 &context->transAuth.NonceEven); 844 if (result) { 845 LogError("Establish Transport command failed: %s", Trspi_Error_String(result)); 846 return result; 847 } 848 849 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 850 result |= Trspi_Hash_UINT32(&hashCtx, result); 851 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_EstablishTransport); 852 result |= Trspi_Hash_UINT32(&hashCtx, context->transMod); 853 result |= Trspi_HashUpdate(&hashCtx, tickLen, ticks); 854 result |= Trspi_Hash_NONCE(&hashCtx, context->transAuth.NonceEven.nonce); 855 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 856 return result; 857 858 if (usesAuth) { 859 if ((result = obj_policy_validate_auth_oiap(hTransKeyPolicy, &digest, pAuth))) 860 return result; 861 } 862 863 /* step 8.b iii */ 864 offset = 0; 865 Trspi_UnloadBlob_CURRENT_TICKS(&offset, ticks, &context->transLogOut.currentTicks); 866 free(ticks); 867 868 /* If logging is on, do TPM commands spec rev106 step 8.b */ 869 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC) { 870 context->transLogOut.tag = TPM_TAG_TRANSPORT_LOG_OUT; 871 872 /* step 8.b i */ 873 memcpy(context->transLogOut.parameters.digest, digest.digest, sizeof(TPM_DIGEST)); 874 875 /* step 8.b ii */ 876 context->transLogOut.locality = context->transMod; 877 878 /* step 8.b iii was done above */ 879 /* step 8.b iv */ 880 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 881 result |= Trspi_Hash_DIGEST(&hashCtx, context->transLogDigest.digest); 882 result |= Trspi_Hash_TRANSPORT_LOG_OUT(&hashCtx, &context->transLogOut); 883 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogDigest.digest))) 884 return result; 885 } 886 887 LogDebug("Transport session established successfully"); 888 889 pTransAuth = &context->transAuth; 890 pTransAuth->fContinueAuthSession = TRUE; 891 if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE), 892 (BYTE **)pTransAuth->NonceOdd.nonce))) { 893 LogError("Failed creating random nonce"); 894 return TSPERR(TSS_E_INTERNAL_ERROR); 895 } 896 897 return TSS_SUCCESS; 898 } 899 900 TSS_RESULT 901 do_transport_decryption(TPM_TRANSPORT_PUBLIC *transPub, 902 TPM_AUTH *pTransAuth, 903 BYTE *secret, 904 UINT32 inLen, 905 BYTE *in, 906 UINT32 *outLen, 907 BYTE **out) 908 { 909 TSS_RESULT result; 910 UINT32 i, decLen; 911 UINT32 seedLen, ivLen; 912 BYTE *dec; 913 BYTE seed[(2 * sizeof(TPM_NONCE)) + strlen("out") + TPM_SHA1_160_HASH_LEN]; 914 915 /* allocate the most data anyone below might need */ 916 decLen = inLen;//((inLen / TSS_MAX_SYM_BLOCK_SIZE) + 1) * TSS_MAX_SYM_BLOCK_SIZE; 917 if ((dec = malloc(decLen)) == NULL) { 918 LogError("malloc of %u bytes failed", decLen); 919 return TSPERR(TSS_E_OUTOFMEMORY); 920 } 921 922 /* set the common 3 initial values of 'seed', which is used to generate either the IV or 923 * mask */ 924 memcpy(seed, pTransAuth->NonceEven.nonce, sizeof(TPM_NONCE)); 925 memcpy(&seed[sizeof(TPM_NONCE)], pTransAuth->NonceOdd.nonce, sizeof(TPM_NONCE)); 926 memcpy(&seed[2 * sizeof(TPM_NONCE)], "out", strlen("out")); 927 928 switch (transPub->algId) { 929 case TPM_ALG_MGF1: 930 { 931 decLen = inLen; 932 seedLen = sizeof(seed); 933 934 /* add the secret data to the seed for MGF1 */ 935 memcpy(&seed[2 * sizeof(TPM_NONCE) + strlen("out")], secret, TPM_SHA1_160_HASH_LEN); 936 937 if ((result = Trspi_MGF1(TSS_HASH_SHA1, seedLen, seed, decLen, dec))) { 938 free(dec); 939 return result; 940 } 941 942 for (i = 0; i < inLen; i++) 943 dec[i] ^= in[i]; 944 break; 945 } 946 case TPM_ALG_AES128: 947 { 948 BYTE iv[TSS_MAX_SYM_BLOCK_SIZE]; 949 950 ivLen = TSS_MAX_SYM_BLOCK_SIZE; 951 seedLen = (2 * sizeof(TPM_NONCE)) + strlen("out"); 952 953 if ((result = Trspi_MGF1(TSS_HASH_SHA1, seedLen, seed, ivLen, iv))) { 954 free(dec); 955 return result; 956 } 957 958 /* use the secret data as the key for AES */ 959 if ((result = Trspi_SymEncrypt(transPub->algId, transPub->encScheme, secret, iv, in, 960 inLen, dec, &decLen))) { 961 free(dec); 962 return result; 963 } 964 965 break; 966 } 967 default: 968 LogDebug("Unknown algorithm for encrypted transport session: 0x%x", 969 transPub->algId); 970 free(dec); 971 return TSPERR(TSS_E_INTERNAL_ERROR); 972 } 973 974 *out = dec; 975 *outLen = decLen; 976 977 return result; 978 } 979 980 TSS_RESULT 981 do_transport_encryption(TPM_TRANSPORT_PUBLIC *transPub, 982 TPM_AUTH *pTransAuth, 983 BYTE *secret, 984 UINT32 inLen, 985 BYTE *in, 986 UINT32 *outLen, 987 BYTE **out) 988 { 989 TSS_RESULT result; 990 UINT32 i, encLen; 991 UINT32 seedLen, ivLen; 992 BYTE *enc; 993 BYTE seed[(2 * sizeof(TPM_NONCE)) + strlen("in") + TPM_SHA1_160_HASH_LEN]; 994 995 /* allocate the most data anyone below might need */ 996 encLen = ((inLen / TSS_MAX_SYM_BLOCK_SIZE) + 1) * TSS_MAX_SYM_BLOCK_SIZE; 997 if ((enc = malloc(encLen)) == NULL) { 998 LogError("malloc of %u bytes failed", encLen); 999 return TSPERR(TSS_E_OUTOFMEMORY); 1000 } 1001 1002 /* set the common 3 initial values of 'seed', which is used to generate either the IV or 1003 * mask */ 1004 memcpy(seed, pTransAuth->NonceEven.nonce, sizeof(TPM_NONCE)); 1005 memcpy(&seed[sizeof(TPM_NONCE)], pTransAuth->NonceOdd.nonce, sizeof(TPM_NONCE)); 1006 memcpy(&seed[2 * sizeof(TPM_NONCE)], "in", strlen("in")); 1007 1008 switch (transPub->algId) { 1009 case TPM_ALG_MGF1: 1010 { 1011 encLen = inLen; 1012 seedLen = sizeof(seed); 1013 1014 /* add the secret data to the seed for MGF1 */ 1015 memcpy(&seed[2 * sizeof(TPM_NONCE) + strlen("in")], secret, TPM_SHA1_160_HASH_LEN); 1016 1017 if ((result = Trspi_MGF1(TSS_HASH_SHA1, seedLen, seed, encLen, enc))) { 1018 free(enc); 1019 return result; 1020 } 1021 1022 for (i = 0; i < inLen; i++) 1023 enc[i] ^= in[i]; 1024 break; 1025 } 1026 case TPM_ALG_AES128: 1027 { 1028 BYTE iv[TSS_MAX_SYM_BLOCK_SIZE]; 1029 1030 ivLen = TSS_MAX_SYM_BLOCK_SIZE; 1031 seedLen = (2 * sizeof(TPM_NONCE)) + strlen("in"); 1032 1033 if ((result = Trspi_MGF1(TSS_HASH_SHA1, seedLen, seed, ivLen, iv))) { 1034 free(enc); 1035 return result; 1036 } 1037 1038 /* use the secret data as the key for AES */ 1039 if ((result = Trspi_SymEncrypt(transPub->algId, transPub->encScheme, secret, iv, in, 1040 inLen, enc, &encLen))) { 1041 free(enc); 1042 return result; 1043 } 1044 1045 break; 1046 } 1047 default: 1048 LogDebug("Unknown algorithm for encrypted transport session: 0x%x", 1049 transPub->algId); 1050 free(enc); 1051 return TSPERR(TSS_E_INTERNAL_ERROR); 1052 } 1053 1054 *out = enc; 1055 *outLen = encLen; 1056 1057 return result; 1058 } 1059 1060 TSS_RESULT 1061 obj_context_transport_execute(TSS_HCONTEXT tspContext, 1062 TPM_COMMAND_CODE ordinal, 1063 UINT32 ulDataLen, 1064 BYTE* rgbData, 1065 TPM_DIGEST* pubKeyHash, 1066 UINT32* handlesLen, 1067 TCS_HANDLE** handles, 1068 TPM_AUTH* pAuth1, 1069 TPM_AUTH* pAuth2, 1070 UINT32* outLen, 1071 BYTE** out) 1072 { 1073 TSS_RESULT result = TSS_SUCCESS; 1074 struct tsp_object *obj; 1075 struct tr_context_obj *context; 1076 UINT32 encLen, ulWrappedDataLen = 0; 1077 BYTE *pEnc = NULL, *rgbWrappedData = NULL; 1078 TPM_RESULT tpmResult; 1079 Trspi_HashCtx hashCtx; 1080 TPM_DIGEST etDigest, wDigest; 1081 TPM_AUTH *pTransAuth; 1082 UINT64 currentTicks; 1083 TSS_BOOL free_enc = FALSE; 1084 1085 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 1086 return TSPERR(TSS_E_INVALID_HANDLE); 1087 1088 context = (struct tr_context_obj *)obj->data; 1089 1090 pTransAuth = &context->transAuth; 1091 1092 /* TPM Commands spec rev106 step 6 */ 1093 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 1094 result |= Trspi_Hash_UINT32(&hashCtx, ordinal); 1095 1096 switch (ordinal) { 1097 case TPM_ORD_OSAP: 1098 case TPM_ORD_OIAP: 1099 break; 1100 default: 1101 result |= Trspi_HashUpdate(&hashCtx, ulDataLen, rgbData); 1102 break; 1103 } 1104 1105 if ((result |= Trspi_HashFinal(&hashCtx, wDigest.digest))) 1106 goto done; 1107 1108 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC) { 1109 /* TPM Commands spec rev106 step 10.b */ 1110 memcpy(context->transLogIn.parameters.digest, wDigest.digest, sizeof(TPM_DIGEST)); 1111 /* TPM Commands spec rev106 step 10.c, d or e, calculated by the caller */ 1112 if (pubKeyHash) 1113 memcpy(context->transLogIn.pubKeyHash.digest, pubKeyHash->digest, 1114 sizeof(TPM_DIGEST)); 1115 else 1116 memset(context->transLogIn.pubKeyHash.digest, 0, sizeof(TPM_DIGEST)); 1117 1118 /* TPM Commands spec rev106 step 10.f */ 1119 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 1120 result |= Trspi_Hash_DIGEST(&hashCtx, context->transLogDigest.digest); 1121 result |= Trspi_Hash_TRANSPORT_LOG_IN(&hashCtx, &context->transLogIn); 1122 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogDigest.digest))) 1123 goto done; 1124 } 1125 1126 /* TPM Commands spec rev106 step 7.a */ 1127 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 1128 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ExecuteTransport); 1129 result |= Trspi_Hash_UINT32(&hashCtx, ulDataLen + TSS_TPM_TXBLOB_HDR_LEN 1130 + (*handlesLen * sizeof(UINT32)) 1131 + (pAuth1 ? TPM_AUTH_RQU_SIZE : 0) 1132 + (pAuth2 ? TPM_AUTH_RQU_SIZE : 0)); 1133 result |= Trspi_HashUpdate(&hashCtx, TPM_SHA1_160_HASH_LEN, wDigest.digest); 1134 if ((result |= Trspi_HashFinal(&hashCtx, etDigest.digest))) 1135 goto done; 1136 1137 /* encrypt the data if necessary */ 1138 if (ulDataLen && context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT) { 1139 switch (ordinal) { 1140 case TPM_ORD_OSAP: 1141 case TPM_ORD_OIAP: 1142 encLen = ulDataLen; 1143 pEnc = rgbData; 1144 break; 1145 case TPM_ORD_DSAP: 1146 { 1147 UINT64 offset; 1148 UINT32 tmpLen, entityValueLen; 1149 BYTE *tmpEnc, *entityValuePtr; 1150 1151 /* DSAP is a special case where only entityValue is encrypted. So, we'll 1152 * parse through rgbData until we get to entityValue, encrypt it, alloc 1153 * new space for rgbData (since it could be up to a block length larger 1154 * than it came in) and copy the unencrypted data and the encrypted 1155 * entityValue to the new block, setting pEnc and encLen to new values. */ 1156 1157 offset = (2 * sizeof(UINT32)) + sizeof(TPM_NONCE); 1158 Trspi_UnloadBlob_UINT32(&offset, &entityValueLen, rgbData); 1159 1160 entityValuePtr = &rgbData[offset]; 1161 if ((result = do_transport_encryption(&context->transPub, pTransAuth, 1162 context->transSecret.authData.authdata, 1163 entityValueLen, entityValuePtr, &tmpLen, 1164 &tmpEnc))) 1165 goto done; 1166 1167 /* offset is the amount of data before the block we encrypted and tmpLen is 1168 * the size of the encrypted data */ 1169 encLen = offset + tmpLen; 1170 if ((pEnc = malloc(encLen)) == NULL) { 1171 LogError("malloc of %u bytes failed.", encLen); 1172 result = TSPERR(TSS_E_OUTOFMEMORY); 1173 goto done; 1174 } 1175 memcpy(pEnc, rgbData, offset); 1176 memcpy(&pEnc[offset], tmpEnc, tmpLen); 1177 free(tmpEnc); 1178 1179 free_enc = TRUE; 1180 break; 1181 } 1182 default: 1183 if ((result = do_transport_encryption(&context->transPub, pTransAuth, 1184 context->transSecret.authData.authdata, 1185 ulDataLen, rgbData, &encLen, &pEnc))) 1186 goto done; 1187 1188 free_enc = TRUE; 1189 break; 1190 } 1191 } else { 1192 encLen = ulDataLen; 1193 pEnc = rgbData; 1194 } 1195 1196 /* TPM Commands spec rev106 step 7.b */ 1197 HMAC_Auth(context->transSecret.authData.authdata, etDigest.digest, pTransAuth); 1198 1199 if ((result = RPC_ExecuteTransport(tspContext, ordinal, encLen, pEnc, handlesLen, handles, 1200 pAuth1, pAuth2, pTransAuth, ¤tTicks, 1201 &context->transMod, &tpmResult, &ulWrappedDataLen, 1202 &rgbWrappedData))) { 1203 LogDebugFn("Execute Transport failed: %s", Trspi_Error_String(result)); 1204 goto done; 1205 } 1206 1207 if (tpmResult) { 1208 LogDebug("Wrapped command ordinal 0x%x failed with result: 0x%x", ordinal, 1209 tpmResult); 1210 result = tpmResult; 1211 goto done; 1212 } 1213 1214 /* decrypt the returned wrapped data if necessary */ 1215 if (ulWrappedDataLen && context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT) { 1216 switch (ordinal) { 1217 case TPM_ORD_OSAP: 1218 case TPM_ORD_OIAP: 1219 case TPM_ORD_DSAP: 1220 *outLen = ulWrappedDataLen; 1221 *out = rgbWrappedData; 1222 break; 1223 default: 1224 if ((result = do_transport_decryption(&context->transPub, pTransAuth, 1225 context->transSecret.authData.authdata, 1226 ulWrappedDataLen, rgbWrappedData, outLen, 1227 out))) 1228 goto done; 1229 1230 free(rgbWrappedData); 1231 } 1232 } else { 1233 if (outLen) { 1234 *outLen = ulWrappedDataLen; 1235 *out = rgbWrappedData; 1236 } 1237 } 1238 1239 /* TPM Commands spec rev106 step 14 */ 1240 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 1241 result |= Trspi_Hash_UINT32(&hashCtx, tpmResult); 1242 result |= Trspi_Hash_UINT32(&hashCtx, ordinal); 1243 1244 switch (ordinal) { 1245 case TPM_ORD_OSAP: 1246 case TPM_ORD_OIAP: 1247 break; 1248 default: 1249 if (outLen) 1250 result |= Trspi_HashUpdate(&hashCtx, *outLen, *out); 1251 break; 1252 } 1253 1254 if ((result |= Trspi_HashFinal(&hashCtx, wDigest.digest))) 1255 goto done; 1256 1257 /* TPM Commands spec rev106 step 15 */ 1258 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 1259 result |= Trspi_Hash_UINT32(&hashCtx, result); 1260 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ExecuteTransport); 1261 result |= Trspi_Hash_UINT64(&hashCtx, currentTicks); 1262 result |= Trspi_Hash_UINT32(&hashCtx, context->transMod); 1263 result |= Trspi_Hash_UINT32(&hashCtx, (outLen ? *outLen : 0) 1264 + TSS_TPM_TXBLOB_HDR_LEN 1265 + (*handlesLen * sizeof(UINT32)) 1266 + (pAuth1 ? TPM_AUTH_RSP_SIZE : 0) 1267 + (pAuth2 ? TPM_AUTH_RSP_SIZE : 0)); 1268 result |= Trspi_HashUpdate(&hashCtx, TPM_SHA1_160_HASH_LEN, wDigest.digest); 1269 if ((result |= Trspi_HashFinal(&hashCtx, etDigest.digest))) 1270 goto done; 1271 1272 if (validateReturnAuth(context->transSecret.authData.authdata, etDigest.digest, 1273 pTransAuth)) { 1274 result = TSPERR(TSS_E_TSP_TRANS_AUTHFAIL); 1275 goto done; 1276 } 1277 1278 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC) { 1279 context->transLogOut.currentTicks.currentTicks = currentTicks; 1280 1281 /* TPM Commands spec rev106 step 16.b */ 1282 memcpy(context->transLogOut.parameters.digest, wDigest.digest, sizeof(TPM_DIGEST)); 1283 /* TPM Commands spec rev106 step 16.c done above */ 1284 /* TPM Commands spec rev106 step 16.d */ 1285 context->transLogOut.locality = context->transMod; 1286 1287 /* TPM Commands spec rev106 step 16.d */ 1288 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 1289 result |= Trspi_Hash_DIGEST(&hashCtx, context->transLogDigest.digest); 1290 result |= Trspi_Hash_TRANSPORT_LOG_OUT(&hashCtx, &context->transLogOut); 1291 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogDigest.digest))) 1292 goto done; 1293 } 1294 1295 /* Refresh nonceOdd for continued transport auth session */ 1296 if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE), 1297 (BYTE **)pTransAuth->NonceOdd.nonce))) { 1298 LogError("Failed creating random nonce"); 1299 } 1300 1301 done: 1302 if (free_enc) 1303 free(pEnc); 1304 obj_list_put(&context_list); 1305 1306 return result; 1307 } 1308 1309 /* called to close a transport session */ 1310 TSS_RESULT 1311 obj_context_transport_close(TSS_HCONTEXT tspContext, 1312 TSS_HKEY hKey, 1313 TSS_HPOLICY hPolicy, 1314 TSS_BOOL usesAuth, 1315 TPM_SIGN_INFO* signInfo, 1316 UINT32* sigLen, 1317 BYTE** sig) 1318 { 1319 TSS_RESULT result = TSS_SUCCESS; 1320 struct tsp_object *obj; 1321 struct tr_context_obj *context; 1322 Trspi_HashCtx hashCtx; 1323 TPM_DIGEST digest; 1324 TPM_AUTH auth, *pAuth; 1325 TCS_KEY_HANDLE tcsKey; 1326 BYTE *ticks = NULL; 1327 UINT32 tickLen; 1328 1329 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 1330 return TSPERR(TSS_E_INVALID_HANDLE); 1331 1332 context = (struct tr_context_obj *)obj->data; 1333 1334 /* return immediately if we're not in a transport session */ 1335 if (!(context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED)) { 1336 result = TSPERR(TSS_E_INTERNAL_ERROR); 1337 goto done; 1338 } 1339 1340 if ((result = obj_rsakey_get_tcs_handle(hKey, &tcsKey))) 1341 goto done; 1342 1343 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 1344 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ReleaseTransportSigned); 1345 result |= Trspi_Hash_NONCE(&hashCtx, signInfo->replay.nonce); 1346 if ((result |= Trspi_HashFinal(&hashCtx, (BYTE *)&digest))) 1347 goto done; 1348 1349 if (usesAuth) { 1350 if ((result = secret_PerformAuth_OIAP(hKey, TPM_ORD_ReleaseTransportSigned, 1351 hPolicy, FALSE, &digest, &auth))) 1352 goto done; 1353 1354 pAuth = &auth; 1355 } else 1356 pAuth = NULL; 1357 1358 /* continue the auth session established in obj_context_transport_establish */ 1359 HMAC_Auth(context->transSecret.authData.authdata, digest.digest, &context->transAuth); 1360 1361 if ((result = RPC_ReleaseTransportSigned(tspContext, tcsKey, &signInfo->replay, pAuth, 1362 &context->transAuth, 1363 &context->transLogOut.locality, &tickLen, &ticks, 1364 sigLen, sig))) 1365 goto done; 1366 1367 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 1368 result |= Trspi_Hash_UINT32(&hashCtx, result); 1369 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ReleaseTransportSigned); 1370 result |= Trspi_Hash_UINT32(&hashCtx, context->transLogOut.locality); 1371 result |= Trspi_HashUpdate(&hashCtx, tickLen, ticks); 1372 result |= Trspi_Hash_UINT32(&hashCtx, *sigLen); 1373 result |= Trspi_HashUpdate(&hashCtx, *sigLen, *sig); 1374 if ((result |= Trspi_HashFinal(&hashCtx, (BYTE *)&digest))) 1375 goto done_disabled; 1376 1377 /* validate the return data using the key's auth */ 1378 if (pAuth) { 1379 if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, pAuth))) 1380 goto done_disabled; 1381 } 1382 1383 /* validate again using the transport session's auth */ 1384 if ((result = validateReturnAuth(context->transSecret.authData.authdata, digest.digest, 1385 &context->transAuth))) { 1386 result = TSPERR(TSS_E_TSP_TRANS_AUTHFAIL); 1387 goto done_disabled; 1388 } 1389 1390 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC) { 1391 UINT64 offset; 1392 1393 /* TPM Commands Spec step 6.b */ 1394 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 1395 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ReleaseTransportSigned); 1396 result |= Trspi_Hash_NONCE(&hashCtx, signInfo->replay.nonce); 1397 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogOut.parameters.digest))) 1398 goto done_disabled; 1399 1400 /* TPM Commands Spec step 6.c */ 1401 offset = 0; 1402 Trspi_UnloadBlob_CURRENT_TICKS(&offset, ticks, &context->transLogOut.currentTicks); 1403 free(ticks); 1404 1405 /* TPM Commands Spec step 6.d was set above */ 1406 /* TPM Commands Spec step 6.e */ 1407 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 1408 result |= Trspi_Hash_DIGEST(&hashCtx, context->transLogDigest.digest); 1409 result |= Trspi_Hash_TRANSPORT_LOG_OUT(&hashCtx, &context->transLogOut); 1410 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogDigest.digest))) 1411 goto done_disabled; 1412 } 1413 1414 if ((signInfo->data = malloc(sizeof(TPM_DIGEST))) == NULL) { 1415 LogError("malloc %zd bytes failed.", sizeof(TPM_DIGEST)); 1416 result = TSPERR(TSS_E_OUTOFMEMORY); 1417 goto done_disabled; 1418 } 1419 memcpy(signInfo->data, context->transLogDigest.digest, sizeof(TPM_DIGEST)); 1420 signInfo->dataLen = sizeof(TPM_DIGEST); 1421 1422 /* destroy all transport session info, except the key handle */ 1423 memset(&context->transPub, 0, sizeof(TPM_TRANSPORT_PUBLIC)); 1424 memset(&context->transMod, 0, sizeof(TPM_MODIFIER_INDICATOR)); 1425 memset(&context->transSecret, 0, sizeof(TPM_TRANSPORT_AUTH)); 1426 memset(&context->transAuth, 0, sizeof(TPM_AUTH)); 1427 memset(&context->transLogIn, 0, sizeof(TPM_TRANSPORT_LOG_IN)); 1428 memset(&context->transLogOut, 0, sizeof(TPM_TRANSPORT_LOG_OUT)); 1429 memset(&context->transLogDigest, 0, sizeof(TPM_DIGEST)); 1430 1431 done_disabled: 1432 context->flags &= ~TSS_CONTEXT_FLAGS_TRANSPORT_ESTABLISHED; 1433 done: 1434 obj_list_put(&context_list); 1435 1436 return result; 1437 } 1438 #endif 1439 1440 /* XXX change 0,1,2 to #defines */ 1441 TSS_RESULT 1442 obj_context_set_tpm_version(TSS_HCONTEXT tspContext, UINT32 ver) 1443 { 1444 TSS_RESULT result = TSS_SUCCESS; 1445 struct tsp_object *obj; 1446 struct tr_context_obj *context; 1447 1448 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 1449 return TSPERR(TSS_E_INVALID_HANDLE); 1450 1451 context = (struct tr_context_obj *)obj->data; 1452 1453 switch (ver) { 1454 case 1: 1455 context->flags &= ~TSS_CONTEXT_FLAGS_TPM_VERSION_MASK; 1456 context->flags |= TSS_CONTEXT_FLAGS_TPM_VERSION_1; 1457 break; 1458 case 2: 1459 context->flags &= ~TSS_CONTEXT_FLAGS_TPM_VERSION_MASK; 1460 context->flags |= TSS_CONTEXT_FLAGS_TPM_VERSION_2; 1461 break; 1462 default: 1463 LogError("Invalid TPM version set: %u", ver); 1464 result = TSPERR(TSS_E_INTERNAL_ERROR); 1465 break; 1466 } 1467 1468 obj_list_put(&context_list); 1469 1470 return result; 1471 } 1472 1473 /* XXX change 0,1,2 to #defines */ 1474 TSS_RESULT 1475 obj_context_get_tpm_version(TSS_HCONTEXT tspContext, UINT32 *ver) 1476 { 1477 struct tsp_object *obj; 1478 struct tr_context_obj *context; 1479 1480 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 1481 return TSPERR(TSS_E_INVALID_HANDLE); 1482 1483 context = (struct tr_context_obj *)obj->data; 1484 1485 if (context->flags & TSS_CONTEXT_FLAGS_TPM_VERSION_1) 1486 *ver = 1; 1487 else if (context->flags & TSS_CONTEXT_FLAGS_TPM_VERSION_2) 1488 *ver = 2; 1489 else 1490 *ver = 0; 1491 1492 obj_list_put(&context_list); 1493 1494 return TSS_SUCCESS; 1495 } 1496 1497 TSS_RESULT 1498 obj_context_get_loadkey_ordinal(TSS_HCONTEXT tspContext, TPM_COMMAND_CODE *ordinal) 1499 { 1500 struct tsp_object *obj; 1501 struct tr_context_obj *context; 1502 1503 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL) 1504 return TSPERR(TSS_E_INVALID_HANDLE); 1505 1506 context = (struct tr_context_obj *)obj->data; 1507 1508 switch (context->flags & TSS_CONTEXT_FLAGS_TPM_VERSION_MASK) { 1509 case TSS_CONTEXT_FLAGS_TPM_VERSION_2: 1510 *ordinal = TPM_ORD_LoadKey2; 1511 break; 1512 default: 1513 LogDebugFn("No TPM version set!"); 1514 /* fall through */ 1515 case TSS_CONTEXT_FLAGS_TPM_VERSION_1: 1516 *ordinal = TPM_ORD_LoadKey; 1517 break; 1518 } 1519 1520 obj_list_put(&context_list); 1521 1522 return TSS_SUCCESS; 1523 } 1524 1525