1*758e9fbaSOystein Eftevaag /* SPDX-License-Identifier: BSD-2-Clause */
2*758e9fbaSOystein Eftevaag /*******************************************************************************
3*758e9fbaSOystein Eftevaag * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
4*758e9fbaSOystein Eftevaag * All rights reserved.
5*758e9fbaSOystein Eftevaag *******************************************************************************/
6*758e9fbaSOystein Eftevaag
7*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
8*758e9fbaSOystein Eftevaag #include <config.h>
9*758e9fbaSOystein Eftevaag #endif
10*758e9fbaSOystein Eftevaag
11*758e9fbaSOystein Eftevaag #include <stdlib.h>
12*758e9fbaSOystein Eftevaag #include <string.h>
13*758e9fbaSOystein Eftevaag #include <unistd.h>
14*758e9fbaSOystein Eftevaag #include <errno.h>
15*758e9fbaSOystein Eftevaag #ifndef NO_DL
16*758e9fbaSOystein Eftevaag #include <dlfcn.h>
17*758e9fbaSOystein Eftevaag #endif /* NO_DL */
18*758e9fbaSOystein Eftevaag
19*758e9fbaSOystein Eftevaag #include "tss2_tcti.h"
20*758e9fbaSOystein Eftevaag #include "tss2_tctildr.h"
21*758e9fbaSOystein Eftevaag #include "tss2_esys.h"
22*758e9fbaSOystein Eftevaag #include "tss2_fapi.h"
23*758e9fbaSOystein Eftevaag #include "fapi_int.h"
24*758e9fbaSOystein Eftevaag #include "fapi_util.h"
25*758e9fbaSOystein Eftevaag #include "ifapi_json_deserialize.h"
26*758e9fbaSOystein Eftevaag #define LOGMODULE fapi
27*758e9fbaSOystein Eftevaag #include "util/log.h"
28*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
29*758e9fbaSOystein Eftevaag
30*758e9fbaSOystein Eftevaag /** One-Call function for Fapi_Initialize
31*758e9fbaSOystein Eftevaag *
32*758e9fbaSOystein Eftevaag * Initializes a FAPI_CONTEXT that holds all the state and metadata information
33*758e9fbaSOystein Eftevaag * during an interaction with the TPM.
34*758e9fbaSOystein Eftevaag *
35*758e9fbaSOystein Eftevaag * @param[out] context The FAPI_CONTEXT
36*758e9fbaSOystein Eftevaag * @param[in] uri Unused in this version of the FAPI. Must be NULL
37*758e9fbaSOystein Eftevaag *
38*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS: if the function call was a success.
39*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
40*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_VALUE: if uri is not NULL.
41*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
42*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
43*758e9fbaSOystein Eftevaag * internal operations or return parameters.
44*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
45*758e9fbaSOystein Eftevaag * this function needs to be called again.
46*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
47*758e9fbaSOystein Eftevaag * operation already pending.
48*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
49*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_PATH if the used path in inappropriate-
50*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
51*758e9fbaSOystein Eftevaag */
52*758e9fbaSOystein Eftevaag TSS2_RC
Fapi_Initialize(FAPI_CONTEXT ** context,char const * uri)53*758e9fbaSOystein Eftevaag Fapi_Initialize(
54*758e9fbaSOystein Eftevaag FAPI_CONTEXT **context,
55*758e9fbaSOystein Eftevaag char const *uri)
56*758e9fbaSOystein Eftevaag {
57*758e9fbaSOystein Eftevaag LOG_TRACE("called for context:%p", context);
58*758e9fbaSOystein Eftevaag
59*758e9fbaSOystein Eftevaag TSS2_RC r = TSS2_RC_SUCCESS;
60*758e9fbaSOystein Eftevaag
61*758e9fbaSOystein Eftevaag /* Check for NULL parameters */
62*758e9fbaSOystein Eftevaag check_not_null(context);
63*758e9fbaSOystein Eftevaag if (uri != NULL) {
64*758e9fbaSOystein Eftevaag LOG_ERROR("uri is not NULL");
65*758e9fbaSOystein Eftevaag return TSS2_FAPI_RC_BAD_VALUE;
66*758e9fbaSOystein Eftevaag }
67*758e9fbaSOystein Eftevaag
68*758e9fbaSOystein Eftevaag r = Fapi_Initialize_Async(context, uri);
69*758e9fbaSOystein Eftevaag return_if_error(r, "FAPI Async call initialize");
70*758e9fbaSOystein Eftevaag check_oom(*context);
71*758e9fbaSOystein Eftevaag
72*758e9fbaSOystein Eftevaag do {
73*758e9fbaSOystein Eftevaag /* We wait for file I/O to be ready if the FAPI state automata
74*758e9fbaSOystein Eftevaag are in a file I/O state. */
75*758e9fbaSOystein Eftevaag r = ifapi_io_poll(&(*context)->io);
76*758e9fbaSOystein Eftevaag return_if_error(r, "Something went wrong with IO polling");
77*758e9fbaSOystein Eftevaag
78*758e9fbaSOystein Eftevaag /* Repeatedly call the finish function, until FAPI has transitioned
79*758e9fbaSOystein Eftevaag through all execution stages / states of this invocation. */
80*758e9fbaSOystein Eftevaag r = Fapi_Initialize_Finish(context);
81*758e9fbaSOystein Eftevaag } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
82*758e9fbaSOystein Eftevaag
83*758e9fbaSOystein Eftevaag LOG_TRACE("finished");
84*758e9fbaSOystein Eftevaag return r;
85*758e9fbaSOystein Eftevaag }
86*758e9fbaSOystein Eftevaag
87*758e9fbaSOystein Eftevaag /** Asynchronous function for Fapi_Initialize
88*758e9fbaSOystein Eftevaag *
89*758e9fbaSOystein Eftevaag * Initializes a FAPI_CONTEXT that holds all the state and metadata information
90*758e9fbaSOystein Eftevaag * during an interaction with the TPM.
91*758e9fbaSOystein Eftevaag *
92*758e9fbaSOystein Eftevaag * Call Fapi_Initialize to finish the execution of this command.
93*758e9fbaSOystein Eftevaag *
94*758e9fbaSOystein Eftevaag * @param[out] context The FAPI_CONTEXT
95*758e9fbaSOystein Eftevaag * @param[in] uri Unused in this version of the FAPI. Must be NULL
96*758e9fbaSOystein Eftevaag *
97*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS: if the function call was a success.
98*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
99*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_VALUE: if uri is not NULL.
100*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
101*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
102*758e9fbaSOystein Eftevaag * internal operations or return parameters.
103*758e9fbaSOystein Eftevaag */
104*758e9fbaSOystein Eftevaag TSS2_RC
Fapi_Initialize_Async(FAPI_CONTEXT ** context,char const * uri)105*758e9fbaSOystein Eftevaag Fapi_Initialize_Async(
106*758e9fbaSOystein Eftevaag FAPI_CONTEXT **context,
107*758e9fbaSOystein Eftevaag char const *uri)
108*758e9fbaSOystein Eftevaag {
109*758e9fbaSOystein Eftevaag LOG_TRACE("called for context:%p", context);
110*758e9fbaSOystein Eftevaag LOG_TRACE("uri: %s", uri);
111*758e9fbaSOystein Eftevaag
112*758e9fbaSOystein Eftevaag TSS2_RC r = TSS2_RC_SUCCESS;
113*758e9fbaSOystein Eftevaag
114*758e9fbaSOystein Eftevaag /* Check for NULL parameters */
115*758e9fbaSOystein Eftevaag check_not_null(context);
116*758e9fbaSOystein Eftevaag if (uri != NULL) {
117*758e9fbaSOystein Eftevaag LOG_ERROR("uri is not NULL");
118*758e9fbaSOystein Eftevaag return TSS2_FAPI_RC_BAD_VALUE;
119*758e9fbaSOystein Eftevaag }
120*758e9fbaSOystein Eftevaag
121*758e9fbaSOystein Eftevaag *context = NULL;
122*758e9fbaSOystein Eftevaag
123*758e9fbaSOystein Eftevaag /* Allocate memory for the FAPI context
124*758e9fbaSOystein Eftevaag * After this errors must jump to cleanup_return instead of returning. */
125*758e9fbaSOystein Eftevaag *context = calloc(1, sizeof(FAPI_CONTEXT));
126*758e9fbaSOystein Eftevaag return_if_null(*context, "Out of memory.", TSS2_FAPI_RC_MEMORY);
127*758e9fbaSOystein Eftevaag memset(*context, 0, sizeof(FAPI_CONTEXT));
128*758e9fbaSOystein Eftevaag
129*758e9fbaSOystein Eftevaag /* Initialize the context */
130*758e9fbaSOystein Eftevaag r = ifapi_config_initialize_async(&(*context)->io);
131*758e9fbaSOystein Eftevaag goto_if_error(r, "Could not initialize FAPI context", cleanup_return);
132*758e9fbaSOystein Eftevaag
133*758e9fbaSOystein Eftevaag /* Initialize the context state for this operation. */
134*758e9fbaSOystein Eftevaag (*context)->state = INITIALIZE_READ;
135*758e9fbaSOystein Eftevaag
136*758e9fbaSOystein Eftevaag cleanup_return:
137*758e9fbaSOystein Eftevaag if (r)
138*758e9fbaSOystein Eftevaag SAFE_FREE(*context);
139*758e9fbaSOystein Eftevaag LOG_TRACE("finished");
140*758e9fbaSOystein Eftevaag return r;
141*758e9fbaSOystein Eftevaag }
142*758e9fbaSOystein Eftevaag
143*758e9fbaSOystein Eftevaag /** Asynchronous finish function for Fapi_Initialize
144*758e9fbaSOystein Eftevaag *
145*758e9fbaSOystein Eftevaag * This function should be called after a previous Fapi_Initialize_Async.
146*758e9fbaSOystein Eftevaag *
147*758e9fbaSOystein Eftevaag * @param[out] context The FAPI_CONTEXT
148*758e9fbaSOystein Eftevaag *
149*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS: if the function call was a success.
150*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
151*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
152*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
153*758e9fbaSOystein Eftevaag * operation already pending.
154*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
155*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
156*758e9fbaSOystein Eftevaag * internal operations or return parameters.
157*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
158*758e9fbaSOystein Eftevaag * complete. Call this function again later.
159*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
160*758e9fbaSOystein Eftevaag * the function.
161*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
162*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_PATH if the used path in inappropriate-
163*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
164*758e9fbaSOystein Eftevaag */
165*758e9fbaSOystein Eftevaag TSS2_RC
Fapi_Initialize_Finish(FAPI_CONTEXT ** context)166*758e9fbaSOystein Eftevaag Fapi_Initialize_Finish(
167*758e9fbaSOystein Eftevaag FAPI_CONTEXT **context)
168*758e9fbaSOystein Eftevaag {
169*758e9fbaSOystein Eftevaag LOG_TRACE("called for context:%p", context);
170*758e9fbaSOystein Eftevaag
171*758e9fbaSOystein Eftevaag TSS2_RC r;
172*758e9fbaSOystein Eftevaag TPMI_YES_NO moreData;
173*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT *fapi_tcti = NULL;
174*758e9fbaSOystein Eftevaag
175*758e9fbaSOystein Eftevaag /* Check for NULL parameters */
176*758e9fbaSOystein Eftevaag check_not_null(context);
177*758e9fbaSOystein Eftevaag check_not_null(*context);
178*758e9fbaSOystein Eftevaag
179*758e9fbaSOystein Eftevaag /* Helpful alias pointers */
180*758e9fbaSOystein Eftevaag TPMS_CAPABILITY_DATA **capability = &(*context)->cmd.Initialize.capability;
181*758e9fbaSOystein Eftevaag
182*758e9fbaSOystein Eftevaag switch ((*context)->state) {
183*758e9fbaSOystein Eftevaag statecase((*context)->state, INITIALIZE_READ);
184*758e9fbaSOystein Eftevaag /* This is the entry point; finishing the initialization of the config module. */
185*758e9fbaSOystein Eftevaag r = ifapi_config_initialize_finish(&(*context)->io, &(*context)->config);
186*758e9fbaSOystein Eftevaag return_try_again(r);
187*758e9fbaSOystein Eftevaag goto_if_error(r, "Could not finish initialization", cleanup_return);
188*758e9fbaSOystein Eftevaag
189*758e9fbaSOystein Eftevaag /* Initialize the event log module. */
190*758e9fbaSOystein Eftevaag r = ifapi_eventlog_initialize(&((*context)->eventlog), (*context)->config.log_dir);
191*758e9fbaSOystein Eftevaag goto_if_error(r, "Initializing evenlog module", cleanup_return);
192*758e9fbaSOystein Eftevaag
193*758e9fbaSOystein Eftevaag /* Initialize the keystore. */
194*758e9fbaSOystein Eftevaag r = ifapi_keystore_initialize(&((*context)->keystore),
195*758e9fbaSOystein Eftevaag (*context)->config.keystore_dir,
196*758e9fbaSOystein Eftevaag (*context)->config.user_dir,
197*758e9fbaSOystein Eftevaag (*context)->config.profile_name);
198*758e9fbaSOystein Eftevaag goto_if_error2(r, "Keystore could not be initialized.", cleanup_return);
199*758e9fbaSOystein Eftevaag
200*758e9fbaSOystein Eftevaag /* Initialize the policy store. */
201*758e9fbaSOystein Eftevaag /* Policy directory will be placed in keystore dir */
202*758e9fbaSOystein Eftevaag r = ifapi_policy_store_initialize(&((*context)->pstore),
203*758e9fbaSOystein Eftevaag (*context)->config.keystore_dir);
204*758e9fbaSOystein Eftevaag goto_if_error2(r, "Keystore could not be initialized.", cleanup_return);
205*758e9fbaSOystein Eftevaag
206*758e9fbaSOystein Eftevaag fallthrough;
207*758e9fbaSOystein Eftevaag
208*758e9fbaSOystein Eftevaag statecase((*context)->state, INITIALIZE_INIT_TCTI);
209*758e9fbaSOystein Eftevaag if (strcasecmp((*context)->config.tcti, "none") == 0) {
210*758e9fbaSOystein Eftevaag /* FAPI will be used in none TPM mode */
211*758e9fbaSOystein Eftevaag (*context)->esys = NULL;
212*758e9fbaSOystein Eftevaag (*context)->state = INITIALIZE_READ_PROFILE_INIT;
213*758e9fbaSOystein Eftevaag return TSS2_FAPI_RC_TRY_AGAIN;
214*758e9fbaSOystein Eftevaag }
215*758e9fbaSOystein Eftevaag
216*758e9fbaSOystein Eftevaag /* Call for the TctiLdr to initialize a TCTI context given the config
217*758e9fbaSOystein Eftevaag from the FAPI config module. */
218*758e9fbaSOystein Eftevaag r = Tss2_TctiLdr_Initialize((*context)->config.tcti, &fapi_tcti);
219*758e9fbaSOystein Eftevaag goto_if_error(r, "Initializing TCTI.", cleanup_return);
220*758e9fbaSOystein Eftevaag
221*758e9fbaSOystein Eftevaag /* Initialize an ESYS context using this Tcti. */
222*758e9fbaSOystein Eftevaag r = Esys_Initialize(&((*context)->esys), fapi_tcti, NULL);
223*758e9fbaSOystein Eftevaag goto_if_error(r, "Initialize esys context.", cleanup_return);
224*758e9fbaSOystein Eftevaag
225*758e9fbaSOystein Eftevaag /* Call Startup on the TPM. */
226*758e9fbaSOystein Eftevaag r = Esys_Startup((*context)->esys, TPM2_SU_CLEAR);
227*758e9fbaSOystein Eftevaag if (r != TSS2_RC_SUCCESS && r != TPM2_RC_INITIALIZE) {
228*758e9fbaSOystein Eftevaag LOG_ERROR("Esys_Startup FAILED! Response Code : 0x%x", r);
229*758e9fbaSOystein Eftevaag return r;
230*758e9fbaSOystein Eftevaag }
231*758e9fbaSOystein Eftevaag fallthrough;
232*758e9fbaSOystein Eftevaag
233*758e9fbaSOystein Eftevaag statecase((*context)->state, INITIALIZE_GET_CAP);
234*758e9fbaSOystein Eftevaag /* Retrieve the maximal value for transfer of nv data from the TPM. */
235*758e9fbaSOystein Eftevaag r = Esys_GetCapability_Async((*context)->esys, ESYS_TR_NONE, ESYS_TR_NONE,
236*758e9fbaSOystein Eftevaag ESYS_TR_NONE,
237*758e9fbaSOystein Eftevaag TPM2_CAP_TPM_PROPERTIES, TPM2_PT_NV_BUFFER_MAX, 1);
238*758e9fbaSOystein Eftevaag goto_if_error(r, "Error json deserialize", cleanup_return);
239*758e9fbaSOystein Eftevaag
240*758e9fbaSOystein Eftevaag fallthrough;
241*758e9fbaSOystein Eftevaag
242*758e9fbaSOystein Eftevaag statecase((*context)->state, INITIALIZE_WAIT_FOR_CAP);
243*758e9fbaSOystein Eftevaag r = Esys_GetCapability_Finish((*context)->esys, &moreData, capability);
244*758e9fbaSOystein Eftevaag return_try_again(r);
245*758e9fbaSOystein Eftevaag goto_if_error(r, "Get capability data.", cleanup_return);
246*758e9fbaSOystein Eftevaag
247*758e9fbaSOystein Eftevaag /* Check if the TPM returns the NV_BUFFER_MAX value. */
248*758e9fbaSOystein Eftevaag if ((*capability)->data.tpmProperties.count == 1 &&
249*758e9fbaSOystein Eftevaag (*capability)->data.tpmProperties.tpmProperty[0].property ==
250*758e9fbaSOystein Eftevaag TPM2_PT_NV_BUFFER_MAX) {
251*758e9fbaSOystein Eftevaag (*context)->nv_buffer_max = (*capability)->data.tpmProperties.tpmProperty[0].value;
252*758e9fbaSOystein Eftevaag /* FAPI also contains an upper limit on the NV_MAX_BUFFER size. This is
253*758e9fbaSOystein Eftevaag useful for vTPMs that could in theory allow for several Megabytes of
254*758e9fbaSOystein Eftevaag max transfer buffer sizes. */
255*758e9fbaSOystein Eftevaag if ((*context)->nv_buffer_max > IFAPI_MAX_BUFFER_SIZE)
256*758e9fbaSOystein Eftevaag (*context)->nv_buffer_max = IFAPI_MAX_BUFFER_SIZE;
257*758e9fbaSOystein Eftevaag } else {
258*758e9fbaSOystein Eftevaag /* Note that for some time it was legal for a TPM to not return this value.
259*758e9fbaSOystein Eftevaag in that case FAPI falls back to 64 bytes for NV_BUFFER_MAX that all TPMs
260*758e9fbaSOystein Eftevaag must support. This slows down communication for NV read and write but
261*758e9fbaSOystein Eftevaag ensures that data can be exchanged with the TPM. */
262*758e9fbaSOystein Eftevaag (*context)->nv_buffer_max = 64;
263*758e9fbaSOystein Eftevaag }
264*758e9fbaSOystein Eftevaag fallthrough;
265*758e9fbaSOystein Eftevaag
266*758e9fbaSOystein Eftevaag statecase((*context)->state, INITIALIZE_READ_PROFILE_INIT);
267*758e9fbaSOystein Eftevaag /* Initialize the proviles module that loads cryptographic profiles.
268*758e9fbaSOystein Eftevaag The default profile is taken from config. */
269*758e9fbaSOystein Eftevaag r = ifapi_profiles_initialize_async(&(*context)->profiles, &(*context)->io,
270*758e9fbaSOystein Eftevaag (*context)->config.profile_dir,
271*758e9fbaSOystein Eftevaag (*context)->config.profile_name);
272*758e9fbaSOystein Eftevaag return_if_error(r, "Read profile");
273*758e9fbaSOystein Eftevaag
274*758e9fbaSOystein Eftevaag fallthrough;
275*758e9fbaSOystein Eftevaag
276*758e9fbaSOystein Eftevaag statecase((*context)->state, INITIALIZE_READ_PROFILE);
277*758e9fbaSOystein Eftevaag r = ifapi_profiles_initialize_finish(&(*context)->profiles, &(*context)->io);
278*758e9fbaSOystein Eftevaag FAPI_SYNC(r, "Read profile.", cleanup_return);
279*758e9fbaSOystein Eftevaag
280*758e9fbaSOystein Eftevaag LOG_DEBUG("success: *context %p", *context);
281*758e9fbaSOystein Eftevaag break;
282*758e9fbaSOystein Eftevaag
283*758e9fbaSOystein Eftevaag statecasedefault((*context)->state);
284*758e9fbaSOystein Eftevaag }
285*758e9fbaSOystein Eftevaag
286*758e9fbaSOystein Eftevaag (*context)->state = _FAPI_STATE_INIT;
287*758e9fbaSOystein Eftevaag SAFE_FREE(*capability);
288*758e9fbaSOystein Eftevaag LOG_TRACE("finished");
289*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
290*758e9fbaSOystein Eftevaag
291*758e9fbaSOystein Eftevaag cleanup_return:
292*758e9fbaSOystein Eftevaag /* Cleanup any intermediate results and state stored in the context. */
293*758e9fbaSOystein Eftevaag if ((*context)->esys) {
294*758e9fbaSOystein Eftevaag Esys_GetTcti((*context)->esys, &fapi_tcti);
295*758e9fbaSOystein Eftevaag Esys_Finalize(&(*context)->esys);
296*758e9fbaSOystein Eftevaag }
297*758e9fbaSOystein Eftevaag if (fapi_tcti) {
298*758e9fbaSOystein Eftevaag Tss2_TctiLdr_Finalize(&fapi_tcti);
299*758e9fbaSOystein Eftevaag }
300*758e9fbaSOystein Eftevaag
301*758e9fbaSOystein Eftevaag /* Free the context memory in case of an error. */
302*758e9fbaSOystein Eftevaag free(*context);
303*758e9fbaSOystein Eftevaag *context = NULL;
304*758e9fbaSOystein Eftevaag
305*758e9fbaSOystein Eftevaag return r;
306*758e9fbaSOystein Eftevaag }
307