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_keystore.h"
15 #define LOGMODULE fapi
16 #include "util/log.h"
17 #include "util/aux_util.h"
18 #include "ifapi_json_deserialize.h"
19 #include "ifapi_json_serialize.h"
20 
21 /** Initialize the linked list for an explicit key path.
22  *
23  * An implicit key path will be expanded to a key path starting with the profile
24  * directory. Missing parts will be added if possible.
25  * A linked list of the directories of the explicit path will be returned.
26  *
27  * @param[in] context_profile  The profile name used for expansion of the
28  *            implicit key path.
29  * @param[in] ipath the implicit key path which has to be expanded.
30  * @param[out] list_node1 The first directory of the implicit list.
31  * @param[out] current_list_node The tail of the path list after the path
32  *             which was expanded.
33  * @param[out] result The list of directories as linked list.
34  * @retval TSS2_RC_SUCCESS If the explicit path was created.
35  * @retval TSS2_FAPI_RC_MEMORY: If memory for the path list could not be allocated.
36  * @retval TSS2_FAPI_RC_BAD_VALUE If no explicit path can be derived from the
37  *         implicit path.
38  */
39 static TSS2_RC
initialize_explicit_key_path(const char * context_profile,const char * ipath,NODE_STR_T ** list_node1,NODE_STR_T ** current_list_node,NODE_STR_T ** result)40 initialize_explicit_key_path(
41     const char *context_profile,
42     const char *ipath,
43     NODE_STR_T **list_node1,
44     NODE_STR_T **current_list_node,
45     NODE_STR_T **result)
46 {
47     *list_node1 = split_string(ipath, IFAPI_FILE_DELIM);
48     NODE_STR_T *list_node = *list_node1;
49     char const *profile;
50     char *hierarchy;
51     TSS2_RC r = TSS2_RC_SUCCESS;
52 
53     *result = NULL;
54     if (list_node == NULL) {
55         LOG_ERROR("Invalid path");
56         free_string_list(*list_node1);
57         return TSS2_FAPI_RC_BAD_VALUE;
58     }
59     /* Check whether profile is part of the implicit path. */
60     if (strncmp("P_", list_node->str, 2) == 0) {
61         profile = list_node->str;
62         list_node = list_node->next;
63     } else {
64         profile = context_profile;
65     }
66     /* Create the initial node of the linked list. */
67     *result = init_string_list(profile);
68     if (*result == NULL) {
69         free_string_list(*list_node1);
70         LOG_ERROR("Out of memory");
71         return TSS2_FAPI_RC_MEMORY;
72     }
73     if (list_node == NULL) {
74         /* Storage hierarchy will be used as default. */
75         hierarchy = "HS";
76     } else {
77         if (strcmp(list_node->str, "HS") == 0 ||
78                 strcmp(list_node->str, "HE") == 0 ||
79                 strcmp(list_node->str, "HP") == 0 ||
80                 strcmp(list_node->str, "HN") == 0 ||
81                 strcmp(list_node->str, "HP") == 0) {
82             hierarchy = list_node->str;
83             list_node = list_node->next;
84         } else if (strcmp(list_node->str, "EK") == 0) {
85             /* The hierarchy for an endorsement key will be added. */
86             hierarchy = "HE";
87         } else if (list_node->next != NULL &&
88                    (strcmp(list_node->str, "SRK") == 0 ||
89                     strcmp(list_node->str, "SDK") == 0 ||
90                     strcmp(list_node->str, "UNK") == 0 ||
91                     strcmp(list_node->str, "UDK") == 0)) {
92             /* The storage hierachy will be added. */
93             hierarchy = "HS";
94         } else {
95             hierarchy = "HS";
96         }
97     }
98     /* Add the used hierarcy to the linked list. */
99     if (!add_string_to_list(*result, hierarchy)) {
100         LOG_ERROR("Out of memory");
101         r = TSS2_FAPI_RC_MEMORY;
102         goto error;
103     }
104     if (list_node == NULL) {
105         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Explicit path can't be determined.",
106                    error);
107     }
108     /* Add the primary directory to the linked list. */
109     if (!add_string_to_list(*result, list_node->str)) {
110         LOG_ERROR("Out of memory");
111         r = TSS2_FAPI_RC_MEMORY;
112         goto error;
113     }
114     /* Return the rest of the path. */
115     *current_list_node = list_node->next;
116     return TSS2_RC_SUCCESS;
117 
118 error:
119     free_string_list(*result);
120     *result = NULL;
121     free_string_list(*list_node1);
122     *list_node1 = NULL;
123     return r;
124 }
125 
126 /** Get explicit key path as linked list.
127  *
128  * An implicit key path will be expanded to a key path starting with the profile
129  * directory. Missing parts will be added if possible.
130  * A linked list of the directories of the explicit path will be returned.
131  * @param[in] keystore The key directories and default profile.
132  * @param[in] ipath the implicit key path which has to be expanded.
133  * @param[out] result The list of directories as linked list.
134  * @retval TSS2_RC_SUCCESS If the explicit path was created.
135  * @retval TSS2_FAPI_RC_MEMORY: If memory for the path list could not be allocated.
136  * @retval TSS2_FAPI_RC_BAD_VALUE If no explicit path can be derived from the
137  *         implicit path.
138  */
139 static TSS2_RC
get_explicit_key_path(IFAPI_KEYSTORE * keystore,const char * ipath,NODE_STR_T ** result)140 get_explicit_key_path(
141     IFAPI_KEYSTORE *keystore,
142     const char *ipath,
143     NODE_STR_T **result)
144 {
145     NODE_STR_T *list_node1 = NULL;
146     NODE_STR_T *list_node = NULL;
147     TSS2_RC r = initialize_explicit_key_path(keystore->defaultprofile, ipath,
148                                              &list_node1, &list_node, result);
149     goto_if_error(r, "init_explicit_key_path", error);
150 
151     while (list_node != NULL) {
152         /* Add tail of path list to expanded head of the path list. */
153         if (!add_string_to_list(*result, list_node->str)) {
154             LOG_ERROR("Out of memory");
155             r = TSS2_FAPI_RC_MEMORY;
156             goto error;
157         }
158         list_node = list_node->next;
159     }
160     free_string_list(list_node1);
161     return TSS2_RC_SUCCESS;
162 
163 error:
164     if (*result)
165         free_string_list(*result);
166     if (list_node1)
167         free_string_list(list_node1);
168     return r;
169 }
170 
171 /** Convert full FAPI path to relative path.
172  *
173  * The relative path will be copied directly into the passed object.
174  *
175  * @param[in] keystore The key directories and default profile.
176  * @param[in,out] path The absolute path.
177  */
178 void
full_path_to_fapi_path(IFAPI_KEYSTORE * keystore,char * path)179 full_path_to_fapi_path(IFAPI_KEYSTORE *keystore, char *path)
180 {
181     unsigned int start_pos, end_pos, i;
182     const unsigned int path_length = strlen(path);
183     size_t keystore_length = strlen(keystore->userdir);
184     char fapi_path_delim;
185 
186     start_pos = 0;
187 
188     /* Check type of path, user or system */
189     if (strncmp(&path[0], keystore->userdir, keystore_length) == 0) {
190         start_pos = strlen(keystore->userdir);
191     } else {
192         keystore_length = strlen(keystore->systemdir);
193         if (strncmp(&path[0], keystore->systemdir, keystore_length) == 0)
194             start_pos = strlen(keystore->systemdir);
195     }
196 
197     if (!start_pos)
198         /* relative path was passed */
199         return;
200 
201     /* Move relative path */
202     end_pos = path_length - start_pos;
203     memmove(&path[0], &path[start_pos], end_pos);
204     size_t ip = 0;
205     size_t lp = strlen(path);
206 
207     /* Remove double / */
208     while (ip < lp) {
209         if (strncmp(&path[ip], "//", 2) == 0) {
210             memmove(&path[ip], &path[ip+1], lp-ip);
211             lp -= 1;
212         } else {
213             ip += 1;
214         }
215     }
216 
217     /* A relative policy path will end before the file extension.
218        For other objects only the directory name will be uses as
219        relative name. */
220     if (ifapi_path_type_p(path, IFAPI_POLICY_PATH))
221         fapi_path_delim = '.';
222     else
223         fapi_path_delim = IFAPI_FILE_DELIM_CHAR;
224 
225     for (i = end_pos - 2; i > 0; i--) {
226         if (path[i] == fapi_path_delim) {
227             path[i] = '\0';
228             break;
229         }
230     }
231 }
232 
233 /** Expand key store path.
234  *
235  * Depending on the type of the passed path the path will be expanded. For hierarchies
236  * the profile directory  will be added. For keys the implicit path will
237  * be expanded to an explicit path with all directories.
238  * @param[in] keystore The key directories and default profile.
239  * @param[in] path the implicit  path which has to be expanded if possible.
240  * @param[out] file_name The explicit path (callee-allocated)
241  * @retval TSS2_RC_SUCCESS If the explicit path was created.
242  * @retval TSS2_FAPI_RC_MEMORY: If memory for the path list could not be allocated.
243  * @retval TSS2_FAPI_RC_BAD_VALUE If no explicit path can be derived from the
244  *         implicit path.
245  */
246 static TSS2_RC
expand_path(IFAPI_KEYSTORE * keystore,const char * path,char ** file_name)247 expand_path(IFAPI_KEYSTORE *keystore, const char *path, char **file_name)
248 {
249     TSS2_RC r;
250     NODE_STR_T *node_list = NULL;
251     size_t pos = 0;
252 
253     if (ifapi_hierarchy_path_p(path)) {
254         if (strncmp(path, "P_", 2) == 0 || strncmp(path, "/P_", 3) == 0) {
255             *file_name = strdup(path);
256             return_if_null(*file_name, "Out of memory", TSS2_FAPI_RC_MEMORY);
257         } else {
258             if (strncmp("/", path, 1) == 0)
259                 pos = 1;
260             r = ifapi_asprintf(file_name, "%s%s%s", keystore->defaultprofile,
261                                IFAPI_FILE_DELIM, &path[pos]);
262             return_if_error(r, "Out of memory.");
263         }
264     } else if (ifapi_path_type_p(path, IFAPI_NV_PATH)
265                || ifapi_path_type_p(path, IFAPI_POLICY_PATH)
266                || ifapi_path_type_p(path, IFAPI_EXT_PATH)
267                || strncmp(path, "/P_", 3) == 0 || strncmp(path, "P_", 2) == 0) {
268         *file_name = strdup(path);
269         return_if_null(*file_name, "Out of memory", TSS2_FAPI_RC_MEMORY);
270 
271     } else {
272         r = get_explicit_key_path(keystore, path, &node_list);
273         return_if_error(r, "Out of memory");
274 
275         r = ifapi_path_string(file_name, NULL, node_list, NULL);
276         goto_if_error(r, "Out of memory", error);
277 
278         free_string_list(node_list);
279     }
280     return TSS2_RC_SUCCESS;
281 
282 error:
283     free_string_list(node_list);
284     return r;
285 }
286 /** Expand FAPI path to object path.
287  *
288  * The object file name will be appended and the implicit path will be expanded
289  * if possible.
290  * FAPI object path names correspond to directories of the key store. The
291  * objects are stored in a certain file in this directory. This function
292  * appends the name of the object file  to the FAPI directory to prepare file IO.
293  * @retval TSS2_RC_SUCCESS If the object file path can be created.
294  * @retval TSS2_FAPI_RC_MEMORY: If memory for the path name cannot allocated.
295  * @retval TSS2_FAPI_RC_BAD_VALUE If no explicit path can be derived from the
296  *         implicit path.
297  */
298 static TSS2_RC
expand_path_to_object(IFAPI_KEYSTORE * keystore,const char * path,const char * dir,char ** file_name)299 expand_path_to_object(
300     IFAPI_KEYSTORE *keystore,
301     const char *path,
302     const char *dir,
303     char **file_name)
304 {
305 
306     TSS2_RC r;
307     char *expanded_path = NULL;
308 
309     /* Expand implicit path to explicit path. */
310     r = expand_path(keystore, path, &expanded_path);
311     return_if_error(r, "Expand path");
312 
313     /* Append object file. */
314     r = ifapi_asprintf(file_name, "%s/%s/%s", dir, expanded_path, IFAPI_OBJECT_FILE);
315     SAFE_FREE(expanded_path);
316     return r;
317 }
318 
319 /** Store keystore parameters in the keystore context.
320  *
321  * Also the user directory will be created if it does not exist.
322  *
323  * @param[out] keystore The keystore to be initialized.
324  * @param[in] config_systemdir The configured system directory.
325  * @param[in] config_userdir The configured user directory.
326  * @param[in] config_defaultprofile The configured profile.
327  *
328  * @retval TSS2_RC_SUCCESS If the keystore can be initialized.
329  * @retval TSS2_FAPI_RC_IO_ERROR If the user part of the keystore can't be
330  *         initialized.
331  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
332  * @retval TSS2_FAPI_RC_BAD_PATH if the used path in inappropriate-
333  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
334  *         the function.
335  */
336 TSS2_RC
ifapi_keystore_initialize(IFAPI_KEYSTORE * keystore,const char * config_systemdir,const char * config_userdir,const char * config_defaultprofile)337 ifapi_keystore_initialize(
338     IFAPI_KEYSTORE *keystore,
339     const char *config_systemdir,
340     const char *config_userdir,
341     const char *config_defaultprofile)
342 {
343     TSS2_RC r;
344     char *home_dir;
345     char *home_path = NULL;
346     size_t start_pos;
347 
348     memset(keystore, 0, sizeof(IFAPI_KEYSTORE));
349 
350     /* Check whether usage of home directory is provided in config file */
351     if (strncmp("~", config_userdir, 1) == 0) {
352         start_pos = 1;
353     } else if (strncmp("$HOME", config_userdir, 5) == 0) {
354         start_pos = 5;
355     } else {
356         start_pos = 0;
357     }
358 
359     /* Replace home abbreviation in user path. */
360     if (start_pos) {
361         LOG_DEBUG("Expanding user directory %s to user's home", config_userdir);
362         home_dir = getenv("HOME");
363         goto_if_null2(home_dir, "Home directory can't be determined.",
364                       r, TSS2_FAPI_RC_BAD_PATH, error);
365 
366         r = ifapi_asprintf(&home_path, "%s%s%s", home_dir, IFAPI_FILE_DELIM,
367                            &config_userdir[start_pos]);
368         goto_if_error(r, "Out of memory.", error);
369         keystore->userdir = home_path;
370 
371     } else {
372         keystore->userdir = strdup(config_userdir);
373         goto_if_null2(keystore->userdir, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
374                       error);
375     }
376 
377     /* Create user directory if necessary */
378     r = ifapi_io_check_create_dir(keystore->userdir);
379     goto_if_error2(r, "User directory %s can't be created.", error, keystore->userdir);
380 
381     keystore->systemdir = strdup(config_systemdir);
382     goto_if_null2(keystore->systemdir, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
383                   error);
384 
385     keystore->defaultprofile = strdup(config_defaultprofile);
386     goto_if_null2(keystore->defaultprofile, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
387                   error);
388 
389     SAFE_FREE(home_path);
390     return TSS2_RC_SUCCESS;
391 
392 error:
393     SAFE_FREE(keystore->defaultprofile);
394     SAFE_FREE(keystore->userdir);
395     SAFE_FREE(keystore->systemdir);
396     return r;
397 }
398 
399 /** Get absolute object path for FAPI relative path and check whether file exists.
400  *
401  *  It will be checked whether object exists in user directory, if no
402  *  the path in system directory will be returnde
403  *
404  * @param[in] keystore The key directories and default profile.
405  * @param[in] rel_path The relative path of the object. For keys the path will
406  *           expanded if possible.
407  * @param[out] abs_path The absolute path of the object.
408  * @retval TSS2_RC_SUCCESS If the object can be read.
409  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if the file does not exist (for key objects).
410  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the file does not exist (for NV and hierarchy objects).
411  * @retval TSS2_FAPI_RC_IO_ERROR: If the file could not be read by the IO module.
412  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
413  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
414  *         the function.
415  */
416     static TSS2_RC
rel_path_to_abs_path(IFAPI_KEYSTORE * keystore,const char * rel_path,char ** abs_path)417 rel_path_to_abs_path(
418         IFAPI_KEYSTORE *keystore,
419         const char *rel_path,
420         char **abs_path)
421 {
422     TSS2_RC r;
423     char *directory = NULL;
424 
425     /* First expand path in user directory  */
426     r = expand_path(keystore, rel_path, &directory);
427     goto_if_error(r, "Expand path", cleanup);
428 
429     r = expand_path_to_object(keystore, directory,
430             keystore->userdir, abs_path);
431     goto_if_error2(r, "Object path %s could not be created.", cleanup, directory);
432 
433 
434     if (!ifapi_io_path_exists(*abs_path)) {
435         /* Second try system directory if object not found in user directory */
436         SAFE_FREE(*abs_path);
437         r = expand_path_to_object(keystore, directory,
438                 keystore->systemdir, abs_path);
439         goto_if_error2(r, "Object path %s could not be created.", cleanup, directory);
440 
441         if (ifapi_io_path_exists(*abs_path)) {
442             r = TSS2_RC_SUCCESS;
443             goto cleanup;
444         }
445 
446         /* Check type of object which does not exist. */
447         if (ifapi_path_type_p(rel_path, IFAPI_NV_PATH) ||
448                 (ifapi_hierarchy_path_p(rel_path))) {
449             /* Hierarchy which should be created during provisioning could not be loaded. */
450             goto_error(r, TSS2_FAPI_RC_PATH_NOT_FOUND,
451                     "Keystore not initialized. Hierarchy file %s does not exist.",
452                     cleanup, rel_path);
453         } else {
454             /* Object file for key does not exist in keystore */
455             goto_error(r, TSS2_FAPI_RC_KEY_NOT_FOUND,
456                     "Key %s not found.", cleanup, rel_path);
457         }
458     }
459 
460 cleanup:
461     SAFE_FREE(directory);
462     return r;
463 }
464 
465 /** Start loading FAPI object from key store.
466  *
467  * Keys objects, NV objects, and hierarchies can be loaded.
468  *
469  * @param[in] keystore The key directories and default profile.
470  * @param[in] io  The input/output context being used for file I/O.
471  * @param[in] path The relative path of the object. For keys the path will
472  *           expanded if possible.
473  * @retval TSS2_RC_SUCCESS If the object can be read.
474  * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered.
475  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the file does not exist.
476  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
477  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
478  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
479  *         the function.
480  */
481 TSS2_RC
ifapi_keystore_load_async(IFAPI_KEYSTORE * keystore,IFAPI_IO * io,const char * path)482 ifapi_keystore_load_async(
483     IFAPI_KEYSTORE *keystore,
484     IFAPI_IO *io,
485     const char *path)
486 {
487     TSS2_RC r;
488     char *abs_path = NULL;
489 
490     LOG_TRACE("Load object: %s", path);
491 
492     /* Free old input buffer if buffer exists */
493     SAFE_FREE(io->char_rbuffer);
494 
495     /* Convert relative path to absolute path in keystore */
496     r = rel_path_to_abs_path(keystore, path, &abs_path);
497     goto_if_error2(r, "Object %s not found.", cleanup, path);
498 
499     /* Prepare read operation */
500     r = ifapi_io_read_async(io, abs_path);
501 
502 cleanup:
503     SAFE_FREE(abs_path);
504     return r;
505 }
506 
507 /** Finish loading FAPI object from key store.
508  *
509  * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
510  *
511  * @param[in] keystore The key directories and default profile.
512  * @param[in,out] io The input/output context being used for file I/O.
513  * @param[in] object The caller allocated object which will loaded from keystore.
514  * @retval TSS2_RC_SUCCESS After successfully loading the object.
515  * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
516  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
517  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
518  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
519  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
520  *         the function.
521  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
522  */
523 TSS2_RC
ifapi_keystore_load_finish(IFAPI_KEYSTORE * keystore,IFAPI_IO * io,IFAPI_OBJECT * object)524 ifapi_keystore_load_finish(
525     IFAPI_KEYSTORE *keystore,
526     IFAPI_IO *io,
527     IFAPI_OBJECT *object)
528 {
529     TSS2_RC r;
530     json_object *jso = NULL;
531     uint8_t *buffer = NULL;
532     /* Keystore parameter is used to be prepared if transmission of state information
533        between async and finish will be necessary in future extensions. */
534     (void)keystore;
535 
536     r = ifapi_io_read_finish(io, &buffer, NULL);
537     return_try_again(r);
538     return_if_error(r, "keystore read_finish failed");
539 
540     /* If json objects can't be parse the object store is corrupted */
541     jso = json_tokener_parse((char *)buffer);
542     SAFE_FREE(buffer);
543     return_if_null(jso, "Keystore is corrupted (Json error).", TSS2_FAPI_RC_GENERAL_FAILURE);
544 
545     r = ifapi_json_IFAPI_OBJECT_deserialize(jso, object);
546     goto_if_error(r, "Deserialize object.", cleanup);
547 
548 cleanup:
549     SAFE_FREE(buffer);
550     if (jso)
551         json_object_put(jso);
552     LOG_TRACE("Return %x", r);
553     return r;
554 
555 }
556 
557 /**  Start writing FAPI object to the key store.
558  *
559  *  Keys objects, NV objects, and hierarchies can be written.
560  *
561  * @param[in] keystore The key directories and default profile.
562  * @param[in] io  The input/output context being used for file I/O.
563  * @param[in] path The relative path of the object. For keys the path will
564  *           expanded if possible.
565  * @param[in] object The object to be written to the keystore.
566  * @retval TSS2_RC_SUCCESS if the object is written successfully.
567  * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered;
568  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the output data.
569  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
570  *         the function.
571  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
572  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
573  */
574 TSS2_RC
ifapi_keystore_store_async(IFAPI_KEYSTORE * keystore,IFAPI_IO * io,const char * path,const IFAPI_OBJECT * object)575 ifapi_keystore_store_async(
576     IFAPI_KEYSTORE *keystore,
577     IFAPI_IO *io,
578     const char *path,
579     const IFAPI_OBJECT *object)
580 {
581     TSS2_RC r;
582     char *directory = NULL;
583     char *file = NULL;
584     char *jso_string = NULL;
585     json_object *jso = NULL;
586 
587     LOG_TRACE("Store object: %s", path);
588 
589     /* Prepare write operation: Create directories and valid object path */
590     r = expand_path(keystore, path, &directory);
591     goto_if_error(r, "Expand path", cleanup);
592 
593     if (object->system) {
594         r = ifapi_create_dirs(keystore->systemdir, directory);
595         goto_if_error2(r, "Directory %s could not be created.", cleanup, directory);
596 
597         r = expand_path_to_object(keystore, directory,
598                                   keystore->systemdir, &file);
599     } else {
600         r = ifapi_create_dirs(keystore->userdir, directory);
601         goto_if_error2(r, "Directory %s could not be created.", cleanup, directory);
602 
603         r = expand_path_to_object(keystore, directory,
604                                   keystore->userdir, &file);
605     }
606     goto_if_error2(r, "Object path %s could not be created.", cleanup, directory);
607 
608     /* Generate JSON string to be written to store */
609     r = ifapi_json_IFAPI_OBJECT_serialize(object, &jso);
610     goto_if_error2(r, "Object for %s could not be serialized.", cleanup, file);
611 
612     jso_string = strdup(json_object_to_json_string_ext(jso,
613                                                        JSON_C_TO_STRING_PRETTY));
614     goto_if_null2(jso_string, "Converting json to string", r, TSS2_FAPI_RC_MEMORY,
615                   cleanup);
616 
617     /* Start writing the json string to disk */
618     r = ifapi_io_write_async(io, file, (uint8_t *) jso_string, strlen(jso_string));
619     free(jso_string);
620     goto_if_error(r, "write_async failed", cleanup);
621 
622 cleanup:
623     if (jso)
624         json_object_put(jso);
625     SAFE_FREE(directory);
626     SAFE_FREE(file);
627     return r;
628 }
629 
630 /** Finish writing a FAPI object to the keystore.
631  *
632  * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
633  *
634  * @param[in] keystore The key directories and default profile.
635  * @param[in,out] io The input/output context being used for file I/O.
636  * @retval TSS2_RC_SUCCESS: if the function call was a success.
637  * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
638  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
639  *         Call this function again later.
640  */
641 TSS2_RC
ifapi_keystore_store_finish(IFAPI_KEYSTORE * keystore,IFAPI_IO * io)642 ifapi_keystore_store_finish(
643     IFAPI_KEYSTORE *keystore,
644     IFAPI_IO *io)
645 {
646     TSS2_RC r;
647 
648     /* Keystore parameter is used to be prepared if transmission of state information
649        between async and finish will be necessary in future extensions. */
650     (void)keystore;
651     /* Finish writing the object */
652     r = ifapi_io_write_finish(io);
653     return_try_again(r);
654 
655     LOG_TRACE("Return %x", r);
656     return_if_error(r, "read_finish failed");
657 
658     return TSS2_RC_SUCCESS;
659 }
660 
661 /** Create a list of all files in a certain directory.
662  *
663  * The list will be created in form of absolute pathnames.
664  *
665  * @param[in] keystore The key directories and default profile.
666  * @param[in] searchpath The sub directory in key store used for the
667  *            creation of the file list.
668  * @param[out] results The array of all absolute pathnames.
669  * @param[out] numresults The number of files.
670  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
671  */
672 static TSS2_RC
keystore_list_all_abs(IFAPI_KEYSTORE * keystore,const char * searchpath,char *** results,size_t * numresults)673 keystore_list_all_abs(
674     IFAPI_KEYSTORE *keystore,
675     const char *searchpath,
676     char ***results,
677     size_t *numresults)
678 {
679     TSS2_RC r;
680     char *expanded_search_path = NULL, *full_search_path = NULL;
681     size_t num_paths_system, num_paths_user, i, j;
682     char **file_ary, **file_ary_system, **file_ary_user;
683 
684     *numresults = 0;
685     file_ary_user = NULL;
686     file_ary_system = NULL;
687 
688     if (!searchpath || strcmp(searchpath, "") == 0 || strcmp(searchpath, "/") == 0) {
689         /* The complete keystore will be listed, no path expansion */
690         expanded_search_path = NULL;
691     } else {
692         r = expand_path(keystore, searchpath, &expanded_search_path);
693         return_if_error(r, "Out of memory.");
694     }
695 
696     /* Get the objects from system store */
697     r = ifapi_asprintf(&full_search_path, "%s%s%s", keystore->systemdir, IFAPI_FILE_DELIM,
698                        expanded_search_path ? expanded_search_path : "");
699     goto_if_error(r, "Out of memory.", cleanup);
700 
701     r = ifapi_io_dirfiles_all(full_search_path, &file_ary_system, &num_paths_system);
702     goto_if_error(r, "Get all files in directory.", cleanup);
703     SAFE_FREE(full_search_path);
704 
705     /* Get the objects from user store */
706     r = ifapi_asprintf(&full_search_path, "%s%s%s", keystore->userdir, IFAPI_FILE_DELIM,
707                        expanded_search_path ? expanded_search_path : "");
708     goto_if_error(r, "Out of memory.", cleanup);
709 
710     r = ifapi_io_dirfiles_all(full_search_path, &file_ary_user, &num_paths_user);
711 
712     *numresults = num_paths_system + num_paths_user;
713     SAFE_FREE(full_search_path);
714 
715     if (*numresults > 0) {
716 
717         /* Move file names from list to combined array */
718         file_ary = calloc(*numresults, sizeof(char *));
719         goto_if_null(file_ary, "Out of memory.", TSS2_FAPI_RC_MEMORY,
720                     cleanup);
721         i = 0;
722         for (j = 0; j < num_paths_system; j++)
723             file_ary[i++] = file_ary_system[j];
724         for (j = 0; j < num_paths_user; j++)
725             file_ary[i++] = file_ary_user[j];
726 
727         SAFE_FREE(file_ary_system);
728         SAFE_FREE(file_ary_user);
729         SAFE_FREE(expanded_search_path);
730         *results = file_ary;
731     }
732 
733 cleanup:
734     SAFE_FREE(file_ary_system);
735     SAFE_FREE(file_ary_user);
736     SAFE_FREE(expanded_search_path);
737     SAFE_FREE(full_search_path);
738     return r;
739 }
740 
741 /** Create a list of of objects in a certain search path.
742  *
743  * A vector of relative paths will be computed.
744  *
745  * @param[in] keystore The key directories, the default profile.
746  * @param[in] searchpath The relative search path in key store.
747  * @param[out] results The array with pointers to the relative object paths.
748  * @param[out] numresults The number of found objects.
749  * @retval TSS2_RC_SUCCESS on success.
750  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
751  */
752 TSS2_RC
ifapi_keystore_list_all(IFAPI_KEYSTORE * keystore,const char * searchpath,char *** results,size_t * numresults)753 ifapi_keystore_list_all(
754     IFAPI_KEYSTORE *keystore,
755     const char *searchpath,
756     char ***results,
757     size_t *numresults)
758 {
759     TSS2_RC r;
760     size_t i;
761 
762     r = keystore_list_all_abs(keystore, searchpath, results, numresults);
763     return_if_error(r, "Get all keystore objects.");
764 
765     if (*numresults > 0) {
766         /* Convert absolute path to relative path */
767         for (i = 0; i < *numresults; i++) {
768             full_path_to_fapi_path(keystore, (*results)[i]);
769         }
770     }
771     return r;
772 }
773 
774 /** Remove file storing a keystore object.
775  *
776  * @param[in] keystore The key directories, the default profile.
777  * @param[in] path The relative name of the object be removed.
778  * @retval TSS2_RC_SUCCESS On success.
779  * @retval TSS2_FAPI_RC_MEMORY: If memory could not be allocated.
780  * @retval TSS2_FAPI_RC_IO_ERROR If the file can't be removed.
781  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
782  *         during authorization.
783  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
784  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
785  *         the function.
786  */
787 TSS2_RC
ifapi_keystore_delete(IFAPI_KEYSTORE * keystore,char * path)788 ifapi_keystore_delete(
789     IFAPI_KEYSTORE * keystore,
790     char *path)
791 {
792     TSS2_RC r;
793     char *abs_path = NULL;
794 
795     /* Convert relative path to absolute path in keystore */
796     r = rel_path_to_abs_path(keystore, path, &abs_path);
797     goto_if_error2(r, "Object %s not found.", cleanup, path);
798 
799     r = ifapi_io_remove_file(abs_path);
800 
801 cleanup:
802     SAFE_FREE(abs_path);
803     return r;
804 }
805 
806 /** Expand directory name.
807  *
808  * Depending on the directory type the path will be expanded. For hierarchies
809  * the profile directory  will be added. For keys the implicit path will
810  * be expanded to an explicit path with all directories.
811  * @param[in] keystore The key directories and default profile.
812  * @param[in] path the implicit  path which has to be expanded if possible.
813  * @param[out] directory_name The explicit path (callee-allocated)
814  * @retval TSS2_RC_SUCCESS If the explicit path was created.
815  * @retval TSS2_FAPI_RC_MEMORY: If memory for the path list could not be allocated.
816  * @retval TSS2_FAPI_RC_BAD_VALUE If no explicit path can be derived from the
817  *         implicit path.
818  */
819 static TSS2_RC
expand_directory(IFAPI_KEYSTORE * keystore,const char * path,char ** directory_name)820 expand_directory(IFAPI_KEYSTORE *keystore, const char *path, char **directory_name)
821 {
822     TSS2_RC r;
823 
824     if (path && strcmp(path, "") != 0 && strcmp(path, "/") != 0) {
825         size_t start_pos = 0;
826         if (path[0] == IFAPI_FILE_DELIM_CHAR)
827             start_pos = 1;
828         if ((strncmp(&path[start_pos], "HS", 2) == 0 ||
829              strncmp(&path[start_pos], "HE", 2) == 0) &&
830             strlen(&path[start_pos]) <= 3) {
831             /* Root directory is hierarchy */
832             r = ifapi_asprintf(directory_name, "%s/", keystore->defaultprofile,
833                                path[start_pos]);
834             return_if_error(r, "Out of memory.");
835 
836         } else {
837             /* Try to expand a key path */
838             r = expand_path(keystore, path, directory_name);
839             return_if_error(r, "Out of memory.");
840         }
841     } else {
842         *directory_name = NULL;
843     }
844     return TSS2_RC_SUCCESS;
845 }
846 
847 /** Remove directories in keystore.
848  *
849  * If the expanded directory exists in userdir and systemdir both will be deleted.
850  *
851  * @param[in] keystore The key directories, the default profile.
852  * @param[in] dir_name The relative name of the directory to be removed.
853  * @retval TSS2_RC_SUCCESS on success.
854  * @retval TSS2_FAPI_RC_MEMORY: If memory could not be allocated.
855  * @retval TSS2_FAPI_RC_IO_ERROR If directory can't be deleted.
856  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
857  *         the function.
858  */
859 TSS2_RC
ifapi_keystore_remove_directories(IFAPI_KEYSTORE * keystore,const char * dir_name)860 ifapi_keystore_remove_directories(IFAPI_KEYSTORE *keystore, const char *dir_name)
861 {
862     TSS2_RC r = TSS2_RC_SUCCESS;
863     char *absolute_dir_path = NULL;
864     char *exp_dir_name = NULL;
865     struct stat fbuffer;
866 
867     r = expand_directory(keystore, dir_name, &exp_dir_name);
868     return_if_error(r, "Expand path string.");
869 
870     /* Cleanup user part of the store */
871     r = ifapi_asprintf(&absolute_dir_path, "%s%s%s", keystore->userdir, IFAPI_FILE_DELIM,
872                        exp_dir_name ? exp_dir_name : "");
873     goto_if_error(r, "Out of memory.", cleanup);
874 
875     if (stat(absolute_dir_path, &fbuffer) == 0) {
876         r = ifapi_io_remove_directories(absolute_dir_path);
877         goto_if_error2(r, "Could not remove: %s", cleanup, absolute_dir_path);
878     }
879     SAFE_FREE(absolute_dir_path);
880 
881     /* Cleanup system part of the store */
882     r = ifapi_asprintf(&absolute_dir_path, "%s%s%s", keystore->systemdir,
883                        IFAPI_FILE_DELIM, exp_dir_name ? exp_dir_name : "");
884     goto_if_error(r, "Out of memory.", cleanup);
885 
886     if (stat(absolute_dir_path, &fbuffer) == 0) {
887         r = ifapi_io_remove_directories(absolute_dir_path);
888         goto_if_error2(r, "Could not remove: %s", cleanup, absolute_dir_path);
889     }
890 
891 cleanup:
892     SAFE_FREE(absolute_dir_path);
893     SAFE_FREE(exp_dir_name);
894     return r;
895 }
896 
897 /** Predicate used as function parameter for object searching in keystore.
898  *
899  * @param[in] object The object from keystore which has to be compared.
900  * @param[in] cmp_object The object which will used for the comparison,
901  *            by the function with this signature.
902  * @retval true if the comparison is successful.
903  * @retval true if the comparison is not successful.
904  */
905 typedef TSS2_RC (*ifapi_keystore_object_cmp) (
906     IFAPI_OBJECT *object,
907     void *cmp_object,
908     bool *equal);
909 
910 /** Search object with a certain propoerty in keystore.
911  *
912  * @param[in,out] keystore The key directories, the default profile, and the
913  *               state information for the asynchronous search.
914  * @param[in] io The input/output context being used for file I/O.
915  * @param[in] name The name of the searched key.
916  * @param[out] found_path The relative path of the found key.
917  * @retval TSS2_RC_SUCCESS on success.
918  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
919  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND If the key was not found in keystore.
920  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
921  *         during authorization.
922  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
923  *         this function needs to be called again.
924  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
925  *         operation already pending.
926  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
927  *         the function.
928  * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
929  *         object store.
930  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
931  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
932  */
933 static TSS2_RC
keystore_search_obj(IFAPI_KEYSTORE * keystore,IFAPI_IO * io,void * cmp_object,ifapi_keystore_object_cmp cmp_function,char ** found_path)934 keystore_search_obj(
935     IFAPI_KEYSTORE *keystore,
936     IFAPI_IO *io,
937     void *cmp_object,
938     ifapi_keystore_object_cmp cmp_function,
939     char **found_path)
940 {
941     TSS2_RC r;
942     UINT32 path_idx;
943     char *path;
944     IFAPI_OBJECT object;
945     size_t i;
946 
947     switch (keystore->key_search.state) {
948     statecase(keystore->key_search.state, KSEARCH_INIT)
949         r = ifapi_keystore_list_all(keystore,
950                                     "/", /**< search keys and NV objects in store */
951                                     &keystore->key_search.pathlist,
952                                     &keystore->key_search.numPaths);
953         goto_if_error2(r, "Get entities.", cleanup);
954 
955         keystore->key_search.path_idx = keystore->key_search.numPaths;
956         fallthrough;
957 
958     statecase(keystore->key_search.state, KSEARCH_SEARCH_OBJECT)
959         /* Use the next object in the path list */
960         if (keystore->key_search.path_idx == 0) {
961             goto_error(r, TSS2_FAPI_RC_PATH_NOT_FOUND, "Key not found.", cleanup);
962         }
963         keystore->key_search.path_idx -= 1;
964         path_idx = keystore->key_search.path_idx;
965         path = keystore->key_search.pathlist[path_idx];
966         LOG_TRACE("Check file: %s %zu", path, keystore->key_search.path_idx);
967 
968         r = ifapi_keystore_load_async(keystore, io, path);
969         return_if_error2(r, "Could not open: %s", path);
970 
971         fallthrough;
972 
973     statecase(keystore->key_search.state, KSEARCH_READ)
974         r = ifapi_keystore_load_finish(keystore, io, &object);
975         return_try_again(r);
976         goto_if_error(r, "read_finish failed", cleanup);
977 
978         /* Check whether the key has the passed name */
979         bool keys_equal;
980         r = cmp_function(&object, cmp_object, &keys_equal);
981         ifapi_cleanup_ifapi_object(&object);
982         goto_if_error(r, "Invalid object.", cleanup);
983 
984         if (!keys_equal) {
985             /* Try next key */
986             keystore->key_search.state = KSEARCH_SEARCH_OBJECT;
987             return TSS2_FAPI_RC_TRY_AGAIN;
988         }
989         /* Key found, the absolute path will be converted to relative path. */
990         path_idx = keystore->key_search.path_idx;
991         *found_path = strdup(keystore->key_search.pathlist[path_idx]);
992         goto_if_null(*found_path, "Out of memory.",
993                      TSS2_FAPI_RC_MEMORY, cleanup);
994         full_path_to_fapi_path(keystore, *found_path);
995         break;
996 
997     statecasedefault(keystore->key_search.state);
998     }
999 cleanup:
1000     for (i = 0; i < keystore->key_search.numPaths; i++)
1001         free(keystore->key_search.pathlist[i]);
1002     free(keystore->key_search.pathlist);
1003     if (!*found_path) {
1004         LOG_ERROR("Object not found");
1005         r = TSS2_FAPI_RC_KEY_NOT_FOUND;
1006     }
1007     keystore->key_search.state = KSEARCH_INIT;
1008     return r;
1009 }
1010 
1011 /** Search object with a certain name in keystore.
1012  *
1013  * @param[in,out] keystore The key directories, the default profile, and the
1014  *               state information for the asynchronous search.
1015  * @param[in] io The input/output context being used for file I/O.
1016  * @param[in] name The name of the searched object.
1017  * @param[out] found_path The relative path of the found key.
1018  * @retval TSS2_RC_SUCCESS on success.
1019  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
1020  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND If the key was not found in keystore.
1021  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
1022  *         during authorization.
1023  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1024  *         this function needs to be called again.
1025  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1026  *         operation already pending.
1027  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1028  *         the function.
1029  * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
1030  *         object store.
1031  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1032  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1033  */
1034 TSS2_RC
ifapi_keystore_search_obj(IFAPI_KEYSTORE * keystore,IFAPI_IO * io,TPM2B_NAME * name,char ** found_path)1035 ifapi_keystore_search_obj(
1036     IFAPI_KEYSTORE *keystore,
1037     IFAPI_IO *io,
1038     TPM2B_NAME *name,
1039     char **found_path)
1040 {
1041     return keystore_search_obj(keystore, io, name,
1042                                ifapi_object_cmp_name, found_path);
1043 }
1044 
1045 /** Search nv object with a certain nv_index (from nv_public) in keystore.
1046  *
1047  * @param[in,out] keystore The key directories, the default profile, and the
1048  *               state information for the asynchronous search.
1049  * @param[in] io The input/output context being used for file I/O.
1050  * @param[in] nv_public The public data of the searched nv object.
1051  * @param[out] found_path The relative path of the found key.
1052  * @retval TSS2_RC_SUCCESS on success.
1053  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
1054  * @retval TSS2_FAPI_RC_KEY_NOT_FOUND If the key was not found in keystore.
1055  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1056  *         the function.
1057  * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
1058  *         during authorization.
1059  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1060  *         this function needs to be called again.
1061  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1062  *         operation already pending.
1063  * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
1064  *         object store.
1065  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1066  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1067  * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS if the object already exists in object store.
1068  */
1069 TSS2_RC
ifapi_keystore_search_nv_obj(IFAPI_KEYSTORE * keystore,IFAPI_IO * io,TPM2B_NV_PUBLIC * nv_public,char ** found_path)1070 ifapi_keystore_search_nv_obj(
1071     IFAPI_KEYSTORE *keystore,
1072     IFAPI_IO *io,
1073     TPM2B_NV_PUBLIC *nv_public,
1074     char **found_path)
1075 {
1076     return keystore_search_obj(keystore, io, nv_public,
1077                                ifapi_object_cmp_nv_public, found_path);
1078 }
1079 
1080  /** Check whether keystore object already exists.
1081   *
1082   * The passed relative path will be expanded for user store and system store.
1083   *
1084   *  Keys objects, NV objects, and hierarchies can be written.
1085   *
1086   * @param[in] keystore The key directories and default profile.
1087   * @param[in] io  The input/output context being used for file I/O.
1088   * @param[in] path The relative path of the object. For keys the path will
1089   *           expanded if possible.
1090   * @retval TSS2_RC_SUCCESS if the object does not exist.
1091   * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS if the file in objects exists.
1092   * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the output data.
1093   */
1094 TSS2_RC
ifapi_keystore_check_overwrite(IFAPI_KEYSTORE * keystore,IFAPI_IO * io,const char * path)1095 ifapi_keystore_check_overwrite(
1096     IFAPI_KEYSTORE *keystore,
1097     IFAPI_IO *io,
1098     const char *path)
1099 {
1100     TSS2_RC r;
1101     char *directory = NULL;
1102     char *file = NULL;
1103     (void)io; /* Used to simplify future extensions */
1104 
1105     /* Expand relative path */
1106     r = expand_path(keystore, path, &directory);
1107     goto_if_error(r, "Expand path", cleanup);
1108 
1109     /* Expand absolute path for user and system directory */
1110     r = expand_path_to_object(keystore, directory,
1111                               keystore->systemdir, &file);
1112     goto_if_error(r, "Expand path to object", cleanup);
1113 
1114     if (ifapi_io_path_exists(file)) {
1115         goto_error(r, TSS2_FAPI_RC_PATH_ALREADY_EXISTS,
1116                    "Object %s already exists.", cleanup, path);
1117     }
1118     SAFE_FREE(file);
1119     r = expand_path_to_object(keystore, directory,
1120                               keystore->userdir, &file);
1121     goto_if_error(r, "Expand path to object", cleanup);
1122 
1123     if (ifapi_io_path_exists(file)) {
1124         goto_error(r, TSS2_FAPI_RC_PATH_ALREADY_EXISTS,
1125                    "Object %s already exists.", cleanup, path);
1126     }
1127     r = TSS2_RC_SUCCESS;
1128 
1129 cleanup:
1130     SAFE_FREE(directory);
1131     SAFE_FREE(file);
1132     return r;
1133 }
1134 
1135 /** Check whether keystore object is writeable.
1136  *
1137  * The passed relative path will be expanded first for  user store, second for
1138  * system store if the file does not exist in system store.
1139  *
1140  *  Keys objects, NV objects, and hierarchies can be written.
1141  *
1142  * @param[in] keystore The key directories and default profile.
1143  * @param[in] io  The input/output context being used for file I/O.
1144  * @param[in] path The relative path of the object. For keys the path will
1145  *           expanded if possible.
1146  * @retval TSS2_RC_SUCCESS if the object does not exist.
1147  * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS if the file in objects exists.
1148  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the output data.
1149  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1150  *         the function.
1151  * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
1152  *         object store.
1153  */
1154 TSS2_RC
ifapi_keystore_check_writeable(IFAPI_KEYSTORE * keystore,IFAPI_IO * io,const char * path)1155 ifapi_keystore_check_writeable(
1156     IFAPI_KEYSTORE *keystore,
1157     IFAPI_IO *io,
1158     const char *path)
1159 {
1160     TSS2_RC r;
1161     char *directory = NULL;
1162     char *file = NULL;
1163     (void)io; /* Used to simplify future extensions */
1164 
1165     /* Expand relative path */
1166     r = expand_path(keystore, path, &directory);
1167     goto_if_error(r, "Expand path", cleanup);
1168 
1169     /* Expand absolute path for user and system directory */
1170     r = expand_path_to_object(keystore, directory,
1171                               keystore->userdir, &file);
1172     goto_if_error(r, "Expand path to object", cleanup);
1173 
1174     if (ifapi_io_path_exists(file)) {
1175         r = ifapi_io_check_file_writeable(file);
1176         goto_if_error2(r, "Object %s is not writable.", cleanup, path);
1177 
1178         /* File can be written */
1179         goto cleanup;
1180     } else {
1181         SAFE_FREE(file);
1182         r = expand_path_to_object(keystore, directory,
1183                                   keystore->systemdir, &file);
1184         goto_if_error(r, "Expand path to object", cleanup);
1185 
1186         if (ifapi_io_path_exists(file)) {
1187              r = ifapi_io_check_file_writeable(file);
1188              goto_if_error2(r, "Object %s is not writable.", cleanup, path);
1189 
1190              /* File can be written */
1191              goto cleanup;
1192         }
1193     }
1194 
1195 cleanup:
1196     SAFE_FREE(directory);
1197     SAFE_FREE(file);
1198     return r;
1199 }
1200 
1201 /** Create a copy of a an UINT8 array..
1202  *
1203  * @param[out] dest The caller allocated array which will be the
1204  *                  destination of the copy operation.
1205  * @param[in]  src  The source array.
1206  *
1207  * @retval TSS2_RC_SUCCESS if the function call was a success.
1208  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1209  */
1210 static TSS2_RC
copy_uint8_ary(UINT8_ARY * dest,const UINT8_ARY * src)1211 copy_uint8_ary(UINT8_ARY *dest, const UINT8_ARY * src) {
1212     TSS2_RC r = TSS2_RC_SUCCESS;
1213 
1214     /* Check the parameters if they are valid */
1215     if (src == NULL || dest == NULL) {
1216         return TSS2_FAPI_RC_BAD_REFERENCE;
1217     }
1218 
1219     /* Initialize the object variables for a possible error cleanup */
1220     dest->buffer = NULL;
1221 
1222     /* Create the copy */
1223     dest->size = src->size;
1224     dest->buffer = malloc(dest->size);
1225     goto_if_null(dest->buffer, "Out of memory.", r, error_cleanup);
1226     memcpy(dest->buffer, src->buffer, dest->size);
1227 
1228     return r;
1229 
1230 error_cleanup:
1231     SAFE_FREE(dest->buffer);
1232     return r;
1233 }
1234 
1235 /** Create a copy of a an ifapi key.
1236  *
1237  * @param[out] dest The caller allocated key object which will be the
1238  *                  destination of the copy operation.
1239  * @param[in]  src  The source key.
1240  *
1241  * @retval TSS2_RC_SUCCESS if the function call was a success.
1242  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1243  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1244  */
1245 TSS2_RC
ifapi_copy_ifapi_key(IFAPI_KEY * dest,const IFAPI_KEY * src)1246 ifapi_copy_ifapi_key(IFAPI_KEY * dest, const IFAPI_KEY * src) {
1247     TSS2_RC r = TSS2_RC_SUCCESS;
1248 
1249     /* Check the parameters if they are valid */
1250     if (src == NULL || dest == NULL) {
1251         return TSS2_FAPI_RC_BAD_REFERENCE;
1252     }
1253 
1254     /* Initialize the object variables for a possible error cleanup */
1255     dest->private.buffer = NULL;
1256     dest->serialization.buffer = NULL;
1257     dest->appData.buffer = NULL;
1258     dest->policyInstance = NULL;
1259     dest->description = NULL;
1260 
1261     /* Create the copy */
1262 
1263     r = copy_uint8_ary(&dest->private, &src->private);
1264     goto_if_error(r, "Could not copy private", error_cleanup);
1265     r = copy_uint8_ary(&dest->serialization, &src->serialization);
1266     goto_if_error(r, "Could not copy serialization", error_cleanup);
1267     r = copy_uint8_ary(&dest->appData, &src->appData);
1268     goto_if_error(r, "Could not copy appData", error_cleanup);
1269 
1270     strdup_check(dest->policyInstance, src->policyInstance, r, error_cleanup);
1271     strdup_check(dest->description, src->description, r, error_cleanup);
1272     strdup_check(dest->certificate, src->certificate, r, error_cleanup);
1273 
1274     dest->persistent_handle = src->persistent_handle;
1275     dest->public = src->public;
1276     dest->creationData = src->creationData;
1277     dest->creationTicket = src->creationTicket;
1278     dest->signing_scheme = src->signing_scheme;
1279     dest->name = src->name;
1280     dest->with_auth = src->with_auth;
1281 
1282     return r;
1283 
1284 error_cleanup:
1285     ifapi_cleanup_ifapi_key(dest);
1286     return r;
1287 }
1288 
1289 /** Free memory allocated during deserialization of a key object.
1290  *
1291  * The key will not be freed (might be declared on the stack).
1292  *
1293  * @param[in] key The key object to be cleaned up.
1294  *
1295  */
1296 void
ifapi_cleanup_ifapi_key(IFAPI_KEY * key)1297 ifapi_cleanup_ifapi_key(IFAPI_KEY * key) {
1298     if (key != NULL) {
1299         SAFE_FREE(key->policyInstance);
1300         SAFE_FREE(key->serialization.buffer);
1301         SAFE_FREE(key->private.buffer);
1302         SAFE_FREE(key->description);
1303         SAFE_FREE(key->certificate);
1304         SAFE_FREE(key->appData.buffer);
1305     }
1306 }
1307 
1308 /** Free memory allocated during deserialization of a pubkey object.
1309  *
1310  * The pubkey will not be freed (might be declared on the stack).
1311  *
1312  * @param[in] key The pubkey object to be cleaned up.
1313  */
1314 void
ifapi_cleanup_ifapi_ext_pub_key(IFAPI_EXT_PUB_KEY * key)1315 ifapi_cleanup_ifapi_ext_pub_key(IFAPI_EXT_PUB_KEY * key) {
1316     if (key != NULL) {
1317         SAFE_FREE(key->pem_ext_public);
1318         SAFE_FREE(key->certificate);
1319     }
1320 }
1321 
1322 /** Free memory allocated during deserialization of a hierarchy object.
1323  *
1324  * The hierarchy object will not be freed (might be declared on the stack).
1325  *
1326  * @param[in] hierarchy The hierarchy object to be cleaned up.
1327  */
1328 void
ifapi_cleanup_ifapi_hierarchy(IFAPI_HIERARCHY * hierarchy)1329 ifapi_cleanup_ifapi_hierarchy(IFAPI_HIERARCHY * hierarchy) {
1330     if (hierarchy != NULL) {
1331         SAFE_FREE(hierarchy->description);
1332     }
1333 }
1334 
1335 /** Free memory allocated during deserialization of a nv object.
1336  *
1337  * The nv object will not be freed (might be declared on the stack).
1338  *
1339  * @param[in] nv The nv object to be cleaned up.
1340  */
1341 void
ifapi_cleanup_ifapi_nv(IFAPI_NV * nv)1342 ifapi_cleanup_ifapi_nv(IFAPI_NV * nv) {
1343     if (nv != NULL) {
1344         SAFE_FREE(nv->serialization.buffer);
1345         SAFE_FREE(nv->appData.buffer);
1346         SAFE_FREE(nv->policyInstance);
1347         SAFE_FREE(nv->description);
1348         SAFE_FREE(nv->event_log);
1349     }
1350 }
1351 
1352 /** Free memory allocated during deserialization of a duplicate object.
1353  *
1354  * The duplicate object will not be freed (might be declared on the stack).
1355  *
1356  * @param[in] duplicate The duplicate object to be cleaned up.
1357  */
1358 void
ifapi_cleanup_ifapi_duplicate(IFAPI_DUPLICATE * duplicate)1359 ifapi_cleanup_ifapi_duplicate(IFAPI_DUPLICATE * duplicate) {
1360     if (duplicate != NULL) {
1361         SAFE_FREE(duplicate->certificate);
1362     }
1363 }
1364 
1365 /** Free keystore related memory allocated during FAPI initialization.
1366  *
1367  * The keystore object will not be freed (might be declared on the stack).
1368  *
1369  * @param[in] keystore The kystore object to be cleaned up.
1370  */
1371 void
ifapi_cleanup_ifapi_keystore(IFAPI_KEYSTORE * keystore)1372 ifapi_cleanup_ifapi_keystore(IFAPI_KEYSTORE * keystore) {
1373     if (keystore != NULL) {
1374         SAFE_FREE(keystore->systemdir);
1375         SAFE_FREE(keystore->userdir);
1376         SAFE_FREE(keystore->defaultprofile);
1377     }
1378 }
1379 
1380 /** Create a copy of a an ifapi object storing a key.
1381  *
1382  * The key together with the policy of the key will be copied.
1383  *
1384  * @param[out] dest The caller allocated key object which will be the
1385  *                  destination of the copy operation.
1386  * @param[in]  src  The source key.
1387  *
1388  * @retval TSS2_RC_SUCCESS if the function call was a success.
1389  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if the source is not of type key.
1390  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1391  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1392  */
1393 TSS2_RC
ifapi_copy_ifapi_key_object(IFAPI_OBJECT * dest,const IFAPI_OBJECT * src)1394 ifapi_copy_ifapi_key_object(IFAPI_OBJECT * dest, const IFAPI_OBJECT * src) {
1395     TSS2_RC r = TSS2_RC_SUCCESS;
1396 
1397     /* Check the parameters if they are valid */
1398     if (src == NULL || dest == NULL) {
1399         return TSS2_FAPI_RC_BAD_REFERENCE;
1400     }
1401 
1402     if (src->objectType != IFAPI_KEY_OBJ) {
1403         LOG_ERROR("Bad object type");
1404         return TSS2_FAPI_RC_GENERAL_FAILURE;
1405     }
1406 
1407     /* Initialize the object variables for a possible error cleanup */
1408 
1409     /* Create the copy */
1410     dest->policy = ifapi_copy_policy(src->policy);
1411 
1412     ifapi_copy_ifapi_key(&dest->misc.key, &src->misc.key);
1413     goto_if_error(r, "Could not copy key", error_cleanup);
1414 
1415     dest->objectType = src->objectType;
1416     dest->system = src->system;
1417     dest->handle = src->handle;
1418     dest->authorization_state = src->authorization_state;
1419 
1420     return r;
1421 
1422 error_cleanup:
1423     ifapi_cleanup_ifapi_object(dest);
1424     return r;
1425 }
1426 
1427 /** Free memory allocated during deserialization of object.
1428  *
1429  * The object will not be freed (might be declared on the stack).
1430  *
1431  * @param[in]  object The object to be cleaned up.
1432  *
1433  */
1434 void
ifapi_cleanup_ifapi_object(IFAPI_OBJECT * object)1435 ifapi_cleanup_ifapi_object(
1436     IFAPI_OBJECT * object)
1437 {
1438     if (object != NULL) {
1439         if (object->objectType != IFAPI_OBJ_NONE) {
1440             if (object->objectType == IFAPI_KEY_OBJ) {
1441                 ifapi_cleanup_ifapi_key(&object->misc.key);
1442             } else if (object->objectType == IFAPI_NV_OBJ) {
1443                 ifapi_cleanup_ifapi_nv(&object->misc.nv);
1444             } else if (object->objectType == IFAPI_DUPLICATE_OBJ) {
1445                 ifapi_cleanup_ifapi_duplicate(&object->misc.key_tree);
1446             } else if (object->objectType == IFAPI_EXT_PUB_KEY_OBJ) {
1447                 ifapi_cleanup_ifapi_ext_pub_key(&object->misc.ext_pub_key);
1448             } else if (object->objectType == IFAPI_HIERARCHY_OBJ) {
1449                 ifapi_cleanup_ifapi_hierarchy(&object->misc.hierarchy);
1450             }
1451 
1452             ifapi_cleanup_policy(object->policy);
1453             SAFE_FREE(object->policy);
1454             object->objectType = IFAPI_OBJ_NONE;
1455         }
1456     }
1457 }
1458