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