xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/fapi_util.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 <stdio.h>
12*758e9fbaSOystein Eftevaag #include <string.h>
13*758e9fbaSOystein Eftevaag #include <stdarg.h>
14*758e9fbaSOystein Eftevaag #include <sys/types.h>
15*758e9fbaSOystein Eftevaag #include <sys/stat.h>
16*758e9fbaSOystein Eftevaag #include <stdlib.h>
17*758e9fbaSOystein Eftevaag #include <stdio.h>
18*758e9fbaSOystein Eftevaag #include <unistd.h>
19*758e9fbaSOystein Eftevaag #include <ctype.h>
20*758e9fbaSOystein Eftevaag #include <dirent.h>
21*758e9fbaSOystein Eftevaag 
22*758e9fbaSOystein Eftevaag #include "tss2_mu.h"
23*758e9fbaSOystein Eftevaag #include "fapi_util.h"
24*758e9fbaSOystein Eftevaag #include "fapi_crypto.h"
25*758e9fbaSOystein Eftevaag #include "ifapi_helpers.h"
26*758e9fbaSOystein Eftevaag #include "ifapi_json_serialize.h"
27*758e9fbaSOystein Eftevaag #include "ifapi_json_deserialize.h"
28*758e9fbaSOystein Eftevaag #include "tpm_json_deserialize.h"
29*758e9fbaSOystein Eftevaag #include "fapi_policy.h"
30*758e9fbaSOystein Eftevaag #include "ifapi_policyutil_execute.h"
31*758e9fbaSOystein Eftevaag #define LOGMODULE fapi
32*758e9fbaSOystein Eftevaag #include "util/log.h"
33*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
34*758e9fbaSOystein Eftevaag 
35*758e9fbaSOystein Eftevaag /** State machine for flushing objects.
36*758e9fbaSOystein Eftevaag  *
37*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT.
38*758e9fbaSOystein Eftevaag  * @param[in] handle of the object to be flushed.
39*758e9fbaSOystein Eftevaag  *
40*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
41*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
42*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
43*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
44*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
45*758e9fbaSOystein Eftevaag  *         operation already pending.
46*758e9fbaSOystein Eftevaag  */
47*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_flush_object(FAPI_CONTEXT * context,ESYS_TR handle)48*758e9fbaSOystein Eftevaag ifapi_flush_object(FAPI_CONTEXT *context, ESYS_TR handle)
49*758e9fbaSOystein Eftevaag {
50*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
51*758e9fbaSOystein Eftevaag 
52*758e9fbaSOystein Eftevaag     if (handle == ESYS_TR_NONE)
53*758e9fbaSOystein Eftevaag         return r;
54*758e9fbaSOystein Eftevaag 
55*758e9fbaSOystein Eftevaag     switch (context->flush_object_state) {
56*758e9fbaSOystein Eftevaag     statecase(context->flush_object_state, FLUSH_INIT);
57*758e9fbaSOystein Eftevaag         r = Esys_FlushContext_Async(context->esys, handle);
58*758e9fbaSOystein Eftevaag         return_if_error(r, "Flush Object");
59*758e9fbaSOystein Eftevaag         fallthrough;
60*758e9fbaSOystein Eftevaag 
61*758e9fbaSOystein Eftevaag     statecase(context->flush_object_state, WAIT_FOR_FLUSH);
62*758e9fbaSOystein Eftevaag         r = Esys_FlushContext_Finish(context->esys);
63*758e9fbaSOystein Eftevaag         if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
64*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_TRY_AGAIN;
65*758e9fbaSOystein Eftevaag 
66*758e9fbaSOystein Eftevaag         return_if_error(r, "FlushContext");
67*758e9fbaSOystein Eftevaag 
68*758e9fbaSOystein Eftevaag         context->flush_object_state = FLUSH_INIT;
69*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
70*758e9fbaSOystein Eftevaag 
71*758e9fbaSOystein Eftevaag     statecasedefault(context->flush_object_state);
72*758e9fbaSOystein Eftevaag     }
73*758e9fbaSOystein Eftevaag }
74*758e9fbaSOystein Eftevaag 
75*758e9fbaSOystein Eftevaag /** Preparation for getting a session handle.
76*758e9fbaSOystein Eftevaag  *
77*758e9fbaSOystein Eftevaag  * The corresponding async call be executed and a session secret for encryption
78*758e9fbaSOystein Eftevaag  * TPM2B parameters will be created.
79*758e9fbaSOystein Eftevaag  *
80*758e9fbaSOystein Eftevaag  * @param[in] esys The ESYS_CONTEXT.
81*758e9fbaSOystein Eftevaag  * @param[in] saltkey The key which will be used for the encryption of the session
82*758e9fbaSOystein Eftevaag  *            secret.
83*758e9fbaSOystein Eftevaag  * @param[in] profile The FAPI profile will be used to adjust the sessions symmetric
84*758e9fbaSOystein Eftevaag  *            parameters.
85*758e9fbaSOystein Eftevaag  * @param[in] hashAlg The hash algorithm used for the session.
86*758e9fbaSOystein Eftevaag  *
87*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
88*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
89*758e9fbaSOystein Eftevaag  */
90*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_session_async(ESYS_CONTEXT * esys,ESYS_TR saltkey,const IFAPI_PROFILE * profile,TPMI_ALG_HASH hashAlg)91*758e9fbaSOystein Eftevaag ifapi_get_session_async(ESYS_CONTEXT *esys, ESYS_TR saltkey, const IFAPI_PROFILE *profile,
92*758e9fbaSOystein Eftevaag                         TPMI_ALG_HASH hashAlg)
93*758e9fbaSOystein Eftevaag {
94*758e9fbaSOystein Eftevaag     TSS2_RC r;
95*758e9fbaSOystein Eftevaag 
96*758e9fbaSOystein Eftevaag     r = Esys_StartAuthSession_Async(esys, saltkey,
97*758e9fbaSOystein Eftevaag                                     ESYS_TR_NONE,
98*758e9fbaSOystein Eftevaag                                     ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
99*758e9fbaSOystein Eftevaag                                     NULL,
100*758e9fbaSOystein Eftevaag                                     TPM2_SE_HMAC, &profile->session_symmetric,
101*758e9fbaSOystein Eftevaag                                     hashAlg);
102*758e9fbaSOystein Eftevaag     return_if_error(r, "Creating session.");
103*758e9fbaSOystein Eftevaag 
104*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
105*758e9fbaSOystein Eftevaag }
106*758e9fbaSOystein Eftevaag 
107*758e9fbaSOystein Eftevaag /**  Call for getting a session handle and adjust session parameters.
108*758e9fbaSOystein Eftevaag  *
109*758e9fbaSOystein Eftevaag  * @param[in] esys The ESYS_CONTEXT.
110*758e9fbaSOystein Eftevaag  * @param[out] session The session handle.
111*758e9fbaSOystein Eftevaag  * @param[in] flags The flags to adjust the session attributes.
112*758e9fbaSOystein Eftevaag  *
113*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
114*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
115*758e9fbaSOystein Eftevaag  */
116*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_session_finish(ESYS_CONTEXT * esys,ESYS_TR * session,TPMA_SESSION flags)117*758e9fbaSOystein Eftevaag ifapi_get_session_finish(ESYS_CONTEXT *esys, ESYS_TR *session,
118*758e9fbaSOystein Eftevaag                          TPMA_SESSION flags)
119*758e9fbaSOystein Eftevaag {
120*758e9fbaSOystein Eftevaag     TSS2_RC r;
121*758e9fbaSOystein Eftevaag     TPMA_SESSION sessionAttributes = 0;
122*758e9fbaSOystein Eftevaag 
123*758e9fbaSOystein Eftevaag     /* Check whether authorization callback is defined */
124*758e9fbaSOystein Eftevaag 
125*758e9fbaSOystein Eftevaag     r = Esys_StartAuthSession_Finish(esys, session);
126*758e9fbaSOystein Eftevaag     if (r != TSS2_RC_SUCCESS)
127*758e9fbaSOystein Eftevaag         return r;
128*758e9fbaSOystein Eftevaag 
129*758e9fbaSOystein Eftevaag     sessionAttributes |= flags;
130*758e9fbaSOystein Eftevaag     sessionAttributes |= TPMA_SESSION_CONTINUESESSION;
131*758e9fbaSOystein Eftevaag 
132*758e9fbaSOystein Eftevaag     r = Esys_TRSess_SetAttributes(esys, *session, sessionAttributes,
133*758e9fbaSOystein Eftevaag                                   0xff);
134*758e9fbaSOystein Eftevaag     return_if_error(r, "Set session attributes.");
135*758e9fbaSOystein Eftevaag 
136*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
137*758e9fbaSOystein Eftevaag }
138*758e9fbaSOystein Eftevaag 
139*758e9fbaSOystein Eftevaag /** Get the digest size of the policy of a FAPI object.
140*758e9fbaSOystein Eftevaag  *
141*758e9fbaSOystein Eftevaag  * @param[in] object The object with the correspodning policy.
142*758e9fbaSOystein Eftevaag  *
143*758e9fbaSOystein Eftevaag  * @retval The size of policy digest.
144*758e9fbaSOystein Eftevaag  * @retval 0 if The object does not have a policy.
145*758e9fbaSOystein Eftevaag  */
146*758e9fbaSOystein Eftevaag static size_t
policy_digest_size(IFAPI_OBJECT * object)147*758e9fbaSOystein Eftevaag policy_digest_size(IFAPI_OBJECT *object)
148*758e9fbaSOystein Eftevaag {
149*758e9fbaSOystein Eftevaag     switch (object->objectType) {
150*758e9fbaSOystein Eftevaag     case IFAPI_KEY_OBJ:
151*758e9fbaSOystein Eftevaag         return object->misc.key.public.publicArea.authPolicy.size;
152*758e9fbaSOystein Eftevaag     case IFAPI_NV_OBJ:
153*758e9fbaSOystein Eftevaag         return object->misc.nv.public.nvPublic.authPolicy.size;
154*758e9fbaSOystein Eftevaag     case IFAPI_HIERARCHY_OBJ:
155*758e9fbaSOystein Eftevaag         return object->misc.hierarchy.authPolicy.size;
156*758e9fbaSOystein Eftevaag     default:
157*758e9fbaSOystein Eftevaag         return 0;
158*758e9fbaSOystein Eftevaag     }
159*758e9fbaSOystein Eftevaag }
160*758e9fbaSOystein Eftevaag 
161*758e9fbaSOystein Eftevaag /** Add a object together with size as first element to a linked list.
162*758e9fbaSOystein Eftevaag  *
163*758e9fbaSOystein Eftevaag  * This function can e.g. used to add byte arrays together with their size
164*758e9fbaSOystein Eftevaag  * to a linked list.
165*758e9fbaSOystein Eftevaag  *
166*758e9fbaSOystein Eftevaag  * @param[in] object The object to be added.
167*758e9fbaSOystein Eftevaag  * @param[in] size The size of the object to be added.
168*758e9fbaSOystein Eftevaag  * @param[in,out] object_list The linked list to be extended.
169*758e9fbaSOystein Eftevaag  *
170*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the object was added.
171*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY If memory for the list extension cannot
172*758e9fbaSOystein Eftevaag  *         be allocated.
173*758e9fbaSOystein Eftevaag  */
174*758e9fbaSOystein Eftevaag static TSS2_RC
push_object_with_size_to_list(void * object,size_t size,NODE_OBJECT_T ** object_list)175*758e9fbaSOystein Eftevaag push_object_with_size_to_list(void *object, size_t size, NODE_OBJECT_T **object_list)
176*758e9fbaSOystein Eftevaag {
177*758e9fbaSOystein Eftevaag     TSS2_RC r;
178*758e9fbaSOystein Eftevaag     r = push_object_to_list(object, object_list);
179*758e9fbaSOystein Eftevaag     return_if_error(r, "Push object with size.");
180*758e9fbaSOystein Eftevaag 
181*758e9fbaSOystein Eftevaag     (*object_list)->size = size;
182*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
183*758e9fbaSOystein Eftevaag }
184*758e9fbaSOystein Eftevaag 
185*758e9fbaSOystein Eftevaag /** Initialize and expand the linked list representing a FAPI key path.
186*758e9fbaSOystein Eftevaag  *
187*758e9fbaSOystein Eftevaag  * From a passed key path the explicit key path will be determined. The
188*758e9fbaSOystein Eftevaag  * profile and the hierarchy will be added if necessary and the extension
189*758e9fbaSOystein Eftevaag  * is possible.
190*758e9fbaSOystein Eftevaag  *
191*758e9fbaSOystein Eftevaag  * @param[in]  context_profile The profile used for extension of no profile is
192*758e9fbaSOystein Eftevaag  *             part of the path.
193*758e9fbaSOystein Eftevaag  * @param[in]  ipath The implicit pathname which has to be extended.
194*758e9fbaSOystein Eftevaag  * @param[out] list_node1 The linked list for the passed key path without
195*758e9fbaSOystein Eftevaag  *             extensions.
196*758e9fbaSOystein Eftevaag  * @param[out] current_list_node The current node in the list list_node1,
197*758e9fbaSOystein Eftevaag  *             which represent the tail not processed.
198*758e9fbaSOystein Eftevaag  * @param[out] result The part of the new list which had been extended
199*758e9fbaSOystein Eftevaag  *             without the tail not processed.
200*758e9fbaSOystein Eftevaag  *
201*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: If the initialization was successful.
202*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If an invalid path was passed.
203*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
204*758e9fbaSOystein Eftevaag  */
205*758e9fbaSOystein Eftevaag static TSS2_RC
init_explicit_key_path(const char * context_profile,const char * ipath,NODE_STR_T ** list_node1,NODE_STR_T ** current_list_node,NODE_STR_T ** result)206*758e9fbaSOystein Eftevaag init_explicit_key_path(
207*758e9fbaSOystein Eftevaag     const char *context_profile,
208*758e9fbaSOystein Eftevaag     const char *ipath,
209*758e9fbaSOystein Eftevaag     NODE_STR_T **list_node1,
210*758e9fbaSOystein Eftevaag     NODE_STR_T **current_list_node,
211*758e9fbaSOystein Eftevaag     NODE_STR_T **result)
212*758e9fbaSOystein Eftevaag {
213*758e9fbaSOystein Eftevaag     *list_node1 = split_string(ipath, IFAPI_FILE_DELIM);
214*758e9fbaSOystein Eftevaag     NODE_STR_T *list_node = *list_node1;
215*758e9fbaSOystein Eftevaag     char const *profile;
216*758e9fbaSOystein Eftevaag     char *hierarchy;
217*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
218*758e9fbaSOystein Eftevaag 
219*758e9fbaSOystein Eftevaag     *result = NULL;
220*758e9fbaSOystein Eftevaag     if (list_node == NULL) {
221*758e9fbaSOystein Eftevaag         LOG_ERROR("Invalid path");
222*758e9fbaSOystein Eftevaag         free_string_list(*list_node1);
223*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_BAD_VALUE;
224*758e9fbaSOystein Eftevaag     }
225*758e9fbaSOystein Eftevaag 
226*758e9fbaSOystein Eftevaag     /* Processing of the profile. */
227*758e9fbaSOystein Eftevaag     if (strncmp("P_", list_node->str, 2) == 0) {
228*758e9fbaSOystein Eftevaag         profile = list_node->str;
229*758e9fbaSOystein Eftevaag         list_node = list_node->next;
230*758e9fbaSOystein Eftevaag     } else {
231*758e9fbaSOystein Eftevaag         profile = context_profile;
232*758e9fbaSOystein Eftevaag     }
233*758e9fbaSOystein Eftevaag     *result = init_string_list(profile);
234*758e9fbaSOystein Eftevaag     if (*result == NULL) {
235*758e9fbaSOystein Eftevaag         free_string_list(*list_node1);
236*758e9fbaSOystein Eftevaag         LOG_ERROR("Out of memory");
237*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_MEMORY;
238*758e9fbaSOystein Eftevaag     }
239*758e9fbaSOystein Eftevaag     if (list_node == NULL) {
240*758e9fbaSOystein Eftevaag         /* extend default hierarchy. */
241*758e9fbaSOystein Eftevaag         hierarchy = "HS";
242*758e9fbaSOystein Eftevaag     } else {
243*758e9fbaSOystein Eftevaag         if (strcmp(list_node->str, "HS") == 0 ||
244*758e9fbaSOystein Eftevaag                 strcmp(list_node->str, "HE") == 0 ||
245*758e9fbaSOystein Eftevaag                 strcmp(list_node->str, "HP") == 0 ||
246*758e9fbaSOystein Eftevaag                 strcmp(list_node->str, "HN") == 0 ||
247*758e9fbaSOystein Eftevaag                 strcmp(list_node->str, "HP") == 0) {
248*758e9fbaSOystein Eftevaag             hierarchy = list_node->str;
249*758e9fbaSOystein Eftevaag             list_node = list_node->next;
250*758e9fbaSOystein Eftevaag         }
251*758e9fbaSOystein Eftevaag         /* Extend hierarchy. */
252*758e9fbaSOystein Eftevaag         else if (strcmp(list_node->str, "EK") == 0) {
253*758e9fbaSOystein Eftevaag             hierarchy = "HE";
254*758e9fbaSOystein Eftevaag         } else if (list_node->next != NULL &&
255*758e9fbaSOystein Eftevaag                    (strcmp(list_node->str, "SRK") == 0 ||
256*758e9fbaSOystein Eftevaag                     strcmp(list_node->str, "SDK") == 0 ||
257*758e9fbaSOystein Eftevaag                     strcmp(list_node->str, "UNK") == 0 ||
258*758e9fbaSOystein Eftevaag                     strcmp(list_node->str, "UDK") == 0)) {
259*758e9fbaSOystein Eftevaag             hierarchy = "HS";
260*758e9fbaSOystein Eftevaag         } else {
261*758e9fbaSOystein Eftevaag             hierarchy = "HS";
262*758e9fbaSOystein Eftevaag         }
263*758e9fbaSOystein Eftevaag     }
264*758e9fbaSOystein Eftevaag 
265*758e9fbaSOystein Eftevaag     /* Extend the current result. */
266*758e9fbaSOystein Eftevaag     if (!add_string_to_list(*result, hierarchy)) {
267*758e9fbaSOystein Eftevaag         LOG_ERROR("Out of memory");
268*758e9fbaSOystein Eftevaag         r = TSS2_FAPI_RC_MEMORY;
269*758e9fbaSOystein Eftevaag         goto error;
270*758e9fbaSOystein Eftevaag     }
271*758e9fbaSOystein Eftevaag     if (list_node == NULL) {
272*758e9fbaSOystein Eftevaag         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Explicit path can't be determined.",
273*758e9fbaSOystein Eftevaag                    error);
274*758e9fbaSOystein Eftevaag     }
275*758e9fbaSOystein Eftevaag     if (!add_string_to_list(*result, list_node->str)) {
276*758e9fbaSOystein Eftevaag         LOG_ERROR("Out of memory");
277*758e9fbaSOystein Eftevaag         r = TSS2_FAPI_RC_MEMORY;
278*758e9fbaSOystein Eftevaag         goto error;
279*758e9fbaSOystein Eftevaag     }
280*758e9fbaSOystein Eftevaag     *current_list_node = list_node->next;
281*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
282*758e9fbaSOystein Eftevaag 
283*758e9fbaSOystein Eftevaag error:
284*758e9fbaSOystein Eftevaag     free_string_list(*result);
285*758e9fbaSOystein Eftevaag     *result = NULL;
286*758e9fbaSOystein Eftevaag     free_string_list(*list_node1);
287*758e9fbaSOystein Eftevaag     *list_node1 = NULL;
288*758e9fbaSOystein Eftevaag     return r;
289*758e9fbaSOystein Eftevaag }
290*758e9fbaSOystein Eftevaag 
291*758e9fbaSOystein Eftevaag /** Free first object of a linked list.
292*758e9fbaSOystein Eftevaag  *
293*758e9fbaSOystein Eftevaag  * Note: Referenced objects of the list have to be freed before.
294*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
295*758e9fbaSOystein Eftevaag  */
296*758e9fbaSOystein Eftevaag static TSS2_RC
pop_object_from_list(FAPI_CONTEXT * context,NODE_OBJECT_T ** object_list)297*758e9fbaSOystein Eftevaag pop_object_from_list(FAPI_CONTEXT *context, NODE_OBJECT_T **object_list)
298*758e9fbaSOystein Eftevaag {
299*758e9fbaSOystein Eftevaag     return_if_null(*object_list, "Pop from list.", TSS2_FAPI_RC_BAD_REFERENCE);
300*758e9fbaSOystein Eftevaag 
301*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *head = *object_list;
302*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *next = head->next;
303*758e9fbaSOystein Eftevaag     *object_list = next;
304*758e9fbaSOystein Eftevaag     ifapi_free_object(context, (void *)&head->object);
305*758e9fbaSOystein Eftevaag     free(head);
306*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
307*758e9fbaSOystein Eftevaag }
308*758e9fbaSOystein Eftevaag 
309*758e9fbaSOystein Eftevaag /** Set authorization value for a FAPI object.
310*758e9fbaSOystein Eftevaag  *
311*758e9fbaSOystein Eftevaag  * The callback which provides the auth value must be defined.
312*758e9fbaSOystein Eftevaag  *
313*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
314*758e9fbaSOystein Eftevaag  * @param[in]     auth_object The auth value will be assigned to this object.
315*758e9fbaSOystein Eftevaag  * @param[in]     description The description will be passed to the callback
316*758e9fbaSOystein Eftevaag  *                which delivers the auth value.
317*758e9fbaSOystein Eftevaag  *
318*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
319*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN If the callback for getting
320*758e9fbaSOystein Eftevaag  *         the auth value is not defined.
321*758e9fbaSOystein Eftevaag  */
322*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_set_auth(FAPI_CONTEXT * context,IFAPI_OBJECT * auth_object,const char * description)323*758e9fbaSOystein Eftevaag ifapi_set_auth(
324*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
325*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *auth_object,
326*758e9fbaSOystein Eftevaag     const char *description)
327*758e9fbaSOystein Eftevaag {
328*758e9fbaSOystein Eftevaag     TSS2_RC r;
329*758e9fbaSOystein Eftevaag     char *auth = NULL;
330*758e9fbaSOystein Eftevaag     TPM2B_AUTH authValue = {.size = 0,.buffer = {0} };
331*758e9fbaSOystein Eftevaag     char *obj_description;
332*758e9fbaSOystein Eftevaag 
333*758e9fbaSOystein Eftevaag     obj_description = get_description(auth_object);
334*758e9fbaSOystein Eftevaag 
335*758e9fbaSOystein Eftevaag     if (obj_description)
336*758e9fbaSOystein Eftevaag         description = obj_description;
337*758e9fbaSOystein Eftevaag 
338*758e9fbaSOystein Eftevaag     /* Check whether callback is defined. */
339*758e9fbaSOystein Eftevaag     if (context->callbacks.auth) {
340*758e9fbaSOystein Eftevaag         r = context->callbacks.auth(context, description, &auth,
341*758e9fbaSOystein Eftevaag                                         context->callbacks.authData);
342*758e9fbaSOystein Eftevaag         return_if_error(r, "policyAuthCallback");
343*758e9fbaSOystein Eftevaag         if (auth != NULL) {
344*758e9fbaSOystein Eftevaag             authValue.size = strlen(auth);
345*758e9fbaSOystein Eftevaag             memcpy(&authValue.buffer[0], auth, authValue.size);
346*758e9fbaSOystein Eftevaag         }
347*758e9fbaSOystein Eftevaag         SAFE_FREE(auth);
348*758e9fbaSOystein Eftevaag         /* Store auth value in the ESYS object. */
349*758e9fbaSOystein Eftevaag         r = Esys_TR_SetAuth(context->esys, auth_object->handle, &authValue);
350*758e9fbaSOystein Eftevaag         return_if_error(r, "Set auth value.");
351*758e9fbaSOystein Eftevaag 
352*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
353*758e9fbaSOystein Eftevaag     }
354*758e9fbaSOystein Eftevaag     SAFE_FREE(auth);
355*758e9fbaSOystein Eftevaag     return TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN;
356*758e9fbaSOystein Eftevaag }
357*758e9fbaSOystein Eftevaag 
358*758e9fbaSOystein Eftevaag /** Preparation for getting a free handle after a start handle number.
359*758e9fbaSOystein Eftevaag  *
360*758e9fbaSOystein Eftevaag  * @param[in] fctx The FAPI_CONTEXT.
361*758e9fbaSOystein Eftevaag  * @param[in] handle The start value for handle search.
362*758e9fbaSOystein Eftevaag  *
363*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
364*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
365*758e9fbaSOystein Eftevaag  */
366*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_free_handle_async(FAPI_CONTEXT * fctx,TPM2_HANDLE * handle)367*758e9fbaSOystein Eftevaag ifapi_get_free_handle_async(FAPI_CONTEXT *fctx, TPM2_HANDLE *handle)
368*758e9fbaSOystein Eftevaag {
369*758e9fbaSOystein Eftevaag     TSS2_RC r = Esys_GetCapability_Async(fctx->esys,
370*758e9fbaSOystein Eftevaag                                          ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
371*758e9fbaSOystein Eftevaag                                          TPM2_CAP_HANDLES, *handle, 1);
372*758e9fbaSOystein Eftevaag     return_if_error(r, "GetCapability");
373*758e9fbaSOystein Eftevaag     return r;
374*758e9fbaSOystein Eftevaag }
375*758e9fbaSOystein Eftevaag 
376*758e9fbaSOystein Eftevaag /** Execution of get capability until a free handle is found.
377*758e9fbaSOystein Eftevaag  *
378*758e9fbaSOystein Eftevaag  * The get capability method is called until a free handle is found
379*758e9fbaSOystein Eftevaag  * or the max number of trials passe to the function is exeeded.
380*758e9fbaSOystein Eftevaag  *
381*758e9fbaSOystein Eftevaag  * @param[in] fctx The FAPI_CONTEXT.
382*758e9fbaSOystein Eftevaag  * @param[out] handle The free handle.
383*758e9fbaSOystein Eftevaag  * @param[in] max The maximal number of trials.
384*758e9fbaSOystein Eftevaag  *
385*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
386*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_NV_TOO_SMALL if too many NV handles are defined.
387*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
388*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
389*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
390*758e9fbaSOystein Eftevaag  */
391*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_free_handle_finish(FAPI_CONTEXT * fctx,TPM2_HANDLE * handle,TPM2_HANDLE max)392*758e9fbaSOystein Eftevaag ifapi_get_free_handle_finish(FAPI_CONTEXT *fctx, TPM2_HANDLE *handle,
393*758e9fbaSOystein Eftevaag                              TPM2_HANDLE max)
394*758e9fbaSOystein Eftevaag {
395*758e9fbaSOystein Eftevaag     TPMI_YES_NO moreData;
396*758e9fbaSOystein Eftevaag     TPMS_CAPABILITY_DATA *capabilityData = NULL;
397*758e9fbaSOystein Eftevaag     TSS2_RC r = Esys_GetCapability_Finish(fctx->esys,
398*758e9fbaSOystein Eftevaag                                           &moreData, &capabilityData);
399*758e9fbaSOystein Eftevaag 
400*758e9fbaSOystein Eftevaag     if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
401*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
402*758e9fbaSOystein Eftevaag 
403*758e9fbaSOystein Eftevaag     return_if_error(r, "GetCapability");
404*758e9fbaSOystein Eftevaag 
405*758e9fbaSOystein Eftevaag     if (capabilityData->data.handles.count == 0 ||
406*758e9fbaSOystein Eftevaag             capabilityData->data.handles.handle[0] != *handle) {
407*758e9fbaSOystein Eftevaag         SAFE_FREE(capabilityData);
408*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
409*758e9fbaSOystein Eftevaag     }
410*758e9fbaSOystein Eftevaag     SAFE_FREE(capabilityData);
411*758e9fbaSOystein Eftevaag     *handle += 1;
412*758e9fbaSOystein Eftevaag     if (*handle > max) {
413*758e9fbaSOystein Eftevaag         return_error(TSS2_FAPI_RC_NV_TOO_SMALL, "No NV index free.");
414*758e9fbaSOystein Eftevaag     }
415*758e9fbaSOystein Eftevaag 
416*758e9fbaSOystein Eftevaag     r = ifapi_get_free_handle_async(fctx, handle);
417*758e9fbaSOystein Eftevaag     return_if_error(r, "GetCapability");
418*758e9fbaSOystein Eftevaag 
419*758e9fbaSOystein Eftevaag     return TSS2_FAPI_RC_TRY_AGAIN;
420*758e9fbaSOystein Eftevaag }
421*758e9fbaSOystein Eftevaag 
422*758e9fbaSOystein Eftevaag /** Create a linked list of directories in the key store.
423*758e9fbaSOystein Eftevaag  *
424*758e9fbaSOystein Eftevaag  * If the absolute path in key store is not defined the list will
425*758e9fbaSOystein Eftevaag  * be extended if possible.
426*758e9fbaSOystein Eftevaag  *
427*758e9fbaSOystein Eftevaag  * @param[out] keystore The used keystore.
428*758e9fbaSOystein Eftevaag  * @param[in] ipath The implicit pathname, which might be extended.
429*758e9fbaSOystein Eftevaag  * @param[out] The linked list of directories in the explicit pathname.
430*758e9fbaSOystein Eftevaag  *
431*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the keystore can be initialized.
432*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If the user part of the keystore can't be
433*758e9fbaSOystein Eftevaag  *         initialized.
434*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated.
435*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
436*758e9fbaSOystein Eftevaag  *         the function.
437*758e9fbaSOystein Eftevaag  */
438*758e9fbaSOystein Eftevaag static TSS2_RC
get_explicit_key_path(IFAPI_KEYSTORE * keystore,const char * ipath,NODE_STR_T ** result)439*758e9fbaSOystein Eftevaag get_explicit_key_path(
440*758e9fbaSOystein Eftevaag     IFAPI_KEYSTORE *keystore,
441*758e9fbaSOystein Eftevaag     const char *ipath,
442*758e9fbaSOystein Eftevaag     NODE_STR_T **result)
443*758e9fbaSOystein Eftevaag {
444*758e9fbaSOystein Eftevaag     NODE_STR_T *list_node1 = NULL;
445*758e9fbaSOystein Eftevaag     NODE_STR_T *list_node = NULL;
446*758e9fbaSOystein Eftevaag 
447*758e9fbaSOystein Eftevaag     /* Extend the first part of the list if necessary. */
448*758e9fbaSOystein Eftevaag     TSS2_RC r = init_explicit_key_path(keystore->defaultprofile, ipath,
449*758e9fbaSOystein Eftevaag                                        &list_node1, &list_node, result);
450*758e9fbaSOystein Eftevaag     goto_if_error(r, "init_explicit_key_path", error);
451*758e9fbaSOystein Eftevaag 
452*758e9fbaSOystein Eftevaag     /* Extend the list with the tail of the initial unmodified list. */
453*758e9fbaSOystein Eftevaag     while (list_node != NULL) {
454*758e9fbaSOystein Eftevaag         if (!add_string_to_list(*result, list_node->str)) {
455*758e9fbaSOystein Eftevaag             LOG_ERROR("Out of memory");
456*758e9fbaSOystein Eftevaag             r = TSS2_FAPI_RC_MEMORY;
457*758e9fbaSOystein Eftevaag             goto error;
458*758e9fbaSOystein Eftevaag         }
459*758e9fbaSOystein Eftevaag         list_node = list_node->next;
460*758e9fbaSOystein Eftevaag     }
461*758e9fbaSOystein Eftevaag     free_string_list(list_node1);
462*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
463*758e9fbaSOystein Eftevaag 
464*758e9fbaSOystein Eftevaag error:
465*758e9fbaSOystein Eftevaag     if (*result)
466*758e9fbaSOystein Eftevaag         free_string_list(*result);
467*758e9fbaSOystein Eftevaag     if (list_node1)
468*758e9fbaSOystein Eftevaag         free_string_list(list_node1);
469*758e9fbaSOystein Eftevaag     return r;
470*758e9fbaSOystein Eftevaag }
471*758e9fbaSOystein Eftevaag 
472*758e9fbaSOystein Eftevaag /** Prepare the creation of a primary key.
473*758e9fbaSOystein Eftevaag  *
474*758e9fbaSOystein Eftevaag  * Depending on the parameters the creation of an endorsement or storage root key
475*758e9fbaSOystein Eftevaag  * will be prepared.
476*758e9fbaSOystein Eftevaag  *
477*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT.
478*758e9fbaSOystein Eftevaag  * @param[in] ktype The type of key TSS2_EK or TSS2_SRK.
479*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
480*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if a wrong type was passed.
481*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
482*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
483*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
484*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
485*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
486*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
487*758e9fbaSOystein Eftevaag  *         operation already pending.
488*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
489*758e9fbaSOystein Eftevaag  *         object store.
490*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
491*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
492*758e9fbaSOystein Eftevaag  *         during authorization.
493*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
494*758e9fbaSOystein Eftevaag  */
495*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_init_primary_async(FAPI_CONTEXT * context,TSS2_KEY_TYPE ktype)496*758e9fbaSOystein Eftevaag ifapi_init_primary_async(FAPI_CONTEXT *context, TSS2_KEY_TYPE ktype)
497*758e9fbaSOystein Eftevaag {
498*758e9fbaSOystein Eftevaag     TSS2_RC r;
499*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *hierarchy;
500*758e9fbaSOystein Eftevaag     hierarchy = &context->cmd.Provision.hierarchy;
501*758e9fbaSOystein Eftevaag     TPMS_POLICY *policy;
502*758e9fbaSOystein Eftevaag 
503*758e9fbaSOystein Eftevaag     if (ktype == TSS2_EK) {
504*758e9fbaSOystein Eftevaag         /* Values set according to EK credential profile. */
505*758e9fbaSOystein Eftevaag         if (context->cmd.Provision.public_templ.public.publicArea.type == TPM2_ALG_RSA) {
506*758e9fbaSOystein Eftevaag             context->cmd.Provision.public_templ.public.publicArea.unique.rsa.size = 256;
507*758e9fbaSOystein Eftevaag         } else if (context->cmd.Provision.public_templ.public.publicArea.type == TPM2_ALG_ECC) {
508*758e9fbaSOystein Eftevaag             context->cmd.Provision.public_templ.public.publicArea.unique.ecc.x.size = 32;
509*758e9fbaSOystein Eftevaag             context->cmd.Provision.public_templ.public.publicArea.unique.ecc.y.size = 32;
510*758e9fbaSOystein Eftevaag         }
511*758e9fbaSOystein Eftevaag         ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_ENDORSEMENT);
512*758e9fbaSOystein Eftevaag         policy = context->profiles.default_profile.ek_policy;
513*758e9fbaSOystein Eftevaag     } else if (ktype == TSS2_SRK) {
514*758e9fbaSOystein Eftevaag         policy = context->profiles.default_profile.srk_policy;
515*758e9fbaSOystein Eftevaag         ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
516*758e9fbaSOystein Eftevaag     } else {
517*758e9fbaSOystein Eftevaag         return_error(TSS2_FAPI_RC_BAD_VALUE,
518*758e9fbaSOystein Eftevaag                      "Invalid key type. Only EK or SRK allowed");
519*758e9fbaSOystein Eftevaag     }
520*758e9fbaSOystein Eftevaag 
521*758e9fbaSOystein Eftevaag     if (policy) {
522*758e9fbaSOystein Eftevaag         /* Duplicate policy to prevent profile policy from cleanup. */
523*758e9fbaSOystein Eftevaag         policy = ifapi_copy_policy(policy);
524*758e9fbaSOystein Eftevaag         return_if_null(policy, "Out of memory.", TSS2_FAPI_RC_MEMORY);
525*758e9fbaSOystein Eftevaag 
526*758e9fbaSOystein Eftevaag         r = ifapi_calculate_tree(context, NULL, /**< no path needed */
527*758e9fbaSOystein Eftevaag                                  policy,
528*758e9fbaSOystein Eftevaag                                  context->profiles.default_profile.nameAlg,
529*758e9fbaSOystein Eftevaag                                  &context->cmd.Provision.digest_idx,
530*758e9fbaSOystein Eftevaag                                  &context->cmd.Provision.hash_size);
531*758e9fbaSOystein Eftevaag         if (r) {
532*758e9fbaSOystein Eftevaag             LOG_ERROR("Policy calculation");
533*758e9fbaSOystein Eftevaag             free(policy);
534*758e9fbaSOystein Eftevaag             return r;
535*758e9fbaSOystein Eftevaag         }
536*758e9fbaSOystein Eftevaag 
537*758e9fbaSOystein Eftevaag         context->cmd.Provision.public_templ.public.publicArea.authPolicy.size =
538*758e9fbaSOystein Eftevaag             context->cmd.Provision.hash_size;
539*758e9fbaSOystein Eftevaag         memcpy(&context->cmd.Provision.public_templ.public.publicArea.authPolicy.buffer[0],
540*758e9fbaSOystein Eftevaag                &policy->policyDigests.digests[context->policy.digest_idx].digest,
541*758e9fbaSOystein Eftevaag                context->cmd.Provision.hash_size);
542*758e9fbaSOystein Eftevaag     }
543*758e9fbaSOystein Eftevaag     context->createPrimary.pkey_object.policy = policy;
544*758e9fbaSOystein Eftevaag 
545*758e9fbaSOystein Eftevaag     memset(&context->cmd.Provision.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
546*758e9fbaSOystein Eftevaag     memset(&context->cmd.Provision.outsideInfo, 0, sizeof(TPM2B_DATA));
547*758e9fbaSOystein Eftevaag     memset(&context->cmd.Provision.creationPCR, 0, sizeof(TPML_PCR_SELECTION));
548*758e9fbaSOystein Eftevaag 
549*758e9fbaSOystein Eftevaag     r = Esys_CreatePrimary_Async(context->esys, hierarchy->handle,
550*758e9fbaSOystein Eftevaag                                  ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
551*758e9fbaSOystein Eftevaag                                  &context->cmd.Provision.inSensitive,
552*758e9fbaSOystein Eftevaag                                  &context->cmd.Provision.public_templ.public,
553*758e9fbaSOystein Eftevaag                                  &context->cmd.Provision.outsideInfo,
554*758e9fbaSOystein Eftevaag                                  &context->cmd.Provision.creationPCR);
555*758e9fbaSOystein Eftevaag     return r;
556*758e9fbaSOystein Eftevaag }
557*758e9fbaSOystein Eftevaag 
558*758e9fbaSOystein Eftevaag /** Finalize the creation of a primary key.
559*758e9fbaSOystein Eftevaag  *
560*758e9fbaSOystein Eftevaag  * Depending on the parameters the creation of an endorsement key or a storage root key
561*758e9fbaSOystein Eftevaag  * will be finalized. The created object with the all information needed by FAPI will
562*758e9fbaSOystein Eftevaag  * be stored in the FAPI context.
563*758e9fbaSOystein Eftevaag  *
564*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT.
565*758e9fbaSOystein Eftevaag  * @param[in] ktype The type of key TSS2_EK or TSS2_SRK.
566*758e9fbaSOystein Eftevaag  *
567*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
568*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if the execution cannot be completed.
569*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if a wrong type was passed.
570*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
571*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
572*758e9fbaSOystein Eftevaag  *         is not set.
573*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
574*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
575*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
576*758e9fbaSOystein Eftevaag  */
577*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_init_primary_finish(FAPI_CONTEXT * context,TSS2_KEY_TYPE ktype)578*758e9fbaSOystein Eftevaag ifapi_init_primary_finish(FAPI_CONTEXT *context, TSS2_KEY_TYPE ktype)
579*758e9fbaSOystein Eftevaag {
580*758e9fbaSOystein Eftevaag     TSS2_RC r;
581*758e9fbaSOystein Eftevaag     ESYS_TR primaryHandle;
582*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *hierarchy;
583*758e9fbaSOystein Eftevaag     TPM2B_PUBLIC *outPublic = NULL;
584*758e9fbaSOystein Eftevaag     TPM2B_CREATION_DATA *creationData = NULL;
585*758e9fbaSOystein Eftevaag     TPM2B_DIGEST *creationHash = NULL;
586*758e9fbaSOystein Eftevaag     TPMT_TK_CREATION *creationTicket = NULL;
587*758e9fbaSOystein Eftevaag     IFAPI_KEY *pkey = &context->createPrimary.pkey_object.misc.key;
588*758e9fbaSOystein Eftevaag     NODE_STR_T *k_sub_path = NULL;
589*758e9fbaSOystein Eftevaag 
590*758e9fbaSOystein Eftevaag     hierarchy = &context->cmd.Provision.hierarchy;
591*758e9fbaSOystein Eftevaag 
592*758e9fbaSOystein Eftevaag     r = Esys_CreatePrimary_Finish(context->esys,
593*758e9fbaSOystein Eftevaag                                   &primaryHandle, &outPublic, &creationData, &creationHash,
594*758e9fbaSOystein Eftevaag                                   &creationTicket);
595*758e9fbaSOystein Eftevaag     if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
596*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
597*758e9fbaSOystein Eftevaag 
598*758e9fbaSOystein Eftevaag     /* Retry with authorization callback after trial with null auth */
599*758e9fbaSOystein Eftevaag     if ((((r & ~TPM2_RC_N_MASK) == TPM2_RC_BAD_AUTH))
600*758e9fbaSOystein Eftevaag             && (context->state == PROVISION_AUTH_EK_NO_AUTH_SENT ||
601*758e9fbaSOystein Eftevaag                 context->state == PROVISION_AUTH_SRK_NO_AUTH_SENT)) {
602*758e9fbaSOystein Eftevaag         r = ifapi_set_auth(context, hierarchy, "CreatePrimary");
603*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "CreatePrimary", error_cleanup);
604*758e9fbaSOystein Eftevaag 
605*758e9fbaSOystein Eftevaag         r = Esys_CreatePrimary_Async(context->esys, hierarchy->handle,
606*758e9fbaSOystein Eftevaag                                      ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
607*758e9fbaSOystein Eftevaag                                      &context->cmd.Provision.inSensitive,
608*758e9fbaSOystein Eftevaag                                      &context->cmd.Provision.public,
609*758e9fbaSOystein Eftevaag                                      &context->cmd.Provision.outsideInfo,
610*758e9fbaSOystein Eftevaag                                      &context->cmd.Provision.creationPCR);
611*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "CreatePrimary", error_cleanup);
612*758e9fbaSOystein Eftevaag 
613*758e9fbaSOystein Eftevaag         if (ktype == TSS2_EK)
614*758e9fbaSOystein Eftevaag             context->state = PROVISION_AUTH_EK_AUTH_SENT;
615*758e9fbaSOystein Eftevaag         else
616*758e9fbaSOystein Eftevaag             context->state = PROVISION_AUTH_SRK_AUTH_SENT;
617*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
618*758e9fbaSOystein Eftevaag 
619*758e9fbaSOystein Eftevaag     } else {
620*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "FAPI Provision", error_cleanup);
621*758e9fbaSOystein Eftevaag     }
622*758e9fbaSOystein Eftevaag     /* Set EK or SRK handle in context. */
623*758e9fbaSOystein Eftevaag     if (ktype == TSS2_EK) {
624*758e9fbaSOystein Eftevaag         context->ek_handle = primaryHandle;
625*758e9fbaSOystein Eftevaag     } else if (ktype == TSS2_SRK) {
626*758e9fbaSOystein Eftevaag         context->srk_handle = primaryHandle;
627*758e9fbaSOystein Eftevaag     } else {
628*758e9fbaSOystein Eftevaag         return_error(TSS2_FAPI_RC_BAD_VALUE,
629*758e9fbaSOystein Eftevaag                      "Invalid key type. Only EK or SRK allowed");
630*758e9fbaSOystein Eftevaag     }
631*758e9fbaSOystein Eftevaag 
632*758e9fbaSOystein Eftevaag     /* Prepare serialization of pkey to key store. */
633*758e9fbaSOystein Eftevaag 
634*758e9fbaSOystein Eftevaag     SAFE_FREE(pkey->serialization.buffer);
635*758e9fbaSOystein Eftevaag     r = Esys_TR_Serialize(context->esys, primaryHandle, &pkey->serialization.buffer,
636*758e9fbaSOystein Eftevaag                           &pkey->serialization.size);
637*758e9fbaSOystein Eftevaag     goto_if_error(r, "Error serialize esys object", error_cleanup);
638*758e9fbaSOystein Eftevaag 
639*758e9fbaSOystein Eftevaag     r = ifapi_get_name(&outPublic->publicArea, &pkey->name);
640*758e9fbaSOystein Eftevaag     goto_if_error(r, "Get primary name", error_cleanup);
641*758e9fbaSOystein Eftevaag 
642*758e9fbaSOystein Eftevaag     pkey->public = *outPublic;
643*758e9fbaSOystein Eftevaag     pkey->policyInstance = NULL;
644*758e9fbaSOystein Eftevaag     pkey->creationData = *creationData;
645*758e9fbaSOystein Eftevaag     pkey->creationTicket = *creationTicket;
646*758e9fbaSOystein Eftevaag     pkey->description = NULL;
647*758e9fbaSOystein Eftevaag     pkey->certificate = NULL;
648*758e9fbaSOystein Eftevaag 
649*758e9fbaSOystein Eftevaag     /* Cleanup unused information */
650*758e9fbaSOystein Eftevaag     SAFE_FREE(outPublic);
651*758e9fbaSOystein Eftevaag     SAFE_FREE(creationData);
652*758e9fbaSOystein Eftevaag     SAFE_FREE(creationHash);
653*758e9fbaSOystein Eftevaag     SAFE_FREE(creationTicket);
654*758e9fbaSOystein Eftevaag 
655*758e9fbaSOystein Eftevaag     if (pkey->public.publicArea.type == TPM2_ALG_RSA)
656*758e9fbaSOystein Eftevaag         pkey->signing_scheme = context->profiles.default_profile.rsa_signing_scheme;
657*758e9fbaSOystein Eftevaag     else
658*758e9fbaSOystein Eftevaag         pkey->signing_scheme = context->profiles.default_profile.ecc_signing_scheme;
659*758e9fbaSOystein Eftevaag     context->createPrimary.pkey_object.handle = primaryHandle;
660*758e9fbaSOystein Eftevaag     SAFE_FREE(pkey->serialization.buffer);
661*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
662*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
663*758e9fbaSOystein Eftevaag 
664*758e9fbaSOystein Eftevaag error_cleanup:
665*758e9fbaSOystein Eftevaag     free_string_list(k_sub_path);
666*758e9fbaSOystein Eftevaag     SAFE_FREE(pkey->serialization.buffer);
667*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
668*758e9fbaSOystein Eftevaag     return r;
669*758e9fbaSOystein Eftevaag }
670*758e9fbaSOystein Eftevaag 
671*758e9fbaSOystein Eftevaag /** Prepare the loading of a primary key from key store.
672*758e9fbaSOystein Eftevaag  *
673*758e9fbaSOystein Eftevaag  * The asynchronous loading or the key from keystore will be prepared and
674*758e9fbaSOystein Eftevaag  * the path will be stored in the FAPI context.
675*758e9fbaSOystein Eftevaag  *
676*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT.
677*758e9fbaSOystein Eftevaag  * @param[in] path The FAPI path of the primary key.
678*758e9fbaSOystein Eftevaag  *
679*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
680*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if a wrong type was passed.
681*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error was encountered.
682*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the file does not exist.
683*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
684*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
685*758e9fbaSOystein Eftevaag  */
686*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_load_primary_async(FAPI_CONTEXT * context,char * path)687*758e9fbaSOystein Eftevaag ifapi_load_primary_async(FAPI_CONTEXT *context, char *path)
688*758e9fbaSOystein Eftevaag {
689*758e9fbaSOystein Eftevaag 
690*758e9fbaSOystein Eftevaag     TSS2_RC r;
691*758e9fbaSOystein Eftevaag 
692*758e9fbaSOystein Eftevaag     memset(&context->createPrimary.pkey_object, 0, sizeof(IFAPI_OBJECT));
693*758e9fbaSOystein Eftevaag     context->createPrimary.path = path;
694*758e9fbaSOystein Eftevaag     r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
695*758e9fbaSOystein Eftevaag     return_if_error2(r, "Could not open: %s", path);
696*758e9fbaSOystein Eftevaag     context->primary_state = PRIMARY_READ_KEY;
697*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
698*758e9fbaSOystein Eftevaag 
699*758e9fbaSOystein Eftevaag }
700*758e9fbaSOystein Eftevaag 
701*758e9fbaSOystein Eftevaag /** State machine to finalize the loading of a primary key from key store.
702*758e9fbaSOystein Eftevaag  *
703*758e9fbaSOystein Eftevaag  * The asynchronous loading or the key from keystore will be finalized.
704*758e9fbaSOystein Eftevaag  * Afterwards the hierarchy object, which will be used for authorization will
705*758e9fbaSOystein Eftevaag  * be loaded and the ESAPI functions for primary generation will be called
706*758e9fbaSOystein Eftevaag  * if the primary is not persistent.
707*758e9fbaSOystein Eftevaag  *
708*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT.
709*758e9fbaSOystein Eftevaag  * @param[out] handle The object handle of the primary key.
710*758e9fbaSOystein Eftevaag  *
711*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
712*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if a wrong type was passed.
713*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the hierarchy file does not exist.
714*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error was encountered.
715*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
716*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
717*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
718*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
719*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
720*758e9fbaSOystein Eftevaag  *         operation already pending.
721*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
722*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
723*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
724*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
725*758e9fbaSOystein Eftevaag  *         is not set.
726*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
727*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
728*758e9fbaSOystein Eftevaag  *         was not successful.
729*758e9fbaSOystein Eftevaag  */
730*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_load_primary_finish(FAPI_CONTEXT * context,ESYS_TR * handle)731*758e9fbaSOystein Eftevaag ifapi_load_primary_finish(FAPI_CONTEXT *context, ESYS_TR *handle)
732*758e9fbaSOystein Eftevaag {
733*758e9fbaSOystein Eftevaag     TSS2_RC r;
734*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *hierarchy = &context->createPrimary.hierarchy;
735*758e9fbaSOystein Eftevaag 
736*758e9fbaSOystein Eftevaag     TPM2B_PUBLIC *outPublic = NULL;
737*758e9fbaSOystein Eftevaag     TPM2B_CREATION_DATA *creationData = NULL;
738*758e9fbaSOystein Eftevaag     TPM2B_DIGEST *creationHash = NULL;
739*758e9fbaSOystein Eftevaag     TPMT_TK_CREATION *creationTicket = NULL;
740*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *pkey_object = &context->createPrimary.pkey_object;
741*758e9fbaSOystein Eftevaag     IFAPI_KEY *pkey = &context->createPrimary.pkey_object.misc.key;
742*758e9fbaSOystein Eftevaag     ESYS_TR auth_session;
743*758e9fbaSOystein Eftevaag 
744*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
745*758e9fbaSOystein Eftevaag 
746*758e9fbaSOystein Eftevaag     switch (context->primary_state) {
747*758e9fbaSOystein Eftevaag     statecase(context->primary_state, PRIMARY_READ_KEY);
748*758e9fbaSOystein Eftevaag         /* Read the primary key from keystore. */
749*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_finish(&context->keystore, &context->io,
750*758e9fbaSOystein Eftevaag                                        pkey_object);
751*758e9fbaSOystein Eftevaag         return_try_again(r);
752*758e9fbaSOystein Eftevaag         return_if_error(r, "read_finish failed");
753*758e9fbaSOystein Eftevaag 
754*758e9fbaSOystein Eftevaag         r = ifapi_initialize_object(context->esys, pkey_object);
755*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Initialize key object", error_cleanup);
756*758e9fbaSOystein Eftevaag 
757*758e9fbaSOystein Eftevaag         /* Check whether a persistent key was loaded.
758*758e9fbaSOystein Eftevaag            In this case the handle has already been set. */
759*758e9fbaSOystein Eftevaag         if (pkey_object->handle != ESYS_TR_NONE) {
760*758e9fbaSOystein Eftevaag             if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
761*758e9fbaSOystein Eftevaag                 context->ek_persistent = true;
762*758e9fbaSOystein Eftevaag             } else {
763*758e9fbaSOystein Eftevaag                 context->srk_persistent = true;
764*758e9fbaSOystein Eftevaag             }
765*758e9fbaSOystein Eftevaag             /* Persistent handle will be used. */
766*758e9fbaSOystein Eftevaag             *handle = pkey_object->handle;
767*758e9fbaSOystein Eftevaag             break;
768*758e9fbaSOystein Eftevaag         } else {
769*758e9fbaSOystein Eftevaag             if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
770*758e9fbaSOystein Eftevaag                 context->ek_persistent = false;
771*758e9fbaSOystein Eftevaag             } else {
772*758e9fbaSOystein Eftevaag                 context->srk_persistent = false;
773*758e9fbaSOystein Eftevaag             }
774*758e9fbaSOystein Eftevaag         }
775*758e9fbaSOystein Eftevaag         fallthrough;
776*758e9fbaSOystein Eftevaag 
777*758e9fbaSOystein Eftevaag     statecase(context->primary_state, PRIMARY_READ_HIERARCHY);
778*758e9fbaSOystein Eftevaag         /* The hierarchy object ussed for auth_session will be loaded from key store. */
779*758e9fbaSOystein Eftevaag         if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
780*758e9fbaSOystein Eftevaag             r = ifapi_keystore_load_async(&context->keystore, &context->io, "/HE");
781*758e9fbaSOystein Eftevaag             return_if_error2(r, "Could not open hierarchy /HE");
782*758e9fbaSOystein Eftevaag         } else {
783*758e9fbaSOystein Eftevaag             r = ifapi_keystore_load_async(&context->keystore, &context->io, "/HS");
784*758e9fbaSOystein Eftevaag             return_if_error2(r, "Could not open hierarchy /HS");
785*758e9fbaSOystein Eftevaag         }
786*758e9fbaSOystein Eftevaag         fallthrough;
787*758e9fbaSOystein Eftevaag 
788*758e9fbaSOystein Eftevaag     statecase(context->primary_state, PRIMARY_READ_HIERARCHY_FINISH);
789*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_finish(&context->keystore, &context->io, hierarchy);
790*758e9fbaSOystein Eftevaag         return_try_again(r);
791*758e9fbaSOystein Eftevaag         return_if_error(r, "read_finish failed");
792*758e9fbaSOystein Eftevaag 
793*758e9fbaSOystein Eftevaag         r = ifapi_initialize_object(context->esys, hierarchy);
794*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Initialize hierarchy object", error_cleanup);
795*758e9fbaSOystein Eftevaag 
796*758e9fbaSOystein Eftevaag         if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
797*758e9fbaSOystein Eftevaag             hierarchy->handle = ESYS_TR_RH_ENDORSEMENT;
798*758e9fbaSOystein Eftevaag         } else {
799*758e9fbaSOystein Eftevaag             hierarchy->handle = ESYS_TR_RH_OWNER;
800*758e9fbaSOystein Eftevaag         }
801*758e9fbaSOystein Eftevaag         fallthrough;
802*758e9fbaSOystein Eftevaag 
803*758e9fbaSOystein Eftevaag     statecase(context->primary_state, PRIMARY_AUTHORIZE_HIERARCHY);
804*758e9fbaSOystein Eftevaag         /* The asynchronous authorization of the hierarchy needed for primary. */
805*758e9fbaSOystein Eftevaag         r = ifapi_authorize_object(context, hierarchy, &auth_session);
806*758e9fbaSOystein Eftevaag         FAPI_SYNC(r, "Authorize hierarchy.", error_cleanup);
807*758e9fbaSOystein Eftevaag 
808*758e9fbaSOystein Eftevaag         memset(&context->createPrimary.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
809*758e9fbaSOystein Eftevaag         memset(&context->createPrimary.outsideInfo, 0, sizeof(TPM2B_DATA));
810*758e9fbaSOystein Eftevaag         memset(&context->createPrimary.creationPCR, 0, sizeof(TPML_PCR_SELECTION));
811*758e9fbaSOystein Eftevaag 
812*758e9fbaSOystein Eftevaag         /* Prepare primary creation. */
813*758e9fbaSOystein Eftevaag         r = Esys_CreatePrimary_Async(context->esys, hierarchy->handle,
814*758e9fbaSOystein Eftevaag                                      auth_session, ESYS_TR_NONE, ESYS_TR_NONE,
815*758e9fbaSOystein Eftevaag                                      &context->createPrimary.inSensitive,
816*758e9fbaSOystein Eftevaag                                      &pkey->public,
817*758e9fbaSOystein Eftevaag                                      &context->createPrimary.outsideInfo,
818*758e9fbaSOystein Eftevaag                                      &context->createPrimary.creationPCR);
819*758e9fbaSOystein Eftevaag         return_if_error(r, "CreatePrimary");
820*758e9fbaSOystein Eftevaag         fallthrough;
821*758e9fbaSOystein Eftevaag 
822*758e9fbaSOystein Eftevaag     statecase(context->primary_state, PRIMARY_HAUTH_SENT);
823*758e9fbaSOystein Eftevaag         if (context->createPrimary.handle) {
824*758e9fbaSOystein Eftevaag             *handle = context->createPrimary.handle;
825*758e9fbaSOystein Eftevaag             context->primary_state = PRIMARY_CREATED;
826*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_TRY_AGAIN;
827*758e9fbaSOystein Eftevaag         } else {
828*758e9fbaSOystein Eftevaag             r = Esys_CreatePrimary_Finish(context->esys,
829*758e9fbaSOystein Eftevaag                                           &pkey_object->handle, &outPublic,
830*758e9fbaSOystein Eftevaag                                           &creationData, &creationHash,
831*758e9fbaSOystein Eftevaag                                           &creationTicket);
832*758e9fbaSOystein Eftevaag             return_try_again(r);
833*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "FAPI regenerate primary", error_cleanup);
834*758e9fbaSOystein Eftevaag         }
835*758e9fbaSOystein Eftevaag         *handle = pkey_object->handle;
836*758e9fbaSOystein Eftevaag         context->primary_state = PRIMARY_INIT;
837*758e9fbaSOystein Eftevaag         break;
838*758e9fbaSOystein Eftevaag 
839*758e9fbaSOystein Eftevaag     statecasedefault(context->primary_state);
840*758e9fbaSOystein Eftevaag     }
841*758e9fbaSOystein Eftevaag     SAFE_FREE(outPublic);
842*758e9fbaSOystein Eftevaag     SAFE_FREE(creationData);
843*758e9fbaSOystein Eftevaag     SAFE_FREE(creationHash);
844*758e9fbaSOystein Eftevaag     SAFE_FREE(creationTicket);
845*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&context->createPrimary.hierarchy);
846*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
847*758e9fbaSOystein Eftevaag 
848*758e9fbaSOystein Eftevaag error_cleanup:
849*758e9fbaSOystein Eftevaag     SAFE_FREE(outPublic);
850*758e9fbaSOystein Eftevaag     SAFE_FREE(creationData);
851*758e9fbaSOystein Eftevaag     SAFE_FREE(creationHash);
852*758e9fbaSOystein Eftevaag     SAFE_FREE(creationTicket);
853*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&context->createPrimary.hierarchy);
854*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
855*758e9fbaSOystein Eftevaag     return r;
856*758e9fbaSOystein Eftevaag }
857*758e9fbaSOystein Eftevaag 
858*758e9fbaSOystein Eftevaag /** Prepare session for FAPI command execution.
859*758e9fbaSOystein Eftevaag  *
860*758e9fbaSOystein Eftevaag  * It will be checked whether the context of FAPI and ESAPI is initialized
861*758e9fbaSOystein Eftevaag  * and whether no other FAPI command session is running.
862*758e9fbaSOystein Eftevaag  * Also some handle variables in the context are initialized.
863*758e9fbaSOystein Eftevaag  *
864*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT.
865*758e9fbaSOystein Eftevaag  *
866*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
867*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE if the context is not initialized.
868*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE If a FAPI command session is active.
869*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_NO_TPM if the ESAPI context is not initialized.
870*758e9fbaSOystein Eftevaag  */
871*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_session_init(FAPI_CONTEXT * context)872*758e9fbaSOystein Eftevaag ifapi_session_init(FAPI_CONTEXT *context)
873*758e9fbaSOystein Eftevaag {
874*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
875*758e9fbaSOystein Eftevaag     return_if_null(context, "No context", TSS2_FAPI_RC_BAD_REFERENCE);
876*758e9fbaSOystein Eftevaag 
877*758e9fbaSOystein Eftevaag     return_if_null(context->esys, "No context", TSS2_FAPI_RC_NO_TPM);
878*758e9fbaSOystein Eftevaag 
879*758e9fbaSOystein Eftevaag     if (context->state != _FAPI_STATE_INIT) {
880*758e9fbaSOystein Eftevaag         return_error(TSS2_FAPI_RC_BAD_SEQUENCE, "Invalid State");
881*758e9fbaSOystein Eftevaag     }
882*758e9fbaSOystein Eftevaag 
883*758e9fbaSOystein Eftevaag     context->session1 = ESYS_TR_NONE;
884*758e9fbaSOystein Eftevaag     context->session2 = ESYS_TR_NONE;
885*758e9fbaSOystein Eftevaag     context->policy.session = ESYS_TR_NONE;
886*758e9fbaSOystein Eftevaag     context->srk_handle = ESYS_TR_NONE;
887*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
888*758e9fbaSOystein Eftevaag }
889*758e9fbaSOystein Eftevaag 
890*758e9fbaSOystein Eftevaag /** Prepare session for FAPI command execution without TPM.
891*758e9fbaSOystein Eftevaag  *
892*758e9fbaSOystein Eftevaag  * It will be checked whether the context of FAPI is initialized
893*758e9fbaSOystein Eftevaag  * and whether no other FAPI command session is running.
894*758e9fbaSOystein Eftevaag  * Also some handle variables in the context are initialized.
895*758e9fbaSOystein Eftevaag  *
896*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT.
897*758e9fbaSOystein Eftevaag  *
898*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
899*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE if the context is not initialized.
900*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE If a FAPI command session is active.
901*758e9fbaSOystein Eftevaag  */
902*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_non_tpm_mode_init(FAPI_CONTEXT * context)903*758e9fbaSOystein Eftevaag ifapi_non_tpm_mode_init(FAPI_CONTEXT *context)
904*758e9fbaSOystein Eftevaag {
905*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
906*758e9fbaSOystein Eftevaag     return_if_null(context, "No context", TSS2_FAPI_RC_BAD_REFERENCE);
907*758e9fbaSOystein Eftevaag 
908*758e9fbaSOystein Eftevaag     if (context->state != _FAPI_STATE_INIT) {
909*758e9fbaSOystein Eftevaag         return_error(TSS2_FAPI_RC_BAD_SEQUENCE, "Invalid State");
910*758e9fbaSOystein Eftevaag     }
911*758e9fbaSOystein Eftevaag 
912*758e9fbaSOystein Eftevaag     context->session1 = ESYS_TR_NONE;
913*758e9fbaSOystein Eftevaag     context->session2 = ESYS_TR_NONE;
914*758e9fbaSOystein Eftevaag     context->policy.session = ESYS_TR_NONE;
915*758e9fbaSOystein Eftevaag     context->srk_handle = ESYS_TR_NONE;
916*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
917*758e9fbaSOystein Eftevaag }
918*758e9fbaSOystein Eftevaag 
919*758e9fbaSOystein Eftevaag /** Cleanup FAPI sessions in error cases.
920*758e9fbaSOystein Eftevaag  *
921*758e9fbaSOystein Eftevaag  * The uses sessions and the SRK (if not persistent) will be flushed
922*758e9fbaSOystein Eftevaag  * non asynchronous in error cases.
923*758e9fbaSOystein Eftevaag  *
924*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
925*758e9fbaSOystein Eftevaag  */
926*758e9fbaSOystein Eftevaag void
ifapi_session_clean(FAPI_CONTEXT * context)927*758e9fbaSOystein Eftevaag ifapi_session_clean(FAPI_CONTEXT *context)
928*758e9fbaSOystein Eftevaag {
929*758e9fbaSOystein Eftevaag     if (context->session1 != ESYS_TR_NONE) {
930*758e9fbaSOystein Eftevaag         if (Esys_FlushContext(context->esys, context->session1) != TSS2_RC_SUCCESS) {
931*758e9fbaSOystein Eftevaag             LOG_ERROR("Cleanup session failed.");
932*758e9fbaSOystein Eftevaag         }
933*758e9fbaSOystein Eftevaag         context->session1 = ESYS_TR_NONE;
934*758e9fbaSOystein Eftevaag     }
935*758e9fbaSOystein Eftevaag     if (context->session2 != ESYS_TR_NONE) {
936*758e9fbaSOystein Eftevaag         if (Esys_FlushContext(context->esys, context->session2) != TSS2_RC_SUCCESS) {
937*758e9fbaSOystein Eftevaag             LOG_ERROR("Cleanup session failed.");
938*758e9fbaSOystein Eftevaag             context->session2 = ESYS_TR_NONE;
939*758e9fbaSOystein Eftevaag         }
940*758e9fbaSOystein Eftevaag     }
941*758e9fbaSOystein Eftevaag     if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
942*758e9fbaSOystein Eftevaag         if (Esys_FlushContext(context->esys, context->srk_handle) != TSS2_RC_SUCCESS) {
943*758e9fbaSOystein Eftevaag             LOG_ERROR("Cleanup Policy Session  failed.");
944*758e9fbaSOystein Eftevaag         }
945*758e9fbaSOystein Eftevaag         context->srk_handle = ESYS_TR_NONE;
946*758e9fbaSOystein Eftevaag     }
947*758e9fbaSOystein Eftevaag     context->srk_persistent = false;
948*758e9fbaSOystein Eftevaag }
949*758e9fbaSOystein Eftevaag 
950*758e9fbaSOystein Eftevaag /** State machine for asynchronous cleanup of a FAPI session.
951*758e9fbaSOystein Eftevaag  *
952*758e9fbaSOystein Eftevaag  * Used sessions and the SRK will be flushed.
953*758e9fbaSOystein Eftevaag  *
954*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT storing the used handles.
955*758e9fbaSOystein Eftevaag  *
956*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
957*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
958*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
959*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
960*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
961*758e9fbaSOystein Eftevaag  *         operation already pending.
962*758e9fbaSOystein Eftevaag  */
963*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_cleanup_session(FAPI_CONTEXT * context)964*758e9fbaSOystein Eftevaag ifapi_cleanup_session(FAPI_CONTEXT *context)
965*758e9fbaSOystein Eftevaag {
966*758e9fbaSOystein Eftevaag     TSS2_RC r;
967*758e9fbaSOystein Eftevaag 
968*758e9fbaSOystein Eftevaag     switch (context->cleanup_state) {
969*758e9fbaSOystein Eftevaag         statecase(context->cleanup_state, CLEANUP_INIT);
970*758e9fbaSOystein Eftevaag             if (context->session1 != ESYS_TR_NONE) {
971*758e9fbaSOystein Eftevaag                 r = Esys_FlushContext_Async(context->esys, context->session1);
972*758e9fbaSOystein Eftevaag                 try_again_or_error(r, "Flush session.");
973*758e9fbaSOystein Eftevaag             }
974*758e9fbaSOystein Eftevaag             fallthrough;
975*758e9fbaSOystein Eftevaag 
976*758e9fbaSOystein Eftevaag         statecase(context->cleanup_state, CLEANUP_SESSION1);
977*758e9fbaSOystein Eftevaag             if (context->session1 != ESYS_TR_NONE) {
978*758e9fbaSOystein Eftevaag                 r = Esys_FlushContext_Finish(context->esys);
979*758e9fbaSOystein Eftevaag                 try_again_or_error(r, "Flush session.");
980*758e9fbaSOystein Eftevaag             }
981*758e9fbaSOystein Eftevaag             context->session1 = ESYS_TR_NONE;
982*758e9fbaSOystein Eftevaag 
983*758e9fbaSOystein Eftevaag             if (context->session2 != ESYS_TR_NONE) {
984*758e9fbaSOystein Eftevaag                 r = Esys_FlushContext_Async(context->esys, context->session2);
985*758e9fbaSOystein Eftevaag                 try_again_or_error(r, "Flush session.");
986*758e9fbaSOystein Eftevaag             }
987*758e9fbaSOystein Eftevaag             fallthrough;
988*758e9fbaSOystein Eftevaag 
989*758e9fbaSOystein Eftevaag         statecase(context->cleanup_state, CLEANUP_SESSION2);
990*758e9fbaSOystein Eftevaag             if (context->session2 != ESYS_TR_NONE) {
991*758e9fbaSOystein Eftevaag                 r = Esys_FlushContext_Finish(context->esys);
992*758e9fbaSOystein Eftevaag                 try_again_or_error(r, "Flush session.");
993*758e9fbaSOystein Eftevaag             }
994*758e9fbaSOystein Eftevaag             context->session2 = ESYS_TR_NONE;
995*758e9fbaSOystein Eftevaag 
996*758e9fbaSOystein Eftevaag             if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
997*758e9fbaSOystein Eftevaag                 r = Esys_FlushContext_Async(context->esys, context->srk_handle);
998*758e9fbaSOystein Eftevaag                 try_again_or_error(r, "Flush SRK.");
999*758e9fbaSOystein Eftevaag             }
1000*758e9fbaSOystein Eftevaag             fallthrough;
1001*758e9fbaSOystein Eftevaag 
1002*758e9fbaSOystein Eftevaag         statecase(context->cleanup_state, CLEANUP_SRK);
1003*758e9fbaSOystein Eftevaag             if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
1004*758e9fbaSOystein Eftevaag                 r = Esys_FlushContext_Finish(context->esys);
1005*758e9fbaSOystein Eftevaag                 try_again_or_error(r, "Flush SRK.");
1006*758e9fbaSOystein Eftevaag 
1007*758e9fbaSOystein Eftevaag                 context->srk_handle = ESYS_TR_NONE;
1008*758e9fbaSOystein Eftevaag                 context->srk_persistent = false;
1009*758e9fbaSOystein Eftevaag             }
1010*758e9fbaSOystein Eftevaag             context->cleanup_state = CLEANUP_INIT;
1011*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
1012*758e9fbaSOystein Eftevaag 
1013*758e9fbaSOystein Eftevaag         statecasedefault(context->state);
1014*758e9fbaSOystein Eftevaag     }
1015*758e9fbaSOystein Eftevaag }
1016*758e9fbaSOystein Eftevaag 
1017*758e9fbaSOystein Eftevaag /** Cleanup primary keys in error cases (non asynchronous).
1018*758e9fbaSOystein Eftevaag  *
1019*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT storing the used handles.
1020*758e9fbaSOystein Eftevaag  *
1021*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1022*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1023*758e9fbaSOystein Eftevaag  */
1024*758e9fbaSOystein Eftevaag void
ifapi_primary_clean(FAPI_CONTEXT * context)1025*758e9fbaSOystein Eftevaag ifapi_primary_clean(FAPI_CONTEXT *context)
1026*758e9fbaSOystein Eftevaag {
1027*758e9fbaSOystein Eftevaag     if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
1028*758e9fbaSOystein Eftevaag         if (Esys_FlushContext(context->esys, context->srk_handle) != TSS2_RC_SUCCESS) {
1029*758e9fbaSOystein Eftevaag             LOG_ERROR("Cleanup session failed.");
1030*758e9fbaSOystein Eftevaag         }
1031*758e9fbaSOystein Eftevaag         context->srk_handle = ESYS_TR_NONE;
1032*758e9fbaSOystein Eftevaag     }
1033*758e9fbaSOystein Eftevaag     if (!context->ek_persistent && context->ek_handle != ESYS_TR_NONE) {
1034*758e9fbaSOystein Eftevaag         if (Esys_FlushContext(context->esys, context->ek_handle) != TSS2_RC_SUCCESS) {
1035*758e9fbaSOystein Eftevaag             LOG_ERROR("Cleanup EK failed.");
1036*758e9fbaSOystein Eftevaag         }
1037*758e9fbaSOystein Eftevaag         context->ek_handle = ESYS_TR_NONE;
1038*758e9fbaSOystein Eftevaag     }
1039*758e9fbaSOystein Eftevaag     context->srk_persistent = false;
1040*758e9fbaSOystein Eftevaag }
1041*758e9fbaSOystein Eftevaag 
1042*758e9fbaSOystein Eftevaag /** Prepare the session creation of a FAPI command.
1043*758e9fbaSOystein Eftevaag  *
1044*758e9fbaSOystein Eftevaag  * The initial state of the state machine for session creation will be determined.
1045*758e9fbaSOystein Eftevaag  * Depending of the session_flags creation of a primary for the encryption of
1046*758e9fbaSOystein Eftevaag  * the session secret can be adjusted.
1047*758e9fbaSOystein Eftevaag  * The session passed session attributes will be used for the ESAPI command
1048*758e9fbaSOystein Eftevaag  * Esys_TRSess_SetAttributes.
1049*758e9fbaSOystein Eftevaag  *
1050*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT storing the used handles.
1051*758e9fbaSOystein Eftevaag  * @param[in] session_flags The flags to adjust used session and encryption
1052*758e9fbaSOystein Eftevaag  *            key. With IFAPI_SESSION1 and IFAPI_SESSION2 the session creation
1053*758e9fbaSOystein Eftevaag  *            for sesion1 and session2 can be activated, IFAPI_SESSION_GENEK
1054*758e9fbaSOystein Eftevaag  *            triggers the creation of the primary for session secret encryption.
1055*758e9fbaSOystein Eftevaag  * @param[in] attribute_flags1 The attributes used for session1.
1056*758e9fbaSOystein Eftevaag  * @param[in] attribute_flags2 The attributes used for session2.
1057*758e9fbaSOystein Eftevaag  *
1058*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1059*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the hierarchy file or the primary key file
1060*758e9fbaSOystein Eftevaag  *         does not exist.
1061*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
1062*758e9fbaSOystein Eftevaag  *         of the primary.
1063*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1064*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1065*758e9fbaSOystein Eftevaag  *         the function.
1066*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
1067*758e9fbaSOystein Eftevaag  *         object store.
1068*758e9fbaSOystein Eftevaag  */
1069*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_sessions_async(FAPI_CONTEXT * context,IFAPI_SESSION_TYPE session_flags,TPMA_SESSION attribute_flags1,TPMA_SESSION attribute_flags2)1070*758e9fbaSOystein Eftevaag ifapi_get_sessions_async(FAPI_CONTEXT *context,
1071*758e9fbaSOystein Eftevaag                          IFAPI_SESSION_TYPE session_flags,
1072*758e9fbaSOystein Eftevaag                          TPMA_SESSION attribute_flags1,
1073*758e9fbaSOystein Eftevaag                          TPMA_SESSION attribute_flags2)
1074*758e9fbaSOystein Eftevaag {
1075*758e9fbaSOystein Eftevaag     TSS2_RC r;
1076*758e9fbaSOystein Eftevaag 
1077*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
1078*758e9fbaSOystein Eftevaag     context->session_flags = session_flags;
1079*758e9fbaSOystein Eftevaag     context->session1_attribute_flags = attribute_flags1;
1080*758e9fbaSOystein Eftevaag     context->session2_attribute_flags = attribute_flags2;
1081*758e9fbaSOystein Eftevaag     char *file = NULL;
1082*758e9fbaSOystein Eftevaag 
1083*758e9fbaSOystein Eftevaag     if (!(session_flags & IFAPI_SESSION_GENEK)) {
1084*758e9fbaSOystein Eftevaag         context->srk_handle = ESYS_TR_NONE;
1085*758e9fbaSOystein Eftevaag         context->session_state = SESSION_CREATE_SESSION;
1086*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1087*758e9fbaSOystein Eftevaag     }
1088*758e9fbaSOystein Eftevaag 
1089*758e9fbaSOystein Eftevaag     context->primary_state = PRIMARY_INIT;
1090*758e9fbaSOystein Eftevaag     r = ifapi_asprintf(&file, "%s/%s", context->config.profile_name,
1091*758e9fbaSOystein Eftevaag                        IFAPI_SRK_KEY_PATH);
1092*758e9fbaSOystein Eftevaag     goto_if_error(r, "Error ifapi_asprintf", error_cleanup);
1093*758e9fbaSOystein Eftevaag 
1094*758e9fbaSOystein Eftevaag     r = ifapi_load_primary_async(context, file);
1095*758e9fbaSOystein Eftevaag     return_if_error_reset_state(r, "Load EK");
1096*758e9fbaSOystein Eftevaag     free(file);
1097*758e9fbaSOystein Eftevaag 
1098*758e9fbaSOystein Eftevaag     context->session_state = SESSION_WAIT_FOR_PRIMARY;
1099*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1100*758e9fbaSOystein Eftevaag 
1101*758e9fbaSOystein Eftevaag error_cleanup:
1102*758e9fbaSOystein Eftevaag     SAFE_FREE(file);
1103*758e9fbaSOystein Eftevaag     return r;
1104*758e9fbaSOystein Eftevaag }
1105*758e9fbaSOystein Eftevaag 
1106*758e9fbaSOystein Eftevaag /** State machine for the session creation of a FAPI command.
1107*758e9fbaSOystein Eftevaag  *
1108*758e9fbaSOystein Eftevaag  * The sessions needed for a FAPI command will be created. If needed also the
1109*758e9fbaSOystein Eftevaag  * primary key for session encryption will be created.
1110*758e9fbaSOystein Eftevaag  *
1111*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT storing the used handles.
1112*758e9fbaSOystein Eftevaag  * @param[in] profile The FAPI profile will be used to adjust session parameters.
1113*758e9fbaSOystein Eftevaag  * @param[in] hash_alg The hash algorithm used for the session.
1114*758e9fbaSOystein Eftevaag  *
1115*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1116*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error was encountered.
1117*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
1118*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1119*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1120*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
1121*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1122*758e9fbaSOystein Eftevaag  *         operation already pending.
1123*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1124*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1125*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1126*758e9fbaSOystein Eftevaag  *         the function.
1127*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
1128*758e9fbaSOystein Eftevaag  *         during authorization.
1129*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1130*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
1131*758e9fbaSOystein Eftevaag  *         is not set.
1132*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1133*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
1134*758e9fbaSOystein Eftevaag  *         was not successful.
1135*758e9fbaSOystein Eftevaag  */
1136*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_sessions_finish(FAPI_CONTEXT * context,const IFAPI_PROFILE * profile,TPMI_ALG_HASH hash_alg)1137*758e9fbaSOystein Eftevaag ifapi_get_sessions_finish(
1138*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
1139*758e9fbaSOystein Eftevaag     const IFAPI_PROFILE *profile,
1140*758e9fbaSOystein Eftevaag     TPMI_ALG_HASH hash_alg)
1141*758e9fbaSOystein Eftevaag {
1142*758e9fbaSOystein Eftevaag     TSS2_RC r;
1143*758e9fbaSOystein Eftevaag 
1144*758e9fbaSOystein Eftevaag     switch (context->session_state) {
1145*758e9fbaSOystein Eftevaag     statecase(context->session_state, SESSION_WAIT_FOR_PRIMARY);
1146*758e9fbaSOystein Eftevaag         LOG_TRACE("**STATE** SESSION_WAIT_FOR_PRIMARY");
1147*758e9fbaSOystein Eftevaag         r = ifapi_load_primary_finish(context, &context->srk_handle);
1148*758e9fbaSOystein Eftevaag         return_try_again(r);
1149*758e9fbaSOystein Eftevaag         return_if_error(r, "Load primary.");
1150*758e9fbaSOystein Eftevaag         fallthrough;
1151*758e9fbaSOystein Eftevaag 
1152*758e9fbaSOystein Eftevaag     statecase(context->session_state, SESSION_CREATE_SESSION);
1153*758e9fbaSOystein Eftevaag         LOG_TRACE("**STATE** SESSION_CREATE_SESSION");
1154*758e9fbaSOystein Eftevaag         if (!(context->session_flags & IFAPI_SESSION1)) {
1155*758e9fbaSOystein Eftevaag             LOG_TRACE("finished");
1156*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
1157*758e9fbaSOystein Eftevaag         }
1158*758e9fbaSOystein Eftevaag 
1159*758e9fbaSOystein Eftevaag         /* Initializing the first session for the caller */
1160*758e9fbaSOystein Eftevaag 
1161*758e9fbaSOystein Eftevaag         r = ifapi_get_session_async(context->esys, context->srk_handle, profile,
1162*758e9fbaSOystein Eftevaag                                     hash_alg);
1163*758e9fbaSOystein Eftevaag         return_if_error_reset_state(r, "Create FAPI session async");
1164*758e9fbaSOystein Eftevaag         fallthrough;
1165*758e9fbaSOystein Eftevaag 
1166*758e9fbaSOystein Eftevaag     statecase(context->session_state, SESSION_WAIT_FOR_SESSION1);
1167*758e9fbaSOystein Eftevaag         LOG_TRACE("**STATE** SESSION_WAIT_FOR_SESSION1");
1168*758e9fbaSOystein Eftevaag         r = ifapi_get_session_finish(context->esys, &context->session1,
1169*758e9fbaSOystein Eftevaag                                      context->session1_attribute_flags);
1170*758e9fbaSOystein Eftevaag         return_try_again(r);
1171*758e9fbaSOystein Eftevaag         return_if_error_reset_state(r, "Create FAPI session finish");
1172*758e9fbaSOystein Eftevaag 
1173*758e9fbaSOystein Eftevaag         if (!(context->session_flags & IFAPI_SESSION2)) {
1174*758e9fbaSOystein Eftevaag             LOG_TRACE("finished");
1175*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
1176*758e9fbaSOystein Eftevaag         }
1177*758e9fbaSOystein Eftevaag 
1178*758e9fbaSOystein Eftevaag         /* Initializing the second session for the caller */
1179*758e9fbaSOystein Eftevaag 
1180*758e9fbaSOystein Eftevaag         r = ifapi_get_session_async(context->esys, context->srk_handle, profile,
1181*758e9fbaSOystein Eftevaag                                     profile->nameAlg);
1182*758e9fbaSOystein Eftevaag         return_if_error_reset_state(r, "Create FAPI session async");
1183*758e9fbaSOystein Eftevaag         fallthrough;
1184*758e9fbaSOystein Eftevaag 
1185*758e9fbaSOystein Eftevaag     statecase(context->session_state, SESSION_WAIT_FOR_SESSION2);
1186*758e9fbaSOystein Eftevaag         LOG_TRACE("**STATE** SESSION_WAIT_FOR_SESSION2");
1187*758e9fbaSOystein Eftevaag         r = ifapi_get_session_finish(context->esys, &context->session2,
1188*758e9fbaSOystein Eftevaag                                      context->session2_attribute_flags);
1189*758e9fbaSOystein Eftevaag         return_try_again(r);
1190*758e9fbaSOystein Eftevaag 
1191*758e9fbaSOystein Eftevaag         return_if_error_reset_state(r, "Create FAPI session finish");
1192*758e9fbaSOystein Eftevaag         break;
1193*758e9fbaSOystein Eftevaag 
1194*758e9fbaSOystein Eftevaag     statecasedefault(context->session_state);
1195*758e9fbaSOystein Eftevaag     }
1196*758e9fbaSOystein Eftevaag 
1197*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1198*758e9fbaSOystein Eftevaag }
1199*758e9fbaSOystein Eftevaag 
1200*758e9fbaSOystein Eftevaag /** Merge profile already stored in FAPI context into a NV object template.
1201*758e9fbaSOystein Eftevaag  *
1202*758e9fbaSOystein Eftevaag  * The defaults for NV creation which are stored in the FAPI default profile
1203*758e9fbaSOystein Eftevaag  * will be merged in the passed templates default values.
1204*758e9fbaSOystein Eftevaag  *
1205*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT with the default profile.
1206*758e9fbaSOystein Eftevaag  * @param[in] template The template with the default values for the NV object.
1207*758e9fbaSOystein Eftevaag  *
1208*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1209*758e9fbaSOystein Eftevaag  */
1210*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_merge_profile_into_nv_template(FAPI_CONTEXT * context,IFAPI_NV_TEMPLATE * template)1211*758e9fbaSOystein Eftevaag ifapi_merge_profile_into_nv_template(
1212*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
1213*758e9fbaSOystein Eftevaag     IFAPI_NV_TEMPLATE *template)
1214*758e9fbaSOystein Eftevaag {
1215*758e9fbaSOystein Eftevaag     const TPMA_NV extend_mask = TPM2_NT_EXTEND << TPMA_NV_TPM2_NT_SHIFT;
1216*758e9fbaSOystein Eftevaag     const TPMA_NV counter_mask = TPM2_NT_COUNTER << TPMA_NV_TPM2_NT_SHIFT;
1217*758e9fbaSOystein Eftevaag     const TPMA_NV bitfield_mask = TPM2_NT_BITS << TPMA_NV_TPM2_NT_SHIFT;
1218*758e9fbaSOystein Eftevaag     const IFAPI_PROFILE *profile = &context->profiles.default_profile;
1219*758e9fbaSOystein Eftevaag     size_t hash_size;
1220*758e9fbaSOystein Eftevaag 
1221*758e9fbaSOystein Eftevaag     template->public.nameAlg = profile->nameAlg;
1222*758e9fbaSOystein Eftevaag     if ((template->public.attributes & extend_mask) == extend_mask) {
1223*758e9fbaSOystein Eftevaag         /* The size of the NV ram to be extended must be read from the
1224*758e9fbaSOystein Eftevaag            profile */
1225*758e9fbaSOystein Eftevaag         hash_size = ifapi_hash_get_digest_size(profile->nameAlg);
1226*758e9fbaSOystein Eftevaag         template->public.dataSize = hash_size;
1227*758e9fbaSOystein Eftevaag     } else if ((template->public.attributes & counter_mask) == counter_mask ||
1228*758e9fbaSOystein Eftevaag                (template->public.attributes & bitfield_mask) == bitfield_mask) {
1229*758e9fbaSOystein Eftevaag         /* For bit fields and counters only size 8 is possible */
1230*758e9fbaSOystein Eftevaag         template->public.dataSize = 8;
1231*758e9fbaSOystein Eftevaag     } else {
1232*758e9fbaSOystein Eftevaag         /* For normal NV ram the passed size will be used. */
1233*758e9fbaSOystein Eftevaag         template->public.dataSize = context->nv_cmd.numBytes;
1234*758e9fbaSOystein Eftevaag     }
1235*758e9fbaSOystein Eftevaag 
1236*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1237*758e9fbaSOystein Eftevaag }
1238*758e9fbaSOystein Eftevaag 
1239*758e9fbaSOystein Eftevaag /** Merge profile already stored in FAPI context into a key template.
1240*758e9fbaSOystein Eftevaag  *
1241*758e9fbaSOystein Eftevaag  * The defaults for key creation which are stored in the FAPI default profile
1242*758e9fbaSOystein Eftevaag  * will be merged in the passed templates default values.
1243*758e9fbaSOystein Eftevaag  *
1244*758e9fbaSOystein Eftevaag  * @param[in] profile The profile which will be used to adjust the template.
1245*758e9fbaSOystein Eftevaag  * @param[in] template The template with the default values for the key object.
1246*758e9fbaSOystein Eftevaag  *
1247*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1248*758e9fbaSOystein Eftevaag  */
1249*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_merge_profile_into_template(const IFAPI_PROFILE * profile,IFAPI_KEY_TEMPLATE * template)1250*758e9fbaSOystein Eftevaag ifapi_merge_profile_into_template(
1251*758e9fbaSOystein Eftevaag     const IFAPI_PROFILE *profile,
1252*758e9fbaSOystein Eftevaag     IFAPI_KEY_TEMPLATE *template)
1253*758e9fbaSOystein Eftevaag {
1254*758e9fbaSOystein Eftevaag     /* Merge profile parameters */
1255*758e9fbaSOystein Eftevaag     template->public.publicArea.type = profile->type;
1256*758e9fbaSOystein Eftevaag     template->public.publicArea.nameAlg = profile->nameAlg;
1257*758e9fbaSOystein Eftevaag     if (profile->type == TPM2_ALG_RSA) {
1258*758e9fbaSOystein Eftevaag         template->public.publicArea.parameters.rsaDetail.keyBits = profile->keyBits;
1259*758e9fbaSOystein Eftevaag         template->public.publicArea.parameters.rsaDetail.exponent = profile->exponent;
1260*758e9fbaSOystein Eftevaag     } else if (profile->type == TPM2_ALG_ECC) {
1261*758e9fbaSOystein Eftevaag         template->public.publicArea.parameters.eccDetail.curveID = profile->curveID;
1262*758e9fbaSOystein Eftevaag         template->public.publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL;
1263*758e9fbaSOystein Eftevaag     }
1264*758e9fbaSOystein Eftevaag 
1265*758e9fbaSOystein Eftevaag     /* Set remaining parameters depending on key type */
1266*758e9fbaSOystein Eftevaag     if (template->public.publicArea.objectAttributes & TPMA_OBJECT_RESTRICTED) {
1267*758e9fbaSOystein Eftevaag         if (template->public.publicArea.objectAttributes & TPMA_OBJECT_DECRYPT) {
1268*758e9fbaSOystein Eftevaag             template->public.publicArea.parameters.asymDetail.symmetric =
1269*758e9fbaSOystein Eftevaag             profile->sym_parameters;
1270*758e9fbaSOystein Eftevaag         } else {
1271*758e9fbaSOystein Eftevaag             template->public.publicArea.parameters.asymDetail.symmetric.algorithm =
1272*758e9fbaSOystein Eftevaag             TPM2_ALG_NULL;
1273*758e9fbaSOystein Eftevaag         }
1274*758e9fbaSOystein Eftevaag         if (profile->type == TPM2_ALG_RSA) {
1275*758e9fbaSOystein Eftevaag             if (template->public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT) {
1276*758e9fbaSOystein Eftevaag                 template->public.publicArea.parameters.rsaDetail.scheme.scheme =
1277*758e9fbaSOystein Eftevaag                 profile->rsa_signing_scheme.scheme;
1278*758e9fbaSOystein Eftevaag                 memcpy(&template->public.publicArea.parameters.rsaDetail.scheme.details,
1279*758e9fbaSOystein Eftevaag                        &profile->rsa_signing_scheme.details, sizeof(TPMU_ASYM_SCHEME));
1280*758e9fbaSOystein Eftevaag             } else {
1281*758e9fbaSOystein Eftevaag                 template->public.publicArea.parameters.rsaDetail.scheme.scheme = TPM2_ALG_NULL;
1282*758e9fbaSOystein Eftevaag             }
1283*758e9fbaSOystein Eftevaag         } else if (profile->type == TPM2_ALG_ECC) {
1284*758e9fbaSOystein Eftevaag             if (template->public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT) {
1285*758e9fbaSOystein Eftevaag                 template->public.publicArea.parameters.eccDetail.scheme.scheme =
1286*758e9fbaSOystein Eftevaag                 profile->ecc_signing_scheme.scheme;
1287*758e9fbaSOystein Eftevaag                 memcpy(&template->public.publicArea.parameters.eccDetail.scheme.details,
1288*758e9fbaSOystein Eftevaag                        &profile->ecc_signing_scheme.details, sizeof(TPMU_ASYM_SCHEME));
1289*758e9fbaSOystein Eftevaag             } else {
1290*758e9fbaSOystein Eftevaag                 template->public.publicArea.parameters.eccDetail.scheme.scheme = TPM2_ALG_NULL;
1291*758e9fbaSOystein Eftevaag             }
1292*758e9fbaSOystein Eftevaag         } else {
1293*758e9fbaSOystein Eftevaag             template->public.publicArea.parameters.asymDetail.scheme.scheme = TPM2_ALG_NULL;
1294*758e9fbaSOystein Eftevaag         }
1295*758e9fbaSOystein Eftevaag     } else {
1296*758e9fbaSOystein Eftevaag         /* Non restricted key */
1297*758e9fbaSOystein Eftevaag         template->public.publicArea.parameters.asymDetail.symmetric.algorithm =
1298*758e9fbaSOystein Eftevaag         TPM2_ALG_NULL;
1299*758e9fbaSOystein Eftevaag         template->public.publicArea.parameters.asymDetail.scheme.scheme = TPM2_ALG_NULL;
1300*758e9fbaSOystein Eftevaag     }
1301*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1302*758e9fbaSOystein Eftevaag }
1303*758e9fbaSOystein Eftevaag 
1304*758e9fbaSOystein Eftevaag /** Convert absolute path to FAPI path which can be used as parameter for FAPI commands.
1305*758e9fbaSOystein Eftevaag  *
1306*758e9fbaSOystein Eftevaag  * Function converts the absolute path to a FAPI path.
1307*758e9fbaSOystein Eftevaag  *
1308*758e9fbaSOystein Eftevaag  * @param[in] keystore The used keystore.
1309*758e9fbaSOystein Eftevaag  * @param[out] path FAPI key path.
1310*758e9fbaSOystein Eftevaag  */
1311*758e9fbaSOystein Eftevaag static void
full_path_to_fapi_path(IFAPI_KEYSTORE * keystore,char * path)1312*758e9fbaSOystein Eftevaag full_path_to_fapi_path(IFAPI_KEYSTORE *keystore, char *path)
1313*758e9fbaSOystein Eftevaag {
1314*758e9fbaSOystein Eftevaag     unsigned int start_pos, end_pos, i;
1315*758e9fbaSOystein Eftevaag     const unsigned int path_length = strlen(path);
1316*758e9fbaSOystein Eftevaag     size_t keystore_length = strlen(keystore->userdir);
1317*758e9fbaSOystein Eftevaag     char fapi_path_delim;
1318*758e9fbaSOystein Eftevaag 
1319*758e9fbaSOystein Eftevaag     start_pos = 0;
1320*758e9fbaSOystein Eftevaag 
1321*758e9fbaSOystein Eftevaag     /* Check key store part of the path */
1322*758e9fbaSOystein Eftevaag     if (strncmp(&path[0], keystore->userdir, keystore_length) == 0) {
1323*758e9fbaSOystein Eftevaag         start_pos = strlen(keystore->userdir);
1324*758e9fbaSOystein Eftevaag     } else {
1325*758e9fbaSOystein Eftevaag         keystore_length = strlen(keystore->systemdir);
1326*758e9fbaSOystein Eftevaag         if (strncmp(&path[0], keystore->systemdir, keystore_length) == 0)
1327*758e9fbaSOystein Eftevaag             start_pos = strlen(keystore->systemdir);
1328*758e9fbaSOystein Eftevaag     }
1329*758e9fbaSOystein Eftevaag     if (!start_pos)
1330*758e9fbaSOystein Eftevaag         return;
1331*758e9fbaSOystein Eftevaag 
1332*758e9fbaSOystein Eftevaag     /* Shift FAPI path to the beginning. */
1333*758e9fbaSOystein Eftevaag     end_pos = path_length - start_pos;
1334*758e9fbaSOystein Eftevaag     memmove(&path[0], &path[start_pos], end_pos);
1335*758e9fbaSOystein Eftevaag     size_t ip = 0;
1336*758e9fbaSOystein Eftevaag     size_t lp = strlen(path);
1337*758e9fbaSOystein Eftevaag 
1338*758e9fbaSOystein Eftevaag     /* Special handling for // */
1339*758e9fbaSOystein Eftevaag     while (ip < lp) {
1340*758e9fbaSOystein Eftevaag         if (strncmp(&path[ip], "//", 2) == 0) {
1341*758e9fbaSOystein Eftevaag             memmove(&path[ip], &path[ip + 1], lp - ip);
1342*758e9fbaSOystein Eftevaag             lp -= 1;
1343*758e9fbaSOystein Eftevaag         } else {
1344*758e9fbaSOystein Eftevaag             ip += 1;
1345*758e9fbaSOystein Eftevaag         }
1346*758e9fbaSOystein Eftevaag     }
1347*758e9fbaSOystein Eftevaag 
1348*758e9fbaSOystein Eftevaag     /* Special handling for policy path were the name of the object file
1349*758e9fbaSOystein Eftevaag        is part of the path. */
1350*758e9fbaSOystein Eftevaag     if (ifapi_path_type_p(path, IFAPI_POLICY_PATH))
1351*758e9fbaSOystein Eftevaag         fapi_path_delim = '.';
1352*758e9fbaSOystein Eftevaag     else
1353*758e9fbaSOystein Eftevaag         fapi_path_delim = IFAPI_FILE_DELIM_CHAR;
1354*758e9fbaSOystein Eftevaag 
1355*758e9fbaSOystein Eftevaag     for (i = end_pos - 1; i > 0; i--) {
1356*758e9fbaSOystein Eftevaag         if (path[i] == fapi_path_delim) {
1357*758e9fbaSOystein Eftevaag             path[i] = '\0';
1358*758e9fbaSOystein Eftevaag             break;
1359*758e9fbaSOystein Eftevaag         }
1360*758e9fbaSOystein Eftevaag     }
1361*758e9fbaSOystein Eftevaag }
1362*758e9fbaSOystein Eftevaag 
1363*758e9fbaSOystein Eftevaag /** Asynchronous preparation for loading a key and parent keys.
1364*758e9fbaSOystein Eftevaag  *
1365*758e9fbaSOystein Eftevaag  * The key loading is prepared. The pathname will be extended if possible and
1366*758e9fbaSOystein Eftevaag  * a linked list with the directories will be created.
1367*758e9fbaSOystein Eftevaag  *
1368*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
1369*758e9fbaSOystein Eftevaag  * @param[in]     keyPath the key path without the parent directories
1370*758e9fbaSOystein Eftevaag  *                of the key store. (e.g. HE/EK, HS/SRK/mykey)
1371*758e9fbaSOystein Eftevaag  *
1372*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the preparation is successful.
1373*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
1374*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1375*758e9fbaSOystein Eftevaag  *         the function.
1376*758e9fbaSOystein Eftevaag  */
1377*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_load_keys_async(FAPI_CONTEXT * context,char const * keyPath)1378*758e9fbaSOystein Eftevaag ifapi_load_keys_async(FAPI_CONTEXT *context, char const *keyPath)
1379*758e9fbaSOystein Eftevaag {
1380*758e9fbaSOystein Eftevaag     TSS2_RC r;
1381*758e9fbaSOystein Eftevaag     NODE_STR_T *path_list;
1382*758e9fbaSOystein Eftevaag     size_t path_length;
1383*758e9fbaSOystein Eftevaag     char *fapi_key_path = NULL;
1384*758e9fbaSOystein Eftevaag 
1385*758e9fbaSOystein Eftevaag     LOG_TRACE("Load key: %s", keyPath);
1386*758e9fbaSOystein Eftevaag     fapi_key_path = strdup(keyPath);
1387*758e9fbaSOystein Eftevaag     check_oom(fapi_key_path);
1388*758e9fbaSOystein Eftevaag     full_path_to_fapi_path(&context->keystore, fapi_key_path);
1389*758e9fbaSOystein Eftevaag     r = get_explicit_key_path(&context->keystore, fapi_key_path, &path_list);
1390*758e9fbaSOystein Eftevaag     SAFE_FREE(fapi_key_path);
1391*758e9fbaSOystein Eftevaag     return_if_error(r, "Compute explicit path.");
1392*758e9fbaSOystein Eftevaag 
1393*758e9fbaSOystein Eftevaag     context->loadKey.path_list = path_list;
1394*758e9fbaSOystein Eftevaag     path_length = ifapi_path_length(path_list);
1395*758e9fbaSOystein Eftevaag     r = ifapi_load_key_async(context, path_length);
1396*758e9fbaSOystein Eftevaag     return_if_error(r, "Load key async.");
1397*758e9fbaSOystein Eftevaag 
1398*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1399*758e9fbaSOystein Eftevaag }
1400*758e9fbaSOystein Eftevaag 
1401*758e9fbaSOystein Eftevaag /** Asynchronous finish function for loading a key.
1402*758e9fbaSOystein Eftevaag   *
1403*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
1404*758e9fbaSOystein Eftevaag  * @param[in]     flush_parent If false the parent of the key to be loaded
1405*758e9fbaSOystein Eftevaag  *                will not be flushed.
1406*758e9fbaSOystein Eftevaag  * @param[out]    handle The ESYS handle of the key.
1407*758e9fbaSOystein Eftevaag  * @param[out]    key_object The object which will be used for the
1408*758e9fbaSOystein Eftevaag  *                authorization of the loaded key.
1409*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1410*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
1411*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1412*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1413*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1414*758e9fbaSOystein Eftevaag  *         the function.
1415*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1416*758e9fbaSOystein Eftevaag  *         operation already pending.
1417*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
1418*758e9fbaSOystein Eftevaag  *         during authorization.
1419*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1420*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
1421*758e9fbaSOystein Eftevaag  *         object store.
1422*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1423*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
1424*758e9fbaSOystein Eftevaag  *         is not set.
1425*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1426*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
1427*758e9fbaSOystein Eftevaag  *         was not successful.
1428*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1429*758e9fbaSOystein Eftevaag  */
1430*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_load_keys_finish(FAPI_CONTEXT * context,bool flush_parent,ESYS_TR * handle,IFAPI_OBJECT ** key_object)1431*758e9fbaSOystein Eftevaag ifapi_load_keys_finish(
1432*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
1433*758e9fbaSOystein Eftevaag     bool flush_parent,
1434*758e9fbaSOystein Eftevaag     ESYS_TR *handle,
1435*758e9fbaSOystein Eftevaag     IFAPI_OBJECT **key_object)
1436*758e9fbaSOystein Eftevaag {
1437*758e9fbaSOystein Eftevaag     TSS2_RC r;
1438*758e9fbaSOystein Eftevaag 
1439*758e9fbaSOystein Eftevaag     r = ifapi_load_key_finish(context, flush_parent);
1440*758e9fbaSOystein Eftevaag     if (r == TSS2_FAPI_RC_TRY_AGAIN)
1441*758e9fbaSOystein Eftevaag         return r;
1442*758e9fbaSOystein Eftevaag 
1443*758e9fbaSOystein Eftevaag     return_if_error(r, "Load keys");
1444*758e9fbaSOystein Eftevaag 
1445*758e9fbaSOystein Eftevaag     *handle = context->loadKey.auth_object.handle;
1446*758e9fbaSOystein Eftevaag     /* The current authorization object is the last key loaded and
1447*758e9fbaSOystein Eftevaag        will be used. */
1448*758e9fbaSOystein Eftevaag     *key_object = &context->loadKey.auth_object;
1449*758e9fbaSOystein Eftevaag     free_string_list(context->loadKey.path_list);
1450*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1451*758e9fbaSOystein Eftevaag }
1452*758e9fbaSOystein Eftevaag 
1453*758e9fbaSOystein Eftevaag /** Initialize state machine for loading a key.
1454*758e9fbaSOystein Eftevaag  *
1455*758e9fbaSOystein Eftevaag  * @param[in,out] context for storing all state information.
1456*758e9fbaSOystein Eftevaag  * @param[in] position the position of the key in path list stored in
1457*758e9fbaSOystein Eftevaag  *            context->loadKey.path_list.
1458*758e9fbaSOystein Eftevaag  *
1459*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1460*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
1461*758e9fbaSOystein Eftevaag  */
1462*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_load_key_async(FAPI_CONTEXT * context,size_t position)1463*758e9fbaSOystein Eftevaag ifapi_load_key_async(FAPI_CONTEXT *context, size_t position)
1464*758e9fbaSOystein Eftevaag {
1465*758e9fbaSOystein Eftevaag     context->loadKey.state = LOAD_KEY_GET_PATH;
1466*758e9fbaSOystein Eftevaag     context->loadKey.position = position;
1467*758e9fbaSOystein Eftevaag     context->loadKey.key_list = NULL;
1468*758e9fbaSOystein Eftevaag     context->loadKey.parent_handle = ESYS_TR_NONE;
1469*758e9fbaSOystein Eftevaag     // context->loadKey.auth_object = NULL;
1470*758e9fbaSOystein Eftevaag 
1471*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1472*758e9fbaSOystein Eftevaag }
1473*758e9fbaSOystein Eftevaag 
1474*758e9fbaSOystein Eftevaag /** State machine for loading a key.
1475*758e9fbaSOystein Eftevaag  *
1476*758e9fbaSOystein Eftevaag  * A stack with all sup keys will be created and decremented during
1477*758e9fbaSOystein Eftevaag  * the loading auf all keys.
1478*758e9fbaSOystein Eftevaag  * The object of the loaded key will be stored in:
1479*758e9fbaSOystein Eftevaag  * context->loadKey.auth_object
1480*758e9fbaSOystein Eftevaag  *
1481*758e9fbaSOystein Eftevaag  * @param[in,out] context for storing all state information.
1482*758e9fbaSOystein Eftevaag  * @param[in]     flush_parent If flush_parent is false parent is
1483*758e9fbaSOystein Eftevaag                   only flushed if a new parent is available.
1484*758e9fbaSOystein Eftevaag  *
1485*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the loading of the key was successful.
1486*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1487*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1488*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
1489*758e9fbaSOystein Eftevaag  *         not covered by other return codes.
1490*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
1491*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
1492*758e9fbaSOystein Eftevaag  *         store.
1493*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If an object needed for loading or
1494*758e9fbaSOystein Eftevaag  *         authentication was not found.
1495*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
1496*758e9fbaSOystein Eftevaag  *         not successful.
1497*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for loading
1498*758e9fbaSOystein Eftevaag  *         fails.
1499*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
1500*758e9fbaSOystein Eftevaag  *         is not defined.
1501*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1502*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
1503*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1504*758e9fbaSOystein Eftevaag  *         operation already pending.
1505*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1506*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1507*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1508*758e9fbaSOystein Eftevaag  */
1509*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_load_key_finish(FAPI_CONTEXT * context,bool flush_parent)1510*758e9fbaSOystein Eftevaag ifapi_load_key_finish(FAPI_CONTEXT *context, bool flush_parent)
1511*758e9fbaSOystein Eftevaag {
1512*758e9fbaSOystein Eftevaag     TSS2_RC r;
1513*758e9fbaSOystein Eftevaag     NODE_STR_T *path_list = context->loadKey.path_list;
1514*758e9fbaSOystein Eftevaag     size_t *position = &context->loadKey.position;
1515*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *key_object = NULL;
1516*758e9fbaSOystein Eftevaag     IFAPI_KEY *key = NULL;
1517*758e9fbaSOystein Eftevaag     ESYS_TR auth_session;
1518*758e9fbaSOystein Eftevaag 
1519*758e9fbaSOystein Eftevaag     switch (context->loadKey.state) {
1520*758e9fbaSOystein Eftevaag     statecase(context->loadKey.state, LOAD_KEY_GET_PATH);
1521*758e9fbaSOystein Eftevaag         context->loadKey.key_path = NULL;
1522*758e9fbaSOystein Eftevaag         /* Compute path name of key to be loaded. */
1523*758e9fbaSOystein Eftevaag         r = ifapi_path_string_n(&context->loadKey.key_path, NULL, path_list, NULL,
1524*758e9fbaSOystein Eftevaag                                 *position);
1525*758e9fbaSOystein Eftevaag         return_if_error(r, "Compute key path.");
1526*758e9fbaSOystein Eftevaag 
1527*758e9fbaSOystein Eftevaag         context->loadKey.key_object = ifapi_allocate_object(context);
1528*758e9fbaSOystein Eftevaag         goto_if_null2(context->loadKey.key_object, "Allocating key", r,
1529*758e9fbaSOystein Eftevaag                       TSS2_FAPI_RC_MEMORY, error_cleanup);
1530*758e9fbaSOystein Eftevaag 
1531*758e9fbaSOystein Eftevaag         goto_if_null2(context->loadKey.key_path, "Invalid path", r,
1532*758e9fbaSOystein Eftevaag                       TSS2_FAPI_RC_GENERAL_FAILURE,
1533*758e9fbaSOystein Eftevaag                       error_cleanup); /**< to avoid scan-build errors. */
1534*758e9fbaSOystein Eftevaag 
1535*758e9fbaSOystein Eftevaag         /* Prepare key loading. */
1536*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_async(&context->keystore, &context->io,
1537*758e9fbaSOystein Eftevaag                                       context->loadKey.key_path);
1538*758e9fbaSOystein Eftevaag         return_if_error2(r, "Could not open: %s", context->loadKey.key_path);
1539*758e9fbaSOystein Eftevaag         fallthrough;
1540*758e9fbaSOystein Eftevaag 
1541*758e9fbaSOystein Eftevaag     statecase(context->loadKey.state, LOAD_KEY_READ_KEY);
1542*758e9fbaSOystein Eftevaag         goto_if_null2(context->loadKey.key_path, "Invalid path", r,
1543*758e9fbaSOystein Eftevaag                       TSS2_FAPI_RC_GENERAL_FAILURE,
1544*758e9fbaSOystein Eftevaag                       error_cleanup); /**< to avoid scan-build errors. */
1545*758e9fbaSOystein Eftevaag 
1546*758e9fbaSOystein Eftevaag         key = &context->loadKey.key_object->misc.key;
1547*758e9fbaSOystein Eftevaag 
1548*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_finish(&context->keystore, &context->io,
1549*758e9fbaSOystein Eftevaag                                        context->loadKey.key_object);
1550*758e9fbaSOystein Eftevaag         if (r != TSS2_RC_SUCCESS) {
1551*758e9fbaSOystein Eftevaag             ifapi_cleanup_ifapi_object(context->loadKey.key_object);
1552*758e9fbaSOystein Eftevaag         }
1553*758e9fbaSOystein Eftevaag         return_try_again(r);
1554*758e9fbaSOystein Eftevaag         return_if_error(r, "read_finish failed");
1555*758e9fbaSOystein Eftevaag 
1556*758e9fbaSOystein Eftevaag         if (context->loadKey.key_object->objectType != IFAPI_KEY_OBJ)
1557*758e9fbaSOystein Eftevaag             goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "%s is no key", error_cleanup,
1558*758e9fbaSOystein Eftevaag                        context->loadKey.key_path);
1559*758e9fbaSOystein Eftevaag 
1560*758e9fbaSOystein Eftevaag         r = ifapi_initialize_object(context->esys, context->loadKey.key_object);
1561*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Initialize key object", error_cleanup);
1562*758e9fbaSOystein Eftevaag 
1563*758e9fbaSOystein Eftevaag         SAFE_FREE(context->loadKey.key_path);
1564*758e9fbaSOystein Eftevaag         context->loadKey.handle = context->loadKey.key_object->handle;
1565*758e9fbaSOystein Eftevaag         if (context->loadKey.handle != ESYS_TR_NONE) {
1566*758e9fbaSOystein Eftevaag             /* Persistent key could be desearialized keys can be loaded */
1567*758e9fbaSOystein Eftevaag             r = ifapi_copy_ifapi_key_object(&context->loadKey.auth_object,
1568*758e9fbaSOystein Eftevaag                 context->loadKey.key_object);
1569*758e9fbaSOystein Eftevaag             goto_if_error(r, "Could not copy key object", error_cleanup);
1570*758e9fbaSOystein Eftevaag             ifapi_cleanup_ifapi_object(context->loadKey.key_object);            context->loadKey.state = LOAD_KEY_LOAD_KEY;
1571*758e9fbaSOystein Eftevaag 
1572*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_TRY_AGAIN;
1573*758e9fbaSOystein Eftevaag         }
1574*758e9fbaSOystein Eftevaag 
1575*758e9fbaSOystein Eftevaag         if (key->private.size == 0) {
1576*758e9fbaSOystein Eftevaag             /* Create a deep copy of the primary key */
1577*758e9fbaSOystein Eftevaag             ifapi_cleanup_ifapi_key(key);
1578*758e9fbaSOystein Eftevaag             r = ifapi_copy_ifapi_key(key, &context->createPrimary.pkey_object.misc.key);
1579*758e9fbaSOystein Eftevaag             goto_if_error(r, "Could not copy primary key", error_cleanup);
1580*758e9fbaSOystein Eftevaag             context->primary_state = PRIMARY_READ_HIERARCHY;
1581*758e9fbaSOystein Eftevaag             context->loadKey.state = LOAD_KEY_WAIT_FOR_PRIMARY;
1582*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_TRY_AGAIN;
1583*758e9fbaSOystein Eftevaag         }
1584*758e9fbaSOystein Eftevaag         IFAPI_OBJECT * copyToPush = malloc(sizeof(IFAPI_OBJECT));
1585*758e9fbaSOystein Eftevaag         goto_if_null(copyToPush, "Out of memory", TSS2_FAPI_RC_MEMORY, error_cleanup);
1586*758e9fbaSOystein Eftevaag         r = ifapi_copy_ifapi_key_object(copyToPush, context->loadKey.key_object);
1587*758e9fbaSOystein Eftevaag         if (r) {
1588*758e9fbaSOystein Eftevaag             free(copyToPush);
1589*758e9fbaSOystein Eftevaag             LOG_ERROR("Could not create a copy to push");
1590*758e9fbaSOystein Eftevaag             goto error_cleanup;
1591*758e9fbaSOystein Eftevaag         }
1592*758e9fbaSOystein Eftevaag         /* Add object to the list of keys to be loaded. */
1593*758e9fbaSOystein Eftevaag         r = push_object_to_list(copyToPush, &context->loadKey.key_list);
1594*758e9fbaSOystein Eftevaag         if (r) {
1595*758e9fbaSOystein Eftevaag             free(copyToPush);
1596*758e9fbaSOystein Eftevaag             LOG_ERROR("Out of memory");
1597*758e9fbaSOystein Eftevaag             goto error_cleanup;
1598*758e9fbaSOystein Eftevaag         }
1599*758e9fbaSOystein Eftevaag 
1600*758e9fbaSOystein Eftevaag         ifapi_cleanup_ifapi_object(context->loadKey.key_object);
1601*758e9fbaSOystein Eftevaag 
1602*758e9fbaSOystein Eftevaag         *position -= 1;
1603*758e9fbaSOystein Eftevaag         context->loadKey.state = LOAD_KEY_GET_PATH;
1604*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
1605*758e9fbaSOystein Eftevaag 
1606*758e9fbaSOystein Eftevaag     statecase(context->loadKey.state, LOAD_KEY_LOAD_KEY);
1607*758e9fbaSOystein Eftevaag         if (!(context->loadKey.key_list)) {
1608*758e9fbaSOystein Eftevaag             LOG_TRACE("All keys loaded.");
1609*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
1610*758e9fbaSOystein Eftevaag         }
1611*758e9fbaSOystein Eftevaag 
1612*758e9fbaSOystein Eftevaag         /* if flush_parent is false parent is only flushed if a new parent
1613*758e9fbaSOystein Eftevaag            is available */
1614*758e9fbaSOystein Eftevaag         if (!flush_parent && context->loadKey.parent_handle != ESYS_TR_NONE) {
1615*758e9fbaSOystein Eftevaag             r = Esys_FlushContext(context->esys, context->loadKey.parent_handle);
1616*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "Flush object", error_cleanup);
1617*758e9fbaSOystein Eftevaag         }
1618*758e9fbaSOystein Eftevaag         fallthrough;
1619*758e9fbaSOystein Eftevaag 
1620*758e9fbaSOystein Eftevaag     statecase(context->loadKey.state, LOAD_KEY_AUTHORIZE);
1621*758e9fbaSOystein Eftevaag         key_object = context->loadKey.key_list->object;
1622*758e9fbaSOystein Eftevaag         key = &key_object->misc.key;
1623*758e9fbaSOystein Eftevaag         r = ifapi_authorize_object(context, &context->loadKey.auth_object, &auth_session);
1624*758e9fbaSOystein Eftevaag         FAPI_SYNC(r, "Authorize key.", error_cleanup);
1625*758e9fbaSOystein Eftevaag 
1626*758e9fbaSOystein Eftevaag         /* Store parent handle in context for usage in ChangeAuth if not persistent */
1627*758e9fbaSOystein Eftevaag         context->loadKey.parent_handle = context->loadKey.handle;
1628*758e9fbaSOystein Eftevaag         if (context->loadKey.auth_object.misc.key.persistent_handle)
1629*758e9fbaSOystein Eftevaag             context->loadKey.parent_handle_persistent = true;
1630*758e9fbaSOystein Eftevaag         else
1631*758e9fbaSOystein Eftevaag             context->loadKey.parent_handle_persistent = false;
1632*758e9fbaSOystein Eftevaag 
1633*758e9fbaSOystein Eftevaag         TPM2B_PRIVATE private;
1634*758e9fbaSOystein Eftevaag 
1635*758e9fbaSOystein Eftevaag         private.size = key->private.size;
1636*758e9fbaSOystein Eftevaag         memcpy(&private.buffer[0], key->private.buffer, key->private.size);
1637*758e9fbaSOystein Eftevaag 
1638*758e9fbaSOystein Eftevaag         r = Esys_Load_Async(context->esys, context->loadKey.handle,
1639*758e9fbaSOystein Eftevaag                             auth_session,
1640*758e9fbaSOystein Eftevaag                             ESYS_TR_NONE, ESYS_TR_NONE,
1641*758e9fbaSOystein Eftevaag                             &private, &key->public);
1642*758e9fbaSOystein Eftevaag         goto_if_error(r, "Load async", error_cleanup);
1643*758e9fbaSOystein Eftevaag         fallthrough;
1644*758e9fbaSOystein Eftevaag 
1645*758e9fbaSOystein Eftevaag     statecase(context->loadKey.state, LOAD_KEY_AUTH);
1646*758e9fbaSOystein Eftevaag         r = Esys_Load_Finish(context->esys, &context->loadKey.handle);
1647*758e9fbaSOystein Eftevaag         return_try_again(r);
1648*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Load", error_cleanup);
1649*758e9fbaSOystein Eftevaag 
1650*758e9fbaSOystein Eftevaag         /* The current parent is flushed if not prohibited by flush parent */
1651*758e9fbaSOystein Eftevaag         if (flush_parent && context->loadKey.auth_object.objectType == IFAPI_KEY_OBJ &&
1652*758e9fbaSOystein Eftevaag             ! context->loadKey.auth_object.misc.key.persistent_handle) {
1653*758e9fbaSOystein Eftevaag             r = Esys_FlushContext(context->esys, context->loadKey.auth_object.handle);
1654*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "Flush object", error_cleanup);
1655*758e9fbaSOystein Eftevaag 
1656*758e9fbaSOystein Eftevaag         }
1657*758e9fbaSOystein Eftevaag         LOG_TRACE("New key used as auth object.");
1658*758e9fbaSOystein Eftevaag         ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
1659*758e9fbaSOystein Eftevaag         r = ifapi_copy_ifapi_key_object(&context->loadKey.auth_object,
1660*758e9fbaSOystein Eftevaag                 context->loadKey.key_list->object);
1661*758e9fbaSOystein Eftevaag         goto_if_error(r, "Could not copy loaded key", error_cleanup);
1662*758e9fbaSOystein Eftevaag         context->loadKey.auth_object.handle = context->loadKey.handle;
1663*758e9fbaSOystein Eftevaag         IFAPI_OBJECT *top_obj = context->loadKey.key_list->object;
1664*758e9fbaSOystein Eftevaag         ifapi_cleanup_ifapi_object(top_obj);
1665*758e9fbaSOystein Eftevaag         SAFE_FREE(context->loadKey.key_list->object);
1666*758e9fbaSOystein Eftevaag         r = pop_object_from_list(context, &context->loadKey.key_list);
1667*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Pop key failed.", error_cleanup);
1668*758e9fbaSOystein Eftevaag 
1669*758e9fbaSOystein Eftevaag         if (context->loadKey.key_list) {
1670*758e9fbaSOystein Eftevaag             /* Object can be cleaned if it's not the last */
1671*758e9fbaSOystein Eftevaag             ifapi_free_object(context, &top_obj);
1672*758e9fbaSOystein Eftevaag         }
1673*758e9fbaSOystein Eftevaag 
1674*758e9fbaSOystein Eftevaag         context->loadKey.state = LOAD_KEY_LOAD_KEY;
1675*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
1676*758e9fbaSOystein Eftevaag 
1677*758e9fbaSOystein Eftevaag     statecase(context->loadKey.state, LOAD_KEY_WAIT_FOR_PRIMARY);
1678*758e9fbaSOystein Eftevaag         r = ifapi_load_primary_finish(context, &context->loadKey.handle);
1679*758e9fbaSOystein Eftevaag         return_try_again(r);
1680*758e9fbaSOystein Eftevaag         goto_if_error(r, "CreatePrimary", error_cleanup);
1681*758e9fbaSOystein Eftevaag 
1682*758e9fbaSOystein Eftevaag         /* Save the primary object for authorization */
1683*758e9fbaSOystein Eftevaag         r = ifapi_copy_ifapi_key_object(&context->loadKey.auth_object,
1684*758e9fbaSOystein Eftevaag                 &context->createPrimary.pkey_object);
1685*758e9fbaSOystein Eftevaag         goto_if_error(r, "Could not copy primary key", error_cleanup);
1686*758e9fbaSOystein Eftevaag 
1687*758e9fbaSOystein Eftevaag         if (context->loadKey.key_list) {
1688*758e9fbaSOystein Eftevaag             context->loadKey.state = LOAD_KEY_LOAD_KEY;
1689*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_TRY_AGAIN;
1690*758e9fbaSOystein Eftevaag         } else {
1691*758e9fbaSOystein Eftevaag             LOG_TRACE("success");
1692*758e9fbaSOystein Eftevaag             ifapi_cleanup_ifapi_object(context->loadKey.key_object);
1693*758e9fbaSOystein Eftevaag             ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
1694*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
1695*758e9fbaSOystein Eftevaag         }
1696*758e9fbaSOystein Eftevaag         break;
1697*758e9fbaSOystein Eftevaag 
1698*758e9fbaSOystein Eftevaag     statecasedefault(context->loadKey.state);
1699*758e9fbaSOystein Eftevaag     }
1700*758e9fbaSOystein Eftevaag 
1701*758e9fbaSOystein Eftevaag error_cleanup:
1702*758e9fbaSOystein Eftevaag     ifapi_free_object_list(context->loadKey.key_list);
1703*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(context->loadKey.key_object);
1704*758e9fbaSOystein Eftevaag     SAFE_FREE(context->loadKey.key_path);
1705*758e9fbaSOystein Eftevaag     return r;
1706*758e9fbaSOystein Eftevaag }
1707*758e9fbaSOystein Eftevaag 
1708*758e9fbaSOystein Eftevaag /** Get the name alg corresponding to a FAPI object.
1709*758e9fbaSOystein Eftevaag  *
1710*758e9fbaSOystein Eftevaag  * @param[in] context The context with the default profile.
1711*758e9fbaSOystein Eftevaag  * @param[in] object The object to be checked.
1712*758e9fbaSOystein Eftevaag  * @retval TPMI_ALG_HASH The hash algorithm.
1713*758e9fbaSOystein Eftevaag  * @retval 0 If no name alg can be assigned to the object.
1714*758e9fbaSOystein Eftevaag  */
1715*758e9fbaSOystein Eftevaag static size_t
get_name_alg(FAPI_CONTEXT * context,IFAPI_OBJECT * object)1716*758e9fbaSOystein Eftevaag get_name_alg(FAPI_CONTEXT *context, IFAPI_OBJECT *object)
1717*758e9fbaSOystein Eftevaag {
1718*758e9fbaSOystein Eftevaag     switch (object->objectType) {
1719*758e9fbaSOystein Eftevaag     case IFAPI_KEY_OBJ:
1720*758e9fbaSOystein Eftevaag         return object->misc.key.public.publicArea.nameAlg;
1721*758e9fbaSOystein Eftevaag     case IFAPI_NV_OBJ:
1722*758e9fbaSOystein Eftevaag         return object->misc.nv.public.nvPublic.nameAlg;
1723*758e9fbaSOystein Eftevaag     case IFAPI_HIERARCHY_OBJ:
1724*758e9fbaSOystein Eftevaag         return context->profiles.default_profile.nameAlg;
1725*758e9fbaSOystein Eftevaag     default:
1726*758e9fbaSOystein Eftevaag         return 0;
1727*758e9fbaSOystein Eftevaag     }
1728*758e9fbaSOystein Eftevaag }
1729*758e9fbaSOystein Eftevaag 
1730*758e9fbaSOystein Eftevaag /** Check whether policy session has to be flushed.
1731*758e9fbaSOystein Eftevaag  *
1732*758e9fbaSOystein Eftevaag  * Policy sessions with cleared continue session flag are not flushed in error
1733*758e9fbaSOystein Eftevaag  * cases. Therefore the return code will be checked and if a policy session was
1734*758e9fbaSOystein Eftevaag  * used the session will be flushed if the command was not executed successfully.
1735*758e9fbaSOystein Eftevaag  *
1736*758e9fbaSOystein Eftevaag  * @param[in,out] context for storing all state information.
1737*758e9fbaSOystein Eftevaag  * @param[in] session the session to be checked whether flush is needed.
1738*758e9fbaSOystein Eftevaag  * @param[in] r The return code of the command using the session.
1739*758e9fbaSOystein Eftevaag  */
1740*758e9fbaSOystein Eftevaag void
ifapi_flush_policy_session(FAPI_CONTEXT * context,ESYS_TR session,TSS2_RC r)1741*758e9fbaSOystein Eftevaag ifapi_flush_policy_session(FAPI_CONTEXT *context, ESYS_TR session, TSS2_RC r)
1742*758e9fbaSOystein Eftevaag {
1743*758e9fbaSOystein Eftevaag     if (session != context->session1) {
1744*758e9fbaSOystein Eftevaag         /* A policy session was used instead auf the default session. */
1745*758e9fbaSOystein Eftevaag         if (r != TSS2_RC_SUCCESS) {
1746*758e9fbaSOystein Eftevaag             Esys_FlushContext(context->esys, session);
1747*758e9fbaSOystein Eftevaag         }
1748*758e9fbaSOystein Eftevaag     }
1749*758e9fbaSOystein Eftevaag }
1750*758e9fbaSOystein Eftevaag 
1751*758e9fbaSOystein Eftevaag /** State machine to authorize a key, a NV object of a hierarchy.
1752*758e9fbaSOystein Eftevaag  *
1753*758e9fbaSOystein Eftevaag  * @param[in,out] context for storing all state information.
1754*758e9fbaSOystein Eftevaag  * @param[in] object The FAPI object.
1755*758e9fbaSOystein Eftevaag  * @param[out] session The session which can be used for object authorization.
1756*758e9fbaSOystein Eftevaag  *
1757*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the authorization is successful
1758*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1759*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
1760*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
1761*758e9fbaSOystein Eftevaag  *         store.
1762*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy for a certain path was not found.
1763*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
1764*758e9fbaSOystein Eftevaag  *         not successful.
1765*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for the policy
1766*758e9fbaSOystein Eftevaag  *         execution fails.
1767*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
1768*758e9fbaSOystein Eftevaag            is not defined.
1769*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1770*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
1771*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1772*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1773*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1774*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1775*758e9fbaSOystein Eftevaag  */
1776*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_authorize_object(FAPI_CONTEXT * context,IFAPI_OBJECT * object,ESYS_TR * session)1777*758e9fbaSOystein Eftevaag ifapi_authorize_object(FAPI_CONTEXT *context, IFAPI_OBJECT *object, ESYS_TR *session)
1778*758e9fbaSOystein Eftevaag {
1779*758e9fbaSOystein Eftevaag     TSS2_RC r;
1780*758e9fbaSOystein Eftevaag     TPMI_YES_NO auth_required;
1781*758e9fbaSOystein Eftevaag 
1782*758e9fbaSOystein Eftevaag     LOG_DEBUG("Authorize object: %x", object->handle);
1783*758e9fbaSOystein Eftevaag     switch (object->authorization_state) {
1784*758e9fbaSOystein Eftevaag         statecase(object->authorization_state, AUTH_INIT)
1785*758e9fbaSOystein Eftevaag             LOG_TRACE("**STATE** AUTH_INIT");
1786*758e9fbaSOystein Eftevaag 
1787*758e9fbaSOystein Eftevaag             if (!policy_digest_size(object)) {
1788*758e9fbaSOystein Eftevaag                 /* No policy used authorization callbacks have to be called if necessary. */
1789*758e9fbaSOystein Eftevaag                 if (object_with_auth(object)) {
1790*758e9fbaSOystein Eftevaag                     r = ifapi_set_auth(context, object, "Authorize object");
1791*758e9fbaSOystein Eftevaag                     return_if_error(r, "Set auth value");
1792*758e9fbaSOystein Eftevaag                 }
1793*758e9fbaSOystein Eftevaag                 /* No policy session needed current fapi session can be used */
1794*758e9fbaSOystein Eftevaag                 if (context->session1 && context->session1 != ESYS_TR_NONE)
1795*758e9fbaSOystein Eftevaag                     *session = context->session1;
1796*758e9fbaSOystein Eftevaag                 else
1797*758e9fbaSOystein Eftevaag                     /* Use password session if session1 had not been created */
1798*758e9fbaSOystein Eftevaag                     *session = ESYS_TR_PASSWORD;
1799*758e9fbaSOystein Eftevaag                 break;
1800*758e9fbaSOystein Eftevaag             }
1801*758e9fbaSOystein Eftevaag             r = ifapi_policyutil_execute_prepare(context, get_name_alg(context, object)
1802*758e9fbaSOystein Eftevaag                                                  ,object->policy);
1803*758e9fbaSOystein Eftevaag             return_if_error(r, "Prepare policy execution.");
1804*758e9fbaSOystein Eftevaag 
1805*758e9fbaSOystein Eftevaag             /* Next state will switch from prev context to next context. */
1806*758e9fbaSOystein Eftevaag             context->policy.util_current_policy = context->policy.util_current_policy->prev;
1807*758e9fbaSOystein Eftevaag             object->authorization_state = AUTH_EXEC_POLICY;
1808*758e9fbaSOystein Eftevaag             fallthrough;
1809*758e9fbaSOystein Eftevaag 
1810*758e9fbaSOystein Eftevaag         statecase(object->authorization_state, AUTH_EXEC_POLICY)
1811*758e9fbaSOystein Eftevaag             *session = ESYS_TR_NONE;
1812*758e9fbaSOystein Eftevaag             r = ifapi_policyutil_execute(context, session);
1813*758e9fbaSOystein Eftevaag             if (r == TSS2_FAPI_RC_TRY_AGAIN)
1814*758e9fbaSOystein Eftevaag                 return r;
1815*758e9fbaSOystein Eftevaag 
1816*758e9fbaSOystein Eftevaag             return_if_error(r, "Execute policy.");
1817*758e9fbaSOystein Eftevaag 
1818*758e9fbaSOystein Eftevaag             r = Esys_TRSess_GetAuthRequired(context->esys, *session,
1819*758e9fbaSOystein Eftevaag                                             &auth_required);
1820*758e9fbaSOystein Eftevaag             return_if_error(r, "GetAuthRequired");
1821*758e9fbaSOystein Eftevaag 
1822*758e9fbaSOystein Eftevaag             /* Check whether PolicyCommand requiring authorization was executed */
1823*758e9fbaSOystein Eftevaag             if (auth_required == TPM2_YES) {
1824*758e9fbaSOystein Eftevaag                 r = ifapi_set_auth(context, object, "Authorize object");
1825*758e9fbaSOystein Eftevaag                 goto_if_error(r, "Set auth value", error);
1826*758e9fbaSOystein Eftevaag             }
1827*758e9fbaSOystein Eftevaag             /* Clear continue session flag, so policy session will be flushed after authorization */
1828*758e9fbaSOystein Eftevaag             r = Esys_TRSess_SetAttributes(context->esys, *session, 0, TPMA_SESSION_CONTINUESESSION);
1829*758e9fbaSOystein Eftevaag             goto_if_error(r, "Esys_TRSess_SetAttributes", error);
1830*758e9fbaSOystein Eftevaag             break;
1831*758e9fbaSOystein Eftevaag 
1832*758e9fbaSOystein Eftevaag         general_failure(object->authorization_state)
1833*758e9fbaSOystein Eftevaag     }
1834*758e9fbaSOystein Eftevaag 
1835*758e9fbaSOystein Eftevaag     object->authorization_state = AUTH_INIT;
1836*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1837*758e9fbaSOystein Eftevaag 
1838*758e9fbaSOystein Eftevaag error:
1839*758e9fbaSOystein Eftevaag     /* No policy call was executed session can be flushed */
1840*758e9fbaSOystein Eftevaag     Esys_FlushContext(context->esys, *session);
1841*758e9fbaSOystein Eftevaag     return r;
1842*758e9fbaSOystein Eftevaag }
1843*758e9fbaSOystein Eftevaag 
1844*758e9fbaSOystein Eftevaag /** State machine to write data to the NV ram of the TPM.
1845*758e9fbaSOystein Eftevaag  *
1846*758e9fbaSOystein Eftevaag  * The NV object will be read from object store and the data will be
1847*758e9fbaSOystein Eftevaag  * written by one, or more than one if necessary, ESAPI calls to the NV ram of
1848*758e9fbaSOystein Eftevaag  * the TPM.
1849*758e9fbaSOystein Eftevaag  * The sub context nv_cmd will be prepared:
1850*758e9fbaSOystein Eftevaag  * - data The buffer for the data which has to be written
1851*758e9fbaSOystein Eftevaag  * - offset The current offset for writing
1852*758e9fbaSOystein Eftevaag  * - numBytes The number of bytes which have to be written.
1853*758e9fbaSOystein Eftevaag  *
1854*758e9fbaSOystein Eftevaag  * @param[in,out] context for storing all state information.
1855*758e9fbaSOystein Eftevaag  * @param[in] nvPath The fapi path of the NV object.
1856*758e9fbaSOystein Eftevaag  * @param[in] param_offset The offset in the NV memory (will be stored in context).
1857*758e9fbaSOystein Eftevaag  * @param[in] data The pointer to the data to be written.
1858*758e9fbaSOystein Eftevaag  * @param[in] size The number of bytes to be written.
1859*758e9fbaSOystein Eftevaag  *
1860*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If data can be written.
1861*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1862*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1863*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
1864*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
1865*758e9fbaSOystein Eftevaag  +         not covered by other return codes.
1866*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the object
1867*758e9fbaSOystein Eftevaag  *         store.
1868*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND The nv object or an object needed for
1869*758e9fbaSOystein Eftevaag  *         authentication was not found.
1870*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
1871*758e9fbaSOystein Eftevaag  *          not successful.
1872*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for the
1873*758e9fbaSOystein Eftevaag  *         command execution fails.
1874*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
1875*758e9fbaSOystein Eftevaag  *         is not defined.
1876*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_PATH if the used path in inappropriate-
1877*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1878*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
1879*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1880*758e9fbaSOystein Eftevaag  *         operation already pending.
1881*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1882*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1883*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1884*758e9fbaSOystein Eftevaag  */
1885*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_nv_write(FAPI_CONTEXT * context,char * nvPath,size_t param_offset,uint8_t const * data,size_t size)1886*758e9fbaSOystein Eftevaag ifapi_nv_write(
1887*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
1888*758e9fbaSOystein Eftevaag     char         *nvPath,
1889*758e9fbaSOystein Eftevaag     size_t         param_offset,
1890*758e9fbaSOystein Eftevaag     uint8_t const *data,
1891*758e9fbaSOystein Eftevaag     size_t         size)
1892*758e9fbaSOystein Eftevaag {
1893*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
1894*758e9fbaSOystein Eftevaag     ESYS_TR auth_index;
1895*758e9fbaSOystein Eftevaag     ESYS_TR nv_index = context->nv_cmd.esys_handle;
1896*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *object = &context->nv_cmd.nv_object;
1897*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *auth_object = &context->nv_cmd.auth_object;
1898*758e9fbaSOystein Eftevaag     TPM2B_MAX_NV_BUFFER *aux_data = (TPM2B_MAX_NV_BUFFER *)&context->aux_data;
1899*758e9fbaSOystein Eftevaag     char *nv_file_name = NULL;
1900*758e9fbaSOystein Eftevaag     ESYS_TR auth_session;
1901*758e9fbaSOystein Eftevaag 
1902*758e9fbaSOystein Eftevaag     switch (context->nv_cmd.nv_write_state) {
1903*758e9fbaSOystein Eftevaag     statecase(context->nv_cmd.nv_write_state, NV2_WRITE_INIT);
1904*758e9fbaSOystein Eftevaag         memset(&context->nv_cmd.nv_object, 0, sizeof(IFAPI_OBJECT));
1905*758e9fbaSOystein Eftevaag         context->nv_cmd.nvPath = nvPath;
1906*758e9fbaSOystein Eftevaag         context->nv_cmd.offset = param_offset;
1907*758e9fbaSOystein Eftevaag         context->nv_cmd.numBytes = size;
1908*758e9fbaSOystein Eftevaag         context->nv_cmd.data = data;
1909*758e9fbaSOystein Eftevaag         if (context->nv_cmd.numBytes > context->nv_buffer_max)
1910*758e9fbaSOystein Eftevaag             aux_data->size = context->nv_buffer_max;
1911*758e9fbaSOystein Eftevaag         else
1912*758e9fbaSOystein Eftevaag             aux_data->size = context->nv_cmd.numBytes;
1913*758e9fbaSOystein Eftevaag         context->nv_cmd.data_idx = 0;
1914*758e9fbaSOystein Eftevaag 
1915*758e9fbaSOystein Eftevaag         /* Use calloc to ensure zero padding for write buffer. */
1916*758e9fbaSOystein Eftevaag         context->nv_cmd.write_data = calloc(size, 1);
1917*758e9fbaSOystein Eftevaag         goto_if_null2(context->nv_cmd.write_data, "Out of memory.", r,
1918*758e9fbaSOystein Eftevaag                       TSS2_FAPI_RC_MEMORY,
1919*758e9fbaSOystein Eftevaag                       error_cleanup);
1920*758e9fbaSOystein Eftevaag         memcpy(context->nv_cmd.write_data, data, size);
1921*758e9fbaSOystein Eftevaag         memcpy(&aux_data->buffer[0], &context->nv_cmd.data[0], aux_data->size);
1922*758e9fbaSOystein Eftevaag 
1923*758e9fbaSOystein Eftevaag         /* Prepare reading of the key from keystore. */
1924*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_async(&context->keystore, &context->io,
1925*758e9fbaSOystein Eftevaag                                       context->nv_cmd.nvPath);
1926*758e9fbaSOystein Eftevaag         return_if_error2(r, "Could not open: %s", context->nv_cmd.nvPath);
1927*758e9fbaSOystein Eftevaag         fallthrough;
1928*758e9fbaSOystein Eftevaag 
1929*758e9fbaSOystein Eftevaag     statecase(context->nv_cmd.nv_write_state, NV2_WRITE_READ);
1930*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
1931*758e9fbaSOystein Eftevaag         return_try_again(r);
1932*758e9fbaSOystein Eftevaag         return_if_error(r, "read_finish failed");
1933*758e9fbaSOystein Eftevaag 
1934*758e9fbaSOystein Eftevaag         if (object->objectType != IFAPI_NV_OBJ)
1935*758e9fbaSOystein Eftevaag             goto_error(r, TSS2_FAPI_RC_BAD_PATH, "%s is no NV object.", error_cleanup,
1936*758e9fbaSOystein Eftevaag                        context->nv_cmd.nvPath);
1937*758e9fbaSOystein Eftevaag 
1938*758e9fbaSOystein Eftevaag         r = ifapi_initialize_object(context->esys, object);
1939*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
1940*758e9fbaSOystein Eftevaag 
1941*758e9fbaSOystein Eftevaag         /* Store object info in context */
1942*758e9fbaSOystein Eftevaag         nv_index = context->nv_cmd.nv_object.handle;
1943*758e9fbaSOystein Eftevaag         context->nv_cmd.esys_handle = nv_index;
1944*758e9fbaSOystein Eftevaag         context->nv_cmd.nv_obj = object->misc.nv;
1945*758e9fbaSOystein Eftevaag 
1946*758e9fbaSOystein Eftevaag         /* Determine the object which will be uses for authorization. */
1947*758e9fbaSOystein Eftevaag         if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_PPWRITE) {
1948*758e9fbaSOystein Eftevaag             ifapi_init_hierarchy_object(auth_object, ESYS_TR_RH_PLATFORM);
1949*758e9fbaSOystein Eftevaag             auth_index = ESYS_TR_RH_PLATFORM;
1950*758e9fbaSOystein Eftevaag         } else {
1951*758e9fbaSOystein Eftevaag             if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_OWNERWRITE) {
1952*758e9fbaSOystein Eftevaag                 ifapi_init_hierarchy_object(auth_object, ESYS_TR_RH_OWNER);
1953*758e9fbaSOystein Eftevaag                 auth_index = ESYS_TR_RH_OWNER;
1954*758e9fbaSOystein Eftevaag             } else {
1955*758e9fbaSOystein Eftevaag                 auth_index = nv_index;
1956*758e9fbaSOystein Eftevaag             }
1957*758e9fbaSOystein Eftevaag             *auth_object = *object;
1958*758e9fbaSOystein Eftevaag         }
1959*758e9fbaSOystein Eftevaag         context->nv_cmd.auth_index = auth_index;
1960*758e9fbaSOystein Eftevaag 
1961*758e9fbaSOystein Eftevaag         /* Get A session for authorizing the NV write operation. */
1962*758e9fbaSOystein Eftevaag         r = ifapi_get_sessions_async(context, IFAPI_SESSION_GENEK | IFAPI_SESSION1,
1963*758e9fbaSOystein Eftevaag                                          TPMA_SESSION_DECRYPT, 0);
1964*758e9fbaSOystein Eftevaag         goto_if_error(r, "Create sessions", error_cleanup);
1965*758e9fbaSOystein Eftevaag 
1966*758e9fbaSOystein Eftevaag         fallthrough;
1967*758e9fbaSOystein Eftevaag 
1968*758e9fbaSOystein Eftevaag     statecase(context->nv_cmd.nv_write_state, NV2_WRITE_WAIT_FOR_SESSSION);
1969*758e9fbaSOystein Eftevaag         r = ifapi_get_sessions_finish(context, &context->profiles.default_profile,
1970*758e9fbaSOystein Eftevaag                                       object->misc.nv.public.nvPublic.nameAlg);
1971*758e9fbaSOystein Eftevaag         return_try_again(r);
1972*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
1973*758e9fbaSOystein Eftevaag 
1974*758e9fbaSOystein Eftevaag         fallthrough;
1975*758e9fbaSOystein Eftevaag 
1976*758e9fbaSOystein Eftevaag     statecase(context->nv_cmd.nv_write_state, NV2_WRITE_AUTHORIZE);
1977*758e9fbaSOystein Eftevaag         r = ifapi_authorize_object(context, auth_object, &auth_session);
1978*758e9fbaSOystein Eftevaag         FAPI_SYNC(r, "Authorize NV object.", error_cleanup);
1979*758e9fbaSOystein Eftevaag 
1980*758e9fbaSOystein Eftevaag         /* Prepare the writing to NV ram. */
1981*758e9fbaSOystein Eftevaag         r = Esys_NV_Write_Async(context->esys,
1982*758e9fbaSOystein Eftevaag                                 context->nv_cmd.auth_index,
1983*758e9fbaSOystein Eftevaag                                 nv_index,
1984*758e9fbaSOystein Eftevaag                                 auth_session,
1985*758e9fbaSOystein Eftevaag                                 context->session2,
1986*758e9fbaSOystein Eftevaag                                 ESYS_TR_NONE,
1987*758e9fbaSOystein Eftevaag                                 aux_data,
1988*758e9fbaSOystein Eftevaag                                 context->nv_cmd.data_idx);
1989*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, " Fapi_NvWrite_Async", error_cleanup);
1990*758e9fbaSOystein Eftevaag 
1991*758e9fbaSOystein Eftevaag         if (!(object->misc.nv.public.nvPublic.attributes & TPMA_NV_NO_DA))
1992*758e9fbaSOystein Eftevaag             context->nv_cmd.nv_write_state = NV2_WRITE_AUTH_SENT;
1993*758e9fbaSOystein Eftevaag         else
1994*758e9fbaSOystein Eftevaag             context->nv_cmd.nv_write_state = NV2_WRITE_NULL_AUTH_SENT;
1995*758e9fbaSOystein Eftevaag 
1996*758e9fbaSOystein Eftevaag         context->nv_cmd.bytesRequested = aux_data->size;
1997*758e9fbaSOystein Eftevaag 
1998*758e9fbaSOystein Eftevaag         fallthrough;
1999*758e9fbaSOystein Eftevaag 
2000*758e9fbaSOystein Eftevaag     case NV2_WRITE_AUTH_SENT:
2001*758e9fbaSOystein Eftevaag     case NV2_WRITE_NULL_AUTH_SENT:
2002*758e9fbaSOystein Eftevaag         r = Esys_NV_Write_Finish(context->esys);
2003*758e9fbaSOystein Eftevaag         return_try_again(r);
2004*758e9fbaSOystein Eftevaag 
2005*758e9fbaSOystein Eftevaag         if ((r & ~TPM2_RC_N_MASK) == TPM2_RC_BAD_AUTH) {
2006*758e9fbaSOystein Eftevaag             if (context->nv_cmd.nv_write_state == NV2_WRITE_NULL_AUTH_SENT) {
2007*758e9fbaSOystein Eftevaag                 IFAPI_OBJECT *auth_object = &context->nv_cmd.auth_object;
2008*758e9fbaSOystein Eftevaag                 r = ifapi_set_auth(context, auth_object, "NV Write");
2009*758e9fbaSOystein Eftevaag                 goto_if_error_reset_state(r, " Fapi_NvWrite_Finish", error_cleanup);
2010*758e9fbaSOystein Eftevaag 
2011*758e9fbaSOystein Eftevaag                 /* Prepare the writing to NV ram. */
2012*758e9fbaSOystein Eftevaag                 r = Esys_NV_Write_Async(context->esys,
2013*758e9fbaSOystein Eftevaag                                         context->nv_cmd.auth_index,
2014*758e9fbaSOystein Eftevaag                                         nv_index,
2015*758e9fbaSOystein Eftevaag                                         (!context->policy.session
2016*758e9fbaSOystein Eftevaag                                          || context->policy.session == ESYS_TR_NONE) ? context->session1 :
2017*758e9fbaSOystein Eftevaag                                         context->policy.session,
2018*758e9fbaSOystein Eftevaag                                         context->session2,
2019*758e9fbaSOystein Eftevaag                                         ESYS_TR_NONE,
2020*758e9fbaSOystein Eftevaag                                         aux_data,
2021*758e9fbaSOystein Eftevaag                                         context->nv_cmd.data_idx);
2022*758e9fbaSOystein Eftevaag                 goto_if_error_reset_state(r, "FAPI NV_Write_Async", error_cleanup);
2023*758e9fbaSOystein Eftevaag 
2024*758e9fbaSOystein Eftevaag                 context->nv_cmd.nv_write_state = NV2_WRITE_AUTH_SENT;
2025*758e9fbaSOystein Eftevaag                 return TSS2_FAPI_RC_TRY_AGAIN;
2026*758e9fbaSOystein Eftevaag             }
2027*758e9fbaSOystein Eftevaag         }
2028*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "FAPI NV_Write_Finish", error_cleanup);
2029*758e9fbaSOystein Eftevaag 
2030*758e9fbaSOystein Eftevaag         context->nv_cmd.numBytes -= context->nv_cmd.bytesRequested;
2031*758e9fbaSOystein Eftevaag 
2032*758e9fbaSOystein Eftevaag         if (context->nv_cmd.numBytes > 0) {
2033*758e9fbaSOystein Eftevaag             /* Increment data idx with number of transmitted bytes. */
2034*758e9fbaSOystein Eftevaag             context->nv_cmd.data_idx += aux_data->size;
2035*758e9fbaSOystein Eftevaag             if (context->nv_cmd.numBytes > context->nv_buffer_max)
2036*758e9fbaSOystein Eftevaag                 aux_data->size = context->nv_buffer_max;
2037*758e9fbaSOystein Eftevaag             else
2038*758e9fbaSOystein Eftevaag                 aux_data->size = context->nv_cmd.numBytes;
2039*758e9fbaSOystein Eftevaag             memcpy(&aux_data->buffer[0],
2040*758e9fbaSOystein Eftevaag                    &context->nv_cmd.write_data[context->nv_cmd.data_idx],
2041*758e9fbaSOystein Eftevaag                    aux_data->size);
2042*758e9fbaSOystein Eftevaag 
2043*758e9fbaSOystein Eftevaag             statecase(context->nv_cmd.nv_write_state, NV2_WRITE_AUTHORIZE2);
2044*758e9fbaSOystein Eftevaag                 r = ifapi_authorize_object(context, auth_object, &auth_session);
2045*758e9fbaSOystein Eftevaag                 FAPI_SYNC(r, "Authorize NV object.", error_cleanup);
2046*758e9fbaSOystein Eftevaag 
2047*758e9fbaSOystein Eftevaag             /* Prepare the writing to NV ram */
2048*758e9fbaSOystein Eftevaag             r = Esys_NV_Write_Async(context->esys,
2049*758e9fbaSOystein Eftevaag                                     context->nv_cmd.auth_index,
2050*758e9fbaSOystein Eftevaag                                     nv_index,
2051*758e9fbaSOystein Eftevaag                                     auth_session,
2052*758e9fbaSOystein Eftevaag                                     context->session2,
2053*758e9fbaSOystein Eftevaag                                     ESYS_TR_NONE,
2054*758e9fbaSOystein Eftevaag                                     aux_data,
2055*758e9fbaSOystein Eftevaag                                     context->nv_cmd.data_idx);
2056*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "FAPI NV_Write", error_cleanup);
2057*758e9fbaSOystein Eftevaag 
2058*758e9fbaSOystein Eftevaag             context->nv_cmd.bytesRequested = aux_data->size;
2059*758e9fbaSOystein Eftevaag             context->nv_cmd.nv_write_state = NV2_WRITE_AUTH_SENT;
2060*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_TRY_AGAIN;
2061*758e9fbaSOystein Eftevaag 
2062*758e9fbaSOystein Eftevaag         }
2063*758e9fbaSOystein Eftevaag         fallthrough;
2064*758e9fbaSOystein Eftevaag 
2065*758e9fbaSOystein Eftevaag     statecase(context->nv_cmd.nv_write_state, NV2_WRITE_WRITE_PREPARE);
2066*758e9fbaSOystein Eftevaag         /* Set written bit in keystore */
2067*758e9fbaSOystein Eftevaag         context->nv_cmd.nv_object.misc.nv.public.nvPublic.attributes |= TPMA_NV_WRITTEN;
2068*758e9fbaSOystein Eftevaag         /* Perform esys serialization if necessary */
2069*758e9fbaSOystein Eftevaag         r = ifapi_esys_serialize_object(context->esys, &context->nv_cmd.nv_object);
2070*758e9fbaSOystein Eftevaag         goto_if_error(r, "Prepare serialization", error_cleanup);
2071*758e9fbaSOystein Eftevaag 
2072*758e9fbaSOystein Eftevaag         /* Start writing the NV object to the key store */
2073*758e9fbaSOystein Eftevaag         r = ifapi_keystore_store_async(&context->keystore, &context->io,
2074*758e9fbaSOystein Eftevaag                                        context->nv_cmd.nvPath,
2075*758e9fbaSOystein Eftevaag                                        &context->nv_cmd.nv_object);
2076*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
2077*758e9fbaSOystein Eftevaag                                   context->nv_cmd.nvPath);
2078*758e9fbaSOystein Eftevaag         context->nv_cmd.nv_write_state = NV2_WRITE_WRITE;
2079*758e9fbaSOystein Eftevaag         fallthrough;
2080*758e9fbaSOystein Eftevaag 
2081*758e9fbaSOystein Eftevaag     statecase(context->nv_cmd.nv_write_state, NV2_WRITE_WRITE);
2082*758e9fbaSOystein Eftevaag         /* Finish writing the NV object to the key store */
2083*758e9fbaSOystein Eftevaag         r = ifapi_keystore_store_finish(&context->keystore, &context->io);
2084*758e9fbaSOystein Eftevaag         return_try_again(r);
2085*758e9fbaSOystein Eftevaag         return_if_error_reset_state(r, "write_finish failed");
2086*758e9fbaSOystein Eftevaag 
2087*758e9fbaSOystein Eftevaag         LOG_DEBUG("success");
2088*758e9fbaSOystein Eftevaag         r = TSS2_RC_SUCCESS;
2089*758e9fbaSOystein Eftevaag 
2090*758e9fbaSOystein Eftevaag         context->nv_cmd.nv_write_state = NV2_WRITE_INIT;
2091*758e9fbaSOystein Eftevaag         break;
2092*758e9fbaSOystein Eftevaag 
2093*758e9fbaSOystein Eftevaag     statecasedefault(context->nv_cmd.nv_write_state);
2094*758e9fbaSOystein Eftevaag     }
2095*758e9fbaSOystein Eftevaag 
2096*758e9fbaSOystein Eftevaag error_cleanup:
2097*758e9fbaSOystein Eftevaag     SAFE_FREE(nv_file_name);
2098*758e9fbaSOystein Eftevaag     SAFE_FREE(context->nv_cmd.write_data);
2099*758e9fbaSOystein Eftevaag     return r;
2100*758e9fbaSOystein Eftevaag }
2101*758e9fbaSOystein Eftevaag 
2102*758e9fbaSOystein Eftevaag /** State machine to read data from the NV ram of the TPM.
2103*758e9fbaSOystein Eftevaag  *
2104*758e9fbaSOystein Eftevaag  * Context nv_cmd has to be prepared before the call of this function:
2105*758e9fbaSOystein Eftevaag  * - auth_index The ESAPI handle of the authorization object.
2106*758e9fbaSOystein Eftevaag  * - numBytes The number of bytes which should be read.
2107*758e9fbaSOystein Eftevaag  * - esys_handle The ESAPI handle of the NV object.
2108*758e9fbaSOystein Eftevaag  *
2109*758e9fbaSOystein Eftevaag  * @param[in,out] context for storing all state information.
2110*758e9fbaSOystein Eftevaag  * @param[out] data the data fetched from TPM.
2111*758e9fbaSOystein Eftevaag  * @param[in,out] size The number of bytes requested and fetched.
2112*758e9fbaSOystein Eftevaag  *
2113*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the data was read successfully.
2114*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2115*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2116*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
2117*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
2118*758e9fbaSOystein Eftevaag  +         not covered by other return codes.
2119*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the object
2120*758e9fbaSOystein Eftevaag  *         store.
2121*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy for a certain path was not found.
2122*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
2123*758e9fbaSOystein Eftevaag  *         not successful.
2124*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for the
2125*758e9fbaSOystein Eftevaag  *         execution fails.
2126*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
2127*758e9fbaSOystein Eftevaag  *         is not defined.
2128*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
2129*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
2130*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2131*758e9fbaSOystein Eftevaag  *         operation already pending.
2132*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
2133*758e9fbaSOystein Eftevaag  */
2134*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_nv_read(FAPI_CONTEXT * context,uint8_t ** data,size_t * size)2135*758e9fbaSOystein Eftevaag ifapi_nv_read(
2136*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
2137*758e9fbaSOystein Eftevaag     uint8_t     **data,
2138*758e9fbaSOystein Eftevaag     size_t       *size)
2139*758e9fbaSOystein Eftevaag {
2140*758e9fbaSOystein Eftevaag     TSS2_RC r;
2141*758e9fbaSOystein Eftevaag     UINT16 aux_size;
2142*758e9fbaSOystein Eftevaag     TPM2B_MAX_NV_BUFFER *aux_data;
2143*758e9fbaSOystein Eftevaag     UINT16 bytesRequested = context->nv_cmd.bytesRequested;
2144*758e9fbaSOystein Eftevaag     size_t *numBytes = &context->nv_cmd.numBytes;
2145*758e9fbaSOystein Eftevaag     ESYS_TR nv_index = context->nv_cmd.esys_handle;
2146*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *auth_object = &context->nv_cmd.auth_object;
2147*758e9fbaSOystein Eftevaag     ESYS_TR session;
2148*758e9fbaSOystein Eftevaag 
2149*758e9fbaSOystein Eftevaag     switch (context->nv_cmd.nv_read_state) {
2150*758e9fbaSOystein Eftevaag     statecase(context->nv_cmd.nv_read_state, NV_READ_INIT);
2151*758e9fbaSOystein Eftevaag         LOG_TRACE("NV_READ_INIT");
2152*758e9fbaSOystein Eftevaag         context->nv_cmd.rdata = NULL;
2153*758e9fbaSOystein Eftevaag         fallthrough;
2154*758e9fbaSOystein Eftevaag 
2155*758e9fbaSOystein Eftevaag     statecase(context->nv_cmd.nv_read_state, NV_READ_AUTHORIZE);
2156*758e9fbaSOystein Eftevaag         LOG_TRACE("NV_READ_AUTHORIZE");
2157*758e9fbaSOystein Eftevaag         r = ifapi_authorize_object(context, auth_object, &session);
2158*758e9fbaSOystein Eftevaag         FAPI_SYNC(r, "Authorize NV object.", error_cleanup);
2159*758e9fbaSOystein Eftevaag 
2160*758e9fbaSOystein Eftevaag         if (*numBytes > context->nv_buffer_max)
2161*758e9fbaSOystein Eftevaag             aux_size = context->nv_buffer_max;
2162*758e9fbaSOystein Eftevaag         else
2163*758e9fbaSOystein Eftevaag             aux_size = *numBytes;
2164*758e9fbaSOystein Eftevaag 
2165*758e9fbaSOystein Eftevaag         /* Prepare the reading from NV ram. */
2166*758e9fbaSOystein Eftevaag         r = Esys_NV_Read_Async(context->esys,
2167*758e9fbaSOystein Eftevaag                                context->nv_cmd.auth_index,
2168*758e9fbaSOystein Eftevaag                                nv_index,
2169*758e9fbaSOystein Eftevaag                                session,
2170*758e9fbaSOystein Eftevaag                                ESYS_TR_NONE,
2171*758e9fbaSOystein Eftevaag                                ESYS_TR_NONE,
2172*758e9fbaSOystein Eftevaag                                aux_size,
2173*758e9fbaSOystein Eftevaag                                0);
2174*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, " Fapi_NvRead_Async", error_cleanup);
2175*758e9fbaSOystein Eftevaag 
2176*758e9fbaSOystein Eftevaag         context->nv_cmd.nv_read_state = NV_READ_AUTH_SENT;
2177*758e9fbaSOystein Eftevaag         context->nv_cmd.bytesRequested = aux_size;
2178*758e9fbaSOystein Eftevaag 
2179*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
2180*758e9fbaSOystein Eftevaag 
2181*758e9fbaSOystein Eftevaag     statecase(context->nv_cmd.nv_read_state, NV_READ_AUTH_SENT);
2182*758e9fbaSOystein Eftevaag         LOG_TRACE("NV_READ_NULL_AUTH_SENT");
2183*758e9fbaSOystein Eftevaag         if (context->nv_cmd.rdata == NULL) {
2184*758e9fbaSOystein Eftevaag             /* Allocate the data buffer if not already initialized. */
2185*758e9fbaSOystein Eftevaag             LOG_TRACE("Allocate %zu bytes", *numBytes);
2186*758e9fbaSOystein Eftevaag             context->nv_cmd.rdata = malloc(*numBytes);
2187*758e9fbaSOystein Eftevaag         }
2188*758e9fbaSOystein Eftevaag         *data = context->nv_cmd.rdata;
2189*758e9fbaSOystein Eftevaag         goto_if_null(*data, "Malloc failed", TSS2_FAPI_RC_MEMORY, error_cleanup);
2190*758e9fbaSOystein Eftevaag 
2191*758e9fbaSOystein Eftevaag         r = Esys_NV_Read_Finish(context->esys, &aux_data);
2192*758e9fbaSOystein Eftevaag 
2193*758e9fbaSOystein Eftevaag         if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
2194*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_TRY_AGAIN;
2195*758e9fbaSOystein Eftevaag 
2196*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "FAPI NV_Read_Finish", error_cleanup);
2197*758e9fbaSOystein Eftevaag 
2198*758e9fbaSOystein Eftevaag         if (aux_data->size < bytesRequested)
2199*758e9fbaSOystein Eftevaag             *numBytes = 0;
2200*758e9fbaSOystein Eftevaag         else
2201*758e9fbaSOystein Eftevaag             *numBytes -= aux_data->size;
2202*758e9fbaSOystein Eftevaag         memcpy(*data + context->nv_cmd.data_idx, &aux_data->buffer[0],
2203*758e9fbaSOystein Eftevaag                aux_data->size);
2204*758e9fbaSOystein Eftevaag         context->nv_cmd.data_idx += aux_data->size;
2205*758e9fbaSOystein Eftevaag         free(aux_data);
2206*758e9fbaSOystein Eftevaag         if (*numBytes > 0) {
2207*758e9fbaSOystein Eftevaag             statecase(context->nv_cmd.nv_read_state, NV_READ_AUTHORIZE2);
2208*758e9fbaSOystein Eftevaag                 r = ifapi_authorize_object(context, auth_object, &session);
2209*758e9fbaSOystein Eftevaag                 FAPI_SYNC(r, "Authorize NV object.", error_cleanup);
2210*758e9fbaSOystein Eftevaag 
2211*758e9fbaSOystein Eftevaag             /* The reading of the NV data is not completed. The next
2212*758e9fbaSOystein Eftevaag             reading will be prepared. */
2213*758e9fbaSOystein Eftevaag             if (*numBytes > context->nv_buffer_max)
2214*758e9fbaSOystein Eftevaag                 aux_size = context->nv_buffer_max;
2215*758e9fbaSOystein Eftevaag             else
2216*758e9fbaSOystein Eftevaag                 aux_size = *numBytes;
2217*758e9fbaSOystein Eftevaag 
2218*758e9fbaSOystein Eftevaag             r = Esys_NV_Read_Async(context->esys,
2219*758e9fbaSOystein Eftevaag                                    context->nv_cmd.auth_index,
2220*758e9fbaSOystein Eftevaag                                    nv_index,
2221*758e9fbaSOystein Eftevaag                                    session,
2222*758e9fbaSOystein Eftevaag                                    ESYS_TR_NONE,
2223*758e9fbaSOystein Eftevaag                                    ESYS_TR_NONE,
2224*758e9fbaSOystein Eftevaag                                    aux_size,
2225*758e9fbaSOystein Eftevaag                                    context->nv_cmd.data_idx);
2226*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "FAPI NV_Read", error_cleanup);
2227*758e9fbaSOystein Eftevaag             context->nv_cmd.bytesRequested = aux_size;
2228*758e9fbaSOystein Eftevaag             context->nv_cmd.nv_read_state = NV_READ_AUTH_SENT;
2229*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_TRY_AGAIN;
2230*758e9fbaSOystein Eftevaag         } else {
2231*758e9fbaSOystein Eftevaag             *size = context->nv_cmd.data_idx;
2232*758e9fbaSOystein Eftevaag             context->nv_cmd.nv_read_state = NV_READ_INIT;
2233*758e9fbaSOystein Eftevaag             LOG_DEBUG("success");
2234*758e9fbaSOystein Eftevaag             r = TSS2_RC_SUCCESS;
2235*758e9fbaSOystein Eftevaag             break;
2236*758e9fbaSOystein Eftevaag         }
2237*758e9fbaSOystein Eftevaag     statecasedefault(context->nv_cmd.nv_read_state);
2238*758e9fbaSOystein Eftevaag     }
2239*758e9fbaSOystein Eftevaag 
2240*758e9fbaSOystein Eftevaag error_cleanup:
2241*758e9fbaSOystein Eftevaag     return r;
2242*758e9fbaSOystein Eftevaag }
2243*758e9fbaSOystein Eftevaag 
2244*758e9fbaSOystein Eftevaag #define min(X,Y) (X>Y)?Y:X
2245*758e9fbaSOystein Eftevaag 
2246*758e9fbaSOystein Eftevaag /** State machine to retrieve random data from TPM.
2247*758e9fbaSOystein Eftevaag  *
2248*758e9fbaSOystein Eftevaag  * If the buffer size exceeds the maximum size, several ESAPI calls are made.
2249*758e9fbaSOystein Eftevaag  *
2250*758e9fbaSOystein Eftevaag  * @param[in,out] context for storing all state information.
2251*758e9fbaSOystein Eftevaag  * @param[in] numBytes Number of random bytes to be computed.
2252*758e9fbaSOystein Eftevaag  * @param[out] data The random data.
2253*758e9fbaSOystein Eftevaag  *
2254*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If random data can be computed.
2255*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2256*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2257*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
2258*758e9fbaSOystein Eftevaag  *         the function.
2259*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
2260*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
2261*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2262*758e9fbaSOystein Eftevaag  *         operation already pending.
2263*758e9fbaSOystein Eftevaag  */
2264*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_random(FAPI_CONTEXT * context,size_t numBytes,uint8_t ** data)2265*758e9fbaSOystein Eftevaag ifapi_get_random(FAPI_CONTEXT *context, size_t numBytes, uint8_t **data)
2266*758e9fbaSOystein Eftevaag {
2267*758e9fbaSOystein Eftevaag     TSS2_RC r;
2268*758e9fbaSOystein Eftevaag     TPM2B_DIGEST *aux_data = NULL;
2269*758e9fbaSOystein Eftevaag 
2270*758e9fbaSOystein Eftevaag     switch (context->get_random_state) {
2271*758e9fbaSOystein Eftevaag     statecase(context->get_random_state, GET_RANDOM_INIT);
2272*758e9fbaSOystein Eftevaag         context->get_random.numBytes = numBytes;
2273*758e9fbaSOystein Eftevaag         context->get_random.data = calloc(context->get_random.numBytes, 1);
2274*758e9fbaSOystein Eftevaag         context->get_random.idx = 0;
2275*758e9fbaSOystein Eftevaag         return_if_null(context->get_random.data, "FAPI out of memory.",
2276*758e9fbaSOystein Eftevaag                        TSS2_FAPI_RC_MEMORY);
2277*758e9fbaSOystein Eftevaag 
2278*758e9fbaSOystein Eftevaag         /* Prepare the creation of random data. */
2279*758e9fbaSOystein Eftevaag         r = Esys_GetRandom_Async(context->esys,
2280*758e9fbaSOystein Eftevaag                                  context->session1,
2281*758e9fbaSOystein Eftevaag                                  ESYS_TR_NONE, ESYS_TR_NONE,
2282*758e9fbaSOystein Eftevaag                                  min(context->get_random.numBytes, sizeof(TPMU_HA)));
2283*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "FAPI GetRandom", error_cleanup);
2284*758e9fbaSOystein Eftevaag         fallthrough;
2285*758e9fbaSOystein Eftevaag 
2286*758e9fbaSOystein Eftevaag     statecase(context->get_random_state, GET_RANDOM_SENT);
2287*758e9fbaSOystein Eftevaag         r = Esys_GetRandom_Finish(context->esys, &aux_data);
2288*758e9fbaSOystein Eftevaag         return_try_again(r);
2289*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "FAPI GetRandom_Finish", error_cleanup);
2290*758e9fbaSOystein Eftevaag 
2291*758e9fbaSOystein Eftevaag         if (aux_data -> size > context->get_random.numBytes) {
2292*758e9fbaSOystein Eftevaag             goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "TPM returned too many bytes",
2293*758e9fbaSOystein Eftevaag                        error_cleanup);
2294*758e9fbaSOystein Eftevaag         }
2295*758e9fbaSOystein Eftevaag 
2296*758e9fbaSOystein Eftevaag         /* Save created random data. */
2297*758e9fbaSOystein Eftevaag         memcpy(context->get_random.data + context->get_random.idx, &aux_data->buffer[0],
2298*758e9fbaSOystein Eftevaag                aux_data->size);
2299*758e9fbaSOystein Eftevaag         context->get_random.numBytes -= aux_data->size;
2300*758e9fbaSOystein Eftevaag         context->get_random.idx += aux_data->size;
2301*758e9fbaSOystein Eftevaag         Esys_Free(aux_data);
2302*758e9fbaSOystein Eftevaag         aux_data = NULL;
2303*758e9fbaSOystein Eftevaag         if (context->get_random.numBytes > 0) {
2304*758e9fbaSOystein Eftevaag 
2305*758e9fbaSOystein Eftevaag             /* Continue creaion of random data if needed. */
2306*758e9fbaSOystein Eftevaag             r = Esys_GetRandom_Async(context->esys, context->session1, ESYS_TR_NONE,
2307*758e9fbaSOystein Eftevaag                                      ESYS_TR_NONE, min(context->get_random.numBytes, sizeof(TPMU_HA)));
2308*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "FAPI GetRandom", error_cleanup);
2309*758e9fbaSOystein Eftevaag 
2310*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_TRY_AGAIN;
2311*758e9fbaSOystein Eftevaag         }
2312*758e9fbaSOystein Eftevaag         break;
2313*758e9fbaSOystein Eftevaag 
2314*758e9fbaSOystein Eftevaag     statecasedefault(context->get_random_state);
2315*758e9fbaSOystein Eftevaag     }
2316*758e9fbaSOystein Eftevaag 
2317*758e9fbaSOystein Eftevaag     *data = context->get_random.data;
2318*758e9fbaSOystein Eftevaag 
2319*758e9fbaSOystein Eftevaag     LOG_DEBUG("success");
2320*758e9fbaSOystein Eftevaag     context->get_random_state = GET_RANDOM_INIT;
2321*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
2322*758e9fbaSOystein Eftevaag 
2323*758e9fbaSOystein Eftevaag error_cleanup:
2324*758e9fbaSOystein Eftevaag     if (aux_data)
2325*758e9fbaSOystein Eftevaag         Esys_Free(aux_data);
2326*758e9fbaSOystein Eftevaag     context->get_random_state = GET_RANDOM_INIT;
2327*758e9fbaSOystein Eftevaag     if (context->get_random.data != NULL)
2328*758e9fbaSOystein Eftevaag         SAFE_FREE(context->get_random.data);
2329*758e9fbaSOystein Eftevaag     return r;
2330*758e9fbaSOystein Eftevaag }
2331*758e9fbaSOystein Eftevaag 
2332*758e9fbaSOystein Eftevaag /** Load a key and initialize profile and session for ESAPI execution.
2333*758e9fbaSOystein Eftevaag  *
2334*758e9fbaSOystein Eftevaag  * This state machine prepares the session for key loading. Some
2335*758e9fbaSOystein Eftevaag  * session related parameters will be taken from profile.
2336*758e9fbaSOystein Eftevaag  *
2337*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
2338*758e9fbaSOystein Eftevaag  * @param[in]     keyPath the key path without the parent directories
2339*758e9fbaSOystein Eftevaag  *                of the key store. (e.g. HE/EK, HS/SRK/mykey)
2340*758e9fbaSOystein Eftevaag  * @param[out]    key_object The callee allocated internal representation
2341*758e9fbaSOystein Eftevaag  *                of a key object.
2342*758e9fbaSOystein Eftevaag  *
2343*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the key was loaded successfully.
2344*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2345*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2346*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
2347*758e9fbaSOystein Eftevaag  *         not covered by other return codes.
2348*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
2349*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the object
2350*758e9fbaSOystein Eftevaag  *         store.
2351*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy or key was not found.
2352*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
2353*758e9fbaSOystein Eftevaag  *         not successful.
2354*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for policy
2355*758e9fbaSOystein Eftevaag  *         execution fails.
2356*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
2357*758e9fbaSOystein Eftevaag            is not defined.
2358*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2359*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
2360*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
2361*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2362*758e9fbaSOystein Eftevaag  *         operation already pending.
2363*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
2364*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
2365*758e9fbaSOystein Eftevaag  */
2366*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_load_key(FAPI_CONTEXT * context,char const * keyPath,IFAPI_OBJECT ** key_object)2367*758e9fbaSOystein Eftevaag ifapi_load_key(
2368*758e9fbaSOystein Eftevaag     FAPI_CONTEXT  *context,
2369*758e9fbaSOystein Eftevaag     char    const *keyPath,
2370*758e9fbaSOystein Eftevaag     IFAPI_OBJECT **key_object)
2371*758e9fbaSOystein Eftevaag {
2372*758e9fbaSOystein Eftevaag     TSS2_RC r;
2373*758e9fbaSOystein Eftevaag     const IFAPI_PROFILE *profile;
2374*758e9fbaSOystein Eftevaag 
2375*758e9fbaSOystein Eftevaag     return_if_null(keyPath, "Bad reference for key path.",
2376*758e9fbaSOystein Eftevaag                    TSS2_FAPI_RC_BAD_REFERENCE);
2377*758e9fbaSOystein Eftevaag 
2378*758e9fbaSOystein Eftevaag     switch (context->Key_Sign.state) {
2379*758e9fbaSOystein Eftevaag     statecase(context->Key_Sign.state, SIGN_INIT);
2380*758e9fbaSOystein Eftevaag         context->Key_Sign.keyPath = keyPath;
2381*758e9fbaSOystein Eftevaag 
2382*758e9fbaSOystein Eftevaag         /* Prepare the session creation. */
2383*758e9fbaSOystein Eftevaag         r = ifapi_get_sessions_async(context,
2384*758e9fbaSOystein Eftevaag                                      IFAPI_SESSION_GENEK | IFAPI_SESSION1,
2385*758e9fbaSOystein Eftevaag                                      TPMA_SESSION_DECRYPT, 0);
2386*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Create sessions", error_cleanup);
2387*758e9fbaSOystein Eftevaag         fallthrough;
2388*758e9fbaSOystein Eftevaag 
2389*758e9fbaSOystein Eftevaag     statecase(context->Key_Sign.state, SIGN_WAIT_FOR_SESSION);
2390*758e9fbaSOystein Eftevaag         r = ifapi_profiles_get(&context->profiles, context->Key_Sign.keyPath, &profile);
2391*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Reading profile data", error_cleanup);
2392*758e9fbaSOystein Eftevaag 
2393*758e9fbaSOystein Eftevaag         r = ifapi_get_sessions_finish(context, profile, profile->nameAlg);
2394*758e9fbaSOystein Eftevaag         return_try_again(r);
2395*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
2396*758e9fbaSOystein Eftevaag 
2397*758e9fbaSOystein Eftevaag         /* Prepare the key loading. */
2398*758e9fbaSOystein Eftevaag         r = ifapi_load_keys_async(context, context->Key_Sign.keyPath);
2399*758e9fbaSOystein Eftevaag         goto_if_error(r, "Load keys.", error_cleanup);
2400*758e9fbaSOystein Eftevaag         fallthrough;
2401*758e9fbaSOystein Eftevaag 
2402*758e9fbaSOystein Eftevaag     statecase(context->Key_Sign.state, SIGN_WAIT_FOR_KEY);
2403*758e9fbaSOystein Eftevaag         r = ifapi_load_keys_finish(context, IFAPI_FLUSH_PARENT,
2404*758e9fbaSOystein Eftevaag                                    &context->Key_Sign.handle,
2405*758e9fbaSOystein Eftevaag                                    key_object);
2406*758e9fbaSOystein Eftevaag         return_try_again(r);
2407*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, " Load key.", error_cleanup);
2408*758e9fbaSOystein Eftevaag 
2409*758e9fbaSOystein Eftevaag         context->Key_Sign.state = SIGN_INIT;
2410*758e9fbaSOystein Eftevaag         break;
2411*758e9fbaSOystein Eftevaag 
2412*758e9fbaSOystein Eftevaag     statecasedefault(context->Key_Sign.state);
2413*758e9fbaSOystein Eftevaag     }
2414*758e9fbaSOystein Eftevaag 
2415*758e9fbaSOystein Eftevaag error_cleanup:
2416*758e9fbaSOystein Eftevaag     return r;
2417*758e9fbaSOystein Eftevaag }
2418*758e9fbaSOystein Eftevaag 
2419*758e9fbaSOystein Eftevaag /** State machine for signing operation.
2420*758e9fbaSOystein Eftevaag  *
2421*758e9fbaSOystein Eftevaag  * The key used for signing will be authorized and the signing of the passed data
2422*758e9fbaSOystein Eftevaag  * will be executed.
2423*758e9fbaSOystein Eftevaag  *
2424*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
2425*758e9fbaSOystein Eftevaag  * @param[in]     sig_key_object The Fapi key object which will be used to
2426*758e9fbaSOystein Eftevaag  *                sign the passed digest.
2427*758e9fbaSOystein Eftevaag  * @param[in]     padding is the padding algorithm used. Possible values are RSA_SSA,
2428*758e9fbaSOystein Eftevaag  *                RSA_PPSS (case insensitive). padding MAY be NULL.
2429*758e9fbaSOystein Eftevaag  * @param[in]     digest is the data to be signed, already hashed.
2430*758e9fbaSOystein Eftevaag  *                digest MUST NOT be NULL.
2431*758e9fbaSOystein Eftevaag  * @param[out]    tpm_signature returns the signature in binary form (DER format).
2432*758e9fbaSOystein Eftevaag  *                tpm_signature MUST NOT be NULL (callee-allocated).
2433*758e9fbaSOystein Eftevaag  * @param[out]    publicKey is the public key of the signing key in PEM format.
2434*758e9fbaSOystein Eftevaag  *                publicKey is callee allocated and MAY be NULL.
2435*758e9fbaSOystein Eftevaag  * @param[out]    certificate is the certificate associated with the signing key
2436*758e9fbaSOystein Eftevaag  *                in PEM format. certificate MAY be NULL.
2437*758e9fbaSOystein Eftevaag  *
2438*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the signing was successful.
2439*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2440*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2441*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
2442*758e9fbaSOystein Eftevaag  *         not covered by other return codes.
2443*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
2444*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
2445*758e9fbaSOystein Eftevaag  *         store.
2446*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy for a certain path was not found.
2447*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
2448*758e9fbaSOystein Eftevaag  *         not successful.
2449*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_TEMPLATE In a invalid policy is loaded during execution.
2450*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for policy
2451*758e9fbaSOystein Eftevaag  *         execution fails.
2452*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
2453*758e9fbaSOystein Eftevaag  *         is not defined.
2454*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
2455*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
2456*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2457*758e9fbaSOystein Eftevaag  *         operation already pending.
2458*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
2459*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2460*758e9fbaSOystein Eftevaag  */
2461*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_key_sign(FAPI_CONTEXT * context,IFAPI_OBJECT * sig_key_object,char const * padding,TPM2B_DIGEST * digest,TPMT_SIGNATURE ** tpm_signature,char ** publicKey,char ** certificate)2462*758e9fbaSOystein Eftevaag ifapi_key_sign(
2463*758e9fbaSOystein Eftevaag     FAPI_CONTEXT     *context,
2464*758e9fbaSOystein Eftevaag     IFAPI_OBJECT     *sig_key_object,
2465*758e9fbaSOystein Eftevaag     char const       *padding,
2466*758e9fbaSOystein Eftevaag     TPM2B_DIGEST     *digest,
2467*758e9fbaSOystein Eftevaag     TPMT_SIGNATURE  **tpm_signature,
2468*758e9fbaSOystein Eftevaag     char            **publicKey,
2469*758e9fbaSOystein Eftevaag     char            **certificate)
2470*758e9fbaSOystein Eftevaag {
2471*758e9fbaSOystein Eftevaag     TSS2_RC r;
2472*758e9fbaSOystein Eftevaag     TPMT_SIG_SCHEME sig_scheme;
2473*758e9fbaSOystein Eftevaag     ESYS_TR session;
2474*758e9fbaSOystein Eftevaag 
2475*758e9fbaSOystein Eftevaag     TPMT_TK_HASHCHECK hash_validation = {
2476*758e9fbaSOystein Eftevaag         .tag = TPM2_ST_HASHCHECK,
2477*758e9fbaSOystein Eftevaag         .hierarchy = TPM2_RH_OWNER,
2478*758e9fbaSOystein Eftevaag     };
2479*758e9fbaSOystein Eftevaag     memset(&hash_validation.digest, 0, sizeof(TPM2B_DIGEST));
2480*758e9fbaSOystein Eftevaag 
2481*758e9fbaSOystein Eftevaag     switch (context->Key_Sign.state) {
2482*758e9fbaSOystein Eftevaag     statecase(context->Key_Sign.state, SIGN_INIT);
2483*758e9fbaSOystein Eftevaag         sig_key_object = context->Key_Sign.key_object;
2484*758e9fbaSOystein Eftevaag 
2485*758e9fbaSOystein Eftevaag         r = ifapi_authorize_object(context, sig_key_object, &session);
2486*758e9fbaSOystein Eftevaag         FAPI_SYNC(r, "Authorize signature key.", cleanup);
2487*758e9fbaSOystein Eftevaag 
2488*758e9fbaSOystein Eftevaag         context->policy.session = session;
2489*758e9fbaSOystein Eftevaag 
2490*758e9fbaSOystein Eftevaag         r = ifapi_get_sig_scheme(context, sig_key_object, padding, digest, &sig_scheme);
2491*758e9fbaSOystein Eftevaag         goto_if_error(r, "Get signature scheme", cleanup);
2492*758e9fbaSOystein Eftevaag 
2493*758e9fbaSOystein Eftevaag         /* Prepare the signing operation. */
2494*758e9fbaSOystein Eftevaag         r = Esys_Sign_Async(context->esys,
2495*758e9fbaSOystein Eftevaag                             context->Key_Sign.handle,
2496*758e9fbaSOystein Eftevaag                             session,
2497*758e9fbaSOystein Eftevaag                             ESYS_TR_NONE, ESYS_TR_NONE,
2498*758e9fbaSOystein Eftevaag                             digest,
2499*758e9fbaSOystein Eftevaag                             &sig_scheme,
2500*758e9fbaSOystein Eftevaag                             &hash_validation);
2501*758e9fbaSOystein Eftevaag         goto_if_error(r, "Error: Sign", cleanup);
2502*758e9fbaSOystein Eftevaag         fallthrough;
2503*758e9fbaSOystein Eftevaag 
2504*758e9fbaSOystein Eftevaag     statecase(context->Key_Sign.state, SIGN_AUTH_SENT);
2505*758e9fbaSOystein Eftevaag         context->Key_Sign.signature = NULL;
2506*758e9fbaSOystein Eftevaag         r = Esys_Sign_Finish(context->esys,
2507*758e9fbaSOystein Eftevaag                              &context->Key_Sign.signature);
2508*758e9fbaSOystein Eftevaag         return_try_again(r);
2509*758e9fbaSOystein Eftevaag         ifapi_flush_policy_session(context, context->policy.session, r);
2510*758e9fbaSOystein Eftevaag         goto_if_error(r, "Error: Sign", cleanup);
2511*758e9fbaSOystein Eftevaag 
2512*758e9fbaSOystein Eftevaag         /* Prepare the flushing of the signing key. */
2513*758e9fbaSOystein Eftevaag         r = Esys_FlushContext_Async(context->esys, context->Key_Sign.handle);
2514*758e9fbaSOystein Eftevaag         goto_if_error(r, "Error: FlushContext", cleanup);
2515*758e9fbaSOystein Eftevaag         fallthrough;
2516*758e9fbaSOystein Eftevaag 
2517*758e9fbaSOystein Eftevaag     statecase(context->Key_Sign.state, SIGN_WAIT_FOR_FLUSH);
2518*758e9fbaSOystein Eftevaag         r = Esys_FlushContext_Finish(context->esys);
2519*758e9fbaSOystein Eftevaag         return_try_again(r);
2520*758e9fbaSOystein Eftevaag         goto_if_error(r, "Error: Sign", cleanup);
2521*758e9fbaSOystein Eftevaag 
2522*758e9fbaSOystein Eftevaag         int pem_size;
2523*758e9fbaSOystein Eftevaag         if (publicKey) {
2524*758e9fbaSOystein Eftevaag             /* Convert internal key object to PEM format. */
2525*758e9fbaSOystein Eftevaag             r = ifapi_pub_pem_key_from_tpm(&sig_key_object->misc.key.public,
2526*758e9fbaSOystein Eftevaag                                                 publicKey,
2527*758e9fbaSOystein Eftevaag                                                 &pem_size);
2528*758e9fbaSOystein Eftevaag             goto_if_error(r, "Conversion pub key to PEM failed", cleanup);
2529*758e9fbaSOystein Eftevaag         }
2530*758e9fbaSOystein Eftevaag         context->Key_Sign.handle = ESYS_TR_NONE;
2531*758e9fbaSOystein Eftevaag         *tpm_signature = context->Key_Sign.signature;
2532*758e9fbaSOystein Eftevaag         if (certificate) {
2533*758e9fbaSOystein Eftevaag             *certificate = strdup(context->Key_Sign.key_object->misc.key.certificate);
2534*758e9fbaSOystein Eftevaag             goto_if_null(*certificate, "Out of memory.",
2535*758e9fbaSOystein Eftevaag                     TSS2_FAPI_RC_MEMORY, cleanup);
2536*758e9fbaSOystein Eftevaag         }
2537*758e9fbaSOystein Eftevaag         context->Key_Sign.state = SIGN_INIT;
2538*758e9fbaSOystein Eftevaag         LOG_TRACE("success");
2539*758e9fbaSOystein Eftevaag         r = TSS2_RC_SUCCESS;
2540*758e9fbaSOystein Eftevaag         break;
2541*758e9fbaSOystein Eftevaag 
2542*758e9fbaSOystein Eftevaag     statecasedefault(context->Key_Sign.state);
2543*758e9fbaSOystein Eftevaag     }
2544*758e9fbaSOystein Eftevaag 
2545*758e9fbaSOystein Eftevaag cleanup:
2546*758e9fbaSOystein Eftevaag     if (context->Key_Sign.handle != ESYS_TR_NONE)
2547*758e9fbaSOystein Eftevaag         Esys_FlushContext(context->esys, context->Key_Sign.handle);
2548*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(context->Key_Sign.key_object);
2549*758e9fbaSOystein Eftevaag     return r;
2550*758e9fbaSOystein Eftevaag }
2551*758e9fbaSOystein Eftevaag 
2552*758e9fbaSOystein Eftevaag /** Get json encoding for FAPI object.
2553*758e9fbaSOystein Eftevaag  *
2554*758e9fbaSOystein Eftevaag  * A json representation which can be used for exporting of a FAPI object will
2555*758e9fbaSOystein Eftevaag  * be created.
2556*758e9fbaSOystein Eftevaag  *
2557*758e9fbaSOystein Eftevaag  * @param[in]   context The FAPI_CONTEXT.
2558*758e9fbaSOystein Eftevaag  * @param[in]   object The object to be serialized.
2559*758e9fbaSOystein Eftevaag  * @param[out]  json_string The json string created by the deserialzation
2560*758e9fbaSOystein Eftevaag  *              function (callee-allocated).
2561*758e9fbaSOystein Eftevaag  *
2562*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the serialization was successful.
2563*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2564*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during
2565*758e9fbaSOystein Eftevaag  *         serialization.
2566*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE If a NULL pointer was passed for
2567*758e9fbaSOystein Eftevaag  *         the object.
2568*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
2569*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2570*758e9fbaSOystein Eftevaag  */
2571*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_json(FAPI_CONTEXT * context,IFAPI_OBJECT * object,char ** json_string)2572*758e9fbaSOystein Eftevaag ifapi_get_json(FAPI_CONTEXT *context, IFAPI_OBJECT *object, char **json_string)
2573*758e9fbaSOystein Eftevaag {
2574*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
2575*758e9fbaSOystein Eftevaag     json_object *jso = NULL;
2576*758e9fbaSOystein Eftevaag 
2577*758e9fbaSOystein Eftevaag     /* Perform esys serialization if necessary */
2578*758e9fbaSOystein Eftevaag     r = ifapi_esys_serialize_object(context->esys, object);
2579*758e9fbaSOystein Eftevaag     goto_if_error(r, "Prepare serialization", cleanup);
2580*758e9fbaSOystein Eftevaag 
2581*758e9fbaSOystein Eftevaag     r = ifapi_json_IFAPI_OBJECT_serialize(object, &jso);
2582*758e9fbaSOystein Eftevaag     return_if_error(r, "Serialize duplication object");
2583*758e9fbaSOystein Eftevaag 
2584*758e9fbaSOystein Eftevaag     *json_string = strdup(json_object_to_json_string_ext(jso,
2585*758e9fbaSOystein Eftevaag                           JSON_C_TO_STRING_PRETTY));
2586*758e9fbaSOystein Eftevaag     goto_if_null2(*json_string, "Converting json to string", r, TSS2_FAPI_RC_MEMORY,
2587*758e9fbaSOystein Eftevaag                   cleanup);
2588*758e9fbaSOystein Eftevaag 
2589*758e9fbaSOystein Eftevaag cleanup:
2590*758e9fbaSOystein Eftevaag     if (jso)
2591*758e9fbaSOystein Eftevaag         json_object_put(jso);
2592*758e9fbaSOystein Eftevaag     return r;
2593*758e9fbaSOystein Eftevaag }
2594*758e9fbaSOystein Eftevaag 
2595*758e9fbaSOystein Eftevaag /** Serialize persistent objects into buffer of keystore object.
2596*758e9fbaSOystein Eftevaag  *
2597*758e9fbaSOystein Eftevaag  * NV objects and persistent keys will serialized via the ESYS API to
2598*758e9fbaSOystein Eftevaag  * enable reconstruction durinng loading from keystore.
2599*758e9fbaSOystein Eftevaag  *
2600*758e9fbaSOystein Eftevaag  * @param[in]     ectx The ESAPI context.
2601*758e9fbaSOystein Eftevaag  * @param[in,out] object  The nv object or the key.
2602*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the function call was a success.
2603*758e9fbaSOystein Eftevaag  */
2604*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_esys_serialize_object(ESYS_CONTEXT * ectx,IFAPI_OBJECT * object)2605*758e9fbaSOystein Eftevaag ifapi_esys_serialize_object(ESYS_CONTEXT *ectx, IFAPI_OBJECT *object)
2606*758e9fbaSOystein Eftevaag {
2607*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
2608*758e9fbaSOystein Eftevaag     IFAPI_KEY *key_object = NULL;
2609*758e9fbaSOystein Eftevaag     IFAPI_NV *nv_object;
2610*758e9fbaSOystein Eftevaag 
2611*758e9fbaSOystein Eftevaag     switch (object->objectType) {
2612*758e9fbaSOystein Eftevaag     case IFAPI_NV_OBJ:
2613*758e9fbaSOystein Eftevaag         nv_object = &object->misc.nv;
2614*758e9fbaSOystein Eftevaag         if (nv_object->serialization.buffer != NULL) {
2615*758e9fbaSOystein Eftevaag             /* Cleanup old buffer */
2616*758e9fbaSOystein Eftevaag             Fapi_Free(nv_object->serialization.buffer);
2617*758e9fbaSOystein Eftevaag             nv_object->serialization.buffer = NULL;
2618*758e9fbaSOystein Eftevaag         }
2619*758e9fbaSOystein Eftevaag         r = Esys_TR_Serialize(ectx, object->handle,
2620*758e9fbaSOystein Eftevaag                               &nv_object->serialization.buffer,
2621*758e9fbaSOystein Eftevaag                               &nv_object->serialization.size);
2622*758e9fbaSOystein Eftevaag         return_if_error(r, "Error serialize esys object");
2623*758e9fbaSOystein Eftevaag         break;
2624*758e9fbaSOystein Eftevaag 
2625*758e9fbaSOystein Eftevaag     case IFAPI_KEY_OBJ:
2626*758e9fbaSOystein Eftevaag         key_object = &object->misc.key;
2627*758e9fbaSOystein Eftevaag         key_object->serialization.size = 0;
2628*758e9fbaSOystein Eftevaag         if (key_object->serialization.buffer != NULL) {
2629*758e9fbaSOystein Eftevaag             /* Cleanup old buffer */
2630*758e9fbaSOystein Eftevaag             Fapi_Free(key_object->serialization.buffer);
2631*758e9fbaSOystein Eftevaag             key_object->serialization.buffer = NULL;
2632*758e9fbaSOystein Eftevaag         }
2633*758e9fbaSOystein Eftevaag         if (object->handle != ESYS_TR_NONE && key_object->persistent_handle) {
2634*758e9fbaSOystein Eftevaag             key_object->serialization.buffer = NULL;
2635*758e9fbaSOystein Eftevaag             r = Esys_TR_Serialize(ectx, object->handle,
2636*758e9fbaSOystein Eftevaag                                   &key_object->serialization.buffer,
2637*758e9fbaSOystein Eftevaag                                   &key_object->serialization.size);
2638*758e9fbaSOystein Eftevaag             return_if_error(r, "Error serialize esys object");
2639*758e9fbaSOystein Eftevaag         }
2640*758e9fbaSOystein Eftevaag         break;
2641*758e9fbaSOystein Eftevaag 
2642*758e9fbaSOystein Eftevaag     default:
2643*758e9fbaSOystein Eftevaag         /* Nothing to be done */
2644*758e9fbaSOystein Eftevaag         break;
2645*758e9fbaSOystein Eftevaag     }
2646*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
2647*758e9fbaSOystein Eftevaag }
2648*758e9fbaSOystein Eftevaag 
2649*758e9fbaSOystein Eftevaag  /** Initialize the part of an IFAPI_OBJECT  which is not serialized.
2650*758e9fbaSOystein Eftevaag   *
2651*758e9fbaSOystein Eftevaag   * For persistent objects the correspodning ESYS object will be created.
2652*758e9fbaSOystein Eftevaag   *
2653*758e9fbaSOystein Eftevaag   * @param[in,out] ectx The ESYS context.
2654*758e9fbaSOystein Eftevaag   * @param[out] object the deserialzed binary object.
2655*758e9fbaSOystein Eftevaag   * @retval TSS2_RC_SUCCESS if the function call was a success.
2656*758e9fbaSOystein Eftevaag   * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
2657*758e9fbaSOystein Eftevaag   */
2658*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_initialize_object(ESYS_CONTEXT * ectx,IFAPI_OBJECT * object)2659*758e9fbaSOystein Eftevaag ifapi_initialize_object(
2660*758e9fbaSOystein Eftevaag     ESYS_CONTEXT *ectx,
2661*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *object)
2662*758e9fbaSOystein Eftevaag {
2663*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
2664*758e9fbaSOystein Eftevaag     ESYS_TR handle;
2665*758e9fbaSOystein Eftevaag 
2666*758e9fbaSOystein Eftevaag     switch (object->objectType) {
2667*758e9fbaSOystein Eftevaag     case IFAPI_NV_OBJ:
2668*758e9fbaSOystein Eftevaag         if (object->misc.nv.serialization.size > 0) {
2669*758e9fbaSOystein Eftevaag             r = Esys_TR_Deserialize(ectx, &object->misc.nv.serialization.buffer[0],
2670*758e9fbaSOystein Eftevaag                                     object->misc.nv.serialization.size, &handle);
2671*758e9fbaSOystein Eftevaag             goto_if_error(r, "Error dserialize esys object", cleanup);
2672*758e9fbaSOystein Eftevaag         } else {
2673*758e9fbaSOystein Eftevaag             handle = ESYS_TR_NONE;
2674*758e9fbaSOystein Eftevaag         }
2675*758e9fbaSOystein Eftevaag         object->authorization_state = AUTH_INIT;
2676*758e9fbaSOystein Eftevaag         object->handle = handle;
2677*758e9fbaSOystein Eftevaag         break;
2678*758e9fbaSOystein Eftevaag 
2679*758e9fbaSOystein Eftevaag     case IFAPI_KEY_OBJ:
2680*758e9fbaSOystein Eftevaag         if (object->misc.key.serialization.size > 0) {
2681*758e9fbaSOystein Eftevaag             r = Esys_TR_Deserialize(ectx, &object->misc.key.serialization.buffer[0],
2682*758e9fbaSOystein Eftevaag                                     object->misc.key.serialization.size, &handle);
2683*758e9fbaSOystein Eftevaag             goto_if_error(r, "Error deserialize esys object", cleanup);
2684*758e9fbaSOystein Eftevaag         } else {
2685*758e9fbaSOystein Eftevaag             handle = ESYS_TR_NONE;
2686*758e9fbaSOystein Eftevaag         }
2687*758e9fbaSOystein Eftevaag         object->authorization_state = AUTH_INIT;
2688*758e9fbaSOystein Eftevaag         object->handle = handle;
2689*758e9fbaSOystein Eftevaag         break;
2690*758e9fbaSOystein Eftevaag 
2691*758e9fbaSOystein Eftevaag     default:
2692*758e9fbaSOystein Eftevaag         /* Nothing to be done */
2693*758e9fbaSOystein Eftevaag         break;
2694*758e9fbaSOystein Eftevaag     }
2695*758e9fbaSOystein Eftevaag 
2696*758e9fbaSOystein Eftevaag     return r;
2697*758e9fbaSOystein Eftevaag 
2698*758e9fbaSOystein Eftevaag cleanup:
2699*758e9fbaSOystein Eftevaag     SAFE_FREE(object->policy);
2700*758e9fbaSOystein Eftevaag     return r;
2701*758e9fbaSOystein Eftevaag }
2702*758e9fbaSOystein Eftevaag 
2703*758e9fbaSOystein Eftevaag /** Prepare key creation with an auth value.
2704*758e9fbaSOystein Eftevaag  *
2705*758e9fbaSOystein Eftevaag  * The auth value will be copied int the FAPI context for later use in key creation.
2706*758e9fbaSOystein Eftevaag  *
2707*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
2708*758e9fbaSOystein Eftevaag  * @param[in]     keyPath the key path without the parent directories
2709*758e9fbaSOystein Eftevaag  *                of the key store. (e.g. HE/EK, HS/SRK/mykey)
2710*758e9fbaSOystein Eftevaag  * @param[in]     policyPath identifies the policy to be associated with the new key.
2711*758e9fbaSOystein Eftevaag  *                policyPath MAY be NULL. If policyPath is NULL then no policy will
2712*758e9fbaSOystein Eftevaag  *                be associated with the key.
2713*758e9fbaSOystein Eftevaag  * @param[in]     authValue The authentication value of the key.
2714*758e9fbaSOystein Eftevaag  *
2715*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the preparation was successful.
2716*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS If the object with does already exist in
2717*758e9fbaSOystein Eftevaag  *         keystore.
2718*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2719*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
2720*758e9fbaSOystein Eftevaag  *         the function.
2721*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2722*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
2723*758e9fbaSOystein Eftevaag  *         config file.
2724*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2725*758e9fbaSOystein Eftevaag  *         operation already pending.
2726*758e9fbaSOystein Eftevaag  */
2727*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_key_create_prepare_auth(FAPI_CONTEXT * context,char const * keyPath,char const * policyPath,char const * authValue)2728*758e9fbaSOystein Eftevaag ifapi_key_create_prepare_auth(
2729*758e9fbaSOystein Eftevaag     FAPI_CONTEXT  *context,
2730*758e9fbaSOystein Eftevaag     char   const *keyPath,
2731*758e9fbaSOystein Eftevaag     char   const *policyPath,
2732*758e9fbaSOystein Eftevaag     char   const *authValue)
2733*758e9fbaSOystein Eftevaag {
2734*758e9fbaSOystein Eftevaag     TSS2_RC r;
2735*758e9fbaSOystein Eftevaag 
2736*758e9fbaSOystein Eftevaag     memset(&context->cmd.Key_Create.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
2737*758e9fbaSOystein Eftevaag     if (authValue) {
2738*758e9fbaSOystein Eftevaag         /* Copy the auth value */
2739*758e9fbaSOystein Eftevaag         if (strlen(authValue) > sizeof(TPMU_HA)) {
2740*758e9fbaSOystein Eftevaag             return_error(TSS2_FAPI_RC_BAD_VALUE, "Password too long.");
2741*758e9fbaSOystein Eftevaag         }
2742*758e9fbaSOystein Eftevaag         memcpy(&context->cmd.Key_Create.inSensitive.sensitive.userAuth.buffer,
2743*758e9fbaSOystein Eftevaag                authValue, strlen(authValue));
2744*758e9fbaSOystein Eftevaag         context->cmd.Key_Create.inSensitive.sensitive.userAuth.size = strlen(authValue);
2745*758e9fbaSOystein Eftevaag     }
2746*758e9fbaSOystein Eftevaag     context->cmd.Key_Create.inSensitive.sensitive.data.size = 0;
2747*758e9fbaSOystein Eftevaag     r = ifapi_key_create_prepare(context, keyPath, policyPath);
2748*758e9fbaSOystein Eftevaag     return r;
2749*758e9fbaSOystein Eftevaag }
2750*758e9fbaSOystein Eftevaag 
2751*758e9fbaSOystein Eftevaag /** Prepare key creation with an auth value and sensitive data.
2752*758e9fbaSOystein Eftevaag  *
2753*758e9fbaSOystein Eftevaag  * The auth value and the sensitive data will be copied int the FAPI context
2754*758e9fbaSOystein Eftevaag  * for later use in key creation.
2755*758e9fbaSOystein Eftevaag  *
2756*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
2757*758e9fbaSOystein Eftevaag  * @param[in]     keyPath the key path without the parent directories
2758*758e9fbaSOystein Eftevaag  *                of the key store. (e.g. HE/EK, HS/SRK/mykey)
2759*758e9fbaSOystein Eftevaag  * @param[in]     policyPath identifies the policy to be associated with the new key.
2760*758e9fbaSOystein Eftevaag  *                policyPath MAY be NULL. If policyPath is NULL then no policy will
2761*758e9fbaSOystein Eftevaag  *                be associated with the key.
2762*758e9fbaSOystein Eftevaag  * @param[in]     dataSize The size of the sensitive data.
2763*758e9fbaSOystein Eftevaag  * @param[in]     authValue The authentication value of the key.
2764*758e9fbaSOystein Eftevaag  * @param[in]     data The sensitive data.
2765*758e9fbaSOystein Eftevaag  *
2766*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the preparation was successful.
2767*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS If the object with does already exist in
2768*758e9fbaSOystein Eftevaag  *         keystore.
2769*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2770*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
2771*758e9fbaSOystein Eftevaag  *         the function.
2772*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2773*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
2774*758e9fbaSOystein Eftevaag  *         config file.
2775*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2776*758e9fbaSOystein Eftevaag  *         operation already pending.
2777*758e9fbaSOystein Eftevaag  */
2778*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_key_create_prepare_sensitive(FAPI_CONTEXT * context,char const * keyPath,char const * policyPath,size_t dataSize,char const * authValue,uint8_t const * data)2779*758e9fbaSOystein Eftevaag ifapi_key_create_prepare_sensitive(
2780*758e9fbaSOystein Eftevaag     FAPI_CONTEXT  *context,
2781*758e9fbaSOystein Eftevaag     char    const *keyPath,
2782*758e9fbaSOystein Eftevaag     char    const *policyPath,
2783*758e9fbaSOystein Eftevaag     size_t         dataSize,
2784*758e9fbaSOystein Eftevaag     char    const *authValue,
2785*758e9fbaSOystein Eftevaag     uint8_t const *data)
2786*758e9fbaSOystein Eftevaag {
2787*758e9fbaSOystein Eftevaag     TSS2_RC r;
2788*758e9fbaSOystein Eftevaag 
2789*758e9fbaSOystein Eftevaag     memset(&context->cmd.Key_Create.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
2790*758e9fbaSOystein Eftevaag     if (dataSize > sizeof(TPMU_HA) || dataSize == 0) {
2791*758e9fbaSOystein Eftevaag         return_error(TSS2_FAPI_RC_BAD_VALUE, "Data to big or equal zero.");
2792*758e9fbaSOystein Eftevaag     }
2793*758e9fbaSOystein Eftevaag     if (data)
2794*758e9fbaSOystein Eftevaag         /* Copy the sensitive data */
2795*758e9fbaSOystein Eftevaag         memcpy(&context->cmd.Key_Create.inSensitive.sensitive.data.buffer,
2796*758e9fbaSOystein Eftevaag                data, dataSize);
2797*758e9fbaSOystein Eftevaag     context->cmd.Key_Create.inSensitive.sensitive.data.size = dataSize;
2798*758e9fbaSOystein Eftevaag     if (authValue) {
2799*758e9fbaSOystein Eftevaag         /* Copy the auth value. */
2800*758e9fbaSOystein Eftevaag         if (strlen(authValue) > sizeof(TPMU_HA)) {
2801*758e9fbaSOystein Eftevaag             return_error(TSS2_FAPI_RC_BAD_VALUE, "Password too long.");
2802*758e9fbaSOystein Eftevaag         }
2803*758e9fbaSOystein Eftevaag         memcpy(&context->cmd.Key_Create.inSensitive.sensitive.userAuth.buffer,
2804*758e9fbaSOystein Eftevaag                authValue, strlen(authValue));
2805*758e9fbaSOystein Eftevaag         context->cmd.Key_Create.inSensitive.sensitive.userAuth.size = strlen(authValue);
2806*758e9fbaSOystein Eftevaag     }
2807*758e9fbaSOystein Eftevaag     r = ifapi_key_create_prepare(context, keyPath, policyPath);
2808*758e9fbaSOystein Eftevaag     return r;
2809*758e9fbaSOystein Eftevaag }
2810*758e9fbaSOystein Eftevaag 
2811*758e9fbaSOystein Eftevaag /** Prepare key creation if possible.
2812*758e9fbaSOystein Eftevaag  *
2813*758e9fbaSOystein Eftevaag  * It will be checked whether the object already exists in key store and the FAPI context
2814*758e9fbaSOystein Eftevaag  * will be initialized appropriate for key creation.
2815*758e9fbaSOystein Eftevaag  *
2816*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
2817*758e9fbaSOystein Eftevaag  * @param[in]     keyPath the key path without the parent directories
2818*758e9fbaSOystein Eftevaag  *                of the key store. (e.g. HE/EK, HS/SRK/mykey)
2819*758e9fbaSOystein Eftevaag  * @param[in]     policyPath identifies the policy to be associated with the new key.
2820*758e9fbaSOystein Eftevaag  *                policyPath MAY be NULL. If policyPath is NULL then no policy will
2821*758e9fbaSOystein Eftevaag  *                be associated with the key.
2822*758e9fbaSOystein Eftevaag  *
2823*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the preparation was successful.
2824*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS If the object with does already exist in
2825*758e9fbaSOystein Eftevaag  *         keystore.
2826*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2827*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2828*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
2829*758e9fbaSOystein Eftevaag  *         config file.
2830*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2831*758e9fbaSOystein Eftevaag  *         operation already pending.
2832*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
2833*758e9fbaSOystein Eftevaag  *         the function.
2834*758e9fbaSOystein Eftevaag  */
2835*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_key_create_prepare(FAPI_CONTEXT * context,char const * keyPath,char const * policyPath)2836*758e9fbaSOystein Eftevaag ifapi_key_create_prepare(
2837*758e9fbaSOystein Eftevaag     FAPI_CONTEXT  *context,
2838*758e9fbaSOystein Eftevaag     char   const *keyPath,
2839*758e9fbaSOystein Eftevaag     char   const *policyPath)
2840*758e9fbaSOystein Eftevaag {
2841*758e9fbaSOystein Eftevaag     TSS2_RC r;
2842*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *object = &context->cmd.Key_Create.object;
2843*758e9fbaSOystein Eftevaag     NODE_STR_T *path_list = NULL;
2844*758e9fbaSOystein Eftevaag 
2845*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
2846*758e9fbaSOystein Eftevaag     r = ifapi_session_init(context);
2847*758e9fbaSOystein Eftevaag     return_if_error(r, "Initialize Key_Create");
2848*758e9fbaSOystein Eftevaag 
2849*758e9fbaSOystein Eftevaag     /* First check whether an existing object would be overwritten */
2850*758e9fbaSOystein Eftevaag     r = ifapi_keystore_check_overwrite(&context->keystore, &context->io,
2851*758e9fbaSOystein Eftevaag                                        keyPath);
2852*758e9fbaSOystein Eftevaag     return_if_error2(r, "Check overwrite %s", keyPath);
2853*758e9fbaSOystein Eftevaag 
2854*758e9fbaSOystein Eftevaag     context->srk_handle = 0;
2855*758e9fbaSOystein Eftevaag 
2856*758e9fbaSOystein Eftevaag     /* Clear the memory used for the the new key object */
2857*758e9fbaSOystein Eftevaag     memset(&context->cmd.Key_Create.outsideInfo, 0, sizeof(TPM2B_DATA));
2858*758e9fbaSOystein Eftevaag     memset(&context->cmd.Key_Create.creationPCR, 0, sizeof(TPML_PCR_SELECTION));
2859*758e9fbaSOystein Eftevaag     memset(object, 0, sizeof(IFAPI_OBJECT));
2860*758e9fbaSOystein Eftevaag 
2861*758e9fbaSOystein Eftevaag     strdup_check(context->cmd.Key_Create.policyPath, policyPath, r, error);
2862*758e9fbaSOystein Eftevaag     strdup_check(context->cmd.Key_Create.keyPath, keyPath, r, error);
2863*758e9fbaSOystein Eftevaag     r = get_explicit_key_path(&context->keystore, keyPath, &path_list);
2864*758e9fbaSOystein Eftevaag     return_if_error(r, "Compute explicit path.");
2865*758e9fbaSOystein Eftevaag 
2866*758e9fbaSOystein Eftevaag     context->loadKey.path_list = path_list;
2867*758e9fbaSOystein Eftevaag     char *file;
2868*758e9fbaSOystein Eftevaag     r = ifapi_path_string(&file, NULL, path_list, NULL);
2869*758e9fbaSOystein Eftevaag     goto_if_error(r, "Compute explicit path.", error);
2870*758e9fbaSOystein Eftevaag 
2871*758e9fbaSOystein Eftevaag     LOG_DEBUG("Explicit key path: %s", file);
2872*758e9fbaSOystein Eftevaag 
2873*758e9fbaSOystein Eftevaag     free(file);
2874*758e9fbaSOystein Eftevaag 
2875*758e9fbaSOystein Eftevaag     context->cmd.Key_Create.state = KEY_CREATE_INIT;
2876*758e9fbaSOystein Eftevaag 
2877*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
2878*758e9fbaSOystein Eftevaag 
2879*758e9fbaSOystein Eftevaag error:
2880*758e9fbaSOystein Eftevaag     free_string_list(path_list);
2881*758e9fbaSOystein Eftevaag     return r;
2882*758e9fbaSOystein Eftevaag }
2883*758e9fbaSOystein Eftevaag 
2884*758e9fbaSOystein Eftevaag /** State machine for key creation.
2885*758e9fbaSOystein Eftevaag  *
2886*758e9fbaSOystein Eftevaag  * The function for the preparation of the key have to called before the state machine can
2887*758e9fbaSOystein Eftevaag  * be activated. The linked list for the used directories must be available in the
2888*758e9fbaSOystein Eftevaag  * FAPI context.
2889*758e9fbaSOystein Eftevaag  * It will be checked whether the object already exists in key store and the FAPI context
2890*758e9fbaSOystein Eftevaag  * will be initialized appropriate for key creation.
2891*758e9fbaSOystein Eftevaag  *
2892*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
2893*758e9fbaSOystein Eftevaag  * @param[in] template The template which defines the key attributes and whether the
2894*758e9fbaSOystein Eftevaag  *            key will be persistent.
2895*758e9fbaSOystein Eftevaag  *
2896*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the key could be generated.
2897*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2898*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2899*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
2900*758e9fbaSOystein Eftevaag  *         not covered by other return codes.
2901*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
2902*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
2903*758e9fbaSOystein Eftevaag  *         store.
2904*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If an object needed for creation or
2905*758e9fbaSOystein Eftevaag            authentication was not found.
2906*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
2907*758e9fbaSOystein Eftevaag  *         not successful.
2908*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for creation
2909*758e9fbaSOystein Eftevaag  *         fails.
2910*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
2911*758e9fbaSOystein Eftevaag  *         is not defined.
2912*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
2913*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
2914*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2915*758e9fbaSOystein Eftevaag  *         operation already pending.
2916*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2917*758e9fbaSOystein Eftevaag  */
2918*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_key_create(FAPI_CONTEXT * context,IFAPI_KEY_TEMPLATE * template)2919*758e9fbaSOystein Eftevaag ifapi_key_create(
2920*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
2921*758e9fbaSOystein Eftevaag     IFAPI_KEY_TEMPLATE *template)
2922*758e9fbaSOystein Eftevaag {
2923*758e9fbaSOystein Eftevaag     TSS2_RC r;
2924*758e9fbaSOystein Eftevaag     size_t path_length;
2925*758e9fbaSOystein Eftevaag     NODE_STR_T *path_list = context->loadKey.path_list;
2926*758e9fbaSOystein Eftevaag     TPM2B_PUBLIC *outPublic = NULL;
2927*758e9fbaSOystein Eftevaag     TPM2B_PRIVATE *outPrivate = NULL;
2928*758e9fbaSOystein Eftevaag     TPM2B_CREATION_DATA *creationData = NULL;
2929*758e9fbaSOystein Eftevaag     TPM2B_DIGEST *creationHash = NULL;
2930*758e9fbaSOystein Eftevaag     TPMT_TK_CREATION *creationTicket = NULL;
2931*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *object = &context->cmd.Key_Create.object;
2932*758e9fbaSOystein Eftevaag     ESYS_TR auth_session;
2933*758e9fbaSOystein Eftevaag 
2934*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
2935*758e9fbaSOystein Eftevaag 
2936*758e9fbaSOystein Eftevaag     switch (context->cmd.Key_Create.state) {
2937*758e9fbaSOystein Eftevaag     statecase(context->cmd.Key_Create.state, KEY_CREATE_INIT);
2938*758e9fbaSOystein Eftevaag         context->cmd.Key_Create.public_templ = *template;
2939*758e9fbaSOystein Eftevaag 
2940*758e9fbaSOystein Eftevaag         /* Profile name is first element of the explicit path list */
2941*758e9fbaSOystein Eftevaag         char *profile_name = context->loadKey.path_list->str;
2942*758e9fbaSOystein Eftevaag         r = ifapi_profiles_get(&context->profiles, profile_name, &context->cmd.Key_Create.profile);
2943*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Retrieving profile data", error_cleanup);
2944*758e9fbaSOystein Eftevaag 
2945*758e9fbaSOystein Eftevaag         if (context->cmd.Key_Create.inSensitive.sensitive.data.size > 0) {
2946*758e9fbaSOystein Eftevaag             /* A keyed hash object sealing sensitive data will be created */
2947*758e9fbaSOystein Eftevaag             context->cmd.Key_Create.public_templ.public.publicArea.type = TPM2_ALG_KEYEDHASH;
2948*758e9fbaSOystein Eftevaag             context->cmd.Key_Create.public_templ.public.publicArea.nameAlg =
2949*758e9fbaSOystein Eftevaag                     context->cmd.Key_Create.profile->nameAlg;
2950*758e9fbaSOystein Eftevaag             context->cmd.Key_Create.public_templ.public.publicArea.parameters.keyedHashDetail.scheme.scheme =
2951*758e9fbaSOystein Eftevaag             TPM2_ALG_NULL;
2952*758e9fbaSOystein Eftevaag         } else {
2953*758e9fbaSOystein Eftevaag             r = ifapi_merge_profile_into_template(context->cmd.Key_Create.profile,
2954*758e9fbaSOystein Eftevaag                                                   &context->cmd.Key_Create.public_templ);
2955*758e9fbaSOystein Eftevaag             goto_if_error_reset_state(r, "Merge profile", error_cleanup);
2956*758e9fbaSOystein Eftevaag         }
2957*758e9fbaSOystein Eftevaag 
2958*758e9fbaSOystein Eftevaag         if (context->cmd.Key_Create.policyPath
2959*758e9fbaSOystein Eftevaag                 && strcmp(context->cmd.Key_Create.policyPath, "") != 0)
2960*758e9fbaSOystein Eftevaag             context->cmd.Key_Create.state = KEY_CREATE_CALCULATE_POLICY;
2961*758e9fbaSOystein Eftevaag         /* else jump over to KEY_CREATE_WAIT_FOR_SESSION below */
2962*758e9fbaSOystein Eftevaag     /* FALLTHRU */
2963*758e9fbaSOystein Eftevaag 
2964*758e9fbaSOystein Eftevaag     case KEY_CREATE_CALCULATE_POLICY:
2965*758e9fbaSOystein Eftevaag         if (context->cmd.Key_Create.state == KEY_CREATE_CALCULATE_POLICY) {
2966*758e9fbaSOystein Eftevaag             r = ifapi_calculate_tree(context, context->cmd.Key_Create.policyPath,
2967*758e9fbaSOystein Eftevaag                                      &context->policy.policy,
2968*758e9fbaSOystein Eftevaag                                      context->cmd.Key_Create.public_templ.public.publicArea.nameAlg,
2969*758e9fbaSOystein Eftevaag                                      &context->policy.digest_idx,
2970*758e9fbaSOystein Eftevaag                                      &context->policy.hash_size);
2971*758e9fbaSOystein Eftevaag             return_try_again(r);
2972*758e9fbaSOystein Eftevaag             goto_if_error2(r, "Calculate policy tree %s", error_cleanup,
2973*758e9fbaSOystein Eftevaag                            context->cmd.Key_Create.policyPath);
2974*758e9fbaSOystein Eftevaag 
2975*758e9fbaSOystein Eftevaag             /* Store the calculated policy in the key object */
2976*758e9fbaSOystein Eftevaag             object->policy = calloc(1, sizeof(TPMS_POLICY));
2977*758e9fbaSOystein Eftevaag             return_if_null(object->policy, "Out of memory",
2978*758e9fbaSOystein Eftevaag                     TSS2_FAPI_RC_MEMORY);
2979*758e9fbaSOystein Eftevaag             *(object->policy) = context->policy.policy;
2980*758e9fbaSOystein Eftevaag 
2981*758e9fbaSOystein Eftevaag             context->cmd.Key_Create.public_templ.public.publicArea.authPolicy.size =
2982*758e9fbaSOystein Eftevaag                 context->policy.hash_size;
2983*758e9fbaSOystein Eftevaag             memcpy(&context->cmd.Key_Create.public_templ.public.publicArea.authPolicy.buffer[0],
2984*758e9fbaSOystein Eftevaag                    &context->policy.policy.policyDigests.digests[context->policy.digest_idx].digest,
2985*758e9fbaSOystein Eftevaag                    context->policy.hash_size);
2986*758e9fbaSOystein Eftevaag         }
2987*758e9fbaSOystein Eftevaag         r = ifapi_get_sessions_async(context,
2988*758e9fbaSOystein Eftevaag                                      IFAPI_SESSION_GENEK | IFAPI_SESSION1,
2989*758e9fbaSOystein Eftevaag                                      TPMA_SESSION_DECRYPT, 0);
2990*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Create sessions", error_cleanup);
2991*758e9fbaSOystein Eftevaag         fallthrough;
2992*758e9fbaSOystein Eftevaag 
2993*758e9fbaSOystein Eftevaag     statecase(context->cmd.Key_Create.state, KEY_CREATE_WAIT_FOR_SESSION);
2994*758e9fbaSOystein Eftevaag         LOG_TRACE("KEY_CREATE_WAIT_FOR_SESSION");
2995*758e9fbaSOystein Eftevaag         r = ifapi_get_sessions_finish(context, context->cmd.Key_Create.profile,
2996*758e9fbaSOystein Eftevaag                                       context->cmd.Key_Create.profile->nameAlg);
2997*758e9fbaSOystein Eftevaag         return_try_again(r);
2998*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
2999*758e9fbaSOystein Eftevaag 
3000*758e9fbaSOystein Eftevaag         path_length = ifapi_path_length(path_list);
3001*758e9fbaSOystein Eftevaag         r = ifapi_load_key_async(context, path_length - 1);
3002*758e9fbaSOystein Eftevaag         goto_if_error(r, "LoadKey async", error_cleanup);
3003*758e9fbaSOystein Eftevaag         fallthrough;
3004*758e9fbaSOystein Eftevaag 
3005*758e9fbaSOystein Eftevaag     statecase(context->cmd.Key_Create.state, KEY_CREATE_WAIT_FOR_PARENT);
3006*758e9fbaSOystein Eftevaag         LOG_TRACE("KEY_CREATE_WAIT_FOR_PARENT");
3007*758e9fbaSOystein Eftevaag         r = ifapi_load_key_finish(context, IFAPI_FLUSH_PARENT);
3008*758e9fbaSOystein Eftevaag         return_try_again(r);
3009*758e9fbaSOystein Eftevaag         goto_if_error(r, "LoadKey finish", error_cleanup);
3010*758e9fbaSOystein Eftevaag         fallthrough;
3011*758e9fbaSOystein Eftevaag 
3012*758e9fbaSOystein Eftevaag     statecase(context->cmd.Key_Create.state, KEY_CREATE_WAIT_FOR_AUTHORIZATION);
3013*758e9fbaSOystein Eftevaag         r = ifapi_authorize_object(context, &context->loadKey.auth_object, &auth_session);
3014*758e9fbaSOystein Eftevaag         FAPI_SYNC(r, "Authorize key.", error_cleanup);
3015*758e9fbaSOystein Eftevaag 
3016*758e9fbaSOystein Eftevaag         r = Esys_Create_Async(context->esys, context->loadKey.auth_object.handle,
3017*758e9fbaSOystein Eftevaag                               auth_session,
3018*758e9fbaSOystein Eftevaag                               ESYS_TR_NONE, ESYS_TR_NONE,
3019*758e9fbaSOystein Eftevaag                               &context->cmd.Key_Create.inSensitive,
3020*758e9fbaSOystein Eftevaag                               &context->cmd.Key_Create.public_templ.public,
3021*758e9fbaSOystein Eftevaag                               &context->cmd.Key_Create.outsideInfo,
3022*758e9fbaSOystein Eftevaag                               &context->cmd.Key_Create.creationPCR);
3023*758e9fbaSOystein Eftevaag         goto_if_error(r, "Create_Async", error_cleanup);
3024*758e9fbaSOystein Eftevaag         fallthrough;
3025*758e9fbaSOystein Eftevaag 
3026*758e9fbaSOystein Eftevaag     statecase(context->cmd.Key_Create.state, KEY_CREATE_AUTH_SENT);
3027*758e9fbaSOystein Eftevaag         r = Esys_Create_Finish(context->esys, &outPrivate, &outPublic, &creationData,
3028*758e9fbaSOystein Eftevaag                                &creationHash, &creationTicket);
3029*758e9fbaSOystein Eftevaag         try_again_or_error_goto(r, "Key create finish", error_cleanup);
3030*758e9fbaSOystein Eftevaag 
3031*758e9fbaSOystein Eftevaag         /* Prepare object for serialization */
3032*758e9fbaSOystein Eftevaag         object->system = context->cmd.Key_Create.public_templ.system;
3033*758e9fbaSOystein Eftevaag         object->objectType = IFAPI_KEY_OBJ;
3034*758e9fbaSOystein Eftevaag         object->misc.key.public = *outPublic;
3035*758e9fbaSOystein Eftevaag         object->misc.key.private.size = outPrivate->size;
3036*758e9fbaSOystein Eftevaag         object->misc.key.private.buffer = calloc(1, outPrivate->size);
3037*758e9fbaSOystein Eftevaag         goto_if_null2( object->misc.key.private.buffer, "Out of memory.", r,
3038*758e9fbaSOystein Eftevaag                        TSS2_FAPI_RC_MEMORY, error_cleanup);
3039*758e9fbaSOystein Eftevaag 
3040*758e9fbaSOystein Eftevaag         object->misc.key.private.buffer = memcpy(&object->misc.key.private.buffer[0],
3041*758e9fbaSOystein Eftevaag                                                  &outPrivate->buffer[0], outPrivate->size);
3042*758e9fbaSOystein Eftevaag         object->misc.key.policyInstance = NULL;
3043*758e9fbaSOystein Eftevaag         object->misc.key.creationData = *creationData;
3044*758e9fbaSOystein Eftevaag         object->misc.key.creationTicket = *creationTicket;
3045*758e9fbaSOystein Eftevaag         object->misc.key.description = NULL;
3046*758e9fbaSOystein Eftevaag         object->misc.key.certificate = NULL;
3047*758e9fbaSOystein Eftevaag         SAFE_FREE(outPrivate);
3048*758e9fbaSOystein Eftevaag         SAFE_FREE(creationData);
3049*758e9fbaSOystein Eftevaag         SAFE_FREE(creationTicket);
3050*758e9fbaSOystein Eftevaag         SAFE_FREE(creationHash);
3051*758e9fbaSOystein Eftevaag         if (context->cmd.Key_Create.inSensitive.sensitive.userAuth.size > 0)
3052*758e9fbaSOystein Eftevaag             object->misc.key.with_auth = TPM2_YES;
3053*758e9fbaSOystein Eftevaag         else
3054*758e9fbaSOystein Eftevaag             object->misc.key.with_auth = TPM2_NO;;
3055*758e9fbaSOystein Eftevaag         r = ifapi_get_name(&outPublic->publicArea, &object->misc.key.name);
3056*758e9fbaSOystein Eftevaag         goto_if_error(r, "Get key name", error_cleanup);
3057*758e9fbaSOystein Eftevaag 
3058*758e9fbaSOystein Eftevaag         if (object->misc.key.public.publicArea.type == TPM2_ALG_RSA)
3059*758e9fbaSOystein Eftevaag             object->misc.key.signing_scheme = context->cmd.Key_Create.profile->rsa_signing_scheme;
3060*758e9fbaSOystein Eftevaag         else
3061*758e9fbaSOystein Eftevaag             object->misc.key.signing_scheme = context->cmd.Key_Create.profile->ecc_signing_scheme;
3062*758e9fbaSOystein Eftevaag         SAFE_FREE(outPublic);
3063*758e9fbaSOystein Eftevaag         fallthrough;
3064*758e9fbaSOystein Eftevaag 
3065*758e9fbaSOystein Eftevaag     statecase(context->cmd.Key_Create.state, KEY_CREATE_WRITE_PREPARE);
3066*758e9fbaSOystein Eftevaag         /* Perform esys serialization if necessary */
3067*758e9fbaSOystein Eftevaag         r = ifapi_esys_serialize_object(context->esys, object);
3068*758e9fbaSOystein Eftevaag         goto_if_error(r, "Prepare serialization", error_cleanup);
3069*758e9fbaSOystein Eftevaag 
3070*758e9fbaSOystein Eftevaag         /* Start writing the NV object to the key store */
3071*758e9fbaSOystein Eftevaag         r = ifapi_keystore_store_async(&context->keystore, &context->io,
3072*758e9fbaSOystein Eftevaag                                        context->cmd.Key_Create.keyPath, object);
3073*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
3074*758e9fbaSOystein Eftevaag                                   context->cmd.Key_Create.keyPath);
3075*758e9fbaSOystein Eftevaag         ifapi_cleanup_ifapi_object(object);
3076*758e9fbaSOystein Eftevaag         fallthrough;
3077*758e9fbaSOystein Eftevaag 
3078*758e9fbaSOystein Eftevaag     statecase(context->cmd.Key_Create.state, KEY_CREATE_WRITE);
3079*758e9fbaSOystein Eftevaag         /* Finish writing the key to the key store */
3080*758e9fbaSOystein Eftevaag         r = ifapi_keystore_store_finish(&context->keystore, &context->io);
3081*758e9fbaSOystein Eftevaag         return_try_again(r);
3082*758e9fbaSOystein Eftevaag         return_if_error_reset_state(r, "write_finish failed");
3083*758e9fbaSOystein Eftevaag 
3084*758e9fbaSOystein Eftevaag         if (context->loadKey.auth_object.misc.key.persistent_handle) {
3085*758e9fbaSOystein Eftevaag             context->cmd.Key_Create.state = KEY_CREATE_INIT;
3086*758e9fbaSOystein Eftevaag             r = TSS2_RC_SUCCESS;
3087*758e9fbaSOystein Eftevaag             break;
3088*758e9fbaSOystein Eftevaag         }
3089*758e9fbaSOystein Eftevaag         /* Prepare Flushing of key used for authorization */
3090*758e9fbaSOystein Eftevaag         r = Esys_FlushContext_Async(context->esys, context->loadKey.auth_object.handle);
3091*758e9fbaSOystein Eftevaag         goto_if_error(r, "Flush parent", error_cleanup);
3092*758e9fbaSOystein Eftevaag         fallthrough;
3093*758e9fbaSOystein Eftevaag 
3094*758e9fbaSOystein Eftevaag     statecase(context->cmd.Key_Create.state, KEY_CREATE_FLUSH);
3095*758e9fbaSOystein Eftevaag         r = Esys_FlushContext_Finish(context->esys);
3096*758e9fbaSOystein Eftevaag         try_again_or_error_goto(r, "Flush context", error_cleanup);
3097*758e9fbaSOystein Eftevaag         fallthrough;
3098*758e9fbaSOystein Eftevaag 
3099*758e9fbaSOystein Eftevaag     statecase(context->cmd.Key_Create.state, KEY_CREATE_CLEANUP);
3100*758e9fbaSOystein Eftevaag         r = ifapi_cleanup_session(context);
3101*758e9fbaSOystein Eftevaag         try_again_or_error_goto(r, "Cleanup", error_cleanup);
3102*758e9fbaSOystein Eftevaag 
3103*758e9fbaSOystein Eftevaag         context->cmd.Key_Create.state = KEY_CREATE_INIT;
3104*758e9fbaSOystein Eftevaag         r = TSS2_RC_SUCCESS;
3105*758e9fbaSOystein Eftevaag         break;
3106*758e9fbaSOystein Eftevaag 
3107*758e9fbaSOystein Eftevaag     statecasedefault(context->cmd.Key_Create.state);
3108*758e9fbaSOystein Eftevaag     }
3109*758e9fbaSOystein Eftevaag error_cleanup:
3110*758e9fbaSOystein Eftevaag     free_string_list(context->loadKey.path_list);
3111*758e9fbaSOystein Eftevaag     SAFE_FREE(outPublic);
3112*758e9fbaSOystein Eftevaag     SAFE_FREE(outPrivate);
3113*758e9fbaSOystein Eftevaag     SAFE_FREE(creationData);
3114*758e9fbaSOystein Eftevaag     SAFE_FREE(creationHash);
3115*758e9fbaSOystein Eftevaag     SAFE_FREE(creationTicket);
3116*758e9fbaSOystein Eftevaag     SAFE_FREE(context->cmd.Key_Create.policyPath);
3117*758e9fbaSOystein Eftevaag     SAFE_FREE(context->cmd.Key_Create.keyPath);
3118*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(object);
3119*758e9fbaSOystein Eftevaag     ifapi_session_clean(context);
3120*758e9fbaSOystein Eftevaag     return r;
3121*758e9fbaSOystein Eftevaag }
3122*758e9fbaSOystein Eftevaag 
3123*758e9fbaSOystein Eftevaag /** Get signature scheme for key.
3124*758e9fbaSOystein Eftevaag  *
3125*758e9fbaSOystein Eftevaag  * If padding is passed the scheme will be derived from paddint otherwise
3126*758e9fbaSOystein Eftevaag  * the scheme form object will be used.
3127*758e9fbaSOystein Eftevaag  *
3128*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT.
3129*758e9fbaSOystein Eftevaag  * @param[in] object The internal FAPI object of the key.
3130*758e9fbaSOystein Eftevaag  * @param[in] padding The strings RSA_SSA or RSA_PSS will be converted
3131*758e9fbaSOystein Eftevaag  *            into the TSS constants used for the signing scheme.
3132*758e9fbaSOystein Eftevaag  * @param[in] digest The digest size will be used to determine the hashalg
3133*758e9fbaSOystein Eftevaag  *            for the signature scheme.
3134*758e9fbaSOystein Eftevaag  * @param[out] sig_scheme The computed signature scheme.
3135*758e9fbaSOystein Eftevaag  *
3136*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If the digest size is not appropriate.
3137*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
3138*758e9fbaSOystein Eftevaag  */
3139*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_sig_scheme(FAPI_CONTEXT * context,IFAPI_OBJECT * object,char const * padding,TPM2B_DIGEST * digest,TPMT_SIG_SCHEME * sig_scheme)3140*758e9fbaSOystein Eftevaag ifapi_get_sig_scheme(
3141*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
3142*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *object,
3143*758e9fbaSOystein Eftevaag     char const *padding,
3144*758e9fbaSOystein Eftevaag     TPM2B_DIGEST *digest,
3145*758e9fbaSOystein Eftevaag     TPMT_SIG_SCHEME *sig_scheme)
3146*758e9fbaSOystein Eftevaag {
3147*758e9fbaSOystein Eftevaag     TPMI_ALG_HASH hash_alg;
3148*758e9fbaSOystein Eftevaag     TSS2_RC r;
3149*758e9fbaSOystein Eftevaag 
3150*758e9fbaSOystein Eftevaag     if (padding) {
3151*758e9fbaSOystein Eftevaag         /* Get hash algorithm from digest size */
3152*758e9fbaSOystein Eftevaag         r = ifapi_get_hash_alg_for_size(digest->size, &hash_alg);
3153*758e9fbaSOystein Eftevaag         return_if_error2(r, "Invalid digest size.");
3154*758e9fbaSOystein Eftevaag 
3155*758e9fbaSOystein Eftevaag         /* Use scheme object from context */
3156*758e9fbaSOystein Eftevaag         if (strcasecmp("RSA_SSA", padding) == 0) {
3157*758e9fbaSOystein Eftevaag             context->Key_Sign.scheme.scheme = TPM2_ALG_RSASSA;
3158*758e9fbaSOystein Eftevaag             context->Key_Sign.scheme.details.rsassa.hashAlg = hash_alg;
3159*758e9fbaSOystein Eftevaag         }
3160*758e9fbaSOystein Eftevaag         if (strcasecmp("RSA_PSS", padding) == 0) {
3161*758e9fbaSOystein Eftevaag             context->Key_Sign.scheme.scheme = TPM2_ALG_RSAPSS;
3162*758e9fbaSOystein Eftevaag             context->Key_Sign.scheme.details.rsapss.hashAlg = hash_alg;
3163*758e9fbaSOystein Eftevaag         }
3164*758e9fbaSOystein Eftevaag         *sig_scheme = context->Key_Sign.scheme;
3165*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
3166*758e9fbaSOystein Eftevaag     } else {
3167*758e9fbaSOystein Eftevaag         /* Use scheme defined for object */
3168*758e9fbaSOystein Eftevaag         *sig_scheme = object->misc.key.signing_scheme;
3169*758e9fbaSOystein Eftevaag         /* Get hash algorithm from digest size */
3170*758e9fbaSOystein Eftevaag         r = ifapi_get_hash_alg_for_size(digest->size, &hash_alg);
3171*758e9fbaSOystein Eftevaag         return_if_error2(r, "Invalid digest size.");
3172*758e9fbaSOystein Eftevaag 
3173*758e9fbaSOystein Eftevaag         sig_scheme->details.any.hashAlg = hash_alg;
3174*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
3175*758e9fbaSOystein Eftevaag     }
3176*758e9fbaSOystein Eftevaag }
3177*758e9fbaSOystein Eftevaag 
3178*758e9fbaSOystein Eftevaag /** State machine for changing the hierarchy authorization.
3179*758e9fbaSOystein Eftevaag  *
3180*758e9fbaSOystein Eftevaag  * First it will be tried to set the auth value of the hierarchy with a
3181*758e9fbaSOystein Eftevaag  * "null" authorization. If this trial is not successful it will be tried to
3182*758e9fbaSOystein Eftevaag  * authorize the hierarchy via a callback.
3183*758e9fbaSOystein Eftevaag  * If an not null auth value is passed with_auth is set to yes for the
3184*758e9fbaSOystein Eftevaag  * object otherwise to no. So for later authorizations it will be clear
3185*758e9fbaSOystein Eftevaag  * whether null authorization is possible or not.
3186*758e9fbaSOystein Eftevaag  *
3187*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT.
3188*758e9fbaSOystein Eftevaag  * @param[in] handle The ESAPI handle of the hierarchy.
3189*758e9fbaSOystein Eftevaag  * @param[in,out] hierarchy_object The internal FAPI representation of a
3190*758e9fbaSOystein Eftevaag  *                hierarchy.
3191*758e9fbaSOystein Eftevaag  * @param[in] newAuthValue The new authorization for the hierarchy.
3192*758e9fbaSOystein Eftevaag  *
3193*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
3194*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
3195*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
3196*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
3197*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
3198*758e9fbaSOystein Eftevaag  *         operation already pending.
3199*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
3200*758e9fbaSOystein Eftevaag  *         is not set.
3201*758e9fbaSOystein Eftevaag  */
3202*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_change_auth_hierarchy(FAPI_CONTEXT * context,ESYS_TR handle,IFAPI_OBJECT * hierarchy_object,TPM2B_AUTH * newAuthValue)3203*758e9fbaSOystein Eftevaag ifapi_change_auth_hierarchy(
3204*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
3205*758e9fbaSOystein Eftevaag     ESYS_TR handle,
3206*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *hierarchy_object,
3207*758e9fbaSOystein Eftevaag     TPM2B_AUTH *newAuthValue)
3208*758e9fbaSOystein Eftevaag {
3209*758e9fbaSOystein Eftevaag     TSS2_RC r;
3210*758e9fbaSOystein Eftevaag 
3211*758e9fbaSOystein Eftevaag     switch (context->hierarchy_state) {
3212*758e9fbaSOystein Eftevaag     statecase(context->hierarchy_state, HIERARCHY_CHANGE_AUTH_INIT);
3213*758e9fbaSOystein Eftevaag         if (newAuthValue->size > 0)
3214*758e9fbaSOystein Eftevaag             hierarchy_object->misc.hierarchy.with_auth = TPM2_YES;
3215*758e9fbaSOystein Eftevaag         else
3216*758e9fbaSOystein Eftevaag             hierarchy_object->misc.hierarchy.with_auth = TPM2_NO;
3217*758e9fbaSOystein Eftevaag         r = Esys_HierarchyChangeAuth_Async(context->esys,
3218*758e9fbaSOystein Eftevaag                                            handle,
3219*758e9fbaSOystein Eftevaag                                            (context->session1
3220*758e9fbaSOystein Eftevaag                                             && context->session1 != ESYS_TR_NONE) ?
3221*758e9fbaSOystein Eftevaag                                            context->session1 : ESYS_TR_PASSWORD,
3222*758e9fbaSOystein Eftevaag                                            ESYS_TR_NONE, ESYS_TR_NONE,
3223*758e9fbaSOystein Eftevaag                                            newAuthValue);
3224*758e9fbaSOystein Eftevaag         return_if_error(r, "HierarchyChangeAuth");
3225*758e9fbaSOystein Eftevaag         fallthrough;
3226*758e9fbaSOystein Eftevaag 
3227*758e9fbaSOystein Eftevaag     statecase(context->hierarchy_state, HIERARCHY_CHANGE_AUTH_NULL_AUTH_SENT);
3228*758e9fbaSOystein Eftevaag         r = Esys_HierarchyChangeAuth_Finish(context->esys);
3229*758e9fbaSOystein Eftevaag         return_try_again(r);
3230*758e9fbaSOystein Eftevaag 
3231*758e9fbaSOystein Eftevaag         if ((r & ~TPM2_RC_N_MASK) != TPM2_RC_BAD_AUTH) {
3232*758e9fbaSOystein Eftevaag             return_if_error(r, "Hierarchy change auth.");
3233*758e9fbaSOystein Eftevaag             context->hierarchy_state = HIERARCHY_CHANGE_AUTH_INIT;
3234*758e9fbaSOystein Eftevaag             LOG_TRACE("success");
3235*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
3236*758e9fbaSOystein Eftevaag         }
3237*758e9fbaSOystein Eftevaag 
3238*758e9fbaSOystein Eftevaag         /* Retry after NULL authorization was not successful */
3239*758e9fbaSOystein Eftevaag         r = ifapi_set_auth(context, hierarchy_object, "Hierarchy object");
3240*758e9fbaSOystein Eftevaag         return_if_error(r, "HierarchyChangeAuth");
3241*758e9fbaSOystein Eftevaag 
3242*758e9fbaSOystein Eftevaag         r = Esys_HierarchyChangeAuth_Async(context->esys,
3243*758e9fbaSOystein Eftevaag                                            handle,
3244*758e9fbaSOystein Eftevaag                                            (context->session1
3245*758e9fbaSOystein Eftevaag                                             && context->session1 != ESYS_TR_NONE) ?
3246*758e9fbaSOystein Eftevaag                                            context->session1 : ESYS_TR_PASSWORD,
3247*758e9fbaSOystein Eftevaag                                            ESYS_TR_NONE, ESYS_TR_NONE,
3248*758e9fbaSOystein Eftevaag                                            newAuthValue);
3249*758e9fbaSOystein Eftevaag         return_if_error(r, "HierarchyChangeAuth");
3250*758e9fbaSOystein Eftevaag         fallthrough;
3251*758e9fbaSOystein Eftevaag 
3252*758e9fbaSOystein Eftevaag     statecase(context->hierarchy_state, HIERARCHY_CHANGE_AUTH_AUTH_SENT);
3253*758e9fbaSOystein Eftevaag         r = Esys_HierarchyChangeAuth_Finish(context->esys);
3254*758e9fbaSOystein Eftevaag         FAPI_SYNC(r, "Hierarchy change auth.", error);
3255*758e9fbaSOystein Eftevaag 
3256*758e9fbaSOystein Eftevaag         context->hierarchy_state = HIERARCHY_CHANGE_AUTH_INIT;
3257*758e9fbaSOystein Eftevaag         return r;
3258*758e9fbaSOystein Eftevaag 
3259*758e9fbaSOystein Eftevaag     statecasedefault(context->hierarchy_state);
3260*758e9fbaSOystein Eftevaag     }
3261*758e9fbaSOystein Eftevaag 
3262*758e9fbaSOystein Eftevaag error:
3263*758e9fbaSOystein Eftevaag     return r;
3264*758e9fbaSOystein Eftevaag }
3265*758e9fbaSOystein Eftevaag 
3266*758e9fbaSOystein Eftevaag /** State machine for changing the policy of a hierarchy.
3267*758e9fbaSOystein Eftevaag  *
3268*758e9fbaSOystein Eftevaag  * Based on a passed policy the policy digest will be computed.
3269*758e9fbaSOystein Eftevaag  * First it will be tried to set the policy of the hierarchy with a
3270*758e9fbaSOystein Eftevaag  * "null" authorization. If this trial is not successful it will be tried to
3271*758e9fbaSOystein Eftevaag  * authorize the hierarchy via a callback.
3272*758e9fbaSOystein Eftevaag  * If an not null auth value is passed with_auth is set to yes for the
3273*758e9fbaSOystein Eftevaag  * object otherwise to no. So for later authorizations it will be clear
3274*758e9fbaSOystein Eftevaag  * whether null authorization is possible or not.
3275*758e9fbaSOystein Eftevaag  *
3276*758e9fbaSOystein Eftevaag  * @param[in] context The FAPI_CONTEXT.
3277*758e9fbaSOystein Eftevaag  * @param[in] handle The ESAPI handle of the hierarchy.
3278*758e9fbaSOystein Eftevaag  * @param[in,out] hierarchy_object The internal FAPI representation of a
3279*758e9fbaSOystein Eftevaag  *                hierarchy.
3280*758e9fbaSOystein Eftevaag  * @param[in] policy The new policy assigned to the hierarchy.
3281*758e9fbaSOystein Eftevaag  *
3282*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
3283*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
3284*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
3285*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
3286*758e9fbaSOystein Eftevaag  *         not covered by other return codes.
3287*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during policy calculation.
3288*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
3289*758e9fbaSOystein Eftevaag  *         store.
3290*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If an object needed for policy calculation was
3291*758e9fbaSOystein Eftevaag  *         not found.
3292*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
3293*758e9fbaSOystein Eftevaag  *         not successful.
3294*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
3295*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
3296*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
3297*758e9fbaSOystein Eftevaag  *         operation already pending.
3298*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
3299*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
3300*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
3301*758e9fbaSOystein Eftevaag  *         is not set.
3302*758e9fbaSOystein Eftevaag  */
3303*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_change_policy_hierarchy(FAPI_CONTEXT * context,ESYS_TR handle,IFAPI_OBJECT * hierarchy_object,TPMS_POLICY * policy)3304*758e9fbaSOystein Eftevaag ifapi_change_policy_hierarchy(
3305*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
3306*758e9fbaSOystein Eftevaag     ESYS_TR handle,
3307*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *hierarchy_object,
3308*758e9fbaSOystein Eftevaag     TPMS_POLICY *policy)
3309*758e9fbaSOystein Eftevaag {
3310*758e9fbaSOystein Eftevaag     TSS2_RC r;
3311*758e9fbaSOystein Eftevaag 
3312*758e9fbaSOystein Eftevaag     switch (context->hierarchy_policy_state) {
3313*758e9fbaSOystein Eftevaag     statecase(context->hierarchy_policy_state, HIERARCHY_CHANGE_POLICY_INIT);
3314*758e9fbaSOystein Eftevaag         if (! policy || ! policy->policy) {
3315*758e9fbaSOystein Eftevaag             /* No policy will be used for hierarchy */
3316*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
3317*758e9fbaSOystein Eftevaag         }
3318*758e9fbaSOystein Eftevaag 
3319*758e9fbaSOystein Eftevaag         context->policy.state = POLICY_INIT;
3320*758e9fbaSOystein Eftevaag 
3321*758e9fbaSOystein Eftevaag         /* Calculate the policy digest which will be used as hierarchy policy. */
3322*758e9fbaSOystein Eftevaag         r = ifapi_calculate_tree(context, NULL, /**< no path needed */
3323*758e9fbaSOystein Eftevaag                                  policy,
3324*758e9fbaSOystein Eftevaag                                  context->profiles.default_profile.nameAlg,
3325*758e9fbaSOystein Eftevaag                                  &context->cmd.Provision.digest_idx,
3326*758e9fbaSOystein Eftevaag                                  &context->cmd.Provision.hash_size);
3327*758e9fbaSOystein Eftevaag         goto_if_error(r, "Policy calculation", error);
3328*758e9fbaSOystein Eftevaag 
3329*758e9fbaSOystein Eftevaag 
3330*758e9fbaSOystein Eftevaag         /* Policy data will be stored in the provisioning context. */
3331*758e9fbaSOystein Eftevaag         context->cmd.Provision.policy_digest.size = context->cmd.Provision.hash_size;
3332*758e9fbaSOystein Eftevaag         memcpy(&context->cmd.Provision.policy_digest.buffer[0],
3333*758e9fbaSOystein Eftevaag                &policy
3334*758e9fbaSOystein Eftevaag                ->policyDigests.digests[context->cmd.Provision.digest_idx].digest,
3335*758e9fbaSOystein Eftevaag                context->cmd.Provision.hash_size);
3336*758e9fbaSOystein Eftevaag 
3337*758e9fbaSOystein Eftevaag         hierarchy_object->policy = policy;
3338*758e9fbaSOystein Eftevaag         hierarchy_object->misc.hierarchy.authPolicy = context->cmd.Provision.policy_digest;
3339*758e9fbaSOystein Eftevaag 
3340*758e9fbaSOystein Eftevaag         /* Prepare the setting of the policy. */
3341*758e9fbaSOystein Eftevaag         r = Esys_SetPrimaryPolicy_Async(context->esys, handle,
3342*758e9fbaSOystein Eftevaag                                         ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
3343*758e9fbaSOystein Eftevaag                                         &context->cmd.Provision.policy_digest,
3344*758e9fbaSOystein Eftevaag                                         context->profiles.default_profile.nameAlg);
3345*758e9fbaSOystein Eftevaag         return_if_error(r, "Esys_SetPrimaryPolicy_Async");
3346*758e9fbaSOystein Eftevaag         fallthrough;
3347*758e9fbaSOystein Eftevaag 
3348*758e9fbaSOystein Eftevaag     statecase(context->hierarchy_policy_state, HIERARCHY_CHANGE_POLICY_NULL_AUTH_SENT);
3349*758e9fbaSOystein Eftevaag         r = Esys_SetPrimaryPolicy_Finish(context->esys);
3350*758e9fbaSOystein Eftevaag         return_try_again(r);
3351*758e9fbaSOystein Eftevaag         if ((r & ~TPM2_RC_N_MASK) != TPM2_RC_BAD_AUTH) {
3352*758e9fbaSOystein Eftevaag             return_if_error(r, "SetPrimaryPolicy_Finish");
3353*758e9fbaSOystein Eftevaag             context->hierarchy_policy_state = HIERARCHY_CHANGE_POLICY_INIT;
3354*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
3355*758e9fbaSOystein Eftevaag         }
3356*758e9fbaSOystein Eftevaag 
3357*758e9fbaSOystein Eftevaag         /* Retry after NULL authorization was not successful */
3358*758e9fbaSOystein Eftevaag         ifapi_init_hierarchy_object(hierarchy_object, handle);
3359*758e9fbaSOystein Eftevaag         r = ifapi_set_auth(context, hierarchy_object, "Hierarchy object");
3360*758e9fbaSOystein Eftevaag         return_if_error(r, "HierarchyChangePolicy");
3361*758e9fbaSOystein Eftevaag 
3362*758e9fbaSOystein Eftevaag         r = Esys_SetPrimaryPolicy_Async(context->esys, handle,
3363*758e9fbaSOystein Eftevaag                                         context->session1, ESYS_TR_NONE, ESYS_TR_NONE,
3364*758e9fbaSOystein Eftevaag                                         &context->cmd.Provision.policy_digest,
3365*758e9fbaSOystein Eftevaag                                         context->profiles.default_profile.nameAlg);
3366*758e9fbaSOystein Eftevaag         return_if_error(r, "Esys_SetPrimaryPolicy_Async");
3367*758e9fbaSOystein Eftevaag 
3368*758e9fbaSOystein Eftevaag         fallthrough;
3369*758e9fbaSOystein Eftevaag 
3370*758e9fbaSOystein Eftevaag     statecase(context->hierarchy_policy_state, HIERARCHY_CHANGE_POLICY_AUTH_SENT);
3371*758e9fbaSOystein Eftevaag         r = Esys_SetPrimaryPolicy_Finish(context->esys);
3372*758e9fbaSOystein Eftevaag         return_try_again(r);
3373*758e9fbaSOystein Eftevaag         return_if_error(r, "SetPrimaryPolicy_Finish");
3374*758e9fbaSOystein Eftevaag 
3375*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
3376*758e9fbaSOystein Eftevaag 
3377*758e9fbaSOystein Eftevaag     statecasedefault(context->hierarchy_policy_state);
3378*758e9fbaSOystein Eftevaag     }
3379*758e9fbaSOystein Eftevaag 
3380*758e9fbaSOystein Eftevaag error:
3381*758e9fbaSOystein Eftevaag     return r;
3382*758e9fbaSOystein Eftevaag }
3383*758e9fbaSOystein Eftevaag 
3384*758e9fbaSOystein Eftevaag /** Allocate ifapi object and store the result in a linked list.
3385*758e9fbaSOystein Eftevaag  *
3386*758e9fbaSOystein Eftevaag  * Allocated ifapi objects will be recorded in the context.
3387*758e9fbaSOystein Eftevaag  *
3388*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
3389*758e9fbaSOystein Eftevaag  *
3390*758e9fbaSOystein Eftevaag  * @retval The allocated ifapi object.
3391*758e9fbaSOystein Eftevaag  * @retval NULL if the object cannot be allocated.
3392*758e9fbaSOystein Eftevaag  */
3393*758e9fbaSOystein Eftevaag IFAPI_OBJECT
ifapi_allocate_object(FAPI_CONTEXT * context)3394*758e9fbaSOystein Eftevaag *ifapi_allocate_object(FAPI_CONTEXT *context)
3395*758e9fbaSOystein Eftevaag {
3396*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *node = calloc(1, sizeof(NODE_OBJECT_T));
3397*758e9fbaSOystein Eftevaag     if (!node)
3398*758e9fbaSOystein Eftevaag         return NULL;
3399*758e9fbaSOystein Eftevaag 
3400*758e9fbaSOystein Eftevaag     node->object = calloc(1, sizeof(IFAPI_OBJECT));
3401*758e9fbaSOystein Eftevaag     if (!node->object) {
3402*758e9fbaSOystein Eftevaag         free(node);
3403*758e9fbaSOystein Eftevaag         return NULL;
3404*758e9fbaSOystein Eftevaag     }
3405*758e9fbaSOystein Eftevaag     node->next = context->object_list;
3406*758e9fbaSOystein Eftevaag     context->object_list = node;
3407*758e9fbaSOystein Eftevaag     return (IFAPI_OBJECT *) node->object;
3408*758e9fbaSOystein Eftevaag }
3409*758e9fbaSOystein Eftevaag 
3410*758e9fbaSOystein Eftevaag /** Free all ifapi objects stored in the context.
3411*758e9fbaSOystein Eftevaag  *
3412*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
3413*758e9fbaSOystein Eftevaag  */
3414*758e9fbaSOystein Eftevaag void
ifapi_free_objects(FAPI_CONTEXT * context)3415*758e9fbaSOystein Eftevaag ifapi_free_objects(FAPI_CONTEXT *context)
3416*758e9fbaSOystein Eftevaag {
3417*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *free_node;
3418*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *node = context->object_list;
3419*758e9fbaSOystein Eftevaag     while (node) {
3420*758e9fbaSOystein Eftevaag         free(node->object);
3421*758e9fbaSOystein Eftevaag         free_node = node;
3422*758e9fbaSOystein Eftevaag         node = node->next;
3423*758e9fbaSOystein Eftevaag         free(free_node);
3424*758e9fbaSOystein Eftevaag     }
3425*758e9fbaSOystein Eftevaag }
3426*758e9fbaSOystein Eftevaag 
3427*758e9fbaSOystein Eftevaag /** Free ifapi a object stored in the context.
3428*758e9fbaSOystein Eftevaag  *
3429*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
3430*758e9fbaSOystein Eftevaag  * @param[in,out] object The object which should be removed from the
3431*758e9fbaSOystein Eftevaag  *                the linked list stored in context.
3432*758e9fbaSOystein Eftevaag  */
3433*758e9fbaSOystein Eftevaag void
ifapi_free_object(FAPI_CONTEXT * context,IFAPI_OBJECT ** object)3434*758e9fbaSOystein Eftevaag ifapi_free_object(FAPI_CONTEXT *context, IFAPI_OBJECT **object)
3435*758e9fbaSOystein Eftevaag {
3436*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *node;
3437*758e9fbaSOystein Eftevaag     NODE_OBJECT_T **update_ptr;
3438*758e9fbaSOystein Eftevaag 
3439*758e9fbaSOystein Eftevaag     for (node = context->object_list,
3440*758e9fbaSOystein Eftevaag              update_ptr = &context->object_list;
3441*758e9fbaSOystein Eftevaag              node != NULL;
3442*758e9fbaSOystein Eftevaag          update_ptr = &node->next, node = node->next) {
3443*758e9fbaSOystein Eftevaag         if (node->object == object) {
3444*758e9fbaSOystein Eftevaag             *update_ptr = node->next;
3445*758e9fbaSOystein Eftevaag             SAFE_FREE(node->object);
3446*758e9fbaSOystein Eftevaag             SAFE_FREE(node);
3447*758e9fbaSOystein Eftevaag             *object = NULL;
3448*758e9fbaSOystein Eftevaag             return;
3449*758e9fbaSOystein Eftevaag         }
3450*758e9fbaSOystein Eftevaag     }
3451*758e9fbaSOystein Eftevaag }
3452*758e9fbaSOystein Eftevaag 
3453*758e9fbaSOystein Eftevaag #define ADD_CAPABILITY_INFO(capability, field, subfield, max_count, property_count) \
3454*758e9fbaSOystein Eftevaag     if (context->cmd.GetInfo.fetched_data->data.capability.count > max_count - property_count) { \
3455*758e9fbaSOystein Eftevaag         context->cmd.GetInfo.fetched_data->data.capability.count = max_count - property_count; \
3456*758e9fbaSOystein Eftevaag     } \
3457*758e9fbaSOystein Eftevaag \
3458*758e9fbaSOystein Eftevaag     memmove(&context->cmd.GetInfo.capability_data->data.capability.field[property_count], \
3459*758e9fbaSOystein Eftevaag             context->cmd.GetInfo.fetched_data->data.capability.field, \
3460*758e9fbaSOystein Eftevaag             context->cmd.GetInfo.fetched_data->data.capability.count \
3461*758e9fbaSOystein Eftevaag             * sizeof(context->cmd.GetInfo.fetched_data->data.capability.field[0]));       \
3462*758e9fbaSOystein Eftevaag     property_count += context->cmd.GetInfo.fetched_data->data.capability.count; \
3463*758e9fbaSOystein Eftevaag \
3464*758e9fbaSOystein Eftevaag     context->cmd.GetInfo.capability_data->data.capability.count = property_count; \
3465*758e9fbaSOystein Eftevaag \
3466*758e9fbaSOystein Eftevaag     if (more_data && property_count < count \
3467*758e9fbaSOystein Eftevaag         && context->cmd.GetInfo.fetched_data->data.capability.count) {  \
3468*758e9fbaSOystein Eftevaag         context->cmd.GetInfo.property \
3469*758e9fbaSOystein Eftevaag             = context->cmd.GetInfo.capability_data->data. \
3470*758e9fbaSOystein Eftevaag             capability.field[property_count - 1]subfield + 1;   \
3471*758e9fbaSOystein Eftevaag     } else { \
3472*758e9fbaSOystein Eftevaag         more_data = false; \
3473*758e9fbaSOystein Eftevaag     }
3474*758e9fbaSOystein Eftevaag 
3475*758e9fbaSOystein Eftevaag 
3476*758e9fbaSOystein Eftevaag /** Prepare the receiving of capability data.
3477*758e9fbaSOystein Eftevaag  *
3478*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
3479*758e9fbaSOystein Eftevaag  *
3480*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS.
3481*758e9fbaSOystein Eftevaag  */
3482*758e9fbaSOystein Eftevaag TPM2_RC
ifapi_capability_init(FAPI_CONTEXT * context)3483*758e9fbaSOystein Eftevaag ifapi_capability_init(FAPI_CONTEXT *context)
3484*758e9fbaSOystein Eftevaag {
3485*758e9fbaSOystein Eftevaag     context->cmd.GetInfo.capability_data = NULL;
3486*758e9fbaSOystein Eftevaag     context->cmd.GetInfo.fetched_data = NULL;
3487*758e9fbaSOystein Eftevaag 
3488*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
3489*758e9fbaSOystein Eftevaag 
3490*758e9fbaSOystein Eftevaag 
3491*758e9fbaSOystein Eftevaag }
3492*758e9fbaSOystein Eftevaag 
3493*758e9fbaSOystein Eftevaag /** State machine for receiving TPM capability information.
3494*758e9fbaSOystein Eftevaag  *
3495*758e9fbaSOystein Eftevaag  * The state machine shares the state with the FAPI function Fapi_GetInfo.
3496*758e9fbaSOystein Eftevaag  * context->state == GET_INFO_GET_CAP_MORE signals that more capability data can
3497*758e9fbaSOystein Eftevaag  * be retrieved.
3498*758e9fbaSOystein Eftevaag  *
3499*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT.
3500*758e9fbaSOystein Eftevaag  * @param[in]     capability The capability to be retrieved.
3501*758e9fbaSOystein Eftevaag  * @param[in]     count The maximal number of items that should be retrieved.
3502*758e9fbaSOystein Eftevaag  * @param[out]    capability_data The retrieved capability information.
3503*758e9fbaSOystein Eftevaag  *
3504*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If all capability data is retrieved.
3505*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if more capability data is available.
3506*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
3507*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
3508*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
3509*758e9fbaSOystein Eftevaag  *         the function.
3510*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
3511*758e9fbaSOystein Eftevaag  *         operation already pending.
3512*758e9fbaSOystein Eftevaag  */
3513*758e9fbaSOystein Eftevaag TPM2_RC
ifapi_capability_get(FAPI_CONTEXT * context,TPM2_CAP capability,UINT32 count,TPMS_CAPABILITY_DATA ** capability_data)3514*758e9fbaSOystein Eftevaag ifapi_capability_get(FAPI_CONTEXT *context, TPM2_CAP capability,
3515*758e9fbaSOystein Eftevaag                      UINT32 count, TPMS_CAPABILITY_DATA **capability_data) {
3516*758e9fbaSOystein Eftevaag 
3517*758e9fbaSOystein Eftevaag     TPMI_YES_NO more_data;
3518*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
3519*758e9fbaSOystein Eftevaag     ESYS_CONTEXT *ectx = context->esys;
3520*758e9fbaSOystein Eftevaag 
3521*758e9fbaSOystein Eftevaag     switch (context->state) {
3522*758e9fbaSOystein Eftevaag     statecase(context->state, GET_INFO_GET_CAP);
3523*758e9fbaSOystein Eftevaag         /* fetch capability info */
3524*758e9fbaSOystein Eftevaag         context->cmd.GetInfo.fetched_data = NULL;
3525*758e9fbaSOystein Eftevaag         context->cmd.GetInfo.capability_data = NULL;
3526*758e9fbaSOystein Eftevaag         fallthrough;
3527*758e9fbaSOystein Eftevaag 
3528*758e9fbaSOystein Eftevaag     statecase(context->state, GET_INFO_GET_CAP_MORE);
3529*758e9fbaSOystein Eftevaag         r = Esys_GetCapability_Async(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
3530*758e9fbaSOystein Eftevaag                                      capability, context->cmd.GetInfo.property,
3531*758e9fbaSOystein Eftevaag                                      count - context->cmd.GetInfo.property_count);
3532*758e9fbaSOystein Eftevaag         goto_if_error(r, "Error GetCapability", error_cleanup);
3533*758e9fbaSOystein Eftevaag         fallthrough;
3534*758e9fbaSOystein Eftevaag 
3535*758e9fbaSOystein Eftevaag     statecase(context->state, GET_INFO_WAIT_FOR_CAP);
3536*758e9fbaSOystein Eftevaag         r = Esys_GetCapability_Finish(ectx, &more_data, &context->cmd.GetInfo.fetched_data);
3537*758e9fbaSOystein Eftevaag         return_try_again(r);
3538*758e9fbaSOystein Eftevaag         goto_if_error(r, "Error GetCapability", error_cleanup);
3539*758e9fbaSOystein Eftevaag 
3540*758e9fbaSOystein Eftevaag         LOG_TRACE("GetCapability: capability: 0x%x, property: 0x%x", capability,
3541*758e9fbaSOystein Eftevaag                   context->cmd.GetInfo.property);
3542*758e9fbaSOystein Eftevaag 
3543*758e9fbaSOystein Eftevaag         if (context->cmd.GetInfo.fetched_data->capability != capability) {
3544*758e9fbaSOystein Eftevaag             goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
3545*758e9fbaSOystein Eftevaag                        "TPM returned different capability than requested: 0x%x != 0x%x",
3546*758e9fbaSOystein Eftevaag                        error_cleanup,
3547*758e9fbaSOystein Eftevaag                        context->cmd.GetInfo.fetched_data->capability, capability);
3548*758e9fbaSOystein Eftevaag         }
3549*758e9fbaSOystein Eftevaag 
3550*758e9fbaSOystein Eftevaag         if (context->cmd.GetInfo.capability_data == NULL) {
3551*758e9fbaSOystein Eftevaag             /* reuse the TPM's result structure */
3552*758e9fbaSOystein Eftevaag             context->cmd.GetInfo.capability_data = context->cmd.GetInfo.fetched_data;
3553*758e9fbaSOystein Eftevaag 
3554*758e9fbaSOystein Eftevaag             if (!more_data) {
3555*758e9fbaSOystein Eftevaag                 /* there won't be another iteration of the loop, just return the result unmodified */
3556*758e9fbaSOystein Eftevaag                 *capability_data = context->cmd.GetInfo.capability_data;
3557*758e9fbaSOystein Eftevaag                 return TPM2_RC_SUCCESS;
3558*758e9fbaSOystein Eftevaag             }
3559*758e9fbaSOystein Eftevaag         }
3560*758e9fbaSOystein Eftevaag 
3561*758e9fbaSOystein Eftevaag         /* append the TPM's results to the initial structure, as long as there is still space left */
3562*758e9fbaSOystein Eftevaag         switch (capability) {
3563*758e9fbaSOystein Eftevaag         case TPM2_CAP_ALGS:
3564*758e9fbaSOystein Eftevaag             ADD_CAPABILITY_INFO(algorithms, algProperties, .alg,
3565*758e9fbaSOystein Eftevaag                                 TPM2_MAX_CAP_ALGS,
3566*758e9fbaSOystein Eftevaag                                 context->cmd.GetInfo.property_count);
3567*758e9fbaSOystein Eftevaag             break;
3568*758e9fbaSOystein Eftevaag         case TPM2_CAP_HANDLES:
3569*758e9fbaSOystein Eftevaag             ADD_CAPABILITY_INFO(handles, handle,,
3570*758e9fbaSOystein Eftevaag                                 TPM2_MAX_CAP_HANDLES,
3571*758e9fbaSOystein Eftevaag                                 context->cmd.GetInfo.property_count);
3572*758e9fbaSOystein Eftevaag             break;
3573*758e9fbaSOystein Eftevaag         case TPM2_CAP_COMMANDS:
3574*758e9fbaSOystein Eftevaag             ADD_CAPABILITY_INFO(command, commandAttributes,,
3575*758e9fbaSOystein Eftevaag                                 TPM2_MAX_CAP_CC,
3576*758e9fbaSOystein Eftevaag                                 context->cmd.GetInfo.property_count);
3577*758e9fbaSOystein Eftevaag             /* workaround because tpm2-tss does not implement attribute commandIndex for TPMA_CC */
3578*758e9fbaSOystein Eftevaag             context->cmd.GetInfo.property &= TPMA_CC_COMMANDINDEX_MASK;
3579*758e9fbaSOystein Eftevaag             break;
3580*758e9fbaSOystein Eftevaag         case TPM2_CAP_PP_COMMANDS:
3581*758e9fbaSOystein Eftevaag             ADD_CAPABILITY_INFO(ppCommands, commandCodes,,
3582*758e9fbaSOystein Eftevaag                                 TPM2_MAX_CAP_CC,
3583*758e9fbaSOystein Eftevaag                                 context->cmd.GetInfo.property_count);
3584*758e9fbaSOystein Eftevaag             break;
3585*758e9fbaSOystein Eftevaag         case TPM2_CAP_AUDIT_COMMANDS:
3586*758e9fbaSOystein Eftevaag             ADD_CAPABILITY_INFO(auditCommands, commandCodes,,
3587*758e9fbaSOystein Eftevaag                                 TPM2_MAX_CAP_CC,
3588*758e9fbaSOystein Eftevaag                                 context->cmd.GetInfo.property_count);
3589*758e9fbaSOystein Eftevaag             break;
3590*758e9fbaSOystein Eftevaag         case TPM2_CAP_PCRS:
3591*758e9fbaSOystein Eftevaag             ADD_CAPABILITY_INFO(assignedPCR, pcrSelections, .hash,
3592*758e9fbaSOystein Eftevaag                                 TPM2_NUM_PCR_BANKS,
3593*758e9fbaSOystein Eftevaag                                 context->cmd.GetInfo.property_count);
3594*758e9fbaSOystein Eftevaag             break;
3595*758e9fbaSOystein Eftevaag         case TPM2_CAP_TPM_PROPERTIES:
3596*758e9fbaSOystein Eftevaag             ADD_CAPABILITY_INFO(tpmProperties, tpmProperty, .property,
3597*758e9fbaSOystein Eftevaag                                 TPM2_MAX_TPM_PROPERTIES,
3598*758e9fbaSOystein Eftevaag                                 context->cmd.GetInfo.property_count);
3599*758e9fbaSOystein Eftevaag             break;
3600*758e9fbaSOystein Eftevaag         case TPM2_CAP_PCR_PROPERTIES:
3601*758e9fbaSOystein Eftevaag             ADD_CAPABILITY_INFO(pcrProperties, pcrProperty, .tag,
3602*758e9fbaSOystein Eftevaag                                 TPM2_MAX_PCR_PROPERTIES,
3603*758e9fbaSOystein Eftevaag                                 context->cmd.GetInfo.property_count);
3604*758e9fbaSOystein Eftevaag             break;
3605*758e9fbaSOystein Eftevaag         case TPM2_CAP_ECC_CURVES:
3606*758e9fbaSOystein Eftevaag             ADD_CAPABILITY_INFO(eccCurves, eccCurves,,
3607*758e9fbaSOystein Eftevaag                                 TPM2_MAX_ECC_CURVES,
3608*758e9fbaSOystein Eftevaag                                 context->cmd.GetInfo.property_count);
3609*758e9fbaSOystein Eftevaag             break;
3610*758e9fbaSOystein Eftevaag         case TPM2_CAP_VENDOR_PROPERTY:
3611*758e9fbaSOystein Eftevaag             ADD_CAPABILITY_INFO(intelPttProperty, property,,
3612*758e9fbaSOystein Eftevaag                                 TPM2_MAX_PTT_PROPERTIES,
3613*758e9fbaSOystein Eftevaag                                 context->cmd.GetInfo.property_count);
3614*758e9fbaSOystein Eftevaag             break;
3615*758e9fbaSOystein Eftevaag         default:
3616*758e9fbaSOystein Eftevaag             LOG_ERROR("Unsupported capability: 0x%x\n", capability);
3617*758e9fbaSOystein Eftevaag             if (context->cmd.GetInfo.fetched_data != context->cmd.GetInfo.capability_data) {
3618*758e9fbaSOystein Eftevaag                 free(context->cmd.GetInfo.fetched_data);
3619*758e9fbaSOystein Eftevaag             }
3620*758e9fbaSOystein Eftevaag             free(context->cmd.GetInfo.capability_data);
3621*758e9fbaSOystein Eftevaag             *capability_data = NULL;
3622*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_BAD_VALUE;
3623*758e9fbaSOystein Eftevaag         }
3624*758e9fbaSOystein Eftevaag 
3625*758e9fbaSOystein Eftevaag         if (context->cmd.GetInfo.fetched_data != context->cmd.GetInfo.capability_data) {
3626*758e9fbaSOystein Eftevaag             free(context->cmd.GetInfo.fetched_data);
3627*758e9fbaSOystein Eftevaag         }
3628*758e9fbaSOystein Eftevaag         *capability_data = context->cmd.GetInfo.capability_data;
3629*758e9fbaSOystein Eftevaag         break;
3630*758e9fbaSOystein Eftevaag 
3631*758e9fbaSOystein Eftevaag     statecasedefault(context->state);
3632*758e9fbaSOystein Eftevaag     }
3633*758e9fbaSOystein Eftevaag     if (more_data) {
3634*758e9fbaSOystein Eftevaag         context->state = GET_INFO_GET_CAP_MORE;
3635*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
3636*758e9fbaSOystein Eftevaag     } else {
3637*758e9fbaSOystein Eftevaag         context->state = _FAPI_STATE_INIT;
3638*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
3639*758e9fbaSOystein Eftevaag     }
3640*758e9fbaSOystein Eftevaag 
3641*758e9fbaSOystein Eftevaag error_cleanup:
3642*758e9fbaSOystein Eftevaag     context->state = _FAPI_STATE_INIT;
3643*758e9fbaSOystein Eftevaag     SAFE_FREE(context->cmd.GetInfo.capability_data);
3644*758e9fbaSOystein Eftevaag     SAFE_FREE(context->cmd.GetInfo.fetched_data);
3645*758e9fbaSOystein Eftevaag     return r;
3646*758e9fbaSOystein Eftevaag }
3647*758e9fbaSOystein Eftevaag 
3648*758e9fbaSOystein Eftevaag /** Get certificates stored in NV ram.
3649*758e9fbaSOystein Eftevaag  *
3650*758e9fbaSOystein Eftevaag  * The NV handles in the certificate range are determined. The corresponding
3651*758e9fbaSOystein Eftevaag  * certificates are read out and stored in a linked list.
3652*758e9fbaSOystein Eftevaag  *
3653*758e9fbaSOystein Eftevaag  * @param[in,out] context The FAPI_CONTEXT. The sub context for NV reading
3654*758e9fbaSOystein Eftevaag  *                will be used.
3655*758e9fbaSOystein Eftevaag  * @param[in] min_handle The first possible handle in the handle range.
3656*758e9fbaSOystein Eftevaag  * @param[in] max_handle Maximal handle to filter out the handles not in the
3657*758e9fbaSOystein Eftevaag  *            handle range for certificates.
3658*758e9fbaSOystein Eftevaag  * @param[out] cert_list The callee allocates linked list of certificates.
3659*758e9fbaSOystein Eftevaag  *
3660*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
3661*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
3662*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
3663*758e9fbaSOystein Eftevaag  *
3664*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
3665*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
3666*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
3667*758e9fbaSOystein Eftevaag  *         operation already pending.
3668*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
3669*758e9fbaSOystein Eftevaag  *         is not set.
3670*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
3671*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
3672*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
3673*758e9fbaSOystein Eftevaag  *         object store.
3674*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
3675*758e9fbaSOystein Eftevaag  *         was not successful.
3676*758e9fbaSOystein Eftevaag  */
3677*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_certificates(FAPI_CONTEXT * context,UINT32 min_handle,UINT32 max_handle,NODE_OBJECT_T ** cert_list)3678*758e9fbaSOystein Eftevaag ifapi_get_certificates(
3679*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
3680*758e9fbaSOystein Eftevaag     UINT32 min_handle,
3681*758e9fbaSOystein Eftevaag     UINT32 max_handle,
3682*758e9fbaSOystein Eftevaag     NODE_OBJECT_T **cert_list)
3683*758e9fbaSOystein Eftevaag {
3684*758e9fbaSOystein Eftevaag     TSS2_RC r;
3685*758e9fbaSOystein Eftevaag     TPMI_YES_NO moreData;
3686*758e9fbaSOystein Eftevaag     TPMS_CAPABILITY_DATA **capabilityData = &context->cmd.Provision.capabilityData;
3687*758e9fbaSOystein Eftevaag     TPM2B_NV_PUBLIC *nvPublic;
3688*758e9fbaSOystein Eftevaag     uint8_t *cert_data;
3689*758e9fbaSOystein Eftevaag     size_t cert_size;
3690*758e9fbaSOystein Eftevaag 
3691*758e9fbaSOystein Eftevaag     context->cmd.Provision.cert_nv_idx = MIN_EK_CERT_HANDLE;
3692*758e9fbaSOystein Eftevaag     context->cmd.Provision.capabilityData = NULL;
3693*758e9fbaSOystein Eftevaag 
3694*758e9fbaSOystein Eftevaag     switch (context->get_cert_state) {
3695*758e9fbaSOystein Eftevaag     statecase(context->get_cert_state, GET_CERT_INIT);
3696*758e9fbaSOystein Eftevaag         *cert_list = NULL;
3697*758e9fbaSOystein Eftevaag         context->cmd.Provision.cert_idx = 0;
3698*758e9fbaSOystein Eftevaag         /* Prepare the reading of the capability handles in the certificate range */
3699*758e9fbaSOystein Eftevaag         r = Esys_GetCapability_Async(context->esys,
3700*758e9fbaSOystein Eftevaag                                      ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
3701*758e9fbaSOystein Eftevaag                                      TPM2_CAP_HANDLES, min_handle,
3702*758e9fbaSOystein Eftevaag                                      TPM2_MAX_CAP_HANDLES);
3703*758e9fbaSOystein Eftevaag         goto_if_error(r, "Esys_GetCapability_Async", error);
3704*758e9fbaSOystein Eftevaag         fallthrough;
3705*758e9fbaSOystein Eftevaag 
3706*758e9fbaSOystein Eftevaag     statecase(context->get_cert_state, GET_CERT_WAIT_FOR_GET_CAP);
3707*758e9fbaSOystein Eftevaag         r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
3708*758e9fbaSOystein Eftevaag         return_try_again(r);
3709*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "GetCapablity_Finish", error);
3710*758e9fbaSOystein Eftevaag 
3711*758e9fbaSOystein Eftevaag         if (!*capabilityData || (*capabilityData)->data.handles.count == 0) {
3712*758e9fbaSOystein Eftevaag             *cert_list = NULL;
3713*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
3714*758e9fbaSOystein Eftevaag         }
3715*758e9fbaSOystein Eftevaag         context->cmd.Provision.capabilityData = *capabilityData;
3716*758e9fbaSOystein Eftevaag         context->cmd.Provision.cert_count = (*capabilityData)->data.handles.count;
3717*758e9fbaSOystein Eftevaag 
3718*758e9fbaSOystein Eftevaag         /* Filter out NV handles beyond the EK cert range */
3719*758e9fbaSOystein Eftevaag         for (size_t i = 0; i < context->cmd.Provision.cert_count; i++) {
3720*758e9fbaSOystein Eftevaag             if (context->cmd.Provision.capabilityData->data.handles.handle[i] > max_handle) {
3721*758e9fbaSOystein Eftevaag                 context->cmd.Provision.cert_count = i;
3722*758e9fbaSOystein Eftevaag                 break;
3723*758e9fbaSOystein Eftevaag             }
3724*758e9fbaSOystein Eftevaag         }
3725*758e9fbaSOystein Eftevaag         fallthrough;
3726*758e9fbaSOystein Eftevaag 
3727*758e9fbaSOystein Eftevaag     statecase(context->get_cert_state, GET_CERT_GET_CERT_NV);
3728*758e9fbaSOystein Eftevaag         goto_if_null(context->cmd.Provision.capabilityData,
3729*758e9fbaSOystein Eftevaag             "capabilityData is null", TSS2_FAPI_RC_MEMORY, error);
3730*758e9fbaSOystein Eftevaag         context->cmd.Provision.cert_nv_idx
3731*758e9fbaSOystein Eftevaag             = context->cmd.Provision.capabilityData
3732*758e9fbaSOystein Eftevaag             ->data.handles.handle[context->cmd.Provision.cert_idx];
3733*758e9fbaSOystein Eftevaag 
3734*758e9fbaSOystein Eftevaag         ifapi_init_hierarchy_object(&context->nv_cmd.auth_object,
3735*758e9fbaSOystein Eftevaag                                     TPM2_RH_OWNER);
3736*758e9fbaSOystein Eftevaag 
3737*758e9fbaSOystein Eftevaag         r = Esys_TR_FromTPMPublic_Async(context->esys,
3738*758e9fbaSOystein Eftevaag                                         context->cmd.Provision.cert_nv_idx,
3739*758e9fbaSOystein Eftevaag                                         ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
3740*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Esys_TR_FromTPMPublic_Async", error);
3741*758e9fbaSOystein Eftevaag         fallthrough;
3742*758e9fbaSOystein Eftevaag 
3743*758e9fbaSOystein Eftevaag     statecase(context->get_cert_state, GET_CERT_GET_CERT_NV_FINISH);
3744*758e9fbaSOystein Eftevaag         r = Esys_TR_FromTPMPublic_Finish(context->esys,
3745*758e9fbaSOystein Eftevaag                                          &context->cmd.Provision.esys_nv_cert_handle);
3746*758e9fbaSOystein Eftevaag         return_try_again(r);
3747*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "TR_FromTPMPublic_Finish", error);
3748*758e9fbaSOystein Eftevaag 
3749*758e9fbaSOystein Eftevaag         /* Read public to get size of certificate */
3750*758e9fbaSOystein Eftevaag         r = Esys_NV_ReadPublic_Async(context->esys,
3751*758e9fbaSOystein Eftevaag                                      context->cmd.Provision.esys_nv_cert_handle,
3752*758e9fbaSOystein Eftevaag                                      ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
3753*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, "Esys_NV_ReadPublic_Async", error);
3754*758e9fbaSOystein Eftevaag         fallthrough;
3755*758e9fbaSOystein Eftevaag 
3756*758e9fbaSOystein Eftevaag     statecase(context->get_cert_state, GET_CERT_GET_CERT_READ_PUBLIC);
3757*758e9fbaSOystein Eftevaag         r = Esys_NV_ReadPublic_Finish(context->esys,
3758*758e9fbaSOystein Eftevaag                                       &nvPublic,
3759*758e9fbaSOystein Eftevaag                                       NULL);
3760*758e9fbaSOystein Eftevaag         return_try_again(r);
3761*758e9fbaSOystein Eftevaag         goto_if_error(r, "Error: nv read public", error);
3762*758e9fbaSOystein Eftevaag 
3763*758e9fbaSOystein Eftevaag         /* TPMA_NV_NO_DA is set for NV certificate */
3764*758e9fbaSOystein Eftevaag         context->nv_cmd.nv_object.misc.nv.public.nvPublic.attributes = TPMA_NV_NO_DA;
3765*758e9fbaSOystein Eftevaag 
3766*758e9fbaSOystein Eftevaag         /* Prepare context for nv read */
3767*758e9fbaSOystein Eftevaag         context->nv_cmd.data_idx = 0;
3768*758e9fbaSOystein Eftevaag         context->nv_cmd.auth_index = ESYS_TR_RH_OWNER;
3769*758e9fbaSOystein Eftevaag         context->nv_cmd.numBytes = nvPublic->nvPublic.dataSize;
3770*758e9fbaSOystein Eftevaag         context->nv_cmd.esys_handle = context->cmd.Provision.esys_nv_cert_handle;
3771*758e9fbaSOystein Eftevaag         context->nv_cmd.offset = 0;
3772*758e9fbaSOystein Eftevaag         context->cmd.Provision.pem_cert = NULL;
3773*758e9fbaSOystein Eftevaag         context->session1 = ESYS_TR_PASSWORD;
3774*758e9fbaSOystein Eftevaag         context->session2 = ESYS_TR_NONE;
3775*758e9fbaSOystein Eftevaag         context->nv_cmd.nv_read_state = NV_READ_INIT;
3776*758e9fbaSOystein Eftevaag         memset(&context->nv_cmd.nv_object, 0, sizeof(IFAPI_OBJECT));
3777*758e9fbaSOystein Eftevaag         Esys_Free(nvPublic);
3778*758e9fbaSOystein Eftevaag         fallthrough;
3779*758e9fbaSOystein Eftevaag 
3780*758e9fbaSOystein Eftevaag     statecase(context->get_cert_state, GET_CERT_READ_CERT);
3781*758e9fbaSOystein Eftevaag         r = ifapi_nv_read(context, &cert_data, &cert_size);
3782*758e9fbaSOystein Eftevaag         return_try_again(r);
3783*758e9fbaSOystein Eftevaag         goto_if_error_reset_state(r, " FAPI NV_Read", error);
3784*758e9fbaSOystein Eftevaag 
3785*758e9fbaSOystein Eftevaag         context->cmd.Provision.cert_idx += 1;
3786*758e9fbaSOystein Eftevaag 
3787*758e9fbaSOystein Eftevaag         /* Add cert to list */
3788*758e9fbaSOystein Eftevaag         if (context->cmd.Provision.cert_idx == context->cmd.Provision.cert_count) {
3789*758e9fbaSOystein Eftevaag             context->get_cert_state = GET_CERT_GET_CERT_NV;
3790*758e9fbaSOystein Eftevaag 
3791*758e9fbaSOystein Eftevaag             r = push_object_with_size_to_list(cert_data, cert_size, cert_list);
3792*758e9fbaSOystein Eftevaag             goto_if_error(r, "Store certificate in list.", error);
3793*758e9fbaSOystein Eftevaag 
3794*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
3795*758e9fbaSOystein Eftevaag         } else {
3796*758e9fbaSOystein Eftevaag             context->get_cert_state = GET_CERT_GET_CERT_NV;
3797*758e9fbaSOystein Eftevaag         }
3798*758e9fbaSOystein Eftevaag         break;
3799*758e9fbaSOystein Eftevaag 
3800*758e9fbaSOystein Eftevaag     statecasedefault(context->get_cert_state);
3801*758e9fbaSOystein Eftevaag     }
3802*758e9fbaSOystein Eftevaag 
3803*758e9fbaSOystein Eftevaag error:
3804*758e9fbaSOystein Eftevaag     ifapi_free_object_list(*cert_list);
3805*758e9fbaSOystein Eftevaag     return r;
3806*758e9fbaSOystein Eftevaag }
3807*758e9fbaSOystein Eftevaag 
3808*758e9fbaSOystein Eftevaag 
3809*758e9fbaSOystein Eftevaag /** Get description of an internal FAPI object.
3810*758e9fbaSOystein Eftevaag  *
3811*758e9fbaSOystein Eftevaag  * @param[in] object The object with the description.
3812*758e9fbaSOystein Eftevaag  * @param[out] description The callee allocated description.
3813*758e9fbaSOystein Eftevaag  *
3814*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If a copy of the description can be returned
3815*758e9fbaSOystein Eftevaag  *         or if no description exists.
3816*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY in the copy cannot be allocated.
3817*758e9fbaSOystein Eftevaag  */
3818*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_description(IFAPI_OBJECT * object,char ** description)3819*758e9fbaSOystein Eftevaag ifapi_get_description(IFAPI_OBJECT *object, char **description)
3820*758e9fbaSOystein Eftevaag {
3821*758e9fbaSOystein Eftevaag     char *obj_description = NULL;
3822*758e9fbaSOystein Eftevaag 
3823*758e9fbaSOystein Eftevaag     switch (object->objectType) {
3824*758e9fbaSOystein Eftevaag     case IFAPI_KEY_OBJ:
3825*758e9fbaSOystein Eftevaag         obj_description = object->misc.key.description;
3826*758e9fbaSOystein Eftevaag         break;
3827*758e9fbaSOystein Eftevaag     case IFAPI_NV_OBJ:
3828*758e9fbaSOystein Eftevaag         obj_description = object->misc.nv.description;
3829*758e9fbaSOystein Eftevaag         break;
3830*758e9fbaSOystein Eftevaag     case IFAPI_HIERARCHY_OBJ:
3831*758e9fbaSOystein Eftevaag         obj_description = object->misc.hierarchy.description;
3832*758e9fbaSOystein Eftevaag         break;
3833*758e9fbaSOystein Eftevaag     default:
3834*758e9fbaSOystein Eftevaag         *description = NULL;
3835*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
3836*758e9fbaSOystein Eftevaag     }
3837*758e9fbaSOystein Eftevaag     if (obj_description) {
3838*758e9fbaSOystein Eftevaag         *description = strdup(obj_description);
3839*758e9fbaSOystein Eftevaag         check_oom(*description);
3840*758e9fbaSOystein Eftevaag     } else {
3841*758e9fbaSOystein Eftevaag         *description = NULL;
3842*758e9fbaSOystein Eftevaag     }
3843*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
3844*758e9fbaSOystein Eftevaag }
3845*758e9fbaSOystein Eftevaag 
3846*758e9fbaSOystein Eftevaag /** Set description of an internal FAPI object.
3847*758e9fbaSOystein Eftevaag  *
3848*758e9fbaSOystein Eftevaag  * @param[in,out] object The object with the description.
3849*758e9fbaSOystein Eftevaag  * @param[in] description The description char strint or NULL.
3850*758e9fbaSOystein Eftevaag  */
3851*758e9fbaSOystein Eftevaag void
ifapi_set_description(IFAPI_OBJECT * object,char * description)3852*758e9fbaSOystein Eftevaag ifapi_set_description(IFAPI_OBJECT *object, char *description)
3853*758e9fbaSOystein Eftevaag {
3854*758e9fbaSOystein Eftevaag     switch (object->objectType) {
3855*758e9fbaSOystein Eftevaag     case IFAPI_KEY_OBJ:
3856*758e9fbaSOystein Eftevaag         SAFE_FREE(object->misc.key.description);
3857*758e9fbaSOystein Eftevaag         object->misc.key.description = description;
3858*758e9fbaSOystein Eftevaag         break;
3859*758e9fbaSOystein Eftevaag     case IFAPI_NV_OBJ:
3860*758e9fbaSOystein Eftevaag         SAFE_FREE(object->misc.nv.description);
3861*758e9fbaSOystein Eftevaag         object->misc.nv.description = description;
3862*758e9fbaSOystein Eftevaag         break;
3863*758e9fbaSOystein Eftevaag     case IFAPI_HIERARCHY_OBJ:
3864*758e9fbaSOystein Eftevaag         SAFE_FREE(object->misc.hierarchy.description);
3865*758e9fbaSOystein Eftevaag         object->misc.hierarchy.description = description;
3866*758e9fbaSOystein Eftevaag         break;
3867*758e9fbaSOystein Eftevaag     default:
3868*758e9fbaSOystein Eftevaag         LOG_WARNING("Description can't be set");
3869*758e9fbaSOystein Eftevaag         break;
3870*758e9fbaSOystein Eftevaag     }
3871*758e9fbaSOystein Eftevaag }
3872