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