xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/api/Fapi_Provision.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*******************************************************************************
3  * Copyright 2018-2019, 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 <stdlib.h>
12 #include <errno.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <string.h>
16 
17 #include "fapi_util.h"
18 #include "tss2_tcti.h"
19 #include "tss2_esys.h"
20 #include "tss2_fapi.h"
21 #include "fapi_int.h"
22 #include "fapi_crypto.h"
23 #include "fapi_policy.h"
24 #include "ifapi_get_intl_cert.h"
25 
26 #define LOGMODULE fapi
27 #include "util/log.h"
28 #include "util/aux_util.h"
29 
30 #define EK_CERT_RANGE (0x01c07fff)
31 
32 /** One-Call function for the initial FAPI provisioning.
33  *
34  * Provisions a TSS with its TPM. This includes the setting of important passwords
35  * and policy settings as well as the readout of the EK and its certificate and
36  * the initialization of the system-wide keystore.
37  *
38  * @param[in,out] context The FAPI_CONTEXT.
39  * @param[in] authValueEh The authorization value for the endorsement
40  *            hierarchy. May be NULL
41  * @param[in] authValueSh The authorization value for the storage hierarchy.
42  *            Should be NULL
43  * @param[in] authValueLockout The authorization value for lockout.
44  *
45  * @retval TSS2_RC_SUCCESS: if the function call was a success.
46  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
47  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
48  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
49  *         operation already pending.
50  * @retval TSS2_FAPI_RC_NO_CERT: if no certificate was found for the computed EK.
51  * @retval TSS2_FAPI_RC_BAD_KEY: if public key of the EK does not match the
52  *         configured certificate or the configured fingerprint does not match
53  *          the computed EK.
54  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
55  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
56  *         internal operations or return parameters.
57  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
58  *         config file.
59  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
60  *         this function needs to be called again.
61  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
62  *         the function.
63  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
64  *         is not set.
65  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
66  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
67  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
68  *         was not successful.
69  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
70  *         during authorization.
71  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
72  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
73  */
74 TSS2_RC
Fapi_Provision(FAPI_CONTEXT * context,char const * authValueEh,char const * authValueSh,char const * authValueLockout)75 Fapi_Provision(
76     FAPI_CONTEXT *context,
77     char   const *authValueEh,
78     char   const *authValueSh,
79     char   const *authValueLockout)
80 {
81     LOG_TRACE("called for context:%p", context);
82 
83     TSS2_RC r, r2;
84 
85     /* Check for NULL parameters */
86     check_not_null(context);
87 
88     /* Check whether TCTI and ESYS are initialized */
89     return_if_null(context->esys, "Command can't be executed in none TPM mode.",
90                    TSS2_FAPI_RC_NO_TPM);
91 
92     /* If the async state automata of FAPI shall be tested, then we must not set
93        the timeouts of ESYS to blocking mode.
94        During testing, the mssim tcti will ensure multiple re-invocations.
95        Usually however the synchronous invocations of FAPI shall instruct ESYS
96        to block until a result is available. */
97 #ifndef TEST_FAPI_ASYNC
98     r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
99     return_if_error_reset_state(r, "Set Timeout to blocking");
100 #endif /* TEST_FAPI_ASYNC */
101 
102     r = Fapi_Provision_Async(context, authValueEh, authValueSh, authValueLockout);
103     return_if_error_reset_state(r, "Provision");
104 
105     do {
106         /* We wait for file I/O to be ready if the FAPI state automata
107            are in a file I/O state. */
108         r = ifapi_io_poll(&context->io);
109         return_if_error(r, "Something went wrong with IO polling");
110 
111         /* Repeatedly call the finish function, until FAPI has transitioned
112            through all execution stages / states of this invocation. */
113         r = Fapi_Provision_Finish(context);
114     } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
115 
116     /* Reset the ESYS timeout to non-blocking, immediate response. */
117     r2 = Esys_SetTimeout(context->esys, 0);
118     return_if_error(r2, "Set Timeout to non-blocking");
119 
120     return_if_error_reset_state(r, "Provision");
121 
122     LOG_TRACE("finished");
123     return TSS2_RC_SUCCESS;
124 }
125 
126 /** Asynchronous function for the initial FAPI provisioning.
127  *
128  * Provisions a TSS with its TPM. This includes the setting of important passwords
129  * and policy settings as well as the readout of the EK and its certificate and
130  * the initialization of the system-wide keystore.
131  *
132  * Call Fapi_Provision_Finish to finish the execution of this command.
133  *
134  * @param[in,out] context The FAPI_CONTEXT.
135  * @param[in] authValueEh The authorization value for the endorsement
136  *            hierarchy. May be NULL
137  * @param[in] authValueSh The authorization value for the storage hierarchy.
138  *            Should be NULL
139  * @param[in] authValueLockout The authorization value for lockout.
140  *
141  * @retval TSS2_RC_SUCCESS: if the function call was a success.
142  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
143  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
144  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
145  *         operation already pending.
146  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
147  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
148  *         internal operations or return parameters.
149  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
150  *         config file.
151  */
152 TSS2_RC
Fapi_Provision_Async(FAPI_CONTEXT * context,char const * authValueEh,char const * authValueSh,char const * authValueLockout)153 Fapi_Provision_Async(
154     FAPI_CONTEXT *context,
155     char const *authValueEh,
156     char const *authValueSh,
157     char const *authValueLockout)
158 {
159     LOG_TRACE("called for context:%p", context);
160     LOG_TRACE("authValueEh: %s", authValueEh);
161     LOG_TRACE("authValueSh: %s", authValueSh);
162     LOG_TRACE("authValueLockout: %s", authValueLockout);
163 
164     TSS2_RC r;
165 
166     /* Check for NULL parameters */
167     check_not_null(context);
168 
169     /* Helpful alias pointers */
170     IFAPI_Provision * command = &context->cmd.Provision;
171 
172     r = ifapi_session_init(context);
173     goto_if_error(r, "Initialize Provision", end);
174 
175     /* Initialize context and duplicate parameters */
176     strdup_check(command->authValueLockout, authValueLockout, r, end);
177     strdup_check(command->authValueEh, authValueEh, r, end);
178     strdup_check(command->authValueSh, authValueSh, r, end);
179     context->ek_handle = ESYS_TR_NONE;
180     context->srk_handle = ESYS_TR_NONE;
181     command->cert_nv_idx = MIN_EK_CERT_HANDLE;
182     command->capabilityData = NULL;
183 
184     /* Set the initial state for the finish method. */
185     context->state = PROVISION_READ_PROFILE;
186     LOG_TRACE("finished");
187     return TSS2_RC_SUCCESS;
188 end:
189     SAFE_FREE(command->authValueLockout);
190     SAFE_FREE(command->authValueEh);
191     SAFE_FREE(command->authValueSh);
192     return r;
193 }
194 
195 /** Asynchronous finish function for Fapi_Provision
196  *
197  * This function should be called after a previous Fapi_Provision_Async.
198  *
199  * @param[in,out] context The FAPI_CONTEXT
200  *
201  * @retval TSS2_RC_SUCCESS: if the function call was a success.
202  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
203  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
204  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
205  *         operation already pending.
206  * @retval TSS2_FAPI_RC_NO_CERT: if no certificate was found for the computed EK.
207  * @retval TSS2_FAPI_RC_BAD_KEY: if public key of the EK does not match the
208  *         configured certificate or the configured fingerprint does not match
209  *         the computed EK.
210  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
211  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
212  *         internal operations or return parameters.
213  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
214  *         complete. Call this function again later.
215  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
216  *         the function.
217  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
218  *         is not set.
219  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
220  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
221  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
222  *         was not successful.
223  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
224  *         during authorization.
225  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
226  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
227  */
228 TSS2_RC
Fapi_Provision_Finish(FAPI_CONTEXT * context)229 Fapi_Provision_Finish(FAPI_CONTEXT *context)
230 {
231     LOG_TRACE("called for context:%p", context);
232 
233     TSS2_RC r = TSS2_RC_SUCCESS;
234     TPM2B_NV_PUBLIC *nvPublic = NULL;
235     uint8_t *certData = NULL;
236     size_t certSize;
237     TPMI_YES_NO moreData;
238     size_t hash_size;
239     TPMI_ALG_HASH hash_alg;
240     TPM2B_DIGEST ek_fingerprint;
241 
242     /* Check for NULL parameters */
243     check_not_null(context);
244 
245     /* Helpful alias pointers */
246     IFAPI_Provision * command = &context->cmd.Provision;
247     IFAPI_OBJECT *hierarchy = &command->hierarchy;
248     TPMS_CAPABILITY_DATA **capabilityData = &command->capabilityData;
249     IFAPI_NV_Cmds * nvCmd = &context->nv_cmd;
250     IFAPI_OBJECT * pkeyObject = &context->createPrimary.pkey_object;
251     IFAPI_KEY * pkey = &pkeyObject->misc.key;
252     IFAPI_PROFILE * defaultProfile = &context->profiles.default_profile;
253     int curl_rc;
254 
255     switch (context->state) {
256         statecase(context->state, PROVISION_READ_PROFILE);
257             /*
258              * The default values used for profiling will be used from
259              * the default profile.
260              */
261             command->root_crt = NULL;
262 
263             /* Generate template for SRK creation. */
264             r = ifapi_set_key_flags(defaultProfile->srk_template,
265                     context->profiles.default_profile.srk_policy ? true : false,
266                     &command->public_templ);
267             goto_if_error(r, "Set key flags for SRK", error_cleanup);
268 
269             r = ifapi_merge_profile_into_template(&context->profiles.default_profile,
270                     &command->public_templ);
271             goto_if_error(r, "Merging profile and template", error_cleanup);
272 
273             /* Prepare the setting of the dictionary attack parameters. */
274             r = Esys_DictionaryAttackParameters_Async(context->esys, ESYS_TR_RH_LOCKOUT,
275                     ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
276                     defaultProfile->newMaxTries, defaultProfile->newRecoveryTime,
277                     defaultProfile->lockoutRecovery);
278             goto_if_error(r, "Error Esys_DictionaryAttackParameters",
279                           error_cleanup);
280             fallthrough;
281 
282         statecase(context->state, PROVISION_WRITE_LOCKOUT_PARAM);
283             r = Esys_DictionaryAttackParameters_Finish(context->esys);
284             return_try_again(r);
285             goto_if_error_reset_state(r, "DictionaryAttackParameters_Finish",
286                     error_cleanup);
287 
288             /* Prepare the command for reading the TPMs PCR capabilities. */
289             r = Esys_GetCapability_Async(context->esys,
290                     ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, TPM2_CAP_PCRS, 0, 1);
291             goto_if_error(r, "Esys_GetCapability_Async", error_cleanup);
292 
293             fallthrough;
294 
295         statecase(context->state, PROVISION_WAIT_FOR_GET_CAP1);
296             r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
297             return_try_again(r);
298             goto_if_error_reset_state(r, "GetCapablity_Finish", error_cleanup);
299 
300             /* Check whether the TPMs PCR capabilities are compatible with the profile. */
301             TPML_PCR_SELECTION pcr_capability = (*capabilityData)->data.assignedPCR;
302             r = ifapi_check_profile_pcr_selection(&defaultProfile->pcr_selection,
303                     &pcr_capability);
304             goto_if_error(r, "Invalid PCR selection in profile.", error_cleanup);
305 
306             SAFE_FREE(*capabilityData);
307             fallthrough;
308 
309         statecase(context->state, PROVISION_INIT_SRK);
310             /* Clear key object for the primary to be created */
311             memset(pkey, 0, sizeof(IFAPI_KEY));
312 
313             /* Prepare the SRK generation. */
314             r = ifapi_init_primary_async(context, TSS2_SRK);
315             goto_if_error(r, "Initialize primary", error_cleanup);
316 
317             context->state = PROVISION_AUTH_SRK_NO_AUTH_SENT;
318             fallthrough;
319 
320         statecase(context->state, PROVISION_AUTH_SRK_AUTH_SENT);
321             fallthrough;
322 
323         statecase(context->state, PROVISION_AUTH_SRK_NO_AUTH_SENT);
324             r = ifapi_init_primary_finish(context, TSS2_SRK);
325             return_try_again(r);
326             goto_if_error(r, "Init primary finish.", error_cleanup);
327 
328             /* Check whether a persistent SRK handle was defined in profile. */
329             if (command->public_templ.persistent_handle) {
330                 /* Assign found handle to object */
331                 pkey->persistent_handle = command->public_templ.persistent_handle;
332 
333                 /* Initialize hierarchy object used for evict control. */
334                 ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
335 
336                 /* Prepare making the SRK permanent. */
337                 r = Esys_EvictControl_Async(context->esys, hierarchy->handle,
338                     pkeyObject->handle, ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
339                     pkey->persistent_handle);
340                 goto_if_error(r, "Error Esys EvictControl", error_cleanup);
341 
342                 context->state = PROVISION_WAIT_FOR_SRK_PERSISTENT;
343                 return TSS2_FAPI_RC_TRY_AGAIN;
344             }
345             /* No further ESYS command is needed, the keystore object can be written. */
346             context->state = PROVISION_SRK_WRITE_PREPARE;
347             fallthrough;
348 
349         statecase(context->state, PROVISION_SRK_WRITE_PREPARE);
350             pkeyObject->objectType = IFAPI_KEY_OBJ;
351             pkeyObject->system = command->public_templ.system;
352 
353             /* Perform esys serialization if necessary */
354             r = ifapi_esys_serialize_object(context->esys, pkeyObject);
355             goto_if_error(r, "Prepare serialization", error_cleanup);
356 
357             /* Start writing the SRK to the key store */
358             r = ifapi_keystore_store_async(&context->keystore, &context->io, "HS/SRK",
359                     pkeyObject);
360             goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "HS/SRK");
361             context->state = PROVISION_SRK_WRITE;
362             fallthrough;
363 
364         statecase(context->state, PROVISION_SRK_WRITE);
365             /* Finish writing the SRK to the key store */
366             r = ifapi_keystore_store_finish(&context->keystore, &context->io);
367             return_try_again(r);
368             goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
369 
370             /* Clean objects used for SRK computation */
371             ifapi_cleanup_ifapi_object(pkeyObject);
372             memset(&command->public_templ, 0, sizeof(IFAPI_KEY_TEMPLATE));
373 
374              /* Generate template for EK creation. */
375             r = ifapi_set_key_flags(defaultProfile->ek_template,
376                      context->profiles.default_profile.ek_policy ? true : false,
377                      &command->public_templ);
378             goto_if_error(r, "Set key flags for SRK", error_cleanup);
379 
380             r = ifapi_merge_profile_into_template(&context->profiles.default_profile,
381                     &command->public_templ);
382             goto_if_error(r, "Merging profile", error_cleanup);
383 
384             /* Clear key object for the primary to be created */
385             memset(pkey, 0, sizeof(IFAPI_KEY));
386 
387             /* Prepare the EK generation. */
388             r = ifapi_init_primary_async(context, TSS2_EK);
389             goto_if_error(r, "Initialize primary", error_cleanup);
390             fallthrough;
391         statecase(context->state, PROVISION_AUTH_EK_AUTH_SENT);
392             fallthrough;
393 
394         statecase(context->state, PROVISION_AUTH_EK_NO_AUTH_SENT);
395             r = ifapi_init_primary_finish(context, TSS2_EK);
396             return_try_again(r);
397             goto_if_error(r, "Init primary finish", error_cleanup);
398 
399             /* Check whether a persistent EK handle was defined in profile. */
400             if (command->public_templ.persistent_handle) {
401 
402                 /* Initialize hierarchy object used for EK processing. */
403                 ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
404 
405                 pkey->persistent_handle = command->public_templ.persistent_handle;
406 
407                 /* Prepare making the EK permanent. */
408                 r = Esys_EvictControl_Async(context->esys, hierarchy->handle,
409                         pkeyObject->handle, ESYS_TR_PASSWORD, ESYS_TR_NONE,
410                         ESYS_TR_NONE, pkey->persistent_handle);
411                 goto_if_error(r, "Error Esys EvictControl", error_cleanup);
412                 context->state = PROVISION_WAIT_FOR_EK_PERSISTENT;
413                 return TSS2_FAPI_RC_TRY_AGAIN;
414             }
415             fallthrough;
416 
417         statecase(context->state, PROVISION_INIT_GET_CAP2);
418             if (context->config.ek_cert_less == TPM2_YES) {
419                 /* Skip certificate validation. */
420                 context->state = PROVISION_EK_WRITE_PREPARE;
421                 return TSS2_FAPI_RC_TRY_AGAIN;
422             }
423 
424             /* Check whether fingerprint for EK is defined in config file. */
425             hash_alg = context->config.ek_fingerprint.hashAlg;
426             if (hash_alg) {
427                 LOG_DEBUG("Only fingerprint check for EK.");
428                 if (!(hash_size =ifapi_hash_get_digest_size(hash_alg))) {
429                     goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
430                                "Unsupported hash algorithm (%" PRIu16 ")", error_cleanup,
431                                hash_alg);
432                 }
433                 r = ifapi_get_tpm_key_fingerprint(&pkeyObject->misc.key.public, hash_alg,
434                                                   &ek_fingerprint);
435                 goto_if_error_reset_state(r, "Get fingerprint of EK", error_cleanup);
436 
437                 if (hash_size != ek_fingerprint.size ||
438                     memcmp(&context->config.ek_fingerprint.digest, &ek_fingerprint.buffer[0],
439                            hash_size) != 0) {
440                     goto_error(r, TSS2_FAPI_RC_BAD_KEY,
441                                "Fingerprint of EK not equal to fingerprint in config file.",
442                                error_cleanup);
443                 }
444                 /* The fingerprint was found no further certificate processing needed. */
445                 context->state = PROVISION_EK_WRITE_PREPARE;
446                 return TSS2_FAPI_RC_TRY_AGAIN;
447             }
448 
449             /* Check whether EK certificate has to be retrieved */
450             if (context->config.ek_cert_file) {
451                 size_t cert_size;
452                 TPM2B_PUBLIC public_key;
453 
454                 /* Curl will be used to retrieve the certificate from a file or via HTTP. */
455                 curl_rc = ifapi_get_curl_buffer((unsigned char *)context->config.ek_cert_file,
456                                                 (unsigned char **)&command->pem_cert, &cert_size);
457                 if (curl_rc != 0) {
458                     goto_error_reset_state(r, TSS2_FAPI_RC_NO_CERT, "Get certificate.",
459                                            error_cleanup);
460                 }
461 
462                 /* Get the public key from the certificate. */
463                 r = ifapi_get_public_from_pem_cert(command->pem_cert, &public_key);
464                 goto_if_error_reset_state(r, "Get public key from pem certificate",
465                                           error_cleanup);
466                 /* Compare public key of certificate with public data of EK */
467                 if (ifapi_cmp_public_key(&pkeyObject->misc.key.public, &public_key)) {
468                     /* The retrieved certificate will be written to keystore,
469                        no further certificate processing needed. */
470                     context->state = PROVISION_EK_WRITE_PREPARE;
471                     return TSS2_FAPI_RC_TRY_AGAIN;
472                 }
473                 goto_error(r, TSS2_FAPI_RC_BAD_KEY,
474                            "Public key of EK does not match certificate.",
475                            error_cleanup);
476             }
477 
478             /* Prepare the search for certificates store in the NV ram of the TPM. */
479             r = Esys_GetCapability_Async(context->esys,
480                     ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, TPM2_CAP_HANDLES,
481                     MIN_EK_CERT_HANDLE, TPM2_MAX_CAP_HANDLES);
482             goto_if_error(r, "Esys_GetCapability_Async", error_cleanup);
483 
484             fallthrough;
485 
486         statecase(context->state, PROVISION_WAIT_FOR_GET_CAP2);
487             r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
488             return_try_again(r);
489             goto_if_error_reset_state(r, "GetCapablity_Finish", error_cleanup);
490 
491             if ((*capabilityData)->data.handles.count == 0) {
492                 /* No more certificate, the EK can be compared with the certificates. */
493                 Esys_Free(*capabilityData);
494                 context->state = PROVISION_CHECK_FOR_VENDOR_CERT;
495                 return TSS2_FAPI_RC_TRY_AGAIN;
496             }
497             command->capabilityData = *capabilityData;
498             command->cert_count = (*capabilityData)->data.handles.count;
499 
500             /* Filter out NV handles beyond the EK cert range */
501             for (size_t i = 0; i < command->cert_count; i++) {
502                 if (command->capabilityData->data.handles.handle[i] > EK_CERT_RANGE) {
503                     command->cert_count = i;
504                 }
505             }
506 
507             if (command->cert_count == 0) {
508                 /* No certificates were found the cert range. */
509                 Esys_Free(command->capabilityData);
510                 command->capabilityData = NULL;
511                 context->state = PROVISION_CHECK_FOR_VENDOR_CERT;
512                 return TSS2_FAPI_RC_TRY_AGAIN;
513             }
514             fallthrough;
515 
516         statecase(context->state, PROVISION_GET_CERT_NV);
517 
518             /* Detemine the NV index of the certifcate from the read capability data. */
519             command->cert_nv_idx
520                 = command->capabilityData->data.handles.handle[command->cert_count-1];
521 
522             if ((command->cert_nv_idx % 2) || /**< Certificates will be stored at even address */
523                 command->cert_nv_idx == 0x01c00004 || /**< RSA template */
524                 command->cert_nv_idx == 0x01c0000c) { /**< ECC template */
525                 if (command->cert_count > 1) {
526                     command->cert_count -= 1;
527                     /* Check next certificate */
528                     context->state = PROVISION_GET_CERT_NV;
529                     return TSS2_FAPI_RC_TRY_AGAIN;
530                 } else {
531                     /* All certificates have been read, the EK can be written. */
532                     context->state = PROVISION_EK_WRITE_PREPARE;
533                     return TSS2_FAPI_RC_TRY_AGAIN;
534                 }
535             }
536             ifapi_init_hierarchy_object(&nvCmd->auth_object, TPM2_RH_OWNER);
537 
538             /* Create esys object for the NV object of the certificate. */
539             r = Esys_TR_FromTPMPublic_Async(context->esys, command->cert_nv_idx,
540                     ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
541             goto_if_error_reset_state(r, "Esys_TR_FromTPMPublic_Async", error_cleanup);
542 
543             context->state = PROVISION_GET_CERT_NV_FINISH;
544             fallthrough;
545 
546         statecase(context->state, PROVISION_GET_CERT_NV_FINISH);
547             r = Esys_TR_FromTPMPublic_Finish(context->esys,
548                     &command->esys_nv_cert_handle);
549             return_try_again(r);
550             goto_if_error_reset_state(r, "TR_FromTPMPublic_Finish", error_cleanup);
551 
552             /* Read public to get size of certificate */
553             r = Esys_NV_ReadPublic_Async(context->esys, command->esys_nv_cert_handle,
554                      ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
555             goto_if_error_reset_state(r, "Esys_NV_ReadPublic_Async", error_cleanup);
556 
557             context->state = PROVISION_GET_CERT_READ_PUBLIC;
558             fallthrough;
559 
560         statecase(context->state, PROVISION_GET_CERT_READ_PUBLIC);
561             r = Esys_NV_ReadPublic_Finish(context->esys, &nvPublic, NULL);
562             return_try_again(r);
563 
564             goto_if_error(r, "Error: nv read public", error_cleanup);
565 
566             /* TPMA_NV_NO_DA is set for NV certificate */
567             nvCmd->nv_object.misc.nv.public.nvPublic.attributes = TPMA_NV_NO_DA;
568 
569             /* Prepare context for nv read */
570             nvCmd->data_idx = 0;
571             nvCmd->auth_index = ESYS_TR_RH_OWNER;
572             nvCmd->numBytes = nvPublic->nvPublic.dataSize;
573             nvCmd->esys_handle = command->esys_nv_cert_handle;
574             nvCmd->offset = 0;
575             command->pem_cert = NULL;
576             context->session1 = ESYS_TR_PASSWORD;
577             context->session2 = ESYS_TR_NONE;
578             nvCmd->nv_read_state = NV_READ_INIT;
579             memset(&nvCmd->nv_object, 0, sizeof(IFAPI_OBJECT));
580             SAFE_FREE(nvPublic);
581 
582             context->state = PROVISION_READ_CERT;
583             fallthrough;
584 
585         statecase(context->state, PROVISION_READ_CERT);
586             TPM2B_PUBLIC public_key;
587             char * root_ca_file;
588 
589             /* The NV object of the certificate will be read asynchronous. */
590             r = ifapi_nv_read(context, &certData, &certSize);
591             return_try_again(r);
592             goto_if_error_reset_state(r, " FAPI NV_Read", error_cleanup);
593 
594             /* For storage in key store the certificate will be converted to PEM. */
595             r = ifapi_cert_to_pem(certData, certSize, &command->pem_cert,
596                                   &command->cert_key_type, &public_key);
597             SAFE_FREE(certData);
598             goto_if_error(r, "Convert certificate to pem.", error_cleanup);
599 
600             /* Check whether the EKs public key corresponds to the certificate. */
601             if (ifapi_cmp_public_key(&pkeyObject->misc.key.public, &public_key)) {
602                 context->state = PROVISION_PREPARE_READ_ROOT_CERT;
603                 return TSS2_FAPI_RC_TRY_AGAIN;
604             } else {
605                 /* Certificate not appropriate for current EK key type */
606                 command->cert_count -= 1;
607                 SAFE_FREE(command->pem_cert);
608                 if (command->cert_count > 0) {
609                     /* Check next certificate */
610                     context->state = PROVISION_GET_CERT_NV;
611                     return TSS2_FAPI_RC_TRY_AGAIN;
612                 }
613             }
614 
615             goto_error(r, TSS2_FAPI_RC_NO_CERT, "No EK certificate found.",
616                        error_cleanup);
617 
618         statecase(context->state, PROVISION_PREPARE_READ_ROOT_CERT);
619             /* Prepare reading of root certificate. */
620             root_ca_file = getenv("FAPI_TEST_ROOT_CERT");
621             if (!root_ca_file) {
622                 context->state = PROVISION_EK_CHECK_CERT;
623                 return TSS2_FAPI_RC_TRY_AGAIN;
624             }
625             r = ifapi_io_read_async(&context->io, root_ca_file);
626             return_try_again(r);
627             goto_if_error2(r, "Reading certificate %s", error_cleanup, root_ca_file);
628 
629 	        fallthrough;
630 
631         statecase(context->state, PROVISION_READ_ROOT_CERT);
632             r = ifapi_io_read_finish(&context->io, (uint8_t **) &command->root_crt, NULL);
633             return_try_again(r);
634             goto_if_error(r, "Reading root certificate failed", error_cleanup);
635 
636             fallthrough;
637 
638         statecase(context->state, PROVISION_EK_CHECK_CERT);
639             /* The EK certificate will be verified against the FAPI list of root certificates. */
640             r = ifapi_verify_ek_cert(command->root_crt, command->intermed_crt, command->pem_cert);
641             SAFE_FREE(command->root_crt);
642             SAFE_FREE(command->intermed_crt);
643             goto_if_error2(r, "Verify EK certificate", error_cleanup);
644 
645             fallthrough;
646 
647         statecase(context->state, PROVISION_EK_WRITE_PREPARE);
648             pkeyObject->objectType = IFAPI_KEY_OBJ;
649             pkeyObject->system = command->public_templ.system;
650             strdup_check(pkeyObject->misc.key.certificate, command->pem_cert, r, error_cleanup);
651             SAFE_FREE(command->pem_cert);
652 
653             /* Perform esys serialization if necessary */
654             r = ifapi_esys_serialize_object(context->esys,
655                     pkeyObject);
656             goto_if_error(r, "Prepare serialization", error_cleanup);
657 
658             /* Start writing the EK to the key store */
659             r = ifapi_keystore_store_async(&context->keystore, &context->io, "HE/EK",
660                     pkeyObject);
661             goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "HE/EK");
662 
663             fallthrough;
664 
665         statecase(context->state, PROVISION_EK_WRITE);
666             /* Finish writing the EK to the key store */
667             r = ifapi_keystore_store_finish(&context->keystore, &context->io);
668             return_try_again(r);
669             goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
670 
671             /* Clean objects used for EK computation */
672             ifapi_cleanup_ifapi_object(pkeyObject);
673             memset(&command->public_templ, 0, sizeof(IFAPI_KEY_TEMPLATE));
674             SAFE_FREE(hierarchy->misc.hierarchy.description);
675 
676             /*
677              * Adaption of the lockout hierarchy to the passed parameters
678              * and the current profile.
679              */
680             ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_LOCKOUT);
681             strdup_check(hierarchy->misc.hierarchy.description, "Lockout Hierarchy",
682                     r, error_cleanup);
683 
684             if (!command->authValueLockout ||
685                 strcmp(command->authValueLockout, "") == 0) {
686                 context->state = PROVISION_LOCKOUT_CHANGE_POLICY;
687                 /* Auth value of lockout hierarchy will not be changed. */
688                 return TSS2_FAPI_RC_TRY_AGAIN;
689             }
690 
691             if (strlen(command->authValueLockout) > sizeof(TPMU_HA)) {
692                 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
693                         "Password too long.", error_cleanup);
694             }
695             /* Copy auth value into context. */
696             memcpy(&command->hierarchy_auth.buffer[0],
697                    command->authValueLockout, strlen(command->authValueLockout));
698             command->hierarchy_auth.size = strlen(command->authValueLockout);
699             context->state = PROVISION_CHANGE_LOCKOUT_AUTH;
700             return TSS2_FAPI_RC_TRY_AGAIN;
701 
702         statecase(context->state, PROVISION_WAIT_FOR_SRK_PERSISTENT);
703             r = Esys_EvictControl_Finish(context->esys, &pkeyObject->handle);
704             return_try_again(r);
705             goto_if_error(r, "Evict control failed", error_cleanup);
706 
707             /* The SRK was made persistent and can be written to key store. */
708             context->state = PROVISION_SRK_WRITE_PREPARE;
709             return TSS2_FAPI_RC_TRY_AGAIN;
710 
711         statecase(context->state, PROVISION_WAIT_FOR_EK_PERSISTENT);
712             r = Esys_EvictControl_Finish(context->esys, &pkeyObject->handle);
713             return_try_again(r);
714             goto_if_error(r, "Evict control failed", error_cleanup);
715 
716             context->state = PROVISION_INIT_GET_CAP2;
717             return TSS2_FAPI_RC_TRY_AGAIN;
718 
719         statecase(context->state, PROVISION_CHANGE_LOCKOUT_AUTH);
720 
721             /* If a lockout auth value is provided by profile, the auth value
722                if the hierarchy will be changed asynchronous. */
723             r = ifapi_change_auth_hierarchy(context, ESYS_TR_RH_LOCKOUT,
724                     &command->hierarchy, &command->hierarchy_auth);
725             return_try_again(r);
726             goto_if_error(r, "Change auth hierarchy.", error_cleanup);
727 
728             context->state = PROVISION_LOCKOUT_CHANGE_POLICY;
729             fallthrough;
730 
731         statecase(context->state, PROVISION_LOCKOUT_CHANGE_POLICY);
732             /* If a lockout policy is provided by profile, the policy will be
733                assigned to lockout hierarchy asynchronous. */
734             r = ifapi_change_policy_hierarchy(context, ESYS_TR_RH_LOCKOUT,
735                     hierarchy, defaultProfile->lockout_policy);
736             return_try_again(r);
737             goto_if_error(r, "Change policy LOCKOUT", error_cleanup);
738 
739             /* Start writing the lockout hierarchy object to the key store */
740             r = ifapi_keystore_store_async(&context->keystore, &context->io, "/LOCKOUT",
741                     &command->hierarchy);
742             goto_if_error_reset_state(r, "Could not open: %sh",
743                     error_cleanup, "/LOCKOUT");
744 
745             context->state = PROVISION_WRITE_LOCKOUT;
746             fallthrough;
747 
748         statecase(context->state, PROVISION_WRITE_LOCKOUT);
749             /* Finish writing the lockout hierarchy to the key store */
750             r = ifapi_keystore_store_finish(&context->keystore, &context->io);
751             return_try_again(r);
752             goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
753 
754             SAFE_FREE(hierarchy->misc.hierarchy.description);
755 
756             /*
757              * Adaption of the Endorsement hierarchy to the passed parameters
758              * and the current profile.
759              */
760             ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_ENDORSEMENT);
761             strdup_check(hierarchy->misc.hierarchy.description,
762                     "Endorsement Hierarchy", r, error_cleanup);
763 
764             context->state = PROVISION_CHANGE_EH_CHECK;
765             fallthrough;
766 
767         statecase(context->state, PROVISION_CHANGE_EH_CHECK);
768             if (command->authValueEh) {
769                 context->state = PROVISION_CHANGE_EH_AUTH;
770                 /* Save auth value of endorsement hierarchy in context. */
771                 memcpy(&command->hierarchy_auth.buffer[0], command->authValueEh,
772                        strlen(command->authValueEh));
773                 command->hierarchy_auth.size = strlen(command->authValueEh);
774             } else {
775                 /* Auth value of lockout hierarchy will not be changed. */
776                 context->state = PROVISION_EH_CHANGE_POLICY;
777                 return TSS2_FAPI_RC_TRY_AGAIN;
778             }
779             context->state = PROVISION_CHANGE_EH_AUTH;
780             fallthrough;
781 
782         statecase(context->state, PROVISION_CHANGE_EH_AUTH);
783             /* If an endorsement hierarchy auth value is provided by profile,
784                the auth value will be changed asynchronous. */
785             r = ifapi_change_auth_hierarchy(context, ESYS_TR_RH_ENDORSEMENT,
786                     &command->hierarchy, &command->hierarchy_auth);
787             return_try_again(r);
788             goto_if_error(r, "Change auth hierarchy.", error_cleanup);
789 
790             context->state = PROVISION_EH_CHANGE_POLICY;
791             fallthrough;
792 
793         statecase(context->state, PROVISION_EH_CHANGE_POLICY);
794             /* If an endorsement hierarchy policy is provided by profile,
795                the policy will be assigned asynchronous. */
796             r = ifapi_change_policy_hierarchy(context, ESYS_TR_RH_ENDORSEMENT,
797                     hierarchy, defaultProfile->eh_policy);
798             return_try_again(r);
799             goto_if_error(r, "Change policy EH", error_cleanup);
800 
801             /* Start writing the endorsement hierarchy object to the key store */
802             r = ifapi_keystore_store_async(&context->keystore, &context->io, "/HE",
803                     &command->hierarchy);
804             goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "/HE");
805 
806             context->state = PROVISION_WRITE_EH;
807             fallthrough;
808 
809         statecase(context->state, PROVISION_WRITE_EH);
810             /* Finish writing the endorsement hierarchy to the key store */
811             r = ifapi_keystore_store_finish(&context->keystore, &context->io);
812             return_try_again(r);
813             return_if_error_reset_state(r, "write_finish failed");
814 
815             SAFE_FREE(hierarchy->misc.hierarchy.description);
816 
817             /*
818              * Adaption of the owner hierarchy to the passed parameters
819              * and the current profile.
820              */
821             ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
822             strdup_check(hierarchy->misc.hierarchy.description,
823                    "Owner Hierarchy", r, error_cleanup);
824 
825             context->state = PROVISION_CHANGE_SH_CHECK;
826             fallthrough;
827 
828         statecase(context->state, PROVISION_CHANGE_SH_CHECK);
829             if (command->authValueSh) {
830                 context->state = PROVISION_CHANGE_SH_AUTH;
831                 /* Save auth value of owner hierarchy in context. */
832                 memcpy(&command->hierarchy_auth.buffer[0], command->authValueSh,
833                        strlen(command->authValueSh));
834                 command->hierarchy_auth.size = strlen(command->authValueSh);
835                     context->state = PROVISION_CHANGE_SH_AUTH;
836             } else {
837                 /* Auth value of owner hierarchy will not be changed. */
838                 context->state = PROVISION_SH_CHANGE_POLICY;
839                 return TSS2_FAPI_RC_TRY_AGAIN;
840             }
841             context->state = PROVISION_CHANGE_SH_AUTH;
842             fallthrough;
843 
844         statecase(context->state, PROVISION_CHANGE_SH_AUTH);
845             /* If an owner hierarchy auth value is provided by profile,
846                the auth value will be changed asynchronous. */
847             r = ifapi_change_auth_hierarchy(context, ESYS_TR_RH_OWNER,
848                     &command->hierarchy, &command->hierarchy_auth);
849             return_try_again(r);
850             goto_if_error(r, "Change auth hierarchy.", error_cleanup);
851 
852             context->state = PROVISION_SH_CHANGE_POLICY;
853             fallthrough;
854 
855         statecase(context->state, PROVISION_SH_CHANGE_POLICY);
856             /* If an owner hierarchy policy is provided by profile,
857                the policy will be assigned asynchronous. */
858             r = ifapi_change_policy_hierarchy(context, ESYS_TR_RH_OWNER,
859                     hierarchy, defaultProfile->sh_policy);
860             return_try_again(r);
861             goto_if_error(r, "Change policy SH", error_cleanup);
862 
863             /* Start writing the owner hierarchy object to the key store */
864             r = ifapi_keystore_store_async(&context->keystore, &context->io, "/HS",
865                     &command->hierarchy);
866             goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "/HS");
867             context->state = PROVISION_WRITE_SH;
868             fallthrough;
869 
870         statecase(context->state, PROVISION_WRITE_SH);
871             /* The onwer hierarchy object will be written to key store. */
872             r = ifapi_keystore_store_finish(&context->keystore, &context->io);
873             return_try_again(r);
874             goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
875             fallthrough;
876 
877         statecase(context->state, PROVISION_FINISHED);
878             if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
879                 /* Prepare the flushing of a non persistent SRK. */
880                 r = Esys_FlushContext_Async(context->esys, context->srk_handle);
881                 goto_if_error(r, "Flush SRK", error_cleanup);
882             }
883             fallthrough;
884 
885         /* Flush the SRK if not persistent */
886         statecase(context->state, PROVISION_FLUSH_SRK);
887             if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
888                 r = Esys_FlushContext_Finish(context->esys);
889                 try_again_or_error_goto(r, "Flush SRK", error_cleanup);
890 
891                 context->srk_handle = ESYS_TR_NONE;
892 
893             }
894             if (!context->ek_persistent && context->ek_handle != ESYS_TR_NONE) {
895                  /* Prepare the flushing of a non persistent EK. */
896                 r = Esys_FlushContext_Async(context->esys, context->ek_handle);
897                 goto_if_error(r, "Flush EK", error_cleanup);
898             }
899             fallthrough;
900 
901          /* Flush the EK if not persistent */
902         statecase(context->state, PROVISION_FLUSH_EK);
903             if (!context->ek_persistent && context->ek_handle != ESYS_TR_NONE) {
904                 r = Esys_FlushContext_Finish(context->esys);
905                 try_again_or_error_goto(r, "Flush EK", error_cleanup);
906 
907                 context->ek_handle = ESYS_TR_NONE;
908             }
909 
910             context->state = _FAPI_STATE_INIT;
911             break;
912 
913         /*
914          * The vendor ID stored in the TPM has to be read to check whether
915          * a special certificate handling is needed.
916          */
917         statecase(context->state, PROVISION_CHECK_FOR_VENDOR_CERT);
918             /* Prepare reading the vendor ID */
919             r = Esys_GetCapability_Async(context->esys,
920                                          ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
921                                          TPM2_CAP_TPM_PROPERTIES, TPM2_PT_MANUFACTURER, 1);
922             goto_if_error(r, "Esys_GetCapability_Async", error_cleanup);
923 
924             fallthrough;
925 
926         statecase(context->state, PROVISION_GET_VENDOR);
927             /* Get the vendor ID asynchronous. */
928             r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
929             return_try_again(r);
930             goto_if_error_reset_state(r, "GetCapablity_Finish", error_cleanup);
931 
932             if ((*capabilityData)->data.tpmProperties.tpmProperty[0].value == VENDOR_INTC) {
933                 /* Get INTEL certificate for EK public hash via web */
934                 uint8_t *cert_buffer = NULL;
935                 size_t cert_size;
936                 TPM2B_PUBLIC public;
937                 r = ifapi_get_intl_ek_certificate(context, &pkey->public, &cert_buffer,
938                                                   &cert_size);
939                 goto_if_error_reset_state(r, "Get certificates", error_cleanup);
940 
941                 r = ifapi_cert_to_pem(cert_buffer, cert_size, &command->pem_cert,
942                                       NULL, &public);
943                 SAFE_FREE(cert_buffer);
944                 goto_if_error_reset_state(r, "Convert certificate buffer to PEM.",
945                                           error_cleanup);
946             }
947             SAFE_FREE(*capabilityData);
948             context->state = PROVISION_EK_WRITE_PREPARE;
949             return TSS2_FAPI_RC_TRY_AGAIN;
950 
951         statecasedefault(context->state);
952     }
953 
954 error_cleanup:
955     /* Primaries might not have been flushed in error cases */
956     ifapi_primary_clean(context);
957     SAFE_FREE(command->root_crt);
958     SAFE_FREE(*capabilityData);
959     SAFE_FREE(hierarchy->misc.hierarchy.description);
960     SAFE_FREE(command->authValueLockout);
961     SAFE_FREE(command->authValueEh);
962     SAFE_FREE(command->authValueSh);
963     SAFE_FREE(command->pem_cert);
964     SAFE_FREE(certData);
965     SAFE_FREE(nvPublic);
966     LOG_TRACE("finished");
967     return r;
968 }
969