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 "tss2_esys.h"
21 #define LOGMODULE fapi
22 #include "util/log.h"
23 #include "util/aux_util.h"
24
25 /** One-Call function for Fapi_GetAppData
26 *
27 * Every object has a description field that can be retrieved in order to obtain
28 * additional information in its “path” entry.
29 *
30 * @param[in,out] context The FAPI_CONTEXT
31 * @param[in] path The path to the object for which the appData is returned
32 * @param[out] appData A copy of the appData. May be NULL (callee-allocated)
33 * @param[out] appDataSize The size of the returned AppData. May be NULL
34 *
35 * @retval TSS2_RC_SUCCESS: if the function call was a success.
36 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
37 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
38 * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
39 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
40 * operation already pending.
41 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
42 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
43 * internal operations or return parameters.
44 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
45 * config file.
46 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
47 * during authorization.
48 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
49 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
50 * the function.
51 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
52 * this function needs to be called again.
53 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
54 */
55 TSS2_RC
Fapi_GetAppData(FAPI_CONTEXT * context,char const * path,uint8_t ** appData,size_t * appDataSize)56 Fapi_GetAppData(
57 FAPI_CONTEXT *context,
58 char const *path,
59 uint8_t **appData,
60 size_t *appDataSize)
61 {
62 LOG_TRACE("called for context:%p", context);
63
64 TSS2_RC r;
65
66 /* Check for NULL parameters */
67 check_not_null(context);
68 check_not_null(path);
69
70 r = Fapi_GetAppData_Async(context, path);
71 return_if_error_reset_state(r, "Path_SetDescription");
72
73 do {
74 /* We wait for file I/O to be ready if the FAPI state automata
75 are in a file I/O state. */
76 r = ifapi_io_poll(&context->io);
77 return_if_error(r, "Something went wrong with IO polling");
78
79 /* Repeatedly call the finish function, until FAPI has transitioned
80 through all execution stages / states of this invocation. */
81 r = Fapi_GetAppData_Finish(context, appData, appDataSize);
82 } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
83
84 return_if_error_reset_state(r, "Path_SetDescription");
85
86 LOG_TRACE("finished");
87 return TSS2_RC_SUCCESS;
88 }
89
90 /** Asynchronous function for Fapi_GetAppData
91 *
92 * Every object has a description field that can be retrieved in order to obtain
93 * additional information in its “path” entry.
94 *
95 * Call Fapi_GetAppData_Finish to finish the execution of this command.
96 *
97 * @param[in,out] context The FAPI_CONTEXT
98 * @param[in] path The path to the object for which the appData is returned
99 *
100 * @retval TSS2_RC_SUCCESS: if the function call was a success.
101 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
102 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
103 * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
104 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
105 * operation already pending.
106 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
107 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
108 * internal operations or return parameters.
109 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
110 * config file.
111 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
112 * during authorization.
113 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
114 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
115 * the function.
116 */
117 TSS2_RC
Fapi_GetAppData_Async(FAPI_CONTEXT * context,char const * path)118 Fapi_GetAppData_Async(
119 FAPI_CONTEXT *context,
120 char const *path)
121 {
122 LOG_TRACE("called for context:%p", context);
123 LOG_TRACE("path: %s", path);
124
125 TSS2_RC r;
126
127 /* Check for NULL parameters */
128 check_not_null(context);
129 check_not_null(path);
130
131 /* Reset all context-internal session state information. */
132 r = ifapi_session_init(context);
133 return_if_error(r, "Initialize GetAppData");
134
135 /* Load the object metadata from keystore. */
136 r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
137 return_if_error2(r, "Could not open: %s", path);
138
139 context->state = PATH_GET_DESCRIPTION_READ;
140 LOG_TRACE("finished");
141 return TSS2_RC_SUCCESS;
142 }
143
144 /** Asynchronous finish function for Fapi_GetAppData
145 *
146 * This function should be called after a previous Fapi_GetAppData_Async.
147 *
148 * @param[in,out] context The FAPI_CONTEXT
149 * @param[out] appData A copy of the appData. May be Null (callee-allocated)
150 * @param[out] appDataSize The size of the returned AppData. May be NULL
151 *
152 * @retval TSS2_RC_SUCCESS: if the function call was a success.
153 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
154 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
155 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
156 * operation already pending.
157 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
158 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
159 * internal operations or return parameters.
160 * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
161 * complete. Call this function again later.
162 * @retval TSS2_FAPI_RC_BAD_PATH if the used path in inappropriate-
163 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
164 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
165 * the function.
166 */
167 TSS2_RC
Fapi_GetAppData_Finish(FAPI_CONTEXT * context,uint8_t ** appData,size_t * appDataSize)168 Fapi_GetAppData_Finish(
169 FAPI_CONTEXT *context,
170 uint8_t **appData,
171 size_t *appDataSize)
172 {
173 LOG_TRACE("called for context:%p", context);
174
175 TSS2_RC r;
176 IFAPI_OBJECT object;
177 UINT8_ARY *objAppData;
178
179 /* Check for NULL parameters */
180 check_not_null(context);
181
182 switch (context->state) {
183 statecase(context->state, PATH_GET_DESCRIPTION_READ);
184 r = ifapi_keystore_load_finish(&context->keystore, &context->io, &object);
185 return_try_again(r);
186 return_if_error_reset_state(r, "read_finish failed");
187
188 /* Get the application data from the metadata objects. */
189 switch (object.objectType) {
190 case IFAPI_KEY_OBJ:
191 objAppData = &object.misc.key.appData;
192 break;
193 case IFAPI_NV_OBJ:
194 objAppData = &object.misc.nv.appData;
195 break;
196 default:
197 goto_error(r, TSS2_FAPI_RC_BAD_PATH, "Object has no app data.", cleanup);
198 }
199
200 if (appData) {
201 /* Duplicate the application data to be returned to the caller. */
202 if (objAppData->size) {
203 *appData = malloc(objAppData->size);
204 goto_if_null2(*appData, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
205 cleanup);
206 memcpy(*appData, &objAppData->buffer[0],
207 objAppData->size);
208 } else {
209 *appData = NULL;
210 }
211 }
212 if (appDataSize)
213 *appDataSize = objAppData->size;
214
215 context->state = _FAPI_STATE_INIT;
216 r = TSS2_RC_SUCCESS;
217 break;
218
219 statecasedefault(context->state);
220 }
221
222 cleanup:
223 /* Cleanup any intermediate results and state stored in the context. */
224 ifapi_cleanup_ifapi_object(&object);
225 ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
226 ifapi_cleanup_ifapi_object(context->loadKey.key_object);
227 ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
228 LOG_TRACE("finished");
229 return r;
230 }
231