blob: 29455e1fa758ce0d3ea67e136232c4dfd6317279 [file] [log] [blame]
/* 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;
}