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 <string.h>
13 #include <unistd.h>
14 #include <errno.h>
15
16 #include "tss2_mu.h"
17 #include "tss2_fapi.h"
18 #include "fapi_int.h"
19 #include "fapi_util.h"
20 #include "tss2_esys.h"
21 #include "ifapi_policy_json_serialize.h"
22 #define LOGMODULE fapi
23 #include "util/log.h"
24 #include "util/aux_util.h"
25
26
27 /** One-Call function for Fapi_GetTpmBlobs
28 *
29 * Get the public and private blobs of a TPM object. They can be loaded with a
30 * lower-level API such as the SAPI or the ESAPI.
31 *
32 * @param[in,out] context The FAPI_CONTEXT
33 * @param[in] path The path to the key for which the blobs will be returned
34 * @param[out] tpm2bPublic The returned public area of the object. May be NULL
35 * @param[out] tpm2bPublicSize The size of tpm2bPublic in bytes. May be NULL
36 * @param[out] tpm2bPrivate The returned private area of the object. May be
37 * NULL
38 * @param[out] tpm2bPrivateSize The size of tpm2bPrivate in bytes. May be NULL
39 * @param[out] policy The policy that is associated with the object encoded in
40 * JSON. May be 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_BAD_PATH: if path does not map to a FAPI entity.
46 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
47 * operation already pending.
48 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
49 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
50 * internal operations or return parameters.
51 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
52 * during authorization.
53 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
54 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
55 * the function.
56 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
57 * this function needs to be called again.
58 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
59 */
60 TSS2_RC
Fapi_GetTpmBlobs(FAPI_CONTEXT * context,char const * path,uint8_t ** tpm2bPublic,size_t * tpm2bPublicSize,uint8_t ** tpm2bPrivate,size_t * tpm2bPrivateSize,char ** policy)61 Fapi_GetTpmBlobs(
62 FAPI_CONTEXT *context,
63 char const *path,
64 uint8_t **tpm2bPublic,
65 size_t *tpm2bPublicSize,
66 uint8_t **tpm2bPrivate,
67 size_t *tpm2bPrivateSize,
68 char **policy)
69 {
70 LOG_TRACE("called for context:%p", context);
71
72 TSS2_RC r;
73
74 /* Check for NULL parameters */
75 check_not_null(context);
76 check_not_null(path);
77
78 r = Fapi_GetTpmBlobs_Async(context, path);
79 return_if_error_reset_state(r, "Entity_GetTPMBlobs");
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_GetTpmBlobs_Finish(context, tpm2bPublic, tpm2bPublicSize, tpm2bPrivate,
90 tpm2bPrivateSize, policy);
91 } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
92
93 return_if_error_reset_state(r, "Entity_GetTPMBlobs");
94
95 LOG_TRACE("finished");
96 return TSS2_RC_SUCCESS;
97 }
98
99 /** Asynchronous function for Fapi_GetTpmBlobs
100 *
101 * Get the public and private blobs of a TPM object. They can be loaded with a
102 * lower-level API such as the SAPI or the ESAPI.
103 *
104 * Call Fapi_GetTpmBlobs_Finish to finish the execution of this command.
105 *
106 * @param[in,out] context The FAPI_CONTEXT
107 * @param[in] path The path to the key for which the blobs will be returned
108 *
109 * @retval TSS2_RC_SUCCESS: if the function call was a success.
110 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
111 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
112 * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
113 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
114 * operation already pending.
115 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
116 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
117 * internal operations or return parameters.
118 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
119 * during authorization.
120 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
121 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
122 * the function.
123 */
124 TSS2_RC
Fapi_GetTpmBlobs_Async(FAPI_CONTEXT * context,char const * path)125 Fapi_GetTpmBlobs_Async(
126 FAPI_CONTEXT *context,
127 char const *path)
128 {
129 LOG_TRACE("called for context:%p", context);
130 LOG_TRACE("path: %s", path);
131
132 TSS2_RC r;
133
134 /* Check for NULL parameters */
135 check_not_null(context);
136 check_not_null(path);
137
138 /* Load the object from the key store. */
139 r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
140 return_if_error2(r, "Could not open: %s", path);
141
142 /* Initialize the context state for this operation. */
143 context->state = ENTITY_GET_TPM_BLOBS_READ;
144 LOG_TRACE("finished");
145 return TSS2_RC_SUCCESS;
146 }
147
148 /** Asynchronous finish function for Fapi_GetTpmBlobs
149 *
150 * This function should be called after a previous Fapi_GetTpmBlobs_Async.
151 *
152 * @param[in,out] context The FAPI_CONTEXT
153 * @param[out] tpm2bPublic The returned public area of the object. May be NULL
154 * @param[out] tpm2bPublicSize The size of tpm2bPublic in bytes. May be NULL
155 * @param[out] tpm2bPrivate The returned private area of the object. May be
156 * NULL
157 * @param[out] tpm2bPrivateSize The size of tpm2bPrivate in bytes. May be NULL
158 * @param[out] policy The policy that is associated with the object encoded in
159 * JSON. May be NULL
160 *
161 * @retval TSS2_RC_SUCCESS: if the function call was a success.
162 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
163 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
164 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
165 * operation already pending.
166 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
167 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
168 * internal operations or return parameters.
169 * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
170 * complete. Call this function again later.
171 * @retval TSS2_FAPI_RC_BAD_PATH if the used path in inappropriate-
172 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
173 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
174 * the function.
175 */
176 TSS2_RC
Fapi_GetTpmBlobs_Finish(FAPI_CONTEXT * context,uint8_t ** tpm2bPublic,size_t * tpm2bPublicSize,uint8_t ** tpm2bPrivate,size_t * tpm2bPrivateSize,char ** policy)177 Fapi_GetTpmBlobs_Finish(
178 FAPI_CONTEXT *context,
179 uint8_t **tpm2bPublic,
180 size_t *tpm2bPublicSize,
181 uint8_t **tpm2bPrivate,
182 size_t *tpm2bPrivateSize,
183 char **policy)
184 {
185 LOG_TRACE("called for context:%p", context);
186
187 TSS2_RC r;
188 IFAPI_OBJECT object;
189 UINT16 private_size;
190 size_t offset;
191 json_object *jso = NULL;
192
193 /* Check for NULL parameters */
194 check_not_null(context);
195
196 switch (context->state) {
197 statecase(context->state, ENTITY_GET_TPM_BLOBS_READ);
198 /* Finish readon the metadata from key store. */
199 r = ifapi_keystore_load_finish(&context->keystore, &context->io, &object);
200 return_try_again(r);
201 return_if_error_reset_state(r, "read_finish failed");
202
203 if (object.objectType != IFAPI_KEY_OBJ) {
204 goto_error(r, TSS2_FAPI_RC_BAD_PATH, "No key object.", error_cleanup);
205 }
206
207 /* Marshal the public data to the output parameter. */
208 if (tpm2bPublic && tpm2bPublicSize) {
209 *tpm2bPublic = malloc(sizeof(uint8_t) * sizeof(TPM2B_PUBLIC));
210 goto_if_null(*tpm2bPublic, "Out of memory.",
211 TSS2_FAPI_RC_MEMORY, error_cleanup);
212 offset = 0;
213 r = Tss2_MU_TPM2B_PUBLIC_Marshal(&object.misc.key.public,
214 *tpm2bPublic, sizeof(TPM2B_PUBLIC), &offset);
215 goto_if_error_reset_state(r, "FAPI marshal TPM2B_PUBLIC",
216 error_cleanup);
217
218 *tpm2bPublicSize = offset;
219 goto_if_error(r, "Marshaling TPM2B_PUBLIC", error_cleanup);
220 }
221
222 /* Marshal the private data to the output parameter. */
223 if (tpm2bPrivate && tpm2bPrivateSize) {
224 private_size = object.misc.key.private.size;
225 *tpm2bPrivateSize = private_size + sizeof(UINT16);
226 *tpm2bPrivate = malloc(*tpm2bPrivateSize);
227 goto_if_null(*tpm2bPrivate, "Out of memory.",
228 TSS2_FAPI_RC_MEMORY, error_cleanup);
229 offset = 0;
230 r = Tss2_MU_UINT16_Marshal(private_size,
231 *tpm2bPrivate, sizeof(TPM2B_PRIVATE), &offset);
232 goto_if_error_reset_state(r, "FAPI marshal UINT16", error_cleanup);
233
234 memcpy(*tpm2bPrivate + offset, &object.misc.key.private.buffer[0], private_size);
235 }
236
237 /* Duplicate the policy to the output parameter. */
238 if (object.policy && policy) {
239 r = ifapi_json_TPMS_POLICY_serialize(
240 object.policy, &jso);
241 goto_if_error(r, "Serialize policy", error_cleanup);
242
243 strdup_check(*policy,
244 json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY),
245 r, error_cleanup);
246 json_object_put(jso);
247 }
248
249 /* Cleanup any intermediate results and state stored in the context. */
250 ifapi_cleanup_ifapi_object(&object);
251 context->state = _FAPI_STATE_INIT;
252 LOG_TRACE("finished");
253 return TSS2_RC_SUCCESS;
254
255 statecasedefault(context->state);
256 }
257 error_cleanup:
258 /* Cleanup any intermediate results and state stored in the context. */
259 if (jso)
260 json_object_put(jso);
261 ifapi_cleanup_ifapi_object(&object);
262 ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
263 ifapi_cleanup_ifapi_object(context->loadKey.key_object);
264 ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
265 LOG_TRACE("finished");
266 return r;
267 }
268