xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/ifapi_policy_callbacks.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1*758e9fbaSOystein Eftevaag /* SPDX-License-Identifier: BSD-2-Clause */
2*758e9fbaSOystein Eftevaag /*******************************************************************************
3*758e9fbaSOystein Eftevaag  * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
4*758e9fbaSOystein Eftevaag  * All rights reserved.
5*758e9fbaSOystein Eftevaag  *******************************************************************************/
6*758e9fbaSOystein Eftevaag 
7*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
8*758e9fbaSOystein Eftevaag #include <config.h>
9*758e9fbaSOystein Eftevaag #endif
10*758e9fbaSOystein Eftevaag 
11*758e9fbaSOystein Eftevaag #include <string.h>
12*758e9fbaSOystein Eftevaag #include <stdlib.h>
13*758e9fbaSOystein Eftevaag 
14*758e9fbaSOystein Eftevaag #include "fapi_util.h"
15*758e9fbaSOystein Eftevaag #include "fapi_policy.h"
16*758e9fbaSOystein Eftevaag #include "ifapi_helpers.h"
17*758e9fbaSOystein Eftevaag #include "fapi_crypto.h"
18*758e9fbaSOystein Eftevaag #include "ifapi_policy_instantiate.h"
19*758e9fbaSOystein Eftevaag #include "ifapi_policyutil_execute.h"
20*758e9fbaSOystein Eftevaag #include "ifapi_policy_execute.h"
21*758e9fbaSOystein Eftevaag #include "ifapi_policy_callbacks.h"
22*758e9fbaSOystein Eftevaag #include "tss2_mu.h"
23*758e9fbaSOystein Eftevaag 
24*758e9fbaSOystein Eftevaag #define LOGMODULE fapi
25*758e9fbaSOystein Eftevaag #include "util/log.h"
26*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
27*758e9fbaSOystein Eftevaag 
28*758e9fbaSOystein Eftevaag /** Determine the auth object of a NV index.
29*758e9fbaSOystein Eftevaag  *
30*758e9fbaSOystein Eftevaag  * The auth object is determined depending on the object flags.
31*758e9fbaSOystein Eftevaag  *
32*758e9fbaSOystein Eftevaag  * @param[in]  nv_object The internal FAPI object representing the NV index.
33*758e9fbaSOystein Eftevaag  * @param[out] nv_index The ESYS handle of the NV index.
34*758e9fbaSOystein Eftevaag  * @param[out] auth_object The internal FAPI auth object.
35*758e9fbaSOystein Eftevaag  * @param[out] auth_index The ESYS handle of the auth object.
36*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
37*758e9fbaSOystein Eftevaag  */
38*758e9fbaSOystein Eftevaag static void
get_nv_auth_object(IFAPI_OBJECT * nv_object,ESYS_TR nv_index,IFAPI_OBJECT * auth_object,ESYS_TR * auth_index)39*758e9fbaSOystein Eftevaag get_nv_auth_object(
40*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *nv_object,
41*758e9fbaSOystein Eftevaag     ESYS_TR nv_index,
42*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *auth_object,
43*758e9fbaSOystein Eftevaag     ESYS_TR *auth_index)
44*758e9fbaSOystein Eftevaag {
45*758e9fbaSOystein Eftevaag     if (nv_object->misc.nv.public.nvPublic.attributes & TPMA_NV_PPREAD) {
46*758e9fbaSOystein Eftevaag         ifapi_init_hierarchy_object(auth_object, ESYS_TR_RH_PLATFORM);
47*758e9fbaSOystein Eftevaag         *auth_index = ESYS_TR_RH_PLATFORM;
48*758e9fbaSOystein Eftevaag     } else {
49*758e9fbaSOystein Eftevaag         if (nv_object->misc.nv.public.nvPublic.attributes & TPMA_NV_OWNERREAD) {
50*758e9fbaSOystein Eftevaag             ifapi_init_hierarchy_object(auth_object, ESYS_TR_RH_OWNER);
51*758e9fbaSOystein Eftevaag             *auth_index = ESYS_TR_RH_OWNER;
52*758e9fbaSOystein Eftevaag         } else {
53*758e9fbaSOystein Eftevaag             *auth_index = nv_index;
54*758e9fbaSOystein Eftevaag             *auth_object = *nv_object;
55*758e9fbaSOystein Eftevaag         }
56*758e9fbaSOystein Eftevaag     }
57*758e9fbaSOystein Eftevaag }
58*758e9fbaSOystein Eftevaag 
59*758e9fbaSOystein Eftevaag /** Get public data of a key from keystore.
60*758e9fbaSOystein Eftevaag  *
61*758e9fbaSOystein Eftevaag  * @param[in] path The relative path of the key.
62*758e9fbaSOystein Eftevaag  * @param[out] public The caller allocated public structure.
63*758e9fbaSOystein Eftevaag  * @param[in,out] ctx The context to access io and keystore module and to store
64*758e9fbaSOystein Eftevaag  *                      the io state.
65*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
66*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be loaded.
67*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
68*758e9fbaSOystein Eftevaag  *         internal operations or return parameters.
69*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_TEMPLATE If the loaded template is not
70*758e9fbaSOystein Eftevaag  *         appropriate for this operation.
71*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
72*758e9fbaSOystein Eftevaag  *         the function.
73*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
74*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
75*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
76*758e9fbaSOystein Eftevaag  *         operation already pending.
77*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
78*758e9fbaSOystein Eftevaag  *         during authorization.
79*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
80*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
81*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
82*758e9fbaSOystein Eftevaag  */
83*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_key_public(const char * path,TPMT_PUBLIC * public,void * ctx)84*758e9fbaSOystein Eftevaag ifapi_get_key_public(
85*758e9fbaSOystein Eftevaag     const char *path,
86*758e9fbaSOystein Eftevaag     TPMT_PUBLIC *public,
87*758e9fbaSOystein Eftevaag     void *ctx)
88*758e9fbaSOystein Eftevaag {
89*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
90*758e9fbaSOystein Eftevaag     IFAPI_OBJECT object;
91*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context = ctx;
92*758e9fbaSOystein Eftevaag 
93*758e9fbaSOystein Eftevaag     switch (context->io_state) {
94*758e9fbaSOystein Eftevaag     statecase(context->io_state, IO_INIT)
95*758e9fbaSOystein Eftevaag         /* Prepare the loading of the object. */
96*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
97*758e9fbaSOystein Eftevaag         return_if_error2(r, "Could not open: %s", path);
98*758e9fbaSOystein Eftevaag         fallthrough;
99*758e9fbaSOystein Eftevaag 
100*758e9fbaSOystein Eftevaag     statecase(context->io_state, IO_ACTIVE)
101*758e9fbaSOystein Eftevaag         /* Finalize or retry the reading and check the object type */
102*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_finish(&context->keystore, &context->io,
103*758e9fbaSOystein Eftevaag                                        &object);
104*758e9fbaSOystein Eftevaag         return_try_again(r);
105*758e9fbaSOystein Eftevaag         return_if_error(r, "read_finish failed");
106*758e9fbaSOystein Eftevaag 
107*758e9fbaSOystein Eftevaag         switch (object.objectType) {
108*758e9fbaSOystein Eftevaag         case IFAPI_KEY_OBJ:
109*758e9fbaSOystein Eftevaag             *public = object.misc.key.public.publicArea;
110*758e9fbaSOystein Eftevaag             break;
111*758e9fbaSOystein Eftevaag         case IFAPI_EXT_PUB_KEY_OBJ:
112*758e9fbaSOystein Eftevaag             *public = object.misc.ext_pub_key.public.publicArea;
113*758e9fbaSOystein Eftevaag             break;
114*758e9fbaSOystein Eftevaag         default:
115*758e9fbaSOystein Eftevaag             goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Object %s is not a key.",
116*758e9fbaSOystein Eftevaag                        cleanup, path);
117*758e9fbaSOystein Eftevaag         }
118*758e9fbaSOystein Eftevaag         break;
119*758e9fbaSOystein Eftevaag 
120*758e9fbaSOystein Eftevaag     statecasedefault_error(context->state, r, cleanup);
121*758e9fbaSOystein Eftevaag     }
122*758e9fbaSOystein Eftevaag 
123*758e9fbaSOystein Eftevaag cleanup:
124*758e9fbaSOystein Eftevaag     context->io_state = IO_INIT;
125*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&object);
126*758e9fbaSOystein Eftevaag     return r;
127*758e9fbaSOystein Eftevaag }
128*758e9fbaSOystein Eftevaag 
129*758e9fbaSOystein Eftevaag /** Get TPM name of an object from  key keystore.
130*758e9fbaSOystein Eftevaag  *
131*758e9fbaSOystein Eftevaag  * @param[in] path The relative path of the object.
132*758e9fbaSOystein Eftevaag  * @param[out] name The caller allocate public structure.
133*758e9fbaSOystein Eftevaag  * @param[in,out] ctx The context to access io and keystore module and to store
134*758e9fbaSOystein Eftevaag  *                the io state.
135*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
136*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be loaded.
137*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
138*758e9fbaSOystein Eftevaag  *         internal operations or return parameters.
139*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_TEMPLATE If the loaded template is not
140*758e9fbaSOystein Eftevaag  *         appropriate for this operation.
141*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
142*758e9fbaSOystein Eftevaag  *         the function.
143*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
144*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
145*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
146*758e9fbaSOystein Eftevaag  *         operation already pending.
147*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
148*758e9fbaSOystein Eftevaag  *         during authorization.
149*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
150*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
151*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
152*758e9fbaSOystein Eftevaag  */
153*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_object_name(const char * path,TPM2B_NAME * name,void * ctx)154*758e9fbaSOystein Eftevaag ifapi_get_object_name(
155*758e9fbaSOystein Eftevaag     const char *path,
156*758e9fbaSOystein Eftevaag     TPM2B_NAME *name,
157*758e9fbaSOystein Eftevaag     void *ctx)
158*758e9fbaSOystein Eftevaag {
159*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
160*758e9fbaSOystein Eftevaag     IFAPI_OBJECT object;
161*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context = ctx;
162*758e9fbaSOystein Eftevaag 
163*758e9fbaSOystein Eftevaag     switch (context->io_state) {
164*758e9fbaSOystein Eftevaag     statecase(context->io_state, IO_INIT)
165*758e9fbaSOystein Eftevaag         /* Prepare the loading of the object. */
166*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
167*758e9fbaSOystein Eftevaag         return_if_error2(r, "Could not open: %s", path);
168*758e9fbaSOystein Eftevaag         fallthrough;
169*758e9fbaSOystein Eftevaag 
170*758e9fbaSOystein Eftevaag     statecase(context->io_state, IO_ACTIVE)
171*758e9fbaSOystein Eftevaag         /* Finalize or retry the reading and check the object type */
172*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_finish(&context->keystore, &context->io,
173*758e9fbaSOystein Eftevaag                                        &object);
174*758e9fbaSOystein Eftevaag         return_try_again(r);
175*758e9fbaSOystein Eftevaag         return_if_error(r, "read_finish failed");
176*758e9fbaSOystein Eftevaag 
177*758e9fbaSOystein Eftevaag         switch (object.objectType) {
178*758e9fbaSOystein Eftevaag         case IFAPI_KEY_OBJ:
179*758e9fbaSOystein Eftevaag             r = ifapi_get_name(&object.misc.key.public.publicArea,
180*758e9fbaSOystein Eftevaag                                (TPM2B_NAME *)name);
181*758e9fbaSOystein Eftevaag             break;
182*758e9fbaSOystein Eftevaag         case IFAPI_EXT_PUB_KEY_OBJ:
183*758e9fbaSOystein Eftevaag             r = ifapi_get_name(&object.misc.ext_pub_key.public.publicArea,
184*758e9fbaSOystein Eftevaag                                (TPM2B_NAME *)name);
185*758e9fbaSOystein Eftevaag             break;
186*758e9fbaSOystein Eftevaag         case IFAPI_NV_OBJ:
187*758e9fbaSOystein Eftevaag             r = ifapi_nv_get_name(&object.misc.nv.public, name);
188*758e9fbaSOystein Eftevaag             break;
189*758e9fbaSOystein Eftevaag         default:
190*758e9fbaSOystein Eftevaag             goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid object %s.",
191*758e9fbaSOystein Eftevaag                        cleanup, path);
192*758e9fbaSOystein Eftevaag         }
193*758e9fbaSOystein Eftevaag         goto_if_error(r, "Get object name.", cleanup);
194*758e9fbaSOystein Eftevaag         break;
195*758e9fbaSOystein Eftevaag 
196*758e9fbaSOystein Eftevaag     statecasedefault(context->state);
197*758e9fbaSOystein Eftevaag     }
198*758e9fbaSOystein Eftevaag 
199*758e9fbaSOystein Eftevaag cleanup:
200*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&object);
201*758e9fbaSOystein Eftevaag     return r;
202*758e9fbaSOystein Eftevaag }
203*758e9fbaSOystein Eftevaag 
204*758e9fbaSOystein Eftevaag /** Get public data of a NV object from keystore.
205*758e9fbaSOystein Eftevaag  *
206*758e9fbaSOystein Eftevaag  * @param[in] path The relative path of the NV object.
207*758e9fbaSOystein Eftevaag  * @param[out] nv_public The caller allocated public structure.
208*758e9fbaSOystein Eftevaag  * @param[in,out] ctx The context to access io and keystore module and to store
209*758e9fbaSOystein Eftevaag  *                the io state.
210*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
211*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be loaded.
212*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
213*758e9fbaSOystein Eftevaag  *         internal operations or return parameters.
214*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_TEMPLATE If the loaded template is not
215*758e9fbaSOystein Eftevaag  *         appropriate for this operation.
216*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
217*758e9fbaSOystein Eftevaag  *         the function.
218*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
219*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
220*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
221*758e9fbaSOystein Eftevaag  *         operation already pending.
222*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
223*758e9fbaSOystein Eftevaag  *         during authorization.
224*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
225*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
226*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
227*758e9fbaSOystein Eftevaag  */
228*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_nv_public(const char * path,TPM2B_NV_PUBLIC * nv_public,void * ctx)229*758e9fbaSOystein Eftevaag ifapi_get_nv_public(
230*758e9fbaSOystein Eftevaag     const char *path,
231*758e9fbaSOystein Eftevaag     TPM2B_NV_PUBLIC *nv_public,
232*758e9fbaSOystein Eftevaag     void *ctx)
233*758e9fbaSOystein Eftevaag {
234*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
235*758e9fbaSOystein Eftevaag     IFAPI_OBJECT object;
236*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context = ctx;
237*758e9fbaSOystein Eftevaag 
238*758e9fbaSOystein Eftevaag     switch (context->io_state) {
239*758e9fbaSOystein Eftevaag     statecase(context->io_state, IO_INIT)
240*758e9fbaSOystein Eftevaag         /* Prepare the loading of the NV object. */
241*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
242*758e9fbaSOystein Eftevaag         return_if_error2(r, "Could not open: %s", path);
243*758e9fbaSOystein Eftevaag         fallthrough;
244*758e9fbaSOystein Eftevaag 
245*758e9fbaSOystein Eftevaag     statecase(context->io_state, IO_ACTIVE)
246*758e9fbaSOystein Eftevaag         /* Finalize or retry the reading and check the object type */
247*758e9fbaSOystein Eftevaag         r = ifapi_keystore_load_finish(&context->keystore, &context->io,
248*758e9fbaSOystein Eftevaag                                        &object);
249*758e9fbaSOystein Eftevaag         return_try_again(r);
250*758e9fbaSOystein Eftevaag         return_if_error(r, "read_finish failed");
251*758e9fbaSOystein Eftevaag 
252*758e9fbaSOystein Eftevaag         if (object.objectType != IFAPI_NV_OBJ) {
253*758e9fbaSOystein Eftevaag             goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Object %s is not a key.",
254*758e9fbaSOystein Eftevaag                        cleanup, path);
255*758e9fbaSOystein Eftevaag         }
256*758e9fbaSOystein Eftevaag 
257*758e9fbaSOystein Eftevaag         *nv_public = object.misc.nv.public;
258*758e9fbaSOystein Eftevaag         context->io_state = IO_INIT;
259*758e9fbaSOystein Eftevaag         break;
260*758e9fbaSOystein Eftevaag 
261*758e9fbaSOystein Eftevaag     statecasedefault(context->state);
262*758e9fbaSOystein Eftevaag     }
263*758e9fbaSOystein Eftevaag 
264*758e9fbaSOystein Eftevaag cleanup:
265*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&object);
266*758e9fbaSOystein Eftevaag     return r;
267*758e9fbaSOystein Eftevaag }
268*758e9fbaSOystein Eftevaag 
269*758e9fbaSOystein Eftevaag /** Read values of PCR registers and clear selection.
270*758e9fbaSOystein Eftevaag  *
271*758e9fbaSOystein Eftevaag  * @param[in,out] pcr_select The registers to be read (bank selection from profile).
272*758e9fbaSOystein Eftevaag  * @param[in,out] pcr_selection The registers to be read (with bank selection).
273*758e9fbaSOystein Eftevaag  * @param[out] pcr_values The callee-allocated public structure.
274*758e9fbaSOystein Eftevaag  * @param[in,out] ctx The context to access io and keystore module and to store
275*758e9fbaSOystein Eftevaag  *                the io state.
276*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
277*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if the input parameters had inappropriate values.
278*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
279*758e9fbaSOystein Eftevaag  *         complete. Call this function again later.
280*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
281*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
282*758e9fbaSOystein Eftevaag  *         operation already pending.
283*758e9fbaSOystein Eftevaag  */
284*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_read_pcr(TPMS_PCR_SELECT * pcr_select,TPML_PCR_SELECTION * pcr_selection,TPML_PCRVALUES ** pcr_values,void * ctx)285*758e9fbaSOystein Eftevaag ifapi_read_pcr(
286*758e9fbaSOystein Eftevaag     TPMS_PCR_SELECT *pcr_select,
287*758e9fbaSOystein Eftevaag     TPML_PCR_SELECTION *pcr_selection,
288*758e9fbaSOystein Eftevaag     TPML_PCRVALUES **pcr_values,
289*758e9fbaSOystein Eftevaag     void *ctx)
290*758e9fbaSOystein Eftevaag {
291*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
292*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context = ctx;
293*758e9fbaSOystein Eftevaag     UINT32 update_counter;
294*758e9fbaSOystein Eftevaag     TPML_PCR_SELECTION *out_selection = NULL;
295*758e9fbaSOystein Eftevaag     TPML_PCR_SELECTION *profile_selection;
296*758e9fbaSOystein Eftevaag     TPML_DIGEST *pcr_digests = NULL;
297*758e9fbaSOystein Eftevaag     size_t i, pcr, n_pcrs = 0, i_pcr;
298*758e9fbaSOystein Eftevaag 
299*758e9fbaSOystein Eftevaag     switch (context->io_state) {
300*758e9fbaSOystein Eftevaag     statecase(context->io_state, IO_INIT)
301*758e9fbaSOystein Eftevaag         if (pcr_select->sizeofSelect) {
302*758e9fbaSOystein Eftevaag             if (pcr_selection->count) {
303*758e9fbaSOystein Eftevaag                 /* If pcr_select is used pcr_selection can't be initialized */
304*758e9fbaSOystein Eftevaag                 return_error(TSS2_FAPI_RC_BAD_VALUE,
305*758e9fbaSOystein Eftevaag                              "Policy PCR: pcr_selection can't be used if pcr_selection is used.");
306*758e9fbaSOystein Eftevaag             }
307*758e9fbaSOystein Eftevaag             /* Determine hash alg */
308*758e9fbaSOystein Eftevaag             profile_selection = &context->profiles.default_profile.pcr_selection;
309*758e9fbaSOystein Eftevaag             for (i = 0; i < profile_selection->count; i++) {
310*758e9fbaSOystein Eftevaag                 for (pcr = 0; pcr < TPM2_MAX_PCRS; pcr++) {
311*758e9fbaSOystein Eftevaag                     uint8_t byte_idx = pcr / 8;
312*758e9fbaSOystein Eftevaag                     uint8_t flag = 1 << (pcr % 8);
313*758e9fbaSOystein Eftevaag                     /* Check whether PCR is used. */
314*758e9fbaSOystein Eftevaag                     if (flag & profile_selection->pcrSelections[i].pcrSelect[byte_idx] &&
315*758e9fbaSOystein Eftevaag                         flag & pcr_select->pcrSelect[byte_idx]) {
316*758e9fbaSOystein Eftevaag                         pcr_selection->pcrSelections[0].hash = profile_selection->pcrSelections[i].hash;
317*758e9fbaSOystein Eftevaag                     }
318*758e9fbaSOystein Eftevaag                 }
319*758e9fbaSOystein Eftevaag             }
320*758e9fbaSOystein Eftevaag             if (!pcr_selection->pcrSelections[0].hash) {
321*758e9fbaSOystein Eftevaag                 /* hash for current pcr_select can't be determined */
322*758e9fbaSOystein Eftevaag                 return_error(TSS2_FAPI_RC_BAD_VALUE,
323*758e9fbaSOystein Eftevaag                              "Policy PCR: pcr_select does not match profile.");
324*758e9fbaSOystein Eftevaag             }
325*758e9fbaSOystein Eftevaag             /* Only one bank will be used. The hash alg from profile will be used */
326*758e9fbaSOystein Eftevaag             pcr_selection->count = 1;
327*758e9fbaSOystein Eftevaag             pcr_selection->pcrSelections[0].sizeofSelect = pcr_select->sizeofSelect;
328*758e9fbaSOystein Eftevaag             for (i = 0; i < pcr_select->sizeofSelect; i++)
329*758e9fbaSOystein Eftevaag                 pcr_selection->pcrSelections[0].pcrSelect[i] = pcr_select->pcrSelect[i];
330*758e9fbaSOystein Eftevaag         }
331*758e9fbaSOystein Eftevaag 
332*758e9fbaSOystein Eftevaag         /* Prepare the PCR Reading. */
333*758e9fbaSOystein Eftevaag         r = Esys_PCR_Read_Async(context->esys,
334*758e9fbaSOystein Eftevaag                                 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
335*758e9fbaSOystein Eftevaag                                 pcr_selection);
336*758e9fbaSOystein Eftevaag         return_if_error(r, "PCR Read");
337*758e9fbaSOystein Eftevaag         fallthrough;
338*758e9fbaSOystein Eftevaag 
339*758e9fbaSOystein Eftevaag     statecase(context->io_state, IO_ACTIVE)
340*758e9fbaSOystein Eftevaag         /* Finalize or retry the reading and check the object type */
341*758e9fbaSOystein Eftevaag         r = Esys_PCR_Read_Finish(context->esys,
342*758e9fbaSOystein Eftevaag                                  &update_counter,
343*758e9fbaSOystein Eftevaag                                  &out_selection,
344*758e9fbaSOystein Eftevaag                                  &pcr_digests);
345*758e9fbaSOystein Eftevaag 
346*758e9fbaSOystein Eftevaag         if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
347*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_TRY_AGAIN;
348*758e9fbaSOystein Eftevaag 
349*758e9fbaSOystein Eftevaag         return_if_error(r, "PCR_Read_Finish");
350*758e9fbaSOystein Eftevaag 
351*758e9fbaSOystein Eftevaag         /* Count pcrs */
352*758e9fbaSOystein Eftevaag         for (i = 0; i < out_selection->count; i++) {
353*758e9fbaSOystein Eftevaag             for (pcr = 0; pcr < TPM2_MAX_PCRS; pcr++) {
354*758e9fbaSOystein Eftevaag                 uint8_t byte_idx = pcr / 8;
355*758e9fbaSOystein Eftevaag                 uint8_t flag = 1 << (pcr % 8);
356*758e9fbaSOystein Eftevaag                 /* Check whether PCR is used. */
357*758e9fbaSOystein Eftevaag                 if (flag & out_selection->pcrSelections[i].pcrSelect[byte_idx])
358*758e9fbaSOystein Eftevaag                     n_pcrs += 1;
359*758e9fbaSOystein Eftevaag             }
360*758e9fbaSOystein Eftevaag         }
361*758e9fbaSOystein Eftevaag 
362*758e9fbaSOystein Eftevaag         *pcr_values = calloc(1, sizeof(TPML_PCRVALUES) + n_pcrs* sizeof(TPMS_PCRVALUE));
363*758e9fbaSOystein Eftevaag         goto_if_null2(*pcr_values, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup);
364*758e9fbaSOystein Eftevaag 
365*758e9fbaSOystein Eftevaag         /* Initialize digest list with pcr values from TPM */
366*758e9fbaSOystein Eftevaag         i_pcr = 0;
367*758e9fbaSOystein Eftevaag         for (i = 0; i < out_selection->count; i++) {
368*758e9fbaSOystein Eftevaag             for (pcr = 0; pcr < TPM2_MAX_PCRS; pcr++) {
369*758e9fbaSOystein Eftevaag                 uint8_t byte_idx = pcr / 8;
370*758e9fbaSOystein Eftevaag                 uint8_t flag = 1 << (pcr % 8);
371*758e9fbaSOystein Eftevaag                 /* Check whether PCR is used. */
372*758e9fbaSOystein Eftevaag                 if (flag & out_selection->pcrSelections[i].pcrSelect[byte_idx]) {
373*758e9fbaSOystein Eftevaag                     (*pcr_values)->pcrs[i_pcr].pcr = pcr;
374*758e9fbaSOystein Eftevaag                     (*pcr_values)->pcrs[i_pcr].hashAlg = out_selection->pcrSelections[i].hash;
375*758e9fbaSOystein Eftevaag                     memcpy(&(*pcr_values)->pcrs[i_pcr].digest,
376*758e9fbaSOystein Eftevaag                            &pcr_digests->digests[i_pcr].buffer[0],
377*758e9fbaSOystein Eftevaag                            pcr_digests->digests[i_pcr].size);
378*758e9fbaSOystein Eftevaag                     i_pcr += 1;
379*758e9fbaSOystein Eftevaag                 }
380*758e9fbaSOystein Eftevaag             }
381*758e9fbaSOystein Eftevaag         }
382*758e9fbaSOystein Eftevaag 
383*758e9fbaSOystein Eftevaag         context->io_state = IO_INIT;
384*758e9fbaSOystein Eftevaag         break;
385*758e9fbaSOystein Eftevaag 
386*758e9fbaSOystein Eftevaag     statecasedefault(context->state);
387*758e9fbaSOystein Eftevaag     }
388*758e9fbaSOystein Eftevaag 
389*758e9fbaSOystein Eftevaag cleanup:
390*758e9fbaSOystein Eftevaag     SAFE_FREE(out_selection);
391*758e9fbaSOystein Eftevaag     SAFE_FREE(pcr_digests);
392*758e9fbaSOystein Eftevaag     return r;
393*758e9fbaSOystein Eftevaag }
394*758e9fbaSOystein Eftevaag 
395*758e9fbaSOystein Eftevaag /** Callback for authorization of objects used by policy.
396*758e9fbaSOystein Eftevaag  *
397*758e9fbaSOystein Eftevaag  * @param[in] name The name of the object to be authorized.
398*758e9fbaSOystein Eftevaag  * @param[in] object_handle The ESYS handle of the used object.
399*758e9fbaSOystein Eftevaag  * @param[in] auth_handle will be used for object authorization. For
400*758e9fbaSOystein Eftevaag               keys it will we equal to the object handle.
401*758e9fbaSOystein Eftevaag  * @param[out] authSession The session used for object authorization.
402*758e9fbaSOystein Eftevaag  * @param[in,out] userdata The Fapi context which will be used for keystore
403*758e9fbaSOystein Eftevaag  *                access, and storing the policy execution state.
404*758e9fbaSOystein Eftevaag  *                the io state.
405*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
406*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or policy is NULL.
407*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
408*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
409*758e9fbaSOystein Eftevaag  *         complete. Call this function again later.
410*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
411*758e9fbaSOystein Eftevaag  *         operation already pending.
412*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy was not found.
413*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND If a key was not found.
414*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If an IO error occurred during reading
415*758e9fbaSOystein Eftevaag  *         a policy or a key.
416*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an error in an used library
417*758e9fbaSOystein Eftevaag  *         occurred.
418*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
419*758e9fbaSOystein Eftevaag  *         the function.
420*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
421*758e9fbaSOystein Eftevaag  *         is not set.
422*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
423*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
424*758e9fbaSOystein Eftevaag  *         was not successful.
425*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
426*758e9fbaSOystein Eftevaag  */
427*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_policyeval_cbauth(TPM2B_NAME * name,ESYS_TR * object_handle,ESYS_TR * auth_handle,ESYS_TR * authSession,void * userdata)428*758e9fbaSOystein Eftevaag ifapi_policyeval_cbauth(
429*758e9fbaSOystein Eftevaag     TPM2B_NAME *name,
430*758e9fbaSOystein Eftevaag     ESYS_TR *object_handle,
431*758e9fbaSOystein Eftevaag     ESYS_TR *auth_handle,
432*758e9fbaSOystein Eftevaag     ESYS_TR *authSession,
433*758e9fbaSOystein Eftevaag     void *userdata)
434*758e9fbaSOystein Eftevaag {
435*758e9fbaSOystein Eftevaag     TSS2_RC r;
436*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *fapi_ctx = userdata;
437*758e9fbaSOystein Eftevaag     IFAPI_POLICY_EXEC_CTX *current_policy;
438*758e9fbaSOystein Eftevaag     IFAPI_POLICY_EXEC_CB_CTX *cb_ctx;
439*758e9fbaSOystein Eftevaag     bool next_case;
440*758e9fbaSOystein Eftevaag 
441*758e9fbaSOystein Eftevaag     return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
442*758e9fbaSOystein Eftevaag     return_if_null(fapi_ctx->policy.policyutil_stack, "Policy not initialized.",
443*758e9fbaSOystein Eftevaag                    TSS2_FAPI_RC_BAD_REFERENCE);
444*758e9fbaSOystein Eftevaag 
445*758e9fbaSOystein Eftevaag     if (fapi_ctx->policy.util_current_policy) {
446*758e9fbaSOystein Eftevaag         /* Use the current policy in the policy stack. */
447*758e9fbaSOystein Eftevaag         current_policy = fapi_ctx->policy.util_current_policy->pol_exec_ctx;
448*758e9fbaSOystein Eftevaag     } else {
449*758e9fbaSOystein Eftevaag         /* Start with the bottom of the policy stack */
450*758e9fbaSOystein Eftevaag         current_policy = fapi_ctx->policy.policyutil_stack->pol_exec_ctx;
451*758e9fbaSOystein Eftevaag     }
452*758e9fbaSOystein Eftevaag     cb_ctx = current_policy->app_data;
453*758e9fbaSOystein Eftevaag 
454*758e9fbaSOystein Eftevaag     do {
455*758e9fbaSOystein Eftevaag         next_case = false;
456*758e9fbaSOystein Eftevaag         switch (cb_ctx->cb_state) {
457*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_EXECUTE_INIT);
458*758e9fbaSOystein Eftevaag             cb_ctx->auth_index = ESYS_TR_NONE;
459*758e9fbaSOystein Eftevaag             /* Search object with name in keystore. */
460*758e9fbaSOystein Eftevaag             r = ifapi_keystore_search_obj(&fapi_ctx->keystore, &fapi_ctx->io,
461*758e9fbaSOystein Eftevaag                                           name,
462*758e9fbaSOystein Eftevaag                                           &cb_ctx->object_path);
463*758e9fbaSOystein Eftevaag             FAPI_SYNC(r, "Search Object", cleanup);
464*758e9fbaSOystein Eftevaag 
465*758e9fbaSOystein Eftevaag             r = ifapi_keystore_load_async(&fapi_ctx->keystore, &fapi_ctx->io,
466*758e9fbaSOystein Eftevaag                                           cb_ctx->object_path);
467*758e9fbaSOystein Eftevaag             return_if_error2(r, "Could not open: %s", cb_ctx->object_path);
468*758e9fbaSOystein Eftevaag             SAFE_FREE(cb_ctx->object_path);
469*758e9fbaSOystein Eftevaag             fallthrough;
470*758e9fbaSOystein Eftevaag 
471*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_READ_OBJECT);
472*758e9fbaSOystein Eftevaag             /* Get object from file */
473*758e9fbaSOystein Eftevaag             r = ifapi_keystore_load_finish(&fapi_ctx->keystore, &fapi_ctx->io,
474*758e9fbaSOystein Eftevaag                                            &cb_ctx->object);
475*758e9fbaSOystein Eftevaag             return_try_again(r);
476*758e9fbaSOystein Eftevaag             return_if_error(r, "read_finish failed");
477*758e9fbaSOystein Eftevaag 
478*758e9fbaSOystein Eftevaag             r = ifapi_initialize_object(fapi_ctx->esys, &cb_ctx->object);
479*758e9fbaSOystein Eftevaag             goto_if_error(r, "Initialize NV object", cleanup);
480*758e9fbaSOystein Eftevaag 
481*758e9fbaSOystein Eftevaag             if (cb_ctx->object.objectType == IFAPI_NV_OBJ) {
482*758e9fbaSOystein Eftevaag                 /* NV Authorization */
483*758e9fbaSOystein Eftevaag 
484*758e9fbaSOystein Eftevaag                 cb_ctx->nv_index = cb_ctx->object.handle;
485*758e9fbaSOystein Eftevaag 
486*758e9fbaSOystein Eftevaag                 /* Determine the object used for authorization. */
487*758e9fbaSOystein Eftevaag                 get_nv_auth_object(&cb_ctx->object,
488*758e9fbaSOystein Eftevaag                                    cb_ctx->object.handle,
489*758e9fbaSOystein Eftevaag                                    &cb_ctx->auth_object,
490*758e9fbaSOystein Eftevaag                                    &cb_ctx->auth_index);
491*758e9fbaSOystein Eftevaag 
492*758e9fbaSOystein Eftevaag                 goto_if_error(r, "PolicySecret set authorization", cleanup);
493*758e9fbaSOystein Eftevaag                 cb_ctx->cb_state = POL_CB_AUTHORIZE_OBJECT;
494*758e9fbaSOystein Eftevaag 
495*758e9fbaSOystein Eftevaag                 cb_ctx->auth_object_ptr = &cb_ctx->auth_object;
496*758e9fbaSOystein Eftevaag                 next_case = true;
497*758e9fbaSOystein Eftevaag                 break;
498*758e9fbaSOystein Eftevaag             } else if (cb_ctx->object.objectType == IFAPI_HIERARCHY_OBJ) {
499*758e9fbaSOystein Eftevaag                 cb_ctx->cb_state = POL_CB_AUTHORIZE_OBJECT;
500*758e9fbaSOystein Eftevaag                 next_case = true;
501*758e9fbaSOystein Eftevaag                 break;
502*758e9fbaSOystein Eftevaag             } else {
503*758e9fbaSOystein Eftevaag                 cb_ctx->key_handle = cb_ctx->object.handle;
504*758e9fbaSOystein Eftevaag                 cb_ctx->cb_state = POL_CB_LOAD_KEY;
505*758e9fbaSOystein Eftevaag             }
506*758e9fbaSOystein Eftevaag             fallthrough;
507*758e9fbaSOystein Eftevaag 
508*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_LOAD_KEY);
509*758e9fbaSOystein Eftevaag             /* Key loading and authorization */
510*758e9fbaSOystein Eftevaag             r = ifapi_load_key(fapi_ctx, cb_ctx->object_path,
511*758e9fbaSOystein Eftevaag                                &cb_ctx->auth_object_ptr);
512*758e9fbaSOystein Eftevaag             FAPI_SYNC(r, "Fapi load key.", cleanup);
513*758e9fbaSOystein Eftevaag 
514*758e9fbaSOystein Eftevaag             cb_ctx->object = *cb_ctx->key_object_ptr;
515*758e9fbaSOystein Eftevaag             SAFE_FREE(cb_ctx->key_object_ptr);
516*758e9fbaSOystein Eftevaag             cb_ctx->auth_object_ptr = &cb_ctx->object;
517*758e9fbaSOystein Eftevaag             fallthrough;
518*758e9fbaSOystein Eftevaag 
519*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_AUTHORIZE_OBJECT);
520*758e9fbaSOystein Eftevaag             r = ifapi_authorize_object(fapi_ctx, cb_ctx->auth_object_ptr, authSession);
521*758e9fbaSOystein Eftevaag             return_try_again(r);
522*758e9fbaSOystein Eftevaag             goto_if_error(r, "Authorize  object.", cleanup);
523*758e9fbaSOystein Eftevaag 
524*758e9fbaSOystein Eftevaag             cb_ctx->cb_state = POL_CB_EXECUTE_INIT;
525*758e9fbaSOystein Eftevaag             break;
526*758e9fbaSOystein Eftevaag             /* FALLTHRU */
527*758e9fbaSOystein Eftevaag 
528*758e9fbaSOystein Eftevaag         statecasedefault(cb_ctx->cb_state);
529*758e9fbaSOystein Eftevaag         }
530*758e9fbaSOystein Eftevaag     } while (next_case);
531*758e9fbaSOystein Eftevaag     *object_handle = cb_ctx->object.handle;
532*758e9fbaSOystein Eftevaag     if (cb_ctx->object.objectType == IFAPI_NV_OBJ)
533*758e9fbaSOystein Eftevaag         *auth_handle = cb_ctx->auth_index;
534*758e9fbaSOystein Eftevaag     else
535*758e9fbaSOystein Eftevaag         *auth_handle = cb_ctx->object.handle;
536*758e9fbaSOystein Eftevaag 
537*758e9fbaSOystein Eftevaag     if (current_policy->policySessionSav != ESYS_TR_NONE)
538*758e9fbaSOystein Eftevaag         fapi_ctx->policy.session = current_policy->policySessionSav;
539*758e9fbaSOystein Eftevaag 
540*758e9fbaSOystein Eftevaag cleanup:
541*758e9fbaSOystein Eftevaag     ifapi_cleanup_ifapi_object(&cb_ctx->object);
542*758e9fbaSOystein Eftevaag     if (current_policy->policySessionSav
543*758e9fbaSOystein Eftevaag         && current_policy->policySessionSav != ESYS_TR_NONE)
544*758e9fbaSOystein Eftevaag         fapi_ctx->policy.session = current_policy->policySessionSav;
545*758e9fbaSOystein Eftevaag     return r;
546*758e9fbaSOystein Eftevaag }
547*758e9fbaSOystein Eftevaag 
548*758e9fbaSOystein Eftevaag /** Callback for branch selection of policy or.
549*758e9fbaSOystein Eftevaag  *
550*758e9fbaSOystein Eftevaag  * @param[in]  branches The list of policy branches.
551*758e9fbaSOystein Eftevaag  * @param[out] branch_idx The index of the selcted branch.
552*758e9fbaSOystein Eftevaag  * @param[in,out] userdata The Fapi context which will be used for keystore
553*758e9fbaSOystein Eftevaag  *                access, and storing the policy execution state.
554*758e9fbaSOystein Eftevaag  *                the io state.
555*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
556*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
557*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if no branch selection callback is
558*758e9fbaSOystein Eftevaag  *         defined. This callback will be needed of or policies which have to be
559*758e9fbaSOystein Eftevaag  *         executed.
560*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the computed branch index
561*758e9fbaSOystein Eftevaag  *         delivered by the callback does not identify a branch.
562*758e9fbaSOystein Eftevaag  */
563*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_branch_selection(TPML_POLICYBRANCHES * branches,size_t * branch_idx,void * userdata)564*758e9fbaSOystein Eftevaag ifapi_branch_selection(
565*758e9fbaSOystein Eftevaag     TPML_POLICYBRANCHES *branches,
566*758e9fbaSOystein Eftevaag     size_t *branch_idx,
567*758e9fbaSOystein Eftevaag     void *userdata)
568*758e9fbaSOystein Eftevaag {
569*758e9fbaSOystein Eftevaag     TSS2_RC r;
570*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *fapi_ctx = userdata;
571*758e9fbaSOystein Eftevaag     size_t i;
572*758e9fbaSOystein Eftevaag     const char *names[8];
573*758e9fbaSOystein Eftevaag 
574*758e9fbaSOystein Eftevaag     return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
575*758e9fbaSOystein Eftevaag 
576*758e9fbaSOystein Eftevaag     if (!fapi_ctx->callbacks.branch) {
577*758e9fbaSOystein Eftevaag         return_error(TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN,
578*758e9fbaSOystein Eftevaag                      "No branch selection callback");
579*758e9fbaSOystein Eftevaag     }
580*758e9fbaSOystein Eftevaag     for (i = 0; i < branches->count; i++)
581*758e9fbaSOystein Eftevaag         names[i] = branches->authorizations[i].name;
582*758e9fbaSOystein Eftevaag 
583*758e9fbaSOystein Eftevaag     r = fapi_ctx->callbacks.branch(fapi_ctx, "PolicyOR",
584*758e9fbaSOystein Eftevaag                                    &names[0],
585*758e9fbaSOystein Eftevaag                                    branches->count,
586*758e9fbaSOystein Eftevaag                                    branch_idx,
587*758e9fbaSOystein Eftevaag                                    fapi_ctx->callbacks.branchData);
588*758e9fbaSOystein Eftevaag     return_if_error(r, "policyBranchSelectionCallback");
589*758e9fbaSOystein Eftevaag 
590*758e9fbaSOystein Eftevaag     if (*branch_idx >= branches->count) {
591*758e9fbaSOystein Eftevaag         return_error2(TSS2_FAPI_RC_AUTHORIZATION_FAILED, "Invalid branch number.");
592*758e9fbaSOystein Eftevaag     }
593*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
594*758e9fbaSOystein Eftevaag }
595*758e9fbaSOystein Eftevaag 
596*758e9fbaSOystein Eftevaag /** Callback for policy action.
597*758e9fbaSOystein Eftevaag  *
598*758e9fbaSOystein Eftevaag  * @param[in] action The name of the policy action.
599*758e9fbaSOystein Eftevaag  * @param[in,out] userdata The Fapi context which will be used for keystore
600*758e9fbaSOystein Eftevaag  *                access, and storing the policy execution state.
601*758e9fbaSOystein Eftevaag  *                the io state.
602*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
603*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN If the callback for branch selection is
604*758e9fbaSOystein Eftevaag  *         not defined. This callback will be needed of or policies have to be
605*758e9fbaSOystein Eftevaag  *         executed.
606*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE If no user data is passed.
607*758e9fbaSOystein Eftevaag  */
608*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_policy_action(const char * action,void * userdata)609*758e9fbaSOystein Eftevaag ifapi_policy_action(
610*758e9fbaSOystein Eftevaag     const char *action,
611*758e9fbaSOystein Eftevaag     void *userdata)
612*758e9fbaSOystein Eftevaag {
613*758e9fbaSOystein Eftevaag     TSS2_RC r;
614*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *fapi_ctx = userdata;
615*758e9fbaSOystein Eftevaag     return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
616*758e9fbaSOystein Eftevaag 
617*758e9fbaSOystein Eftevaag     if (!fapi_ctx->callbacks.action) {
618*758e9fbaSOystein Eftevaag         return_error(TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN,
619*758e9fbaSOystein Eftevaag                      "No action callback");
620*758e9fbaSOystein Eftevaag     }
621*758e9fbaSOystein Eftevaag     r = fapi_ctx->callbacks.action(fapi_ctx, action,
622*758e9fbaSOystein Eftevaag                                    fapi_ctx->callbacks.actionData);
623*758e9fbaSOystein Eftevaag     return_if_error(r, "ifapi_policy_action callback");
624*758e9fbaSOystein Eftevaag 
625*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
626*758e9fbaSOystein Eftevaag }
627*758e9fbaSOystein Eftevaag 
628*758e9fbaSOystein Eftevaag /** Callback for signing a byte buffer.
629*758e9fbaSOystein Eftevaag  *
630*758e9fbaSOystein Eftevaag  * @param[in] key_pem The pem key used for signing operation.
631*758e9fbaSOystein Eftevaag  * @param[in] public_key_hint A human readable hint to denote which public
632*758e9fbaSOystein Eftevaag  *            key to use.
633*758e9fbaSOystein Eftevaag  * @param[in] key_pem_hash_alg The hash alg used for digest computation.
634*758e9fbaSOystein Eftevaag  * @param[in] buffer the byte array to be signed.
635*758e9fbaSOystein Eftevaag  * @param[in] buffer_size The size of the buffer to be signed.
636*758e9fbaSOystein Eftevaag  * @param[out] signature The signature in DER format.
637*758e9fbaSOystein Eftevaag  * @param[out] signature_size The size of the signature.
638*758e9fbaSOystein Eftevaag  * @param[in] userdata The user context to retrieve the signing function.
639*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
640*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN If the callback for signing is
641*758e9fbaSOystein Eftevaag  *         not defined.
642*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE If no user data is passed.
643*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the callback operation is not yet
644*758e9fbaSOystein Eftevaag  *         complete. Call this function again later.
645*758e9fbaSOystein Eftevaag  */
646*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_sign_buffer(char * key_pem,char * public_key_hint,TPMI_ALG_HASH key_pem_hash_alg,uint8_t * buffer,size_t buffer_size,uint8_t ** signature,size_t * signature_size,void * userdata)647*758e9fbaSOystein Eftevaag ifapi_sign_buffer(
648*758e9fbaSOystein Eftevaag     char *key_pem,
649*758e9fbaSOystein Eftevaag     char *public_key_hint,
650*758e9fbaSOystein Eftevaag     TPMI_ALG_HASH key_pem_hash_alg,
651*758e9fbaSOystein Eftevaag     uint8_t *buffer,
652*758e9fbaSOystein Eftevaag     size_t buffer_size,
653*758e9fbaSOystein Eftevaag     uint8_t **signature,
654*758e9fbaSOystein Eftevaag     size_t *signature_size,
655*758e9fbaSOystein Eftevaag     void *userdata)
656*758e9fbaSOystein Eftevaag {
657*758e9fbaSOystein Eftevaag     TSS2_RC r;
658*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *fapi_ctx = userdata;
659*758e9fbaSOystein Eftevaag 
660*758e9fbaSOystein Eftevaag     return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
661*758e9fbaSOystein Eftevaag 
662*758e9fbaSOystein Eftevaag     if (!fapi_ctx->callbacks.sign) {
663*758e9fbaSOystein Eftevaag         return_error2(TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN,
664*758e9fbaSOystein Eftevaag                       "No signature callback.");
665*758e9fbaSOystein Eftevaag     }
666*758e9fbaSOystein Eftevaag     r = fapi_ctx->callbacks.sign(fapi_ctx, "PolicySigned", key_pem,
667*758e9fbaSOystein Eftevaag                                  public_key_hint ? public_key_hint : "",
668*758e9fbaSOystein Eftevaag                                  key_pem_hash_alg,
669*758e9fbaSOystein Eftevaag                                  buffer, buffer_size,
670*758e9fbaSOystein Eftevaag                                  signature, signature_size,
671*758e9fbaSOystein Eftevaag                                  fapi_ctx->callbacks.signData);
672*758e9fbaSOystein Eftevaag     try_again_or_error(r, "Execute policy signature callback.");
673*758e9fbaSOystein Eftevaag 
674*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
675*758e9fbaSOystein Eftevaag }
676*758e9fbaSOystein Eftevaag 
677*758e9fbaSOystein Eftevaag /**  Check whether public data of key is assigned to policy.
678*758e9fbaSOystein Eftevaag  *
679*758e9fbaSOystein Eftevaag  * It will be checked whether policy was authorized by abort key with public
680*758e9fbaSOystein Eftevaag  * data of type TPMT_PUBLIC.
681*758e9fbaSOystein Eftevaag  *
682*758e9fbaSOystein Eftevaag  * @param[in] policy The policy to be checked.
683*758e9fbaSOystein Eftevaag  * @param[in] publicVoid The public information of the key.
684*758e9fbaSOystein Eftevaag  * @param[in] nameAlgVoid Not used for this compare function.
685*758e9fbaSOystein Eftevaag  * @param[out] equal Switch whether check was successful.
686*758e9fbaSOystein Eftevaag  */
687*758e9fbaSOystein Eftevaag static TSS2_RC
equal_policy_authorization(TPMS_POLICY * policy,void * publicVoid,void * nameAlgVoid,bool * equal)688*758e9fbaSOystein Eftevaag equal_policy_authorization(
689*758e9fbaSOystein Eftevaag     TPMS_POLICY *policy,
690*758e9fbaSOystein Eftevaag     void *publicVoid,
691*758e9fbaSOystein Eftevaag     void *nameAlgVoid,
692*758e9fbaSOystein Eftevaag     bool *equal)
693*758e9fbaSOystein Eftevaag {
694*758e9fbaSOystein Eftevaag     TPMT_PUBLIC *public = publicVoid;
695*758e9fbaSOystein Eftevaag     (void)nameAlgVoid;
696*758e9fbaSOystein Eftevaag     size_t i;
697*758e9fbaSOystein Eftevaag     TPML_POLICYAUTHORIZATIONS *authorizations = policy->policyAuthorizations;
698*758e9fbaSOystein Eftevaag 
699*758e9fbaSOystein Eftevaag     *equal = false;
700*758e9fbaSOystein Eftevaag     if (authorizations) {
701*758e9fbaSOystein Eftevaag         for (i = 0; i < authorizations->count; i++) {
702*758e9fbaSOystein Eftevaag             if (ifapi_TPMT_PUBLIC_cmp
703*758e9fbaSOystein Eftevaag                 (public, &authorizations->authorizations[i].key)) {
704*758e9fbaSOystein Eftevaag                 *equal = true;
705*758e9fbaSOystein Eftevaag                 return TSS2_RC_SUCCESS;
706*758e9fbaSOystein Eftevaag             }
707*758e9fbaSOystein Eftevaag         }
708*758e9fbaSOystein Eftevaag     }
709*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
710*758e9fbaSOystein Eftevaag }
711*758e9fbaSOystein Eftevaag 
712*758e9fbaSOystein Eftevaag /** Check whether policy digest can be found in policy.
713*758e9fbaSOystein Eftevaag  *
714*758e9fbaSOystein Eftevaag  * It will be tested whether the policy has been instatiated with the
715*758e9fbaSOystein Eftevaag  * passed digest.
716*758e9fbaSOystein Eftevaag  *
717*758e9fbaSOystein Eftevaag  * @param[in] policy The policy to be checked.
718*758e9fbaSOystein Eftevaag  * @param[in] authPolicyVoid The digest to be searched.
719*758e9fbaSOystein Eftevaag  * @param[in] nameAlgVoid The hash algorithm used for the digest computation.
720*758e9fbaSOystein Eftevaag  * @param[out] equal Switch whether check was successful.
721*758e9fbaSOystein Eftevaag  */
722*758e9fbaSOystein Eftevaag static TSS2_RC
compare_policy_digest(TPMS_POLICY * policy,void * authPolicyVoid,void * nameAlgVoid,bool * equal)723*758e9fbaSOystein Eftevaag compare_policy_digest(
724*758e9fbaSOystein Eftevaag     TPMS_POLICY *policy,
725*758e9fbaSOystein Eftevaag     void *authPolicyVoid,
726*758e9fbaSOystein Eftevaag     void *nameAlgVoid,
727*758e9fbaSOystein Eftevaag     bool *equal)
728*758e9fbaSOystein Eftevaag {
729*758e9fbaSOystein Eftevaag     TPM2B_DIGEST *authPolicy = authPolicyVoid;
730*758e9fbaSOystein Eftevaag     TPMI_ALG_HASH *hash_alg_ptr = nameAlgVoid;
731*758e9fbaSOystein Eftevaag     TPMI_ALG_HASH hash_alg = *hash_alg_ptr;
732*758e9fbaSOystein Eftevaag     size_t i;
733*758e9fbaSOystein Eftevaag     TPML_DIGEST_VALUES *digest_values;
734*758e9fbaSOystein Eftevaag 
735*758e9fbaSOystein Eftevaag     *equal = false;
736*758e9fbaSOystein Eftevaag 
737*758e9fbaSOystein Eftevaag     digest_values = &policy->policyDigests;
738*758e9fbaSOystein Eftevaag 
739*758e9fbaSOystein Eftevaag     if (digest_values) {
740*758e9fbaSOystein Eftevaag         for (i = 0; i < digest_values->count; i++) {
741*758e9fbaSOystein Eftevaag             if (digest_values->digests[i].hashAlg == hash_alg) {
742*758e9fbaSOystein Eftevaag                 if (memcmp(&digest_values->digests[i].digest,
743*758e9fbaSOystein Eftevaag                            &authPolicy->buffer[0],
744*758e9fbaSOystein Eftevaag                            authPolicy->size))
745*758e9fbaSOystein Eftevaag                     continue;
746*758e9fbaSOystein Eftevaag                 *equal = true;
747*758e9fbaSOystein Eftevaag                 return TSS2_RC_SUCCESS;
748*758e9fbaSOystein Eftevaag             }
749*758e9fbaSOystein Eftevaag         }
750*758e9fbaSOystein Eftevaag     }
751*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
752*758e9fbaSOystein Eftevaag }
753*758e9fbaSOystein Eftevaag 
754*758e9fbaSOystein Eftevaag /** Search a policy file which fulfills a certain predicate.
755*758e9fbaSOystein Eftevaag  *
756*758e9fbaSOystein Eftevaag  * @param[in] context The context for storing the state information of the search
757*758e9fbaSOystein Eftevaag               process and the keystore paths.
758*758e9fbaSOystein Eftevaag  * @param[in] compare The function which will be used for comparison.
759*758e9fbaSOystein Eftevaag  * @param[in] all_objects Switch which determines wheter all policies fulfilling the
760*758e9fbaSOystein Eftevaag  *            the condition will be returned or only the first policy.
761*758e9fbaSOystein Eftevaag  * @param[in] object1 The first object used for comparison.
762*758e9fbaSOystein Eftevaag  * @param[in] object2 The second object used for comparison.
763*758e9fbaSOystein Eftevaag  * @param[out] policy_found The linked list with the policies fulfilling the condition.
764*758e9fbaSOystein Eftevaag  *
765*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
766*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
767*758e9fbaSOystein Eftevaag  *         was not successful.
768*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
769*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
770*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
771*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
772*758e9fbaSOystein Eftevaag  *         the function.
773*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
774*758e9fbaSOystein Eftevaag  *         object store.
775*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
776*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
777*758e9fbaSOystein Eftevaag  */
778*758e9fbaSOystein Eftevaag static TSS2_RC
search_policy(FAPI_CONTEXT * context,Policy_Compare_Object compare,bool all_objects,void * object1,void * object2,struct POLICY_LIST ** policy_found)779*758e9fbaSOystein Eftevaag search_policy(
780*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *context,
781*758e9fbaSOystein Eftevaag     Policy_Compare_Object compare,
782*758e9fbaSOystein Eftevaag     bool all_objects,
783*758e9fbaSOystein Eftevaag     void *object1,
784*758e9fbaSOystein Eftevaag     void *object2,
785*758e9fbaSOystein Eftevaag     struct POLICY_LIST **policy_found)
786*758e9fbaSOystein Eftevaag {
787*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
788*758e9fbaSOystein Eftevaag     char *path;
789*758e9fbaSOystein Eftevaag     TPMS_POLICY policy = { 0 };
790*758e9fbaSOystein Eftevaag     bool found;
791*758e9fbaSOystein Eftevaag     struct POLICY_LIST *policy_object = NULL;
792*758e9fbaSOystein Eftevaag     struct POLICY_LIST *second;
793*758e9fbaSOystein Eftevaag 
794*758e9fbaSOystein Eftevaag     switch (context->fsearch.state) {
795*758e9fbaSOystein Eftevaag     case FSEARCH_INIT:
796*758e9fbaSOystein Eftevaag         LOG_DEBUG("** STATE ** FSEARCH_INIT");
797*758e9fbaSOystein Eftevaag         memset(&context->fsearch, 0, sizeof(IFAPI_FILE_SEARCH_CTX));
798*758e9fbaSOystein Eftevaag         /* Get the list of all files. */
799*758e9fbaSOystein Eftevaag         r = ifapi_keystore_list_all(&context->keystore, IFAPI_POLICY_DIR, &context->fsearch.pathlist,
800*758e9fbaSOystein Eftevaag                                     &context->fsearch.numPaths);
801*758e9fbaSOystein Eftevaag         return_if_error(r, "get entities.");
802*758e9fbaSOystein Eftevaag         context->fsearch.path_idx = context->fsearch.numPaths;
803*758e9fbaSOystein Eftevaag 
804*758e9fbaSOystein Eftevaag         context->fsearch.state = FSEARCH_OBJECT;
805*758e9fbaSOystein Eftevaag     /* FALLTHRU */
806*758e9fbaSOystein Eftevaag 
807*758e9fbaSOystein Eftevaag     case FSEARCH_OBJECT:
808*758e9fbaSOystein Eftevaag         LOG_DEBUG("** STATE ** FSEARCH_OBJECT");
809*758e9fbaSOystein Eftevaag 
810*758e9fbaSOystein Eftevaag         /* Test whether all files have been checked. */
811*758e9fbaSOystein Eftevaag         if (context->fsearch.path_idx == 0) {
812*758e9fbaSOystein Eftevaag             if (*policy_found) {
813*758e9fbaSOystein Eftevaag                 context->fsearch.state = FSEARCH_INIT;
814*758e9fbaSOystein Eftevaag                 for (size_t i = 0; i < context->fsearch.numPaths; i++) {
815*758e9fbaSOystein Eftevaag                     SAFE_FREE(context->fsearch.pathlist[i]);
816*758e9fbaSOystein Eftevaag                 }
817*758e9fbaSOystein Eftevaag                 SAFE_FREE(context->fsearch.pathlist);
818*758e9fbaSOystein Eftevaag                 return TSS2_RC_SUCCESS;
819*758e9fbaSOystein Eftevaag             }
820*758e9fbaSOystein Eftevaag             goto_error(r, TSS2_FAPI_RC_POLICY_UNKNOWN, "Policy not found.", cleanup);
821*758e9fbaSOystein Eftevaag         }
822*758e9fbaSOystein Eftevaag         context->fsearch.path_idx -= 1;
823*758e9fbaSOystein Eftevaag         path = context->fsearch.pathlist[context->fsearch.path_idx];
824*758e9fbaSOystein Eftevaag         context->fsearch.current_path = path;
825*758e9fbaSOystein Eftevaag         LOG_DEBUG("Check file: %s %zu", path, context->fsearch.path_idx);
826*758e9fbaSOystein Eftevaag 
827*758e9fbaSOystein Eftevaag         /* Prepare policy loading. */
828*758e9fbaSOystein Eftevaag         r = ifapi_policy_store_load_async(&context->pstore, &context->io, path);
829*758e9fbaSOystein Eftevaag         goto_if_error2(r, "Can't open: %s", cleanup, path);
830*758e9fbaSOystein Eftevaag 
831*758e9fbaSOystein Eftevaag         context->fsearch.state = FSEARCH_READ;
832*758e9fbaSOystein Eftevaag     /* FALLTHRU */
833*758e9fbaSOystein Eftevaag 
834*758e9fbaSOystein Eftevaag     case FSEARCH_READ:
835*758e9fbaSOystein Eftevaag         LOG_DEBUG("** STATE ** FSEARCH_READ");
836*758e9fbaSOystein Eftevaag         /* Finalize policy loading if possible. */
837*758e9fbaSOystein Eftevaag         r = ifapi_policy_store_load_finish(&context->pstore, &context->io, &policy);
838*758e9fbaSOystein Eftevaag         return_try_again(r);
839*758e9fbaSOystein Eftevaag         goto_if_error(r, "read_finish failed", cleanup);
840*758e9fbaSOystein Eftevaag 
841*758e9fbaSOystein Eftevaag         /* Call the passed compare function. */
842*758e9fbaSOystein Eftevaag         r = compare(&policy, object1, object2, &found);
843*758e9fbaSOystein Eftevaag         if (found) {
844*758e9fbaSOystein Eftevaag             LOG_DEBUG("compare true  %s",
845*758e9fbaSOystein Eftevaag                       context->fsearch.pathlist[context->fsearch.path_idx]);
846*758e9fbaSOystein Eftevaag         } else {
847*758e9fbaSOystein Eftevaag             LOG_DEBUG("compare false  %s",
848*758e9fbaSOystein Eftevaag                       context->fsearch.pathlist[context->fsearch.path_idx]);
849*758e9fbaSOystein Eftevaag         }
850*758e9fbaSOystein Eftevaag         goto_if_error(r, "Invalid cipher object.", cleanup);
851*758e9fbaSOystein Eftevaag 
852*758e9fbaSOystein Eftevaag         if (!found) {
853*758e9fbaSOystein Eftevaag             if (!all_objects && context->fsearch.path_idx == 0) {
854*758e9fbaSOystein Eftevaag                 /* All files checked, but no policy found. */
855*758e9fbaSOystein Eftevaag                 context->fsearch.state = FSEARCH_INIT;
856*758e9fbaSOystein Eftevaag                 ifapi_cleanup_policy(&policy);
857*758e9fbaSOystein Eftevaag                 return TSS2_BASE_RC_POLICY_UNKNOWN;
858*758e9fbaSOystein Eftevaag             } else {
859*758e9fbaSOystein Eftevaag                 /* Continue search. */
860*758e9fbaSOystein Eftevaag                 context->fsearch.state = FSEARCH_OBJECT;
861*758e9fbaSOystein Eftevaag                 ifapi_cleanup_policy(&policy);
862*758e9fbaSOystein Eftevaag                 return TSS2_FAPI_RC_TRY_AGAIN;
863*758e9fbaSOystein Eftevaag             }
864*758e9fbaSOystein Eftevaag         }
865*758e9fbaSOystein Eftevaag         /* Extend linked list.*/
866*758e9fbaSOystein Eftevaag         policy_object = calloc(sizeof(struct POLICY_LIST), 1);
867*758e9fbaSOystein Eftevaag         return_if_null(policy_object, "Out of memory.", TSS2_FAPI_RC_MEMORY);
868*758e9fbaSOystein Eftevaag 
869*758e9fbaSOystein Eftevaag         strdup_check(policy_object->path, context->fsearch.current_path, r, cleanup);
870*758e9fbaSOystein Eftevaag         policy_object->policy = policy;
871*758e9fbaSOystein Eftevaag         if (*policy_found != NULL) {
872*758e9fbaSOystein Eftevaag             second = *policy_found;
873*758e9fbaSOystein Eftevaag             policy_object->next = second;
874*758e9fbaSOystein Eftevaag         }
875*758e9fbaSOystein Eftevaag         *policy_found = policy_object;
876*758e9fbaSOystein Eftevaag 
877*758e9fbaSOystein Eftevaag         if (context->fsearch.path_idx == 0) {
878*758e9fbaSOystein Eftevaag             context->fsearch.state = FSEARCH_INIT;
879*758e9fbaSOystein Eftevaag             /* Cleanup list of all paths. */
880*758e9fbaSOystein Eftevaag             for (size_t i = 0; i < context->fsearch.numPaths; i++) {
881*758e9fbaSOystein Eftevaag                 SAFE_FREE(context->fsearch.pathlist[i]);
882*758e9fbaSOystein Eftevaag             }
883*758e9fbaSOystein Eftevaag             SAFE_FREE(context->fsearch.pathlist);
884*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
885*758e9fbaSOystein Eftevaag         }
886*758e9fbaSOystein Eftevaag 
887*758e9fbaSOystein Eftevaag         if (all_objects) {
888*758e9fbaSOystein Eftevaag             context->fsearch.state = FSEARCH_OBJECT;
889*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_TRY_AGAIN;
890*758e9fbaSOystein Eftevaag         }
891*758e9fbaSOystein Eftevaag 
892*758e9fbaSOystein Eftevaag         break;
893*758e9fbaSOystein Eftevaag 
894*758e9fbaSOystein Eftevaag     default:
895*758e9fbaSOystein Eftevaag         context->state = _FAPI_STATE_INTERNALERROR;
896*758e9fbaSOystein Eftevaag         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid state for load key.", cleanup);
897*758e9fbaSOystein Eftevaag     }
898*758e9fbaSOystein Eftevaag     context->fsearch.state = FSEARCH_INIT;
899*758e9fbaSOystein Eftevaag     for (size_t i = 0; i < context->fsearch.numPaths; i++) {
900*758e9fbaSOystein Eftevaag         SAFE_FREE(context->fsearch.pathlist[i]);
901*758e9fbaSOystein Eftevaag     }
902*758e9fbaSOystein Eftevaag     SAFE_FREE(context->fsearch.pathlist);
903*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
904*758e9fbaSOystein Eftevaag cleanup:
905*758e9fbaSOystein Eftevaag     SAFE_FREE(policy_object);
906*758e9fbaSOystein Eftevaag     ifapi_cleanup_policy(&policy);
907*758e9fbaSOystein Eftevaag     for (size_t i = 0; i < context->fsearch.numPaths; i++) {
908*758e9fbaSOystein Eftevaag         SAFE_FREE(context->fsearch.pathlist[i]);
909*758e9fbaSOystein Eftevaag     }
910*758e9fbaSOystein Eftevaag     SAFE_FREE(context->fsearch.pathlist);
911*758e9fbaSOystein Eftevaag     context->fsearch.state = FSEARCH_INIT;
912*758e9fbaSOystein Eftevaag     return r;
913*758e9fbaSOystein Eftevaag }
914*758e9fbaSOystein Eftevaag 
915*758e9fbaSOystein Eftevaag /** Get policy digest for a certain hash alg.
916*758e9fbaSOystein Eftevaag  *
917*758e9fbaSOystein Eftevaag  * @param[in]  policy The policy with the digest list.
918*758e9fbaSOystein Eftevaag  * @param[in]  hashAlg The hash algorithm used for the digest computation.
919*758e9fbaSOystein Eftevaag  * @param[out] digest The digest matching hashAlg.
920*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
921*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
922*758e9fbaSOystein Eftevaag  *         the function.
923*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
924*758e9fbaSOystein Eftevaag  */
925*758e9fbaSOystein Eftevaag static TSS2_RC
get_policy_digest(TPMS_POLICY * policy,TPMI_ALG_HASH hashAlg,TPM2B_DIGEST * digest)926*758e9fbaSOystein Eftevaag get_policy_digest(TPMS_POLICY *policy,
927*758e9fbaSOystein Eftevaag                   TPMI_ALG_HASH hashAlg,
928*758e9fbaSOystein Eftevaag                   TPM2B_DIGEST *digest)
929*758e9fbaSOystein Eftevaag {
930*758e9fbaSOystein Eftevaag     size_t i;
931*758e9fbaSOystein Eftevaag 
932*758e9fbaSOystein Eftevaag     if (!(digest->size = ifapi_hash_get_digest_size(hashAlg))) {
933*758e9fbaSOystein Eftevaag         return_error2(TSS2_FAPI_RC_BAD_VALUE,
934*758e9fbaSOystein Eftevaag                       "Unsupported hash algorithm (%" PRIu16 ")", hashAlg);
935*758e9fbaSOystein Eftevaag     }
936*758e9fbaSOystein Eftevaag 
937*758e9fbaSOystein Eftevaag     for (i = 0; i < policy->policyDigests.count; i++) {
938*758e9fbaSOystein Eftevaag         if (policy->policyDigests.digests[i].hashAlg == hashAlg) {
939*758e9fbaSOystein Eftevaag             memcpy(&digest->buffer[0],
940*758e9fbaSOystein Eftevaag                    &policy->policyDigests.digests[i].digest, digest->size);
941*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
942*758e9fbaSOystein Eftevaag         }
943*758e9fbaSOystein Eftevaag     }
944*758e9fbaSOystein Eftevaag     return TSS2_FAPI_RC_GENERAL_FAILURE;
945*758e9fbaSOystein Eftevaag }
946*758e9fbaSOystein Eftevaag 
947*758e9fbaSOystein Eftevaag /** Get policy authorization for a certain public key
948*758e9fbaSOystein Eftevaag  *
949*758e9fbaSOystein Eftevaag  * @param[in]  policy The policy with the authorization.
950*758e9fbaSOystein Eftevaag  * @param[in]  public The public data of the key.
951*758e9fbaSOystein Eftevaag  * @param[out] signature The signature found in the authorization list.
952*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
953*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
954*758e9fbaSOystein Eftevaag  */
955*758e9fbaSOystein Eftevaag static TSS2_RC
get_policy_signature(TPMS_POLICY * policy,TPMT_PUBLIC * public,TPMT_SIGNATURE * signature)956*758e9fbaSOystein Eftevaag get_policy_signature(
957*758e9fbaSOystein Eftevaag     TPMS_POLICY *policy,
958*758e9fbaSOystein Eftevaag     TPMT_PUBLIC *public,
959*758e9fbaSOystein Eftevaag     TPMT_SIGNATURE *signature)
960*758e9fbaSOystein Eftevaag {
961*758e9fbaSOystein Eftevaag     size_t i;
962*758e9fbaSOystein Eftevaag 
963*758e9fbaSOystein Eftevaag     for (i = 0; i < policy->policyAuthorizations->count; i++) {
964*758e9fbaSOystein Eftevaag         if (ifapi_TPMT_PUBLIC_cmp(public,
965*758e9fbaSOystein Eftevaag                                   &policy->policyAuthorizations->authorizations[i].key)) {
966*758e9fbaSOystein Eftevaag             *signature = policy->policyAuthorizations->authorizations[i].signature;
967*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
968*758e9fbaSOystein Eftevaag         }
969*758e9fbaSOystein Eftevaag     }
970*758e9fbaSOystein Eftevaag     /* Appropriate authorization should always exist */
971*758e9fbaSOystein Eftevaag     return TSS2_FAPI_RC_GENERAL_FAILURE;
972*758e9fbaSOystein Eftevaag }
973*758e9fbaSOystein Eftevaag 
974*758e9fbaSOystein Eftevaag /** Cleanup a linked list of policies.
975*758e9fbaSOystein Eftevaag  *
976*758e9fbaSOystein Eftevaag  * @param[in] The linked list.
977*758e9fbaSOystein Eftevaag  */
978*758e9fbaSOystein Eftevaag static void
cleanup_policy_list(struct POLICY_LIST * list)979*758e9fbaSOystein Eftevaag cleanup_policy_list(struct POLICY_LIST * list) {
980*758e9fbaSOystein Eftevaag     if (list) {
981*758e9fbaSOystein Eftevaag         struct POLICY_LIST * branch = list;
982*758e9fbaSOystein Eftevaag         while (branch) {
983*758e9fbaSOystein Eftevaag             struct POLICY_LIST *next = branch->next;
984*758e9fbaSOystein Eftevaag             /* Cleanup the policy stored in the list. */
985*758e9fbaSOystein Eftevaag             ifapi_cleanup_policy(&branch->policy);
986*758e9fbaSOystein Eftevaag             SAFE_FREE(branch->path);
987*758e9fbaSOystein Eftevaag             SAFE_FREE(branch);
988*758e9fbaSOystein Eftevaag             branch = next;
989*758e9fbaSOystein Eftevaag         }
990*758e9fbaSOystein Eftevaag     }
991*758e9fbaSOystein Eftevaag }
992*758e9fbaSOystein Eftevaag 
993*758e9fbaSOystein Eftevaag /** Callback for retrieving, selecting and execute a authorized policy.
994*758e9fbaSOystein Eftevaag  *
995*758e9fbaSOystein Eftevaag  * All policies authorized by a certain key will be retrieved and one policy
996*758e9fbaSOystein Eftevaag  * will be selected via a branch selection callback.
997*758e9fbaSOystein Eftevaag  *
998*758e9fbaSOystein Eftevaag  * @param[in] key_public the public data of the key which was used for policy
999*758e9fbaSOystein Eftevaag  *            authorization.
1000*758e9fbaSOystein Eftevaag  * @param[in] hash_alg The hash algorithm used for policy computation.
1001*758e9fbaSOystein Eftevaag  * @param[out] digest The policy digest of the authorized policy.
1002*758e9fbaSOystein Eftevaag  * @param[out] signature The signature produced during policy authorization.
1003*758e9fbaSOystein Eftevaag  * @param[in] userdata The user context to retrieve the policy.
1004*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1005*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if it's not possible to allocate enough memory.
1006*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE If no user data id passed or context stack
1007*758e9fbaSOystein Eftevaag  *         is not initialized.
1008*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
1009*758e9fbaSOystein Eftevaag  *         store.
1010*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy for a certain path was not found.
1011*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest
1012*758e9fbaSOystein Eftevaag  *         was not successful.
1013*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for policy
1014*758e9fbaSOystein Eftevaag  *         execution fails.
1015*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
1016*758e9fbaSOystein Eftevaag  *         is not set.
1017*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1018*758e9fbaSOystein Eftevaag  *         the function.
1019*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1020*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1021*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
1022*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1023*758e9fbaSOystein Eftevaag  *         operation already pending.
1024*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1025*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1026*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1027*758e9fbaSOystein Eftevaag  */
1028*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_exec_auth_policy(TPMT_PUBLIC * key_public,TPMI_ALG_HASH hash_alg,TPM2B_DIGEST * digest,TPMT_SIGNATURE * signature,void * userdata)1029*758e9fbaSOystein Eftevaag ifapi_exec_auth_policy(
1030*758e9fbaSOystein Eftevaag     TPMT_PUBLIC *key_public,
1031*758e9fbaSOystein Eftevaag     TPMI_ALG_HASH hash_alg,
1032*758e9fbaSOystein Eftevaag     TPM2B_DIGEST *digest,
1033*758e9fbaSOystein Eftevaag     TPMT_SIGNATURE *signature,
1034*758e9fbaSOystein Eftevaag     void *userdata)
1035*758e9fbaSOystein Eftevaag {
1036*758e9fbaSOystein Eftevaag     TSS2_RC r;
1037*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *fapi_ctx = userdata;
1038*758e9fbaSOystein Eftevaag     IFAPI_POLICY_EXEC_CTX *current_policy;
1039*758e9fbaSOystein Eftevaag     IFAPI_POLICY_EXEC_CB_CTX *cb_ctx;
1040*758e9fbaSOystein Eftevaag     size_t n, i;
1041*758e9fbaSOystein Eftevaag     struct POLICY_LIST *branch;
1042*758e9fbaSOystein Eftevaag     const char **names = NULL;
1043*758e9fbaSOystein Eftevaag     size_t branch_idx;
1044*758e9fbaSOystein Eftevaag     bool policy_set = false;
1045*758e9fbaSOystein Eftevaag 
1046*758e9fbaSOystein Eftevaag     return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
1047*758e9fbaSOystein Eftevaag     return_if_null(fapi_ctx->policy.policyutil_stack, "Policy not initialized.",
1048*758e9fbaSOystein Eftevaag                    TSS2_FAPI_RC_BAD_REFERENCE);
1049*758e9fbaSOystein Eftevaag 
1050*758e9fbaSOystein Eftevaag     if (fapi_ctx->policy.util_current_policy) {
1051*758e9fbaSOystein Eftevaag         /* Use the current policy in the policy stack. */
1052*758e9fbaSOystein Eftevaag         current_policy = fapi_ctx->policy.util_current_policy->pol_exec_ctx;
1053*758e9fbaSOystein Eftevaag     } else {
1054*758e9fbaSOystein Eftevaag         /* Start with the bottom of the policy stack */
1055*758e9fbaSOystein Eftevaag         current_policy = fapi_ctx->policy.policyutil_stack->pol_exec_ctx;
1056*758e9fbaSOystein Eftevaag     }
1057*758e9fbaSOystein Eftevaag     cb_ctx = current_policy->app_data;
1058*758e9fbaSOystein Eftevaag 
1059*758e9fbaSOystein Eftevaag     switch (cb_ctx->cb_state) {
1060*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_EXECUTE_INIT)
1061*758e9fbaSOystein Eftevaag             current_policy->object_handle = ESYS_TR_NONE;
1062*758e9fbaSOystein Eftevaag             current_policy->policy_list = NULL;
1063*758e9fbaSOystein Eftevaag             fallthrough;
1064*758e9fbaSOystein Eftevaag 
1065*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_SEARCH_POLICY)
1066*758e9fbaSOystein Eftevaag             r = search_policy(fapi_ctx,
1067*758e9fbaSOystein Eftevaag                               equal_policy_authorization, true,
1068*758e9fbaSOystein Eftevaag                               key_public, NULL,
1069*758e9fbaSOystein Eftevaag                               &current_policy->policy_list);
1070*758e9fbaSOystein Eftevaag             FAPI_SYNC(r, "Search policy", cleanup);
1071*758e9fbaSOystein Eftevaag 
1072*758e9fbaSOystein Eftevaag             if (current_policy->policy_list->next) {
1073*758e9fbaSOystein Eftevaag                 /* More than one policy has to be selected via
1074*758e9fbaSOystein Eftevaag                    callback */
1075*758e9fbaSOystein Eftevaag                 if (!fapi_ctx->callbacks.branch) {
1076*758e9fbaSOystein Eftevaag                     return_error(TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN,
1077*758e9fbaSOystein Eftevaag                                  "No branch selection callback");
1078*758e9fbaSOystein Eftevaag                 }
1079*758e9fbaSOystein Eftevaag                 n = 1;
1080*758e9fbaSOystein Eftevaag 
1081*758e9fbaSOystein Eftevaag                 /* Count policies */
1082*758e9fbaSOystein Eftevaag                 for (branch = current_policy->policy_list; branch->next;
1083*758e9fbaSOystein Eftevaag                      branch = branch->next)
1084*758e9fbaSOystein Eftevaag                     n += 1;
1085*758e9fbaSOystein Eftevaag                 names = malloc(sizeof(char *) * n);
1086*758e9fbaSOystein Eftevaag                 return_if_null(names, "Out of memory.", TSS2_FAPI_RC_MEMORY);
1087*758e9fbaSOystein Eftevaag                 i = 0;
1088*758e9fbaSOystein Eftevaag                 branch = current_policy->policy_list;
1089*758e9fbaSOystein Eftevaag                 /* Compute name list for slectiion callback. */
1090*758e9fbaSOystein Eftevaag                 do {
1091*758e9fbaSOystein Eftevaag                     names[i] = branch->path;
1092*758e9fbaSOystein Eftevaag                     i += 1;
1093*758e9fbaSOystein Eftevaag                     branch = branch->next;
1094*758e9fbaSOystein Eftevaag                 } while (branch);
1095*758e9fbaSOystein Eftevaag 
1096*758e9fbaSOystein Eftevaag                 /* Policy selection */
1097*758e9fbaSOystein Eftevaag                 r = fapi_ctx->callbacks.branch(fapi_ctx, "PolicyAuthorize",
1098*758e9fbaSOystein Eftevaag                                                &names[0], n, &branch_idx,
1099*758e9fbaSOystein Eftevaag                                                fapi_ctx->callbacks.branchData);
1100*758e9fbaSOystein Eftevaag                 goto_if_error(r, "policyBranchSelectionCallback", cleanup);
1101*758e9fbaSOystein Eftevaag 
1102*758e9fbaSOystein Eftevaag                 if (branch_idx >= n) {
1103*758e9fbaSOystein Eftevaag                     goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid branch number.",
1104*758e9fbaSOystein Eftevaag                                cleanup);
1105*758e9fbaSOystein Eftevaag                 }
1106*758e9fbaSOystein Eftevaag                 /* Get policy from policy list */
1107*758e9fbaSOystein Eftevaag                 n = 0;
1108*758e9fbaSOystein Eftevaag                 branch = current_policy->policy_list;
1109*758e9fbaSOystein Eftevaag                 do {
1110*758e9fbaSOystein Eftevaag                     if (n == branch_idx) {
1111*758e9fbaSOystein Eftevaag                         cb_ctx->policy = &branch->policy;
1112*758e9fbaSOystein Eftevaag                         policy_set = true;
1113*758e9fbaSOystein Eftevaag                         break;
1114*758e9fbaSOystein Eftevaag                     }
1115*758e9fbaSOystein Eftevaag                     n += 1;
1116*758e9fbaSOystein Eftevaag                     branch = branch->next;
1117*758e9fbaSOystein Eftevaag                 }  while (branch);
1118*758e9fbaSOystein Eftevaag 
1119*758e9fbaSOystein Eftevaag             } else {
1120*758e9fbaSOystein Eftevaag                 /* Only one policy found. */
1121*758e9fbaSOystein Eftevaag                 cb_ctx->policy = &current_policy->policy_list->policy;
1122*758e9fbaSOystein Eftevaag                 policy_set = true;
1123*758e9fbaSOystein Eftevaag             }
1124*758e9fbaSOystein Eftevaag             if (!policy_set) {
1125*758e9fbaSOystein Eftevaag                 goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Policy could not be set.",
1126*758e9fbaSOystein Eftevaag                            cleanup);
1127*758e9fbaSOystein Eftevaag             }
1128*758e9fbaSOystein Eftevaag             /* Prepare policy execution */
1129*758e9fbaSOystein Eftevaag             r = ifapi_policyutil_execute_prepare(fapi_ctx, current_policy->hash_alg,
1130*758e9fbaSOystein Eftevaag                                                  cb_ctx->policy);
1131*758e9fbaSOystein Eftevaag             /* Next state will switch from prev context to next context. */
1132*758e9fbaSOystein Eftevaag             goto_if_error(r, "Prepare policy execution.", cleanup);
1133*758e9fbaSOystein Eftevaag             fallthrough;
1134*758e9fbaSOystein Eftevaag 
1135*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_EXECUTE_SUB_POLICY)
1136*758e9fbaSOystein Eftevaag             ESYS_TR session = current_policy->session;
1137*758e9fbaSOystein Eftevaag             r = ifapi_policyutil_execute(fapi_ctx, &session);
1138*758e9fbaSOystein Eftevaag             if (r == TSS2_FAPI_RC_TRY_AGAIN){
1139*758e9fbaSOystein Eftevaag                 SAFE_FREE(names);
1140*758e9fbaSOystein Eftevaag                 return r;
1141*758e9fbaSOystein Eftevaag             }
1142*758e9fbaSOystein Eftevaag 
1143*758e9fbaSOystein Eftevaag             goto_if_error(r, "Execute policy.", cleanup);
1144*758e9fbaSOystein Eftevaag 
1145*758e9fbaSOystein Eftevaag             r = get_policy_signature(cb_ctx->policy, key_public,
1146*758e9fbaSOystein Eftevaag                                      signature);
1147*758e9fbaSOystein Eftevaag             goto_if_error(r, "Get authorization", cleanup);
1148*758e9fbaSOystein Eftevaag 
1149*758e9fbaSOystein Eftevaag             r = get_policy_digest(cb_ctx->policy, hash_alg, digest);
1150*758e9fbaSOystein Eftevaag             goto_if_error(r, "Get authorization", cleanup);
1151*758e9fbaSOystein Eftevaag             cb_ctx->cb_state = POL_CB_EXECUTE_INIT;
1152*758e9fbaSOystein Eftevaag             break;
1153*758e9fbaSOystein Eftevaag 
1154*758e9fbaSOystein Eftevaag         statecasedefault_error(cb_ctx->state, r, cleanup);
1155*758e9fbaSOystein Eftevaag     }
1156*758e9fbaSOystein Eftevaag cleanup:
1157*758e9fbaSOystein Eftevaag     SAFE_FREE(names);
1158*758e9fbaSOystein Eftevaag     cleanup_policy_list(current_policy->policy_list);
1159*758e9fbaSOystein Eftevaag     return r;
1160*758e9fbaSOystein Eftevaag }
1161*758e9fbaSOystein Eftevaag 
1162*758e9fbaSOystein Eftevaag /** Callback for executing a policy identified by a digest stored in a nv object.
1163*758e9fbaSOystein Eftevaag  *
1164*758e9fbaSOystein Eftevaag  * @param[in] nv_public the public data of the nv object which stores the digest
1165*758e9fbaSOystein Eftevaag  *            of the authorized policy.
1166*758e9fbaSOystein Eftevaag  * @param[in] hash_alg The hash algorithm used for policy computation.
1167*758e9fbaSOystein Eftevaag  * @param[in] userdata The user context to retrieve the policy.
1168*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1169*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if it's not possible to allocate enough memory.
1170*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE If no user data id passed or context stack
1171*758e9fbaSOystein Eftevaag  *         is not initialized.
1172*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
1173*758e9fbaSOystein Eftevaag  *         store.
1174*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy for a certain path was not found.
1175*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
1176*758e9fbaSOystein Eftevaag  *         not successful.
1177*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for policy
1178*758e9fbaSOystein Eftevaag  *         execution fails.
1179*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1180*758e9fbaSOystein Eftevaag  *         the function.
1181*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1182*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
1183*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1184*758e9fbaSOystein Eftevaag  *         operation already pending.
1185*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1186*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1187*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
1188*758e9fbaSOystein Eftevaag  *         is not set.
1189*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1190*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1191*758e9fbaSOystein Eftevaag  */
1192*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_exec_auth_nv_policy(TPM2B_NV_PUBLIC * nv_public,TPMI_ALG_HASH hash_alg,void * userdata)1193*758e9fbaSOystein Eftevaag ifapi_exec_auth_nv_policy(
1194*758e9fbaSOystein Eftevaag     TPM2B_NV_PUBLIC *nv_public,
1195*758e9fbaSOystein Eftevaag     TPMI_ALG_HASH hash_alg,
1196*758e9fbaSOystein Eftevaag     void *userdata)
1197*758e9fbaSOystein Eftevaag {
1198*758e9fbaSOystein Eftevaag     TSS2_RC r;
1199*758e9fbaSOystein Eftevaag     TPM2B_MAX_NV_BUFFER *aux_data;
1200*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *fapi_ctx = userdata;
1201*758e9fbaSOystein Eftevaag     IFAPI_POLICY_EXEC_CTX *current_policy;
1202*758e9fbaSOystein Eftevaag     IFAPI_POLICY_EXEC_CB_CTX *cb_ctx;
1203*758e9fbaSOystein Eftevaag     char *nv_path = NULL;
1204*758e9fbaSOystein Eftevaag     ESYS_CONTEXT *esys_ctx;
1205*758e9fbaSOystein Eftevaag     size_t digest_size, offset;
1206*758e9fbaSOystein Eftevaag     TPMT_HA nv_policy;
1207*758e9fbaSOystein Eftevaag 
1208*758e9fbaSOystein Eftevaag     return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
1209*758e9fbaSOystein Eftevaag     return_if_null(fapi_ctx->policy.policyutil_stack, "Policy not initialized.",
1210*758e9fbaSOystein Eftevaag                    TSS2_FAPI_RC_BAD_REFERENCE);
1211*758e9fbaSOystein Eftevaag 
1212*758e9fbaSOystein Eftevaag     if (fapi_ctx->policy.util_current_policy) {
1213*758e9fbaSOystein Eftevaag         /* Use the current policy in the policy stack. */
1214*758e9fbaSOystein Eftevaag         current_policy = fapi_ctx->policy.util_current_policy->pol_exec_ctx;
1215*758e9fbaSOystein Eftevaag     } else {
1216*758e9fbaSOystein Eftevaag         /* Start with the bottom of the policy stack */
1217*758e9fbaSOystein Eftevaag         current_policy = fapi_ctx->policy.policyutil_stack->pol_exec_ctx;
1218*758e9fbaSOystein Eftevaag     }
1219*758e9fbaSOystein Eftevaag     cb_ctx = current_policy->app_data;
1220*758e9fbaSOystein Eftevaag     esys_ctx = fapi_ctx->esys;
1221*758e9fbaSOystein Eftevaag 
1222*758e9fbaSOystein Eftevaag     if (!(digest_size = ifapi_hash_get_digest_size(hash_alg))) {
1223*758e9fbaSOystein Eftevaag         return_error2(TSS2_FAPI_RC_BAD_VALUE,
1224*758e9fbaSOystein Eftevaag                       "Unsupported hash algorithm (%" PRIu16 ")", hash_alg);
1225*758e9fbaSOystein Eftevaag     }
1226*758e9fbaSOystein Eftevaag 
1227*758e9fbaSOystein Eftevaag     switch (cb_ctx->cb_state) {
1228*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_EXECUTE_INIT)
1229*758e9fbaSOystein Eftevaag             /* Search a NV object with a certain NV indext stored in nv_public. */
1230*758e9fbaSOystein Eftevaag             r = ifapi_keystore_search_nv_obj(&fapi_ctx->keystore, &fapi_ctx->io,
1231*758e9fbaSOystein Eftevaag                                              nv_public, &nv_path);
1232*758e9fbaSOystein Eftevaag             FAPI_SYNC(r, "Search Object", cleanup);
1233*758e9fbaSOystein Eftevaag 
1234*758e9fbaSOystein Eftevaag             r = ifapi_keystore_load_async(&fapi_ctx->keystore, &fapi_ctx->io, nv_path);
1235*758e9fbaSOystein Eftevaag             SAFE_FREE(nv_path);
1236*758e9fbaSOystein Eftevaag             return_if_error2(r, "Could not open: %s", nv_path);
1237*758e9fbaSOystein Eftevaag 
1238*758e9fbaSOystein Eftevaag             fallthrough;
1239*758e9fbaSOystein Eftevaag 
1240*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_NV_READ)
1241*758e9fbaSOystein Eftevaag             /* Get object from file */
1242*758e9fbaSOystein Eftevaag             r = ifapi_keystore_load_finish(&fapi_ctx->keystore, &fapi_ctx->io,
1243*758e9fbaSOystein Eftevaag                                            &cb_ctx->object);
1244*758e9fbaSOystein Eftevaag             return_try_again(r);
1245*758e9fbaSOystein Eftevaag             return_if_error(r, "read_finish failed");
1246*758e9fbaSOystein Eftevaag 
1247*758e9fbaSOystein Eftevaag             r = ifapi_initialize_object(esys_ctx, &cb_ctx->object);
1248*758e9fbaSOystein Eftevaag             goto_if_error(r, "Initialize NV object", cleanup);
1249*758e9fbaSOystein Eftevaag 
1250*758e9fbaSOystein Eftevaag             current_policy->nv_index = cb_ctx->object.handle;
1251*758e9fbaSOystein Eftevaag             ifapi_cleanup_ifapi_object(&cb_ctx->object);
1252*758e9fbaSOystein Eftevaag             get_nv_auth_object(&cb_ctx->object,
1253*758e9fbaSOystein Eftevaag                                current_policy->nv_index,
1254*758e9fbaSOystein Eftevaag                                &current_policy->auth_object,
1255*758e9fbaSOystein Eftevaag                                &current_policy->auth_handle);
1256*758e9fbaSOystein Eftevaag             fallthrough;
1257*758e9fbaSOystein Eftevaag 
1258*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_AUTHORIZE_OBJECT)
1259*758e9fbaSOystein Eftevaag             /* Authorize the NV object with the corresponding auth object. */
1260*758e9fbaSOystein Eftevaag             r = ifapi_authorize_object(fapi_ctx, &cb_ctx->auth_object, &cb_ctx->session);
1261*758e9fbaSOystein Eftevaag             return_try_again(r);
1262*758e9fbaSOystein Eftevaag             goto_if_error(r, "Authorize  object.", cleanup);
1263*758e9fbaSOystein Eftevaag 
1264*758e9fbaSOystein Eftevaag             /* Prepare the reading of the NV index from TPM. */
1265*758e9fbaSOystein Eftevaag             r = Esys_NV_Read_Async(esys_ctx,
1266*758e9fbaSOystein Eftevaag                             current_policy->auth_handle, current_policy->nv_index,
1267*758e9fbaSOystein Eftevaag                             cb_ctx->session, ESYS_TR_NONE, ESYS_TR_NONE,
1268*758e9fbaSOystein Eftevaag                             sizeof(TPMI_ALG_HASH) + digest_size, 0);
1269*758e9fbaSOystein Eftevaag             goto_if_error(r, "Unmarshal policy", cleanup);
1270*758e9fbaSOystein Eftevaag             fallthrough;
1271*758e9fbaSOystein Eftevaag 
1272*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_READ_NV_POLICY)
1273*758e9fbaSOystein Eftevaag             /* Finalize the reading. */
1274*758e9fbaSOystein Eftevaag             r = Esys_NV_Read_Finish(esys_ctx, &aux_data);
1275*758e9fbaSOystein Eftevaag             try_again_or_error_goto(r, "NV read", cleanup);
1276*758e9fbaSOystein Eftevaag 
1277*758e9fbaSOystein Eftevaag             offset = 0;
1278*758e9fbaSOystein Eftevaag             r = Tss2_MU_TPMT_HA_Unmarshal(&aux_data->buffer[0], aux_data->size,
1279*758e9fbaSOystein Eftevaag                                           &offset, &nv_policy);
1280*758e9fbaSOystein Eftevaag             Esys_Free(aux_data);
1281*758e9fbaSOystein Eftevaag             goto_if_error(r, "Unmarshal policy", cleanup);
1282*758e9fbaSOystein Eftevaag 
1283*758e9fbaSOystein Eftevaag             cb_ctx->policy_digest.size = digest_size;
1284*758e9fbaSOystein Eftevaag             memcpy(&cb_ctx->policy_digest.buffer[0], &nv_policy.digest, digest_size);
1285*758e9fbaSOystein Eftevaag             fallthrough;
1286*758e9fbaSOystein Eftevaag 
1287*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_SEARCH_POLICY)
1288*758e9fbaSOystein Eftevaag             /* Search policy appropriate in object store */
1289*758e9fbaSOystein Eftevaag             r = search_policy(fapi_ctx, compare_policy_digest, false,
1290*758e9fbaSOystein Eftevaag                               &cb_ctx->policy_digest, &hash_alg,
1291*758e9fbaSOystein Eftevaag                               &current_policy->policy_list);
1292*758e9fbaSOystein Eftevaag             FAPI_SYNC(r, "Search policy", cleanup);
1293*758e9fbaSOystein Eftevaag 
1294*758e9fbaSOystein Eftevaag             if (!current_policy->policy_list) {
1295*758e9fbaSOystein Eftevaag                 goto_error(r, TSS2_FAPI_RC_POLICY_UNKNOWN, "Policy not found", cleanup);
1296*758e9fbaSOystein Eftevaag             }
1297*758e9fbaSOystein Eftevaag             /* Prepare policy execution */
1298*758e9fbaSOystein Eftevaag             r = ifapi_policyutil_execute_prepare(fapi_ctx, current_policy->hash_alg,
1299*758e9fbaSOystein Eftevaag                                                  &current_policy->policy_list->policy);
1300*758e9fbaSOystein Eftevaag             return_if_error(r, "Prepare policy execution.");
1301*758e9fbaSOystein Eftevaag             fallthrough;
1302*758e9fbaSOystein Eftevaag 
1303*758e9fbaSOystein Eftevaag         statecase(cb_ctx->cb_state, POL_CB_EXECUTE_SUB_POLICY)
1304*758e9fbaSOystein Eftevaag             ESYS_TR session = current_policy->session;
1305*758e9fbaSOystein Eftevaag             r = ifapi_policyutil_execute(fapi_ctx, &session);
1306*758e9fbaSOystein Eftevaag             if (r == TSS2_FAPI_RC_TRY_AGAIN)
1307*758e9fbaSOystein Eftevaag                 return r;
1308*758e9fbaSOystein Eftevaag 
1309*758e9fbaSOystein Eftevaag             goto_if_error(r, "Execute policy.", cleanup);
1310*758e9fbaSOystein Eftevaag             cb_ctx->cb_state = POL_CB_EXECUTE_INIT;
1311*758e9fbaSOystein Eftevaag             break;
1312*758e9fbaSOystein Eftevaag 
1313*758e9fbaSOystein Eftevaag         statecasedefault_error(cb_ctx->state, r, cleanup);
1314*758e9fbaSOystein Eftevaag     }
1315*758e9fbaSOystein Eftevaag cleanup:
1316*758e9fbaSOystein Eftevaag     cleanup_policy_list(current_policy->policy_list);
1317*758e9fbaSOystein Eftevaag     SAFE_FREE(nv_path);
1318*758e9fbaSOystein Eftevaag     return r;
1319*758e9fbaSOystein Eftevaag 
1320*758e9fbaSOystein Eftevaag }
1321*758e9fbaSOystein Eftevaag 
1322*758e9fbaSOystein Eftevaag /** Callback for getting the name of a key to be duplicated.
1323*758e9fbaSOystein Eftevaag  *
1324*758e9fbaSOystein Eftevaag  * @param[out] name the name of the object to be duplicated.
1325*758e9fbaSOystein Eftevaag  * @param[in] userdata The user context to retrieve the key.
1326*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1327*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if the context is not passed or the
1328*758e9fbaSOystein Eftevaag  *         object to be duplicated is not set.
1329*758e9fbaSOystein Eftevaag  */
1330*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_duplicate_name(TPM2B_NAME * name,void * userdata)1331*758e9fbaSOystein Eftevaag ifapi_get_duplicate_name(
1332*758e9fbaSOystein Eftevaag     TPM2B_NAME *name,
1333*758e9fbaSOystein Eftevaag     void *userdata)
1334*758e9fbaSOystein Eftevaag {
1335*758e9fbaSOystein Eftevaag     FAPI_CONTEXT *fapi_ctx = userdata;
1336*758e9fbaSOystein Eftevaag 
1337*758e9fbaSOystein Eftevaag     return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
1338*758e9fbaSOystein Eftevaag     return_if_null(fapi_ctx->duplicate_key, "Object for duplication no set.",
1339*758e9fbaSOystein Eftevaag                    TSS2_FAPI_RC_BAD_REFERENCE);
1340*758e9fbaSOystein Eftevaag     *name = fapi_ctx->duplicate_key->misc.key.name;
1341*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1342*758e9fbaSOystein Eftevaag }
1343