1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*******************************************************************************
3  * Copyright 2017, 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 #include <stdlib.h>
11 
12 #include "tss2_esys.h"
13 #include "tss2_tctildr.h"
14 
15 #include "esys_iutil.h"
16 #include "tss2-tcti/tctildr-interface.h"
17 #define LOGMODULE esys
18 #include "util/log.h"
19 #include "util/aux_util.h"
20 
21 /** Initialize an ESYS_CONTEXT for further use.
22  *
23  * Initialize an ESYS_CONTEXT that holds all the state and metadata information
24  * during an interaction with the TPM.
25  * If not specified, load a TCTI in this order:
26  *       Library libtss2-tcti-default.so (link to the preferred TCTI)
27  *       Library libtss2-tcti-tabrmd.so (tabrmd)
28  *       Device /dev/tpmrm0 (kernel resident resource manager)
29  *       Device /dev/tpm0 (hardware TPM)
30  *       TCP socket localhost:2321 (TPM simulator)
31  * @param esys_context [out] The ESYS_CONTEXT.
32  * @param tcti [in] The TCTI context used to connect to the TPM (may be NULL).
33  * @param abiVersion [in,out] The abi version to check and the abi version
34  *        supported by this implementation (may be NULL).
35  * @retval TSS2_ESYS_RC_SUCCESS if the function call was a success.
36  * @retval TSS2_ESYS_RC_BAD_REFERENCE if esysContext is NULL.
37  * @retval TSS2_ESYS_RC_MEMORY if the ESAPI cannot allocate enough memory to
38  *         create the context.
39  * @retval TSS2_RCs produced by lower layers of the software stack may be
40  *         returned to the caller unaltered unless handled internally.
41  */
42 TSS2_RC
Esys_Initialize(ESYS_CONTEXT ** esys_context,TSS2_TCTI_CONTEXT * tcti,TSS2_ABI_VERSION * abiVersion)43 Esys_Initialize(ESYS_CONTEXT ** esys_context, TSS2_TCTI_CONTEXT * tcti,
44                 TSS2_ABI_VERSION * abiVersion)
45 {
46     TSS2_RC r;
47     size_t syssize;
48 
49     _ESYS_ASSERT_NON_NULL(esys_context);
50     *esys_context = NULL;
51 
52     /* Allocate memory for the ESYS context
53      * After this errors must jump to cleanup_return instead of returning. */
54     *esys_context = calloc(1, sizeof(ESYS_CONTEXT));
55     return_if_null(*esys_context, "Out of memory.", TSS2_ESYS_RC_MEMORY);
56 
57     /* Allocate memory for the SYS context */
58     syssize = Tss2_Sys_GetContextSize(0);
59     (*esys_context)->sys = calloc(1, syssize);
60     goto_if_null((*esys_context)->sys, "Error: During malloc.",
61                  TSS2_ESYS_RC_MEMORY, cleanup_return);
62 
63     /* Store the application provided tcti to be return on Esys_GetTcti(). */
64     (*esys_context)->tcti_app_param = tcti;
65 
66     /* If no tcti was provided, initialize the default one. */
67     if (tcti == NULL) {
68         r = Tss2_TctiLdr_Initialize (NULL, &tcti);
69         goto_if_error(r, "Initialize default tcti.", cleanup_return);
70     }
71 
72     /* Initialize the ESAPI */
73     r = Tss2_Sys_Initialize((*esys_context)->sys, syssize, tcti, abiVersion);
74     goto_if_error(r, "During syscontext initialization", cleanup_return);
75 
76     /* Use random number for initial esys handle value to provide pseudo
77        namespace for handles */
78     (*esys_context)->esys_handle_cnt = ESYS_TR_MIN_OBJECT + (rand() % 6000000);
79 
80     /* Initialize crypto backend. */
81     r = iesys_initialize_crypto();
82     goto_if_error(r, "Initialize crypto backend.", cleanup_return);
83 
84     return TSS2_RC_SUCCESS;
85 
86 cleanup_return:
87     /* If we created the tcti ourselves, we must clean it up */
88     if ((*esys_context)->tcti_app_param == NULL && tcti != NULL) {
89         Tss2_TctiLdr_Finalize(&tcti);
90     }
91 
92     /* No need to finalize (*esys_context)->sys only free since
93        it is the last goto in this function. */
94     free((*esys_context)->sys);
95     free(*esys_context);
96     *esys_context = NULL;
97     return r;
98 }
99 
100 /** Finalize an ESYS_CONTEXT
101  *
102  * After interactions with the TPM the context holding the metadata needs to be
103  * freed. Since additional internal memory allocations may have happened during
104  * use of the context, it needs to be finalized correctly.
105  * @param esys_context [in,out] The ESYS_CONTEXT. (will be freed and set to NULL)
106  */
107 void
Esys_Finalize(ESYS_CONTEXT ** esys_context)108 Esys_Finalize(ESYS_CONTEXT ** esys_context)
109 {
110     TSS2_RC r;
111     TSS2_TCTI_CONTEXT *tctcontext = NULL;
112 
113     if (esys_context == NULL || *esys_context == NULL) {
114         LOG_WARNING("Finalizing NULL context.");
115         return;
116     }
117 
118     /* Flush from TPM and free all resource objects first */
119     iesys_DeleteAllResourceObjects(*esys_context);
120 
121     /* If no tcti context was provided during initialization, then we need to
122        finalize the tcti context. So we retrieve here before finalizing the
123        SAPI context. */
124     if ((*esys_context)->tcti_app_param == NULL) {
125         r = Tss2_Sys_GetTctiContext((*esys_context)->sys, &tctcontext);
126         if (r != TSS2_RC_SUCCESS) {
127             LOG_ERROR("Internal error in Tss2_Sys_GetTctiContext.");
128             tctcontext = NULL;
129         }
130     }
131 
132     /* Finalize the syscontext */
133     Tss2_Sys_Finalize((*esys_context)->sys);
134     free((*esys_context)->sys);
135 
136     /* If no tcti context was provided during initialization, then we need to
137        finalize the tcti context here. */
138     if (tctcontext != NULL) {
139         Tss2_TctiLdr_Finalize(&tctcontext);
140     }
141 
142     /* Free esys_context */
143     free(*esys_context);
144     *esys_context = NULL;
145 }
146 
147 /** Return the used TCTI context.
148  *
149  * If a tcti context was passed into Esys_Initialize then this tcti context is
150  * return. If NULL was passed in, then NULL will be returned.
151  * This function is useful before Esys_Finalize to retrieve the tcti context and
152  * perform a clean Tss2_Tcti_Finalize.
153  * @param esys_context [in] The ESYS_CONTEXT.
154  * @param tcti [out] The TCTI context used to connect to the TPM (may be NULL).
155  * @retval TSS2_RC_SUCCESS on Success.
156  * @retval TSS2_ESYS_RC_BAD_REFERENCE if esysContext or tcti is NULL.
157  */
158 TSS2_RC
Esys_GetTcti(ESYS_CONTEXT * esys_context,TSS2_TCTI_CONTEXT ** tcti)159 Esys_GetTcti(ESYS_CONTEXT * esys_context, TSS2_TCTI_CONTEXT ** tcti)
160 {
161     _ESYS_ASSERT_NON_NULL(esys_context);
162     _ESYS_ASSERT_NON_NULL(tcti);
163     *tcti = esys_context->tcti_app_param;
164     return TSS2_RC_SUCCESS;
165 }
166 
167 /** Return the poll handles of the used TCTI.
168  *
169  * The connection to the TPM is held using a TCTI. These may optionally provide
170  * handles that can be used to poll for incoming data. This is useful when
171  * using the asynchronous function of ESAPI in an event-loop model.
172  * @param esys_context [in] The ESYS_CONTEXT.
173  * @param handles [out] The poll handles (callee-allocated, use free())
174  * @param count [out] The number of poll handles.
175  * @retval TSS2_RC_SUCCESS on Success.
176  * @retval TSS2_ESYS_RC_BAD_REFERENCE if esysContext, handles or count is NULL.
177  * @retval TSS2_RCs produced by lower layers of the software stack.
178  */
179 TSS2_RC
Esys_GetPollHandles(ESYS_CONTEXT * esys_context,TSS2_TCTI_POLL_HANDLE ** handles,size_t * count)180 Esys_GetPollHandles(ESYS_CONTEXT * esys_context,
181                     TSS2_TCTI_POLL_HANDLE ** handles, size_t * count)
182 {
183     TSS2_RC r;
184     TSS2_TCTI_CONTEXT *tcti_context;
185 
186     _ESYS_ASSERT_NON_NULL(esys_context);
187     _ESYS_ASSERT_NON_NULL(handles);
188     _ESYS_ASSERT_NON_NULL(count);
189 
190     /* Get the tcti-context to use */
191     r = Tss2_Sys_GetTctiContext(esys_context->sys, &tcti_context);
192     return_if_error(r, "Invalid SAPI or TCTI context.");
193 
194     /* Allocate the memory to hold the poll handles */
195     r = Tss2_Tcti_GetPollHandles(tcti_context, NULL, count);
196     return_if_error(r, "Error getting poll handle count.");
197     *handles = calloc(*count, sizeof(TSS2_TCTI_POLL_HANDLE));
198     return_if_null(*handles, "Out of memory.", TSS2_ESYS_RC_MEMORY);
199 
200     /* Retrieve the poll handles */
201     r = Tss2_Tcti_GetPollHandles(tcti_context, *handles, count);
202     return_if_error(r, "Error getting poll handles.");
203     return r;
204 }
205 
206 /** Set the timeout of Esys asynchronous functions.
207  *
208  * Sets the timeout for the _finish() functions in the asynchronous versions of
209  * the Esys commands.
210  * @param esys_context [in] The ESYS_CONTEXT.
211  * @param timeout [in] The timeout in ms or -1 to block indefinately.
212  * @retval TSS2_RC_SUCCESS on Success.
213  * @retval TSS2_ESYS_RC_BAD_REFERENCE if esysContext is NULL.
214  */
215 TSS2_RC
Esys_SetTimeout(ESYS_CONTEXT * esys_context,int32_t timeout)216 Esys_SetTimeout(ESYS_CONTEXT * esys_context, int32_t timeout)
217 {
218     _ESYS_ASSERT_NON_NULL(esys_context);
219     esys_context->timeout = timeout;
220     return TSS2_RC_SUCCESS;
221 }
222 
223 /** Helper function that returns sys contest from the give esys context.
224  *
225  * Function returns sys contest from the give esys context.
226  * @param esys_context [in] ESYS context.
227  * @param sys_context [out] SYS context.
228  * @retval TSS2_RC_SUCCESS on Success.
229  * @retval TSS2_ESYS_RC_BAD_REFERENCE if esys_context of sys_context are NULL.
230  */
231 TSS2_RC
Esys_GetSysContext(ESYS_CONTEXT * esys_context,TSS2_SYS_CONTEXT ** sys_context)232 Esys_GetSysContext(ESYS_CONTEXT *esys_context, TSS2_SYS_CONTEXT **sys_context)
233 {
234     if (esys_context == NULL || sys_context == NULL)
235         return TSS2_ESYS_RC_BAD_REFERENCE;
236 
237     *sys_context = esys_context->sys;
238 
239     return TSS2_RC_SUCCESS;
240 }
241