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 #include <dirent.h>
10 #endif
11
12 #include "ifapi_io.h"
13 #include "ifapi_helpers.h"
14 #include "ifapi_policy_types.h"
15 #include "ifapi_policy_store.h"
16 #include "ifapi_macros.h"
17 #define LOGMODULE fapi
18 #include "util/log.h"
19 #include "util/aux_util.h"
20 #include "ifapi_policy_json_deserialize.h"
21 #include "ifapi_policy_json_serialize.h"
22
23 /** Compute absolute path of policy for IO.
24 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
25 */
26 static TSS2_RC
policy_rel_path_to_abs_path(IFAPI_POLICY_STORE * pstore,const char * rel_path,char ** abs_path)27 policy_rel_path_to_abs_path(
28 IFAPI_POLICY_STORE *pstore,
29 const char *rel_path,
30 char **abs_path)
31 {
32 TSS2_RC r;
33
34 if (ifapi_path_type_p(rel_path, IFAPI_POLICY_PATH)) {
35 r = ifapi_asprintf(abs_path, "%s%s%s.json", pstore->policydir,
36 IFAPI_FILE_DELIM, rel_path);
37 } else {
38 r = ifapi_asprintf(abs_path, "%s%s%s%s%s.json", pstore->policydir,
39 IFAPI_FILE_DELIM, IFAPI_POLICY_PATH, IFAPI_FILE_DELIM, rel_path);
40
41 }
42 return_if_error(r, "Create policy file name.");
43 return r;
44 }
45 /** Remove file storing a policy object.
46 *
47 * @param[in] pstore The policy directory.
48 * @param[in] path The relative name of the object be removed.
49 * @retval TSS2_RC_SUCCESS On success.
50 * @retval TSS2_FAPI_RC_MEMORY: If memory could not be allocated.
51 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If no file is found in policy store.
52 * @retval TSS2_FAPI_RC_IO_ERROR If the file can't be removed.
53 */
54 TSS2_RC
ifapi_policy_delete(IFAPI_POLICY_STORE * pstore,char * path)55 ifapi_policy_delete(
56 IFAPI_POLICY_STORE * pstore,
57 char *path)
58 {
59 TSS2_RC r;
60 char *abs_path = NULL;
61
62 /* Convert relative path to absolute path in policy store */
63 r = policy_rel_path_to_abs_path(pstore, path, &abs_path);
64 goto_if_error2(r, "Path %s could not be created.", cleanup, path);
65
66 if (!ifapi_io_path_exists(abs_path)) {
67 goto_error(r, TSS2_FAPI_RC_PATH_NOT_FOUND,
68 "Policy %s not found.", cleanup, path);
69 }
70
71 if (remove(abs_path) != 0) {
72 LOG_WARNING("File: %s can't be deleted.", abs_path);
73 }
74
75 cleanup:
76 SAFE_FREE(abs_path);
77 return r;
78 }
79
80 /** Store policy store parameters in the policy store context.
81 *
82 * Also the user directory will be created if it does not exist.
83 *
84 * @param[out] pstore The keystore to be initialized.
85 * @param[in] config_policydir The configured policy directory.
86 * @retval TSS2_RC_SUCCESS If the keystore can be initialized.
87 * @retval TSS2_FAPI_RC_IO_ERROR If the policy store can't be
88 * initialized.
89 * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
90 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
91 * the function.
92 */
93 TSS2_RC
ifapi_policy_store_initialize(IFAPI_POLICY_STORE * pstore,const char * config_policydir)94 ifapi_policy_store_initialize(
95 IFAPI_POLICY_STORE *pstore,
96 const char *config_policydir)
97 {
98 TSS2_RC r;
99 char *policy_dir = NULL;
100
101 memset(pstore, 0, sizeof(IFAPI_POLICY_STORE));
102 strdup_check(pstore->policydir, config_policydir, r, error);
103
104 r = ifapi_asprintf(&policy_dir, "%s%s%s", config_policydir, IFAPI_FILE_DELIM,
105 IFAPI_POLICY_PATH);
106 goto_if_error(r, "Out of memory.", error);
107
108 r = ifapi_io_check_create_dir(policy_dir);
109 goto_if_error2(r, "Policy directory %s can't be created.", error, policy_dir);
110
111 SAFE_FREE(policy_dir);
112 return TSS2_RC_SUCCESS;
113
114 error:
115 SAFE_FREE(policy_dir);
116 return r;
117 }
118
119 /** Start loading FAPI policy from policy store.
120 *
121 * Keys objects, NV objects, and hierarchies can be loaded.
122 *
123 * @param[in] pstore The policy directory.
124 * @param[in] io The input/output context being used for file I/O.
125 * @param[in] path The relative path of the object. For keys the path will
126 * expanded if possible.
127 * @retval TSS2_RC_SUCCESS If the object can be read.
128 * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered.
129 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the file does not exist.
130 * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
131 */
132 TSS2_RC
ifapi_policy_store_load_async(IFAPI_POLICY_STORE * pstore,IFAPI_IO * io,const char * path)133 ifapi_policy_store_load_async(
134 IFAPI_POLICY_STORE *pstore,
135 IFAPI_IO *io,
136 const char *path)
137 {
138 TSS2_RC r;
139 char *abs_path = NULL;
140
141 LOG_TRACE("Load policy: %s", path);
142
143 /* Free old input buffer if buffer exists */
144 SAFE_FREE(io->char_rbuffer);
145
146 /* Convert relative path to absolute path in keystore */
147 r = policy_rel_path_to_abs_path(pstore, path, &abs_path);
148 goto_if_error2(r, "Object %s not found.", cleanup, path);
149
150 /* Prepare read operation */
151 r = ifapi_io_read_async(io, abs_path);
152
153 cleanup:
154 SAFE_FREE(abs_path);
155 return r;
156 }
157
158 /** Finish loading FAPI policy from policy store.
159 *
160 *
161 * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
162 *
163 * @param[in] pstore The policy context with the policy directory.
164 * @param[in,out] io The input/output context being used for file I/O.
165 * @param[in] policy The caller allocated policy which will loaded from policy store.
166 * @retval TSS2_RC_SUCCESS After successfully loading the object.
167 * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
168 * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
169 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
170 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
171 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
172 * the function.
173 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
174 */
175 TSS2_RC
ifapi_policy_store_load_finish(IFAPI_POLICY_STORE * pstore,IFAPI_IO * io,TPMS_POLICY * policy)176 ifapi_policy_store_load_finish(
177 IFAPI_POLICY_STORE *pstore,
178 IFAPI_IO *io,
179 TPMS_POLICY *policy)
180 {
181 TSS2_RC r;
182 json_object *jso = NULL;
183 uint8_t *buffer = NULL;
184 /* ptore parameter is used to be prepared if transmission of state information
185 between async and finish will be necessary in future extensions. */
186 (void)pstore;
187
188 r = ifapi_io_read_finish(io, &buffer, NULL);
189 return_try_again(r);
190 return_if_error(r, "keystore read_finish failed");
191
192 /* If json objects can't be parse the object store is corrupted */
193 jso = json_tokener_parse((char *)buffer);
194 SAFE_FREE(buffer);
195 return_if_null(jso, "Policy store is corrupted (Json error).", TSS2_FAPI_RC_GENERAL_FAILURE);
196
197 r = ifapi_json_TPMS_POLICY_deserialize(jso, policy);
198 goto_if_error(r, "Deserialize policy", cleanup);
199
200 cleanup:
201 SAFE_FREE(buffer);
202 if (jso)
203 json_object_put(jso);
204 LOG_TRACE("Return %x", r);
205 return r;
206
207 }
208
209 /** Start writing FAPI object to the key store.
210 *
211 * The relative path will be expanded, if the default policy directory (/policy)
212 * is not part of the path.
213 *
214 * @param[in] pstore The policy context with the policy directory.
215 * @param[in] io The input/output context being used for file I/O.
216 * @param[in] path The relative path of the policy.
217 * @param[in] policy The policy to be written to the policy store.
218 * @retval TSS2_RC_SUCCESS If the policy is written successfully.
219 * @retval TSS2_FAPI_RC_IO_ERROR: If an I/O error was encountered;
220 * @retval TSS2_FAPI_RC_MEMORY: If memory could not be allocated to hold the output data.
221 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
222 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
223 * the function.
224 */
225 TSS2_RC
ifapi_policy_store_store_async(IFAPI_POLICY_STORE * pstore,IFAPI_IO * io,const char * path,const TPMS_POLICY * policy)226 ifapi_policy_store_store_async(
227 IFAPI_POLICY_STORE *pstore,
228 IFAPI_IO *io,
229 const char *path,
230 const TPMS_POLICY *policy)
231 {
232 TSS2_RC r;
233 char *jso_string = NULL;
234 json_object *jso = NULL;
235 char *abs_path = NULL;
236
237 LOG_TRACE("Store policy: %s", path);
238
239 /* Convert relative path to absolute path in the policy store */
240 r = policy_rel_path_to_abs_path(pstore, path, &abs_path);
241 goto_if_error2(r, "Path %s could not be created.", cleanup, path);
242
243 /* Generate JSON string to be written to store */
244 r = ifapi_json_TPMS_POLICY_serialize(policy, &jso);
245 goto_if_error2(r, "Policy %s could not be serialized.", cleanup, path);
246
247 jso_string = strdup(json_object_to_json_string_ext(jso,
248 JSON_C_TO_STRING_PRETTY));
249 goto_if_null2(jso_string, "Converting json to string", r, TSS2_FAPI_RC_MEMORY,
250 cleanup);
251
252 /* Start writing the json string to disk */
253 r = ifapi_io_write_async(io, abs_path, (uint8_t *) jso_string, strlen(jso_string));
254 free(jso_string);
255 goto_if_error(r, "write_async failed", cleanup);
256
257 cleanup:
258 if (jso)
259 json_object_put(jso);
260 SAFE_FREE(abs_path);
261 return r;
262 }
263
264 /** Finish writing a FAPI policy object to the policy store.
265 *
266 * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
267 *
268 * @param[in] pstore The policy context with the policy directory.
269 * @param[in,out] io The input/output context being used for file I/O.
270 * @retval TSS2_RC_SUCCESS: if the function call was a success.
271 * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
272 * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
273 Call this function again later.
274 */
275 TSS2_RC
ifapi_policy_store_store_finish(IFAPI_POLICY_STORE * pstore,IFAPI_IO * io)276 ifapi_policy_store_store_finish(
277 IFAPI_POLICY_STORE *pstore,
278 IFAPI_IO *io)
279 {
280 TSS2_RC r;
281
282 /* Pstore parameter is used to be prepared if transmission of state information
283 between async and finish will be necessary in future extensions. */
284 (void)pstore;
285 /* Finish writing the policy */
286 r = ifapi_io_write_finish(io);
287 return_try_again(r);
288
289 LOG_TRACE("Return %x", r);
290 return_if_error(r, "read_finish failed");
291
292 return TSS2_RC_SUCCESS;
293 }
294