xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/api/Fapi_CreateNv.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 <string.h>
12*758e9fbaSOystein Eftevaag #include <stdio.h>
13*758e9fbaSOystein Eftevaag #include <unistd.h>
14*758e9fbaSOystein Eftevaag #include <stdlib.h>
15*758e9fbaSOystein Eftevaag #include <errno.h>
16*758e9fbaSOystein Eftevaag 
17*758e9fbaSOystein Eftevaag #include "tss2_fapi.h"
18*758e9fbaSOystein Eftevaag #include "fapi_int.h"
19*758e9fbaSOystein Eftevaag #include "fapi_util.h"
20*758e9fbaSOystein Eftevaag #include "fapi_policy.h"
21*758e9fbaSOystein Eftevaag #include "tss2_esys.h"
22*758e9fbaSOystein Eftevaag #define LOGMODULE fapi
23*758e9fbaSOystein Eftevaag #include "util/log.h"
24*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
25*758e9fbaSOystein Eftevaag 
26*758e9fbaSOystein Eftevaag /** One-Call function for Fapi_CreateNv
27*758e9fbaSOystein Eftevaag  *
28*758e9fbaSOystein Eftevaag  * This command creates an NV index in the TPM using a given path and type.
29*758e9fbaSOystein Eftevaag  *
30*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT
31*758e9fbaSOystein Eftevaag  * @param[in] path The path to the new NV index
32*758e9fbaSOystein Eftevaag  * @param[in] type The intended type of the new NV index. May be NULL
33*758e9fbaSOystein Eftevaag  * @param[in] size The size of the new NV index in bytes. May be 0 if the size
34*758e9fbaSOystein Eftevaag  *            is inferred from the type
35*758e9fbaSOystein Eftevaag  * @param[in] policyPath The path to the policy that is associated with the new
36*758e9fbaSOystein Eftevaag  *            NV index. May be NULL
37*758e9fbaSOystein Eftevaag  * @param[in] authValue The authorization value that is associated with the new
38*758e9fbaSOystein Eftevaag  *            NV index. May be NULL
39*758e9fbaSOystein Eftevaag  *
40*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: if the function call was a success.
41*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
42*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
43*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if an NV index already exists at
44*758e9fbaSOystein Eftevaag  *         path.
45*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE: if type is non-NULL but invalid or does not
46*758e9fbaSOystein Eftevaag  *         match the size.
47*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath is non-NULL and does not map to
48*758e9fbaSOystein Eftevaag  *         a FAPI policy or if path dos not refer to a valid NV index path.
49*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
50*758e9fbaSOystein Eftevaag  *         operation already pending.
51*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
52*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
53*758e9fbaSOystein Eftevaag  *         internal operations or return parameters.
54*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
55*758e9fbaSOystein Eftevaag  *         config file.
56*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
57*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
58*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
59*758e9fbaSOystein Eftevaag  *         during authorization.
60*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
61*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
62*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_NV_TOO_SMALL if too many NV handles are defined.
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_POLICY_UNKNOWN if policy search for a certain policy digest
67*758e9fbaSOystein Eftevaag  *         was not successful.
68*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
69*758e9fbaSOystein Eftevaag  */
70*758e9fbaSOystein Eftevaag TSS2_RC
Fapi_CreateNv(FAPI_CONTEXT * context,char const * path,char const * type,size_t size,char const * policyPath,char const * authValue)71*758e9fbaSOystein Eftevaag Fapi_CreateNv(
72*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
73*758e9fbaSOystein Eftevaag     char   const *path,
74*758e9fbaSOystein Eftevaag     char   const *type,
75*758e9fbaSOystein Eftevaag     size_t size,
76*758e9fbaSOystein Eftevaag     char   const *policyPath,
77*758e9fbaSOystein Eftevaag     char   const *authValue)
78*758e9fbaSOystein Eftevaag {
79*758e9fbaSOystein Eftevaag     LOG_TRACE("called for context:%p", context);
80*758e9fbaSOystein Eftevaag 
81*758e9fbaSOystein Eftevaag     TSS2_RC r, r2;
82*758e9fbaSOystein Eftevaag 
83*758e9fbaSOystein Eftevaag     /* Check for NULL parameters */
84*758e9fbaSOystein Eftevaag     check_not_null(context);
85*758e9fbaSOystein Eftevaag     check_not_null(path);
86*758e9fbaSOystein Eftevaag 
87*758e9fbaSOystein Eftevaag     /* Check whether TCTI and ESYS are initialized */
88*758e9fbaSOystein Eftevaag     return_if_null(context->esys, "Command can't be executed in none TPM mode.",
89*758e9fbaSOystein Eftevaag                    TSS2_FAPI_RC_NO_TPM);
90*758e9fbaSOystein Eftevaag 
91*758e9fbaSOystein Eftevaag     /* If the async state automata of FAPI shall be tested, then we must not set
92*758e9fbaSOystein Eftevaag        the timeouts of ESYS to blocking mode.
93*758e9fbaSOystein Eftevaag        During testing, the mssim tcti will ensure multiple re-invocations.
94*758e9fbaSOystein Eftevaag        Usually however the synchronous invocations of FAPI shall instruct ESYS
95*758e9fbaSOystein Eftevaag        to block until a result is available. */
96*758e9fbaSOystein Eftevaag #ifndef TEST_FAPI_ASYNC
97*758e9fbaSOystein Eftevaag     r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
98*758e9fbaSOystein Eftevaag     return_if_error_reset_state(r, "Set Timeout to blocking");
99*758e9fbaSOystein Eftevaag #endif /* TEST_FAPI_ASYNC */
100*758e9fbaSOystein Eftevaag 
101*758e9fbaSOystein Eftevaag     r = Fapi_CreateNv_Async(context, path, type, size,
102*758e9fbaSOystein Eftevaag                             policyPath, authValue);
103*758e9fbaSOystein Eftevaag     return_if_error_reset_state(r, "NV_CreateWithTemplate");
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_CreateNv_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, "NV_CreateWithTemplate");
121*758e9fbaSOystein Eftevaag 
122*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
123*758e9fbaSOystein Eftevaag }
124*758e9fbaSOystein Eftevaag 
125*758e9fbaSOystein Eftevaag /** Asynchronous function for Fapi_CreateNv
126*758e9fbaSOystein Eftevaag  *
127*758e9fbaSOystein Eftevaag  * This command creates an NV index in the TPM using a given path and type.
128*758e9fbaSOystein Eftevaag  *
129*758e9fbaSOystein Eftevaag  * Call Fapi_CreateNv_Finish to finish the execution of this command.
130*758e9fbaSOystein Eftevaag  *
131*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT
132*758e9fbaSOystein Eftevaag  * @param[in] path The path to the new NV index
133*758e9fbaSOystein Eftevaag  * @param[in] type The intended type of the new NV index. May be NULL
134*758e9fbaSOystein Eftevaag  * @param[in] size The size of the new NV index in bytes. May be 0 if the size
135*758e9fbaSOystein Eftevaag  *            is inferred from the type
136*758e9fbaSOystein Eftevaag  * @param[in] policyPath The path to the policy that is associated with the new
137*758e9fbaSOystein Eftevaag  *            NV index. May be NULL
138*758e9fbaSOystein Eftevaag  * @param[in] authValue The authorization value that is associated with the new
139*758e9fbaSOystein Eftevaag  *            NV index. May be NULL
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 or path is NULL.
143*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
144*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if an NV index already exists at
145*758e9fbaSOystein Eftevaag  *         path.
146*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE: if type is non-NULL but invalid or does not
147*758e9fbaSOystein Eftevaag  *         match the size.
148*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath is non-NULL and does not map to
149*758e9fbaSOystein Eftevaag  *         a FAPI policy or if path dos not refer to a valid NV index path.
150*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
151*758e9fbaSOystein Eftevaag  *         operation already pending.
152*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
153*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
154*758e9fbaSOystein Eftevaag  *         internal operations or return parameters.
155*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
156*758e9fbaSOystein Eftevaag  *         config file.
157*758e9fbaSOystein Eftevaag  */
158*758e9fbaSOystein Eftevaag TSS2_RC
Fapi_CreateNv_Async(FAPI_CONTEXT * context,char const * path,char const * type,size_t size,char const * policyPath,char const * authValue)159*758e9fbaSOystein Eftevaag Fapi_CreateNv_Async(
160*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
161*758e9fbaSOystein Eftevaag     char   const *path,
162*758e9fbaSOystein Eftevaag     char   const *type,
163*758e9fbaSOystein Eftevaag     size_t size,
164*758e9fbaSOystein Eftevaag     char   const *policyPath,
165*758e9fbaSOystein Eftevaag     char   const *authValue)
166*758e9fbaSOystein Eftevaag {
167*758e9fbaSOystein Eftevaag     LOG_TRACE("called for context:%p", context);
168*758e9fbaSOystein Eftevaag     LOG_TRACE("path: %s", path);
169*758e9fbaSOystein Eftevaag     LOG_TRACE("type: %s", type);
170*758e9fbaSOystein Eftevaag     LOG_TRACE("size: %zi", size);
171*758e9fbaSOystein Eftevaag     LOG_TRACE("policyPath: %s", policyPath);
172*758e9fbaSOystein Eftevaag     LOG_TRACE("authValue: %s", authValue);
173*758e9fbaSOystein Eftevaag 
174*758e9fbaSOystein Eftevaag     TSS2_RC r;
175*758e9fbaSOystein Eftevaag 
176*758e9fbaSOystein Eftevaag     /* Check for NULL parameters */
177*758e9fbaSOystein Eftevaag     check_not_null(context);
178*758e9fbaSOystein Eftevaag     check_not_null(path);
179*758e9fbaSOystein Eftevaag 
180*758e9fbaSOystein Eftevaag     /* Helpful alias pointers */
181*758e9fbaSOystein Eftevaag     IFAPI_NV_Cmds * nvCmd = &(context->nv_cmd);
182*758e9fbaSOystein Eftevaag     TPM2B_AUTH *auth = &nvCmd->auth;
183*758e9fbaSOystein Eftevaag     IFAPI_NV * miscNv = &(nvCmd->nv_object.misc.nv);
184*758e9fbaSOystein Eftevaag 
185*758e9fbaSOystein Eftevaag     /* Reset all context-internal session state information. */
186*758e9fbaSOystein Eftevaag     r = ifapi_session_init(context);
187*758e9fbaSOystein Eftevaag     return_if_error(r, "Initialize NV_CreateNv");
188*758e9fbaSOystein Eftevaag 
189*758e9fbaSOystein Eftevaag     /* First check whether an existing object would be overwritten */
190*758e9fbaSOystein Eftevaag     r = ifapi_keystore_check_overwrite(&context->keystore, &context->io,
191*758e9fbaSOystein Eftevaag                                        path);
192*758e9fbaSOystein Eftevaag     return_if_error2(r, "Check overwrite %s", path);
193*758e9fbaSOystein Eftevaag 
194*758e9fbaSOystein Eftevaag     /* Copy parameters to context for use during _Finish. */
195*758e9fbaSOystein Eftevaag     memset(&context->nv_cmd, 0, sizeof(IFAPI_NV_Cmds));
196*758e9fbaSOystein Eftevaag     if (authValue) {
197*758e9fbaSOystein Eftevaag         if (strlen(authValue) > sizeof(TPMU_HA)) {
198*758e9fbaSOystein Eftevaag             return_error(TSS2_FAPI_RC_BAD_VALUE, "AuthValue too long");
199*758e9fbaSOystein Eftevaag         }
200*758e9fbaSOystein Eftevaag 
201*758e9fbaSOystein Eftevaag         auth->size = strlen(authValue);
202*758e9fbaSOystein Eftevaag         memcpy(&auth->buffer[0], authValue, auth->size);
203*758e9fbaSOystein Eftevaag     } else {
204*758e9fbaSOystein Eftevaag         auth->size = 0;
205*758e9fbaSOystein Eftevaag     }
206*758e9fbaSOystein Eftevaag     strdup_check(nvCmd->nvPath, path, r, error_cleanup);
207*758e9fbaSOystein Eftevaag     nvCmd->numBytes = size;
208*758e9fbaSOystein Eftevaag     nvCmd->nv_object.objectType = IFAPI_NV_OBJ;
209*758e9fbaSOystein Eftevaag     strdup_check(miscNv->policyInstance, policyPath, r, error_cleanup);
210*758e9fbaSOystein Eftevaag 
211*758e9fbaSOystein Eftevaag     /* Set the flags of the NV index to be created. If no type is given the empty-string
212*758e9fbaSOystein Eftevaag        default type flags are set. */
213*758e9fbaSOystein Eftevaag     r = ifapi_set_nv_flags(type ? type : "", &nvCmd->public_templ,
214*758e9fbaSOystein Eftevaag                            policyPath);
215*758e9fbaSOystein Eftevaag     goto_if_error(r, "Set key flags for NV object", error_cleanup);
216*758e9fbaSOystein Eftevaag 
217*758e9fbaSOystein Eftevaag     /* Initialize the context state for this operation. */
218*758e9fbaSOystein Eftevaag     context->state = NV_CREATE_READ_PROFILE;
219*758e9fbaSOystein Eftevaag     LOG_TRACE("finished");
220*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
221*758e9fbaSOystein Eftevaag 
222*758e9fbaSOystein Eftevaag error_cleanup:
223*758e9fbaSOystein Eftevaag     /* Cleanup duplicated input parameters that were copied before. */
224*758e9fbaSOystein Eftevaag     SAFE_FREE(nvCmd->nvPath);
225*758e9fbaSOystein Eftevaag     SAFE_FREE(miscNv->policyInstance);
226*758e9fbaSOystein Eftevaag     return r;
227*758e9fbaSOystein Eftevaag }
228*758e9fbaSOystein Eftevaag 
229*758e9fbaSOystein Eftevaag /** Asynchronous finish function for Fapi_CreateNv
230*758e9fbaSOystein Eftevaag  *
231*758e9fbaSOystein Eftevaag  * This function should be called after a previous Fapi_CreateNv_Async.
232*758e9fbaSOystein Eftevaag  *
233*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT
234*758e9fbaSOystein Eftevaag  *
235*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: if the function call was a success.
236*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
237*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
238*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
239*758e9fbaSOystein Eftevaag  *         operation already pending.
240*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
241*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
242*758e9fbaSOystein Eftevaag  *         internal operations or return parameters.
243*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
244*758e9fbaSOystein Eftevaag  *         complete. Call this function again later.
245*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
246*758e9fbaSOystein Eftevaag  *         the function.
247*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
248*758e9fbaSOystein Eftevaag  *         during authorization.
249*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
250*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
251*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_PATH if the used path in inappropriate-
252*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_NV_TOO_SMALL if too many NV handles are defined.
253*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
254*758e9fbaSOystein Eftevaag  *         is not set.
255*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
256*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
257*758e9fbaSOystein Eftevaag  *         was not successful.
258*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
259*758e9fbaSOystein Eftevaag  */
260*758e9fbaSOystein Eftevaag TSS2_RC
Fapi_CreateNv_Finish(FAPI_CONTEXT * context)261*758e9fbaSOystein Eftevaag Fapi_CreateNv_Finish(
262*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context)
263*758e9fbaSOystein Eftevaag {
264*758e9fbaSOystein Eftevaag     LOG_TRACE("called for context:%p", context);
265*758e9fbaSOystein Eftevaag 
266*758e9fbaSOystein Eftevaag     TSS2_RC r;
267*758e9fbaSOystein Eftevaag     ESYS_TR nvHandle;
268*758e9fbaSOystein Eftevaag 
269*758e9fbaSOystein Eftevaag     /* Check for NULL parameters */
270*758e9fbaSOystein Eftevaag     check_not_null(context);
271*758e9fbaSOystein Eftevaag 
272*758e9fbaSOystein Eftevaag     /* Helpful alias pointers */
273*758e9fbaSOystein Eftevaag     IFAPI_NV_Cmds * nvCmd = &(context->nv_cmd);
274*758e9fbaSOystein Eftevaag     TPM2B_AUTH *auth = &nvCmd->auth;
275*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *hierarchy = &nvCmd->auth_object;
276*758e9fbaSOystein Eftevaag     IFAPI_NV * miscNv = &(nvCmd->nv_object.misc.nv);
277*758e9fbaSOystein Eftevaag     TPM2B_NV_PUBLIC *publicInfo = &miscNv->public;
278*758e9fbaSOystein Eftevaag     TPM2B_DIGEST * authPolicy = &(miscNv->public.nvPublic.authPolicy);
279*758e9fbaSOystein Eftevaag     TPMS_POLICY * policy = &(context->policy.policy);
280*758e9fbaSOystein Eftevaag     TPMS_POLICY ** nvCmdPolicy = &nvCmd->nv_object.policy;
281*758e9fbaSOystein Eftevaag     ESYS_TR auth_session;
282*758e9fbaSOystein Eftevaag 
283*758e9fbaSOystein Eftevaag     switch (context->state) {
284*758e9fbaSOystein Eftevaag         statecase(context->state, NV_CREATE_READ_PROFILE)
285*758e9fbaSOystein Eftevaag             /* Mix the provided flags provided via the type with with template
286*758e9fbaSOystein Eftevaag                of the current active crypto profile. */
287*758e9fbaSOystein Eftevaag             r = ifapi_merge_profile_into_nv_template(context,
288*758e9fbaSOystein Eftevaag                     &nvCmd->public_templ);
289*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "Merge profile", error_cleanup);
290*758e9fbaSOystein Eftevaag 
291*758e9fbaSOystein Eftevaag             /* Store information from template in context */
292*758e9fbaSOystein Eftevaag             miscNv->description = NULL;
293*758e9fbaSOystein Eftevaag             publicInfo->nvPublic = nvCmd->public_templ.public;
294*758e9fbaSOystein Eftevaag 
295*758e9fbaSOystein Eftevaag             /* Check that the hierarchy for the NV index to be created is "Owner".
296*758e9fbaSOystein Eftevaag                FAPI does not allow the creation of "Platform" NV indexes. */
297*758e9fbaSOystein Eftevaag             if (nvCmd->public_templ.hierarchy == TPM2_RH_OWNER) {
298*758e9fbaSOystein Eftevaag                 miscNv->hierarchy = ESYS_TR_RH_OWNER;
299*758e9fbaSOystein Eftevaag             } else {
300*758e9fbaSOystein Eftevaag                 goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong hierarchy", error_cleanup);
301*758e9fbaSOystein Eftevaag             }
302*758e9fbaSOystein Eftevaag 
303*758e9fbaSOystein Eftevaag             /* Load the Storage Hierarchy "Owner" meta data for used during
304*758e9fbaSOystein Eftevaag                NV creation authorization. */
305*758e9fbaSOystein Eftevaag             r = ifapi_keystore_load_async(&context->keystore, &context->io, "HS");
306*758e9fbaSOystein Eftevaag             return_if_error_reset_state(r, "Could not open storage hierarchy  HS");
307*758e9fbaSOystein Eftevaag             fallthrough;
308*758e9fbaSOystein Eftevaag 
309*758e9fbaSOystein Eftevaag         statecase(context->state, NV_CREATE_READ_HIERARCHY)
310*758e9fbaSOystein Eftevaag             r = ifapi_keystore_load_finish(&context->keystore, &context->io,
311*758e9fbaSOystein Eftevaag                                            &nvCmd->auth_object);
312*758e9fbaSOystein Eftevaag             return_try_again(r);
313*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "read_finish failed", error_cleanup);
314*758e9fbaSOystein Eftevaag 
315*758e9fbaSOystein Eftevaag             /* Initialize the esys object for the hierarchy. */
316*758e9fbaSOystein Eftevaag             r = ifapi_initialize_object(context->esys, &nvCmd->auth_object);
317*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
318*758e9fbaSOystein Eftevaag 
319*758e9fbaSOystein Eftevaag             nvCmd->auth_object.handle
320*758e9fbaSOystein Eftevaag                 = miscNv->hierarchy;
321*758e9fbaSOystein Eftevaag 
322*758e9fbaSOystein Eftevaag             /* Check if a policy is set for the NV index to be created. */
323*758e9fbaSOystein Eftevaag             if (miscNv->policyInstance &&
324*758e9fbaSOystein Eftevaag                     strcmp(miscNv->policyInstance, "") != 0)
325*758e9fbaSOystein Eftevaag                 nvCmd->skip_policy_computation = false;
326*758e9fbaSOystein Eftevaag             else
327*758e9fbaSOystein Eftevaag                 nvCmd->skip_policy_computation = true;
328*758e9fbaSOystein Eftevaag             fallthrough;
329*758e9fbaSOystein Eftevaag 
330*758e9fbaSOystein Eftevaag         statecase(context->state, NV_CREATE_CALCULATE_POLICY)
331*758e9fbaSOystein Eftevaag             if (!nvCmd->skip_policy_computation) {
332*758e9fbaSOystein Eftevaag                 /* Calculate the policy as read for the keystore. */
333*758e9fbaSOystein Eftevaag                 r = ifapi_calculate_tree(context,
334*758e9fbaSOystein Eftevaag                                          miscNv->policyInstance,
335*758e9fbaSOystein Eftevaag                                          policy,
336*758e9fbaSOystein Eftevaag                                          miscNv->public.nvPublic.nameAlg,
337*758e9fbaSOystein Eftevaag                                          &context->policy.digest_idx,
338*758e9fbaSOystein Eftevaag                                          &context->policy.hash_size);
339*758e9fbaSOystein Eftevaag                 return_try_again(r);
340*758e9fbaSOystein Eftevaag 
341*758e9fbaSOystein Eftevaag                 goto_if_error2(r, "Calculate policy tree %s", error_cleanup,
342*758e9fbaSOystein Eftevaag                                context->cmd.Key_Create.policyPath);
343*758e9fbaSOystein Eftevaag 
344*758e9fbaSOystein Eftevaag                 /* Store the calculated policy in the NV object */
345*758e9fbaSOystein Eftevaag                 *nvCmdPolicy = calloc(1,
346*758e9fbaSOystein Eftevaag                         sizeof(TPMS_POLICY));
347*758e9fbaSOystein Eftevaag                 goto_if_null(*nvCmdPolicy,
348*758e9fbaSOystein Eftevaag                         "Out of memory,", TSS2_FAPI_RC_MEMORY, error_cleanup);
349*758e9fbaSOystein Eftevaag                 **(nvCmdPolicy) = *policy;
350*758e9fbaSOystein Eftevaag 
351*758e9fbaSOystein Eftevaag                 authPolicy->size =
352*758e9fbaSOystein Eftevaag                     context->policy.hash_size;
353*758e9fbaSOystein Eftevaag                 memcpy(&authPolicy->buffer[0],
354*758e9fbaSOystein Eftevaag                        &policy->policyDigests.digests[context->policy.digest_idx].digest,
355*758e9fbaSOystein Eftevaag                        context->policy.hash_size);
356*758e9fbaSOystein Eftevaag                 LOGBLOB_TRACE(
357*758e9fbaSOystein Eftevaag                     &authPolicy->buffer[0],
358*758e9fbaSOystein Eftevaag                     context->policy.hash_size, "Create Key Policy");
359*758e9fbaSOystein Eftevaag             }
360*758e9fbaSOystein Eftevaag             fallthrough;
361*758e9fbaSOystein Eftevaag 
362*758e9fbaSOystein Eftevaag         statecase(context->state, NV_CREATE_GET_INDEX)
363*758e9fbaSOystein Eftevaag             r = ifapi_get_nv_start_index(nvCmd->nvPath,
364*758e9fbaSOystein Eftevaag                                          &publicInfo->nvPublic.nvIndex);
365*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "FAPI get handle index.", error_cleanup);
366*758e9fbaSOystein Eftevaag 
367*758e9fbaSOystein Eftevaag             /* We are searching for a new free NV-index handle. */
368*758e9fbaSOystein Eftevaag             r = ifapi_get_free_handle_async(context, &publicInfo->nvPublic.nvIndex);
369*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "FAPI get handle index.", error_cleanup);
370*758e9fbaSOystein Eftevaag             nvCmd->maxNvIndex = publicInfo->nvPublic.nvIndex + 100;
371*758e9fbaSOystein Eftevaag 
372*758e9fbaSOystein Eftevaag             fallthrough;
373*758e9fbaSOystein Eftevaag 
374*758e9fbaSOystein Eftevaag         statecase(context->state, NV_CREATE_FIND_INDEX)
375*758e9fbaSOystein Eftevaag             r = ifapi_get_free_handle_finish(context, &publicInfo->nvPublic.nvIndex,
376*758e9fbaSOystein Eftevaag                                              nvCmd->maxNvIndex);
377*758e9fbaSOystein Eftevaag             return_try_again(r);
378*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "FAPI get handle index.", error_cleanup);
379*758e9fbaSOystein Eftevaag 
380*758e9fbaSOystein Eftevaag             /* Start a authorization session for the NV creation. */
381*758e9fbaSOystein Eftevaag             context->primary_state = PRIMARY_INIT;
382*758e9fbaSOystein Eftevaag             r = ifapi_get_sessions_async(context,
383*758e9fbaSOystein Eftevaag                                          IFAPI_SESSION_GENEK | IFAPI_SESSION1,
384*758e9fbaSOystein Eftevaag                                          0, 0);
385*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "Create sessions", error_cleanup);
386*758e9fbaSOystein Eftevaag             fallthrough;
387*758e9fbaSOystein Eftevaag 
388*758e9fbaSOystein Eftevaag         statecase(context->state, NV_CREATE_WAIT_FOR_SESSION)
389*758e9fbaSOystein Eftevaag             r = ifapi_get_sessions_finish(context, &context->profiles.default_profile,
390*758e9fbaSOystein Eftevaag                                           context->profiles.default_profile.nameAlg);
391*758e9fbaSOystein Eftevaag             return_try_again(r);
392*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
393*758e9fbaSOystein Eftevaag 
394*758e9fbaSOystein Eftevaag 
395*758e9fbaSOystein Eftevaag             fallthrough;
396*758e9fbaSOystein Eftevaag 
397*758e9fbaSOystein Eftevaag         statecase(context->state, NV_CREATE_AUTHORIZE_HIERARCHY)
398*758e9fbaSOystein Eftevaag             /* Authorize with the storage hierarhcy / "owner" for NV creation. */
399*758e9fbaSOystein Eftevaag             r = ifapi_authorize_object(context, &nvCmd->auth_object, &auth_session);
400*758e9fbaSOystein Eftevaag             FAPI_SYNC(r, "Authorize hierarchy.", error_cleanup);
401*758e9fbaSOystein Eftevaag 
402*758e9fbaSOystein Eftevaag             /* Create the NV Index. */
403*758e9fbaSOystein Eftevaag             r = Esys_NV_DefineSpace_Async(context->esys,
404*758e9fbaSOystein Eftevaag                                           hierarchy->handle,
405*758e9fbaSOystein Eftevaag                                           auth_session,
406*758e9fbaSOystein Eftevaag                                           ESYS_TR_NONE,
407*758e9fbaSOystein Eftevaag                                           ESYS_TR_NONE,
408*758e9fbaSOystein Eftevaag                                           auth,
409*758e9fbaSOystein Eftevaag                                           publicInfo);
410*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, " Fapi_CreateNv_Async", error_cleanup);
411*758e9fbaSOystein Eftevaag             fallthrough;
412*758e9fbaSOystein Eftevaag 
413*758e9fbaSOystein Eftevaag         statecase(context->state, NV_CREATE_AUTH_SENT)
414*758e9fbaSOystein Eftevaag             r = Esys_NV_DefineSpace_Finish(context->esys, &nvHandle);
415*758e9fbaSOystein Eftevaag             return_try_again(r);
416*758e9fbaSOystein Eftevaag 
417*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "FAPI CreateWithTemplate_Finish", error_cleanup);
418*758e9fbaSOystein Eftevaag 
419*758e9fbaSOystein Eftevaag             /* Store whether the NV index requires a password. */
420*758e9fbaSOystein Eftevaag             nvCmd->nv_object.handle = nvHandle;
421*758e9fbaSOystein Eftevaag             if (nvCmd->auth.size > 0)
422*758e9fbaSOystein Eftevaag                 miscNv->with_auth = TPM2_YES;
423*758e9fbaSOystein Eftevaag             else
424*758e9fbaSOystein Eftevaag                 miscNv->with_auth = TPM2_NO;
425*758e9fbaSOystein Eftevaag 
426*758e9fbaSOystein Eftevaag             /* Perform esys serialization if necessary */
427*758e9fbaSOystein Eftevaag             r = ifapi_esys_serialize_object(context->esys, &nvCmd->nv_object);
428*758e9fbaSOystein Eftevaag             goto_if_error(r, "Prepare serialization", error_cleanup);
429*758e9fbaSOystein Eftevaag 
430*758e9fbaSOystein Eftevaag             /* Start writing the NV object to the key store */
431*758e9fbaSOystein Eftevaag             r = ifapi_keystore_store_async(&context->keystore, &context->io,
432*758e9fbaSOystein Eftevaag                                            nvCmd->nvPath,
433*758e9fbaSOystein Eftevaag                                            &nvCmd->nv_object);
434*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
435*758e9fbaSOystein Eftevaag                                       nvCmd->nvPath);
436*758e9fbaSOystein Eftevaag 
437*758e9fbaSOystein Eftevaag             fallthrough;
438*758e9fbaSOystein Eftevaag 
439*758e9fbaSOystein Eftevaag         statecase(context->state, NV_CREATE_WRITE)
440*758e9fbaSOystein Eftevaag             /* Finish writing the NV object to the key store */
441*758e9fbaSOystein Eftevaag             r = ifapi_keystore_store_finish(&context->keystore, &context->io);
442*758e9fbaSOystein Eftevaag             return_try_again(r);
443*758e9fbaSOystein Eftevaag             return_if_error_reset_state(r, "write_finish failed");
444*758e9fbaSOystein Eftevaag 
445*758e9fbaSOystein Eftevaag             break;
446*758e9fbaSOystein Eftevaag 
447*758e9fbaSOystein Eftevaag         statecasedefault(context->state);
448*758e9fbaSOystein Eftevaag     }
449*758e9fbaSOystein Eftevaag 
450*758e9fbaSOystein Eftevaag     context->state = _FAPI_STATE_INIT;
451*758e9fbaSOystein Eftevaag     LOG_DEBUG("success");
452*758e9fbaSOystein Eftevaag     r = TSS2_RC_SUCCESS;
453*758e9fbaSOystein Eftevaag 
454*758e9fbaSOystein Eftevaag error_cleanup:
455*758e9fbaSOystein Eftevaag     /* Cleanup any intermediate results and state stored in the context. */
456*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&nvCmd->nv_object);
457*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&nvCmd->auth_object);
458*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
459*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(context->loadKey.key_object);
460*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
461*758e9fbaSOystein Eftevaag     SAFE_FREE(miscNv->policyInstance);
462*758e9fbaSOystein Eftevaag     SAFE_FREE(nvCmd->nvPath);
463*758e9fbaSOystein Eftevaag     ifapi_session_clean(context);
464*758e9fbaSOystein Eftevaag     LOG_TRACE("finished");
465*758e9fbaSOystein Eftevaag     return r;
466*758e9fbaSOystein Eftevaag }
467