| /* 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) |
| { |
| 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; |
| } |