1// This file was extracted from the TCG Published 2// Trusted Platform Module Library 3// Part 4: Supporting Routines 4// Family "2.0" 5// Level 00 Revision 01.16 6// October 30, 2014 7 8#define SESSION_PROCESS_C 9#include "InternalRoutines.h" 10#include "SessionProcess_fp.h" 11#include "Platform.h" 12// 13// 14// Authorization Support Functions 15// 16// IsDAExempted() 17// 18// This function indicates if a handle is exempted from DA logic. A handle is exempted if it is 19// a) a primary seed handle, 20// b) an object with noDA bit SET, 21// c) an NV Index with TPMA_NV_NO_DA bit SET, or 22// d) a PCR handle. 23// 24// Return Value Meaning 25// 26// TRUE handle is exempted from DA logic 27// FALSE handle is not exempted from DA logic 28// 29BOOL 30IsDAExempted( 31 TPM_HANDLE handle // IN: entity handle 32 ) 33{ 34 BOOL result = FALSE; 35 switch(HandleGetType(handle)) 36 { 37 case TPM_HT_PERMANENT: 38 // All permanent handles, other than TPM_RH_LOCKOUT, are exempt from 39 // DA protection. 40 result = (handle != TPM_RH_LOCKOUT); 41 break; 42 // When this function is called, a persistent object will have been loaded 43 // into an object slot and assigned a transient handle. 44 case TPM_HT_TRANSIENT: 45 { 46 OBJECT *object; 47 object = ObjectGet(handle); 48 result = (object->publicArea.objectAttributes.noDA == SET); 49 break; 50 } 51 case TPM_HT_NV_INDEX: 52 { 53 NV_INDEX nvIndex; 54 NvGetIndexInfo(handle, &nvIndex); 55 result = (nvIndex.publicArea.attributes.TPMA_NV_NO_DA == SET); 56 break; 57 } 58 case TPM_HT_PCR: 59 // PCRs are always exempted from DA. 60 result = TRUE; 61 break; 62 default: 63 break; 64 } 65 return result; 66} 67// 68// 69// IncrementLockout() 70// 71// This function is called after an authorization failure that involves use of an authValue. If the entity 72// referenced by the handle is not exempt from DA protection, then the failedTries counter will be 73// incremented. 74// 75// Error Returns Meaning 76// 77// TPM_RC_AUTH_FAIL authorization failure that caused DA lockout to increment 78// TPM_RC_BAD_AUTH authorization failure did not cause DA lockout to increment 79// 80static TPM_RC 81IncrementLockout( 82 UINT32 sessionIndex 83 ) 84{ 85 TPM_HANDLE handle = s_associatedHandles[sessionIndex]; 86 TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex]; 87 TPM_RC result; 88 SESSION *session = NULL; 89 // Don't increment lockout unless the handle associated with the session 90 // is DA protected or the session is bound to a DA protected entity. 91 if(sessionHandle == TPM_RS_PW) 92 { 93 if(IsDAExempted(handle)) 94 return TPM_RC_BAD_AUTH; 95 } 96 else 97 { 98 session = SessionGet(sessionHandle); 99 // If the session is bound to lockout, then use that as the relevant 100 // handle. This means that an auth failure with a bound session 101 // bound to lockoutAuth will take precedence over any other 102 // lockout check 103 if(session->attributes.isLockoutBound == SET) 104 handle = TPM_RH_LOCKOUT; 105 if( session->attributes.isDaBound == CLEAR 106 && IsDAExempted(handle) 107 ) 108 // If the handle was changed to TPM_RH_LOCKOUT, this will not return 109 // TPM_RC_BAD_AUTH 110 return TPM_RC_BAD_AUTH; 111 } 112 if(handle == TPM_RH_LOCKOUT) 113 { 114 pAssert(gp.lockOutAuthEnabled); 115 gp.lockOutAuthEnabled = FALSE; 116 // For TPM_RH_LOCKOUT, if lockoutRecovery is 0, no need to update NV since 117 // the lockout auth will be reset at startup. 118 if(gp.lockoutRecovery != 0) 119 { 120 result = NvIsAvailable(); 121 if(result != TPM_RC_SUCCESS) 122 { 123 // No NV access for now. Put the TPM in pending mode. 124 s_DAPendingOnNV = TRUE; 125 } 126 else 127 { 128 // Update NV. 129 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); 130 g_updateNV = TRUE; 131 } 132 } 133 } 134 else 135 { 136 if(gp.recoveryTime != 0) 137 { 138 gp.failedTries++; 139 result = NvIsAvailable(); 140 if(result != TPM_RC_SUCCESS) 141 { 142 // No NV access for now. Put the TPM in pending mode. 143 s_DAPendingOnNV = TRUE; 144 } 145 else 146 { 147 // Record changes to NV. 148 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); 149 g_updateNV = TRUE; 150 } 151 } 152 } 153 // Register a DA failure and reset the timers. 154 DARegisterFailure(handle); 155 return TPM_RC_AUTH_FAIL; 156} 157// 158// 159// IsSessionBindEntity() 160// 161// This function indicates if the entity associated with the handle is the entity, to which this session is bound. 162// The binding would occur by making the bind parameter in TPM2_StartAuthSession() not equal to 163// TPM_RH_NULL. The binding only occurs if the session is an HMAC session. The bind value is a 164// combination of the Name and the authValue of the entity. 165// 166// Return Value Meaning 167// 168// TRUE handle points to the session start entity 169// FALSE handle does not point to the session start entity 170// 171static BOOL 172IsSessionBindEntity( 173 TPM_HANDLE associatedHandle, // IN: handle to be authorized 174 SESSION *session // IN: associated session 175 ) 176{ 177 TPM2B_NAME entity; // The bind value for the entity 178 // If the session is not bound, return FALSE. 179 if(!session->attributes.isBound) 180 return FALSE; 181 // Compute the bind value for the entity. 182 SessionComputeBoundEntity(associatedHandle, &entity); 183 // Compare to the bind value in the session. 184 session->attributes.requestWasBound = 185 Memory2BEqual(&entity.b, &session->u1.boundEntity.b); 186 return session->attributes.requestWasBound; 187} 188// 189// 190// IsPolicySessionRequired() 191// 192// Checks if a policy session is required for a command. If a command requires DUP or ADMIN role 193// authorization, then the handle that requires that role is the first handle in the command. This simplifies 194// this checking. If a new command is created that requires multiple ADMIN role authorizations, then it will 195// have to be special-cased in this function. A policy session is required if: 196// a) the command requires the DUP role, 197// b) the command requires the ADMIN role and the authorized entity is an object and its adminWithPolicy 198// bit is SET, or 199// c) the command requires the ADMIN role and the authorized entity is a permanent handle or an NV 200// Index. 201// d) The authorized entity is a PCR belonging to a policy group, and has its policy initialized 202// 203// Return Value Meaning 204// 205// TRUE policy session is required 206// FALSE policy session is not required 207// 208static BOOL 209IsPolicySessionRequired( 210 TPM_CC commandCode, // IN: command code 211 UINT32 sessionIndex // IN: session index 212 ) 213{ 214 AUTH_ROLE role = CommandAuthRole(commandCode, sessionIndex); 215 TPM_HT type = HandleGetType(s_associatedHandles[sessionIndex]); 216 if(role == AUTH_DUP) 217 return TRUE; 218 if(role == AUTH_ADMIN) 219 { 220 if(type == TPM_HT_TRANSIENT) 221 { 222 OBJECT *object = ObjectGet(s_associatedHandles[sessionIndex]); 223 if(object->publicArea.objectAttributes.adminWithPolicy == CLEAR) 224 return FALSE; 225 } 226 return TRUE; 227 } 228// 229 if(type == TPM_HT_PCR) 230 { 231 if(PCRPolicyIsAvailable(s_associatedHandles[sessionIndex])) 232 { 233 TPM2B_DIGEST policy; 234 TPMI_ALG_HASH policyAlg; 235 policyAlg = PCRGetAuthPolicy(s_associatedHandles[sessionIndex], 236 &policy); 237 if(policyAlg != TPM_ALG_NULL) 238 return TRUE; 239 } 240 } 241 return FALSE; 242} 243// 244// 245// IsAuthValueAvailable() 246// 247// This function indicates if authValue is available and allowed for USER role authorization of an entity. 248// This function is similar to IsAuthPolicyAvailable() except that it does not check the size of the authValue 249// as IsAuthPolicyAvailable() does (a null authValue is a valid auth, but a null policy is not a valid policy). 250// This function does not check that the handle reference is valid or if the entity is in an enabled hierarchy. 251// Those checks are assumed to have been performed during the handle unmarshaling. 252// 253// Return Value Meaning 254// 255// TRUE authValue is available 256// FALSE authValue is not available 257// 258static BOOL 259IsAuthValueAvailable( 260 TPM_HANDLE handle, // IN: handle of entity 261 TPM_CC commandCode, // IN: commandCode 262 UINT32 sessionIndex // IN: session index 263 ) 264{ 265 BOOL result = FALSE; 266 // If a policy session is required, the entity can not be authorized by 267 // authValue. However, at this point, the policy session requirement should 268 // already have been checked. 269 pAssert(!IsPolicySessionRequired(commandCode, sessionIndex)); 270 switch(HandleGetType(handle)) 271 { 272 case TPM_HT_PERMANENT: 273 switch(handle) 274 { 275 // At this point hierarchy availability has already been 276 // checked so primary seed handles are always available here 277 case TPM_RH_OWNER: 278 case TPM_RH_ENDORSEMENT: 279 case TPM_RH_PLATFORM: 280#ifdef VENDOR_PERMANENT 281 // This vendor defined handle associated with the 282 // manufacturer's shared secret 283 case VENDOR_PERMANENT: 284#endif 285 // NullAuth is always available. 286 case TPM_RH_NULL: 287 // At the point when authValue availability is checked, control 288 // path has already passed the DA check so LockOut auth is 289 // always available here 290 case TPM_RH_LOCKOUT: 291 result = TRUE; 292 break; 293 default: 294 // Otherwise authValue is not available. 295 break; 296 } 297 break; 298 case TPM_HT_TRANSIENT: 299 // A persistent object has already been loaded and the internal 300 // handle changed. 301 { 302 OBJECT *object; 303 object = ObjectGet(handle); 304 // authValue is always available for a sequence object. 305 if(ObjectIsSequence(object)) 306 { 307 result = TRUE; 308 break; 309 } 310 // authValue is available for an object if it has its sensitive 311 // portion loaded and 312 // 1. userWithAuth bit is SET, or 313 // 2. ADMIN role is required 314 if( object->attributes.publicOnly == CLEAR 315 && (object->publicArea.objectAttributes.userWithAuth == SET 316 || (CommandAuthRole(commandCode, sessionIndex) == AUTH_ADMIN 317 && object->publicArea.objectAttributes.adminWithPolicy 318 == CLEAR))) 319 result = TRUE; 320 } 321 break; 322 case TPM_HT_NV_INDEX: 323 // NV Index. 324 { 325 NV_INDEX nvIndex; 326 NvGetIndexInfo(handle, &nvIndex); 327 if(IsWriteOperation(commandCode)) 328 { 329 if (nvIndex.publicArea.attributes.TPMA_NV_AUTHWRITE == SET) 330 result = TRUE; 331 } 332 else 333 { 334 if (nvIndex.publicArea.attributes.TPMA_NV_AUTHREAD == SET) 335 result = TRUE; 336 } 337 } 338 break; 339 case TPM_HT_PCR: 340 // PCR handle. 341 // authValue is always allowed for PCR 342 result = TRUE; 343 break; 344 default: 345 // Otherwise, authValue is not available 346 break; 347 } 348 return result; 349} 350// 351// 352// 353// IsAuthPolicyAvailable() 354// 355// This function indicates if an authPolicy is available and allowed. 356// This function does not check that the handle reference is valid or if the entity is in an enabled hierarchy. 357// Those checks are assumed to have been performed during the handle unmarshaling. 358// 359// Return Value Meaning 360// 361// TRUE authPolicy is available 362// FALSE authPolicy is not available 363// 364static BOOL 365IsAuthPolicyAvailable( 366 TPM_HANDLE handle, // IN: handle of entity 367 TPM_CC commandCode, // IN: commandCode 368 UINT32 sessionIndex // IN: session index 369 ) 370{ 371 BOOL result = FALSE; 372 switch(HandleGetType(handle)) 373 { 374 case TPM_HT_PERMANENT: 375 switch(handle) 376 { 377 // At this point hierarchy availability has already been checked. 378 case TPM_RH_OWNER: 379 if (gp.ownerPolicy.t.size != 0) 380 result = TRUE; 381 break; 382 case TPM_RH_ENDORSEMENT: 383 if (gp.endorsementPolicy.t.size != 0) 384 result = TRUE; 385 break; 386 case TPM_RH_PLATFORM: 387 if (gc.platformPolicy.t.size != 0) 388 result = TRUE; 389 break; 390 case TPM_RH_LOCKOUT: 391 if(gp.lockoutPolicy.t.size != 0) 392 result = TRUE; 393 break; 394 default: 395 break; 396 } 397 break; 398 case TPM_HT_TRANSIENT: 399 { 400 // Object handle. 401 // An evict object would already have been loaded and given a 402 // transient object handle by this point. 403 OBJECT *object = ObjectGet(handle); 404 // Policy authorization is not available for an object with only 405 // public portion loaded. 406 if(object->attributes.publicOnly == CLEAR) 407 { 408 // Policy authorization is always available for an object but 409 // is never available for a sequence. 410 if(!ObjectIsSequence(object)) 411 result = TRUE; 412 } 413 break; 414 } 415 case TPM_HT_NV_INDEX: 416 // An NV Index. 417 { 418 NV_INDEX nvIndex; 419 NvGetIndexInfo(handle, &nvIndex); 420 // If the policy size is not zero, check if policy can be used. 421 if(nvIndex.publicArea.authPolicy.t.size != 0) 422 { 423 // If policy session is required for this handle, always 424 // uses policy regardless of the attributes bit setting 425 if(IsPolicySessionRequired(commandCode, sessionIndex)) 426 result = TRUE; 427 // Otherwise, the presence of the policy depends on the NV 428 // attributes. 429 else if(IsWriteOperation(commandCode)) 430 { 431 if ( nvIndex.publicArea.attributes.TPMA_NV_POLICYWRITE 432 == SET) 433 result = TRUE; 434 } 435 else 436 { 437 if ( nvIndex.publicArea.attributes.TPMA_NV_POLICYREAD 438 == SET) 439 result = TRUE; 440 } 441 } 442 } 443 break; 444 case TPM_HT_PCR: 445 // PCR handle. 446 if(PCRPolicyIsAvailable(handle)) 447 result = TRUE; 448 break; 449 default: 450 break; 451 } 452 return result; 453} 454// 455// 456// Session Parsing Functions 457// 458// ComputeCpHash() 459// 460// This function computes the cpHash as defined in Part 2 and described in Part 1. 461// 462static void 463ComputeCpHash( 464 TPMI_ALG_HASH hashAlg, // IN: hash algorithm 465 TPM_CC commandCode, // IN: command code 466 UINT32 handleNum, // IN: number of handle 467 TPM_HANDLE handles[], // IN: array of handle 468 UINT32 parmBufferSize, // IN: size of input parameter area 469 BYTE *parmBuffer, // IN: input parameter area 470 TPM2B_DIGEST *cpHash, // OUT: cpHash 471 TPM2B_DIGEST *nameHash // OUT: name hash of command 472 ) 473{ 474 UINT32 i; 475 HASH_STATE hashState; 476 TPM2B_NAME name; 477// 478 // cpHash = hash(commandCode [ || authName1 479 // [ || authName2 480 // [ || authName 3 ]]] 481 // [ || parameters]) 482 // A cpHash can contain just a commandCode only if the lone session is 483 // an audit session. 484 // Start cpHash. 485 cpHash->t.size = CryptStartHash(hashAlg, &hashState); 486 // Add commandCode. 487 CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode); 488 // Add authNames for each of the handles. 489 for(i = 0; i < handleNum; i++) 490 { 491 name.t.size = EntityGetName(handles[i], &name.t.name); 492 CryptUpdateDigest2B(&hashState, &name.b); 493 } 494 // Add the parameters. 495 CryptUpdateDigest(&hashState, parmBufferSize, parmBuffer); 496 // Complete the hash. 497 CryptCompleteHash2B(&hashState, &cpHash->b); 498 // If the nameHash is needed, compute it here. 499 if(nameHash != NULL) 500 { 501 // Start name hash. hashState may be reused. 502 nameHash->t.size = CryptStartHash(hashAlg, &hashState); 503 // Adding names. 504 for(i = 0; i < handleNum; i++) 505 { 506 name.t.size = EntityGetName(handles[i], &name.t.name); 507 CryptUpdateDigest2B(&hashState, &name.b); 508 } 509 // Complete hash. 510 CryptCompleteHash2B(&hashState, &nameHash->b); 511 } 512 return; 513} 514// 515// 516// CheckPWAuthSession() 517// 518// This function validates the authorization provided in a PWAP session. It compares the input value to 519// authValue of the authorized entity. Argument sessionIndex is used to get handles handle of the 520// referenced entities from s_inputAuthValues[] and s_associatedHandles[]. 521// 522// Error Returns Meaning 523// 524// TPM_RC_AUTH_FAIL auth fails and increments DA failure count 525// TPM_RC_BAD_AUTH auth fails but DA does not apply 526// 527static TPM_RC 528CheckPWAuthSession( 529 UINT32 sessionIndex // IN: index of session to be processed 530 ) 531{ 532 TPM2B_AUTH authValue; 533 TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex]; 534 // Strip trailing zeros from the password. 535 MemoryRemoveTrailingZeros(&s_inputAuthValues[sessionIndex]); 536 // Get the auth value and size. 537 authValue.t.size = EntityGetAuthValue(associatedHandle, &authValue.t.buffer); 538 // Success if the digests are identical. 539 if(Memory2BEqual(&s_inputAuthValues[sessionIndex].b, &authValue.b)) 540 { 541 return TPM_RC_SUCCESS; 542 } 543 else // if the digests are not identical 544 { 545 // Invoke DA protection if applicable. 546 return IncrementLockout(sessionIndex); 547 } 548} 549// 550// 551// ComputeCommandHMAC() 552// 553// This function computes the HMAC for an authorization session in a command. 554// 555static void 556ComputeCommandHMAC( 557 UINT32 sessionIndex, // IN: index of session to be processed 558 TPM2B_DIGEST *cpHash, // IN: cpHash 559 TPM2B_DIGEST *hmac // OUT: authorization HMAC 560 ) 561{ 562 TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2)); 563 TPM2B_KEY key; 564 BYTE marshalBuffer[sizeof(TPMA_SESSION)]; 565 BYTE *buffer; 566 INT32 bufferSize; 567 UINT32 marshalSize; 568 HMAC_STATE hmacState; 569 TPM2B_NONCE *nonceDecrypt; 570 TPM2B_NONCE *nonceEncrypt; 571 SESSION *session; 572 TPM_HT sessionHandleType = 573 HandleGetType(s_sessionHandles[sessionIndex]); 574 nonceDecrypt = NULL; 575 nonceEncrypt = NULL; 576 // Determine if extra nonceTPM values are going to be required. 577 // If this is the first session (sessionIndex = 0) and it is an authorization 578 // session that uses an HMAC, then check if additional session nonces are to be 579 // included. 580 if( sessionIndex == 0 581 && s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) 582 { 583 // If there is a decrypt session and if this is not the decrypt session, 584 // then an extra nonce may be needed. 585 if( s_decryptSessionIndex != UNDEFINED_INDEX 586 && s_decryptSessionIndex != sessionIndex) 587 { 588 // Will add the nonce for the decrypt session. 589 SESSION *decryptSession 590 = SessionGet(s_sessionHandles[s_decryptSessionIndex]); 591 nonceDecrypt = &decryptSession->nonceTPM; 592 } 593 // Now repeat for the encrypt session. 594 if( s_encryptSessionIndex != UNDEFINED_INDEX 595 && s_encryptSessionIndex != sessionIndex 596// 597 && s_encryptSessionIndex != s_decryptSessionIndex) 598 { 599 // Have to have the nonce for the encrypt session. 600 SESSION *encryptSession 601 = SessionGet(s_sessionHandles[s_encryptSessionIndex]); 602 nonceEncrypt = &encryptSession->nonceTPM; 603 } 604 } 605 // Continue with the HMAC processing. 606 session = SessionGet(s_sessionHandles[sessionIndex]); 607 // Generate HMAC key. 608 MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); 609 // Check if the session has an associated handle and if the associated entity 610 // is the one to which the session is bound. If not, add the authValue of 611 // this entity to the HMAC key. 612 // If the session is bound to the object or the session is a policy session 613 // with no authValue required, do not include the authValue in the HMAC key. 614 // Note: For a policy session, its isBound attribute is CLEARED. 615 // If the session isn't used for authorization, then there is no auth value 616 // to add 617 if(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) 618 { 619 // used for auth so see if this is a policy session with authValue needed 620 // or an hmac session that is not bound 621 if (((sessionHandleType == TPM_HT_POLICY_SESSION) 622 && (session->attributes.isAuthValueNeeded == SET)) 623 || ((sessionHandleType == TPM_HT_HMAC_SESSION) 624 && !IsSessionBindEntity(s_associatedHandles[sessionIndex], session)) 625 ) 626 { 627 // add the authValue to the HMAC key 628 pAssert((sizeof(AUTH_VALUE) + key.t.size) <= sizeof(key.t.buffer)); 629 key.t.size = key.t.size 630 + EntityGetAuthValue(s_associatedHandles[sessionIndex], 631 (AUTH_VALUE *)&(key.t.buffer[key.t.size])); 632 } 633 } 634 // if the HMAC key size is 0, a NULL string HMAC is allowed 635 if( key.t.size == 0 636 && s_inputAuthValues[sessionIndex].t.size == 0) 637 { 638 hmac->t.size = 0; 639 return; 640 } 641 // Start HMAC 642 hmac->t.size = CryptStartHMAC2B(session->authHashAlg, &key.b, &hmacState); 643 // Add cpHash 644 CryptUpdateDigest2B(&hmacState, &cpHash->b); 645 // Add nonceCaller 646 CryptUpdateDigest2B(&hmacState, &s_nonceCaller[sessionIndex].b); 647 // Add nonceTPM 648 CryptUpdateDigest2B(&hmacState, &session->nonceTPM.b); 649 // If needed, add nonceTPM for decrypt session 650 if(nonceDecrypt != NULL) 651 CryptUpdateDigest2B(&hmacState, &nonceDecrypt->b); 652 // If needed, add nonceTPM for encrypt session 653 if(nonceEncrypt != NULL) 654 CryptUpdateDigest2B(&hmacState, &nonceEncrypt->b); 655 // Add sessionAttributes 656 buffer = marshalBuffer; 657 bufferSize = sizeof(TPMA_SESSION); 658 marshalSize = TPMA_SESSION_Marshal(&(s_attributes[sessionIndex]), 659 &buffer, &bufferSize); 660 CryptUpdateDigest(&hmacState, marshalSize, marshalBuffer); 661 // Complete the HMAC computation 662 CryptCompleteHMAC2B(&hmacState, &hmac->b); 663 return; 664} 665// 666// 667// CheckSessionHMAC() 668// 669// This function checks the HMAC of in a session. It uses ComputeCommandHMAC() to compute the 670// expected HMAC value and then compares the result with the HMAC in the authorization session. The 671// authorization is successful if they are the same. 672// If the authorizations are not the same, IncrementLockout() is called. It will return TPM_RC_AUTH_FAIL if 673// the failure caused the failureCount to increment. Otherwise, it will return TPM_RC_BAD_AUTH. 674// 675// Error Returns Meaning 676// 677// TPM_RC_AUTH_FAIL auth failure caused failureCount increment 678// TPM_RC_BAD_AUTH auth failure did not cause failureCount increment 679// 680static TPM_RC 681CheckSessionHMAC( 682 UINT32 sessionIndex, // IN: index of session to be processed 683 TPM2B_DIGEST *cpHash // IN: cpHash of the command 684 ) 685{ 686 TPM2B_DIGEST hmac; // authHMAC for comparing 687 // Compute authHMAC 688 ComputeCommandHMAC(sessionIndex, cpHash, &hmac); 689 // Compare the input HMAC with the authHMAC computed above. 690 if(!Memory2BEqual(&s_inputAuthValues[sessionIndex].b, &hmac.b)) 691 { 692 // If an HMAC session has a failure, invoke the anti-hammering 693 // if it applies to the authorized entity or the session. 694 // Otherwise, just indicate that the authorization is bad. 695 return IncrementLockout(sessionIndex); 696 } 697 return TPM_RC_SUCCESS; 698} 699// 700// 701// CheckPolicyAuthSession() 702// 703// This function is used to validate the authorization in a policy session. This function performs the following 704// comparisons to see if a policy authorization is properly provided. The check are: 705// a) compare policyDigest in session with authPolicy associated with the entity to be authorized; 706// b) compare timeout if applicable; 707// c) compare commandCode if applicable; 708// 709// d) compare cpHash if applicable; and 710// e) see if PCR values have changed since computed. 711// If all the above checks succeed, the handle is authorized. The order of these comparisons is not 712// important because any failure will result in the same error code. 713// 714// Error Returns Meaning 715// 716// TPM_RC_PCR_CHANGED PCR value is not current 717// TPM_RC_POLICY_FAIL policy session fails 718// TPM_RC_LOCALITY command locality is not allowed 719// TPM_RC_POLICY_CC CC doesn't match 720// TPM_RC_EXPIRED policy session has expired 721// TPM_RC_PP PP is required but not asserted 722// TPM_RC_NV_UNAVAILABLE NV is not available for write 723// TPM_RC_NV_RATE NV is rate limiting 724// 725static TPM_RC 726CheckPolicyAuthSession( 727 UINT32 sessionIndex, // IN: index of session to be processed 728 TPM_CC commandCode, // IN: command code 729 TPM2B_DIGEST *cpHash, // IN: cpHash using the algorithm of this 730 // session 731 TPM2B_DIGEST *nameHash // IN: nameHash using the session algorithm 732 ) 733{ 734 TPM_RC result = TPM_RC_SUCCESS; 735 SESSION *session; 736 TPM2B_DIGEST authPolicy; 737 TPMI_ALG_HASH policyAlg; 738 UINT8 locality; 739 // Initialize pointer to the auth session. 740 session = SessionGet(s_sessionHandles[sessionIndex]); 741 // If the command is TPM_RC_PolicySecret(), make sure that 742 // either password or authValue is required 743 if( commandCode == TPM_CC_PolicySecret 744 && session->attributes.isPasswordNeeded == CLEAR 745 && session->attributes.isAuthValueNeeded == CLEAR) 746 return TPM_RC_MODE; 747 // See if the PCR counter for the session is still valid. 748 if( !SessionPCRValueIsCurrent(s_sessionHandles[sessionIndex]) ) 749 return TPM_RC_PCR_CHANGED; 750 // Get authPolicy. 751 policyAlg = EntityGetAuthPolicy(s_associatedHandles[sessionIndex], 752 &authPolicy); 753 // Compare authPolicy. 754 if(!Memory2BEqual(&session->u2.policyDigest.b, &authPolicy.b)) 755 return TPM_RC_POLICY_FAIL; 756 // Policy is OK so check if the other factors are correct 757 // Compare policy hash algorithm. 758 if(policyAlg != session->authHashAlg) 759 return TPM_RC_POLICY_FAIL; 760 // Compare timeout. 761 if(session->timeOut != 0) 762 { 763 // Cannot compare time if clock stop advancing. An TPM_RC_NV_UNAVAILABLE 764 // or TPM_RC_NV_RATE error may be returned here. 765 result = NvIsAvailable(); 766 if(result != TPM_RC_SUCCESS) 767 return result; 768 if(session->timeOut < go.clock) 769 return TPM_RC_EXPIRED; 770 } 771 // If command code is provided it must match 772 if(session->commandCode != 0) 773 { 774 if(session->commandCode != commandCode) 775 return TPM_RC_POLICY_CC; 776 } 777 else 778 { 779 // If command requires a DUP or ADMIN authorization, the session must have 780 // command code set. 781 AUTH_ROLE role = CommandAuthRole(commandCode, sessionIndex); 782 if(role == AUTH_ADMIN || role == AUTH_DUP) 783 return TPM_RC_POLICY_FAIL; 784 } 785 // Check command locality. 786 { 787 BYTE sessionLocality[sizeof(TPMA_LOCALITY)]; 788 BYTE *buffer = sessionLocality; 789 INT32 bufferSize = sizeof(TPMA_LOCALITY); 790 // Get existing locality setting in canonical form 791 TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, &bufferSize); 792 // See if the locality has been set 793 if(sessionLocality[0] != 0) 794 { 795 // If so, get the current locality 796 locality = _plat__LocalityGet(); 797 if (locality < 5) 798 { 799 if( ((sessionLocality[0] & (1 << locality)) == 0) 800 || sessionLocality[0] > 31) 801 return TPM_RC_LOCALITY; 802 } 803 else if (locality > 31) 804 { 805 if(sessionLocality[0] != locality) 806 return TPM_RC_LOCALITY; 807 } 808 else 809 { 810 // Could throw an assert here but a locality error is just 811 // as good. It just means that, whatever the locality is, it isn't 812 // the locality requested so... 813 return TPM_RC_LOCALITY; 814 } 815 } 816 } // end of locality check 817 // Check physical presence. 818 if( session->attributes.isPPRequired == SET 819 && !_plat__PhysicalPresenceAsserted()) 820 return TPM_RC_PP; 821 // Compare cpHash/nameHash if defined, or if the command requires an ADMIN or 822 // DUP role for this handle. 823 if(session->u1.cpHash.b.size != 0) 824 { 825 if(session->attributes.iscpHashDefined) 826 { 827 // Compare cpHash. 828 if(!Memory2BEqual(&session->u1.cpHash.b, &cpHash->b)) 829 return TPM_RC_POLICY_FAIL; 830 } 831 else 832 { 833 // Compare nameHash. 834 // When cpHash is not defined, nameHash is placed in its space. 835 if(!Memory2BEqual(&session->u1.cpHash.b, &nameHash->b)) 836 return TPM_RC_POLICY_FAIL; 837 } 838 } 839 if(session->attributes.checkNvWritten) 840 { 841 NV_INDEX nvIndex; 842 // If this is not an NV index, the policy makes no sense so fail it. 843 if(HandleGetType(s_associatedHandles[sessionIndex])!= TPM_HT_NV_INDEX) 844 return TPM_RC_POLICY_FAIL; 845 // Get the index data 846 NvGetIndexInfo(s_associatedHandles[sessionIndex], &nvIndex); 847 // Make sure that the TPMA_WRITTEN_ATTRIBUTE has the desired state 848 if( (nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET) 849 != (session->attributes.nvWrittenState == SET)) 850 return TPM_RC_POLICY_FAIL; 851 } 852 return TPM_RC_SUCCESS; 853} 854// 855// 856// RetrieveSessionData() 857// 858// This function will unmarshal the sessions in the session area of a command. The values are placed in the 859// arrays that are defined at the beginning of this file. The normal unmarshaling errors are possible. 860// 861// Error Returns Meaning 862// 863// TPM_RC_SUCCSS unmarshaled without error 864// TPM_RC_SIZE the number of bytes unmarshaled is not the same as the value for 865// authorizationSize in the command 866// 867static TPM_RC 868RetrieveSessionData ( 869 TPM_CC commandCode, // IN: command code 870 UINT32 *sessionCount, // OUT: number of sessions found 871 BYTE *sessionBuffer, // IN: pointer to the session buffer 872 INT32 bufferSize // IN: size of the session buffer 873 ) 874{ 875 int sessionIndex; 876 int i; 877 TPM_RC result; 878 SESSION *session; 879 TPM_HT sessionType; 880 s_decryptSessionIndex = UNDEFINED_INDEX; 881 s_encryptSessionIndex = UNDEFINED_INDEX; 882 s_auditSessionIndex = UNDEFINED_INDEX; 883 for(sessionIndex = 0; bufferSize > 0; sessionIndex++) 884 { 885 // If maximum allowed number of sessions has been parsed, return a size 886 // error with a session number that is larger than the number of allowed 887 // sessions 888 if(sessionIndex == MAX_SESSION_NUM) 889 return TPM_RC_SIZE + TPM_RC_S + g_rcIndex[sessionIndex+1]; 890 // make sure that the associated handle for each session starts out 891 // unassigned 892 s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED; 893 // First parameter: Session handle. 894 result = TPMI_SH_AUTH_SESSION_Unmarshal(&s_sessionHandles[sessionIndex], 895 &sessionBuffer, &bufferSize, TRUE); 896 if(result != TPM_RC_SUCCESS) 897 return result + TPM_RC_S + g_rcIndex[sessionIndex]; 898 // Second parameter: Nonce. 899 result = TPM2B_NONCE_Unmarshal(&s_nonceCaller[sessionIndex], 900 &sessionBuffer, &bufferSize); 901 if(result != TPM_RC_SUCCESS) 902 return result + TPM_RC_S + g_rcIndex[sessionIndex]; 903 // Third parameter: sessionAttributes. 904 result = TPMA_SESSION_Unmarshal(&s_attributes[sessionIndex], 905 &sessionBuffer, &bufferSize); 906 if(result != TPM_RC_SUCCESS) 907 return result + TPM_RC_S + g_rcIndex[sessionIndex]; 908 // Fourth parameter: authValue (PW or HMAC). 909 result = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[sessionIndex], 910 &sessionBuffer, &bufferSize); 911 if(result != TPM_RC_SUCCESS) 912 return result + TPM_RC_S + g_rcIndex[sessionIndex]; 913 if(s_sessionHandles[sessionIndex] == TPM_RS_PW) 914 { 915 // A PWAP session needs additional processing. 916 // Can't have any attributes set other than continueSession bit 917 if( s_attributes[sessionIndex].encrypt 918 || s_attributes[sessionIndex].decrypt 919 || s_attributes[sessionIndex].audit 920 || s_attributes[sessionIndex].auditExclusive 921 || s_attributes[sessionIndex].auditReset 922 ) 923 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; 924 // The nonce size must be zero. 925 if(s_nonceCaller[sessionIndex].t.size != 0) 926 return TPM_RC_NONCE + TPM_RC_S + g_rcIndex[sessionIndex]; 927 continue; 928 } 929 // For not password sessions... 930 // Find out if the session is loaded. 931 if(!SessionIsLoaded(s_sessionHandles[sessionIndex])) 932 return TPM_RC_REFERENCE_S0 + sessionIndex; 933 sessionType = HandleGetType(s_sessionHandles[sessionIndex]); 934 session = SessionGet(s_sessionHandles[sessionIndex]); 935 // Check if the session is an HMAC/policy session. 936 if( ( session->attributes.isPolicy == SET 937 && sessionType == TPM_HT_HMAC_SESSION 938 ) 939 || ( session->attributes.isPolicy == CLEAR 940 && sessionType == TPM_HT_POLICY_SESSION 941 ) 942 ) 943 return TPM_RC_HANDLE + TPM_RC_S + g_rcIndex[sessionIndex]; 944 // Check that this handle has not previously been used. 945 for(i = 0; i < sessionIndex; i++) 946 { 947 if(s_sessionHandles[i] == s_sessionHandles[sessionIndex]) 948 return TPM_RC_HANDLE + TPM_RC_S + g_rcIndex[sessionIndex]; 949 } 950 // If the session is used for parameter encryption or audit as well, set 951 // the corresponding indices. 952 // First process decrypt. 953 if(s_attributes[sessionIndex].decrypt) 954 { 955 // Check if the commandCode allows command parameter encryption. 956 if(DecryptSize(commandCode) == 0) 957 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; 958 // Encrypt attribute can only appear in one session 959 if(s_decryptSessionIndex != UNDEFINED_INDEX) 960 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; 961 // Can't decrypt if the session's symmetric algorithm is TPM_ALG_NULL 962 if(session->symmetric.algorithm == TPM_ALG_NULL) 963 return TPM_RC_SYMMETRIC + TPM_RC_S + g_rcIndex[sessionIndex]; 964 // All checks passed, so set the index for the session used to decrypt 965 // a command parameter. 966 s_decryptSessionIndex = sessionIndex; 967 } 968 // Now process encrypt. 969 if(s_attributes[sessionIndex].encrypt) 970 { 971 // Check if the commandCode allows response parameter encryption. 972 if(EncryptSize(commandCode) == 0) 973 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; 974 // Encrypt attribute can only appear in one session. 975 if(s_encryptSessionIndex != UNDEFINED_INDEX) 976 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; 977 // Can't encrypt if the session's symmetric algorithm is TPM_ALG_NULL 978 if(session->symmetric.algorithm == TPM_ALG_NULL) 979 return TPM_RC_SYMMETRIC + TPM_RC_S + g_rcIndex[sessionIndex]; 980 // All checks passed, so set the index for the session used to encrypt 981 // a response parameter. 982 s_encryptSessionIndex = sessionIndex; 983 } 984 // At last process audit. 985 if(s_attributes[sessionIndex].audit) 986 { 987 // Audit attribute can only appear in one session. 988 if(s_auditSessionIndex != UNDEFINED_INDEX) 989 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; 990 // An audit session can not be policy session. 991 if( HandleGetType(s_sessionHandles[sessionIndex]) 992 == TPM_HT_POLICY_SESSION) 993 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; 994 // If this is a reset of the audit session, or the first use 995 // of the session as an audit session, it doesn't matter what 996 // the exclusive state is. The session will become exclusive. 997 if( s_attributes[sessionIndex].auditReset == CLEAR 998 && session->attributes.isAudit == SET) 999 { 1000 // Not first use or reset. If auditExlusive is SET, then this 1001 // session must be the current exclusive session. 1002 if( s_attributes[sessionIndex].auditExclusive == SET 1003 && g_exclusiveAuditSession != s_sessionHandles[sessionIndex]) 1004 return TPM_RC_EXCLUSIVE; 1005 } 1006 s_auditSessionIndex = sessionIndex; 1007 } 1008 // Initialize associated handle as undefined. This will be changed when 1009 // the handles are processed. 1010 s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED; 1011 } 1012 // Set the number of sessions found. 1013 *sessionCount = sessionIndex; 1014 return TPM_RC_SUCCESS; 1015} 1016// 1017// 1018// CheckLockedOut() 1019// 1020// This function checks to see if the TPM is in lockout. This function should only be called if the entity being 1021// checked is subject to DA protection. The TPM is in lockout if the NV is not available and a DA write is 1022// pending. Otherwise the TPM is locked out if checking for lockoutAuth (lockoutAuthCheck == TRUE) and 1023// use of lockoutAuth is disabled, or failedTries >= maxTries 1024// 1025// Error Returns Meaning 1026// 1027// TPM_RC_NV_RATE NV is rate limiting 1028// TPM_RC_NV_UNAVAILABLE NV is not available at this time 1029// TPM_RC_LOCKOUT TPM is in lockout 1030// 1031static TPM_RC 1032CheckLockedOut( 1033 BOOL lockoutAuthCheck // IN: TRUE if checking is for lockoutAuth 1034 ) 1035{ 1036 TPM_RC result; 1037 // If NV is unavailable, and current cycle state recorded in NV is not 1038 // SHUTDOWN_NONE, refuse to check any authorization because we would 1039 // not be able to handle a DA failure. 1040 result = NvIsAvailable(); 1041 if(result != TPM_RC_SUCCESS && gp.orderlyState != SHUTDOWN_NONE) 1042 return result; 1043 // Check if DA info needs to be updated in NV. 1044 if(s_DAPendingOnNV) 1045 { 1046 // If NV is accessible, ... 1047 if(result == TPM_RC_SUCCESS) 1048 { 1049 // ... write the pending DA data and proceed. 1050 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, 1051 &gp.lockOutAuthEnabled); 1052 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); 1053 g_updateNV = TRUE; 1054 s_DAPendingOnNV = FALSE; 1055 } 1056 else 1057 { 1058 // Otherwise no authorization can be checked. 1059 return result; 1060 } 1061 } 1062 // Lockout is in effect if checking for lockoutAuth and use of lockoutAuth 1063 // is disabled... 1064 if(lockoutAuthCheck) 1065 { 1066 if(gp.lockOutAuthEnabled == FALSE) 1067 return TPM_RC_LOCKOUT; 1068 } 1069 else 1070 { 1071 // ... or if the number of failed tries has been maxed out. 1072 if(gp.failedTries >= gp.maxTries) 1073 return TPM_RC_LOCKOUT; 1074 } 1075 return TPM_RC_SUCCESS; 1076} 1077// 1078// 1079// CheckAuthSession() 1080// 1081// This function checks that the authorization session properly authorizes the use of the associated handle. 1082// 1083// Error Returns Meaning 1084// 1085// TPM_RC_LOCKOUT entity is protected by DA and TPM is in lockout, or TPM is locked out 1086// on NV update pending on DA parameters 1087// TPM_RC_PP Physical Presence is required but not provided 1088// TPM_RC_AUTH_FAIL HMAC or PW authorization failed with DA side-effects (can be a 1089// policy session) 1090// TPM_RC_BAD_AUTH HMAC or PW authorization failed without DA side-effects (can be a 1091// policy session) 1092// TPM_RC_POLICY_FAIL if policy session fails 1093// TPM_RC_POLICY_CC command code of policy was wrong 1094// TPM_RC_EXPIRED the policy session has expired 1095// TPM_RC_PCR ??? 1096// TPM_RC_AUTH_UNAVAILABLE authValue or authPolicy unavailable 1097// 1098static TPM_RC 1099CheckAuthSession( 1100 TPM_CC commandCode, // IN: commandCode 1101 UINT32 sessionIndex, // IN: index of session to be processed 1102 TPM2B_DIGEST *cpHash, // IN: cpHash 1103 TPM2B_DIGEST *nameHash // IN: nameHash 1104// 1105 ) 1106{ 1107 TPM_RC result; 1108 SESSION *session = NULL; 1109 TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex]; 1110 TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex]; 1111 TPM_HT sessionHandleType = HandleGetType(sessionHandle); 1112 pAssert(sessionHandle != TPM_RH_UNASSIGNED); 1113 if(sessionHandle != TPM_RS_PW) 1114 session = SessionGet(sessionHandle); 1115 pAssert(sessionHandleType != TPM_HT_POLICY_SESSION || session != NULL); 1116 // If the authorization session is not a policy session, or if the policy 1117 // session requires authorization, then check lockout. 1118 if( sessionHandleType != TPM_HT_POLICY_SESSION 1119 || session->attributes.isAuthValueNeeded 1120 || session->attributes.isPasswordNeeded) 1121 { 1122 // See if entity is subject to lockout. 1123 if(!IsDAExempted(associatedHandle)) 1124 { 1125 // If NV is unavailable, and current cycle state recorded in NV is not 1126 // SHUTDOWN_NONE, refuse to check any authorization because we would 1127 // not be able to handle a DA failure. 1128 result = CheckLockedOut(associatedHandle == TPM_RH_LOCKOUT); 1129 if(result != TPM_RC_SUCCESS) 1130 return result; 1131 } 1132 } 1133 if(associatedHandle == TPM_RH_PLATFORM) 1134 { 1135 // If the physical presence is required for this command, check for PP 1136 // assertion. If it isn't asserted, no point going any further. 1137 if( PhysicalPresenceIsRequired(commandCode) 1138 && !_plat__PhysicalPresenceAsserted() 1139 ) 1140 return TPM_RC_PP; 1141 } 1142 // If a policy session is required, make sure that it is being used. 1143 if( IsPolicySessionRequired(commandCode, sessionIndex) 1144 && sessionHandleType != TPM_HT_POLICY_SESSION) 1145 return TPM_RC_AUTH_TYPE; 1146 // If this is a PW authorization, check it and return. 1147 if(sessionHandle == TPM_RS_PW) 1148 { 1149 if(IsAuthValueAvailable(associatedHandle, commandCode, sessionIndex)) 1150 return CheckPWAuthSession(sessionIndex); 1151 else 1152 return TPM_RC_AUTH_UNAVAILABLE; 1153 } 1154 // If this is a policy session, ... 1155 if(sessionHandleType == TPM_HT_POLICY_SESSION) 1156 { 1157 // ... see if the entity has a policy, ... 1158 if( !IsAuthPolicyAvailable(associatedHandle, commandCode, sessionIndex)) 1159 return TPM_RC_AUTH_UNAVAILABLE; 1160 // ... and check the policy session. 1161 result = CheckPolicyAuthSession(sessionIndex, commandCode, 1162 cpHash, nameHash); 1163 if (result != TPM_RC_SUCCESS) 1164 return result; 1165 } 1166 else 1167 { 1168 // For non policy, the entity being accessed must allow authorization 1169 // with an auth value. This is required even if the auth value is not 1170 // going to be used in an HMAC because it is bound. 1171 if(!IsAuthValueAvailable(associatedHandle, commandCode, sessionIndex)) 1172 return TPM_RC_AUTH_UNAVAILABLE; 1173 } 1174 // At this point, the session must be either a policy or an HMAC session. 1175 session = SessionGet(s_sessionHandles[sessionIndex]); 1176 if( sessionHandleType == TPM_HT_POLICY_SESSION 1177 && session->attributes.isPasswordNeeded == SET) 1178 { 1179 // For policy session that requires a password, check it as PWAP session. 1180 return CheckPWAuthSession(sessionIndex); 1181 } 1182 else 1183 { 1184 // For other policy or HMAC sessions, have its HMAC checked. 1185 return CheckSessionHMAC(sessionIndex, cpHash); 1186 } 1187} 1188#ifdef TPM_CC_GetCommandAuditDigest 1189// 1190// 1191// CheckCommandAudit() 1192// 1193// This function checks if the current command may trigger command audit, and if it is safe to perform the 1194// action. 1195// 1196// Error Returns Meaning 1197// 1198// TPM_RC_NV_UNAVAILABLE NV is not available for write 1199// TPM_RC_NV_RATE NV is rate limiting 1200// 1201static TPM_RC 1202CheckCommandAudit( 1203 TPM_CC commandCode, // IN: Command code 1204 UINT32 handleNum, // IN: number of element in handle array 1205 TPM_HANDLE handles[], // IN: array of handle 1206 BYTE *parmBufferStart, // IN: start of parameter buffer 1207 UINT32 parmBufferSize // IN: size of parameter buffer 1208 ) 1209{ 1210 TPM_RC result = TPM_RC_SUCCESS; 1211 // If audit is implemented, need to check to see if auditing is being done 1212 // for this command. 1213 if(CommandAuditIsRequired(commandCode)) 1214 { 1215 // If the audit digest is clear and command audit is required, NV must be 1216 // available so that TPM2_GetCommandAuditDigest() is able to increment 1217 // audit counter. If NV is not available, the function bails out to prevent 1218 // the TPM from attempting an operation that would fail anyway. 1219 if( gr.commandAuditDigest.t.size == 0 1220 || commandCode == TPM_CC_GetCommandAuditDigest) 1221 { 1222 result = NvIsAvailable(); 1223 if(result != TPM_RC_SUCCESS) 1224 return result; 1225 } 1226 ComputeCpHash(gp.auditHashAlg, commandCode, handleNum, 1227 handles, parmBufferSize, parmBufferStart, 1228 &s_cpHashForCommandAudit, NULL); 1229 } 1230 return TPM_RC_SUCCESS; 1231} 1232#endif 1233// 1234// 1235// ParseSessionBuffer() 1236// 1237// This function is the entry function for command session processing. It iterates sessions in session area 1238// and reports if the required authorization has been properly provided. It also processes audit session and 1239// passes the information of encryption sessions to parameter encryption module. 1240// 1241// Error Returns Meaning 1242// 1243// various parsing failure or authorization failure 1244// 1245TPM_RC 1246ParseSessionBuffer( 1247 TPM_CC commandCode, // IN: Command code 1248 UINT32 handleNum, // IN: number of element in handle array 1249 TPM_HANDLE handles[], // IN: array of handle 1250 BYTE *sessionBufferStart, // IN: start of session buffer 1251 UINT32 sessionBufferSize, // IN: size of session buffer 1252 BYTE *parmBufferStart, // IN: start of parameter buffer 1253 UINT32 parmBufferSize // IN: size of parameter buffer 1254 ) 1255{ 1256 TPM_RC result; 1257 UINT32 i; 1258 INT32 size = 0; 1259 TPM2B_AUTH extraKey; 1260 UINT32 sessionIndex; 1261 SESSION *session; 1262 TPM2B_DIGEST cpHash; 1263 TPM2B_DIGEST nameHash; 1264 TPM_ALG_ID cpHashAlg = TPM_ALG_NULL; // algID for the last computed 1265 // cpHash 1266 // Check if a command allows any session in its session area. 1267 if(!IsSessionAllowed(commandCode)) 1268 return TPM_RC_AUTH_CONTEXT; 1269 // Default-initialization. 1270 s_sessionNum = 0; 1271 cpHash.t.size = 0; 1272 result = RetrieveSessionData(commandCode, &s_sessionNum, 1273 sessionBufferStart, sessionBufferSize); 1274 if(result != TPM_RC_SUCCESS) 1275 return result; 1276 // There is no command in the TPM spec that has more handles than 1277 // MAX_SESSION_NUM. 1278 pAssert(handleNum <= MAX_SESSION_NUM); 1279 // Associate the session with an authorization handle. 1280 for(i = 0; i < handleNum; i++) 1281 { 1282 if(CommandAuthRole(commandCode, i) != AUTH_NONE) 1283 { 1284 // If the received session number is less than the number of handle 1285 // that requires authorization, an error should be returned. 1286 // Note: for all the TPM 2.0 commands, handles requiring 1287 // authorization come first in a command input. 1288 if(i > (s_sessionNum - 1)) 1289 return TPM_RC_AUTH_MISSING; 1290 // Record the handle associated with the authorization session 1291 s_associatedHandles[i] = handles[i]; 1292 } 1293 } 1294 // Consistency checks are done first to avoid auth failure when the command 1295 // will not be executed anyway. 1296 for(sessionIndex = 0; sessionIndex < s_sessionNum; sessionIndex++) 1297 { 1298 // PW session must be an authorization session 1299 if(s_sessionHandles[sessionIndex] == TPM_RS_PW ) 1300 { 1301 if(s_associatedHandles[sessionIndex] == TPM_RH_UNASSIGNED) 1302 return TPM_RC_HANDLE + g_rcIndex[sessionIndex]; 1303 } 1304 else 1305 { 1306 session = SessionGet(s_sessionHandles[sessionIndex]); 1307 // A trial session can not appear in session area, because it cannot 1308 // be used for authorization, audit or encrypt/decrypt. 1309 if(session->attributes.isTrialPolicy == SET) 1310 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; 1311 // See if the session is bound to a DA protected entity 1312 // NOTE: Since a policy session is never bound, a policy is still 1313 // usable even if the object is DA protected and the TPM is in 1314 // lockout. 1315 if(session->attributes.isDaBound == SET) 1316 { 1317 result = CheckLockedOut(session->attributes.isLockoutBound == SET); 1318 if(result != TPM_RC_SUCCESS) 1319 return result; 1320 } 1321 // If the current cpHash is the right one, don't re-compute. 1322 if(cpHashAlg != session->authHashAlg) // different so compute 1323 { 1324 cpHashAlg = session->authHashAlg; // save this new algID 1325 ComputeCpHash(session->authHashAlg, commandCode, handleNum, 1326 handles, parmBufferSize, parmBufferStart, 1327 &cpHash, &nameHash); 1328 } 1329 // If this session is for auditing, save the cpHash. 1330 if(s_attributes[sessionIndex].audit) 1331 s_cpHashForAudit = cpHash; 1332 } 1333 // if the session has an associated handle, check the auth 1334 if(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) 1335 { 1336 result = CheckAuthSession(commandCode, sessionIndex, 1337 &cpHash, &nameHash); 1338 if(result != TPM_RC_SUCCESS) 1339 return RcSafeAddToResult(result, 1340 TPM_RC_S + g_rcIndex[sessionIndex]); 1341 } 1342 else 1343 { 1344 // a session that is not for authorization must either be encrypt, 1345 // decrypt, or audit 1346 if( s_attributes[sessionIndex].audit == CLEAR 1347 && s_attributes[sessionIndex].encrypt == CLEAR 1348 && s_attributes[sessionIndex].decrypt == CLEAR) 1349 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; 1350 // check HMAC for encrypt/decrypt/audit only sessions 1351 result = CheckSessionHMAC(sessionIndex, &cpHash); 1352 if(result != TPM_RC_SUCCESS) 1353 return RcSafeAddToResult(result, 1354 TPM_RC_S + g_rcIndex[sessionIndex]); 1355 } 1356 } 1357#ifdef TPM_CC_GetCommandAuditDigest 1358 // Check if the command should be audited. 1359 result = CheckCommandAudit(commandCode, handleNum, handles, 1360 parmBufferStart, parmBufferSize); 1361 if(result != TPM_RC_SUCCESS) 1362 return result; // No session number to reference 1363#endif 1364 // Decrypt the first parameter if applicable. This should be the last operation 1365 // in session processing. 1366 // If the encrypt session is associated with a handle and the handle's 1367 // authValue is available, then authValue is concatenated with sessionAuth to 1368 // generate encryption key, no matter if the handle is the session bound entity 1369 // or not. 1370 if(s_decryptSessionIndex != UNDEFINED_INDEX) 1371 { 1372 // Get size of the leading size field in decrypt parameter 1373 if( s_associatedHandles[s_decryptSessionIndex] != TPM_RH_UNASSIGNED 1374 && IsAuthValueAvailable(s_associatedHandles[s_decryptSessionIndex], 1375 commandCode, 1376 s_decryptSessionIndex) 1377 ) 1378 { 1379 extraKey.b.size= 1380 EntityGetAuthValue(s_associatedHandles[s_decryptSessionIndex], 1381 &extraKey.t.buffer); 1382 } 1383 else 1384 { 1385 extraKey.b.size = 0; 1386 } 1387 size = DecryptSize(commandCode); 1388 result = CryptParameterDecryption( 1389 s_sessionHandles[s_decryptSessionIndex], 1390 &s_nonceCaller[s_decryptSessionIndex].b, 1391 parmBufferSize, (UINT16)size, 1392 &extraKey, 1393 parmBufferStart); 1394 if(result != TPM_RC_SUCCESS) 1395 return RcSafeAddToResult(result, 1396 TPM_RC_S + g_rcIndex[s_decryptSessionIndex]); 1397 } 1398 return TPM_RC_SUCCESS; 1399} 1400// 1401// 1402// CheckAuthNoSession() 1403// 1404// Function to process a command with no session associated. The function makes sure all the handles in 1405// the command require no authorization. 1406// 1407// 1408// 1409// Error Returns Meaning 1410// 1411// TPM_RC_AUTH_MISSING failure - one or more handles require auth 1412// 1413TPM_RC 1414CheckAuthNoSession( 1415 TPM_CC commandCode, // IN: Command Code 1416 UINT32 handleNum, // IN: number of handles in command 1417 TPM_HANDLE handles[], // IN: array of handle 1418 BYTE *parmBufferStart, // IN: start of parameter buffer 1419 UINT32 parmBufferSize // IN: size of parameter buffer 1420 ) 1421{ 1422 UINT32 i; 1423 TPM_RC result = TPM_RC_SUCCESS; 1424 // Check if the commandCode requires authorization 1425 for(i = 0; i < handleNum; i++) 1426 { 1427 if(CommandAuthRole(commandCode, i) != AUTH_NONE) 1428 return TPM_RC_AUTH_MISSING; 1429 } 1430#ifdef TPM_CC_GetCommandAuditDigest 1431 // Check if the command should be audited. 1432 result = CheckCommandAudit(commandCode, handleNum, handles, 1433 parmBufferStart, parmBufferSize); 1434 if(result != TPM_RC_SUCCESS) return result; 1435#endif 1436 // Initialize number of sessions to be 0 1437 s_sessionNum = 0; 1438 return TPM_RC_SUCCESS; 1439} 1440// 1441// 1442// Response Session Processing 1443// 1444// Introduction 1445// 1446// The following functions build the session area in a response, and handle the audit sessions (if present). 1447// 1448// ComputeRpHash() 1449// 1450// Function to compute rpHash (Response Parameter Hash). The rpHash is only computed if there is an 1451// HMAC authorization session and the return code is TPM_RC_SUCCESS. 1452// 1453static void 1454ComputeRpHash( 1455 TPM_ALG_ID hashAlg, // IN: hash algorithm to compute rpHash 1456 TPM_CC commandCode, // IN: commandCode 1457 UINT32 resParmBufferSize, // IN: size of response parameter buffer 1458 BYTE *resParmBuffer, // IN: response parameter buffer 1459 TPM2B_DIGEST *rpHash // OUT: rpHash 1460 ) 1461{ 1462 // The command result in rpHash is always TPM_RC_SUCCESS. 1463 TPM_RC responseCode = TPM_RC_SUCCESS; 1464 HASH_STATE hashState; 1465 // rpHash := hash(responseCode || commandCode || parameters) 1466 // Initiate hash creation. 1467 rpHash->t.size = CryptStartHash(hashAlg, &hashState); 1468 // Add hash constituents. 1469 CryptUpdateDigestInt(&hashState, sizeof(TPM_RC), &responseCode); 1470 CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode); 1471 CryptUpdateDigest(&hashState, resParmBufferSize, resParmBuffer); 1472 // Complete hash computation. 1473 CryptCompleteHash2B(&hashState, &rpHash->b); 1474 return; 1475} 1476// 1477// 1478// InitAuditSession() 1479// 1480// This function initializes the audit data in an audit session. 1481// 1482static void 1483InitAuditSession( 1484 SESSION *session // session to be initialized 1485 ) 1486{ 1487 // Mark session as an audit session. 1488 session->attributes.isAudit = SET; 1489 // Audit session can not be bound. 1490 session->attributes.isBound = CLEAR; 1491 // Size of the audit log is the size of session hash algorithm digest. 1492 session->u2.auditDigest.t.size = CryptGetHashDigestSize(session->authHashAlg); 1493 // Set the original digest value to be 0. 1494 MemorySet(&session->u2.auditDigest.t.buffer, 1495 0, 1496 session->u2.auditDigest.t.size); 1497 return; 1498} 1499// 1500// 1501// Audit() 1502// 1503// This function updates the audit digest in an audit session. 1504// 1505static void 1506Audit( 1507 SESSION *auditSession, // IN: loaded audit session 1508 TPM_CC commandCode, // IN: commandCode 1509 UINT32 resParmBufferSize, // IN: size of response parameter buffer 1510 BYTE *resParmBuffer // IN: response parameter buffer 1511 ) 1512{ 1513 TPM2B_DIGEST rpHash; // rpHash for response 1514 HASH_STATE hashState; 1515 // Compute rpHash 1516 ComputeRpHash(auditSession->authHashAlg, 1517 commandCode, 1518 resParmBufferSize, 1519 resParmBuffer, 1520 &rpHash); 1521 // auditDigestnew := hash (auditDigestold || cpHash || rpHash) 1522 // Start hash computation. 1523 CryptStartHash(auditSession->authHashAlg, &hashState); 1524 // Add old digest. 1525 CryptUpdateDigest2B(&hashState, &auditSession->u2.auditDigest.b); 1526 // Add cpHash and rpHash. 1527 CryptUpdateDigest2B(&hashState, &s_cpHashForAudit.b); 1528 CryptUpdateDigest2B(&hashState, &rpHash.b); 1529 // Finalize the hash. 1530 CryptCompleteHash2B(&hashState, &auditSession->u2.auditDigest.b); 1531 return; 1532} 1533#ifdef TPM_CC_GetCommandAuditDigest 1534// 1535// 1536// CommandAudit() 1537// 1538// This function updates the command audit digest. 1539// 1540static void 1541CommandAudit( 1542 TPM_CC commandCode, // IN: commandCode 1543 UINT32 resParmBufferSize, // IN: size of response parameter buffer 1544 BYTE *resParmBuffer // IN: response parameter buffer 1545 ) 1546{ 1547 if(CommandAuditIsRequired(commandCode)) 1548 { 1549 TPM2B_DIGEST rpHash; // rpHash for response 1550 HASH_STATE hashState; 1551 // Compute rpHash. 1552 ComputeRpHash(gp.auditHashAlg, commandCode, resParmBufferSize, 1553 resParmBuffer, &rpHash); 1554 // If the digest.size is one, it indicates the special case of changing 1555 // the audit hash algorithm. For this case, no audit is done on exit. 1556 // NOTE: When the hash algorithm is changed, g_updateNV is set in order to 1557 // force an update to the NV on exit so that the change in digest will 1558 // be recorded. So, it is safe to exit here without setting any flags 1559 // because the digest change will be written to NV when this code exits. 1560 if(gr.commandAuditDigest.t.size == 1) 1561 { 1562 gr.commandAuditDigest.t.size = 0; 1563 return; 1564 } 1565 // If the digest size is zero, need to start a new digest and increment 1566 // the audit counter. 1567 if(gr.commandAuditDigest.t.size == 0) 1568 { 1569 gr.commandAuditDigest.t.size = CryptGetHashDigestSize(gp.auditHashAlg); 1570 MemorySet(gr.commandAuditDigest.t.buffer, 1571 0, 1572 gr.commandAuditDigest.t.size); 1573 // Bump the counter and save its value to NV. 1574 gp.auditCounter++; 1575 NvWriteReserved(NV_AUDIT_COUNTER, &gp.auditCounter); 1576 g_updateNV = TRUE; 1577// 1578 } 1579 // auditDigestnew := hash (auditDigestold || cpHash || rpHash) 1580 // Start hash computation. 1581 CryptStartHash(gp.auditHashAlg, &hashState); 1582 // Add old digest. 1583 CryptUpdateDigest2B(&hashState, &gr.commandAuditDigest.b); 1584 // Add cpHash 1585 CryptUpdateDigest2B(&hashState, &s_cpHashForCommandAudit.b); 1586 // Add rpHash 1587 CryptUpdateDigest2B(&hashState, &rpHash.b); 1588 // Finalize the hash. 1589 CryptCompleteHash2B(&hashState, &gr.commandAuditDigest.b); 1590 } 1591 return; 1592} 1593#endif 1594// 1595// 1596// UpdateAuditSessionStatus() 1597// 1598// Function to update the internal audit related states of a session. It 1599// a) initializes the session as audit session and sets it to be exclusive if this is the first time it is used for 1600// audit or audit reset was requested; 1601// b) reports exclusive audit session; 1602// c) extends audit log; and 1603// d) clears exclusive audit session if no audit session found in the command. 1604// 1605static void 1606UpdateAuditSessionStatus( 1607 TPM_CC commandCode, // IN: commandCode 1608 UINT32 resParmBufferSize, // IN: size of response parameter buffer 1609 BYTE *resParmBuffer // IN: response parameter buffer 1610 ) 1611{ 1612 UINT32 i; 1613 TPM_HANDLE auditSession = TPM_RH_UNASSIGNED; 1614 // Iterate through sessions 1615 for (i = 0; i < s_sessionNum; i++) 1616 { 1617 SESSION *session; 1618 // PW session do not have a loaded session and can not be an audit 1619 // session either. Skip it. 1620 if(s_sessionHandles[i] == TPM_RS_PW) continue; 1621 session = SessionGet(s_sessionHandles[i]); 1622 // If a session is used for audit 1623 if(s_attributes[i].audit == SET) 1624 { 1625 // An audit session has been found 1626 auditSession = s_sessionHandles[i]; 1627 // If the session has not been an audit session yet, or 1628 // the auditSetting bits indicate a reset, initialize it and set 1629 // it to be the exclusive session 1630 if( session->attributes.isAudit == CLEAR 1631 || s_attributes[i].auditReset == SET 1632 ) 1633 { 1634 InitAuditSession(session); 1635 g_exclusiveAuditSession = auditSession; 1636 } 1637 else 1638 { 1639 // Check if the audit session is the current exclusive audit 1640 // session and, if not, clear previous exclusive audit session. 1641 if(g_exclusiveAuditSession != auditSession) 1642 g_exclusiveAuditSession = TPM_RH_UNASSIGNED; 1643 } 1644 // Report audit session exclusivity. 1645 if(g_exclusiveAuditSession == auditSession) 1646 { 1647 s_attributes[i].auditExclusive = SET; 1648 } 1649 else 1650 { 1651 s_attributes[i].auditExclusive = CLEAR; 1652 } 1653 // Extend audit log. 1654 Audit(session, commandCode, resParmBufferSize, resParmBuffer); 1655 } 1656 } 1657 // If no audit session is found in the command, and the command allows 1658 // a session then, clear the current exclusive 1659 // audit session. 1660 if(auditSession == TPM_RH_UNASSIGNED && IsSessionAllowed(commandCode)) 1661 { 1662 g_exclusiveAuditSession = TPM_RH_UNASSIGNED; 1663 } 1664 return; 1665} 1666// 1667// 1668// ComputeResponseHMAC() 1669// 1670// Function to compute HMAC for authorization session in a response. 1671// 1672static void 1673ComputeResponseHMAC( 1674 UINT32 sessionIndex, // IN: session index to be processed 1675 SESSION *session, // IN: loaded session 1676 TPM_CC commandCode, // IN: commandCode 1677 TPM2B_NONCE *nonceTPM, // IN: nonceTPM 1678 UINT32 resParmBufferSize, // IN: size of response parameter buffer 1679 BYTE *resParmBuffer, // IN: response parameter buffer 1680 TPM2B_DIGEST *hmac // OUT: authHMAC 1681 ) 1682{ 1683 TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2)); 1684 TPM2B_KEY key; // HMAC key 1685 BYTE marshalBuffer[sizeof(TPMA_SESSION)]; 1686 BYTE *buffer; 1687 INT32 bufferSize; 1688 UINT32 marshalSize; 1689 HMAC_STATE hmacState; 1690 TPM2B_DIGEST rp_hash; 1691// 1692 // Compute rpHash. 1693 ComputeRpHash(session->authHashAlg, commandCode, resParmBufferSize, 1694 resParmBuffer, &rp_hash); 1695 // Generate HMAC key 1696 MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); 1697 // Check if the session has an associated handle and the associated entity is 1698 // the one that the session is bound to. 1699 // If not bound, add the authValue of this entity to the HMAC key. 1700 if( s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED 1701 && !( HandleGetType(s_sessionHandles[sessionIndex]) 1702 == TPM_HT_POLICY_SESSION 1703 && session->attributes.isAuthValueNeeded == CLEAR) 1704 && !session->attributes.requestWasBound) 1705 { 1706 pAssert((sizeof(AUTH_VALUE) + key.t.size) <= sizeof(key.t.buffer)); 1707 key.t.size = key.t.size + 1708 EntityGetAuthValue(s_associatedHandles[sessionIndex], 1709 (AUTH_VALUE *)&key.t.buffer[key.t.size]); 1710 } 1711 // if the HMAC key size for a policy session is 0, the response HMAC is 1712 // computed according to the input HMAC 1713 if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION 1714 && key.t.size == 0 1715 && s_inputAuthValues[sessionIndex].t.size == 0) 1716 { 1717 hmac->t.size = 0; 1718 return; 1719 } 1720 // Start HMAC computation. 1721 hmac->t.size = CryptStartHMAC2B(session->authHashAlg, &key.b, &hmacState); 1722 // Add hash components. 1723 CryptUpdateDigest2B(&hmacState, &rp_hash.b); 1724 CryptUpdateDigest2B(&hmacState, &nonceTPM->b); 1725 CryptUpdateDigest2B(&hmacState, &s_nonceCaller[sessionIndex].b); 1726 // Add session attributes. 1727 buffer = marshalBuffer; 1728 bufferSize = sizeof(TPMA_SESSION); 1729 marshalSize = TPMA_SESSION_Marshal(&s_attributes[sessionIndex], &buffer, &bufferSize); 1730 CryptUpdateDigest(&hmacState, marshalSize, marshalBuffer); 1731 // Finalize HMAC. 1732 CryptCompleteHMAC2B(&hmacState, &hmac->b); 1733 return; 1734} 1735// 1736// 1737// BuildSingleResponseAuth() 1738// 1739// Function to compute response for an authorization session. 1740// 1741static void 1742BuildSingleResponseAuth( 1743 UINT32 sessionIndex, // IN: session index to be processed 1744 TPM_CC commandCode, // IN: commandCode 1745 UINT32 resParmBufferSize, // IN: size of response parameter buffer 1746 BYTE *resParmBuffer, // IN: response parameter buffer 1747 TPM2B_AUTH *auth // OUT: authHMAC 1748 ) 1749// 1750{ 1751 // For password authorization, field is empty. 1752 if(s_sessionHandles[sessionIndex] == TPM_RS_PW) 1753 { 1754 auth->t.size = 0; 1755 } 1756 else 1757 { 1758 // Fill in policy/HMAC based session response. 1759 SESSION *session = SessionGet(s_sessionHandles[sessionIndex]); 1760 // If the session is a policy session with isPasswordNeeded SET, the auth 1761 // field is empty. 1762 if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION 1763 && session->attributes.isPasswordNeeded == SET) 1764 auth->t.size = 0; 1765 else 1766 // Compute response HMAC. 1767 ComputeResponseHMAC(sessionIndex, 1768 session, 1769 commandCode, 1770 &session->nonceTPM, 1771 resParmBufferSize, 1772 resParmBuffer, 1773 auth); 1774 } 1775 return; 1776} 1777// 1778// 1779// UpdateTPMNonce() 1780// 1781// Updates TPM nonce in both internal session or response if applicable. 1782// 1783static void 1784UpdateTPMNonce( 1785 UINT16 noncesSize, // IN: number of elements in 'nonces' array 1786 TPM2B_NONCE nonces[] // OUT: nonceTPM 1787 ) 1788{ 1789 UINT32 i; 1790 pAssert(noncesSize >= s_sessionNum); 1791 for(i = 0; i < s_sessionNum; i++) 1792 { 1793 SESSION *session; 1794 // For PW session, nonce is 0. 1795 if(s_sessionHandles[i] == TPM_RS_PW) 1796 { 1797 nonces[i].t.size = 0; 1798 continue; 1799 } 1800 session = SessionGet(s_sessionHandles[i]); 1801 // Update nonceTPM in both internal session and response. 1802 CryptGenerateRandom(session->nonceTPM.t.size, session->nonceTPM.t.buffer); 1803 nonces[i] = session->nonceTPM; 1804 } 1805 return; 1806} 1807// 1808// 1809// UpdateInternalSession() 1810// 1811// Updates internal sessions: 1812// 1813// 1814// a) Restarts session time, and 1815// b) Clears a policy session since nonce is rolling. 1816// 1817static void 1818UpdateInternalSession( 1819 void 1820 ) 1821{ 1822 UINT32 i; 1823 for(i = 0; i < s_sessionNum; i++) 1824 { 1825 // For PW session, no update. 1826 if(s_sessionHandles[i] == TPM_RS_PW) continue; 1827 if(s_attributes[i].continueSession == CLEAR) 1828 { 1829 // Close internal session. 1830 SessionFlush(s_sessionHandles[i]); 1831 } 1832 else 1833 { 1834 // If nonce is rolling in a policy session, the policy related data 1835 // will be re-initialized. 1836 if(HandleGetType(s_sessionHandles[i]) == TPM_HT_POLICY_SESSION) 1837 { 1838 SESSION *session = SessionGet(s_sessionHandles[i]); 1839 // When the nonce rolls it starts a new timing interval for the 1840 // policy session. 1841 SessionResetPolicyData(session); 1842 session->startTime = go.clock; 1843 } 1844 } 1845 } 1846 return; 1847} 1848// 1849// 1850// BuildResponseSession() 1851// 1852// Function to build Session buffer in a response. 1853// 1854void 1855BuildResponseSession( 1856 TPM_ST tag, // IN: tag 1857 TPM_CC commandCode, // IN: commandCode 1858 UINT32 resHandleSize, // IN: size of response handle buffer 1859 UINT32 resParmSize, // IN: size of response parameter buffer 1860 UINT32 *resSessionSize // OUT: response session area 1861 ) 1862{ 1863 BYTE *resParmBuffer; 1864 INT32 bufferSize; 1865 TPM2B_NONCE responseNonces[MAX_SESSION_NUM]; 1866 // Compute response parameter buffer start. 1867 resParmBuffer = MemoryGetResponseBuffer(commandCode) + sizeof(TPM_ST) + 1868 sizeof(UINT32) + sizeof(TPM_RC) + resHandleSize; 1869 bufferSize = MAX_RESPONSE_SIZE - sizeof(TPM_ST) - sizeof(UINT32) - 1870 sizeof(TPM_RC) - resHandleSize; 1871 // For TPM_ST_SESSIONS, there is parameterSize field. 1872 if(tag == TPM_ST_SESSIONS) { 1873 resParmBuffer += sizeof(UINT32); 1874 bufferSize -= sizeof(UINT32); 1875 } 1876 // Session nonce should be updated before parameter encryption 1877 if(tag == TPM_ST_SESSIONS) 1878 { 1879 UpdateTPMNonce(MAX_SESSION_NUM, responseNonces); 1880 // Encrypt first parameter if applicable. Parameter encryption should 1881 // happen after nonce update and before any rpHash is computed. 1882 // If the encrypt session is associated with a handle, the authValue of 1883 // this handle will be concatenated with sessionAuth to generate 1884 // encryption key, no matter if the handle is the session bound entity 1885 // or not. The authValue is added to sessionAuth only when the authValue 1886 // is available. 1887 if(s_encryptSessionIndex != UNDEFINED_INDEX) 1888 { 1889 UINT32 size; 1890 TPM2B_AUTH extraKey; 1891 // Get size of the leading size field 1892 if( s_associatedHandles[s_encryptSessionIndex] != TPM_RH_UNASSIGNED 1893 && IsAuthValueAvailable(s_associatedHandles[s_encryptSessionIndex], 1894 commandCode, s_encryptSessionIndex) 1895 ) 1896 { 1897 extraKey.b.size = 1898 EntityGetAuthValue(s_associatedHandles[s_encryptSessionIndex], 1899 &extraKey.t.buffer); 1900 } 1901 else 1902 { 1903 extraKey.b.size = 0; 1904 } 1905 size = EncryptSize(commandCode); 1906 CryptParameterEncryption(s_sessionHandles[s_encryptSessionIndex], 1907 &s_nonceCaller[s_encryptSessionIndex].b, 1908 (UINT16)size, 1909 &extraKey, 1910 resParmBuffer); 1911 } 1912 } 1913 // Audit session should be updated first regardless of the tag. 1914 // A command with no session may trigger a change of the exclusivity state. 1915 UpdateAuditSessionStatus(commandCode, resParmSize, resParmBuffer); 1916 // Audit command. 1917 CommandAudit(commandCode, resParmSize, resParmBuffer); 1918 // Process command with sessions. 1919 if(tag == TPM_ST_SESSIONS) 1920 { 1921 UINT32 i; 1922 BYTE *buffer; 1923 TPM2B_DIGEST responseAuths[MAX_SESSION_NUM]; 1924 pAssert(s_sessionNum > 0); 1925 // Iterate over each session in the command session area, and create 1926 // corresponding sessions for response. 1927 for(i = 0; i < s_sessionNum; i++) 1928 { 1929 BuildSingleResponseAuth( 1930 i, 1931 commandCode, 1932 resParmSize, 1933 resParmBuffer, 1934 &responseAuths[i]); 1935 // Make sure that continueSession is SET on any Password session. 1936 // This makes it marginally easier for the management software 1937 // to keep track of the closed sessions. 1938 if( s_attributes[i].continueSession == CLEAR 1939 && s_sessionHandles[i] == TPM_RS_PW) 1940 { 1941 s_attributes[i].continueSession = SET; 1942 } 1943 } 1944 // Assemble Response Sessions. 1945 *resSessionSize = 0; 1946 buffer = resParmBuffer + resParmSize; 1947 bufferSize -= resParmSize; 1948 for(i = 0; i < s_sessionNum; i++) 1949 { 1950 *resSessionSize += TPM2B_NONCE_Marshal(&responseNonces[i], 1951 &buffer, &bufferSize); 1952 *resSessionSize += TPMA_SESSION_Marshal(&s_attributes[i], 1953 &buffer, &bufferSize); 1954 *resSessionSize += TPM2B_DIGEST_Marshal(&responseAuths[i], 1955 &buffer, &bufferSize); 1956 } 1957 // Update internal sessions after completing response buffer computation. 1958 UpdateInternalSession(); 1959 } 1960 else 1961 { 1962 // Process command with no session. 1963 *resSessionSize = 0; 1964 } 1965 return; 1966} 1967