Line | Count | Source (jump to first uncovered line) |
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 |
28 | | EntityGetLoadStatus( |
29 | | TPM_HANDLE *handle, // IN/OUT: handle of the entity |
30 | | TPM_CC commandCode // IN: the commmandCode |
31 | | ) |
32 | 71 | { |
33 | 71 | TPM_RC result = TPM_RC_SUCCESS; |
34 | 71 | switch(HandleGetType(*handle)) |
35 | 71 | { |
36 | | // For handles associated with hierarchies, the entity is present |
37 | | // only if the associated enable is SET. |
38 | 50 | case TPM_HT_PERMANENT: |
39 | 50 | switch(*handle) |
40 | 50 | { |
41 | 7 | case TPM_RH_OWNER: |
42 | 7 | if(!gc.shEnable) |
43 | 0 | result = TPM_RC_HIERARCHY; |
44 | 7 | break; |
45 | | #ifdef VENDOR_PERMANENT |
46 | | case VENDOR_PERMANENT: |
47 | | #endif |
48 | 12 | case TPM_RH_ENDORSEMENT: |
49 | 12 | if(!gc.ehEnable) |
50 | 0 | result = TPM_RC_HIERARCHY; |
51 | 12 | break; |
52 | 13 | case TPM_RH_PLATFORM: |
53 | 13 | if(!g_phEnable) |
54 | 0 | result = TPM_RC_HIERARCHY; |
55 | 13 | break; |
56 | | // null handle, PW session handle and lockout |
57 | | // handle are always available |
58 | 18 | case TPM_RH_NULL: |
59 | 18 | case TPM_RS_PW: |
60 | 18 | case TPM_RH_LOCKOUT: |
61 | 18 | break; |
62 | 0 | default: |
63 | | // handling of the manufacture_specific handles |
64 | 0 | if( ((TPM_RH)*handle >= TPM_RH_FIRST) |
65 | 0 | && ((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 | 0 | result = TPM_RC_VALUE; |
69 | 0 | else |
70 | 0 | pAssert(FALSE); |
71 | 0 | break; |
72 | 50 | } |
73 | 50 | break; |
74 | 50 | case TPM_HT_TRANSIENT: |
75 | | // For a transient object, check if the handle is associated |
76 | | // with a loaded object. |
77 | 0 | if(!ObjectIsPresent(*handle)) |
78 | 0 | result = TPM_RC_REFERENCE_H0; |
79 | 0 | break; |
80 | 0 | 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 | 0 | result = ObjectLoadEvict(handle, commandCode); |
87 | 0 | break; |
88 | 0 | 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 | 0 | if(SessionIsLoaded(*handle)) |
93 | 0 | { |
94 | 0 | SESSION *session; |
95 | 0 | session = SessionGet(*handle); |
96 | | // Check if the session is a HMAC session |
97 | 0 | if(session->attributes.isPolicy == SET) |
98 | 0 | result = TPM_RC_HANDLE; |
99 | 0 | } |
100 | 0 | else |
101 | 0 | result = TPM_RC_REFERENCE_H0; |
102 | 0 | break; |
103 | 0 | 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 | 0 | if(SessionIsLoaded(*handle)) |
108 | 0 | { |
109 | 0 | SESSION *session; |
110 | 0 | session = SessionGet(*handle); |
111 | | // Check if the session is a policy session |
112 | 0 | if(session->attributes.isPolicy == CLEAR) |
113 | 0 | result = TPM_RC_HANDLE; |
114 | 0 | } |
115 | 0 | else |
116 | 0 | result = TPM_RC_REFERENCE_H0; |
117 | 0 | break; |
118 | 1 | case TPM_HT_NV_INDEX: |
119 | | // For an NV Index, use the platform-specific routine |
120 | | // to search the IN Index space. |
121 | 1 | result = NvIndexIsAccessible(*handle, commandCode); |
122 | 1 | break; |
123 | 20 | case TPM_HT_PCR: |
124 | | // Any PCR handle that is unmarshaled successfully referenced |
125 | | // a PCR that is defined. |
126 | 20 | break; |
127 | 0 | default: |
128 | | // Any other handle type is a defect in the unmarshaling code. |
129 | 0 | pAssert(FALSE); |
130 | 0 | break; |
131 | 71 | } |
132 | 71 | return result; |
133 | 71 | } |
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 |
147 | | EntityGetAuthValue( |
148 | | TPMI_DH_ENTITY handle, // IN: handle of entity |
149 | | AUTH_VALUE *auth // OUT: authValue of the entity |
150 | | ) |
151 | 48 | { |
152 | 48 | TPM2B_AUTH authValue = {}; |
153 | 48 | switch(HandleGetType(handle)) |
154 | 48 | { |
155 | 32 | case TPM_HT_PERMANENT: |
156 | 32 | switch(handle) |
157 | 32 | { |
158 | 6 | case TPM_RH_OWNER: |
159 | | // ownerAuth for TPM_RH_OWNER |
160 | 6 | authValue = gp.ownerAuth; |
161 | 6 | break; |
162 | 6 | case TPM_RH_ENDORSEMENT: |
163 | | // endorsementAuth for TPM_RH_ENDORSEMENT |
164 | 6 | authValue = gp.endorsementAuth; |
165 | 6 | break; |
166 | 8 | case TPM_RH_PLATFORM: |
167 | | // platformAuth for TPM_RH_PLATFORM |
168 | 8 | authValue = gc.platformAuth; |
169 | 8 | break; |
170 | 0 | case TPM_RH_LOCKOUT: |
171 | | // lockoutAuth for TPM_RH_LOCKOUT |
172 | 0 | authValue = gp.lockoutAuth; |
173 | 0 | break; |
174 | 12 | case TPM_RH_NULL: |
175 | | // nullAuth for TPM_RH_NULL. Return 0 directly here |
176 | 12 | return 0; |
177 | 0 | break; |
178 | | #ifdef VENDOR_PERMANENT |
179 | | case VENDOR_PERMANENT: |
180 | | // vendor auth value |
181 | | authValue = g_platformUniqueDetails; |
182 | | #endif |
183 | 0 | default: |
184 | | // If any other permanent handle is present it is |
185 | | // a code defect. |
186 | 0 | pAssert(FALSE); |
187 | 0 | break; |
188 | 32 | } |
189 | 20 | break; |
190 | 20 | 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 | 0 | { |
195 | 0 | OBJECT *object; |
196 | 0 | object = ObjectGet(handle); |
197 | | // special handling if this is a sequence object |
198 | 0 | if(ObjectIsSequence(object)) |
199 | 0 | { |
200 | 0 | authValue = ((HASH_OBJECT *)object)->auth; |
201 | 0 | } |
202 | 0 | else |
203 | 0 | { |
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 | 0 | pAssert(object->attributes.publicOnly == CLEAR); |
208 | 0 | authValue = object->sensitive.authValue; |
209 | 0 | } |
210 | 0 | } |
211 | 0 | break; |
212 | 0 | case TPM_HT_NV_INDEX: |
213 | | // authValue for an NV index |
214 | 0 | { |
215 | 0 | NV_INDEX nvIndex; |
216 | 0 | NvGetIndexInfo(handle, &nvIndex); |
217 | 0 | authValue = nvIndex.authValue; |
218 | 0 | } |
219 | 0 | break; |
220 | 16 | case TPM_HT_PCR: |
221 | | // authValue for PCR |
222 | 16 | PCRGetAuthValue(handle, &authValue); |
223 | 16 | break; |
224 | 0 | default: |
225 | | // If any other handle type is present here, then there is a defect |
226 | | // in the unmarshaling code. |
227 | 0 | pAssert(FALSE); |
228 | 0 | break; |
229 | 48 | } |
230 | | // Copy the authValue |
231 | 36 | pAssert(authValue.t.size <= sizeof(authValue.t.buffer)); |
232 | 36 | MemoryCopy(auth, authValue.t.buffer, authValue.t.size, sizeof(TPMU_HA)); |
233 | 36 | return authValue.t.size; |
234 | 48 | } |
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 |
247 | | EntityGetAuthPolicy( |
248 | | TPMI_DH_ENTITY handle, // IN: handle of entity |
249 | | TPM2B_DIGEST *authPolicy // OUT: authPolicy of the entity |
250 | | ) |
251 | 0 | { |
252 | 0 | TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; |
253 | 0 | switch(HandleGetType(handle)) |
254 | 0 | { |
255 | 0 | case TPM_HT_PERMANENT: |
256 | 0 | switch(handle) |
257 | 0 | { |
258 | 0 | case TPM_RH_OWNER: |
259 | | // |
260 | | // ownerPolicy for TPM_RH_OWNER |
261 | 0 | *authPolicy = gp.ownerPolicy; |
262 | 0 | hashAlg = gp.ownerAlg; |
263 | 0 | break; |
264 | 0 | case TPM_RH_ENDORSEMENT: |
265 | | // endorsementPolicy for TPM_RH_ENDORSEMENT |
266 | 0 | *authPolicy = gp.endorsementPolicy; |
267 | 0 | hashAlg = gp.endorsementAlg; |
268 | 0 | break; |
269 | 0 | case TPM_RH_PLATFORM: |
270 | | // platformPolicy for TPM_RH_PLATFORM |
271 | 0 | *authPolicy = gc.platformPolicy; |
272 | 0 | hashAlg = gc.platformAlg; |
273 | 0 | break; |
274 | 0 | case TPM_RH_LOCKOUT: |
275 | | // lockoutPolicy for TPM_RH_LOCKOUT |
276 | 0 | *authPolicy = gp.lockoutPolicy; |
277 | 0 | hashAlg = gp.lockoutAlg; |
278 | 0 | break; |
279 | 0 | default: |
280 | | // If any other permanent handle is present it is |
281 | | // a code defect. |
282 | 0 | pAssert(FALSE); |
283 | 0 | break; |
284 | 0 | } |
285 | 0 | break; |
286 | 0 | case TPM_HT_TRANSIENT: |
287 | | // authPolicy for an object |
288 | 0 | { |
289 | 0 | OBJECT *object = ObjectGet(handle); |
290 | 0 | *authPolicy = object->publicArea.authPolicy; |
291 | 0 | hashAlg = object->publicArea.nameAlg; |
292 | 0 | } |
293 | 0 | break; |
294 | 0 | case TPM_HT_NV_INDEX: |
295 | | // authPolicy for a NV index |
296 | 0 | { |
297 | 0 | NV_INDEX nvIndex; |
298 | 0 | NvGetIndexInfo(handle, &nvIndex); |
299 | 0 | *authPolicy = nvIndex.publicArea.authPolicy; |
300 | 0 | hashAlg = nvIndex.publicArea.nameAlg; |
301 | 0 | } |
302 | 0 | break; |
303 | 0 | case TPM_HT_PCR: |
304 | | // authPolicy for a PCR |
305 | 0 | hashAlg = PCRGetAuthPolicy(handle, authPolicy); |
306 | 0 | break; |
307 | 0 | default: |
308 | | // If any other handle type is present it is a code defect. |
309 | 0 | pAssert(FALSE); |
310 | 0 | break; |
311 | 0 | } |
312 | 0 | return hashAlg; |
313 | 0 | } |
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 |
322 | | EntityGetName( |
323 | | TPMI_DH_ENTITY handle, // IN: handle of entity |
324 | | NAME *name // OUT: name of entity |
325 | | ) |
326 | 0 | { |
327 | 0 | UINT16 nameSize; |
328 | 0 | INT32 bufferSize = sizeof(TPM_HANDLE); |
329 | 0 | switch(HandleGetType(handle)) |
330 | 0 | { |
331 | 0 | case TPM_HT_TRANSIENT: |
332 | | // Name for an object |
333 | 0 | nameSize = ObjectGetName(handle, name); |
334 | 0 | break; |
335 | 0 | case TPM_HT_NV_INDEX: |
336 | | // Name for a NV index |
337 | 0 | nameSize = NvGetName(handle, name); |
338 | 0 | break; |
339 | 0 | default: |
340 | | // For all other types, the handle is the Name |
341 | 0 | nameSize = TPM_HANDLE_Marshal(&handle, (BYTE **)&name, &bufferSize); |
342 | 0 | break; |
343 | 0 | } |
344 | 0 | return nameSize; |
345 | 0 | } |
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 |
358 | | EntityGetHierarchy( |
359 | | TPMI_DH_ENTITY handle // IN :handle of entity |
360 | | ) |
361 | 4 | { |
362 | 4 | TPMI_RH_HIERARCHY hierarcy = TPM_RH_NULL; |
363 | 4 | switch(HandleGetType(handle)) |
364 | 4 | { |
365 | 4 | case TPM_HT_PERMANENT: |
366 | | // hierarchy for a permanent handle |
367 | 4 | switch(handle) |
368 | 4 | { |
369 | 0 | case TPM_RH_PLATFORM: |
370 | 3 | case TPM_RH_ENDORSEMENT: |
371 | 4 | case TPM_RH_NULL: |
372 | 4 | hierarcy = handle; |
373 | 4 | break; |
374 | | // all other permanent handles are associated with the owner |
375 | | // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT) |
376 | 0 | default: |
377 | 0 | hierarcy = TPM_RH_OWNER; |
378 | 0 | break; |
379 | 4 | } |
380 | 4 | break; |
381 | 4 | case TPM_HT_NV_INDEX: |
382 | | // hierarchy for NV index |
383 | 0 | { |
384 | 0 | NV_INDEX nvIndex; |
385 | 0 | 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 | 0 | if(nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == SET) |
390 | 0 | hierarcy = TPM_RH_PLATFORM; |
391 | 0 | else |
392 | 0 | hierarcy = TPM_RH_OWNER; |
393 | 0 | } |
394 | 0 | break; |
395 | 0 | case TPM_HT_TRANSIENT: |
396 | | // hierarchy for an object |
397 | 0 | { |
398 | 0 | OBJECT *object; |
399 | 0 | object = ObjectGet(handle); |
400 | 0 | if(object->attributes.ppsHierarchy) |
401 | 0 | { |
402 | 0 | hierarcy = TPM_RH_PLATFORM; |
403 | 0 | } |
404 | 0 | else if(object->attributes.epsHierarchy) |
405 | 0 | { |
406 | 0 | hierarcy = TPM_RH_ENDORSEMENT; |
407 | 0 | } |
408 | 0 | else if(object->attributes.spsHierarchy) |
409 | 0 | { |
410 | 0 | hierarcy = TPM_RH_OWNER; |
411 | 0 | } |
412 | 0 | } |
413 | 0 | break; |
414 | 0 | case TPM_HT_PCR: |
415 | 0 | hierarcy = TPM_RH_OWNER; |
416 | 0 | break; |
417 | 0 | default: |
418 | 0 | pAssert(0); |
419 | 0 | break; |
420 | 4 | } |
421 | | // this is unreachable but it provides a return value for the default |
422 | | // case which makes the complier happy |
423 | 4 | return hierarcy; |
424 | 4 | } |