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