blob: e3821ef6a212d50699b15fb27d63fb7c7f505105 [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 <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;
}