• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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