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