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
ObjectStartup(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
ObjectCleanupEvict(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
ObjectIsPresent(TPMI_DH_OBJECT handle)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
ObjectIsSequence(OBJECT * object)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*
ObjectGet(TPMI_DH_OBJECT handle)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
ObjectGetName(TPMI_DH_OBJECT handle,NAME * name)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
ObjectGetNameAlg(TPMI_DH_OBJECT handle)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
ObjectGetQualifiedName(TPMI_DH_OBJECT handle,TPM2B_NAME * qualifiedName)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
ObjectDataGetHierarchy(OBJECT * object)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
ObjectGetHierarchy(TPMI_DH_OBJECT handle)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
ObjectAllocateSlot(TPMI_DH_OBJECT * handle,OBJECT ** object)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
ObjectLoad(TPMI_RH_HIERARCHY hierarchy,TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,TPM2B_NAME * name,TPM_HANDLE parentHandle,BOOL skipChecks,TPMI_DH_OBJECT * handle)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
AllocateSequenceSlot(TPM_HANDLE * newHandle,HASH_OBJECT ** object,TPM2B_AUTH * auth)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
ObjectCreateHMACSequence(TPMI_ALG_HASH hashAlg,TPM_HANDLE handle,TPM2B_AUTH * auth,TPMI_DH_OBJECT * newHandle)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
ObjectCreateHashSequence(TPMI_ALG_HASH hashAlg,TPM2B_AUTH * auth,TPMI_DH_OBJECT * newHandle)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
ObjectCreateEventSequence(TPM2B_AUTH * auth,TPMI_DH_OBJECT * newHandle)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
ObjectTerminateEvent(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
ObjectContextLoad(OBJECT * object,TPMI_DH_OBJECT * handle)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
ObjectFlush(TPMI_DH_OBJECT handle)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
ObjectFlushHierarchy(TPMI_RH_HIERARCHY hierarchy)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
ObjectLoadEvict(TPM_HANDLE * handle,TPM_CC commandCode)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
ObjectComputeName(TPMT_PUBLIC * publicArea,TPM2B_NAME * name)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
ObjectComputeQualifiedName(TPM2B_NAME * parentQN,TPM_ALG_ID nameAlg,TPM2B_NAME * name,TPM2B_NAME * qualifiedName)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
ObjectDataIsStorage(TPMT_PUBLIC * publicArea)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
ObjectIsStorage(TPMI_DH_OBJECT handle)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
ObjectCapGetLoaded(TPMI_DH_OBJECT handle,UINT32 count,TPML_HANDLE * handleList)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
ObjectCapGetTransientAvail(void)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