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