blob: 14ec018f0a7960d25563963bce39148075bda16f [file] [log] [blame]
Vadim Bendebury56797522015-05-20 10:32:25 -07001// 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"
Vadim Bendebury5f320632015-06-01 10:20:42 -070010#include "Platform.h"
Vadim Bendebury56797522015-05-20 10:32:25 -070011//
12//
13// Functions
14//
15// ObjectStartup()
16//
17// This function is called at TPM2_Startup() to initialize the object subsystem.
18//
19void
20ObjectStartup(
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//
40void
41ObjectCleanupEvict(
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//
71BOOL
72ObjectIsPresent(
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//
99BOOL
100ObjectIsSequence(
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//
119OBJECT*
120ObjectGet(
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//
140UINT16
141ObjectGetName(
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
ChromeOS Developere85c65b2015-07-10 10:12:43 -0700150 MemoryCopy(name, object->name.t.name, object->name.t.size, sizeof(NAME));
Vadim Bendebury56797522015-05-20 10:32:25 -0700151 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//
160TPMI_ALG_HASH
161ObjectGetNameAlg(
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//
179void
180ObjectGetQualifiedName(
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//
199TPMI_RH_HIERARCHY
200ObjectDataGetHierarchy(
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//
230TPMI_RH_HIERARCHY
231ObjectGetHierarchy(
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//
249static BOOL
250ObjectAllocateSlot(
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;
Vadim Bendebury21756122016-12-29 11:14:03 -0800271 // Initialize the container.
272 MemorySet(*object, 0, sizeof(**object));
Vadim Bendebury56797522015-05-20 10:32:25 -0700273 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//
292TPM_RC
293ObjectLoad(
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
ChromeOS Developere85c65b2015-07-10 10:12:43 -0700350 UINT32_TO_BYTE_ARRAY(parentHandle, parentQN.t.name);
Vadim Bendebury56797522015-05-20 10:32:25 -0700351 }
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;
395ErrorExit:
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//
407static BOOL
408AllocateSequenceSlot(
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//
452TPM_RC
453ObjectCreateHMACSequence(
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//
484TPM_RC
485ObjectCreateHashSequence(
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//
511TPM_RC
512ObjectCreateEventSequence(
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//
543void
544ObjectTerminateEvent(
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//
579TPM_RC
580ObjectContextLoad(
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//
600void
601ObjectFlush(
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//
621void
622ObjectFlushHierarchy(
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//
667TPM_RC
668ObjectLoadEvict(
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//
717void
718ObjectComputeName(
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
Jocelyn Bohr32be4042015-07-29 15:14:01 -0700725 INT32 bufferSize;
Vadim Bendebury56797522015-05-20 10:32:25 -0700726 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;
Jocelyn Bohr5aac5852015-08-20 16:05:05 -0700737 bufferSize = sizeof(TPMT_PUBLIC);
Jocelyn Bohr32be4042015-07-29 15:14:01 -0700738 marshalBuffer.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, &bufferSize);
Vadim Bendebury56797522015-05-20 10:32:25 -0700739 // Adding public area
740 CryptUpdateDigest2B(&hashState, &marshalBuffer.b);
741 // Complete hash leaving room for the name algorithm
ChromeOS Developere85c65b2015-07-10 10:12:43 -0700742 CryptCompleteHash(&hashState, name->t.size, &name->t.name[2]);
Vadim Bendebury56797522015-05-20 10:32:25 -0700743 // set the nameAlg
ChromeOS Developere85c65b2015-07-10 10:12:43 -0700744 UINT16_TO_BYTE_ARRAY(publicArea->nameAlg, name->t.name);
Vadim Bendebury56797522015-05-20 10:32:25 -0700745//
746 name->t.size += 2;
747 return;
748}
749//
750//
751// ObjectComputeQualifiedName()
752//
753// This function computes the qualified name of an object.
754//
755void
756ObjectComputeQualifiedName(
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,
ChromeOS Developere85c65b2015-07-10 10:12:43 -0700773 &qualifiedName->t.name[2]);
774 UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name);
Vadim Bendebury56797522015-05-20 10:32:25 -0700775 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//
790BOOL
791ObjectDataIsStorage(
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//
815BOOL
816ObjectIsStorage(
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//
835TPMI_YES_NO
836ObjectCapGetLoaded(
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//
882UINT32
883ObjectCapGetTransientAvail(
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}