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