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