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