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 "tss2_mu.h"
15 #include "fapi_util.h"
16 #include "fapi_crypto.h"
17 //#include "fapi_policy.h"
18 #include "ifapi_policy_execute.h"
19 #include "ifapi_policyutil_execute.h"
20 #include "ifapi_helpers.h"
21 #include "ifapi_json_deserialize.h"
22 #include "tpm_json_deserialize.h"
23 #include "ifapi_policy_callbacks.h"
24 #include "ifapi_policyutil_execute.h"
25 #define LOGMODULE fapi
26 #include "util/log.h"
27 #include "util/aux_util.h"
28
29 /** Create a new policy on policy stack.
30 *
31 * The structures for policy and callback execution are allocated
32 * and the callbacks are assigned.
33 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
34 */
35 static TSS2_RC
new_policy(FAPI_CONTEXT * context,TPMS_POLICY * policy,IFAPI_POLICYUTIL_STACK ** current_policy)36 new_policy(
37 FAPI_CONTEXT *context,
38 TPMS_POLICY *policy,
39 IFAPI_POLICYUTIL_STACK **current_policy)
40 {
41 LOG_DEBUG("ADD POLICY");
42 IFAPI_POLICY_EXEC_CTX *pol_exec_ctx;
43 IFAPI_POLICY_EXEC_CB_CTX *pol_exec_cb_ctx;
44
45 *current_policy = calloc(sizeof(IFAPI_POLICYUTIL_STACK), 1);
46 if (!*current_policy) {
47 return_error(TSS2_FAPI_RC_MEMORY, "Out of memory");
48 }
49
50 pol_exec_ctx = calloc(sizeof(IFAPI_POLICY_EXEC_CTX), 1);
51 if (!pol_exec_ctx) {
52 return_error(TSS2_FAPI_RC_MEMORY, "Out of memory");
53 }
54 (*current_policy)->pol_exec_ctx = pol_exec_ctx;
55 pol_exec_ctx->callbacks.cbauth = ifapi_policyeval_cbauth;
56 pol_exec_ctx->callbacks.cbauth_userdata = context;
57 pol_exec_ctx->callbacks.cbpolsel = ifapi_branch_selection;
58 pol_exec_ctx->callbacks.cbpolsel_userdata = context;
59 pol_exec_ctx->callbacks.cbsign = ifapi_sign_buffer;
60 pol_exec_ctx->callbacks.cbsign_userdata = context;
61 pol_exec_ctx->callbacks.cbauthpol = ifapi_exec_auth_policy;
62 pol_exec_ctx->callbacks.cbauthpol_userdata = context;
63 pol_exec_ctx->callbacks.cbauthnv = ifapi_exec_auth_nv_policy;
64 pol_exec_ctx->callbacks.cbauthnv_userdata = context;
65 pol_exec_ctx->callbacks.cbdup = ifapi_get_duplicate_name;
66 pol_exec_ctx->callbacks.cbdup_userdata = context;
67 pol_exec_ctx->callbacks.cbaction = ifapi_policy_action;
68 pol_exec_ctx->callbacks.cbaction_userdata = context;
69
70 pol_exec_cb_ctx = calloc(sizeof(IFAPI_POLICY_EXEC_CB_CTX), 1);
71 if (!pol_exec_cb_ctx) {
72 return_error(TSS2_FAPI_RC_MEMORY, "Out of memory");
73 }
74 pol_exec_ctx->app_data = pol_exec_cb_ctx;
75 pol_exec_ctx->policy = policy;
76 if (!context->policy.policyutil_stack) {
77 context->policy.policyutil_stack = *current_policy;
78 context->policy.util_current_policy = *current_policy;
79 } else {
80 context->policy.util_current_policy->next = *current_policy;
81 (*current_policy)->prev = context->policy.util_current_policy;
82 }
83 return TSS2_RC_SUCCESS;
84 }
85
86 /** Compute a new session which will be uses as policy session.
87 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
88 * this function needs to be called again.
89 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
90 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
91 */
92 static TSS2_RC
create_session(FAPI_CONTEXT * context,ESYS_TR * session,TPMI_ALG_HASH hash_alg)93 create_session(
94 FAPI_CONTEXT *context,
95 ESYS_TR *session,
96 TPMI_ALG_HASH hash_alg)
97 {
98 TSS2_RC r = TSS2_RC_SUCCESS;
99
100 switch (context->policy.create_session_state) {
101 case CREATE_SESSION_INIT:
102 r = Esys_StartAuthSession_Async(context->esys,
103 context->srk_handle ? context->srk_handle : ESYS_TR_NONE,
104 ESYS_TR_NONE,
105 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
106 NULL,
107 TPM2_SE_POLICY,
108 &context->profiles.default_profile.session_symmetric,
109 hash_alg);
110
111 return_if_error(r, "Creating session.");
112
113 context->policy.create_session_state = WAIT_FOR_CREATE_SESSION;
114 return TSS2_FAPI_RC_TRY_AGAIN;
115
116 case WAIT_FOR_CREATE_SESSION:
117 r = Esys_StartAuthSession_Finish(context->esys, session);
118 if (r != TSS2_RC_SUCCESS)
119 return r;
120 context->policy.create_session_state = CREATE_SESSION_INIT;
121 break;
122
123 default:
124 context->state = _FAPI_STATE_INTERNALERROR;
125 goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid state for create session.",
126 cleanup);
127 }
128
129 cleanup:
130 return r;
131 }
132
133 /** Cleanup the current policy and adapt the policy stack.
134 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
135 */
136 static TSS2_RC
clear_current_policy(FAPI_CONTEXT * context)137 clear_current_policy(FAPI_CONTEXT *context)
138 {
139 LOG_DEBUG("CLEAR POLICY");
140 IFAPI_POLICYUTIL_STACK *prev_pol;
141 if (!context->policy.util_current_policy) {
142 return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "No current policy.");
143 }
144 prev_pol = context->policy.util_current_policy->prev;
145
146 SAFE_FREE(context->policy.util_current_policy->pol_exec_ctx->app_data);
147 SAFE_FREE(context->policy.util_current_policy->pol_exec_ctx);
148 SAFE_FREE(context->policy.util_current_policy);
149
150 if (!prev_pol) {
151 context->policy.policyutil_stack = NULL;
152 } else {
153 prev_pol->next = NULL;
154 }
155 return TSS2_RC_SUCCESS;
156 }
157
158 /** Cleanup the policy stack.
159 *
160 * Will be used if an error occurs.
161 */
162 static void
clear_all_policies(FAPI_CONTEXT * context)163 clear_all_policies(FAPI_CONTEXT *context)
164 {
165 LOG_DEBUG("CLEAR ALL POLICIES");
166
167 IFAPI_POLICYUTIL_STACK *policy = context->policy.policyutil_stack;
168 IFAPI_POLICYUTIL_STACK *next_policy;
169
170 while (policy) {
171 next_policy = policy->next;
172 SAFE_FREE(policy->pol_exec_ctx->app_data);
173 if (policy->pol_exec_ctx->session)
174 Esys_FlushContext(context->esys, policy->pol_exec_ctx->session);
175 SAFE_FREE(policy->pol_exec_ctx);
176 ;
177 SAFE_FREE(policy);
178 policy = next_policy;
179 }
180 context->policy.policyutil_stack = NULL;
181 }
182
183 /** Prepare the execution of a new policy on policy stack.
184 *
185 * The context for the policy utility, the policy execution and the needed
186 * callbacks is initialized.
187 * The policy execution will be prepared. In this step the list of policies
188 * to be executed will be computed.
189 * @param[in,out] context The fapi context with the pointer to the policy stack.
190 * @param[in] hash_alg The hash algorithm used for the policy computation.
191 * @param[in,out] policy The policy to be executed. Some policy elements will
192 * be used to store computed parameters needed for policy
193 * execution.
194 * @retval TSS2_RC_SUCCESS on success.
195 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN If the callback for branch selection is
196 * not defined. This callback will be needed of or policies have to be
197 * executed.
198 * @retval TSS2_FAPI_RC_BAD_VALUE If the computed branch index deliverd by the
199 * callback does not identify a branch.
200 * @retval TSS2_FAPI_RC_BAD_REFERENCE If no context is passed.
201 *
202 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
203 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
204 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
205 */
206 TSS2_RC
ifapi_policyutil_execute_prepare(FAPI_CONTEXT * context,TPMI_ALG_HASH hash_alg,TPMS_POLICY * policy)207 ifapi_policyutil_execute_prepare(
208 FAPI_CONTEXT *context,
209 TPMI_ALG_HASH hash_alg,
210 TPMS_POLICY *policy)
211 {
212 TSS2_RC r;
213 IFAPI_POLICYUTIL_STACK *current_policy;
214
215 return_if_null(context, "Bad context.", TSS2_FAPI_RC_BAD_REFERENCE);
216
217 r = new_policy(context, policy, ¤t_policy);
218 goto_if_error(r, "Create new policy.", error);
219
220 r = ifapi_policyeval_execute_prepare(current_policy->pol_exec_ctx, hash_alg, policy);
221 goto_if_error(r, "Prepare policy execution.", error);
222
223 return r;
224
225 error:
226 while (context->policy.policyutil_stack) {
227 clear_all_policies(context);
228 }
229 SAFE_FREE(current_policy);
230 return r;
231 }
232 /** State machine to Execute the TPM policy commands needed for the current policy.
233 *
234 * In the first step a session will be created if no session is passed.
235 * In the second step the policy engine will execute the policy.
236 *
237 * @param[in,out] context The fapi context with the pointer to the policy stack.
238 * @param[in,out] session The policy session to be extended or if the value is
239 * equal zero or ESYS_TR_NONE a new created session will been
240 * be stored in this parameter.
241 * @retval TSS2_RC_SUCCESS on success.
242 * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
243 * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
244 * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
245 * store.
246 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
247 * not successful.
248 * @retval TSS2_FAPI_RC_BAD_TEMPLATE In a invalid policy is loaded during execution.
249 * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for policy
250 * execution fails.
251 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
252 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
253 * this function needs to be called again.
254 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
255 * operation already pending.
256 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
257 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
258 * during authorization.
259 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
260 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
261 * is not set.
262 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
263 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
264 */
265 TSS2_RC
ifapi_policyutil_execute(FAPI_CONTEXT * context,ESYS_TR * session)266 ifapi_policyutil_execute(FAPI_CONTEXT *context, ESYS_TR *session)
267 {
268 TSS2_RC r;
269 IFAPI_POLICYUTIL_STACK *pol_util_ctx;
270 TPMI_ALG_HASH hash_alg;
271
272 if (context->policy.util_current_policy) {
273 pol_util_ctx = context->policy.util_current_policy->next;
274 context->policy.util_current_policy = context->policy.util_current_policy->next;
275 } else {
276 pol_util_ctx = context->policy.policyutil_stack;
277 context->policy.util_current_policy = pol_util_ctx;
278 }
279 LOG_TRACE("Util context: %p", pol_util_ctx);
280
281 if (!pol_util_ctx) {
282 return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "No policy util stack.");
283 }
284
285 switch (pol_util_ctx->state) {
286 statecase(pol_util_ctx->state, POLICY_UTIL_INIT);
287 LOG_DEBUG("Util session: %x", pol_util_ctx->policy_session);
288 if (*session == ESYS_TR_NONE || *session == 0) {
289 /* Create a new policy session for the current policy execution */
290 hash_alg = pol_util_ctx->pol_exec_ctx->hash_alg;
291 r = create_session(context, &pol_util_ctx->policy_session,
292 hash_alg);
293 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) {
294 context->policy.util_current_policy = pol_util_ctx->prev;
295 return TSS2_FAPI_RC_TRY_AGAIN;
296 }
297 goto_if_error(r, "Create policy session", error);
298
299 pol_util_ctx->pol_exec_ctx->session = pol_util_ctx->policy_session;
300 } else {
301 pol_util_ctx->pol_exec_ctx->session = *session;
302 }
303 fallthrough;
304
305 statecase(pol_util_ctx->state, POLICY_UTIL_EXEC_POLICY);
306 r = ifapi_policyeval_execute(context->esys,
307 pol_util_ctx->pol_exec_ctx);
308 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) {
309 context->policy.util_current_policy = pol_util_ctx->prev;
310 return TSS2_FAPI_RC_TRY_AGAIN;
311 }
312 goto_if_error(r, "Execute policy.", error);
313
314 break;
315
316 statecasedefault(pol_util_ctx->state);
317 }
318 *session = pol_util_ctx->policy_session;
319
320 pol_util_ctx = pol_util_ctx->prev;
321
322 r = clear_current_policy(context);
323 goto_if_error(r, "Clear policy.", error);
324
325 context->policy.util_current_policy = pol_util_ctx;
326
327 LOG_TRACE("success");
328 return r;
329
330 error:
331 while (context->policy.policyutil_stack) {
332 clear_all_policies(context);
333 }
334 return r;
335 }
336