• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ((r & ~TSS2_RC_LAYER_MASK) == 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 ((r & ~TSS2_RC_LAYER_MASK) == 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 ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
315             LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32
316                       " => resubmitting command", r);
317     } while ((r & ~TSS2_RC_LAYER_MASK) == 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     _ESYS_ASSERT_NON_NULL(esys_context);
385     r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
386     if (r != TPM2_RC_SUCCESS)
387         return r;
388 
389     if (authValue == NULL) {
390         esys_object->auth.size = 0;
391     } else {
392         if (authValue->size > sizeof(TPMU_HA)) {
393             return_error(TSS2_ESYS_RC_BAD_SIZE, "Bad size for auth value.");
394         }
395         esys_object->auth = *authValue;
396     }
397     return TSS2_RC_SUCCESS;
398 }
399 
400 /** Retrieve the TPM public name of an Esys_TR object.
401  *
402  * Some operations (i.e. Esys_PolicyNameHash) require the name of a TPM object
403  * to be passed. Esys_TR_GetName provides this name to the caller.
404  * @param esys_context [in,out] The ESYS_CONTEXT.
405  * @param esys_handle [in,out] The ESYS_TR for which to retrieve the name.
406  * @param name [out] The name of the object (caller-allocated; use free()).
407  * @retval TSS2_RC_SUCCESS on Success.
408  * @retval TSS2_ESYS_RC_MEMORY if needed memory can't be allocated.
409  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
410  * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
411  * @retval TSS2_SYS_RC_* for SAPI errors.
412  */
413 TSS2_RC
Esys_TR_GetName(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPM2B_NAME ** name)414 Esys_TR_GetName(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
415                 TPM2B_NAME ** name)
416 {
417     RSRC_NODE_T *esys_object;
418     TSS2_RC r;
419     _ESYS_ASSERT_NON_NULL(esys_context);
420 
421     r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
422     return_if_error(r, "Object not found");
423 
424     *name = malloc(sizeof(TPM2B_NAME));
425     if (*name == NULL) {
426         LOG_ERROR("Error: out of memory");
427         return TSS2_ESYS_RC_MEMORY;
428     }
429     if (esys_object->rsrc.rsrcType == IESYSC_KEY_RSRC) {
430         r = iesys_get_name(&esys_object->rsrc.misc.rsrc_key_pub, *name);
431         goto_if_error(r, "Error get name", error_cleanup);
432 
433     } else {
434         if (esys_object->rsrc.rsrcType == IESYSC_NV_RSRC) {
435             r = iesys_nv_get_name(&esys_object->rsrc.misc.rsrc_nv_pub, *name);
436             goto_if_error(r, "Error get name", error_cleanup);
437 
438         } else {
439             size_t offset = 0;
440             r = Tss2_MU_TPM2_HANDLE_Marshal(esys_object->rsrc.handle,
441                                             &(*name)->name[0], sizeof(TPM2_HANDLE),
442                                             &offset);
443             goto_if_error(r, "Error get name", error_cleanup);
444             (*name)->size = offset;
445         }
446     }
447     return r;
448  error_cleanup:
449     SAFE_FREE(*name);
450     return r;
451 }
452 
453 
454 /** Retrieve the Session Attributes of the ESYS_TR session.
455  *
456  * Sessions possess attributes, such as whether they shall continue of be
457  * flushed after the next command, or whether they are used to encrypt
458  * parameters.
459  * Note: this function only applies to ESYS_TR objects that represent sessions.
460  * @param esys_context [in,out] The ESYS_CONTEXT.
461  * @param esys_handle [in,out] The ESYS_TR of the session.
462  * @param flags [out] The attributes of the session.
463  * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
464  * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the
465  *         ESYS_CONTEXT or ESYS_TR object is not a session object.
466  */
467 TSS2_RC
Esys_TRSess_GetAttributes(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPMA_SESSION * flags)468 Esys_TRSess_GetAttributes(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
469                           TPMA_SESSION * flags)
470 {
471     RSRC_NODE_T *esys_object;
472 
473     _ESYS_ASSERT_NON_NULL(esys_context);
474     TSS2_RC r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
475     return_if_error(r, "Object not found");
476 
477     if (esys_object->rsrc.rsrcType != IESYSC_SESSION_RSRC)
478         return_error(TSS2_ESYS_RC_BAD_TR, "Object is not a session object");
479     *flags = esys_object->rsrc.misc.rsrc_session.sessionAttributes;
480     return TSS2_RC_SUCCESS;
481 }
482 
483 /** Set session attributes
484  *
485  * Set or unset a session's attributes according to the provided flags and mask.
486  * @verbatim new_attributes = old_attributes & ~mask | flags & mask @endverbatim
487  * Note: this function only applies to ESYS_TR objects that represent sessions.
488  * @param esys_context [in,out] The ESYS_CONTEXT.
489  * @param esys_handle [in,out] The ESYS_TR of the session.
490  * @param flags [in] The flags to be set or unset for the session.
491  * @param mask [in] The mask for the flags to be set or unset.
492  * @retval TSS2_RC_SUCCESS on Success.
493  * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
494  * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the
495  *         ESYS_CONTEXT or ESYS_TR object is not a session object.
496  */
497 TSS2_RC
Esys_TRSess_SetAttributes(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPMA_SESSION flags,TPMA_SESSION mask)498 Esys_TRSess_SetAttributes(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
499                           TPMA_SESSION flags, TPMA_SESSION mask)
500 {
501     RSRC_NODE_T *esys_object;
502 
503     _ESYS_ASSERT_NON_NULL(esys_context);
504     TSS2_RC r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
505     return_if_error(r, "Object not found");
506 
507     return_if_null(esys_object, "Object not found", TSS2_ESYS_RC_BAD_VALUE);
508 
509     if (esys_object->rsrc.rsrcType != IESYSC_SESSION_RSRC)
510         return_error(TSS2_ESYS_RC_BAD_TR, "Object is not a session object");
511     esys_object->rsrc.misc.rsrc_session.sessionAttributes =
512         (esys_object->rsrc.misc.rsrc_session.
513          sessionAttributes & ~mask) | (flags & mask);
514     return TSS2_RC_SUCCESS;
515 }
516 
517 /** Retrieve the TPM nonce of an Esys_TR session object.
518  *
519  * Some operations (i.e. Esys_PolicySigned) require the nonce returned by the
520  * TPM during Esys_StartauthSession. This function provides this nonce to the
521  * caller.
522  * @param esys_context [in,out] The ESYS_CONTEXT.
523  * @param esys_handle [in,out] The ESYS_TRsess for which to retrieve the nonce.
524  * @param nonceTPM [out] The nonce of the object (callee-allocated; use free()).
525  * @retval TSS2_RC_SUCCESS on Success.
526  * @retval TSS2_ESYS_RC_MEMORY if needed memory can't be allocated.
527  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
528  * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
529  * @retval TSS2_SYS_RC_* for SAPI errors.
530  */
531 TSS2_RC
Esys_TRSess_GetNonceTPM(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPM2B_NONCE ** nonceTPM)532 Esys_TRSess_GetNonceTPM(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
533                 TPM2B_NONCE **nonceTPM)
534 {
535     RSRC_NODE_T *esys_object;
536     TSS2_RC r;
537     _ESYS_ASSERT_NON_NULL(esys_context);
538     _ESYS_ASSERT_NON_NULL(nonceTPM);
539 
540     r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
541     return_if_error(r, "Object not found");
542 
543     *nonceTPM = calloc(1, sizeof(**nonceTPM));
544     if (*nonceTPM == NULL) {
545         LOG_ERROR("Error: out of memory");
546         return TSS2_ESYS_RC_MEMORY;
547     }
548     if (esys_object->rsrc.rsrcType != IESYSC_SESSION_RSRC) {
549         goto_error(r, TSS2_ESYS_RC_BAD_TR,
550                    "NonceTPM for non-session object requested.",
551                    error_cleanup);
552 
553     }
554     **nonceTPM = esys_object->rsrc.misc.rsrc_session.nonceTPM;
555 
556     return r;
557  error_cleanup:
558     SAFE_FREE(*nonceTPM);
559     return r;
560 }
561 
562 /** Retrieves the associated TPM2_HANDLE from an ESYS_TR object.
563  *
564  * Retrieves the TPM2_HANDLE for an associated ESYS_TR object for use with the
565  * SAPI API or comparisons against raw TPM2_HANDLES from commands like
566  * TPM2_GetCapability or use of various handle bitwise comparisons. For example
567  * the mask TPM2_HR_NV_INDEX.
568  *
569  * @param esys_context [in,out] The ESYS_CONTEXT.
570  * @param esys_handle [in] The ESYS_TR object to retrieve the TPM2_HANDLE from.
571  * @param tpm_handle [out] The TPM2_HANDLE retrieved from the ESYS_TR object.
572  * @retval TSS2_RC_SUCCESS on Success.
573  * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the
574  *         ESYS_CONTEXT or is ESYS_TR_NONE.
575  * @retval TSS2_ESYS_RC_BAD_VALUE if an unknown handle < ESYS_TR_MIN_OBJECT is
576  *         passed.
577  * @retval TSS2_ESYS_RC_BAD_REFERENCE For invalid ESYS_CONTEXT.
578  */
579 TSS2_RC
Esys_TR_GetTpmHandle(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPM2_HANDLE * tpm_handle)580 Esys_TR_GetTpmHandle(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
581                   TPM2_HANDLE * tpm_handle)
582 {
583     TSS2_RC r = TSS2_RC_SUCCESS;
584     RSRC_NODE_T *esys_object;
585 
586     _ESYS_ASSERT_NON_NULL(esys_context);
587     _ESYS_ASSERT_NON_NULL(tpm_handle);
588 
589     if (esys_handle == ESYS_TR_NONE) {
590         return TSS2_ESYS_RC_BAD_TR;
591     }
592 
593     r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
594     return_if_error(r, "Get resource object");
595 
596     *tpm_handle = esys_object->rsrc.handle;
597 
598     return TSS2_RC_SUCCESS;
599 };
600 
601 /** Retrieve whether auth value is required from a Esys_TR session object.
602  *
603  * This function can be used to determin whether PoliyPassword or
604  * PlolicyAuthValue are used for a session.
605  * @param esys_context [in,out] The ESYS_CONTEXT.
606  * @param esys_handle [in,out] The ESYS_TRsess for which to retrieve the nonce.
607  * @param neeed [out] The boolean indicating whether auth value will be
608  *                    needed.
609  * @retval TSS2_RC_SUCCESS on Success.
610  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
611  * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL.
612  * @retval TSS2_SYS_RC_* for SAPI errors.
613  */
614 TSS2_RC
Esys_TRSess_GetAuthRequired(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,TPMI_YES_NO * auth_needed)615 Esys_TRSess_GetAuthRequired(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle,
616                             TPMI_YES_NO *auth_needed)
617 {
618     RSRC_NODE_T *esys_object;
619     TSS2_RC r;
620     _ESYS_ASSERT_NON_NULL(esys_context);
621 
622     r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
623     return_if_error(r, "Object not found");
624 
625     if (esys_object->rsrc.rsrcType != IESYSC_SESSION_RSRC) {
626         return_if_error(TSS2_ESYS_RC_BAD_TR,
627                         "Auth value needed for non-session object requested.");
628     }
629 
630     if (esys_object->rsrc.misc.rsrc_session.type_policy_session == POLICY_AUTH ||
631         esys_object->rsrc.misc.rsrc_session.type_policy_session == POLICY_PASSWORD)
632         *auth_needed = TPM2_YES;
633     else
634         *auth_needed = TPM2_NO;
635     return TSS2_RC_SUCCESS;
636 
637 }
638