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