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 ¤t_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 = ¤t_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 ¤t_policy->auth_object,
1255 ¤t_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 ¤t_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 ¤t_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