blob: c991c6f171a4727a6c751828b2cd9113f82b14ca [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_crypto.h"
#include "fapi_policy.h"
#include "ifapi_helpers.h"
#include "ifapi_json_deserialize.h"
#include "tpm_json_deserialize.h"
#define LOGMODULE fapi
#include "util/log.h"
#include "util/aux_util.h"
/** Copy policy digest.
*
* One digest is copied from certain position in a policy list to the
* same position in a second list.
*
* @param[out] dest The digest list to which the new value is added.
* @param[in] src The digest list with the value to be copied.
* @param[in] digest_idx The index of the digest to be copied.
* @param[in] hash_size The number of bytes to be copied.
* @param[in] txt Text which will be used for additional logging information..
* @retval TSS2_RC_SUCCESS on success.
*/
static void
copy_policy_digest(TPML_DIGEST_VALUES *dest, TPML_DIGEST_VALUES *src,
size_t digest_idx, size_t hash_size, char *txt)
{
(void)(txt); /* If max log-leve < debug, this param is unused */
memcpy(&dest->digests[digest_idx].digest, &src->digests[digest_idx].digest,
hash_size);
dest->digests[digest_idx].hashAlg = src->digests[digest_idx].hashAlg;
LOGBLOB_DEBUG((uint8_t *)&dest->digests[digest_idx].digest, hash_size,
"%s : Copy digest size: %zu", txt, hash_size);
dest->count = src->count;
}
/** Logdefault policy digest.
*
* @param[in] dest The digest to be logged.
* @param[in] digest_idx The index of the digest to be logged
* @param[in] hash_size The number of bytes to be logged
* @param[in] txt Text which will be used for additional logging information.
*/
static void
log_policy_digest(TPML_DIGEST_VALUES *dest, size_t digest_idx, size_t hash_size,
char *txt)
{
(void)(dest);(void)(digest_idx);(void)(hash_size);(void)(txt);
/* If max log-leve < debug, this param is unused */
LOGBLOB_DEBUG((uint8_t *)&dest->digests[digest_idx].digest, hash_size,
"Digest %s", txt);
}
/** Calculate a policy digest for a certain PCR selection.
*
* From a PCR list the list of PCR values and the corresponding PCR digest
* is computed. The passed policy digest will be extended with this data
* and also with the policy command code.
*
* @param[in] policy The policy with the list of selected PCRs.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_compute_policy_pcr(
TPMS_POLICYPCR *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
TPML_PCR_SELECTION pcr_selection;
size_t digest_idx;
TPM2B_DIGEST pcr_digest;
size_t hash_size;
LOG_TRACE("call");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
/* Compute PCR selection and pcr digest */
r = ifapi_compute_policy_digest(policy->pcrs, &pcr_selection,
current_hash_alg, &pcr_digest);
return_if_error(r, "Compute policy digest and selection.");
LOG_TRACE("Compute policy pcr");
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
/* Update the passed policy. */
HASH_UPDATE_BUFFER(cryptoContext,
&current_digest->digests[digest_idx].digest, hash_size,
r, cleanup);
HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyPCR, r, cleanup);
/* The marshaled version of the digest list will be added. */
HASH_UPDATE(cryptoContext, TPML_PCR_SELECTION, &pcr_selection, r, cleanup);
HASH_UPDATE_BUFFER(cryptoContext, &pcr_digest.buffer[0], hash_size, r,
cleanup);
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) & current_digest->
digests[digest_idx].digest, &hash_size);
return_if_error(r, "crypto hash finish");
cleanup:
if (cryptoContext)
ifapi_crypto_hash_abort(&cryptoContext);
return r;
}
/** Calculate a policy digest for a TPM2B object name, and a policy reference.
*
* A policy hash based on a passed policy digest, the policy command code,
* optionally the name, and the policy reference will be computed.
* The calculation is carried out in two steps. First a hash with the
* command code and the passed digest, and optionaly the name is computed.
* This digest, together with the other parameters is used to compute
* the final policy digest.
*
* @param[in] command_code The TPM command code of the policy command.
* @param[in] name The name of a key or a NV object.
* @param[in] policyRef The policy reference value.
* @param[in] hash_size The digest size of the used hash algorithm.
* @param[in] current_hash_alg The used has algorithm.
* @param[in,out] digest The policy digest which will be extended.
*
* @retval TSS2_RC_SUCCESS on success.
* @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_MEMORY if not enough memory can be allocated.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
*/
static TSS2_RC
calculate_policy_key_param(
TPM2_CC command_code,
TPM2B_NAME *name,
TPM2B_NONCE *policyRef,
size_t hash_size,
TPMI_ALG_HASH current_hash_alg,
TPMU_HA *digest)
{
TSS2_RC r = TSS2_RC_SUCCESS;
IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
LOGBLOB_DEBUG((uint8_t *) digest, hash_size, "Digest Start");
/* First compute hash from passed policy digest and command code
and optionally the object name */
HASH_UPDATE_BUFFER(cryptoContext, digest, hash_size, r, cleanup);
HASH_UPDATE(cryptoContext, TPM2_CC, command_code, r, cleanup);
if (name && name->size > 0) {
LOGBLOB_DEBUG(&name->name[0], name->size, "Key name");
HASH_UPDATE_BUFFER(cryptoContext, &name->name[0],
name->size, r, cleanup);
}
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) digest, &hash_size);
LOGBLOB_DEBUG((uint8_t *) digest, hash_size, "Digest Finish");
return_if_error(r, "crypto hash finish");
/* Use policyRef for second hash computation */
if (policyRef) {
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
HASH_UPDATE_BUFFER(cryptoContext, digest, hash_size, r, cleanup);
HASH_UPDATE_BUFFER(cryptoContext, &policyRef->buffer[0],
policyRef->size, r, cleanup);
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) digest, &hash_size);
return_if_error(r, "crypto hash finish");
}
cleanup:
if (cryptoContext)
ifapi_crypto_hash_abort(&cryptoContext);
return r;
}
/** Calculate a policy digest for a signed policy.
*
* Based on the command code, the public key, and the policy reference
* stored in the policy the new policy digest is computed by the function
* calculate_policy_key_param().
*
* @param[in] policy The policy with the public key and the policy reference.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_signed(
TPMS_POLICYSIGNED *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
size_t digest_idx;
size_t hash_size;
LOG_DEBUG("call");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
r = calculate_policy_key_param(TPM2_CC_PolicySigned,
&policy->publicKey,
&policy->policyRef, hash_size,
current_hash_alg,
&current_digest->digests[digest_idx].digest);
goto_if_error(r, "crypto hash start", cleanup);
cleanup:
return r;
}
/** Calculate a policy digest for a policy stored in an approved NV index.
*
* Based on the command code, and the computed NV name the new policy digest
* is computed by the function calculate_policy_key_param().
*
* @param[in] policy The policy with the public information of the NV index.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @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.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
* @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
*/
TSS2_RC
ifapi_calculate_policy_authorize_nv(
TPMS_POLICYAUTHORIZENV *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
size_t digest_idx;
size_t hash_size;
TPM2B_NAME nv_name;
LOG_DEBUG("call");
/* Written flag has to be set for policy calculation, because during
policy execution it will be set. */
policy->nvPublic.nvPublic.attributes |= TPMA_NV_WRITTEN;
r = ifapi_nv_get_name(&policy->nvPublic, &nv_name);
return_if_error(r, "Compute NV name");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
r = calculate_policy_key_param(TPM2_CC_PolicyAuthorizeNV,
&nv_name,
NULL, hash_size, current_hash_alg,
&current_digest->digests[digest_idx].digest);
goto_if_error(r, "crypto hash start", cleanup);
cleanup:
return r;
}
/** Calculate a policy digest to allow duplication force a selected new parent.
*
* Based on the command code, the name of the new parent, and the include object
* switch the new policy digest is computed.
*
* @param[in] policy The policy with the new parent information.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_duplicate(
TPMS_POLICYDUPLICATIONSELECT *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
size_t digest_idx;
size_t hash_size;
LOG_DEBUG("call");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
LOG_TRACE("Compute policy");
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
/* Update the policy digest */
HASH_UPDATE_BUFFER(cryptoContext,
&current_digest->digests[digest_idx].digest, hash_size,
r, cleanup);
HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyDuplicationSelect, r,
cleanup);
LOGBLOB_DEBUG(&policy->newParentName.name[0], policy->newParentName.size,
"Policy Duplicate Parent Name");
HASH_UPDATE_BUFFER(cryptoContext, &policy->newParentName.name[0],
policy->newParentName.size, r, cleanup);
HASH_UPDATE(cryptoContext, BYTE, policy->includeObject, r, cleanup);
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) & current_digest->
digests[digest_idx].digest, &hash_size);
return_if_error(r, "crypto hash finish");
LOGBLOB_DEBUG((uint8_t *) & current_digest->digests[digest_idx].digest,
hash_size, "Policy Duplicate digest");
cleanup:
if (cryptoContext)
ifapi_crypto_hash_abort(&cryptoContext);
return r;
}
/** Calculate a policy digest for a placeholder policy.
*
* The placeholder policy can be extended during execution by a
* signed policy, which can be verified by using the parameters of
* this placeholder policy.
* Based on the command code, the key name of the signing key and
* a policy reference the new policy digest is computed by the
* function calculate_policy_key_param().
*
* @param[in] policy The policy with the name of the public key and the
* policy reference.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_authorize(
TPMS_POLICYAUTHORIZE *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
size_t digest_idx;
size_t hash_size;
LOG_DEBUG("call");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
r = calculate_policy_key_param(TPM2_CC_PolicyAuthorize,
&policy->keyName,
&policy->policyRef, hash_size,
current_hash_alg,
&current_digest->digests[digest_idx].digest);
goto_if_error(r, "crypto hash start", cleanup);
cleanup:
return r;
}
/** Calculate a policy for adding secret-based authorization.
*
* During execution proving the knowledge of the secrect auth value of a certain
* object is required. The name of this object and a policy reference is used
* for policy calculation.
* Based on the command code, the object name and a policy reference the new
* policy digest is computed by the function calculate_policy_key_param().
*
* @param[in] policy The policy with the object name of the object to be
* authorized and the policy reference.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_secret(
TPMS_POLICYSECRET *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
size_t digest_idx;
size_t hash_size;
LOG_DEBUG("call");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
/* Update the policy */
r = calculate_policy_key_param(TPM2_CC_PolicySecret,
(TPM2B_NAME *)&policy->objectName,
&policy->policyRef, hash_size,
current_hash_alg,
&current_digest->digests[digest_idx].digest);
goto_if_error(r, "crypto hash start", cleanup);
cleanup:
return r;
}
/** Calculate a policy for for comparing current TPM timers with the policy.
*
* The timer value and the operation for comparison defined in the policy will
* bu used to update the policy digest.
* The offset which is supported by the TPM policy for FAPI will be 0.
*
* @param[in] policy The policy with the timer value and the operation for
* comparison.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_counter_timer(
TPMS_POLICYCOUNTERTIMER *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
size_t digest_idx;
size_t hash_size;
TPM2B_DIGEST counter_timer_hash;
LOG_DEBUG("call");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
/* Compute a has value from the offset, the timer value and the operation. */
HASH_UPDATE_BUFFER(cryptoContext, &policy->operandB.buffer[0],
policy->operandB.size, r, cleanup);
HASH_UPDATE(cryptoContext, UINT16, policy->offset, r, cleanup);
HASH_UPDATE(cryptoContext, UINT16, policy->operation, r, cleanup);
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) &counter_timer_hash.buffer[0], &hash_size);
return_if_error(r, "crypto hash finish");
/* Extend the policy digest from the hash value computed above and the
command code. */
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
HASH_UPDATE_BUFFER(cryptoContext,
&current_digest->digests[digest_idx].digest, hash_size,
r, cleanup);
HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyCounterTimer, r, cleanup);
HASH_UPDATE_BUFFER(cryptoContext, &counter_timer_hash.buffer[0],
hash_size, r, cleanup);
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) &current_digest->digests[digest_idx].digest,
&hash_size);
cleanup:
if (cryptoContext)
ifapi_crypto_hash_abort(&cryptoContext);
return r;
}
/** Update policy if only the command codes are used.
*
* Some simple policies use onle one or two command codes for policy calculation.
*
* @param[in] command_code1 The first command code for policy extension.
* Can be NULL.
* @param[in] command_code2 The second command code for policy extension.
* Can be NULL.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_simple_policy(
TPM2_CC command_code1,
TPM2_CC command_code2,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
size_t digest_idx;
size_t hash_size;
LOG_DEBUG("call");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
/* Update the policy */
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
HASH_UPDATE_BUFFER(cryptoContext,
&current_digest->digests[digest_idx].digest, hash_size,
r, cleanup);
if (command_code1) {
HASH_UPDATE(cryptoContext, TPM2_CC, command_code1, r, cleanup);
}
if (command_code2) {
HASH_UPDATE(cryptoContext, TPM2_CC, command_code2, r, cleanup);
}
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) &current_digest->digests[digest_idx].digest,
&hash_size);
cleanup:
if (cryptoContext)
ifapi_crypto_hash_abort(&cryptoContext);
return r;
}
/** Update policy with command code policy physical presence.
*
* The policy will be updated with the function ifapi_calculate_simple_policy()
*
* @param[in] policy The policy physical presence.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_physical_presence(
TPMS_POLICYPHYSICALPRESENCE *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
(void)policy;
LOG_DEBUG("call");
r = ifapi_calculate_simple_policy(TPM2_CC_PolicyPhysicalPresence, 0,
current_digest, current_hash_alg);
return_if_error(r, "Calculate policy for command code.");
return r;
}
/** Update policy with command code of policy auth value.
*
* The policy will be updated with the function ifapi_calculate_simple_policy()
*
* @param[in] policy The policy auth value.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_auth_value(
TPMS_POLICYAUTHVALUE *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
(void)policy;
LOG_DEBUG("call");
r = ifapi_calculate_simple_policy(TPM2_CC_PolicyAuthValue, 0,
current_digest, current_hash_alg);
return_if_error(r, "Calculate policy auth value.");
return r;
}
/** Update policy with the command code of policy password.
*
* The policy will be updated with the function ifapi_calculate_simple_policy()
*
* @param[in] policy The policy password.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_password(
TPMS_POLICYPASSWORD *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
(void)policy;
LOG_DEBUG("call");
r = ifapi_calculate_simple_policy(TPM2_CC_PolicyAuthValue, 0,
current_digest, current_hash_alg);
return_if_error(r, "Calculate policy password.");
return r;
}
/** Update policy command code with a command code defined in the policy.
*
* For the update two command codes will be used. The command code of
* policy command code and the passed command code.
* The policy will be updated with the function ifapi_calculate_simple_policy()
*
* @param[in] policy The policy command code with the second command code.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_command_code(
TPMS_POLICYCOMMANDCODE *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
LOG_DEBUG("call");
r = ifapi_calculate_simple_policy(TPM2_CC_PolicyCommandCode, policy->code,
current_digest, current_hash_alg);
return_if_error(r, "Calculate policy for command code.");
return r;
}
/** Compute policy if only a digest and a command code are needed for extension.
*
* @param[in] digest the digest which will be used for policy extension.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
* @param[in] command_code The compute of the command which did compute the digest.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_digest_hash(
TPM2B_DIGEST *digest,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg,
TPM2_CC command_code)
{
TSS2_RC r = TSS2_RC_SUCCESS;
IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
size_t digest_idx;
size_t hash_size;
LOG_DEBUG("call");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
/* Update the policy. */
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
HASH_UPDATE_BUFFER(cryptoContext,
&current_digest->digests[digest_idx].digest, hash_size,
r, cleanup);
HASH_UPDATE(cryptoContext, TPM2_CC, command_code, r, cleanup);
HASH_UPDATE_BUFFER(cryptoContext, &digest->buffer[0],
digest->size, r, cleanup);
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) &current_digest->digests[digest_idx].digest,
&hash_size);
cleanup:
if (cryptoContext)
ifapi_crypto_hash_abort(&cryptoContext);
return r;
}
/** Compute policy bound to a specific set of TPM entities.
*
* The policy digest will be updated with the function
* ifapi_calculate_policy_digest_hash() which will add the hash of the
* entity name list.
*
* @param[in] policy The policy with the list of entity names.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_name_hash(
TPMS_POLICYNAMEHASH *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
size_t hash_size;
size_t i;
LOG_DEBUG("call");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
/* Compute name hash from the list of object names */
for (i = 0; i <= policy->count; i++) {
HASH_UPDATE_BUFFER(cryptoContext, &policy->objectNames[i].name[0],
policy->objectNames[i].size, r,
cleanup);
}
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) &policy->nameHash.buffer[0],
&hash_size);
return_if_error(r, "crypto hash finish");
policy->nameHash.size = hash_size;
/* Update the policy with the computed hash value of the name list and
the command code. */
r = ifapi_calculate_policy_digest_hash(&policy->nameHash,
current_digest,
current_hash_alg, TPM2_CC_PolicyNameHash);
return_if_error(r, "Calculate digest hash for policy");
cleanup:
if (cryptoContext)
ifapi_crypto_hash_abort(&cryptoContext);
return r;
}
/** Compute policy bound to a specific command and command parameters.
*
* The cp hash value and the command code will be updated by the
* function ifapi_calculate_policy_digest_hash().
*
* @param[in] policy The policy with the cp hash value.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_cp_hash(
TPMS_POLICYCPHASH *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
LOG_DEBUG("call");
r = ifapi_calculate_policy_digest_hash(&policy->cpHash,
current_digest, current_hash_alg,
TPM2_CC_PolicyCpHash);
return_if_error(r, "Calculate digest hash for policy");
return r;
}
/** Compute policy which limits authorization to a specific locality.
*
* @param[in] policy The policy with the locality.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_locality(
TPMS_POLICYLOCALITY *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
size_t digest_idx;
size_t hash_size;
LOG_DEBUG("call");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
/* Update the policy */
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
HASH_UPDATE_BUFFER(cryptoContext,
&current_digest->digests[digest_idx].digest, hash_size,
r, cleanup);
HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyLocality, r, cleanup);
HASH_UPDATE(cryptoContext, BYTE, policy->locality, r, cleanup);
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) & current_digest->
digests[digest_idx].digest, &hash_size);
cleanup:
if (cryptoContext)
ifapi_crypto_hash_abort(&cryptoContext);
return r;
}
/** Compute policy bound to bound to the TPMA_NV_WRITTEN attributes.
*
* The expected value of the NV written attribute is part of the policy.
*
* @param[in] policy The policy with the expected attribute value.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_nv_written(
TPMS_POLICYNVWRITTEN *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
size_t digest_idx;
size_t hash_size;
LOG_DEBUG("call");
if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
"Unsupported hash algorithm (%" PRIu16 ")", cleanup,
current_hash_alg);
}
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
/* Update the policy */
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
HASH_UPDATE_BUFFER(cryptoContext,
&current_digest->digests[digest_idx].digest, hash_size,
r, cleanup);
HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyNvWritten, r, cleanup);
/* Update the expected attribute value. */
HASH_UPDATE(cryptoContext, BYTE, policy->writtenSet, r, cleanup);
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) & current_digest->
digests[digest_idx].digest, &hash_size);
cleanup:
if (cryptoContext)
ifapi_crypto_hash_abort(&cryptoContext);
return r;
}
/** Compute policy bound to the content of an NV index.
*
* The value used for comparison, the compare operation and an
* offset for the NV index are part of the policy.
*
* @param[in] policy The policy with the expected values used for comparison.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] current_hash_alg The hash algorithm used for the policy computation.
*
* @retval TSS2_RC_SUCCESS on success.
* @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_MEMORY if not enough memory can be allocated.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
*/
TSS2_RC
ifapi_calculate_policy_nv(
TPMS_POLICYNV *policy,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH current_hash_alg)
{
TSS2_RC r = TSS2_RC_SUCCESS;
IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
TPM2B_NAME nv_name;
size_t hash_size;
TPM2B_DIGEST nv_hash;
size_t digest_idx;
LOG_DEBUG("call");
memset(&nv_name, 0, sizeof(TPM2B_NAME));
/* Written flag has to be set for policy calculation, because during
policy execution it will be set. */
policy->nvPublic.nvPublic.attributes |= TPMA_NV_WRITTEN;
/* Compute NV name from public info */
r = ifapi_nv_get_name(&policy->nvPublic, &nv_name);
return_if_error(r, "Compute NV name");
/* Compute of the index of the current policy in the passed digest list */
r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
return_if_error(r, "Get hash alg for digest.");
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
/* Compute the hash for the compare operation. */
HASH_UPDATE_BUFFER(cryptoContext, &policy->operandB.buffer[0],
policy->operandB.size, r, cleanup);
HASH_UPDATE(cryptoContext, UINT16, policy->offset, r, cleanup);
HASH_UPDATE(cryptoContext, UINT16, policy->operation, r, cleanup);
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) &nv_hash.buffer[0], &hash_size);
return_if_error(r, "crypto hash finish");
nv_hash.size = hash_size;
/* Update the policy with the hash of the compare operation and the NV name. */
r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
return_if_error(r, "crypto hash start");
HASH_UPDATE_BUFFER(cryptoContext,
&current_digest->digests[digest_idx].digest, hash_size,
r, cleanup);
HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyNV, r, cleanup);
HASH_UPDATE_BUFFER(cryptoContext, &nv_hash.buffer[0], nv_hash.size, r, cleanup)
HASH_UPDATE_BUFFER(cryptoContext, &nv_name.name[0], nv_name.size, r, cleanup);
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) &current_digest->digests[digest_idx].digest,
&hash_size);
return_if_error(r, "crypto hash finish");
cleanup:
if (cryptoContext)
ifapi_crypto_hash_abort(&cryptoContext);
return r;
}
/** Compute a list of policies to enable authorization options.
*
* First the policy digest will be computed for every branch.
* After that the policy digest will be reset to zero and extended by the
* list of computed policy digests of the branches.
*
* @param[in] policyOr The policy with the possible policy branches.
* @param[in,out] current_digest The digest list which has to be updated.
* @param[in] hash_alg The hash algorithm used for the policy computation.
* @param[in] hash_size The size of the policy digest.
* @param[in] digest_idx The index of the current policy in the passed digest list.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy_or(
TPMS_POLICYOR *policyOr,
TPML_DIGEST_VALUES *current_digest,
TPMI_ALG_HASH hash_alg,
size_t hash_size,
size_t digest_idx)
{
size_t i;
TSS2_RC r = TSS2_RC_SUCCESS;
IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
for (i = 0; i < policyOr->branches->count; i++) {
/* Compute the policy digest for every branch. */
copy_policy_digest(&policyOr->branches->authorizations[i].policyDigests,
current_digest, digest_idx, hash_size,
"Copy or digest");
r = ifapi_calculate_policy(policyOr->branches->authorizations[i].policy,
&policyOr->branches->authorizations[i].
policyDigests, hash_alg, hash_size,
digest_idx);
log_policy_digest(&policyOr->branches->authorizations[i].policyDigests,
digest_idx, hash_size, "Branch digest");
return_if_error(r, "Compute policy.");
}
/* Reset the or policy digest because the digest is included in all sub policies */
memset(&current_digest->digests[digest_idx], 0, hash_size);
r = ifapi_crypto_hash_start(&cryptoContext, hash_alg);
return_if_error(r, "crypto hash start");
r = ifapi_crypto_hash_update(cryptoContext, (const uint8_t *)
&current_digest->digests[digest_idx].digest,
hash_size);
goto_if_error(r, "crypto hash update", cleanup);
/* Start with the update of the reset digest. */
uint8_t buffer[sizeof(TPM2_CC)];
size_t offset = 0;
r = Tss2_MU_TPM2_CC_Marshal(TPM2_CC_PolicyOR,
&buffer[0], sizeof(TPM2_CC), &offset);
goto_if_error(r, "Marshal cc", cleanup);
r = ifapi_crypto_hash_update(cryptoContext,
(const uint8_t *)&buffer[0], sizeof(TPM2_CC));
goto_if_error(r, "crypto hash update", cleanup);
/* Update the digest with the complete list of computed digests of the branches. */
for (i = 0; i < policyOr->branches->count; i++) {
r = ifapi_crypto_hash_update(cryptoContext, (const uint8_t *)
&policyOr->branches->authorizations[i]
.policyDigests.digests[digest_idx].digest,
hash_size);
log_policy_digest(&policyOr->branches->authorizations[i].policyDigests,
digest_idx, hash_size, "Or branch");
current_digest->count =
policyOr->branches->authorizations[i].policyDigests.count;
goto_if_error(r, "crypto hash update", cleanup);
}
current_digest->digests[digest_idx].hashAlg = hash_alg;
r = ifapi_crypto_hash_finish(&cryptoContext,
(uint8_t *) & current_digest->
digests[digest_idx].digest, &hash_size);
log_policy_digest(current_digest, digest_idx, hash_size, "Final or digest");
goto_if_error(r, "crypto hash finish", cleanup);
cleanup:
if (cryptoContext)
ifapi_crypto_hash_abort(&cryptoContext);
return r;
}
/** Compute policy digest for a list of policies.
*
* Every policy in the list will update the previous policy. Thus the final
* policy digest will describe the sequential execution of the policy list.
*
* @param[in] policy The policy with the policy list.
* @param[in,out] policyDigests The digest list which has to be updated.
* @param[in] hash_alg The hash algorithm used for the policy computation.
* @param[in] hash_size The size of the policy digest.
* @param[in] digest_idx The index of the current policy in the passed digest list.
*
* @retval TSS2_RC_SUCCESS on success.
* @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
* the function.
* @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_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_calculate_policy(
TPML_POLICYELEMENTS *policy,
TPML_DIGEST_VALUES *policyDigests,
TPMI_ALG_HASH hash_alg,
size_t hash_size,
size_t digest_idx)
{
size_t i;
TSS2_RC r = TSS2_RC_SUCCESS;
for (i = 0; i < policy->count; i++) {
copy_policy_digest(&policy->elements[i].policyDigests,
policyDigests, digest_idx, hash_size,
"Copy policy digest (to)");
switch (policy->elements[i].type) {
case POLICYPCR:
r = ifapi_compute_policy_pcr(&policy->elements[i].element.PolicyPCR,
&policy->elements[i].policyDigests,
hash_alg);
return_if_error(r, "Compute policy pcr");
break;
case POLICYSIGNED:
r = ifapi_calculate_policy_signed(&policy->elements[i].element.
PolicySigned,
&policy->elements[i].
policyDigests, hash_alg);
return_if_error(r, "Compute policy nv");
break;
case POLICYDUPLICATIONSELECT:
r = ifapi_calculate_policy_duplicate(&policy->elements[i].element.
PolicyDuplicationSelect,
&policy->elements[i].
policyDigests, hash_alg);
return_if_error(r, "Compute policy duplication select");
break;
case POLICYAUTHORIZENV:
r = ifapi_calculate_policy_authorize_nv(&policy->elements[i].
element.PolicyAuthorizeNv,
&policy->elements[i].
policyDigests, hash_alg);
return_if_error(r, "Compute policy authorizeg");
break;
case POLICYAUTHORIZE:
r = ifapi_calculate_policy_authorize(&policy->elements[i].element.
PolicyAuthorize,
&policy->elements[i].
policyDigests, hash_alg);
return_if_error(r, "Compute policy authorizeg");
break;
case POLICYSECRET:
r = ifapi_calculate_policy_secret(&policy->elements[i].element.
PolicySecret,
&policy->elements[i].
policyDigests, hash_alg);
return_if_error(r, "Compute policy nv");
break;
case POLICYOR:
r = ifapi_calculate_policy_or(&policy->elements[i].element.PolicyOr,
&policy->elements[i].policyDigests,
hash_alg, hash_size, digest_idx);
return_if_error(r, "Compute policy or");
break;
case POLICYNV:
r = ifapi_calculate_policy_nv(&policy->elements[i].element.PolicyNV,
&policy->elements[i].policyDigests,
hash_alg);
return_if_error(r, "Compute policy nv");
break;
case POLICYNVWRITTEN:
r = ifapi_calculate_policy_nv_written(&policy->elements[i].element.
PolicyNvWritten,
&policy->elements[i].
policyDigests, hash_alg);
return_if_error(r, "Compute policy nv written");
break;
case POLICYCOUNTERTIMER:
r = ifapi_calculate_policy_counter_timer(
&policy->elements[i].element.PolicyCounterTimer,
&policy->elements[i].policyDigests, hash_alg);
return_if_error(r, "Compute policy counter timer");
break;
case POLICYPHYSICALPRESENCE:
r = ifapi_calculate_policy_physical_presence(
&policy->elements[i].element.PolicyPhysicalPresence,
&policy->elements[i].policyDigests, hash_alg);
return_if_error(r, "Compute policy physical presence");
break;
case POLICYAUTHVALUE:
r = ifapi_calculate_policy_auth_value(&policy->elements[i].element.PolicyAuthValue,
&policy->elements[i].policyDigests, hash_alg);
return_if_error(r, "Compute policy auth value");
break;
case POLICYPASSWORD:
r = ifapi_calculate_policy_password(&policy->elements[i].element.PolicyPassword,
&policy->elements[i].policyDigests, hash_alg);
return_if_error(r, "Compute policy password");
break;
case POLICYCOMMANDCODE:
r = ifapi_calculate_policy_command_code(&policy->elements[i].element.PolicyCommandCode,
&policy->elements[i].policyDigests, hash_alg);
return_if_error(r, "Compute policy physical presence");
break;
case POLICYNAMEHASH:
r = ifapi_calculate_policy_name_hash(&policy->elements[i].element.PolicyNameHash,
&policy->elements[i].policyDigests, hash_alg);
return_if_error(r, "Compute policy name hash");
break;
case POLICYCPHASH:
r = ifapi_calculate_policy_cp_hash(&policy->elements[i].element.PolicyCpHash,
&policy->elements[i].policyDigests, hash_alg);
return_if_error(r, "Compute policy cp hash");
break;
case POLICYLOCALITY:
r = ifapi_calculate_policy_locality(&policy->elements[i].element.PolicyLocality,
&policy->elements[i].policyDigests, hash_alg);
return_if_error(r, "Compute policy locality");
break;
case POLICYACTION:
/* This does not alter the policyDigest */
break;
default:
return_error(TSS2_FAPI_RC_BAD_VALUE,
"Policy not implemented");
}
copy_policy_digest(policyDigests, &policy->elements[i].policyDigests,
digest_idx, hash_size, "Copy policy digest (from)");
}
return r;
}