xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/api/Fapi_Initialize.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
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