| /* SPDX-License-Identifier: BSD-2-Clause */ |
| /******************************************************************************* |
| * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG |
| * All rights reserved. |
| *******************************************************************************/ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #include <dirent.h> |
| #endif |
| |
| #include "ifapi_io.h" |
| #include "ifapi_helpers.h" |
| #include "ifapi_policy_types.h" |
| #include "ifapi_policy_store.h" |
| #include "ifapi_macros.h" |
| #define LOGMODULE fapi |
| #include "util/log.h" |
| #include "util/aux_util.h" |
| #include "ifapi_policy_json_deserialize.h" |
| #include "ifapi_policy_json_serialize.h" |
| |
| /** Compute absolute path of policy for IO. |
| * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated. |
| */ |
| static TSS2_RC |
| policy_rel_path_to_abs_path( |
| IFAPI_POLICY_STORE *pstore, |
| const char *rel_path, |
| char **abs_path) |
| { |
| TSS2_RC r; |
| |
| if (ifapi_path_type_p(rel_path, IFAPI_POLICY_PATH)) { |
| r = ifapi_asprintf(abs_path, "%s%s%s.json", pstore->policydir, |
| IFAPI_FILE_DELIM, rel_path); |
| } else { |
| r = ifapi_asprintf(abs_path, "%s%s%s%s%s.json", pstore->policydir, |
| IFAPI_FILE_DELIM, IFAPI_POLICY_PATH, IFAPI_FILE_DELIM, rel_path); |
| |
| } |
| return_if_error(r, "Create policy file name."); |
| return r; |
| } |
| /** Remove file storing a policy object. |
| * |
| * @param[in] pstore The policy directory. |
| * @param[in] path The relative name of the object be removed. |
| * @retval TSS2_RC_SUCCESS On success. |
| * @retval TSS2_FAPI_RC_MEMORY: If memory could not be allocated. |
| * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If no file is found in policy store. |
| * @retval TSS2_FAPI_RC_IO_ERROR If the file can't be removed. |
| */ |
| TSS2_RC |
| ifapi_policy_delete( |
| IFAPI_POLICY_STORE * pstore, |
| char *path) |
| { |
| TSS2_RC r; |
| char *abs_path = NULL; |
| |
| /* Convert relative path to absolute path in policy store */ |
| r = policy_rel_path_to_abs_path(pstore, path, &abs_path); |
| goto_if_error2(r, "Path %s could not be created.", cleanup, path); |
| |
| if (!ifapi_io_path_exists(abs_path)) { |
| goto_error(r, TSS2_FAPI_RC_PATH_NOT_FOUND, |
| "Policy %s not found.", cleanup, path); |
| } |
| |
| if (remove(abs_path) != 0) { |
| LOG_WARNING("File: %s can't be deleted.", abs_path); |
| } |
| |
| cleanup: |
| SAFE_FREE(abs_path); |
| return r; |
| } |
| |
| /** Store policy store parameters in the policy store context. |
| * |
| * Also the user directory will be created if it does not exist. |
| * |
| * @param[out] pstore The keystore to be initialized. |
| * @param[in] config_policydir The configured policy directory. |
| * @retval TSS2_RC_SUCCESS If the keystore can be initialized. |
| * @retval TSS2_FAPI_RC_IO_ERROR If the policy store can't be |
| * initialized. |
| * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated. |
| * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into |
| * the function. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| */ |
| TSS2_RC |
| ifapi_policy_store_initialize( |
| IFAPI_POLICY_STORE *pstore, |
| const char *config_policydir) |
| { |
| TSS2_RC r; |
| char *policy_dir = NULL; |
| |
| memset(pstore, 0, sizeof(IFAPI_POLICY_STORE)); |
| check_not_null(config_policydir); |
| |
| strdup_check(pstore->policydir, config_policydir, r, error); |
| |
| r = ifapi_asprintf(&policy_dir, "%s%s%s", config_policydir, |
| (strcmp(&config_policydir[strlen(config_policydir) - 1], |
| IFAPI_FILE_DELIM) == 0) ? "" : IFAPI_FILE_DELIM, |
| IFAPI_POLICY_PATH); |
| goto_if_error(r, "Out of memory.", error); |
| |
| r = ifapi_io_check_create_dir(policy_dir, FAPI_READ); |
| goto_if_error2(r, "Policy directory %s can't be created.", error, policy_dir); |
| |
| SAFE_FREE(policy_dir); |
| return TSS2_RC_SUCCESS; |
| |
| error: |
| SAFE_FREE(policy_dir); |
| return r; |
| } |
| |
| /** Start loading FAPI policy from policy store. |
| * |
| * Keys objects, NV objects, and hierarchies can be loaded. |
| * |
| * @param[in] pstore The policy directory. |
| * @param[in] io The input/output context being used for file I/O. |
| * @param[in] path The relative path of the object. For keys the path will |
| * expanded if possible. |
| * @retval TSS2_RC_SUCCESS If the object can be read. |
| * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered. |
| * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the file does not exist. |
| * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data. |
| */ |
| TSS2_RC |
| ifapi_policy_store_load_async( |
| IFAPI_POLICY_STORE *pstore, |
| IFAPI_IO *io, |
| const char *path) |
| { |
| TSS2_RC r; |
| char *abs_path = NULL; |
| |
| LOG_TRACE("Load policy: %s", path); |
| |
| /* First it will be checked whether the only valid characters occur in the path. */ |
| r = ifapi_check_valid_path(path); |
| return_if_error(r, "Invalid path."); |
| |
| /* Free old input buffer if buffer exists */ |
| SAFE_FREE(io->char_rbuffer); |
| |
| /* Convert relative path to absolute path in keystore */ |
| r = policy_rel_path_to_abs_path(pstore, path, &abs_path); |
| goto_if_error2(r, "Object %s not found.", cleanup, path); |
| |
| /* Prepare read operation */ |
| r = ifapi_io_read_async(io, abs_path); |
| |
| cleanup: |
| SAFE_FREE(abs_path); |
| return r; |
| } |
| |
| /** Finish loading FAPI policy from policy store. |
| * |
| * |
| * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN. |
| * |
| * @param[in] pstore The policy context with the policy directory. |
| * @param[in,out] io The input/output context being used for file I/O. |
| * @param[in] policy The caller allocated policy which will loaded from policy store. |
| * @retval TSS2_RC_SUCCESS After successfully loading the object. |
| * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete. |
| * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into |
| * the function. |
| * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated. |
| */ |
| TSS2_RC |
| ifapi_policy_store_load_finish( |
| IFAPI_POLICY_STORE *pstore, |
| IFAPI_IO *io, |
| TPMS_POLICY *policy) |
| { |
| TSS2_RC r; |
| json_object *jso = NULL; |
| uint8_t *buffer = NULL; |
| /* ptore parameter is used to be prepared if transmission of state information |
| between async and finish will be necessary in future extensions. */ |
| (void)pstore; |
| |
| r = ifapi_io_read_finish(io, &buffer, NULL); |
| return_try_again(r); |
| return_if_error(r, "keystore read_finish failed"); |
| |
| /* If json objects can't be parse the object store is corrupted */ |
| jso = json_tokener_parse((char *)buffer); |
| SAFE_FREE(buffer); |
| return_if_null(jso, "Policy store is corrupted (Json error).", TSS2_FAPI_RC_GENERAL_FAILURE); |
| |
| r = ifapi_json_TPMS_POLICY_deserialize(jso, policy); |
| goto_if_error(r, "Deserialize policy", cleanup); |
| |
| cleanup: |
| SAFE_FREE(buffer); |
| if (jso) |
| json_object_put(jso); |
| LOG_TRACE("Return %x", r); |
| return r; |
| |
| } |
| |
| /** Start writing FAPI object to the key store. |
| * |
| * The relative path will be expanded, if the default policy directory (/policy) |
| * is not part of the path. |
| * |
| * @param[in] pstore The policy context with the policy directory. |
| * @param[in] io The input/output context being used for file I/O. |
| * @param[in] path The relative path of the policy. |
| * @param[in] policy The policy to be written to the policy store. |
| * @retval TSS2_RC_SUCCESS If the policy is written successfully. |
| * @retval TSS2_FAPI_RC_IO_ERROR: If an I/O error was encountered; |
| * @retval TSS2_FAPI_RC_MEMORY: If memory could not be allocated to hold the output data. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into |
| * the function. |
| */ |
| TSS2_RC |
| ifapi_policy_store_store_async( |
| IFAPI_POLICY_STORE *pstore, |
| IFAPI_IO *io, |
| const char *path, |
| const TPMS_POLICY *policy) |
| { |
| TSS2_RC r; |
| char *jso_string = NULL; |
| json_object *jso = NULL; |
| char *abs_path = NULL; |
| |
| LOG_TRACE("Store policy: %s", path); |
| |
| /* Convert relative path to absolute path in the policy store */ |
| r = policy_rel_path_to_abs_path(pstore, path, &abs_path); |
| goto_if_error2(r, "Path %s could not be created.", cleanup, path); |
| |
| /* Generate JSON string to be written to store */ |
| r = ifapi_json_TPMS_POLICY_serialize(policy, &jso); |
| goto_if_error2(r, "Policy %s could not be serialized.", cleanup, path); |
| |
| jso_string = strdup(json_object_to_json_string_ext(jso, |
| JSON_C_TO_STRING_PRETTY)); |
| goto_if_null2(jso_string, "Converting json to string", r, TSS2_FAPI_RC_MEMORY, |
| cleanup); |
| |
| /* Start writing the json string to disk */ |
| r = ifapi_io_write_async(io, abs_path, (uint8_t *) jso_string, strlen(jso_string)); |
| free(jso_string); |
| goto_if_error(r, "write_async failed", cleanup); |
| |
| cleanup: |
| if (jso) |
| json_object_put(jso); |
| SAFE_FREE(abs_path); |
| return r; |
| } |
| |
| /** Finish writing a FAPI policy object to the policy store. |
| * |
| * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN. |
| * |
| * @param[in] pstore The policy context with the policy directory. |
| * @param[in,out] io The input/output context being used for file I/O. |
| * @retval TSS2_RC_SUCCESS: if the function call was a success. |
| * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete. |
| Call this function again later. |
| */ |
| TSS2_RC |
| ifapi_policy_store_store_finish( |
| IFAPI_POLICY_STORE *pstore, |
| IFAPI_IO *io) |
| { |
| TSS2_RC r; |
| |
| /* Pstore parameter is used to be prepared if transmission of state information |
| between async and finish will be necessary in future extensions. */ |
| (void)pstore; |
| /* Finish writing the policy */ |
| r = ifapi_io_write_finish(io); |
| return_try_again(r); |
| |
| LOG_TRACE("Return %x", r); |
| return_if_error(r, "read_finish failed"); |
| |
| return TSS2_RC_SUCCESS; |
| } |