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 #include "InternalRoutines.h"
9 //
10 //
11 //
12 // Functions
13 //
14 // EntityGetLoadStatus()
15 //
16 // This function will indicate if the entity associated with a handle is present in TPM memory. If the handle is
17 // a persistent object handle, and the object exists, the persistent object is moved from NV memory into a
18 // RAM object slot and the persistent handle is replaced with the transient object handle for the slot.
19 //
20 // Error Returns Meaning
21 //
22 // TPM_RC_HANDLE handle type does not match
23 // TPM_RC_REFERENCE_H0 entity is not present
24 // TPM_RC_HIERARCHY entity belongs to a disabled hierarchy
25 // TPM_RC_OBJECT_MEMORY handle is an evict object but there is no space to load it to RAM
26 //
27 TPM_RC
EntityGetLoadStatus(TPM_HANDLE * handle,TPM_CC commandCode)28 EntityGetLoadStatus(
29 TPM_HANDLE *handle, // IN/OUT: handle of the entity
30 TPM_CC commandCode // IN: the commmandCode
31 )
32 {
33 TPM_RC result = TPM_RC_SUCCESS;
34 switch(HandleGetType(*handle))
35 {
36 // For handles associated with hierarchies, the entity is present
37 // only if the associated enable is SET.
38 case TPM_HT_PERMANENT:
39 switch(*handle)
40 {
41 case TPM_RH_OWNER:
42 if(!gc.shEnable)
43 result = TPM_RC_HIERARCHY;
44 break;
45 #ifdef VENDOR_PERMANENT
46 case VENDOR_PERMANENT:
47 #endif
48 case TPM_RH_ENDORSEMENT:
49 if(!gc.ehEnable)
50 result = TPM_RC_HIERARCHY;
51 break;
52 case TPM_RH_PLATFORM:
53 if(!g_phEnable)
54 result = TPM_RC_HIERARCHY;
55 break;
56 // null handle, PW session handle and lockout
57 // handle are always available
58 case TPM_RH_NULL:
59 case TPM_RS_PW:
60 case TPM_RH_LOCKOUT:
61 break;
62 default:
63 // handling of the manufacture_specific handles
64 if( ((TPM_RH)*handle >= TPM_RH_FIRST)
65 && ((TPM_RH)*handle <= TPM_RH_LAST))
66 // use the value that would have been returned from
67 // unmarshaling if it did the handle filtering
68 result = TPM_RC_VALUE;
69 else
70 pAssert(FALSE);
71 break;
72 }
73 break;
74 case TPM_HT_TRANSIENT:
75 // For a transient object, check if the handle is associated
76 // with a loaded object.
77 if(!ObjectIsPresent(*handle))
78 result = TPM_RC_REFERENCE_H0;
79 break;
80 case TPM_HT_PERSISTENT:
81 // Persistent object
82 // Copy the persistent object to RAM and replace the handle with the
83 // handle of the assigned slot. A TPM_RC_OBJECT_MEMORY,
84 // TPM_RC_HIERARCHY or TPM_RC_REFERENCE_H0 error may be returned by
85 // ObjectLoadEvict()
86 result = ObjectLoadEvict(handle, commandCode);
87 break;
88 case TPM_HT_HMAC_SESSION:
89 // For an HMAC session, see if the session is loaded
90 // and if the session in the session slot is actually
91 // an HMAC session.
92 if(SessionIsLoaded(*handle))
93 {
94 SESSION *session;
95 session = SessionGet(*handle);
96 // Check if the session is a HMAC session
97 if(session->attributes.isPolicy == SET)
98 result = TPM_RC_HANDLE;
99 }
100 else
101 result = TPM_RC_REFERENCE_H0;
102 break;
103 case TPM_HT_POLICY_SESSION:
104 // For a policy session, see if the session is loaded
105 // and if the session in the session slot is actually
106 // a policy session.
107 if(SessionIsLoaded(*handle))
108 {
109 SESSION *session;
110 session = SessionGet(*handle);
111 // Check if the session is a policy session
112 if(session->attributes.isPolicy == CLEAR)
113 result = TPM_RC_HANDLE;
114 }
115 else
116 result = TPM_RC_REFERENCE_H0;
117 break;
118 case TPM_HT_NV_INDEX:
119 // For an NV Index, use the platform-specific routine
120 // to search the IN Index space.
121 result = NvIndexIsAccessible(*handle, commandCode);
122 break;
123 case TPM_HT_PCR:
124 // Any PCR handle that is unmarshaled successfully referenced
125 // a PCR that is defined.
126 break;
127 default:
128 // Any other handle type is a defect in the unmarshaling code.
129 pAssert(FALSE);
130 break;
131 }
132 return result;
133 }
134 //
135 //
136 //
137 // EntityGetAuthValue()
138 //
139 // This function is used to access the authValue associated with a handle. This function assumes that the
140 // handle references an entity that is accessible and the handle is not for a persistent objects. That is
141 // EntityGetLoadStatus() should have been called. Also, the accessibility of the authValue should have been
142 // verified by IsAuthValueAvailable().
143 // This function copies the authorization value of the entity to auth.
144 // Return value is the number of octets copied to auth.
145 //
146 UINT16
EntityGetAuthValue(TPMI_DH_ENTITY handle,AUTH_VALUE * auth)147 EntityGetAuthValue(
148 TPMI_DH_ENTITY handle, // IN: handle of entity
149 AUTH_VALUE *auth // OUT: authValue of the entity
150 )
151 {
152 TPM2B_AUTH authValue = {};
153 switch(HandleGetType(handle))
154 {
155 case TPM_HT_PERMANENT:
156 switch(handle)
157 {
158 case TPM_RH_OWNER:
159 // ownerAuth for TPM_RH_OWNER
160 authValue = gp.ownerAuth;
161 break;
162 case TPM_RH_ENDORSEMENT:
163 // endorsementAuth for TPM_RH_ENDORSEMENT
164 authValue = gp.endorsementAuth;
165 break;
166 case TPM_RH_PLATFORM:
167 // platformAuth for TPM_RH_PLATFORM
168 authValue = gc.platformAuth;
169 break;
170 case TPM_RH_LOCKOUT:
171 // lockoutAuth for TPM_RH_LOCKOUT
172 authValue = gp.lockoutAuth;
173 break;
174 case TPM_RH_NULL:
175 // nullAuth for TPM_RH_NULL. Return 0 directly here
176 return 0;
177 break;
178 #ifdef VENDOR_PERMANENT
179 case VENDOR_PERMANENT:
180 // vendor auth value
181 authValue = g_platformUniqueDetails;
182 #endif
183 default:
184 // If any other permanent handle is present it is
185 // a code defect.
186 pAssert(FALSE);
187 break;
188 }
189 break;
190 case TPM_HT_TRANSIENT:
191 // authValue for an object
192 // A persistent object would have been copied into RAM
193 // and would have an transient object handle here.
194 {
195 OBJECT *object;
196 object = ObjectGet(handle);
197 // special handling if this is a sequence object
198 if(ObjectIsSequence(object))
199 {
200 authValue = ((HASH_OBJECT *)object)->auth;
201 }
202 else
203 {
204 // Auth value is available only when the private portion of
205 // the object is loaded. The check should be made before
206 // this function is called
207 pAssert(object->attributes.publicOnly == CLEAR);
208 authValue = object->sensitive.authValue;
209 }
210 }
211 break;
212 case TPM_HT_NV_INDEX:
213 // authValue for an NV index
214 {
215 NV_INDEX nvIndex;
216 NvGetIndexInfo(handle, &nvIndex);
217 authValue = nvIndex.authValue;
218 }
219 break;
220 case TPM_HT_PCR:
221 // authValue for PCR
222 PCRGetAuthValue(handle, &authValue);
223 break;
224 default:
225 // If any other handle type is present here, then there is a defect
226 // in the unmarshaling code.
227 pAssert(FALSE);
228 break;
229 }
230 // Copy the authValue
231 pAssert(authValue.t.size <= sizeof(authValue.t.buffer));
232 MemoryCopy(auth, authValue.t.buffer, authValue.t.size, sizeof(TPMU_HA));
233 return authValue.t.size;
234 }
235 //
236 //
237 // EntityGetAuthPolicy()
238 //
239 // This function is used to access the authPolicy associated with a handle. This function assumes that the
240 // handle references an entity that is accessible and the handle is not for a persistent objects. That is
241 // EntityGetLoadStatus() should have been called. Also, the accessibility of the authPolicy should have
242 // been verified by IsAuthPolicyAvailable().
243 // This function copies the authorization policy of the entity to authPolicy.
244 // The return value is the hash algorithm for the policy.
245 //
246 TPMI_ALG_HASH
EntityGetAuthPolicy(TPMI_DH_ENTITY handle,TPM2B_DIGEST * authPolicy)247 EntityGetAuthPolicy(
248 TPMI_DH_ENTITY handle, // IN: handle of entity
249 TPM2B_DIGEST *authPolicy // OUT: authPolicy of the entity
250 )
251 {
252 TPMI_ALG_HASH hashAlg = TPM_ALG_NULL;
253 switch(HandleGetType(handle))
254 {
255 case TPM_HT_PERMANENT:
256 switch(handle)
257 {
258 case TPM_RH_OWNER:
259 //
260 // ownerPolicy for TPM_RH_OWNER
261 *authPolicy = gp.ownerPolicy;
262 hashAlg = gp.ownerAlg;
263 break;
264 case TPM_RH_ENDORSEMENT:
265 // endorsementPolicy for TPM_RH_ENDORSEMENT
266 *authPolicy = gp.endorsementPolicy;
267 hashAlg = gp.endorsementAlg;
268 break;
269 case TPM_RH_PLATFORM:
270 // platformPolicy for TPM_RH_PLATFORM
271 *authPolicy = gc.platformPolicy;
272 hashAlg = gc.platformAlg;
273 break;
274 case TPM_RH_LOCKOUT:
275 // lockoutPolicy for TPM_RH_LOCKOUT
276 *authPolicy = gp.lockoutPolicy;
277 hashAlg = gp.lockoutAlg;
278 break;
279 default:
280 // If any other permanent handle is present it is
281 // a code defect.
282 pAssert(FALSE);
283 break;
284 }
285 break;
286 case TPM_HT_TRANSIENT:
287 // authPolicy for an object
288 {
289 OBJECT *object = ObjectGet(handle);
290 *authPolicy = object->publicArea.authPolicy;
291 hashAlg = object->publicArea.nameAlg;
292 }
293 break;
294 case TPM_HT_NV_INDEX:
295 // authPolicy for a NV index
296 {
297 NV_INDEX nvIndex;
298 NvGetIndexInfo(handle, &nvIndex);
299 *authPolicy = nvIndex.publicArea.authPolicy;
300 hashAlg = nvIndex.publicArea.nameAlg;
301 }
302 break;
303 case TPM_HT_PCR:
304 // authPolicy for a PCR
305 hashAlg = PCRGetAuthPolicy(handle, authPolicy);
306 break;
307 default:
308 // If any other handle type is present it is a code defect.
309 pAssert(FALSE);
310 break;
311 }
312 return hashAlg;
313 }
314 //
315 //
316 // EntityGetName()
317 //
318 // This function returns the Name associated with a handle. It will set name to the Name and return the size
319 // of the Name string.
320 //
321 UINT16
EntityGetName(TPMI_DH_ENTITY handle,NAME * name)322 EntityGetName(
323 TPMI_DH_ENTITY handle, // IN: handle of entity
324 NAME *name // OUT: name of entity
325 )
326 {
327 UINT16 nameSize;
328 INT32 bufferSize = sizeof(TPM_HANDLE);
329 switch(HandleGetType(handle))
330 {
331 case TPM_HT_TRANSIENT:
332 // Name for an object
333 nameSize = ObjectGetName(handle, name);
334 break;
335 case TPM_HT_NV_INDEX:
336 // Name for a NV index
337 nameSize = NvGetName(handle, name);
338 break;
339 default:
340 // For all other types, the handle is the Name
341 nameSize = TPM_HANDLE_Marshal(&handle, (BYTE **)&name, &bufferSize);
342 break;
343 }
344 return nameSize;
345 }
346 //
347 //
348 // EntityGetHierarchy()
349 //
350 // This function returns the hierarchy handle associated with an entity.
351 // a) A handle that is a hierarchy handle is associated with itself.
352 // b) An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, is SET,
353 // otherwise it belongs to TPM_RH_OWNER
354 // c) An object handle belongs to its hierarchy. All other handles belong to the platform hierarchy. or an NV
355 // Index.
356 //
357 TPMI_RH_HIERARCHY
EntityGetHierarchy(TPMI_DH_ENTITY handle)358 EntityGetHierarchy(
359 TPMI_DH_ENTITY handle // IN :handle of entity
360 )
361 {
362 TPMI_RH_HIERARCHY hierarcy = TPM_RH_NULL;
363 switch(HandleGetType(handle))
364 {
365 case TPM_HT_PERMANENT:
366 // hierarchy for a permanent handle
367 switch(handle)
368 {
369 case TPM_RH_PLATFORM:
370 case TPM_RH_ENDORSEMENT:
371 case TPM_RH_NULL:
372 hierarcy = handle;
373 break;
374 // all other permanent handles are associated with the owner
375 // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT)
376 default:
377 hierarcy = TPM_RH_OWNER;
378 break;
379 }
380 break;
381 case TPM_HT_NV_INDEX:
382 // hierarchy for NV index
383 {
384 NV_INDEX nvIndex;
385 NvGetIndexInfo(handle, &nvIndex);
386 // If only the platform can delete the index, then it is
387 // considered to be in the platform hierarchy, otherwise it
388 // is in the owner hierarchy.
389 if(nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == SET)
390 hierarcy = TPM_RH_PLATFORM;
391 else
392 hierarcy = TPM_RH_OWNER;
393 }
394 break;
395 case TPM_HT_TRANSIENT:
396 // hierarchy for an object
397 {
398 OBJECT *object;
399 object = ObjectGet(handle);
400 if(object->attributes.ppsHierarchy)
401 {
402 hierarcy = TPM_RH_PLATFORM;
403 }
404 else if(object->attributes.epsHierarchy)
405 {
406 hierarcy = TPM_RH_ENDORSEMENT;
407 }
408 else if(object->attributes.spsHierarchy)
409 {
410 hierarcy = TPM_RH_OWNER;
411 }
412 }
413 break;
414 case TPM_HT_PCR:
415 hierarcy = TPM_RH_OWNER;
416 break;
417 default:
418 pAssert(0);
419 break;
420 }
421 // this is unreachable but it provides a return value for the default
422 // case which makes the complier happy
423 return hierarcy;
424 }
425