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