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 ¤t_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 = ¤t_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 ¤t_policy->auth_object,
1255*758e9fbaSOystein Eftevaag ¤t_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 ¤t_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 ¤t_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