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 OBJECT_C 9 #include "InternalRoutines.h" 10 #include "Platform.h" 11 // 12 // 13 // Functions 14 // 15 // ObjectStartup() 16 // 17 // This function is called at TPM2_Startup() to initialize the object subsystem. 18 // 19 void 20 ObjectStartup( 21 void 22 ) 23 { 24 UINT32 i; 25 // object slots initialization 26 for(i = 0; i < MAX_LOADED_OBJECTS; i++) 27 { 28 //Set the slot to not occupied 29 s_objects[i].occupied = FALSE; 30 } 31 return; 32 } 33 // 34 // 35 // ObjectCleanupEvict() 36 // 37 // In this implementation, a persistent object is moved from NV into an object slot for processing. It is 38 // flushed after command execution. This function is called from ExecuteCommand(). 39 // 40 void 41 ObjectCleanupEvict( 42 void 43 ) 44 { 45 UINT32 i; 46 // This has to be iterated because a command may have two handles 47 // and they may both be persistent. 48 // This could be made to be more efficient so that a search is not needed. 49 for(i = 0; i < MAX_LOADED_OBJECTS; i++) 50 { 51 // If an object is a temporary evict object, flush it from slot 52 if(s_objects[i].object.entity.attributes.evict == SET) 53 s_objects[i].occupied = FALSE; 54 } 55 return; 56 } 57 // 58 // 59 // ObjectIsPresent() 60 // 61 // This function checks to see if a transient handle references a loaded object. This routine should not be 62 // called if the handle is not a transient handle. The function validates that the handle is in the 63 // implementation-dependent allowed in range for loaded transient objects. 64 // 65 // Return Value Meaning 66 // 67 // TRUE if the handle references a loaded object 68 // FALSE if the handle is not an object handle, or it does not reference to a 69 // loaded object 70 // 71 BOOL 72 ObjectIsPresent( 73 TPMI_DH_OBJECT handle // IN: handle to be checked 74 ) 75 { 76 UINT32 slotIndex; // index of object slot 77 pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT); 78 // The index in the loaded object array is found by subtracting the first 79 // object handle number from the input handle number. If the indicated 80 // slot is occupied, then indicate that there is already is a loaded 81 // object associated with the handle. 82 slotIndex = handle - TRANSIENT_FIRST; 83 if(slotIndex >= MAX_LOADED_OBJECTS) 84 return FALSE; 85 return s_objects[slotIndex].occupied; 86 } 87 // 88 // 89 // ObjectIsSequence() 90 // 91 // This function is used to check if the object is a sequence object. This function should not be called if the 92 // handle does not reference a loaded object. 93 // 94 // Return Value Meaning 95 // 96 // TRUE object is an HMAC, hash, or event sequence object 97 // FALSE object is not an HMAC, hash, or event sequence object 98 // 99 BOOL 100 ObjectIsSequence( 101 OBJECT *object // IN: handle to be checked 102 ) 103 { 104 pAssert (object != NULL); 105 if( object->attributes.hmacSeq == SET 106 || object->attributes.hashSeq == SET 107 || object->attributes.eventSeq == SET) 108 return TRUE; 109 else 110 return FALSE; 111 } 112 // 113 // 114 // ObjectGet() 115 // 116 // This function is used to find the object structure associated with a handle. 117 // This function requires that handle references a loaded object. 118 // 119 OBJECT* 120 ObjectGet( 121 TPMI_DH_OBJECT handle // IN: handle of the object 122 ) 123 { 124 pAssert( handle >= TRANSIENT_FIRST 125 && handle - TRANSIENT_FIRST < MAX_LOADED_OBJECTS); 126 pAssert(s_objects[handle - TRANSIENT_FIRST].occupied == TRUE); 127 // In this implementation, the handle is determined by the slot occupied by the 128 // object. 129 return &s_objects[handle - TRANSIENT_FIRST].object.entity; 130 } 131 // 132 // 133 // ObjectGetName() 134 // 135 // This function is used to access the Name of the object. In this implementation, the Name is computed 136 // when the object is loaded and is saved in the internal representation of the object. This function copies 137 // the Name data from the object into the buffer at name and returns the number of octets copied. 138 // This function requires that handle references a loaded object. 139 // 140 UINT16 141 ObjectGetName( 142 TPMI_DH_OBJECT handle, // IN: handle of the object 143 NAME *name // OUT: name of the object 144 ) 145 { 146 OBJECT *object = ObjectGet(handle); 147 if(object->publicArea.nameAlg == TPM_ALG_NULL) 148 return 0; 149 // Copy the Name data to the output 150 MemoryCopy(name, object->name.t.name, object->name.t.size, sizeof(NAME)); 151 return object->name.t.size; 152 } 153 // 154 // 155 // ObjectGetNameAlg() 156 // 157 // This function is used to get the Name algorithm of a object. 158 // This function requires that handle references a loaded object. 159 // 160 TPMI_ALG_HASH 161 ObjectGetNameAlg( 162 TPMI_DH_OBJECT handle // IN: handle of the object 163 ) 164 { 165 OBJECT *object = ObjectGet(handle); 166 return object->publicArea.nameAlg; 167 } 168 // 169 // 170 // 171 // ObjectGetQualifiedName() 172 // 173 // This function returns the Qualified Name of the object. In this implementation, the Qualified Name is 174 // computed when the object is loaded and is saved in the internal representation of the object. The 175 // alternative would be to retain the Name of the parent and compute the QN when needed. This would take 176 // the same amount of space so it is not recommended that the alternate be used. 177 // This function requires that handle references a loaded object. 178 // 179 void 180 ObjectGetQualifiedName( 181 TPMI_DH_OBJECT handle, // IN: handle of the object 182 TPM2B_NAME *qualifiedName // OUT: qualified name of the object 183 ) 184 { 185 OBJECT *object = ObjectGet(handle); 186 if(object->publicArea.nameAlg == TPM_ALG_NULL) 187 qualifiedName->t.size = 0; 188 else 189 // Copy the name 190 *qualifiedName = object->qualifiedName; 191 return; 192 } 193 // 194 // 195 // ObjectDataGetHierarchy() 196 // 197 // This function returns the handle for the hierarchy of an object. 198 // 199 TPMI_RH_HIERARCHY 200 ObjectDataGetHierarchy( 201 OBJECT *object // IN :object 202 ) 203 { 204 if(object->attributes.spsHierarchy) 205 { 206 return TPM_RH_OWNER; 207 } 208 else if(object->attributes.epsHierarchy) 209 { 210 return TPM_RH_ENDORSEMENT; 211 } 212 else if(object->attributes.ppsHierarchy) 213 { 214 return TPM_RH_PLATFORM; 215 } 216 else 217 { 218 return TPM_RH_NULL; 219 } 220 } 221 // 222 // 223 // ObjectGetHierarchy() 224 // 225 // This function returns the handle of the hierarchy to which a handle belongs. This function is similar to 226 // ObjectDataGetHierarchy() but this routine takes a handle but ObjectDataGetHierarchy() takes an pointer 227 // to an object. 228 // This function requires that handle references a loaded object. 229 // 230 TPMI_RH_HIERARCHY 231 ObjectGetHierarchy( 232 TPMI_DH_OBJECT handle // IN :object handle 233 ) 234 { 235 OBJECT *object = ObjectGet(handle); 236 return ObjectDataGetHierarchy(object); 237 } 238 // 239 // 240 // ObjectAllocateSlot() 241 // 242 // This function is used to allocate a slot in internal object array. 243 // 244 // Return Value Meaning 245 // 246 // TRUE allocate success 247 // FALSE do not have free slot 248 // 249 static BOOL 250 ObjectAllocateSlot( 251 TPMI_DH_OBJECT *handle, // OUT: handle of allocated object 252 OBJECT **object // OUT: points to the allocated object 253 ) 254 { 255 UINT32 i; 256 // find an unoccupied handle slot 257 for(i = 0; i < MAX_LOADED_OBJECTS; i++) 258 { 259 if(!s_objects[i].occupied) // If found a free slot 260 { 261 // Mark the slot as occupied 262 s_objects[i].occupied = TRUE; 263 break; 264 } 265 } 266 // If we reach the end of object slot without finding a free one, return 267 // error. 268 if(i == MAX_LOADED_OBJECTS) return FALSE; 269 *handle = i + TRANSIENT_FIRST; 270 *object = &s_objects[i].object.entity; 271 // Initialize the object attributes 272 MemorySet(&((*object)->attributes), 0, sizeof(OBJECT_ATTRIBUTES)); 273 return TRUE; 274 } 275 // 276 // 277 // ObjectLoad() 278 // 279 // This function loads an object into an internal object structure. If an error is returned, the internal state is 280 // unchanged. 281 // 282 // 283 // 284 // 285 // Error Returns Meaning 286 // 287 // TPM_RC_BINDING if the public and sensitive parts of the object are not matched 288 // TPM_RC_KEY if the parameters in the public area of the object are not consistent 289 // TPM_RC_OBJECT_MEMORY if there is no free slot for an object 290 // TPM_RC_TYPE the public and private parts are not the same type 291 // 292 TPM_RC 293 ObjectLoad( 294 TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy to which the object belongs 295 TPMT_PUBLIC *publicArea, // IN: public area 296 TPMT_SENSITIVE *sensitive, // IN: sensitive area (may be null) 297 TPM2B_NAME *name, // IN: object's name (may be null) 298 TPM_HANDLE parentHandle, // IN: handle of parent 299 BOOL skipChecks, // IN: flag to indicate if it is OK to skip 300 // consistency checks. 301 TPMI_DH_OBJECT *handle // OUT: object handle 302 ) 303 { 304 OBJECT *object = NULL; 305 OBJECT *parent = NULL; 306 TPM_RC result = TPM_RC_SUCCESS; 307 TPM2B_NAME parentQN; // Parent qualified name 308 // Try to allocate a slot for new object 309 if(!ObjectAllocateSlot(handle, &object)) 310 return TPM_RC_OBJECT_MEMORY; 311 // Initialize public 312 object->publicArea = *publicArea; 313 if(sensitive != NULL) 314 object->sensitive = *sensitive; 315 // Are the consistency checks needed 316 if(!skipChecks) 317 { 318 // Check if key size matches 319 if(!CryptObjectIsPublicConsistent(&object->publicArea)) 320 { 321 result = TPM_RC_KEY; 322 goto ErrorExit; 323 } 324 if(sensitive != NULL) 325 { 326 // Check if public type matches sensitive type 327 result = CryptObjectPublicPrivateMatch(object); 328 if(result != TPM_RC_SUCCESS) 329 goto ErrorExit; 330 } 331 } 332 object->attributes.publicOnly = (sensitive == NULL); 333 // If 'name' is NULL, then there is nothing left to do for this 334 // object as it has no qualified name and it is not a member of any 335 // hierarchy and it is temporary 336 if(name == NULL || name->t.size == 0) 337 { 338 object->qualifiedName.t.size = 0; 339 object->name.t.size = 0; 340 object->attributes.temporary = SET; 341 return TPM_RC_SUCCESS; 342 } 343 // If parent handle is a permanent handle, it is a primary or temporary 344 // object 345 if(HandleGetType(parentHandle) == TPM_HT_PERMANENT) 346 { 347 // initialize QN 348 parentQN.t.size = 4; 349 // for a primary key, parent qualified name is the handle of hierarchy 350 UINT32_TO_BYTE_ARRAY(parentHandle, parentQN.t.name); 351 } 352 else 353 { 354 // Get hierarchy and qualified name of parent 355 ObjectGetQualifiedName(parentHandle, &parentQN); 356 // Check for stClear object 357 parent = ObjectGet(parentHandle); 358 if( publicArea->objectAttributes.stClear == SET 359 || parent->attributes.stClear == SET) 360 object->attributes.stClear = SET; 361 } 362 object->name = *name; 363 // Compute object qualified name 364 ObjectComputeQualifiedName(&parentQN, publicArea->nameAlg, 365 name, &object->qualifiedName); 366 // Any object in TPM_RH_NULL hierarchy is temporary 367 if(hierarchy == TPM_RH_NULL) 368 { 369 object->attributes.temporary = SET; 370 } 371 else if(parentQN.t.size == sizeof(TPM_HANDLE)) 372 { 373 // Otherwise, if the size of parent's qualified name is the size of a 374 // handle, this object is a primary object 375 object->attributes.primary = SET; 376 } 377 switch(hierarchy) 378 { 379 case TPM_RH_PLATFORM: 380 object->attributes.ppsHierarchy = SET; 381 break; 382 case TPM_RH_OWNER: 383 object->attributes.spsHierarchy = SET; 384 break; 385 case TPM_RH_ENDORSEMENT: 386 object->attributes.epsHierarchy = SET; 387 break; 388 case TPM_RH_NULL: 389 break; 390 default: 391 pAssert(FALSE); 392 break; 393 } 394 return TPM_RC_SUCCESS; 395 ErrorExit: 396 ObjectFlush(*handle); 397 return result; 398 } 399 // 400 // 401 // 402 // AllocateSequenceSlot() 403 // 404 // This function allocates a sequence slot and initializes the parts that are used by the normal objects so 405 // that a sequence object is not inadvertently used for an operation that is not appropriate for a sequence. 406 // 407 static BOOL 408 AllocateSequenceSlot( 409 TPM_HANDLE *newHandle, // OUT: receives the allocated handle 410 HASH_OBJECT **object, // OUT: receives pointer to allocated object 411 TPM2B_AUTH *auth // IN: the authValue for the slot 412 ) 413 { 414 OBJECT *objectHash; // the hash as an object 415 if(!ObjectAllocateSlot(newHandle, &objectHash)) 416 return FALSE; 417 *object = (HASH_OBJECT *)objectHash; 418 // Validate that the proper location of the hash state data relative to the 419 // object state data. 420 pAssert(&((*object)->auth) == &objectHash->publicArea.authPolicy); 421 // Set the common values that a sequence object shares with an ordinary object 422 // The type is TPM_ALG_NULL 423 (*object)->type = TPM_ALG_NULL; 424 // This has no name algorithm and the name is the Empty Buffer 425 (*object)->nameAlg = TPM_ALG_NULL; 426 // Clear the attributes 427 MemorySet(&((*object)->objectAttributes), 0, sizeof(TPMA_OBJECT)); 428 // A sequence object is considered to be in the NULL hierarchy so it should 429 // be marked as temporary so that it can't be persisted 430 (*object)->attributes.temporary = SET; 431 // A sequence object is DA exempt. 432 (*object)->objectAttributes.noDA = SET; 433 if(auth != NULL) 434 { 435 MemoryRemoveTrailingZeros(auth); 436 (*object)->auth = *auth; 437 } 438 else 439 (*object)->auth.t.size = 0; 440 return TRUE; 441 } 442 // 443 // 444 // ObjectCreateHMACSequence() 445 // 446 // This function creates an internal HMAC sequence object. 447 // 448 // Error Returns Meaning 449 // 450 // TPM_RC_OBJECT_MEMORY if there is no free slot for an object 451 // 452 TPM_RC 453 ObjectCreateHMACSequence( 454 TPMI_ALG_HASH hashAlg, // IN: hash algorithm 455 TPM_HANDLE handle, // IN: the handle associated with sequence 456 // object 457 TPM2B_AUTH *auth, // IN: authValue 458 TPMI_DH_OBJECT *newHandle // OUT: HMAC sequence object handle 459 ) 460 { 461 HASH_OBJECT *hmacObject; 462 OBJECT *keyObject; 463 // Try to allocate a slot for new object 464 if(!AllocateSequenceSlot(newHandle, &hmacObject, auth)) 465 return TPM_RC_OBJECT_MEMORY; 466 // Set HMAC sequence bit 467 hmacObject->attributes.hmacSeq = SET; 468 // Get pointer to the HMAC key object 469 keyObject = ObjectGet(handle); 470 CryptStartHMACSequence2B(hashAlg, &keyObject->sensitive.sensitive.bits.b, 471 &hmacObject->state.hmacState); 472 return TPM_RC_SUCCESS; 473 } 474 // 475 // 476 // ObjectCreateHashSequence() 477 // 478 // This function creates a hash sequence object. 479 // 480 // Error Returns Meaning 481 // 482 // TPM_RC_OBJECT_MEMORY if there is no free slot for an object 483 // 484 TPM_RC 485 ObjectCreateHashSequence( 486 TPMI_ALG_HASH hashAlg, // IN: hash algorithm 487 TPM2B_AUTH *auth, // IN: authValue 488 TPMI_DH_OBJECT *newHandle // OUT: sequence object handle 489 ) 490 { 491 HASH_OBJECT *hashObject; 492 // Try to allocate a slot for new object 493 if(!AllocateSequenceSlot(newHandle, &hashObject, auth)) 494 return TPM_RC_OBJECT_MEMORY; 495 // Set hash sequence bit 496 hashObject->attributes.hashSeq = SET; 497 // Start hash for hash sequence 498 CryptStartHashSequence(hashAlg, &hashObject->state.hashState[0]); 499 return TPM_RC_SUCCESS; 500 } 501 // 502 // 503 // ObjectCreateEventSequence() 504 // 505 // This function creates an event sequence object. 506 // 507 // Error Returns Meaning 508 // 509 // TPM_RC_OBJECT_MEMORY if there is no free slot for an object 510 // 511 TPM_RC 512 ObjectCreateEventSequence( 513 TPM2B_AUTH *auth, // IN: authValue 514 TPMI_DH_OBJECT *newHandle // OUT: sequence object handle 515 ) 516 { 517 HASH_OBJECT *hashObject; 518 UINT32 count; 519 TPM_ALG_ID hash; 520 // Try to allocate a slot for new object 521 if(!AllocateSequenceSlot(newHandle, &hashObject, auth)) 522 return TPM_RC_OBJECT_MEMORY; 523 // Set the event sequence attribute 524 hashObject->attributes.eventSeq = SET; 525 // Initialize hash states for each implemented PCR algorithms 526 for(count = 0; (hash = CryptGetHashAlgByIndex(count)) != TPM_ALG_NULL; count++) 527 { 528 // If this is a _TPM_Init or _TPM_HashStart, the sequence object will 529 // not leave the TPM so it doesn't need the sequence handling 530 if(auth == NULL) 531 CryptStartHash(hash, &hashObject->state.hashState[count]); 532 else 533 CryptStartHashSequence(hash, &hashObject->state.hashState[count]); 534 } 535 return TPM_RC_SUCCESS; 536 } 537 // 538 // 539 // ObjectTerminateEvent() 540 // 541 // This function is called to close out the event sequence and clean up the hash context states. 542 // 543 void 544 ObjectTerminateEvent( 545 void 546 ) 547 { 548 HASH_OBJECT *hashObject; 549 int count; 550 BYTE buffer[MAX_DIGEST_SIZE]; 551 hashObject = (HASH_OBJECT *)ObjectGet(g_DRTMHandle); 552 // Don't assume that this is a proper sequence object 553 if(hashObject->attributes.eventSeq) 554 { 555 // If it is, close any open hash contexts. This is done in case 556 // the crypto implementation has some context values that need to be 557 // cleaned up (hygiene). 558 // 559 for(count = 0; CryptGetHashAlgByIndex(count) != TPM_ALG_NULL; count++) 560 { 561 CryptCompleteHash(&hashObject->state.hashState[count], 0, buffer); 562 } 563 // Flush sequence object 564 ObjectFlush(g_DRTMHandle); 565 } 566 g_DRTMHandle = TPM_RH_UNASSIGNED; 567 } 568 // 569 // 570 // 571 // ObjectContextLoad() 572 // 573 // This function loads an object from a saved object context. 574 // 575 // Error Returns Meaning 576 // 577 // TPM_RC_OBJECT_MEMORY if there is no free slot for an object 578 // 579 TPM_RC 580 ObjectContextLoad( 581 OBJECT *object, // IN: object structure from saved context 582 TPMI_DH_OBJECT *handle // OUT: object handle 583 ) 584 { 585 OBJECT *newObject; 586 // Try to allocate a slot for new object 587 if(!ObjectAllocateSlot(handle, &newObject)) 588 return TPM_RC_OBJECT_MEMORY; 589 // Copy input object data to internal structure 590 *newObject = *object; 591 return TPM_RC_SUCCESS; 592 } 593 // 594 // 595 // ObjectFlush() 596 // 597 // This function frees an object slot. 598 // This function requires that the object is loaded. 599 // 600 void 601 ObjectFlush( 602 TPMI_DH_OBJECT handle // IN: handle to be freed 603 ) 604 { 605 UINT32 index = handle - TRANSIENT_FIRST; 606 pAssert(ObjectIsPresent(handle)); 607 // Mark the handle slot as unoccupied 608 s_objects[index].occupied = FALSE; 609 // With no attributes 610 MemorySet((BYTE*)&(s_objects[index].object.entity.attributes), 611 0, sizeof(OBJECT_ATTRIBUTES)); 612 return; 613 } 614 // 615 // 616 // ObjectFlushHierarchy() 617 // 618 // This function is called to flush all the loaded transient objects associated with a hierarchy when the 619 // hierarchy is disabled. 620 // 621 void 622 ObjectFlushHierarchy( 623 TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flush 624 ) 625 { 626 UINT16 i; 627 // iterate object slots 628 for(i = 0; i < MAX_LOADED_OBJECTS; i++) 629 { 630 if(s_objects[i].occupied) // If found an occupied slot 631 { 632 switch(hierarchy) 633 { 634 case TPM_RH_PLATFORM: 635 if(s_objects[i].object.entity.attributes.ppsHierarchy == SET) 636 s_objects[i].occupied = FALSE; 637 break; 638 case TPM_RH_OWNER: 639 if(s_objects[i].object.entity.attributes.spsHierarchy == SET) 640 s_objects[i].occupied = FALSE; 641 break; 642 case TPM_RH_ENDORSEMENT: 643 if(s_objects[i].object.entity.attributes.epsHierarchy == SET) 644 s_objects[i].occupied = FALSE; 645 break; 646 default: 647 pAssert(FALSE); 648 break; 649 } 650 } 651 } 652 return; 653 } 654 // 655 // 656 // ObjectLoadEvict() 657 // 658 // This function loads a persistent object into a transient object slot. 659 // This function requires that handle is associated with a persistent object. 660 // 661 // Error Returns Meaning 662 // 663 // TPM_RC_HANDLE the persistent object does not exist or the associated hierarchy is 664 // disabled. 665 // TPM_RC_OBJECT_MEMORY no object slot 666 // 667 TPM_RC 668 ObjectLoadEvict( 669 TPM_HANDLE *handle, // IN:OUT: evict object handle. If success, it 670 // will be replace by the loaded object handle 671 TPM_CC commandCode // IN: the command being processed 672 ) 673 { 674 TPM_RC result; 675 TPM_HANDLE evictHandle = *handle; // Save the evict handle 676 OBJECT *object; 677 // If this is an index that references a persistent object created by 678 // the platform, then return TPM_RH_HANDLE if the phEnable is FALSE 679 if(*handle >= PLATFORM_PERSISTENT) 680 { 681 // belongs to platform 682 if(g_phEnable == CLEAR) 683 return TPM_RC_HANDLE; 684 } 685 // belongs to owner 686 else if(gc.shEnable == CLEAR) 687 return TPM_RC_HANDLE; 688 // Try to allocate a slot for an object 689 if(!ObjectAllocateSlot(handle, &object)) 690 return TPM_RC_OBJECT_MEMORY; 691 // Copy persistent object to transient object slot. A TPM_RC_HANDLE 692 // may be returned at this point. This will mark the slot as containing 693 // a transient object so that it will be flushed at the end of the 694 // command 695 result = NvGetEvictObject(evictHandle, object); 696 // Bail out if this failed 697 if(result != TPM_RC_SUCCESS) 698 return result; 699 // check the object to see if it is in the endorsement hierarchy 700 // if it is and this is not a TPM2_EvictControl() command, indicate 701 // that the hierarchy is disabled. 702 // If the associated hierarchy is disabled, make it look like the 703 // handle is not defined 704 if( ObjectDataGetHierarchy(object) == TPM_RH_ENDORSEMENT 705 && gc.ehEnable == CLEAR 706 && commandCode != TPM_CC_EvictControl 707 ) 708 return TPM_RC_HANDLE; 709 return result; 710 } 711 // 712 // 713 // ObjectComputeName() 714 // 715 // This function computes the Name of an object from its public area. 716 // 717 void 718 ObjectComputeName( 719 TPMT_PUBLIC *publicArea, // IN: public area of an object 720 TPM2B_NAME *name // OUT: name of the object 721 ) 722 { 723 TPM2B_PUBLIC marshalBuffer; 724 BYTE *buffer; // auxiliary marshal buffer pointer 725 INT32 bufferSize; 726 HASH_STATE hashState; // hash state 727 // if the nameAlg is NULL then there is no name. 728 if(publicArea->nameAlg == TPM_ALG_NULL) 729 { 730 name->t.size = 0; 731 return; 732 } 733 // Start hash stack 734 name->t.size = CryptStartHash(publicArea->nameAlg, &hashState); 735 // Marshal the public area into its canonical form 736 buffer = marshalBuffer.b.buffer; 737 bufferSize = sizeof(TPMT_PUBLIC); 738 marshalBuffer.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, &bufferSize); 739 // Adding public area 740 CryptUpdateDigest2B(&hashState, &marshalBuffer.b); 741 // Complete hash leaving room for the name algorithm 742 CryptCompleteHash(&hashState, name->t.size, &name->t.name[2]); 743 // set the nameAlg 744 UINT16_TO_BYTE_ARRAY(publicArea->nameAlg, name->t.name); 745 // 746 name->t.size += 2; 747 return; 748 } 749 // 750 // 751 // ObjectComputeQualifiedName() 752 // 753 // This function computes the qualified name of an object. 754 // 755 void 756 ObjectComputeQualifiedName( 757 TPM2B_NAME *parentQN, // IN: parent's qualified name 758 TPM_ALG_ID nameAlg, // IN: name hash 759 TPM2B_NAME *name, // IN: name of the object 760 TPM2B_NAME *qualifiedName // OUT: qualified name of the object 761 ) 762 { 763 HASH_STATE hashState; // hash state 764 // QN_A = hash_A (QN of parent || NAME_A) 765 // Start hash 766 qualifiedName->t.size = CryptStartHash(nameAlg, &hashState); 767 // Add parent's qualified name 768 CryptUpdateDigest2B(&hashState, &parentQN->b); 769 // Add self name 770 CryptUpdateDigest2B(&hashState, &name->b); 771 // Complete hash leaving room for the name algorithm 772 CryptCompleteHash(&hashState, qualifiedName->t.size, 773 &qualifiedName->t.name[2]); 774 UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name); 775 qualifiedName->t.size += 2; 776 return; 777 } 778 // 779 // 780 // ObjectDataIsStorage() 781 // 782 // This function determines if a public area has the attributes associated with a storage key. A storage key is 783 // an asymmetric object that has its restricted and decrypt attributes SET, and sign CLEAR. 784 // 785 // Return Value Meaning 786 // 787 // TRUE if the object is a storage key 788 // FALSE if the object is not a storage key 789 // 790 BOOL 791 ObjectDataIsStorage( 792 TPMT_PUBLIC *publicArea // IN: public area of the object 793 ) 794 { 795 if( CryptIsAsymAlgorithm(publicArea->type) // must be asymmetric, 796 && publicArea->objectAttributes.restricted == SET // restricted, 797 && publicArea->objectAttributes.decrypt == SET // decryption key 798 && publicArea->objectAttributes.sign == CLEAR // can not be sign key 799 ) 800 return TRUE; 801 else 802 return FALSE; 803 } 804 // 805 // ObjectIsStorage() 806 // 807 // This function determines if an object has the attributes associated with a storage key. A storage key is an 808 // asymmetric object that has its restricted and decrypt attributes SET, and sign CLEAR. 809 // 810 // Return Value Meaning 811 // 812 // TRUE if the object is a storage key 813 // FALSE if the object is not a storage key 814 // 815 BOOL 816 ObjectIsStorage( 817 TPMI_DH_OBJECT handle // IN: object handle 818 ) 819 { 820 OBJECT *object = ObjectGet(handle); 821 return ObjectDataIsStorage(&object->publicArea); 822 } 823 // 824 // 825 // ObjectCapGetLoaded() 826 // 827 // This function returns a a list of handles of loaded object, starting from handle. Handle must be in the 828 // range of valid transient object handles, but does not have to be the handle of a loaded transient object. 829 // 830 // Return Value Meaning 831 // 832 // YES if there are more handles available 833 // NO all the available handles has been returned 834 // 835 TPMI_YES_NO 836 ObjectCapGetLoaded( 837 TPMI_DH_OBJECT handle, // IN: start handle 838 UINT32 count, // IN: count of returned handles 839 TPML_HANDLE *handleList // OUT: list of handle 840 ) 841 { 842 TPMI_YES_NO more = NO; 843 UINT32 i; 844 pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT); 845 // Initialize output handle list 846 handleList->count = 0; 847 // The maximum count of handles we may return is MAX_CAP_HANDLES 848 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; 849 // Iterate object slots to get loaded object handles 850 for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++) 851 { 852 if(s_objects[i].occupied == TRUE) 853 { 854 // A valid transient object can not be the copy of a persistent object 855 pAssert(s_objects[i].object.entity.attributes.evict == CLEAR); 856 if(handleList->count < count) 857 { 858 // If we have not filled up the return list, add this object 859 // handle to it 860 handleList->handle[handleList->count] = i + TRANSIENT_FIRST; 861 handleList->count++; 862 // 863 } 864 else 865 { 866 // If the return list is full but we still have loaded object 867 // available, report this and stop iterating 868 more = YES; 869 break; 870 } 871 } 872 } 873 return more; 874 } 875 // 876 // 877 // ObjectCapGetTransientAvail() 878 // 879 // This function returns an estimate of the number of additional transient objects that could be loaded into 880 // the TPM. 881 // 882 UINT32 883 ObjectCapGetTransientAvail( 884 void 885 ) 886 { 887 UINT32 i; 888 UINT32 num = 0; 889 // Iterate object slot to get the number of unoccupied slots 890 for(i = 0; i < MAX_LOADED_OBJECTS; i++) 891 { 892 if(s_objects[i].occupied == FALSE) num++; 893 } 894 return num; 895 } 896