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
18 #include "tss2_fapi.h"
19 #include "fapi_int.h"
20 #include "fapi_util.h"
21 #include "tss2_esys.h"
22 #define LOGMODULE fapi
23 #include "util/log.h"
24 #include "util/aux_util.h"
25 #include "fapi_crypto.h"
26
27 /** One-Call function for Fapi_GetCertificate
28 *
29 * Gets an x.509 certificate for the key at a given path.
30 *
31 * @param[in,out] context The FAPI_CONTEXT
32 * @param[in] path The path to the key whose certificate is created
33 * @param[out] x509certData The PEM-encoded certificate
34 *
35 * @retval TSS2_RC_SUCCESS: if the function call was a success.
36 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, path or x509CertData is
37 * NULL.
38 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
39 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND: if path does not map to a FAPI entity.
40 * @retval TSS2_FAPI_RC_BAD_KEY: if the key is unsuitable for the requested
41 * operation.
42 * @retval TSS2_FAPI_RC_NO_CERTIFICATE: if there is not a x.509 cert associated
43 * with the path of the key.
44 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
45 * operation already pending.
46 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
47 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
48 * internal operations or return parameters.
49 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
50 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
51 * the function.
52 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
53 * this function needs to be called again.
54 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
55 */
56 TSS2_RC
Fapi_GetCertificate(FAPI_CONTEXT * context,char const * path,char ** x509certData)57 Fapi_GetCertificate(
58 FAPI_CONTEXT *context,
59 char const *path,
60 char **x509certData)
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 check_not_null(x509certData);
70
71 r = Fapi_GetCertificate_Async(context, path);
72 return_if_error_reset_state(r, "Key_GetCertificate");
73
74 do {
75 /* We wait for file I/O to be ready if the FAPI state automata
76 are in a file I/O state. */
77 r = ifapi_io_poll(&context->io);
78 return_if_error(r, "Something went wrong with IO polling");
79
80 /* Repeatedly call the finish function, until FAPI has transitioned
81 through all execution stages / states of this invocation. */
82 r = Fapi_GetCertificate_Finish(context, x509certData);
83 } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
84
85 return_if_error_reset_state(r, "Key_GetCertificate");
86
87 LOG_TRACE("finished");
88 return TSS2_RC_SUCCESS;
89 }
90
91 /** Asynchronous function for Fapi_GetCertificate
92 *
93 * Gets an x.509 certificate for the key at a given path.
94 *
95 * Call Fapi_GetCertificate_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 key whose certificate is created
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_PATH_NOT_FOUND: if path does not map to a FAPI entity.
104 * @retval TSS2_FAPI_RC_BAD_KEY: if the key is unsuitable for the requested
105 * operation.
106 * @retval TSS2_FAPI_RC_NO_CERTIFICATE: if there is not a x.509 cert associated
107 * with the path of the key.
108 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
109 * operation already pending.
110 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
111 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
112 * internal operations or return parameters.
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_GetCertificate_Async(FAPI_CONTEXT * context,char const * path)118 Fapi_GetCertificate_Async(
119 FAPI_CONTEXT *context,
120 char const *path)
121
122 {
123 LOG_TRACE("called for context:%p", context);
124 LOG_TRACE("path: %s", path);
125
126 TSS2_RC r;
127
128 /* Check for NULL parameters */
129 check_not_null(context);
130 check_not_null(path);
131
132 r = ifapi_non_tpm_mode_init(context);
133 return_if_error(r, "Initialize GetCertificate");
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 /* Initialize the context state for this operation. */
140 context->state = KEY_GET_CERTIFICATE_READ;
141
142 LOG_TRACE("finished");
143 return TSS2_RC_SUCCESS;
144 }
145
146 /** Asynchronous finish function for Fapi_GetCertificate
147 *
148 * This function should be called after a previous Fapi_GetCertificate_Async.
149 *
150 * @param[in,out] context The FAPI_CONTEXT
151 * @param[out] x509certData The PEM-encoded certificate
152 *
153 * @retval TSS2_RC_SUCCESS: if the function call was a success.
154 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or x509certData is NULL.
155 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
156 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
157 * operation already pending.
158 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
159 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
160 * internal operations or return parameters.
161 * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
162 * complete. Call this function again later.
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_GetCertificate_Finish(FAPI_CONTEXT * context,char ** x509certData)168 Fapi_GetCertificate_Finish(
169 FAPI_CONTEXT *context,
170 char **x509certData)
171 {
172 LOG_TRACE("called for context:%p", context);
173
174 TSS2_RC r;
175
176 /* Check for NULL parameters */
177 check_not_null(context);
178 check_not_null(x509certData);
179
180 /* Helpful alias pointers */
181 IFAPI_Key_SetCertificate *command = &context->cmd.Key_SetCertificate;
182 IFAPI_OBJECT *keyObject = &command->key_object;
183
184 switch (context->state) {
185 statecase(context->state, KEY_GET_CERTIFICATE_READ)
186 r = ifapi_keystore_load_finish(&context->keystore, &context->io, keyObject);
187 return_try_again(r);
188 return_if_error_reset_state(r, "read_finish failed");
189
190 /* Retrieve the appropriate field from the objects and duplicate its
191 content to be returned to the user. */
192 if (keyObject->objectType == IFAPI_EXT_PUB_KEY_OBJ) {
193 strdup_check(*x509certData, keyObject->misc.ext_pub_key.certificate,
194 r, error_cleanup);
195 } else if (x509certData) {
196 strdup_check(*x509certData, keyObject->misc.key.certificate,
197 r, error_cleanup);
198 }
199
200 context->state = _FAPI_STATE_INIT;
201 r = TSS2_RC_SUCCESS;
202 break;
203
204 statecasedefault(context->state);
205 }
206
207 error_cleanup:
208 /* Cleanup any intermediate results and state stored in the context. */
209 if (keyObject->objectType) {
210 ifapi_cleanup_ifapi_object(keyObject);
211 }
212 ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
213 ifapi_cleanup_ifapi_object(context->loadKey.key_object);
214 ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
215
216 LOG_TRACE("finished");
217 return r;
218 }
219