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 <stdlib.h>
12 #include <errno.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <string.h>
16
17 #include "tss2_fapi.h"
18 #include "fapi_int.h"
19 #include "fapi_util.h"
20 #include "fapi_policy.h"
21 #include "tss2_esys.h"
22 #define LOGMODULE fapi
23 #include "util/log.h"
24 #include "util/aux_util.h"
25
26 /** One-Call function for Fapi_CreateKey
27 *
28 * Creates a key inside the TPM based on the Key type, using the supplied
29 * policy and authValue. The key is then stored either in the FAPI metadata
30 * store or the TPM.
31 *
32 * @param[in,out] context The FAPI_CONTEXT
33 * @param[in] path The path where the new key is stored
34 * @param[in] type The type of the new key. May be NULL
35 * @param[in] policyPath The path to the policy that is associated with the new
36 * key. May be NULL
37 * @param[in] authValue The authorization value for the new key. May be NULL
38 *
39 * @retval TSS2_RC_SUCCESS: if the function call was a success.
40 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
41 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
42 * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath is non-NULL and does not map to
43 * a FAPI policy.
44 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if the parent key does not map to a FAPI
45 * key.
46 * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if a file already exists at path.
47 * @retval TSS2_FAPI_RC_BAD_VALUE: if the keyType is non-NULL and invalid.
48 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
49 * operation already pending.
50 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
51 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
52 * internal operations or return parameters.
53 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
54 * config file.
55 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
56 * this function needs to be called again.
57 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
58 * is not set.
59 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
60 */
61 TSS2_RC
Fapi_CreateKey(FAPI_CONTEXT * context,char const * path,char const * type,char const * policyPath,char const * authValue)62 Fapi_CreateKey(
63 FAPI_CONTEXT *context,
64 char const *path,
65 char const *type,
66 char const *policyPath,
67 char const *authValue)
68 {
69 LOG_TRACE("called for context:%p", context);
70
71 TSS2_RC r, r2;
72
73 /* Check for NULL parameters */
74 check_not_null(context);
75 check_not_null(path);
76
77 /* Check whether TCTI and ESYS are initialized */
78 return_if_null(context->esys, "Command can't be executed in none TPM mode.",
79 TSS2_FAPI_RC_NO_TPM);
80
81 /* If the async state automata of FAPI shall be tested, then we must not set
82 the timeouts of ESYS to blocking mode.
83 During testing, the mssim tcti will ensure multiple re-invocations.
84 Usually however the synchronous invocations of FAPI shall instruct ESYS
85 to block until a result is available. */
86 #ifndef TEST_FAPI_ASYNC
87 r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
88 return_if_error_reset_state(r, "Set Timeout to blocking");
89 #endif /* TEST_FAPI_ASYNC */
90
91 r = Fapi_CreateKey_Async(context, path, type, policyPath, authValue);
92 return_if_error_reset_state(r, "Key_Create");
93
94 do {
95 /* We wait for file I/O to be ready if the FAPI state automata
96 are in a file I/O state. */
97 r = ifapi_io_poll(&context->io);
98 return_if_error(r, "Something went wrong with IO polling");
99
100 /* Repeatedly call the finish function, until FAPI has transitioned
101 through all execution stages / states of this invocation. */
102 r = Fapi_CreateKey_Finish(context);
103 } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
104
105 /* Reset the ESYS timeout to non-blocking, immediate response. */
106 r2 = Esys_SetTimeout(context->esys, 0);
107 return_if_error(r2, "Set Timeout to non-blocking");
108
109 return_if_error_reset_state(r, "Key_Create");
110
111 return TSS2_RC_SUCCESS;
112 }
113
114 /** Asynchronous function for Fapi_CreateKey
115 *
116 * Creates a key inside the TPM based on the Key type, using the supplied
117 * policy and authValue. The key is then stored either in the FAPI metadata
118 * store or the TPM.
119 *
120 * Call Fapi_CreateKey_Finish to finish the execution of this command.
121 *
122 * @param[in,out] context The FAPI_CONTEXT
123 * @param[in] path The path where the new key is stored
124 * @param[in] type The type of the new key. May be NULL
125 * @param[in] policyPath The path to the policy that is associated with the new
126 * key. May be NULL
127 * @param[in] authValue The authorization value for the new key. May be NULL
128 *
129 * @retval TSS2_RC_SUCCESS: if the function call was a success.
130 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
131 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
132 * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath is non-NULL and does not map to
133 * a FAPI policy.
134 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if the parent key does not map to a FAPI
135 * key.
136 * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if a file already exists at path.
137 * @retval TSS2_FAPI_RC_BAD_VALUE: if the keyType is non-NULL and invalid.
138 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
139 * operation already pending.
140 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
141 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
142 * internal operations or return parameters.
143 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
144 * config file.
145 */
146 TSS2_RC
Fapi_CreateKey_Async(FAPI_CONTEXT * context,char const * path,char const * type,char const * policyPath,char const * authValue)147 Fapi_CreateKey_Async(
148 FAPI_CONTEXT *context,
149 char const *path,
150 char const *type,
151 char const *policyPath,
152 char const *authValue)
153 {
154 LOG_TRACE("called for context:%p", context);
155 LOG_TRACE("path: %s", path);
156 LOG_TRACE("type: %s", type);
157 LOG_TRACE("policyPath: %s", policyPath);
158 LOG_TRACE("authValue: %s", authValue);
159
160 TSS2_RC r;
161
162 /* Check for NULL parameters */
163 check_not_null(context);
164 check_not_null(path);
165
166 /* Reset all context-internal session state information. */
167 r = ifapi_session_init(context);
168 return_if_error(r, "Initialize CreateKey");
169
170 /* Prepare the key creation with the authValue.
171 This will also copy the input information for use during the finish call. */
172 r = ifapi_key_create_prepare_auth(context, path, policyPath, authValue);
173 return_if_error(r, "Key create.");
174
175 /* Set the flags of the key to be created. If no type is given the empty-string
176 default type flags are set. If no policy is given, userWithAuth flag is set. */
177 r = ifapi_set_key_flags(type ? type : "",
178 (policyPath && strcmp(policyPath, "") != 0) ? true : false,
179 &context->cmd.Key_Create.public_templ);
180 return_if_error(r, "Set key flags for key");
181
182 /* Initialize the context state for this operation. */
183 context->state = KEY_CREATE;
184 LOG_TRACE("finished");
185 return TSS2_RC_SUCCESS;
186 }
187
188 /** Asynchronous finish function for Fapi_CreateKey
189 *
190 * This function should be called after a previous Fapi_CreateKey_Async.
191 *
192 * @param[in,out] context The FAPI_CONTEXT
193 *
194 * @retval TSS2_RC_SUCCESS: if the function call was a success.
195 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
196 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
197 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
198 * operation already pending.
199 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
200 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
201 * internal operations or return parameters.
202 * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
203 * complete. Call this function again later.
204 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
205 * the function.
206 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
207 * is not set.
208 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
209 */
210 TSS2_RC
Fapi_CreateKey_Finish(FAPI_CONTEXT * context)211 Fapi_CreateKey_Finish(
212 FAPI_CONTEXT *context)
213 {
214 LOG_TRACE("called for context:%p", context);
215
216 TSS2_RC r;
217
218 /* Check for NULL parameters */
219 check_not_null(context);
220
221 /* Helpful alias pointers */
222 IFAPI_Key_Create * command = &context->cmd.Key_Create;
223
224 switch (context->state) {
225 statecase(context->state, KEY_CREATE);
226 /* Finish the key creation inside the helper function. */
227 r = ifapi_key_create(context, &command->public_templ);
228 return_try_again(r);
229 goto_if_error(r, "Key create", error_cleanup);
230
231 /* Cleanup any intermediate results and state stored in the context. */
232 ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
233 ifapi_cleanup_ifapi_object(context->loadKey.key_object);
234 ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
235 context->state = _FAPI_STATE_INIT;
236 LOG_TRACE("finished");
237 return TSS2_RC_SUCCESS;
238
239 statecasedefault(context->state);
240 }
241
242 error_cleanup:
243 /* Cleanup any intermediate results and state stored in the context. */
244 context->cmd.Key_Create.state = KEY_CREATE_INIT;
245 ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
246 ifapi_cleanup_ifapi_object(context->loadKey.key_object);
247 ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
248 LOG_TRACE("finished");
249 return r;
250 }
251