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 }