xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/ifapi_config.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1*758e9fbaSOystein Eftevaag /* SPDX-License-Identifier: BSD-2-Clause */
2*758e9fbaSOystein Eftevaag /*******************************************************************************
3*758e9fbaSOystein Eftevaag  * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
4*758e9fbaSOystein Eftevaag  * All rights reserved.
5*758e9fbaSOystein Eftevaag  *******************************************************************************/
6*758e9fbaSOystein Eftevaag 
7*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
8*758e9fbaSOystein Eftevaag #include <config.h>
9*758e9fbaSOystein Eftevaag #endif
10*758e9fbaSOystein Eftevaag 
11*758e9fbaSOystein Eftevaag #include <json-c/json.h>
12*758e9fbaSOystein Eftevaag #include <json-c/json_util.h>
13*758e9fbaSOystein Eftevaag 
14*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
15*758e9fbaSOystein Eftevaag #include "ifapi_config.h"
16*758e9fbaSOystein Eftevaag #include "ifapi_json_deserialize.h"
17*758e9fbaSOystein Eftevaag #include "tpm_json_deserialize.h"
18*758e9fbaSOystein Eftevaag #include "ifapi_helpers.h"
19*758e9fbaSOystein Eftevaag 
20*758e9fbaSOystein Eftevaag #define LOGMODULE fapi
21*758e9fbaSOystein Eftevaag #include "util/log.h"
22*758e9fbaSOystein Eftevaag 
23*758e9fbaSOystein Eftevaag /**
24*758e9fbaSOystein Eftevaag  * The path of the default config file
25*758e9fbaSOystein Eftevaag  */
26*758e9fbaSOystein Eftevaag #define DEFAULT_CONFIG_FILE (SYSCONFDIR "/tpm2-tss/fapi-config.json")
27*758e9fbaSOystein Eftevaag 
28*758e9fbaSOystein Eftevaag /** Deserializes a configuration JSON object.
29*758e9fbaSOystein Eftevaag  *
30*758e9fbaSOystein Eftevaag  * @param[in]  jso The JSON object to be deserialized
31*758e9fbaSOystein Eftevaag  * @param[out] out The deserialized configuration object
32*758e9fbaSOystein Eftevaag  *
33*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success
34*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE if jso or out is NULL
35*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if the JSON object cannot be deserialized
36*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
37*758e9fbaSOystein Eftevaag  */
38*758e9fbaSOystein Eftevaag static TSS2_RC
ifapi_json_IFAPI_CONFIG_deserialize(json_object * jso,IFAPI_CONFIG * out)39*758e9fbaSOystein Eftevaag ifapi_json_IFAPI_CONFIG_deserialize(json_object *jso, IFAPI_CONFIG *out)
40*758e9fbaSOystein Eftevaag {
41*758e9fbaSOystein Eftevaag     /* Check for NULL parameters */
42*758e9fbaSOystein Eftevaag     return_if_null(out, "out is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
43*758e9fbaSOystein Eftevaag     return_if_null(jso, "jso is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
44*758e9fbaSOystein Eftevaag 
45*758e9fbaSOystein Eftevaag     /* Deserialize the JSON object) */
46*758e9fbaSOystein Eftevaag     json_object *jso2;
47*758e9fbaSOystein Eftevaag     TSS2_RC r;
48*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
49*758e9fbaSOystein Eftevaag 
50*758e9fbaSOystein Eftevaag     if (!ifapi_get_sub_object(jso, "profile_dir", &jso2)) {
51*758e9fbaSOystein Eftevaag         out->profile_dir = NULL;
52*758e9fbaSOystein Eftevaag     } else {
53*758e9fbaSOystein Eftevaag         r = ifapi_json_char_deserialize(jso2, &out->profile_dir);
54*758e9fbaSOystein Eftevaag         return_if_error(r, "BAD VALUE");
55*758e9fbaSOystein Eftevaag     }
56*758e9fbaSOystein Eftevaag 
57*758e9fbaSOystein Eftevaag     if (!ifapi_get_sub_object(jso, "user_dir", &jso2)) {
58*758e9fbaSOystein Eftevaag         out->user_dir = NULL;
59*758e9fbaSOystein Eftevaag     } else {
60*758e9fbaSOystein Eftevaag         r = ifapi_json_char_deserialize(jso2, &out->user_dir);
61*758e9fbaSOystein Eftevaag         return_if_error(r, "BAD VALUE");
62*758e9fbaSOystein Eftevaag     }
63*758e9fbaSOystein Eftevaag 
64*758e9fbaSOystein Eftevaag     if (!ifapi_get_sub_object(jso, "system_dir", &jso2)) {
65*758e9fbaSOystein Eftevaag         out->keystore_dir = NULL;
66*758e9fbaSOystein Eftevaag     } else {
67*758e9fbaSOystein Eftevaag         r = ifapi_json_char_deserialize(jso2, &out->keystore_dir);
68*758e9fbaSOystein Eftevaag         return_if_error(r, "BAD VALUE");
69*758e9fbaSOystein Eftevaag     }
70*758e9fbaSOystein Eftevaag 
71*758e9fbaSOystein Eftevaag     if (!ifapi_get_sub_object(jso, "log_dir", &jso2)) {
72*758e9fbaSOystein Eftevaag         out->log_dir = DEFAULT_LOG_DIR;
73*758e9fbaSOystein Eftevaag     } else {
74*758e9fbaSOystein Eftevaag         r = ifapi_json_char_deserialize(jso2, &out->log_dir);
75*758e9fbaSOystein Eftevaag         return_if_error(r, "BAD VALUE");
76*758e9fbaSOystein Eftevaag     }
77*758e9fbaSOystein Eftevaag 
78*758e9fbaSOystein Eftevaag     if (!ifapi_get_sub_object(jso, "profile_name", &jso2)) {
79*758e9fbaSOystein Eftevaag         LOG_ERROR("Bad value");
80*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_BAD_VALUE;
81*758e9fbaSOystein Eftevaag     }
82*758e9fbaSOystein Eftevaag     r = ifapi_json_char_deserialize(jso2, &out->profile_name);
83*758e9fbaSOystein Eftevaag     return_if_error(r, "BAD VALUE");
84*758e9fbaSOystein Eftevaag     if (!ifapi_get_sub_object(jso, "tcti", &jso2)) {
85*758e9fbaSOystein Eftevaag         LOG_ERROR("Bad value");
86*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_BAD_VALUE;
87*758e9fbaSOystein Eftevaag     }
88*758e9fbaSOystein Eftevaag     r = ifapi_json_char_deserialize(jso2, &out->tcti);
89*758e9fbaSOystein Eftevaag     return_if_error(r, "BAD VALUE");
90*758e9fbaSOystein Eftevaag 
91*758e9fbaSOystein Eftevaag     if (!ifapi_get_sub_object(jso, "system_pcrs", &jso2)) {
92*758e9fbaSOystein Eftevaag         LOG_ERROR("Bad value");
93*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_BAD_VALUE;
94*758e9fbaSOystein Eftevaag     }
95*758e9fbaSOystein Eftevaag     r = ifapi_json_TPML_PCR_SELECTION_deserialize(jso2, &out->system_pcrs);
96*758e9fbaSOystein Eftevaag     return_if_error(r, "BAD VALUE");
97*758e9fbaSOystein Eftevaag 
98*758e9fbaSOystein Eftevaag     if (!ifapi_get_sub_object(jso, "ek_cert_file", &jso2)) {
99*758e9fbaSOystein Eftevaag         out->ek_cert_file = NULL;
100*758e9fbaSOystein Eftevaag     } else {
101*758e9fbaSOystein Eftevaag         r = ifapi_json_char_deserialize(jso2, &out->ek_cert_file);
102*758e9fbaSOystein Eftevaag         return_if_error(r, "BAD VALUE");
103*758e9fbaSOystein Eftevaag     }
104*758e9fbaSOystein Eftevaag 
105*758e9fbaSOystein Eftevaag     if (ifapi_get_sub_object(jso, "ek_cert_less", &jso2)) {
106*758e9fbaSOystein Eftevaag         r = ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->ek_cert_less);
107*758e9fbaSOystein Eftevaag         return_if_error(r, "BAD VALUE");
108*758e9fbaSOystein Eftevaag 
109*758e9fbaSOystein Eftevaag     } else {
110*758e9fbaSOystein Eftevaag         out->ek_cert_less = TPM2_NO;
111*758e9fbaSOystein Eftevaag     }
112*758e9fbaSOystein Eftevaag 
113*758e9fbaSOystein Eftevaag     if (ifapi_get_sub_object(jso, "ek_fingerprint", &jso2)) {
114*758e9fbaSOystein Eftevaag         r = ifapi_json_TPMT_HA_deserialize(jso2, &out->ek_fingerprint);
115*758e9fbaSOystein Eftevaag         return_if_error(r, "BAD VALUE");
116*758e9fbaSOystein Eftevaag     } else {
117*758e9fbaSOystein Eftevaag         out->ek_fingerprint.hashAlg = 0;
118*758e9fbaSOystein Eftevaag     }
119*758e9fbaSOystein Eftevaag 
120*758e9fbaSOystein Eftevaag     if (!ifapi_get_sub_object(jso, "intel_cert_service", &jso2)) {
121*758e9fbaSOystein Eftevaag         out->intel_cert_service = NULL;
122*758e9fbaSOystein Eftevaag     } else {
123*758e9fbaSOystein Eftevaag         r = ifapi_json_char_deserialize(jso2, &out->intel_cert_service);
124*758e9fbaSOystein Eftevaag         return_if_error(r, "BAD VALUE");
125*758e9fbaSOystein Eftevaag     }
126*758e9fbaSOystein Eftevaag 
127*758e9fbaSOystein Eftevaag     LOG_TRACE("true");
128*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
129*758e9fbaSOystein Eftevaag }
130*758e9fbaSOystein Eftevaag 
131*758e9fbaSOystein Eftevaag /**
132*758e9fbaSOystein Eftevaag  * Starts the initialization of the FAPI configuration.
133*758e9fbaSOystein Eftevaag  *
134*758e9fbaSOystein Eftevaag  * @param[in] io An IO object for file system access
135*758e9fbaSOystein Eftevaag  *
136*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success
137*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE if io is NULL
138*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
139*758e9fbaSOystein Eftevaag  *         object store.
140*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
141*758e9fbaSOystein Eftevaag  */
142*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_config_initialize_async(IFAPI_IO * io)143*758e9fbaSOystein Eftevaag ifapi_config_initialize_async(IFAPI_IO *io)
144*758e9fbaSOystein Eftevaag {
145*758e9fbaSOystein Eftevaag     /* Check for NULL parameters */
146*758e9fbaSOystein Eftevaag     return_if_null(io, "io is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
147*758e9fbaSOystein Eftevaag 
148*758e9fbaSOystein Eftevaag     /* Determine the location of the configuration file */
149*758e9fbaSOystein Eftevaag     char *configFile = getenv(ENV_FAPI_CONFIG);
150*758e9fbaSOystein Eftevaag     if (!configFile) {
151*758e9fbaSOystein Eftevaag         /* No config file given, falling back to the default */
152*758e9fbaSOystein Eftevaag         configFile = DEFAULT_CONFIG_FILE;
153*758e9fbaSOystein Eftevaag     }
154*758e9fbaSOystein Eftevaag 
155*758e9fbaSOystein Eftevaag     /* Start reading the config file */
156*758e9fbaSOystein Eftevaag     TSS2_RC r = ifapi_io_read_async(io, configFile);
157*758e9fbaSOystein Eftevaag     return_if_error(r, "Could not read config file ");
158*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
159*758e9fbaSOystein Eftevaag }
160*758e9fbaSOystein Eftevaag 
161*758e9fbaSOystein Eftevaag /**
162*758e9fbaSOystein Eftevaag  * Finishes the initialization of the FAPI configuration.
163*758e9fbaSOystein Eftevaag  * @param[in]  io An IO object for file system access
164*758e9fbaSOystein Eftevaag  * @param[out] config The configuration that is initialized
165*758e9fbaSOystein Eftevaag  *
166*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success
167*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE if config or io is NULL
168*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if the read configuration file does not hold
169*758e9fbaSOystein Eftevaag  *         a valid configuration
170*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if JSON parsing fails
171*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_PATH if the configuration path is invalid
172*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
173*758e9fbaSOystein Eftevaag  *         this function needs to be called again.
174*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
175*758e9fbaSOystein Eftevaag  *         object store.
176*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
177*758e9fbaSOystein Eftevaag  */
178*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_config_initialize_finish(IFAPI_IO * io,IFAPI_CONFIG * config)179*758e9fbaSOystein Eftevaag ifapi_config_initialize_finish(IFAPI_IO *io, IFAPI_CONFIG *config)
180*758e9fbaSOystein Eftevaag {
181*758e9fbaSOystein Eftevaag     /* Check for NULL parameters */
182*758e9fbaSOystein Eftevaag     return_if_null(config, "config is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
183*758e9fbaSOystein Eftevaag     return_if_null(io, "io is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
184*758e9fbaSOystein Eftevaag 
185*758e9fbaSOystein Eftevaag     /* Definitions that must be listed here for the cleanup to work */
186*758e9fbaSOystein Eftevaag     char *homeDir = NULL;
187*758e9fbaSOystein Eftevaag     json_object *jso = NULL;
188*758e9fbaSOystein Eftevaag 
189*758e9fbaSOystein Eftevaag     /* Finish reading operation */
190*758e9fbaSOystein Eftevaag     uint8_t *configFileContent = NULL;
191*758e9fbaSOystein Eftevaag     size_t configFileContentSize = 0;
192*758e9fbaSOystein Eftevaag     TSS2_RC r = ifapi_io_read_finish(io, &configFileContent, &configFileContentSize);
193*758e9fbaSOystein Eftevaag     return_try_again(r);
194*758e9fbaSOystein Eftevaag     goto_if_error(r, "Could not finish read operation", cleanup);
195*758e9fbaSOystein Eftevaag     if (configFileContent == NULL || configFileContentSize == 0) {
196*758e9fbaSOystein Eftevaag         LOG_ERROR("Config file is empty");
197*758e9fbaSOystein Eftevaag         r = TSS2_FAPI_RC_BAD_VALUE;
198*758e9fbaSOystein Eftevaag         goto cleanup;
199*758e9fbaSOystein Eftevaag     }
200*758e9fbaSOystein Eftevaag 
201*758e9fbaSOystein Eftevaag     /* Parse and deserialize the configuration file */
202*758e9fbaSOystein Eftevaag     jso = json_tokener_parse((char *)configFileContent);
203*758e9fbaSOystein Eftevaag     goto_if_null(jso, "Could not parse JSON objects",
204*758e9fbaSOystein Eftevaag             TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
205*758e9fbaSOystein Eftevaag     r = ifapi_json_IFAPI_CONFIG_deserialize(jso, config);
206*758e9fbaSOystein Eftevaag     goto_if_error(r, "Could not deserialize configuration", cleanup);
207*758e9fbaSOystein Eftevaag 
208*758e9fbaSOystein Eftevaag     /* Check, if the values of the configuration are valid */
209*758e9fbaSOystein Eftevaag     goto_if_null(config->profile_dir, "No profile directory defined in config file",
210*758e9fbaSOystein Eftevaag                  TSS2_FAPI_RC_BAD_VALUE, cleanup);
211*758e9fbaSOystein Eftevaag     goto_if_null(config->user_dir, "No user directory defined in config file",
212*758e9fbaSOystein Eftevaag                  TSS2_FAPI_RC_BAD_VALUE, cleanup);
213*758e9fbaSOystein Eftevaag     goto_if_null(config->profile_name, "No default profile defined in config file.",
214*758e9fbaSOystein Eftevaag                  TSS2_FAPI_RC_BAD_VALUE, cleanup);
215*758e9fbaSOystein Eftevaag 
216*758e9fbaSOystein Eftevaag     /* Check whether usage of home directory is provided in config file */
217*758e9fbaSOystein Eftevaag     size_t startPos = 0;
218*758e9fbaSOystein Eftevaag     if (strncmp("~", config->user_dir, 1) == 0) {
219*758e9fbaSOystein Eftevaag         startPos = 1;
220*758e9fbaSOystein Eftevaag     } else if (strncmp("$HOME", config->user_dir, 5) == 0) {
221*758e9fbaSOystein Eftevaag         startPos = 5;
222*758e9fbaSOystein Eftevaag     }
223*758e9fbaSOystein Eftevaag 
224*758e9fbaSOystein Eftevaag     /* Replace home abbreviation in user path. */
225*758e9fbaSOystein Eftevaag     char *homePath = NULL;
226*758e9fbaSOystein Eftevaag     if (startPos != 0) {
227*758e9fbaSOystein Eftevaag         LOG_DEBUG("Expanding user directory %s to user's home", config->user_dir);
228*758e9fbaSOystein Eftevaag         homeDir = getenv("HOME");
229*758e9fbaSOystein Eftevaag         goto_if_null2(homeDir, "Home directory can't be determined.",
230*758e9fbaSOystein Eftevaag                       r, TSS2_FAPI_RC_BAD_PATH, cleanup);
231*758e9fbaSOystein Eftevaag 
232*758e9fbaSOystein Eftevaag         r = ifapi_asprintf(&homePath, "%s%s%s", homeDir, IFAPI_FILE_DELIM,
233*758e9fbaSOystein Eftevaag                            &config->user_dir[startPos]);
234*758e9fbaSOystein Eftevaag         goto_if_error(r, "Out of memory.", cleanup);
235*758e9fbaSOystein Eftevaag 
236*758e9fbaSOystein Eftevaag         SAFE_FREE(config->user_dir);
237*758e9fbaSOystein Eftevaag         config->user_dir = homePath;
238*758e9fbaSOystein Eftevaag     }
239*758e9fbaSOystein Eftevaag 
240*758e9fbaSOystein Eftevaag     /* Log the contents of the configuration */
241*758e9fbaSOystein Eftevaag     LOG_DEBUG("Configuration profile directory: %s", config->profile_dir);
242*758e9fbaSOystein Eftevaag     LOG_DEBUG("Configuration user directory: %s", config->user_dir);
243*758e9fbaSOystein Eftevaag     LOG_DEBUG("Configuration key storage directory: %s", config->keystore_dir);
244*758e9fbaSOystein Eftevaag     LOG_DEBUG("Configuration profile name: %s", config->profile_name);
245*758e9fbaSOystein Eftevaag     LOG_DEBUG("Configuration TCTI: %s", config->tcti);
246*758e9fbaSOystein Eftevaag     LOG_DEBUG("Configuration log directory: %s", config->log_dir);
247*758e9fbaSOystein Eftevaag cleanup:
248*758e9fbaSOystein Eftevaag     SAFE_FREE(configFileContent);
249*758e9fbaSOystein Eftevaag     if (jso != NULL) {
250*758e9fbaSOystein Eftevaag         json_object_put(jso);
251*758e9fbaSOystein Eftevaag     }
252*758e9fbaSOystein Eftevaag     return r;
253*758e9fbaSOystein Eftevaag }
254