/* 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 <string.h>
#include <stdlib.h>

#include "tss2_mu.h"
#include "fapi_util.h"
#include "fapi_int.h"
#include "fapi_crypto.h"
#include "fapi_policy.h"
#include "ifapi_policy_instantiate.h"
#include "ifapi_policy_callbacks.h"
#include "ifapi_helpers.h"
#include "ifapi_json_deserialize.h"
#include "tpm_json_deserialize.h"
#include "ifapi_policy_store.h"
#define LOGMODULE fapi
#include "util/log.h"
#include "util/aux_util.h"

/** Compute policy digest for a policy tree.
 *
 * A policy or a policy path can be passed. If a policy is passed the
 * policy is computed directly from the policy otherwise the policy has to be
 * retrieved from policy store to determine the policy.
 *
 * @param[in,out] context The FAPI_CONTEXT.
 * @param[in]     policyPath The policy path for policy store.
 * @param[in]     policy The result of policy deserialization.
 * @param[in]     hash_alg The used hash alg for policy digest computations.
 * @param[out]    digest_idx The index of the current digest. The policy digest can be
 *                computed for several hash algorithms the digets index is a reverence
 *                to the current digest values.
 * @param[out]    hash_size The size of the current policy digest.
 *
 * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
 * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
 *         not covered by other return codes.
 * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during policy calculation.
 * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
 *         store.
 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If an object needed for policy calculation was
 *         not found.
 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
 *         not successful.
 * @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_BAD_SEQUENCE if the context has an asynchronous
 *         operation already pending.
 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
 * @retval TSS2_FAPI_RC_NOT_PROVISIONED FAPI was not provisioned.
 * @retval TSS2_FAPI_RC_BAD_PATH if the path is used in inappropriate context
 *         or contains illegal characters.
 */
TSS2_RC
ifapi_calculate_tree(
    FAPI_CONTEXT *context,
    const char *policyPath,
    TPMS_POLICY *policy,
    TPMI_ALG_HASH hash_alg,
    size_t *digest_idx,
    size_t *hash_size)
{
    size_t i;
    TSS2_RC r = TSS2_RC_SUCCESS;
    bool already_computed = false;
    IFAPI_POLICY_EVAL_INST_CTX *eval_ctx = NULL;
    ifapi_policyeval_INST_CB *callbacks;

    if (context->policy.state == POLICY_INIT && !policyPath)
        /* Skip policy reading */
        context->policy.state = POLICY_INSTANTIATE_PREPARE;

    switch (context->policy.state) {
    statecase(context->policy.state, POLICY_INIT);
        fallthrough;

    statecase(context->policy.state, POLICY_READ);
        r = ifapi_policy_store_load_async(&context->pstore, &context->io, policyPath);
        goto_if_error2(r, "Can't open: %s", cleanup, policyPath);
        fallthrough;

    statecase(context->policy.state, POLICY_READ_FINISH);
        r = ifapi_policy_store_load_finish(&context->pstore, &context->io, policy);
        return_try_again(r);
        return_if_error_reset_state(r, "read_finish failed");
        fallthrough;

    statecase(context->policy.state, POLICY_INSTANTIATE_PREPARE);
        eval_ctx = &context->policy.eval_ctx;
        callbacks = &eval_ctx->callbacks;
        callbacks->cbname = ifapi_get_object_name;
        callbacks->cbname_userdata = context;
        callbacks->cbpublic = ifapi_get_key_public;
        callbacks->cbpublic_userdata = context;
        callbacks->cbnvpublic = ifapi_get_nv_public;
        callbacks->cbnvpublic_userdata = context;
        callbacks->cbpcr = ifapi_read_pcr;
        callbacks->cbpcr_userdata = context;

        r = ifapi_policyeval_instantiate_async(eval_ctx, policy, callbacks);
        goto_if_error(r, "Instantiate policy.", cleanup);
        fallthrough;

    statecase(context->policy.state, POLICY_INSTANTIATE);
        r = ifapi_policyeval_instantiate_finish(&context->policy.eval_ctx);
        FAPI_SYNC(r, "Instantiate policy.", cleanup);
        ifapi_free_node_list(context->policy.eval_ctx.policy_elements);
        context->policy.eval_ctx.policy_elements = NULL;

        if (!(*hash_size = ifapi_hash_get_digest_size(hash_alg))) {
            goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
                       "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
                       hash_alg);
        }

        for (i = 0; i < policy->policyDigests.count; i++) {
            if (policy->policyDigests.digests[i].hashAlg == hash_alg) {
                /* Digest already computed */
                *digest_idx = i;
                already_computed = true;
            }
        }
        if (already_computed)
            break;

        if (i >= TPM2_NUM_PCR_BANKS) {
            return_error(TSS2_FAPI_RC_BAD_VALUE, "Table overflow");
        }
        *digest_idx = i;
        policy->policyDigests.count += 1;
        policy->policyDigests.digests[i].hashAlg = hash_alg;

        memset(&policy->policyDigests.digests[*digest_idx].digest, 0,
               sizeof(TPMU_HA));

        r = ifapi_calculate_policy(policy->policy,
                                   &policy->policyDigests, hash_alg,
                                   *hash_size, *digest_idx);
        goto_if_error(r, "Compute policy.", cleanup);

        break;
    statecasedefault(context->policy.state);
    }
cleanup:
    ifapi_free_node_list(context->policy.eval_ctx.policy_elements);
    context->policy.eval_ctx.policy_elements = NULL;
    context->policy.state = POLICY_INIT;
    return r;
}
