1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*******************************************************************************
3 * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
4 * All rights reserved.
5 ******************************************************************************/
6
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10
11 #include "tss2_esys.h"
12 #include "esys_mu.h"
13
14 #include "esys_iutil.h"
15 #define LOGMODULE esys
16 #include "util/log.h"
17 #include "util/aux_util.h"
18
19 /** Serialization of an ESYS_TR into a byte buffer.
20 *
21 * Serialize the metadata of an ESYS_TR object into a byte buffer such that it
22 * can be stored on disk for later use by a different program or context.
23 * The serialized object can be deserialized suing Esys_TR_Deserialize.
24 * @param esys_context [in,out] The ESYS_CONTEXT.
25 * @param esys_handle [in] The ESYS_TR object to serialize.
26 * @param buffer [out] The buffer containing the serialized metadata.
27 * (caller-callocated) Shall be freed using free().
28 * @param buffer_size [out] The size of the buffer parameter.
29 * @retval TSS2_RC_SUCCESS on Success.
30 * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the
31 * ESYS_CONTEXT.
32 * @retval TSS2_ESYS_RC_MEMORY if the buffer for marshaling the object can't
33 * be allocated.
34 * @retval TSS2_ESYS_RC_BAD_VALUE For invalid ESYS data to be marshaled.
35 * @retval TSS2_RCs produced by lower layers of the software stack.
36 */
37 TSS2_RC
Esys_TR_Serialize(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,uint8_t ** buffer,size_t * buffer_size)38 Esys_TR_Serialize(ESYS_CONTEXT * esys_context,
39 ESYS_TR esys_handle, uint8_t ** buffer, size_t * buffer_size)
40 {
41 TSS2_RC r = TSS2_RC_SUCCESS;
42 RSRC_NODE_T *esys_object;
43 size_t offset = 0;
44 *buffer_size = 0;
45
46 r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
47 return_if_error(r, "Get resource object");
48
49 r = iesys_MU_IESYS_RESOURCE_Marshal(&esys_object->rsrc, NULL, SIZE_MAX,
50 buffer_size);
51 return_if_error(r, "Marshal resource object");
52
53 *buffer = malloc(*buffer_size);
54 return_if_null(*buffer, "Buffer could not be allocated",
55 TSS2_ESYS_RC_MEMORY);
56
57 r = iesys_MU_IESYS_RESOURCE_Marshal(&esys_object->rsrc, *buffer,
58 *buffer_size, &offset);
59 return_if_error(r, "Marshal resource object");
60
61 return TSS2_RC_SUCCESS;
62 };
63
64 /** Deserialization of an ESYS_TR from a byte buffer.
65 *
66 * Deserialize the metadata of an ESYS_TR object from a byte buffer that was
67 * stored on disk for later use by a different program or context.
68 * An object can be serialized suing Esys_TR_Serialize.
69 * @param esys_context [in,out] The ESYS_CONTEXT.
70 * @param esys_handle [in] The ESYS_TR object to serialize.
71 * @param buffer [out] The buffer containing the serialized metadata.
72 * (caller-callocated) Shall be freed using free().
73 * @param buffer_size [out] The size of the buffer parameter.
74 * @retval TSS2_RC_SUCCESS on Success.
75 * @retval TSS2_ESYS_RC_MEMORY if the object can not be allocated.
76 * @retval TSS2_ESYS_RC_INSUFFICIENT_BUFFER if the buffer for unmarshaling.
77 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
78 * @retval TSS2_RCs produced by lower layers of the software stack.
79 */
80 TSS2_RC
Esys_TR_Deserialize(ESYS_CONTEXT * esys_context,uint8_t const * buffer,size_t buffer_size,ESYS_TR * esys_handle)81 Esys_TR_Deserialize(ESYS_CONTEXT * esys_context,
82 uint8_t const *buffer,
83 size_t buffer_size, ESYS_TR * esys_handle)
84 {
85 TSS2_RC r;
86
87 RSRC_NODE_T *esys_object;
88 size_t offset = 0;
89
90 _ESYS_ASSERT_NON_NULL(esys_context);
91 *esys_handle = esys_context->esys_handle_cnt++;
92 r = esys_CreateResourceObject(esys_context, *esys_handle, &esys_object);
93 return_if_error(r, "Get resource object");
94
95 r = iesys_MU_IESYS_RESOURCE_Unmarshal(buffer, buffer_size, &offset,
96 &esys_object->rsrc);
97 return_if_error(r, "Unmarshal resource object");
98
99 return TSS2_RC_SUCCESS;
100 }
101
102 /** Start synchronous creation of an ESYS_TR object from TPM metadata.
103 *
104 * This function starts the asynchronous retrieval of metadata from the TPM in
105 * order to create a new ESYS_TR object.
106 * @param esys_context [in,out] The ESYS_CONTEXT
107 * @param tpm_handle [in] The handle of the TPM object to represent as ESYS_TR.
108 * @param shandle1 [in,out] A session for securing the TPM command (optional).
109 * @param shandle2 [in,out] A session for securing the TPM command (optional).
110 * @param shandle3 [in,out] A session for securing the TPM command (optional).
111 * @retval TSS2_RC_SUCCESS on success
112 * @retval ESYS_RC_SUCCESS if the function call was a success.
113 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
114 * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected.
115 * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for
116 * internal operations or return parameters.
117 * @retval TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS: if more than one session has
118 * the 'decrypt' attribute bit set.
119 * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS: if more than one session has
120 * the 'encrypt' attribute bit set.
121 * @retval TSS2_ESYS_RC_NO_DECRYPT_PARAM: if one of the sessions has the
122 * 'decrypt' attribute set and the command does not support encryption
123 * of the first command parameter.
124 * @retval TSS2_RCs produced by lower layers of the software stack may be
125 * returned to the caller unaltered unless handled internally.
126 */
127 TSS2_RC
Esys_TR_FromTPMPublic_Async(ESYS_CONTEXT * esys_context,TPM2_HANDLE tpm_handle,ESYS_TR shandle1,ESYS_TR shandle2,ESYS_TR shandle3)128 Esys_TR_FromTPMPublic_Async(ESYS_CONTEXT * esys_context,
129 TPM2_HANDLE tpm_handle,
130 ESYS_TR shandle1,
131 ESYS_TR shandle2, ESYS_TR shandle3)
132 {
133 TSS2_RC r;
134 _ESYS_ASSERT_NON_NULL(esys_context);
135 ESYS_TR esys_handle = esys_context->esys_handle_cnt++;
136 RSRC_NODE_T *esysHandleNode = NULL;
137 r = esys_CreateResourceObject(esys_context, esys_handle, &esysHandleNode);
138 goto_if_error(r, "Error create resource", error_cleanup);
139
140 esysHandleNode->rsrc.handle = tpm_handle;
141 esys_context->esys_handle = esys_handle;
142
143 if (tpm_handle >= TPM2_NV_INDEX_FIRST && tpm_handle <= TPM2_NV_INDEX_LAST) {
144 r = Esys_NV_ReadPublic_Async(esys_context, esys_handle, shandle1,
145 shandle2, shandle3);
146 goto_if_error(r, "Error NV_ReadPublic", error_cleanup);
147
148 } else if(tpm_handle >> TPM2_HR_SHIFT == TPM2_HT_LOADED_SESSION
149 || tpm_handle >> TPM2_HR_SHIFT == TPM2_HT_SAVED_SESSION) {
150 // no readpublic call for loaded or saved sessions.
151 r = TSS2_RC_SUCCESS;
152 } else {
153 r = Esys_ReadPublic_Async(esys_context, esys_handle, shandle1, shandle2,
154 shandle3);
155 goto_if_error(r, "Error ReadPublic", error_cleanup);
156 }
157 return r;
158 error_cleanup:
159 Esys_TR_Close(esys_context, &esys_handle);
160 return r;
161 }
162
163 /** Finish asynchronous creation of an ESYS_TR object from TPM metadata.
164 *
165 * This function finishes the asynchronous retrieval of metadata from the TPM in
166 * order to create a new ESYS_TR object.
167 * @param esys_context [in,out] The ESYS_CONTEXT
168 * @param object [out] The newly created ESYS_TR metadata object.
169 * @retval TSS2_RC_SUCCESS on success
170 * @retval ESYS_RC_SUCCESS if the function call was a success.
171 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input
172 * pointers or required output handle references are NULL.
173 * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected.
174 * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for
175 * internal operations or return parameters.
176 * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous
177 * operation already pending.
178 * @retval TSS2_ESYS_RC_TRY_AGAIN: if the timeout counter expires before the
179 * TPM response is received.
180 * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not
181 * at least contain the tag, response length, and response code.
182 * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted.
183 * @retval TSS2_RCs produced by lower layers of the software stack may be
184 * returned to the caller unaltered unless handled internally.
185 */
186 TSS2_RC
Esys_TR_FromTPMPublic_Finish(ESYS_CONTEXT * esys_context,ESYS_TR * object)187 Esys_TR_FromTPMPublic_Finish(ESYS_CONTEXT * esys_context, ESYS_TR * object)
188 {
189 TSS2_RC r = TSS2_RC_SUCCESS;
190 ESYS_TR objectHandle = ESYS_TR_NONE;
191 RSRC_NODE_T *objectHandleNode;
192
193 _ESYS_ASSERT_NON_NULL(esys_context);
194
195 objectHandle = esys_context->esys_handle;
196
197 r = esys_GetResourceObject(esys_context, objectHandle, &objectHandleNode);
198 goto_if_error(r, "get resource", error_cleanup);
199
200 if (objectHandleNode->rsrc.handle >= TPM2_NV_INDEX_FIRST
201 && objectHandleNode->rsrc.handle <= TPM2_NV_INDEX_LAST) {
202 TPM2B_NV_PUBLIC *nvPublic;
203 TPM2B_NAME *nvName;
204 r = Esys_NV_ReadPublic_Finish(esys_context, &nvPublic, &nvName);
205 if (base_rc(r) == TSS2_BASE_RC_TRY_AGAIN) {
206 LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32
207 " => resubmitting command", r);
208 return r;
209 }
210 goto_if_error(r, "Error NV_ReadPublic", error_cleanup);
211
212 objectHandleNode->rsrc.rsrcType = IESYSC_NV_RSRC;
213 objectHandleNode->rsrc.name = *nvName;
214 objectHandleNode->rsrc.misc.rsrc_nv_pub = *nvPublic;
215 SAFE_FREE(nvPublic);
216 SAFE_FREE(nvName);
217 } else if(objectHandleNode->rsrc.handle >> TPM2_HR_SHIFT == TPM2_HT_LOADED_SESSION
218 || objectHandleNode->rsrc.handle >> TPM2_HR_SHIFT == TPM2_HT_SAVED_SESSION) {
219 objectHandleNode->rsrc.rsrcType = IESYSC_DEGRADED_SESSION_RSRC;
220 } else {
221 TPM2B_PUBLIC *public;
222 TPM2B_NAME *name = NULL;
223 TPM2B_NAME *qualifiedName = NULL;
224 r = Esys_ReadPublic_Finish(esys_context, &public, &name,
225 &qualifiedName);
226 if (base_rc(r) == TSS2_BASE_RC_TRY_AGAIN) {
227 LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32
228 " => resubmitting command", r);
229 return r;
230 }
231 goto_if_error(r, "Error ReadPublic", error_cleanup);
232
233 objectHandleNode->rsrc.rsrcType = IESYSC_KEY_RSRC;
234 objectHandleNode->rsrc.name = *name;
235 objectHandleNode->rsrc.misc.rsrc_key_pub = *public;
236 SAFE_FREE(public);
237 SAFE_FREE(name);
238 SAFE_FREE(qualifiedName);
239 }
240 *object = objectHandle;
241 return TSS2_RC_SUCCESS;
242
243 error_cleanup:
244 Esys_TR_Close(esys_context, &objectHandle);
245 return r;
246 }
247
248 /** Creation of an ESYS_TR object from TPM metadata.
249 *
250 * This function can be used to create ESYS_TR object for Tpm Resources that are
251 * not created or loaded (e.g. using ESys_CreatePrimary or ESys_Load) but
252 * pre-exist inside the TPM. Examples are NV-Indices or persistent object.
253 *
254 * Note: For PCRs and hierarchies, please use the global ESYS_TR identifiers.
255 * Note: If a session is provided the TPM is queried for the metadata twice.
256 * First without a session to retrieve some metadata then with the session where
257 * this metadata is used in the session HMAC calculation and thereby verified.
258 *
259 * Since man in the middle attacks should be prevented as much as possible it is
260 * recommended to pass a session.
261 * @param esys_context [in,out] The ESYS_CONTEXT
262 * @param tpm_handle [in] The handle of the TPM object to represent as ESYS_TR.
263 * @param shandle1 [in,out] A session for securing the TPM command (optional).
264 * @param shandle2 [in,out] A session for securing the TPM command (optional).
265 * @param shandle3 [in,out] A session for securing the TPM command (optional).
266 * @param object [out] The newly created ESYS_TR metadata object.
267 * @retval TSS2_RC_SUCCESS on success
268 * @retval ESYS_RC_SUCCESS if the function call was a success.
269 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input
270 * pointers or required output handle references are NULL.
271 * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected.
272 * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for
273 * internal operations or return parameters.
274 * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous
275 * operation already pending.
276 * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not
277 * at least contain the tag, response length, and response code.
278 * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted.
279 * @retval TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS: if more than one session has
280 * the 'decrypt' attribute bit set.
281 * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS: if more than one session has
282 * the 'encrypt' attribute bit set.
283 * @retval TSS2_ESYS_RC_NO_DECRYPT_PARAM: if one of the sessions has the
284 * 'decrypt' attribute set and the command does not support encryption
285 * of the first command parameter.
286 * @retval TSS2_RCs produced by lower layers of the software stack may be
287 * returned to the caller unaltered unless handled internally.
288 */
289 TSS2_RC
Esys_TR_FromTPMPublic(ESYS_CONTEXT * esys_context,TPM2_HANDLE tpm_handle,ESYS_TR shandle1,ESYS_TR shandle2,ESYS_TR shandle3,ESYS_TR * object)290 Esys_TR_FromTPMPublic(ESYS_CONTEXT * esys_context,
291 TPM2_HANDLE tpm_handle,
292 ESYS_TR shandle1,
293 ESYS_TR shandle2, ESYS_TR shandle3, ESYS_TR * object)
294 {
295 TSS2_RC r;
296
297 _ESYS_ASSERT_NON_NULL(esys_context);
298 r = Esys_TR_FromTPMPublic_Async(esys_context, tpm_handle,
299 shandle1, shandle2, shandle3);
300 return_if_error(r, "Error TR FromTPMPublic");
301
302 /* Set the timeout to indefinite for now, since we want _Finish to block */
303 int32_t timeouttmp = esys_context->timeout;
304 esys_context->timeout = -1;
305 /*
306 * Now we call the finish function, until return code is not equal to
307 * from TSS2_BASE_RC_TRY_AGAIN.
308 * Note that the finish function may return TSS2_RC_TRY_AGAIN, even if we
309 * have set the timeout to -1. This occurs for example if the TPM requests
310 * a retransmission of the command via TPM2_RC_YIELDED.
311 */
312 do {
313 r = Esys_TR_FromTPMPublic_Finish(esys_context, object);
314 if (base_rc(r) == TSS2_BASE_RC_TRY_AGAIN)
315 LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32
316 " => resubmitting command", r);
317 } while (base_rc(r) == TSS2_BASE_RC_TRY_AGAIN);
318
319 /* Restore the timeout value to the original value */
320 esys_context->timeout = timeouttmp;
321 return_if_error(r, "Error TR FromTPMPublic");
322
323 return r;
324 }
325
326 /** Close an ESYS_TR without removing it from the TPM.
327 *
328 * This function deletes an ESYS_TR object from an ESYS_CONTEXT without deleting
329 * it from the TPM. This is useful for NV-Indices or persistent keys, after
330 * Esys_TR_Serialize has been called. Transient objects should be deleted using
331 * Esys_FlushContext.
332 * @param esys_context [in,out] The ESYS_CONTEXT
333 * @param object [out] ESYS_TR metadata object to be deleted from ESYS_CONTEXT.
334 * @retval TSS2_RC_SUCCESS on Success.
335 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
336 * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the
337 * ESYS_CONTEXT.
338 */
339 TSS2_RC
Esys_TR_Close(ESYS_CONTEXT * esys_context,ESYS_TR * object)340 Esys_TR_Close(ESYS_CONTEXT * esys_context, ESYS_TR * object)
341 {
342 RSRC_NODE_T *node;
343 RSRC_NODE_T **update_ptr;
344
345 _ESYS_ASSERT_NON_NULL(esys_context);
346 for (node = esys_context->rsrc_list,
347 update_ptr = &esys_context->rsrc_list;
348 node != NULL;
349 update_ptr = &node->next, node = node->next) {
350 if (node->esys_handle == *object) {
351 *update_ptr = node->next;
352 SAFE_FREE(node);
353 *object = ESYS_TR_NONE;
354 return TSS2_RC_SUCCESS;
355 }
356 }
357 LOG_ERROR("Error: Esys handle does not exist (%x).", TSS2_ESYS_RC_BAD_TR);
358 return TSS2_ESYS_RC_BAD_TR;
359 }
360
361 /** Set the authorization value of an ESYS_TR.
362 *
363 * Authorization values are associated with ESYS_TR Tpm Resource object. They
364 * are then picked up whenever an authorization is needed.
365 *
366 * Note: The authorization value is not stored in the metadata during
367 * Esys_TR_Serialize. Therefor Esys_TR_SetAuth needs to be called again after
368 * every Esys_TR_Deserialize.
369 * @param esys_context [in,out] The ESYS_CONTEXT.
370 * @param esys_handle [in,out] The ESYS_TR for which to set the auth value.
371 * @param authValue [in] The auth value to set for the ESYS_TR or NULL to zero
372 * the auth.
373 * @retval TSS2_RC_SUCCESS on Success.
374 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
375 * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the
376 * ESYS_CONTEXT.
377 */
378 TSS2_RC
Esys_TR_SetAuth(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPM2B_AUTH const * authValue)379 Esys_TR_SetAuth(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
380 TPM2B_AUTH const *authValue)
381 {
382 RSRC_NODE_T *esys_object;
383 TSS2_RC r;
384 TPMI_ALG_HASH name_alg = TPM2_ALG_NULL;
385
386 _ESYS_ASSERT_NON_NULL(esys_context);
387 r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
388 if (r != TPM2_RC_SUCCESS)
389 return r;
390
391 if (authValue == NULL) {
392 esys_object->auth.size = 0;
393 } else {
394 if (authValue->size > sizeof(TPMU_HA)) {
395 return_error(TSS2_ESYS_RC_BAD_SIZE, "Bad size for auth value.");
396 }
397 /* Determine name alg of resource */
398 if (esys_object->rsrc.rsrcType == IESYSC_KEY_RSRC) {
399 name_alg = esys_object->rsrc.misc.rsrc_key_pub.publicArea.nameAlg;
400 } else if (esys_object->rsrc.rsrcType == IESYSC_NV_RSRC) {
401 name_alg = esys_object->rsrc.misc.rsrc_nv_pub.nvPublic.nameAlg;
402 }
403 esys_object->auth = *authValue;
404 /* Adapt auth value to hash for large auth values. */
405 if (name_alg != TPM2_ALG_NULL) {
406 r = iesys_hash_long_auth_values(&esys_object->auth, name_alg);
407 return_if_error(r, "Hashing overlength authValue failed.");
408 }
409 }
410 return TSS2_RC_SUCCESS;
411 }
412
413 /** Retrieve the TPM public name of an Esys_TR object.
414 *
415 * Some operations (i.e. Esys_PolicyNameHash) require the name of a TPM object
416 * to be passed. Esys_TR_GetName provides this name to the caller.
417 * @param esys_context [in,out] The ESYS_CONTEXT.
418 * @param esys_handle [in,out] The ESYS_TR for which to retrieve the name.
419 * @param name [out] The name of the object (caller-allocated; use free()).
420 * @retval TSS2_RC_SUCCESS on Success.
421 * @retval TSS2_ESYS_RC_MEMORY if needed memory can't be allocated.
422 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
423 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
424 * @retval TSS2_SYS_RC_* for SAPI errors.
425 */
426 TSS2_RC
Esys_TR_GetName(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPM2B_NAME ** name)427 Esys_TR_GetName(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
428 TPM2B_NAME ** name)
429 {
430 RSRC_NODE_T *esys_object;
431 TSS2_RC r;
432 _ESYS_ASSERT_NON_NULL(esys_context);
433
434 r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
435 return_if_error(r, "Object not found");
436
437 *name = malloc(sizeof(TPM2B_NAME));
438 if (*name == NULL) {
439 LOG_ERROR("Error: out of memory");
440 return TSS2_ESYS_RC_MEMORY;
441 }
442 if (esys_object->rsrc.rsrcType == IESYSC_KEY_RSRC) {
443 r = iesys_get_name(&esys_object->rsrc.misc.rsrc_key_pub, *name);
444 goto_if_error(r, "Error get name", error_cleanup);
445
446 } else {
447 if (esys_object->rsrc.rsrcType == IESYSC_NV_RSRC) {
448 r = iesys_nv_get_name(&esys_object->rsrc.misc.rsrc_nv_pub, *name);
449 goto_if_error(r, "Error get name", error_cleanup);
450
451 } else {
452 size_t offset = 0;
453 r = Tss2_MU_TPM2_HANDLE_Marshal(esys_object->rsrc.handle,
454 &(*name)->name[0], sizeof(TPM2_HANDLE),
455 &offset);
456 goto_if_error(r, "Error get name", error_cleanup);
457 (*name)->size = offset;
458 }
459 }
460 return r;
461 error_cleanup:
462 SAFE_FREE(*name);
463 return r;
464 }
465
466
467 /** Retrieve the Session Attributes of the ESYS_TR session.
468 *
469 * Sessions possess attributes, such as whether they shall continue of be
470 * flushed after the next command, or whether they are used to encrypt
471 * parameters.
472 * Note: this function only applies to ESYS_TR objects that represent sessions.
473 * @param esys_context [in,out] The ESYS_CONTEXT.
474 * @param esys_handle [in,out] The ESYS_TR of the session.
475 * @param flags [out] The attributes of the session.
476 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
477 * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the
478 * ESYS_CONTEXT or ESYS_TR object is not a session object.
479 */
480 TSS2_RC
Esys_TRSess_GetAttributes(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPMA_SESSION * flags)481 Esys_TRSess_GetAttributes(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
482 TPMA_SESSION * flags)
483 {
484 RSRC_NODE_T *esys_object;
485
486 _ESYS_ASSERT_NON_NULL(esys_context);
487 TSS2_RC r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
488 return_if_error(r, "Object not found");
489
490 if (esys_object->rsrc.rsrcType != IESYSC_SESSION_RSRC)
491 return_error(TSS2_ESYS_RC_BAD_TR, "Object is not a session object");
492 *flags = esys_object->rsrc.misc.rsrc_session.sessionAttributes;
493 return TSS2_RC_SUCCESS;
494 }
495
496 /** Set session attributes
497 *
498 * Set or unset a session's attributes according to the provided flags and mask.
499 * @verbatim new_attributes = old_attributes & ~mask | flags & mask @endverbatim
500 * Note: this function only applies to ESYS_TR objects that represent sessions.
501 * @param esys_context [in,out] The ESYS_CONTEXT.
502 * @param esys_handle [in,out] The ESYS_TR of the session.
503 * @param flags [in] The flags to be set or unset for the session.
504 * @param mask [in] The mask for the flags to be set or unset.
505 * @retval TSS2_RC_SUCCESS on Success.
506 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
507 * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the
508 * ESYS_CONTEXT or ESYS_TR object is not a session object.
509 */
510 TSS2_RC
Esys_TRSess_SetAttributes(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPMA_SESSION flags,TPMA_SESSION mask)511 Esys_TRSess_SetAttributes(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
512 TPMA_SESSION flags, TPMA_SESSION mask)
513 {
514 RSRC_NODE_T *esys_object;
515
516 _ESYS_ASSERT_NON_NULL(esys_context);
517 TSS2_RC r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
518 return_if_error(r, "Object not found");
519
520 return_if_null(esys_object, "Object not found", TSS2_ESYS_RC_BAD_VALUE);
521
522 if (esys_object->rsrc.rsrcType != IESYSC_SESSION_RSRC)
523 return_error(TSS2_ESYS_RC_BAD_TR, "Object is not a session object");
524 esys_object->rsrc.misc.rsrc_session.sessionAttributes =
525 (esys_object->rsrc.misc.rsrc_session.
526 sessionAttributes & ~mask) | (flags & mask);
527 if (esys_object->rsrc.misc.rsrc_session.sessionAttributes & TPMA_SESSION_AUDIT)
528 esys_object->rsrc.misc.rsrc_session.bound_entity.size = 0;
529 return TSS2_RC_SUCCESS;
530 }
531
532 /** Retrieve the TPM nonce of an Esys_TR session object.
533 *
534 * Some operations (i.e. Esys_PolicySigned) require the nonce returned by the
535 * TPM during Esys_StartauthSession. This function provides this nonce to the
536 * caller.
537 * @param esys_context [in,out] The ESYS_CONTEXT.
538 * @param esys_handle [in,out] The ESYS_TRsess for which to retrieve the nonce.
539 * @param nonceTPM [out] The nonce of the object (callee-allocated; use free()).
540 * @retval TSS2_RC_SUCCESS on Success.
541 * @retval TSS2_ESYS_RC_MEMORY if needed memory can't be allocated.
542 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
543 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
544 * @retval TSS2_SYS_RC_* for SAPI errors.
545 */
546 TSS2_RC
Esys_TRSess_GetNonceTPM(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPM2B_NONCE ** nonceTPM)547 Esys_TRSess_GetNonceTPM(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
548 TPM2B_NONCE **nonceTPM)
549 {
550 RSRC_NODE_T *esys_object;
551 TSS2_RC r;
552 _ESYS_ASSERT_NON_NULL(esys_context);
553 _ESYS_ASSERT_NON_NULL(nonceTPM);
554
555 r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
556 return_if_error(r, "Object not found");
557
558 *nonceTPM = calloc(1, sizeof(**nonceTPM));
559 if (*nonceTPM == NULL) {
560 LOG_ERROR("Error: out of memory");
561 return TSS2_ESYS_RC_MEMORY;
562 }
563 if (esys_object->rsrc.rsrcType != IESYSC_SESSION_RSRC) {
564 goto_error(r, TSS2_ESYS_RC_BAD_TR,
565 "NonceTPM for non-session object requested.",
566 error_cleanup);
567
568 }
569 **nonceTPM = esys_object->rsrc.misc.rsrc_session.nonceTPM;
570
571 return r;
572 error_cleanup:
573 SAFE_FREE(*nonceTPM);
574 return r;
575 }
576
577 /** Retrieves the associated TPM2_HANDLE from an ESYS_TR object.
578 *
579 * Retrieves the TPM2_HANDLE for an associated ESYS_TR object for use with the
580 * SAPI API or comparisons against raw TPM2_HANDLES from commands like
581 * TPM2_GetCapability or use of various handle bitwise comparisons. For example
582 * the mask TPM2_HR_NV_INDEX.
583 *
584 * @param esys_context [in,out] The ESYS_CONTEXT.
585 * @param esys_handle [in] The ESYS_TR object to retrieve the TPM2_HANDLE from.
586 * @param tpm_handle [out] The TPM2_HANDLE retrieved from the ESYS_TR object.
587 * @retval TSS2_RC_SUCCESS on Success.
588 * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the
589 * ESYS_CONTEXT or is ESYS_TR_NONE.
590 * @retval TSS2_ESYS_RC_BAD_VALUE if an unknown handle < ESYS_TR_MIN_OBJECT is
591 * passed.
592 * @retval TSS2_ESYS_RC_BAD_REFERENCE For invalid ESYS_CONTEXT.
593 */
594 TSS2_RC
Esys_TR_GetTpmHandle(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPM2_HANDLE * tpm_handle)595 Esys_TR_GetTpmHandle(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
596 TPM2_HANDLE * tpm_handle)
597 {
598 TSS2_RC r = TSS2_RC_SUCCESS;
599 RSRC_NODE_T *esys_object;
600
601 _ESYS_ASSERT_NON_NULL(esys_context);
602 _ESYS_ASSERT_NON_NULL(tpm_handle);
603
604 if (esys_handle == ESYS_TR_NONE) {
605 return TSS2_ESYS_RC_BAD_TR;
606 }
607
608 r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
609 return_if_error(r, "Get resource object");
610
611 *tpm_handle = esys_object->rsrc.handle;
612
613 return TSS2_RC_SUCCESS;
614 };
615
616 /** Retrieve whether auth value is required from a Esys_TR session object.
617 *
618 * This function can be used to determin whether PoliyPassword or
619 * PlolicyAuthValue are used for a session.
620 * @param esys_context [in,out] The ESYS_CONTEXT.
621 * @param esys_handle [in,out] The ESYS_TRsess for which to retrieve the nonce.
622 * @param neeed [out] The boolean indicating whether auth value will be
623 * needed.
624 * @retval TSS2_RC_SUCCESS on Success.
625 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
626 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
627 * @retval TSS2_SYS_RC_* for SAPI errors.
628 */
629 TSS2_RC
Esys_TRSess_GetAuthRequired(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPMI_YES_NO * auth_needed)630 Esys_TRSess_GetAuthRequired(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
631 TPMI_YES_NO *auth_needed)
632 {
633 RSRC_NODE_T *esys_object;
634 TSS2_RC r;
635 _ESYS_ASSERT_NON_NULL(esys_context);
636
637 r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
638 return_if_error(r, "Object not found");
639
640 if (esys_object->rsrc.rsrcType != IESYSC_SESSION_RSRC) {
641 return_if_error(TSS2_ESYS_RC_BAD_TR,
642 "Auth value needed for non-session object requested.");
643 }
644
645 if (esys_object->rsrc.misc.rsrc_session.type_policy_session == POLICY_AUTH ||
646 esys_object->rsrc.misc.rsrc_session.type_policy_session == POLICY_PASSWORD)
647 *auth_needed = TPM2_YES;
648 else
649 *auth_needed = TPM2_NO;
650 return TSS2_RC_SUCCESS;
651
652 }
653