/src/ibmswtpm2/src/Entity.c
Line | Count | Source |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* Accessing properties for handles of various types */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: Entity.c 1259 2018-07-10 19:11:09Z kgoldman $ */ |
7 | | /* */ |
8 | | /* Licenses and Notices */ |
9 | | /* */ |
10 | | /* 1. Copyright Licenses: */ |
11 | | /* */ |
12 | | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ |
13 | | /* this specification (the "Source Code") a worldwide, irrevocable, */ |
14 | | /* nonexclusive, royalty free, copyright license to reproduce, create */ |
15 | | /* derivative works, distribute, display and perform the Source Code and */ |
16 | | /* derivative works thereof, and to grant others the rights granted herein. */ |
17 | | /* */ |
18 | | /* - The TCG grants to the user of the other parts of the specification */ |
19 | | /* (other than the Source Code) the rights to reproduce, distribute, */ |
20 | | /* display, and perform the specification solely for the purpose of */ |
21 | | /* developing products based on such documents. */ |
22 | | /* */ |
23 | | /* 2. Source Code Distribution Conditions: */ |
24 | | /* */ |
25 | | /* - Redistributions of Source Code must retain the above copyright licenses, */ |
26 | | /* this list of conditions and the following disclaimers. */ |
27 | | /* */ |
28 | | /* - Redistributions in binary form must reproduce the above copyright */ |
29 | | /* licenses, this list of conditions and the following disclaimers in the */ |
30 | | /* documentation and/or other materials provided with the distribution. */ |
31 | | /* */ |
32 | | /* 3. Disclaimers: */ |
33 | | /* */ |
34 | | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ |
35 | | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ |
36 | | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ |
37 | | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ |
38 | | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ |
39 | | /* information on specification licensing rights available through TCG */ |
40 | | /* membership agreements. */ |
41 | | /* */ |
42 | | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ |
43 | | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ |
44 | | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ |
45 | | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ |
46 | | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ |
47 | | /* */ |
48 | | /* - Without limitation, TCG and its members and licensors disclaim all */ |
49 | | /* liability, including liability for infringement of any proprietary */ |
50 | | /* rights, relating to use of information in this specification and to the */ |
51 | | /* implementation of this specification, and TCG disclaims all liability for */ |
52 | | /* cost of procurement of substitute goods or services, lost profits, loss */ |
53 | | /* of use, loss of data or any incidental, consequential, direct, indirect, */ |
54 | | /* or special damages, whether under contract, tort, warranty or otherwise, */ |
55 | | /* arising in any way out of use or reliance upon this specification or any */ |
56 | | /* information herein. */ |
57 | | /* */ |
58 | | /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ |
59 | | /* */ |
60 | | /********************************************************************************/ |
61 | | |
62 | | /* 9.4 Entity.c */ |
63 | | /* 9.4.1 Description */ |
64 | | /* The functions in this file are used for accessing properties for handles of various |
65 | | types. Functions in other files require handles of a specific type but the functions in this file |
66 | | allow use of any handle type. */ |
67 | | /* 9.4.2 Includes */ |
68 | | #include "Tpm.h" |
69 | | /* 9.4.3 Functions */ |
70 | | /* 9.4.3.1 EntityGetLoadStatus() */ |
71 | | /* This function will check that all the handles access loaded entities. */ |
72 | | /* Error Returns Meaning */ |
73 | | /* TPM_RC_HANDLE handle type does not match */ |
74 | | /* TPM_RC_REFERENCE_Hx() entity is not present */ |
75 | | /* TPM_RC_HIERARCHY entity belongs to a disabled hierarchy */ |
76 | | /* TPM_RC_OBJECT_MEMORY handle is an evict object but there is no space to load it to RAM */ |
77 | | TPM_RC |
78 | | EntityGetLoadStatus( |
79 | | COMMAND *command // IN/OUT: command parsing structure |
80 | | ) |
81 | 2.44k | { |
82 | 2.44k | UINT32 i; |
83 | 2.44k | TPM_RC result = TPM_RC_SUCCESS; |
84 | | // |
85 | 2.44k | for(i = 0; i < command->handleNum; i++) |
86 | 0 | { |
87 | 0 | TPM_HANDLE handle = command->handles[i]; |
88 | 0 | switch(HandleGetType(handle)) |
89 | 0 | { |
90 | | // For handles associated with hierarchies, the entity is present |
91 | | // only if the associated enable is SET. |
92 | 0 | case TPM_HT_PERMANENT: |
93 | 0 | switch(handle) |
94 | 0 | { |
95 | 0 | case TPM_RH_OWNER: |
96 | 0 | if(!gc.shEnable) |
97 | 0 | result = TPM_RC_HIERARCHY; |
98 | 0 | break; |
99 | | #ifdef VENDOR_PERMANENT |
100 | | case VENDOR_PERMANENT: |
101 | | #endif |
102 | 0 | case TPM_RH_ENDORSEMENT: |
103 | 0 | if(!gc.ehEnable) |
104 | 0 | result = TPM_RC_HIERARCHY; |
105 | 0 | break; |
106 | 0 | case TPM_RH_PLATFORM: |
107 | 0 | if(!g_phEnable) |
108 | 0 | result = TPM_RC_HIERARCHY; |
109 | 0 | break; |
110 | | // null handle, PW session handle and lockout |
111 | | // handle are always available |
112 | 0 | case TPM_RH_NULL: |
113 | 0 | case TPM_RS_PW: |
114 | | // Need to be careful for lockout. Lockout is always available |
115 | | // for policy checks but not always available when authValue |
116 | | // is being checked. |
117 | 0 | case TPM_RH_LOCKOUT: |
118 | 0 | break; |
119 | 0 | default: |
120 | | // handling of the manufacture_specific handles |
121 | 0 | if(((TPM_RH)handle >= TPM_RH_AUTH_00) |
122 | 0 | && ((TPM_RH)handle <= TPM_RH_AUTH_FF)) |
123 | | // use the value that would have been returned from |
124 | | // unmarshaling if it did the handle filtering |
125 | 0 | result = TPM_RC_VALUE; |
126 | 0 | else |
127 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
128 | 0 | break; |
129 | 0 | } |
130 | 0 | break; |
131 | 0 | case TPM_HT_TRANSIENT: |
132 | | // For a transient object, check if the handle is associated |
133 | | // with a loaded object. |
134 | 0 | if(!IsObjectPresent(handle)) |
135 | 0 | result = TPM_RC_REFERENCE_H0; |
136 | 0 | break; |
137 | 0 | case TPM_HT_PERSISTENT: |
138 | | // Persistent object |
139 | | // Copy the persistent object to RAM and replace the handle with the |
140 | | // handle of the assigned slot. A TPM_RC_OBJECT_MEMORY, |
141 | | // TPM_RC_HIERARCHY or TPM_RC_REFERENCE_H0 error may be returned by |
142 | | // ObjectLoadEvict() |
143 | 0 | result = ObjectLoadEvict(&command->handles[i], command->index); |
144 | 0 | break; |
145 | 0 | case TPM_HT_HMAC_SESSION: |
146 | | // For an HMAC session, see if the session is loaded |
147 | | // and if the session in the session slot is actually |
148 | | // an HMAC session. |
149 | 0 | if(SessionIsLoaded(handle)) |
150 | 0 | { |
151 | 0 | SESSION *session; |
152 | 0 | session = SessionGet(handle); |
153 | | // Check if the session is a HMAC session |
154 | 0 | if(session->attributes.isPolicy == SET) |
155 | 0 | result = TPM_RC_HANDLE; |
156 | 0 | } |
157 | 0 | else |
158 | 0 | result = TPM_RC_REFERENCE_H0; |
159 | 0 | break; |
160 | 0 | case TPM_HT_POLICY_SESSION: |
161 | | // For a policy session, see if the session is loaded |
162 | | // and if the session in the session slot is actually |
163 | | // a policy session. |
164 | 0 | if(SessionIsLoaded(handle)) |
165 | 0 | { |
166 | 0 | SESSION *session; |
167 | 0 | session = SessionGet(handle); |
168 | | // Check if the session is a policy session |
169 | 0 | if(session->attributes.isPolicy == CLEAR) |
170 | 0 | result = TPM_RC_HANDLE; |
171 | 0 | } |
172 | 0 | else |
173 | 0 | result = TPM_RC_REFERENCE_H0; |
174 | 0 | break; |
175 | 0 | case TPM_HT_NV_INDEX: |
176 | | // For an NV Index, use the TPM-specific routine |
177 | | // to search the IN Index space. |
178 | 0 | result = NvIndexIsAccessible(handle); |
179 | 0 | break; |
180 | 0 | case TPM_HT_PCR: |
181 | | // Any PCR handle that is unmarshaled successfully referenced |
182 | | // a PCR that is defined. |
183 | 0 | break; |
184 | | #if CC_AC_Send |
185 | | case TPM_HT_AC: |
186 | | // Use the TPM-specific routine to search for the AC |
187 | | result = AcIsAccessible(handle); |
188 | | break; |
189 | | #endif |
190 | 0 | default: |
191 | | // Any other handle type is a defect in the unmarshaling code. |
192 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
193 | 0 | break; |
194 | 0 | } |
195 | 0 | if(result != TPM_RC_SUCCESS) |
196 | 0 | { |
197 | 0 | if(result == TPM_RC_REFERENCE_H0) |
198 | 0 | result = result + i; |
199 | 0 | else |
200 | 0 | result = RcSafeAddToResult(result, TPM_RC_H + g_rcIndex[i]); |
201 | 0 | break; |
202 | 0 | } |
203 | 0 | } |
204 | 2.44k | return result; |
205 | 2.44k | } |
206 | | /* 9.4.3.2 EntityGetAuthValue() */ |
207 | | /* This function is used to access the authValue associated with a handle. This function assumes |
208 | | that the handle references an entity that is accessible and the handle is not for a persistent |
209 | | objects. That is EntityGetLoadStatus() should have been called. Also, the accessibility of the |
210 | | authValue should have been verified by IsAuthValueAvailable(). */ |
211 | | /* This function copies the authorization value of the entity to auth. */ |
212 | | /* Return Values Meaning */ |
213 | | /* count number of bytes in the authValue with zeros stripped */ |
214 | | UINT16 |
215 | | EntityGetAuthValue( |
216 | | TPMI_DH_ENTITY handle, // IN: handle of entity |
217 | | TPM2B_AUTH *auth // OUT: authValue of the entity |
218 | | ) |
219 | 0 | { |
220 | 0 | TPM2B_AUTH *pAuth = NULL; |
221 | 0 | auth->t.size = 0; |
222 | 0 | switch(HandleGetType(handle)) |
223 | 0 | { |
224 | 0 | case TPM_HT_PERMANENT: |
225 | 0 | { |
226 | 0 | switch(handle) |
227 | 0 | { |
228 | 0 | case TPM_RH_OWNER: |
229 | | // ownerAuth for TPM_RH_OWNER |
230 | 0 | pAuth = &gp.ownerAuth; |
231 | 0 | break; |
232 | 0 | case TPM_RH_ENDORSEMENT: |
233 | | // endorsementAuth for TPM_RH_ENDORSEMENT |
234 | 0 | pAuth = &gp.endorsementAuth; |
235 | 0 | break; |
236 | 0 | case TPM_RH_PLATFORM: |
237 | | // platformAuth for TPM_RH_PLATFORM |
238 | 0 | pAuth = &gc.platformAuth; |
239 | 0 | break; |
240 | 0 | case TPM_RH_LOCKOUT: |
241 | | // lockoutAuth for TPM_RH_LOCKOUT |
242 | 0 | pAuth = &gp.lockoutAuth; |
243 | 0 | break; |
244 | 0 | case TPM_RH_NULL: |
245 | | // nullAuth for TPM_RH_NULL. Return 0 directly here |
246 | 0 | return 0; |
247 | 0 | break; |
248 | | #ifdef VENDOR_PERMANENT |
249 | | case VENDOR_PERMANENT: |
250 | | // vendor authorization value |
251 | | pAauth = &g_platformUniqueDetails; |
252 | | #endif |
253 | 0 | default: |
254 | | // If any other permanent handle is present it is |
255 | | // a code defect. |
256 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
257 | 0 | break; |
258 | 0 | } |
259 | 0 | break; |
260 | 0 | } |
261 | 0 | case TPM_HT_TRANSIENT: |
262 | | // authValue for an object |
263 | | // A persistent object would have been copied into RAM |
264 | | // and would have an transient object handle here. |
265 | 0 | { |
266 | 0 | OBJECT *object; |
267 | 0 | object = HandleToObject(handle); |
268 | | // special handling if this is a sequence object |
269 | 0 | if(ObjectIsSequence(object)) |
270 | 0 | { |
271 | 0 | pAuth = &((HASH_OBJECT *)object)->auth; |
272 | 0 | } |
273 | 0 | else |
274 | 0 | { |
275 | | // Authorization is available only when the private portion of |
276 | | // the object is loaded. The check should be made before |
277 | | // this function is called |
278 | 0 | pAssert(object->attributes.publicOnly == CLEAR); |
279 | 0 | pAuth = &object->sensitive.authValue; |
280 | 0 | } |
281 | 0 | } |
282 | 0 | break; |
283 | 0 | case TPM_HT_NV_INDEX: |
284 | | // authValue for an NV index |
285 | 0 | { |
286 | 0 | NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); |
287 | 0 | pAssert(nvIndex != NULL); |
288 | 0 | pAuth = &nvIndex->authValue; |
289 | 0 | } |
290 | 0 | break; |
291 | 0 | case TPM_HT_PCR: |
292 | | // authValue for PCR |
293 | 0 | pAuth = PCRGetAuthValue(handle); |
294 | 0 | break; |
295 | 0 | default: |
296 | | // If any other handle type is present here, then there is a defect |
297 | | // in the unmarshaling code. |
298 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
299 | 0 | break; |
300 | 0 | } |
301 | | // Copy the authValue |
302 | 0 | MemoryCopy2B(&auth->b, &pAuth->b, sizeof(auth->t.buffer)); |
303 | 0 | MemoryRemoveTrailingZeros(auth); |
304 | 0 | return auth->t.size; |
305 | 0 | } |
306 | | /* 9.4.3.3 EntityGetAuthPolicy() */ |
307 | | /* This function is used to access the authPolicy associated with a handle. This function assumes |
308 | | that the handle references an entity that is accessible and the handle is not for a persistent |
309 | | objects. That is EntityGetLoadStatus() should have been called. Also, the accessibility of the |
310 | | authPolicy should have been verified by IsAuthPolicyAvailable(). */ |
311 | | /* This function copies the authorization policy of the entity to authPolicy. */ |
312 | | /* The return value is the hash algorithm for the policy. */ |
313 | | TPMI_ALG_HASH |
314 | | EntityGetAuthPolicy( |
315 | | TPMI_DH_ENTITY handle, // IN: handle of entity |
316 | | TPM2B_DIGEST *authPolicy // OUT: authPolicy of the entity |
317 | | ) |
318 | 0 | { |
319 | 0 | TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; |
320 | 0 | authPolicy->t.size = 0; |
321 | 0 | switch(HandleGetType(handle)) |
322 | 0 | { |
323 | 0 | case TPM_HT_PERMANENT: |
324 | 0 | switch(handle) |
325 | 0 | { |
326 | 0 | case TPM_RH_OWNER: |
327 | | // ownerPolicy for TPM_RH_OWNER |
328 | 0 | *authPolicy = gp.ownerPolicy; |
329 | 0 | hashAlg = gp.ownerAlg; |
330 | 0 | break; |
331 | 0 | case TPM_RH_ENDORSEMENT: |
332 | | // endorsementPolicy for TPM_RH_ENDORSEMENT |
333 | 0 | *authPolicy = gp.endorsementPolicy; |
334 | 0 | hashAlg = gp.endorsementAlg; |
335 | 0 | break; |
336 | 0 | case TPM_RH_PLATFORM: |
337 | | // platformPolicy for TPM_RH_PLATFORM |
338 | 0 | *authPolicy = gc.platformPolicy; |
339 | 0 | hashAlg = gc.platformAlg; |
340 | 0 | break; |
341 | 0 | case TPM_RH_LOCKOUT: |
342 | | // lockoutPolicy for TPM_RH_LOCKOUT |
343 | 0 | *authPolicy = gp.lockoutPolicy; |
344 | 0 | hashAlg = gp.lockoutAlg; |
345 | 0 | break; |
346 | 0 | default: |
347 | 0 | return TPM_ALG_ERROR; |
348 | 0 | break; |
349 | 0 | } |
350 | 0 | break; |
351 | 0 | case TPM_HT_TRANSIENT: |
352 | | // authPolicy for an object |
353 | 0 | { |
354 | 0 | OBJECT *object = HandleToObject(handle); |
355 | 0 | *authPolicy = object->publicArea.authPolicy; |
356 | 0 | hashAlg = object->publicArea.nameAlg; |
357 | 0 | } |
358 | 0 | break; |
359 | 0 | case TPM_HT_NV_INDEX: |
360 | | // authPolicy for a NV index |
361 | 0 | { |
362 | 0 | NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); |
363 | 0 | pAssert(nvIndex != 0); |
364 | 0 | *authPolicy = nvIndex->publicArea.authPolicy; |
365 | 0 | hashAlg = nvIndex->publicArea.nameAlg; |
366 | 0 | } |
367 | 0 | break; |
368 | 0 | case TPM_HT_PCR: |
369 | | // authPolicy for a PCR |
370 | 0 | hashAlg = PCRGetAuthPolicy(handle, authPolicy); |
371 | 0 | break; |
372 | 0 | default: |
373 | | // If any other handle type is present it is a code defect. |
374 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
375 | 0 | break; |
376 | 0 | } |
377 | 0 | return hashAlg; |
378 | 0 | } |
379 | | /* 9.4.3.4 EntityGetName() */ |
380 | | /* This function returns the Name associated with a handle. */ |
381 | | TPM2B_NAME * |
382 | | EntityGetName( |
383 | | TPMI_DH_ENTITY handle, // IN: handle of entity |
384 | | TPM2B_NAME *name // OUT: name of entity |
385 | | ) |
386 | 0 | { |
387 | 0 | switch(HandleGetType(handle)) |
388 | 0 | { |
389 | 0 | case TPM_HT_TRANSIENT: |
390 | 0 | { |
391 | | // Name for an object |
392 | 0 | OBJECT *object = HandleToObject(handle); |
393 | | // an object with no nameAlg has no name |
394 | 0 | if(object->publicArea.nameAlg == TPM_ALG_NULL) |
395 | 0 | name->b.size = 0; |
396 | 0 | else |
397 | 0 | *name = object->name; |
398 | 0 | break; |
399 | 0 | } |
400 | 0 | case TPM_HT_NV_INDEX: |
401 | | // Name for a NV index |
402 | 0 | NvGetNameByIndexHandle(handle, name); |
403 | 0 | break; |
404 | 0 | default: |
405 | | // For all other types, the handle is the Name |
406 | 0 | name->t.size = sizeof(TPM_HANDLE); |
407 | 0 | UINT32_TO_BYTE_ARRAY(handle, name->t.name); |
408 | 0 | break; |
409 | 0 | } |
410 | 0 | return name; |
411 | 0 | } |
412 | | /* 9.4.3.5 EntityGetHierarchy() */ |
413 | | /* This function returns the hierarchy handle associated with an entity. */ |
414 | | /* a) A handle that is a hierarchy handle is associated with itself. */ |
415 | | /* b) An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, is SET, otherwise it belongs |
416 | | to TPM_RH_OWNER */ |
417 | | /* c) An object handle belongs to its hierarchy. All other handles belong to the platform |
418 | | hierarchy. or an NV Index. */ |
419 | | TPMI_RH_HIERARCHY |
420 | | EntityGetHierarchy( |
421 | | TPMI_DH_ENTITY handle // IN :handle of entity |
422 | | ) |
423 | 0 | { |
424 | 0 | TPMI_RH_HIERARCHY hierarchy = TPM_RH_NULL; |
425 | 0 | switch(HandleGetType(handle)) |
426 | 0 | { |
427 | 0 | case TPM_HT_PERMANENT: |
428 | | // hierarchy for a permanent handle |
429 | 0 | switch(handle) |
430 | 0 | { |
431 | 0 | case TPM_RH_PLATFORM: |
432 | 0 | case TPM_RH_ENDORSEMENT: |
433 | 0 | case TPM_RH_NULL: |
434 | 0 | hierarchy = handle; |
435 | 0 | break; |
436 | | // all other permanent handles are associated with the owner |
437 | | // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT) |
438 | 0 | default: |
439 | 0 | hierarchy = TPM_RH_OWNER; |
440 | 0 | break; |
441 | 0 | } |
442 | 0 | break; |
443 | 0 | case TPM_HT_NV_INDEX: |
444 | | // hierarchy for NV index |
445 | 0 | { |
446 | 0 | NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); |
447 | 0 | pAssert(nvIndex != NULL); |
448 | | // If only the platform can delete the index, then it is |
449 | | // considered to be in the platform hierarchy, otherwise it |
450 | | // is in the owner hierarchy. |
451 | 0 | if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, |
452 | 0 | PLATFORMCREATE)) |
453 | 0 | hierarchy = TPM_RH_PLATFORM; |
454 | 0 | else |
455 | 0 | hierarchy = TPM_RH_OWNER; |
456 | 0 | } |
457 | 0 | break; |
458 | 0 | case TPM_HT_TRANSIENT: |
459 | | // hierarchy for an object |
460 | 0 | { |
461 | 0 | OBJECT *object; |
462 | 0 | object = HandleToObject(handle); |
463 | 0 | if(object->attributes.ppsHierarchy) |
464 | 0 | { |
465 | 0 | hierarchy = TPM_RH_PLATFORM; |
466 | 0 | } |
467 | 0 | else if(object->attributes.epsHierarchy) |
468 | 0 | { |
469 | 0 | hierarchy = TPM_RH_ENDORSEMENT; |
470 | 0 | } |
471 | 0 | else if(object->attributes.spsHierarchy) |
472 | 0 | { |
473 | 0 | hierarchy = TPM_RH_OWNER; |
474 | 0 | } |
475 | 0 | } |
476 | 0 | break; |
477 | 0 | case TPM_HT_PCR: |
478 | 0 | hierarchy = TPM_RH_OWNER; |
479 | 0 | break; |
480 | 0 | default: |
481 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
482 | 0 | break; |
483 | 0 | } |
484 | | // this is unreachable but it provides a return value for the default |
485 | | // case which makes the complier happy |
486 | 0 | return hierarchy; |
487 | 0 | } |