blob: b75a4eb2135c5c1d39adc86f04f63520ce00da81 [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>
#endif
#include <json-c/json.h>
#include <json-c/json_util.h>
#include "util/aux_util.h"
#include "ifapi_config.h"
#include "ifapi_json_deserialize.h"
#include "tpm_json_deserialize.h"
#include "ifapi_json_serialize.h"
#include "tpm_json_serialize.h"
#include "ifapi_helpers.h"
#define LOGMODULE fapi
#include "util/log.h"
/**
* The path of the default config file
*/
#define DEFAULT_CONFIG_FILE (SYSCONFDIR "/tpm2-tss/fapi-config.json")
/** Deserializes a configuration JSON object.
*
* @param[in] jso The JSON object to be deserialized
* @param[out] out The deserialized configuration object
*
* @retval TSS2_RC_SUCCESS on success
* @retval TSS2_FAPI_RC_BAD_REFERENCE if jso or out is NULL
* @retval TSS2_FAPI_RC_BAD_VALUE if the JSON object cannot be deserialized
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
static TSS2_RC
ifapi_json_IFAPI_CONFIG_deserialize(json_object *jso, IFAPI_CONFIG *out)
{
/* Check for NULL parameters */
return_if_null(out, "out is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
return_if_null(jso, "jso is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
memset(out, 0, sizeof(IFAPI_CONFIG));
/* Deserialize the JSON object) */
json_object *jso2;
TSS2_RC r;
LOG_TRACE("call");
if (ifapi_get_sub_object(jso, "profile_dir", &jso2)) {
r = ifapi_json_char_deserialize(jso2, &out->profile_dir);
return_if_error(r, "BAD VALUE");
}
if (ifapi_get_sub_object(jso, "user_dir", &jso2)) {
r = ifapi_json_char_deserialize(jso2, &out->user_dir);
return_if_error(r, "BAD VALUE");
}
if (ifapi_get_sub_object(jso, "system_dir", &jso2)) {
r = ifapi_json_char_deserialize(jso2, &out->keystore_dir);
return_if_error(r, "BAD VALUE");
}
if (!ifapi_get_sub_object(jso, "log_dir", &jso2)) {
out->log_dir = strdup(DEFAULT_LOG_DIR);
return_if_null(jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
} else {
r = ifapi_json_char_deserialize(jso2, &out->log_dir);
return_if_error(r, "BAD VALUE");
}
if (!ifapi_get_sub_object(jso, "profile_name", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_char_deserialize(jso2, &out->profile_name);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "tcti", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_char_deserialize(jso2, &out->tcti);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "system_pcrs", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPML_PCR_SELECTION_deserialize(jso2, &out->system_pcrs);
return_if_error(r, "BAD VALUE");
if (ifapi_get_sub_object(jso, "ek_cert_file", &jso2)) {
r = ifapi_json_char_deserialize(jso2, &out->ek_cert_file);
return_if_error(r, "BAD VALUE");
}
if (ifapi_get_sub_object(jso, "ek_cert_less", &jso2)) {
r = ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->ek_cert_less);
return_if_error(r, "BAD VALUE");
} else {
out->ek_cert_less = TPM2_NO;
}
if (ifapi_get_sub_object(jso, "ek_fingerprint", &jso2)) {
r = ifapi_json_TPMT_HA_deserialize(jso2, &out->ek_fingerprint);
return_if_error(r, "BAD VALUE");
} else {
out->ek_fingerprint.hashAlg = 0;
}
if (ifapi_get_sub_object(jso, "intel_cert_service", &jso2)) {
r = ifapi_json_char_deserialize(jso2, &out->intel_cert_service);
return_if_error(r, "BAD VALUE");
}
LOG_TRACE("true");
return TSS2_RC_SUCCESS;
}
/**
* Starts the initialization of the FAPI configuration.
*
* @param[in] io An IO object for file system access
*
* @retval TSS2_RC_SUCCESS on success
* @retval TSS2_FAPI_RC_BAD_REFERENCE if io is NULL
* @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
* object store.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_config_initialize_async(IFAPI_IO *io)
{
/* Check for NULL parameters */
return_if_null(io, "io is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
/* Determine the location of the configuration file */
const char *configFile = getenv(ENV_FAPI_CONFIG);
if (!configFile) {
/* No config file given, falling back to the default */
configFile = DEFAULT_CONFIG_FILE;
}
/* Start reading the config file */
TSS2_RC r = ifapi_io_read_async(io, configFile);
return_if_error(r, "Could not read config file ");
return TSS2_RC_SUCCESS;
}
/**
* Finishes the initialization of the FAPI configuration.
* @param[in] io An IO object for file system access
* @param[out] config The configuration that is initialized
*
* @retval TSS2_RC_SUCCESS on success
* @retval TSS2_FAPI_RC_BAD_REFERENCE if config or io is NULL
* @retval TSS2_FAPI_RC_BAD_VALUE if the read configuration file does not hold
* a valid configuration
* @retval TSS2_FAPI_RC_GENERAL_FAILURE if JSON parsing fails
* @retval TSS2_FAPI_RC_BAD_PATH if the configuration path is invalid
* @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
* this function needs to be called again.
* @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
* object store.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_config_initialize_finish(IFAPI_IO *io, IFAPI_CONFIG *config)
{
/* Check for NULL parameters */
return_if_null(config, "config is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
return_if_null(io, "io is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
/* Definitions that must be listed here for the cleanup to work */
const char *homeDir = NULL;
json_object *jso = NULL;
/* Finish reading operation */
uint8_t *configFileContent = NULL;
size_t configFileContentSize = 0;
TSS2_RC r = ifapi_io_read_finish(io, &configFileContent, &configFileContentSize);
return_try_again(r);
goto_if_error(r, "Could not finish read operation", error);
if (configFileContent == NULL || configFileContentSize == 0) {
LOG_ERROR("Config file is empty");
r = TSS2_FAPI_RC_BAD_VALUE;
goto error;
}
/* Parse and deserialize the configuration file */
jso = json_tokener_parse((char *)configFileContent);
goto_if_null(jso, "Could not parse JSON objects",
TSS2_FAPI_RC_GENERAL_FAILURE, error);
r = ifapi_json_IFAPI_CONFIG_deserialize(jso, config);
goto_if_error(r, "Could not deserialize configuration", error);
/* Check, if the values of the configuration are valid */
goto_if_null(config->profile_dir, "No profile directory defined in config file",
TSS2_FAPI_RC_BAD_VALUE, error);
goto_if_null(config->user_dir, "No user directory defined in config file",
TSS2_FAPI_RC_BAD_VALUE, error);
goto_if_null(config->keystore_dir, "No system directory defined in config file",
TSS2_FAPI_RC_BAD_VALUE, error);
goto_if_null(config->profile_name, "No default profile defined in config file.",
TSS2_FAPI_RC_BAD_VALUE, error);
/* Check whether usage of home directory is provided in config file */
size_t startPos = 0;
if (strncmp("~", config->user_dir, 1) == 0) {
startPos = 1;
} else if (strncmp("$HOME", config->user_dir, 5) == 0) {
startPos = 5;
}
/* Replace home abbreviation in user path. */
char *homePath = NULL;
if (startPos != 0) {
LOG_DEBUG("Expanding user directory %s to user's home", config->user_dir);
homeDir = getenv("HOME");
goto_if_null2(homeDir, "Home directory can't be determined.",
r, TSS2_FAPI_RC_BAD_PATH, error);
r = ifapi_asprintf(&homePath, "%s%s%s", homeDir, IFAPI_FILE_DELIM,
&config->user_dir[startPos]);
goto_if_error(r, "Out of memory.", error);
SAFE_FREE(config->user_dir);
config->user_dir = homePath;
}
/* Log the contents of the configuration */
LOG_DEBUG("Configuration profile directory: %s", config->profile_dir);
LOG_DEBUG("Configuration user directory: %s", config->user_dir);
LOG_DEBUG("Configuration key storage directory: %s", config->keystore_dir);
LOG_DEBUG("Configuration profile name: %s", config->profile_name);
LOG_DEBUG("Configuration TCTI: %s", config->tcti);
LOG_DEBUG("Configuration log directory: %s", config->log_dir);
SAFE_FREE(configFileContent);
if (jso != NULL) {
json_object_put(jso);
}
return r;
error:
SAFE_FREE(config->profile_dir);
SAFE_FREE(config->user_dir);
SAFE_FREE(config->keystore_dir);
SAFE_FREE(config->profile_name);
SAFE_FREE(config->tcti);
SAFE_FREE(config->log_dir);
SAFE_FREE(config->ek_cert_file);
SAFE_FREE(config->intel_cert_service);
SAFE_FREE(configFileContent);
if (jso != NULL) {
json_object_put(jso);
}
return r;
}