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