xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/api/Fapi_GetInfo.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 <json-c/json_util.h>
12 #include <json-c/json_tokener.h>
13 #include <string.h>
14 
15 #include "ifapi_json_serialize.h"
16 #include "tss2_fapi.h"
17 #include "fapi_int.h"
18 #include "fapi_util.h"
19 #include "tss2_esys.h"
20 #define LOGMODULE fapi
21 #include "util/log.h"
22 #include "util/aux_util.h"
23 
24 typedef struct {
25     char *description;
26     TPMI_POLICYTYPE capability;
27     UINT32 property;
28     UINT32 max;
29 } IFAPI_INFO_CAP;
30 
31 static IFAPI_INFO_CAP info_cap_tab[] = {
32     { "algorithms", TPM2_CAP_ALGS,  TPM2_ALG_FIRST, TPM2_MAX_CAP_ALGS},
33     { "handles-transient", TPM2_CAP_HANDLES, TPM2_TRANSIENT_FIRST, TPM2_MAX_CAP_HANDLES},
34     { "handles-persistent", TPM2_CAP_HANDLES, TPM2_PERSISTENT_FIRST, TPM2_MAX_CAP_HANDLES},
35     { "handles-permanent", TPM2_CAP_HANDLES, TPM2_PERMANENT_FIRST, TPM2_MAX_CAP_HANDLES},
36     { "handles-pcr", TPM2_CAP_HANDLES, TPM2_PCR_FIRST, TPM2_MAX_CAP_HANDLES},
37     { "handles-nv-index", TPM2_CAP_HANDLES, TPM2_NV_INDEX_FIRST, TPM2_MAX_CAP_HANDLES},
38     { "handles-loaded-session", TPM2_CAP_HANDLES, TPM2_LOADED_SESSION_FIRST, TPM2_MAX_CAP_HANDLES},
39     { "handles-action-session", TPM2_CAP_HANDLES, TPM2_ACTIVE_SESSION_FIRST, TPM2_MAX_CAP_HANDLES},
40     { "handles-saved-session", TPM2_CAP_HANDLES, TPM2_ACTIVE_SESSION_FIRST, TPM2_MAX_CAP_HANDLES},
41     { "properties-fixed", TPM2_CAP_TPM_PROPERTIES, TPM2_PT_FIXED, TPM2_MAX_TPM_PROPERTIES },
42     { "properties-variable", TPM2_CAP_TPM_PROPERTIES, TPM2_PT_VAR, TPM2_MAX_TPM_PROPERTIES },
43     { "commands", TPM2_CAP_COMMANDS, TPM2_CC_FIRST, TPM2_MAX_CAP_CC },
44     { "pp-commands", TPM2_CAP_PP_COMMANDS, TPM2_CC_FIRST, TPM2_MAX_CAP_CC },
45     { "audit-commands", TPM2_CAP_AUDIT_COMMANDS, TPM2_CC_FIRST, TPM2_MAX_CAP_CC },
46     { "pcrs", TPM2_CAP_PCRS, 0, TPM2_NUM_PCR_BANKS },
47     { "pcr-properties", TPM2_CAP_PCR_PROPERTIES, TPM2_PCR_FIRST, TPM2_MAX_PCR_PROPERTIES },
48     { "ecc-curves", TPM2_CAP_ECC_CURVES, 0, TPM2_MAX_ECC_CURVES },
49 };
50 
51 /** One-Call function for Fapi_GetInfo
52  *
53  * Returns a UTF-8 encoded string that identifies the versions of FAPI, TPM,
54  * configurations and other relevant information.
55  *
56  * @param[in,out] context The FAPI_CONTEXT
57  * @param[out] info The byte buffer for the information string
58  *
59  * @retval TSS2_RC_SUCCESS: if the function call was a success.
60  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or info is NULL.
61  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
62  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
63  *         operation already pending.
64  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
65  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
66  *         internal operations or return parameters.
67  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
68  *         config file.
69  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
70  *         this function needs to be called again.
71  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
72  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
73  *         the function.
74  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
75  */
76 TSS2_RC
Fapi_GetInfo(FAPI_CONTEXT * context,char ** info)77 Fapi_GetInfo(
78     FAPI_CONTEXT *context,
79     char        **info)
80 {
81     LOG_TRACE("called for context:%p", context);
82 
83     TSS2_RC r, r2;
84 
85     /* Check for NULL parameters */
86     check_not_null(context);
87     check_not_null(info);
88 
89     /* Check whether TCTI and ESYS are initialized */
90     return_if_null(context->esys, "Command can't be executed in none TPM mode.",
91                    TSS2_FAPI_RC_NO_TPM);
92 
93     /* If the async state automata of FAPI shall be tested, then we must not set
94        the timeouts of ESYS to blocking mode.
95        During testing, the mssim tcti will ensure multiple re-invocations.
96        Usually however the synchronous invocations of FAPI shall instruct ESYS
97        to block until a result is available. */
98 #ifndef TEST_FAPI_ASYNC
99     r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
100     return_if_error_reset_state(r, "Set Timeout to blocking");
101 #endif /* TEST_FAPI_ASYNC */
102 
103     r = Fapi_GetInfo_Async(context);
104     return_if_error_reset_state(r, "GetTPMInfo");
105 
106     do {
107         /* We wait for file I/O to be ready if the FAPI state automata
108            are in a file I/O state. */
109         r = ifapi_io_poll(&context->io);
110         return_if_error(r, "Something went wrong with IO polling");
111 
112         /* Repeatedly call the finish function, until FAPI has transitioned
113            through all execution stages / states of this invocation. */
114         r = Fapi_GetInfo_Finish(context, info);
115     } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
116 
117     /* Reset the ESYS timeout to non-blocking, immediate response. */
118     r2 = Esys_SetTimeout(context->esys, 0);
119     return_if_error(r2, "Set Timeout to non-blocking");
120 
121     return_if_error_reset_state(r, "GetTPMInfo");
122 
123     LOG_TRACE("finished");
124     return TSS2_RC_SUCCESS;
125 }
126 
127 /** Asynchronous function for Fapi_GetInfo
128  *
129  * Returns a UTF-8 encoded string that identifies the versions of FAPI, TPM,
130  * configurations and other relevant information.
131  *
132  * Call Fapi_GetInfo_Finish to finish the execution of this command.
133  *
134  * @param[in,out] context The FAPI_CONTEXT
135  *
136  * @retval TSS2_RC_SUCCESS: if the function call was a success.
137  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
138  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
139  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
140  *         operation already pending.
141  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
142  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
143  *         internal operations or return parameters.
144  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
145  *         config file.
146  */
147 TSS2_RC
Fapi_GetInfo_Async(FAPI_CONTEXT * context)148 Fapi_GetInfo_Async(
149     FAPI_CONTEXT *context)
150 {
151     LOG_TRACE("called for context:%p", context);
152 
153     TSS2_RC r;
154 
155     /* Check for NULL parameters */
156     check_not_null(context);
157 
158     /* Helpful alias pointers */
159     IFAPI_GetInfo * command = &context->cmd.GetInfo;
160 
161     /* Reset all context-internal session state information. */
162     r = ifapi_session_init(context);
163     return_if_error(r, "Initialize GetInfo");
164 
165     memset(command, 0, sizeof(IFAPI_GetInfo));
166     r = ifapi_capability_init(context);
167     return_if_error(r, "Capability init");
168 
169     /* Initialize the context state for this operation. */
170     command->idx_info_cap = 0;
171     context->state = GET_INFO_GET_CAP;
172 
173     LOG_TRACE("finished");
174     return TSS2_RC_SUCCESS;
175 }
176 
177 /** Asynchronous finish function for Fapi_GetInfo
178  *
179  * This function should be called after a previous Fapi_GetInfo_Async.
180  *
181  * @param[in,out] context The FAPI_CONTEXT
182  * @param[out] info The byte buffer for the information string
183  *
184  * @retval TSS2_RC_SUCCESS: if the function call was a success.
185  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or info is NULL.
186  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
187  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
188  *         operation already pending.
189  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
190  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
191  *         internal operations or return parameters.
192  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
193  *         complete. Call this function again later.
194  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
195  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
196  *         the function.
197  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
198  */
199 TSS2_RC
Fapi_GetInfo_Finish(FAPI_CONTEXT * context,char ** info)200 Fapi_GetInfo_Finish(
201     FAPI_CONTEXT *context,
202     char        **info)
203 {
204     LOG_TRACE("called for context:%p", context);
205 
206     TSS2_RC r;
207     json_object *jso = NULL;
208     size_t capIdx;
209 
210     /* Check for NULL parameters */
211     check_not_null(context);
212     check_not_null(info);
213 
214     /* Helpful alias pointers */
215     IFAPI_GetInfo * command = &context->cmd.GetInfo;
216     IFAPI_INFO *infoObj = &command->info_obj;
217     TPMS_CAPABILITY_DATA *capabilityData = NULL;
218 
219     switch (context->state) {
220     case GET_INFO_GET_CAP:
221         /* Initialize the property for the first ESAPI call */
222         command->property
223             = info_cap_tab[command->idx_info_cap].property;
224         fallthrough;
225 
226     case GET_INFO_GET_CAP_MORE:
227         /* This state is a helper used from fapi_util.c */
228         fallthrough;
229 
230     case GET_INFO_WAIT_FOR_CAP:
231         /* State will be set by sub routine */
232         capIdx = command->idx_info_cap;
233         r = ifapi_capability_get(context,
234                                  info_cap_tab[capIdx].capability,
235                                  info_cap_tab[capIdx].max,
236                                  &capabilityData);
237         return_try_again(r);
238         goto_if_error(r, "Get capability", cleanup);
239 
240         infoObj->cap[capIdx].description = info_cap_tab[capIdx].description;
241         infoObj->cap[capIdx].capability = capabilityData;
242         command->property_count = 0;
243         command->idx_info_cap += 1;
244         if (command->idx_info_cap <  sizeof(info_cap_tab)
245                 / sizeof(info_cap_tab[0])) {
246             /* Not all capabilities have been collected */
247             context->state = GET_INFO_GET_CAP;
248             return TSS2_FAPI_RC_TRY_AGAIN;
249         }
250 
251         infoObj->fapi_version = "OSSTSS 2.2.x";
252         infoObj->fapi_config = "Properties of config have to specified by TCG";
253 
254         /* Serialize the information. */
255         r = ifapi_json_IFAPI_INFO_serialize(infoObj, &jso);
256         goto_if_error(r, "Error serialize info object", cleanup);
257 
258         /* Duplicate the information to be returned to the caller. */
259         *info = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY));
260         goto_if_null2(*info, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup);
261 
262         context->state = _FAPI_STATE_INIT;
263         r = TSS2_RC_SUCCESS;
264         break;
265 
266     statecasedefault(context->state);
267     }
268 
269 cleanup:
270     /* Cleanup any intermediate results and state stored in the context. */
271     json_object_put(jso);
272     for (capIdx = 0; capIdx < IFAPI_MAX_CAP_INFO; capIdx++) {
273         SAFE_FREE(infoObj->cap[capIdx].capability);
274     }
275     LOG_TRACE("finished");
276     return r;
277 }
278