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 "tss2_fapi.h"
12 #include "fapi_int.h"
13 #include "fapi_util.h"
14 #include "tss2_esys.h"
15 #include "fapi_policy.h"
16 #define LOGMODULE fapi
17 #include "util/log.h"
18 #include "util/aux_util.h"
19
20 /** One-Call function for Fapi_ExportPolicy
21 *
22 * Exports a policy to a JSON encoded byte buffer.
23 *
24 * @param[in,out] context The FAPI_CONTEXT
25 * @param[in] path The path to the policy that is to be exported
26 * @param[out] jsonPolicy The JSON-encoded policy. jsonPolicy MUST NOT be NULL.
27 *
28 * @retval TSS2_RC_SUCCESS: if the function call was a success.
29 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, path or jsonPolicy is NULL.
30 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
31 * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI policy.
32 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
33 * operation already pending.
34 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
35 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
36 * internal operations or return parameters.
37 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
38 * config file.
39 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
40 * this function needs to be called again.
41 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
42 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
43 * the function.
44 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
45 * during authorization.
46 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
47 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
48 */
49 TSS2_RC
Fapi_ExportPolicy(FAPI_CONTEXT * context,char const * path,char ** jsonPolicy)50 Fapi_ExportPolicy(
51 FAPI_CONTEXT *context,
52 char const *path,
53 char **jsonPolicy)
54 {
55 LOG_TRACE("called for context:%p", context);
56
57 TSS2_RC r, r2;
58
59 /* Check for NULL parameters */
60 check_not_null(context);
61 check_not_null(path);
62 check_not_null(jsonPolicy);
63
64 /* Check whether TCTI and ESYS are initialized */
65 return_if_null(context->esys, "Command can't be executed in none TPM mode.",
66 TSS2_FAPI_RC_NO_TPM);
67
68 /* If the async state automata of FAPI shall be tested, then we must not set
69 the timeouts of ESYS to blocking mode.
70 During testing, the mssim tcti will ensure multiple re-invocations.
71 Usually however the synchronous invocations of FAPI shall instruct ESYS
72 to block until a result is available. */
73 #ifndef TEST_FAPI_ASYNC
74 r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
75 return_if_error_reset_state(r, "Set Timeout to blocking");
76 #endif /* TEST_FAPI_ASYNC */
77
78 r = Fapi_ExportPolicy_Async(context, path);
79 return_if_error_reset_state(r, "PolicyExport");
80
81 do {
82 /* We wait for file I/O to be ready if the FAPI state automata
83 are in a file I/O state. */
84 r = ifapi_io_poll(&context->io);
85 return_if_error(r, "Something went wrong with IO polling");
86
87 /* Repeatedly call the finish function, until FAPI has transitioned
88 through all execution stages / states of this invocation. */
89 r = Fapi_ExportPolicy_Finish(context, jsonPolicy);
90 } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
91
92 /* Reset the ESYS timeout to non-blocking, immediate response. */
93 r2 = Esys_SetTimeout(context->esys, 0);
94 return_if_error(r2, "Set Timeout to non-blocking");
95
96 return_if_error_reset_state(r, "PolicyExport");
97
98 return TSS2_RC_SUCCESS;
99
100 }
101
102 /** Asynchronous function for Fapi_ExportPolicy
103 *
104 * Exports a policy to a JSON encoded byte buffer.
105 *
106 * Call Fapi_ExportPolicy_Finish to finish the execution of this command.
107 *
108 * @param[in,out] context The FAPI_CONTEXT
109 * @param[in] path The path to the policy that is to be exported
110 *
111 * @retval TSS2_RC_SUCCESS: if the function call was a success.
112 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
113 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
114 * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI policy.
115 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
116 * operation already pending.
117 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
118 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
119 * internal operations or return parameters.
120 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
121 * config file.
122 */
123 TSS2_RC
Fapi_ExportPolicy_Async(FAPI_CONTEXT * context,char const * path)124 Fapi_ExportPolicy_Async(
125 FAPI_CONTEXT *context,
126 char const *path)
127 {
128 LOG_TRACE("called for context:%p", context);
129 LOG_TRACE("path: %s", path);
130
131 TSS2_RC r;
132
133 /* Check for NULL parameters */
134 check_not_null(context);
135 check_not_null(path);
136
137 /* Helpful alias pointers */
138 IFAPI_ExportPolicy * command = &context->cmd.ExportPolicy;
139
140 /* Reset all context-internal session state information. */
141 r = ifapi_session_init(context);
142 return_if_error(r, "Initialize PolicyExport");
143
144 /* Initialize the context state for this operation. */
145 if (ifapi_path_type_p(path, IFAPI_POLICY_PATH)) {
146 context->state = POLICY_EXPORT_READ_POLICY;
147 } else {
148 context->state = POLICY_EXPORT_READ_OBJECT;
149 }
150
151 /* Copy parameters to context for use during _Finish. */
152 strdup_check(command->path, path, r ,error_cleanup);
153 memset(&command->object, 0, sizeof(IFAPI_OBJECT));
154
155 LOG_TRACE("finished");
156 return TSS2_RC_SUCCESS;
157
158 error_cleanup:
159 /* Cleanup duplicated input parameters that were copied before. */
160 SAFE_FREE(command->path);
161 return r;
162 }
163
164 /** Asynchronous finish function for Fapi_ExportPolicy
165 *
166 * This function should be called after a previous Fapi_ExportPolicy_Async.
167 *
168 * @param[in,out] context The FAPI_CONTEXT
169 * @param[out] jsonPolicy The JSON-encoded policy. jsonPolicy MUST NOT be NULL.
170 *
171 * @retval TSS2_RC_SUCCESS: if the function call was a success.
172 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or jsonPolicy is NULL.
173 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
174 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
175 * operation already pending.
176 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
177 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
178 * internal operations or return parameters.
179 * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
180 * complete. Call this function again later.
181 * @retval TSS2_FAPI_RC_BAD_PATH if the used path in inappropriate-
182 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
183 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
184 * the function.
185 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
186 * during authorization.
187 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
188 */
189 TSS2_RC
Fapi_ExportPolicy_Finish(FAPI_CONTEXT * context,char ** jsonPolicy)190 Fapi_ExportPolicy_Finish(
191 FAPI_CONTEXT *context,
192 char **jsonPolicy)
193 {
194 LOG_TRACE("called for context:%p", context);
195
196 TPMS_POLICY policy = {0};
197 json_object *jso = NULL;
198 TSS2_RC r;
199
200 /* Check for NULL parameters */
201 check_not_null(context);
202 check_not_null(jsonPolicy);
203
204 /* Helpful alias pointers */
205 IFAPI_ExportPolicy * command = &context->cmd.ExportPolicy;
206
207 switch (context->state) {
208 statecase(context->state, POLICY_EXPORT_READ_POLICY);
209 /* This is the entry point if a policy from the policy store shall
210 be exported. */
211 /* Load the policy to be exported from the policy store. */
212 r = ifapi_policy_store_load_async(&context->pstore, &context->io,
213 command->path);
214 goto_if_error2(r, "Can't open: %s", error_cleanup,
215 command->path);
216 fallthrough;
217
218 statecase(context->state, POLICY_EXPORT_READ_POLICY_FINISH);
219 r = ifapi_policy_store_load_finish(&context->pstore, &context->io, &policy);
220 return_try_again(r);
221 return_if_error_reset_state(r, "read_finish failed");
222
223 /* Serialize the policy to JSON. */
224 r = ifapi_json_TPMS_POLICY_serialize(&policy, &jso);
225 goto_if_error(r, "Serialize policy", error_cleanup);
226
227 /* Duplicate the JSON string to be returned to the caller. */
228 strdup_check(*jsonPolicy,
229 json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY),
230 r, error_cleanup);
231
232 break;
233 statecase(context->state, POLICY_EXPORT_READ_OBJECT);
234 /* This is the entry point if a policy for a key from the key store
235 shall be exported. */
236 memset(&command->object, 0, sizeof(IFAPI_OBJECT));
237 /* Load the key meta data from the keystore. */
238 r = ifapi_keystore_load_async(&context->keystore, &context->io,
239 command->path);
240 return_if_error2(r, "Could not open: %s", command->path);
241 fallthrough;
242
243 statecase(context->state, POLICY_EXPORT_READ_OBJECT_FINISH);
244 r = ifapi_keystore_load_finish(&context->keystore, &context->io,
245 &command->object);
246 return_try_again(r);
247 return_if_error_reset_state(r, "read_finish failed");
248
249 goto_if_null2(command->object.policy,
250 "Object has no policy",
251 r, TSS2_FAPI_RC_BAD_PATH, error_cleanup);
252
253 /* Serialize the policy to JSON. */
254 r = ifapi_json_TPMS_POLICY_serialize(context->
255 cmd.ExportPolicy.object.policy, &jso);
256 goto_if_error(r, "Serialize policy", error_cleanup);
257
258 /* Duplicate the JSON string to be returned to the caller. */
259 strdup_check(*jsonPolicy,
260 json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY),
261 r, error_cleanup);
262 break;
263
264 statecasedefault(context->state);
265 }
266
267 /* Cleanup any intermediate results and state stored in the context. */
268 context->state = _FAPI_STATE_INIT;
269 if (jso)
270 json_object_put(jso);
271 ifapi_cleanup_ifapi_object(&command->object);
272 ifapi_cleanup_policy(&policy);
273 ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
274 ifapi_cleanup_ifapi_object(context->loadKey.key_object);
275 ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
276 SAFE_FREE(command->path);
277 LOG_TRACE("finished");
278 return TSS2_RC_SUCCESS;
279
280 error_cleanup:
281 /* Cleanup any intermediate results and state stored in the context. */
282 if (command->object.objectType)
283 ifapi_cleanup_ifapi_object(&command->object);
284 if (jso)
285 json_object_put(jso);
286 ifapi_cleanup_policy(&policy);
287 ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
288 ifapi_cleanup_ifapi_object(context->loadKey.key_object);
289 ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
290 SAFE_FREE(command->path);
291 context->state = _FAPI_STATE_INIT;
292 return r;
293 }
294