• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Microsoft Reference Implementation for TPM 2.0
2  *
3  *  The copyright in this software is being made available under the BSD License,
4  *  included below. This software may be subject to other third party and
5  *  contributor rights, including patent rights, and no such rights are granted
6  *  under this license.
7  *
8  *  Copyright (c) Microsoft Corporation
9  *
10  *  All rights reserved.
11  *
12  *  BSD License
13  *
14  *  Redistribution and use in source and binary forms, with or without modification,
15  *  are permitted provided that the following conditions are met:
16  *
17  *  Redistributions of source code must retain the above copyright notice, this list
18  *  of conditions and the following disclaimer.
19  *
20  *  Redistributions in binary form must reproduce the above copyright notice, this
21  *  list of conditions and the following disclaimer in the documentation and/or
22  *  other materials provided with the distribution.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 //** Description
36 // The functions in this file are used for accessing properties for handles of
37 // various types. Functions in other files require handles of a specific
38 // type but the functions in this file allow use of any handle type.
39 
40 //** Includes
41 
42 #include "Tpm.h"
43 
44 //** Functions
45 //*** EntityGetLoadStatus()
46 // This function will check that all the handles access loaded entities.
47 //  Return Type: TPM_RC
48 //      TPM_RC_HANDLE           handle type does not match
49 //      TPM_RC_REFERENCE_Hx     entity is not present
50 //      TPM_RC_HIERARCHY        entity belongs to a disabled hierarchy
51 //      TPM_RC_OBJECT_MEMORY    handle is an evict object but there is no
52 //                               space to load it to RAM
53 TPM_RC
EntityGetLoadStatus(COMMAND * command)54 EntityGetLoadStatus(
55     COMMAND         *command        // IN/OUT: command parsing structure
56     )
57 {
58     UINT32               i;
59     TPM_RC               result = TPM_RC_SUCCESS;
60 //
61     for(i = 0; i < command->handleNum; i++)
62     {
63         TPM_HANDLE      handle = command->handles[i];
64         switch(HandleGetType(handle))
65         {
66             // For handles associated with hierarchies, the entity is present
67             // only if the associated enable is SET.
68             case TPM_HT_PERMANENT:
69                 switch(handle)
70                 {
71                     case TPM_RH_OWNER:
72                         if(!gc.shEnable)
73                             result = TPM_RC_HIERARCHY;
74                         break;
75 
76 #ifdef  VENDOR_PERMANENT
77                     case VENDOR_PERMANENT:
78 #endif
79                     case TPM_RH_ENDORSEMENT:
80                         if(!gc.ehEnable)
81                             result = TPM_RC_HIERARCHY;
82                         break;
83                     case TPM_RH_PLATFORM:
84                         if(!g_phEnable)
85                             result = TPM_RC_HIERARCHY;
86                         break;
87                         // null handle, PW session handle and lockout
88                         // handle are always available
89                     case TPM_RH_NULL:
90                     case TPM_RS_PW:
91                         // Need to be careful for lockout. Lockout is always available
92                         // for policy checks but not always available when authValue
93                         // is being checked.
94                     case TPM_RH_LOCKOUT:
95                     // Rather than have #ifdefs all over the code,
96                     // CASE_ACT_HANDLE is defined in ACT.h. It is 'case TPM_RH_ACT_x:'
97                     // FOR_EACH_ACT(CASE_ACT_HANDLE) creates a simple
98                     // case TPM_RH_ACT_x: // for each of the implemented ACT.
99                     FOR_EACH_ACT(CASE_ACT_HANDLE)
100                         break;
101                     default:
102                         // If the implementation has a manufacturer-specific value
103                         // then test for it here. Since this implementation does
104                         // not have any, this implementation returns the same failure
105                         // that unmarshaling of a bad handle would produce.
106                         if(((TPM_RH)handle >= TPM_RH_AUTH_00)
107                            && ((TPM_RH)handle <= TPM_RH_AUTH_FF))
108                             // if the implementation has a manufacturer-specific value
109                             result = TPM_RC_VALUE;
110                         else
111                             // The handle is in the range of reserved handles but is
112                             // not implemented in this TPM.
113                             result = TPM_RC_VALUE;
114                         break;
115                 }
116                 break;
117             case TPM_HT_TRANSIENT:
118                 // For a transient object, check if the handle is associated
119                 // with a loaded object.
120                 if(!IsObjectPresent(handle))
121                     result = TPM_RC_REFERENCE_H0;
122                 break;
123             case TPM_HT_PERSISTENT:
124                 // Persistent object
125                 // Copy the persistent object to RAM and replace the handle with the
126                 // handle of the assigned slot.  A TPM_RC_OBJECT_MEMORY,
127                 // TPM_RC_HIERARCHY or TPM_RC_REFERENCE_H0 error may be returned by
128                 // ObjectLoadEvict()
129                 result = ObjectLoadEvict(&command->handles[i], command->index);
130                 break;
131             case TPM_HT_HMAC_SESSION:
132                 // For an HMAC session, see if the session is loaded
133                 // and if the session in the session slot is actually
134                 // an HMAC session.
135                 if(SessionIsLoaded(handle))
136                 {
137                     SESSION             *session;
138                     session = SessionGet(handle);
139                     // Check if the session is a HMAC session
140                     if(session->attributes.isPolicy == SET)
141                         result = TPM_RC_HANDLE;
142                 }
143                 else
144                     result = TPM_RC_REFERENCE_H0;
145                 break;
146             case TPM_HT_POLICY_SESSION:
147                 // For a policy session, see if the session is loaded
148                 // and if the session in the session slot is actually
149                 // a policy session.
150                 if(SessionIsLoaded(handle))
151                 {
152                     SESSION             *session;
153                     session = SessionGet(handle);
154                     // Check if the session is a policy session
155                     if(session->attributes.isPolicy == CLEAR)
156                         result = TPM_RC_HANDLE;
157                 }
158                 else
159                     result = TPM_RC_REFERENCE_H0;
160                 break;
161             case TPM_HT_NV_INDEX:
162                 // For an NV Index, use the TPM-specific routine
163                 // to search the IN Index space.
164                 result = NvIndexIsAccessible(handle);
165                 break;
166             case TPM_HT_PCR:
167                 // Any PCR handle that is unmarshaled successfully referenced
168                 // a PCR that is defined.
169                 break;
170 #if CC_AC_Send
171             case TPM_HT_AC:
172                 // Use the TPM-specific routine to search for the AC
173                 result = AcIsAccessible(handle);
174                 break;
175 #endif
176             default:
177                 // Any other handle type is a defect in the unmarshaling code.
178                 FAIL(FATAL_ERROR_INTERNAL);
179                 break;
180         }
181         if(result != TPM_RC_SUCCESS)
182         {
183             if(result == TPM_RC_REFERENCE_H0)
184                 result = result + i;
185             else
186                 result = RcSafeAddToResult(result, TPM_RC_H + g_rcIndex[i]);
187             break;
188         }
189     }
190     return result;
191 }
192 
193 //*** EntityGetAuthValue()
194 // This function is used to access the 'authValue' associated with a handle.
195 // This function assumes that the handle references an entity that is accessible
196 // and the handle is not for a persistent objects. That is EntityGetLoadStatus()
197 // should have been called. Also, the accessibility of the authValue should have
198 // been verified by IsAuthValueAvailable().
199 //
200 // This function copies the authorization value of the entity to 'auth'.
201 // Return Type: UINT16
202 //      count           number of bytes in the authValue with 0's stripped
203 UINT16
EntityGetAuthValue(TPMI_DH_ENTITY handle,TPM2B_AUTH * auth)204 EntityGetAuthValue(
205     TPMI_DH_ENTITY   handle,        // IN: handle of entity
206     TPM2B_AUTH      *auth           // OUT: authValue of the entity
207     )
208 {
209     TPM2B_AUTH      *pAuth = NULL;
210 
211     auth->t.size = 0;
212 
213     switch(HandleGetType(handle))
214     {
215         case TPM_HT_PERMANENT:
216         {
217             switch(handle)
218             {
219                 case TPM_RH_OWNER:
220                     // ownerAuth for TPM_RH_OWNER
221                     pAuth = &gp.ownerAuth;
222                     break;
223                 case TPM_RH_ENDORSEMENT:
224                     // endorsementAuth for TPM_RH_ENDORSEMENT
225                     pAuth = &gp.endorsementAuth;
226                     break;
227                 // The ACT use platformAuth for auth
228                 FOR_EACH_ACT(CASE_ACT_HANDLE)
229                 case TPM_RH_PLATFORM:
230                     // platformAuth for TPM_RH_PLATFORM
231                     pAuth = &gc.platformAuth;
232                     break;
233                 case TPM_RH_LOCKOUT:
234                     // lockoutAuth for TPM_RH_LOCKOUT
235                     pAuth = &gp.lockoutAuth;
236                     break;
237                 case TPM_RH_NULL:
238                     // nullAuth for TPM_RH_NULL. Return 0 directly here
239                     return 0;
240                     break;
241 #ifdef  VENDOR_PERMANENT
242                 case VENDOR_PERMANENT:
243                     // vendor authorization value
244                     pAuth = &g_platformUniqueDetails;
245 #endif
246                 default:
247                     // If any other permanent handle is present it is
248                     // a code defect.
249                     FAIL(FATAL_ERROR_INTERNAL);
250                     break;
251             }
252             break;
253         }
254         case TPM_HT_TRANSIENT:
255             // authValue for an object
256             // A persistent object would have been copied into RAM
257             // and would have an transient object handle here.
258         {
259             OBJECT          *object;
260 
261             object = HandleToObject(handle);
262             // special handling if this is a sequence object
263             if(ObjectIsSequence(object))
264             {
265                 pAuth = &((HASH_OBJECT *)object)->auth;
266             }
267             else
268             {
269                 // Authorization is available only when the private portion of
270                 // the object is loaded.  The check should be made before
271                 // this function is called
272                 pAssert(object->attributes.publicOnly == CLEAR);
273                 pAuth = &object->sensitive.authValue;
274             }
275         }
276         break;
277         case TPM_HT_NV_INDEX:
278             // authValue for an NV index
279         {
280             NV_INDEX        *nvIndex = NvGetIndexInfo(handle, NULL);
281             pAssert(nvIndex != NULL);
282             pAuth = &nvIndex->authValue;
283         }
284         break;
285         case TPM_HT_PCR:
286             // authValue for PCR
287             pAuth = PCRGetAuthValue(handle);
288             break;
289         default:
290             // If any other handle type is present here, then there is a defect
291             // in the unmarshaling code.
292             FAIL(FATAL_ERROR_INTERNAL);
293             break;
294     }
295     // Copy the authValue
296     MemoryCopy2B((TPM2B *)auth, (TPM2B *)pAuth, sizeof(auth->t.buffer));
297     MemoryRemoveTrailingZeros(auth);
298     return auth->t.size;
299 }
300 
301 //*** EntityGetAuthPolicy()
302 // This function is used to access the 'authPolicy' associated with a handle.
303 // This function assumes that the handle references an entity that is accessible
304 // and the handle is not for a persistent objects. That is EntityGetLoadStatus()
305 // should have been called. Also, the accessibility of the authPolicy should have
306 // been verified by IsAuthPolicyAvailable().
307 //
308 // This function copies the authorization policy of the entity to 'authPolicy'.
309 //
310 //  The return value is the hash algorithm for the policy.
311 TPMI_ALG_HASH
EntityGetAuthPolicy(TPMI_DH_ENTITY handle,TPM2B_DIGEST * authPolicy)312 EntityGetAuthPolicy(
313     TPMI_DH_ENTITY   handle,        // IN: handle of entity
314     TPM2B_DIGEST    *authPolicy     // OUT: authPolicy of the entity
315     )
316 {
317     TPMI_ALG_HASH       hashAlg = TPM_ALG_NULL;
318     authPolicy->t.size = 0;
319 
320     switch(HandleGetType(handle))
321     {
322         case TPM_HT_PERMANENT:
323             switch(handle)
324             {
325                 case TPM_RH_OWNER:
326                     // ownerPolicy for TPM_RH_OWNER
327                     *authPolicy = gp.ownerPolicy;
328                     hashAlg = gp.ownerAlg;
329                     break;
330                 case TPM_RH_ENDORSEMENT:
331                     // endorsementPolicy for TPM_RH_ENDORSEMENT
332                     *authPolicy = gp.endorsementPolicy;
333                     hashAlg = gp.endorsementAlg;
334                     break;
335                 case TPM_RH_PLATFORM:
336                     // platformPolicy for TPM_RH_PLATFORM
337                     *authPolicy = gc.platformPolicy;
338                     hashAlg = gc.platformAlg;
339                     break;
340                 case TPM_RH_LOCKOUT:
341                     // lockoutPolicy for TPM_RH_LOCKOUT
342                     *authPolicy = gp.lockoutPolicy;
343                     hashAlg = gp.lockoutAlg;
344                     break;
345 #define ACT_GET_POLICY(N)                                                           \
346                 case TPM_RH_ACT_##N:                                                \
347                     *authPolicy = go.ACT_##N.authPolicy;                            \
348                     hashAlg = go.ACT_##N.hashAlg;                                   \
349                     break;
350                     // Get the policy for each implemented ACT
351                     FOR_EACH_ACT(ACT_GET_POLICY)
352                 default:
353                     hashAlg = TPM_ALG_ERROR;
354                     break;
355             }
356             break;
357         case TPM_HT_TRANSIENT:
358             // authPolicy for an object
359         {
360             OBJECT *object = HandleToObject(handle);
361             *authPolicy = object->publicArea.authPolicy;
362             hashAlg = object->publicArea.nameAlg;
363         }
364         break;
365         case TPM_HT_NV_INDEX:
366             // authPolicy for a NV index
367         {
368             NV_INDEX        *nvIndex = NvGetIndexInfo(handle, NULL);
369             pAssert(nvIndex != 0);
370             *authPolicy = nvIndex->publicArea.authPolicy;
371             hashAlg = nvIndex->publicArea.nameAlg;
372         }
373         break;
374         case TPM_HT_PCR:
375             // authPolicy for a PCR
376             hashAlg = PCRGetAuthPolicy(handle, authPolicy);
377             break;
378         default:
379             // If any other handle type is present it is a code defect.
380             FAIL(FATAL_ERROR_INTERNAL);
381             break;
382     }
383     return hashAlg;
384 }
385 
386 //*** EntityGetName()
387 // This function returns the Name associated with a handle.
388 TPM2B_NAME *
EntityGetName(TPMI_DH_ENTITY handle,TPM2B_NAME * name)389 EntityGetName(
390     TPMI_DH_ENTITY   handle,        // IN: handle of entity
391     TPM2B_NAME      *name           // OUT: name of entity
392     )
393 {
394     switch(HandleGetType(handle))
395     {
396         case TPM_HT_TRANSIENT:
397         {
398             // Name for an object
399             OBJECT      *object = HandleToObject(handle);
400             // an object with no nameAlg has no name
401             if(object->publicArea.nameAlg == TPM_ALG_NULL)
402                 name->b.size = 0;
403             else
404                 *name = object->name;
405             break;
406         }
407         case TPM_HT_NV_INDEX:
408             // Name for a NV index
409             NvGetNameByIndexHandle(handle, name);
410             break;
411         default:
412             // For all other types, the handle is the Name
413             name->t.size = sizeof(TPM_HANDLE);
414             UINT32_TO_BYTE_ARRAY(handle, name->t.name);
415             break;
416     }
417     return name;
418 }
419 
420 //*** EntityGetHierarchy()
421 // This function returns the hierarchy handle associated with an entity.
422 // a) A handle that is a hierarchy handle is associated with itself.
423 // b) An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE,
424 //    is SET, otherwise it belongs to TPM_RH_OWNER
425 // c) An object handle belongs to its hierarchy.
426 TPMI_RH_HIERARCHY
EntityGetHierarchy(TPMI_DH_ENTITY handle)427 EntityGetHierarchy(
428     TPMI_DH_ENTITY   handle         // IN :handle of entity
429     )
430 {
431     TPMI_RH_HIERARCHY       hierarchy = TPM_RH_NULL;
432 
433     switch(HandleGetType(handle))
434     {
435         case TPM_HT_PERMANENT:
436             // hierarchy for a permanent handle
437             switch(handle)
438             {
439                 case TPM_RH_PLATFORM:
440                 case TPM_RH_ENDORSEMENT:
441                 case TPM_RH_NULL:
442                     hierarchy = handle;
443                     break;
444                 // all other permanent handles are associated with the owner
445                 // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT)
446                 default:
447                     hierarchy = TPM_RH_OWNER;
448                     break;
449             }
450             break;
451         case TPM_HT_NV_INDEX:
452             // hierarchy for NV index
453         {
454             NV_INDEX        *nvIndex = NvGetIndexInfo(handle, NULL);
455             pAssert(nvIndex != NULL);
456 
457             // If only the platform can delete the index, then it is
458             // considered to be in the platform hierarchy, otherwise it
459             // is in the owner hierarchy.
460             if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV,
461                             PLATFORMCREATE))
462                 hierarchy = TPM_RH_PLATFORM;
463             else
464                 hierarchy = TPM_RH_OWNER;
465         }
466         break;
467         case TPM_HT_TRANSIENT:
468             // hierarchy for an object
469         {
470             OBJECT          *object;
471             object = HandleToObject(handle);
472             if(object->attributes.ppsHierarchy)
473             {
474                 hierarchy = TPM_RH_PLATFORM;
475             }
476             else if(object->attributes.epsHierarchy)
477             {
478                 hierarchy = TPM_RH_ENDORSEMENT;
479             }
480             else if(object->attributes.spsHierarchy)
481             {
482                 hierarchy = TPM_RH_OWNER;
483             }
484         }
485         break;
486         case TPM_HT_PCR:
487             hierarchy = TPM_RH_OWNER;
488             break;
489         default:
490             FAIL(FATAL_ERROR_INTERNAL);
491             break;
492     }
493     // this is unreachable but it provides a return value for the default
494     // case which makes the complier happy
495     return hierarchy;
496 }