/* SPDX-License-Identifier: BSD-2-Clause */ /******************************************************************************* * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG * All rights reserved. *******************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include #include #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) { 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) { 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, ¤t_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, ¤t_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, ¤t_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, ¤t_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, ¤t_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, ¤t_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, ¤t_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 *) ¤t_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, ¤t_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 *) ¤t_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, ¤t_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 *) ¤t_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, ¤t_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, ¤t_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)); /* 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, ¤t_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 *) ¤t_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(¤t_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 *) ¤t_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; }