xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/api/Fapi_GetRandom.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
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 
14 #include "tss2_fapi.h"
15 #include "fapi_int.h"
16 #include "fapi_util.h"
17 #include "tss2_esys.h"
18 #define LOGMODULE fapi
19 #include "util/log.h"
20 #include "util/aux_util.h"
21 
22 /** One-Call function for Fapi_GetRandom
23  *
24  * Creates an array with a specified number of bytes. May execute the underlying
25  * TPM command multiple times if the requested number of bytes is too big.
26  *
27  * @param[in,out] context The FAPI_CONTEXT
28  * @param[in] numBytes The number of bytes requested from the TPM
29  * @param[out] data The array of random bytes returned from the TPM
30  *
31  * @retval TSS2_RC_SUCCESS: if the function call was a success.
32  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or data is NULL.
33  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
34  * @retval TSS2_FAPI_RC_BAD_VALUE: if numBytes is 0.
35  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
36  *         operation already pending.
37  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
38  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
39  *         internal operations or return parameters.
40  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
41  *         config file.
42  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
43  *         during authorization.
44  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
45  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
46  *         this function needs to be called again.
47  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
48  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
49  *         is not set.
50  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
51  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
52  *         was not successful.
53  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
54  */
55 TSS2_RC
Fapi_GetRandom(FAPI_CONTEXT * context,size_t numBytes,uint8_t ** data)56 Fapi_GetRandom(
57     FAPI_CONTEXT *context,
58     size_t        numBytes,
59     uint8_t     **data)
60 {
61     LOG_TRACE("called for context:%p", context);
62 
63     TSS2_RC r, r2;
64 
65     /* Check for NULL parameters */
66     check_not_null(context);
67     check_not_null(data);
68 
69     /* Check whether TCTI and ESYS are initialized */
70     return_if_null(context->esys, "Command can't be executed in none TPM mode.",
71                    TSS2_FAPI_RC_NO_TPM);
72 
73     /* If the async state automata of FAPI shall be tested, then we must not set
74        the timeouts of ESYS to blocking mode.
75        During testing, the mssim tcti will ensure multiple re-invocations.
76        Usually however the synchronous invocations of FAPI shall instruct ESYS
77        to block until a result is available. */
78 #ifndef TEST_FAPI_ASYNC
79     r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
80     return_if_error_reset_state(r, "Set Timeout to blocking");
81 #endif /* TEST_FAPI_ASYNC */
82 
83     r = Fapi_GetRandom_Async(context, numBytes);
84     return_if_error_reset_state(r, "GetRandom");
85 
86     do {
87         /* We wait for file I/O to be ready if the FAPI state automata
88            are in a file I/O state. */
89         r = ifapi_io_poll(&context->io);
90         return_if_error(r, "Something went wrong with IO polling");
91 
92         /* Repeatedly call the finish function, until FAPI has transitioned
93            through all execution stages / states of this invocation. */
94         r = Fapi_GetRandom_Finish(context, data);
95     } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
96 
97     /* Reset the ESYS timeout to non-blocking, immediate response. */
98     r2 = Esys_SetTimeout(context->esys, 0);
99     return_if_error(r2, "Set Timeout to non-blocking");
100 
101     return_if_error_reset_state(r, "GetRandom");
102 
103     LOG_TRACE("finished");
104     return TSS2_RC_SUCCESS;
105 }
106 
107 /** Asynchronous function for Fapi_GetRandom
108  *
109  * Creates an array with a specified number of bytes. May execute the underlying
110  * TPM command multiple times if the requested number of bytes is too big.
111  *
112  * Call Fapi_GetRandom_Finish to finish the execution of this command.
113  *
114  * @param[in,out] context The FAPI_CONTEXT
115  * @param[in] numBytes The number of bytes requested from the TPM
116  *
117  * @retval TSS2_RC_SUCCESS: if the function call was a success.
118  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
119  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
120  * @retval TSS2_FAPI_RC_BAD_VALUE: if numBytes is 0.
121  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
122  *         operation already pending.
123  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
124  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
125  *         internal operations or return parameters.
126  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
127  *         config file.
128  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
129  *         during authorization.
130  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
131  */
132 TSS2_RC
Fapi_GetRandom_Async(FAPI_CONTEXT * context,size_t numBytes)133 Fapi_GetRandom_Async(
134     FAPI_CONTEXT *context,
135     size_t        numBytes)
136 {
137     LOG_TRACE("called for context:%p", context);
138     LOG_TRACE("numBytes: %zu", numBytes);
139 
140     TSS2_RC r;
141 
142     /* Check for NULL parameters */
143     check_not_null(context);
144 
145     /* Helpful alias pointers */
146     IFAPI_GetRandom * command = &context->get_random;
147 
148     /* Reset all context-internal session state information. */
149     r = ifapi_session_init(context);
150     return_if_error(r, "Initialize GetRandom");
151 
152     /* Copy parameters to context for use during _Finish. */
153     command->numBytes = numBytes;
154     command->data = NULL;
155 
156     /* Start a session for integrity protection and encryption of random data. */
157     r = ifapi_get_sessions_async(context,
158                                  IFAPI_SESSION_GENEK | IFAPI_SESSION1,
159                                  TPMA_SESSION_ENCRYPT | TPMA_SESSION_DECRYPT, 0);
160     return_if_error_reset_state(r, "Create FAPI session");
161 
162     /* Initialize the context state for this operation. */
163     context->state = GET_RANDOM_WAIT_FOR_SESSION;
164     LOG_TRACE("finished");
165     return TSS2_RC_SUCCESS;
166 }
167 
168 /** Asynchronous finish function for Fapi_GetRandom
169  *
170  * This function should be called after a previous Fapi_GetRandom_Async.
171  *
172  * @param[in,out] context The FAPI_CONTEXT
173  * @param[out] data The array of random bytes returned from the TPM
174  *
175  * @retval TSS2_RC_SUCCESS: if the function call was a success.
176  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or data is NULL.
177  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
178  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
179  *         operation already pending.
180  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
181  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
182  *         internal operations or return parameters.
183  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
184  *         complete. Call this function again later.
185  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
186  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
187  *         the function.
188  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
189  *         during authorization.
190  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
191  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
192  *         is not set.
193  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
194  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
195  *         was not successful.
196  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
197  */
198 TSS2_RC
Fapi_GetRandom_Finish(FAPI_CONTEXT * context,uint8_t ** data)199 Fapi_GetRandom_Finish(
200     FAPI_CONTEXT *context,
201     uint8_t     **data)
202 {
203     LOG_TRACE("called for context:%p", context);
204 
205     TSS2_RC r;
206 
207     /* Check for NULL parameters */
208     check_not_null(context);
209     check_not_null(data);
210 
211     /* Helpful alias pointers */
212     IFAPI_GetRandom * command = &context->get_random;
213 
214     switch (context->state) {
215         statecase(context->state, GET_RANDOM_WAIT_FOR_SESSION);
216         r = ifapi_get_sessions_finish(context, &context->profiles.default_profile,
217                                       context->profiles.default_profile.nameAlg);
218             return_try_again(r);
219             goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
220 
221             context->get_random_state = GET_RANDOM_INIT;
222 
223             fallthrough;
224 
225         statecase(context->state, GET_RANDOM_WAIT_FOR_RANDOM);
226             /* Retrieve the random data from the TPM.
227                This may involve several Esys_GetRandom calls. */
228             r = ifapi_get_random(context, command->numBytes, data);
229             return_try_again(r);
230             goto_if_error_reset_state(r, "FAPI GetRandom", error_cleanup);
231             fallthrough;
232 
233         statecase(context->state, GET_RANDOM_CLEANUP)
234             /* Cleanup the session. */
235             r = ifapi_cleanup_session(context);
236             try_again_or_error_goto(r, "Cleanup", error_cleanup);
237 
238             break;
239 
240         statecasedefault(context->state);
241     }
242 
243     /* Cleanup any intermediate results and state stored in the context. */
244     context->state = _FAPI_STATE_INIT;
245     ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
246     ifapi_session_clean(context);
247     LOG_TRACE("finished");
248     return TSS2_RC_SUCCESS;
249 
250 error_cleanup:
251     /* Cleanup any intermediate results and state stored in the context. */
252     ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
253     ifapi_session_clean(context);
254     SAFE_FREE(context->get_random.data);
255     LOG_TRACE("finished");
256     return r;
257 }
258