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