| /* 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_policy_execute.h" |
| #include "ifapi_helpers.h" |
| #include "ifapi_json_deserialize.h" |
| #include "tpm_json_deserialize.h" |
| #include "ifapi_policy_callbacks.h" |
| #define LOGMODULE fapi |
| #include "util/log.h" |
| #include "util/aux_util.h" |
| |
| /** Copy the policy digests from a branch list to a digest list. |
| * |
| * @param[in] branches The list of policy branches. |
| * @param[in] current_hash_alg The hash algorithm used for computation. |
| * @param[out] digest_list The list of policies computed for every branch. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_BAD_VALUE If no appropriate digest was found in |
| * the branch list. |
| */ |
| static TSS2_RC |
| compute_or_digest_list( |
| TPML_POLICYBRANCHES *branches, |
| TPMI_ALG_HASH current_hash_alg, |
| TPML_DIGEST *digest_list) |
| { |
| size_t i; |
| size_t digest_idx, hash_size; |
| bool digest_found = false; |
| |
| if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) { |
| return_error2(TSS2_FAPI_RC_BAD_VALUE, |
| "Unsupported hash algorithm (%" PRIu16 ")", |
| current_hash_alg); |
| } |
| /* Determine digest values with appropriate hash alg */ |
| TPML_DIGEST_VALUES *branch_digests = &branches->authorizations[0].policyDigests; |
| for (i = 0; i < branch_digests->count; i++) { |
| if (branch_digests->digests[i].hashAlg == current_hash_alg) { |
| digest_idx = i; |
| digest_found = true; |
| break; |
| } |
| } |
| if (!digest_found) { |
| return_error(TSS2_FAPI_RC_BAD_VALUE, "No digest found for hash alg"); |
| } |
| |
| digest_list->count = branches->count; |
| for (i = 0; i < branches->count; i++) { |
| if (i > 7) { |
| return_error(TSS2_FAPI_RC_BAD_VALUE, "Too much or branches."); |
| } |
| digest_list->digests[i].size = hash_size; |
| memcpy(&digest_list->digests[i].buffer[0], |
| &branches->authorizations[i].policyDigests. |
| digests[digest_idx].digest, hash_size); |
| LOGBLOB_DEBUG(&digest_list->digests[i].buffer[0], |
| digest_list->digests[i].size, "Compute digest list"); |
| } |
| return TSS2_RC_SUCCESS; |
| } |
| |
| /** Add a new authorization to a policy. |
| * |
| * The the signed hash computed from the policy digest and the policyRef together with |
| * the public key of the key used for signing will be stored in the policy. |
| * |
| * @param[in,out] policy The policy to be authorized. |
| * @param[in] authorization The structure with the signature, the policyRef and |
| * the public key. |
| * |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_MEMORY If the memory for the authorization list cannot be |
| * allocated. |
| */ |
| TSS2_RC |
| ifapi_extend_authorization( |
| TPMS_POLICY *policy, |
| TPMS_POLICYAUTHORIZATION *authorization) |
| { |
| TPML_POLICYAUTHORIZATIONS *save = NULL; |
| size_t n = 0; |
| size_t i; |
| |
| if (policy->policyAuthorizations) { |
| /* Extend old authorizations */ |
| n = policy->policyAuthorizations->count; |
| save = policy->policyAuthorizations; |
| policy->policyAuthorizations = |
| malloc((n + 1) * sizeof(TPMS_POLICYAUTHORIZATION) |
| + sizeof(TPML_POLICYAUTHORIZATIONS)); |
| return_if_null(policy->policyAuthorizations->authorizations, |
| "Out of memory.", TSS2_FAPI_RC_MEMORY); |
| |
| for (i = 0; i < n; i++) |
| policy->policyAuthorizations->authorizations[i] = |
| save->authorizations[i]; |
| policy->policyAuthorizations->authorizations[n] = *authorization; |
| policy->policyAuthorizations->count = n + 1; |
| SAFE_FREE(save); |
| } else { |
| /* No old authorizations exits */ |
| policy->policyAuthorizations = malloc(sizeof(TPMS_POLICYAUTHORIZATION) |
| + sizeof(TPML_POLICYAUTHORIZATIONS)); |
| return_if_null(policy->policyAuthorizations->authorizations, |
| "Out of memory.", TSS2_FAPI_RC_MEMORY); |
| |
| policy->policyAuthorizations->count = 1; |
| policy->policyAuthorizations->authorizations[0] = *authorization; |
| } |
| return TSS2_RC_SUCCESS; |
| } |
| /** Compute the index for the current digest list and clear the digest. |
| * |
| * The list entry with the appropriate hash algorithm will be searched. |
| * The found digest will be set to zero. |
| * |
| * @param[in,out] digest_values The list of policy digests and corresponding |
| * hash algorithms. |
| * @param[in] hashAlg The hash algorithm to be searched. |
| * @param[out] idx The index of the found digest. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_BAD_VALUE If no appropriate digest was found in |
| * the digest list. |
| */ |
| TSS2_RC |
| get_policy_digest_idx(TPML_DIGEST_VALUES *digest_values, TPMI_ALG_HASH hashAlg, |
| size_t *idx) |
| { |
| size_t i; |
| for (i = 0; i < digest_values->count; i++) { |
| /* Check whether current hashAlg is appropriate. */ |
| if (digest_values->digests[i].hashAlg == hashAlg) { |
| *idx = i; |
| return TSS2_RC_SUCCESS; |
| } |
| } |
| |
| if (i >= TPM2_NUM_PCR_BANKS) { |
| return_error(TSS2_FAPI_RC_BAD_VALUE, "Table overflow"); |
| } |
| digest_values->digests[i].hashAlg = hashAlg; |
| memset(&digest_values->digests[i].digest, 0, sizeof(TPMU_HA)); |
| *idx = i; |
| digest_values->count += 1; |
| return TSS2_RC_SUCCESS; |
| } |
| |
| /** Execute policy PCR. |
| * |
| * This command is used to cause conditional gating of a policy based on PCR. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The PCR policy which will be executed. The policy |
| * digest will be added to the policy. |
| * @param[in] current_hash_alg The hash algorithm wich will be used for |
| * policy computation. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| * @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 occured. |
| */ |
| static TSS2_RC |
| execute_policy_pcr( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYPCR *policy, |
| TPMI_ALG_HASH current_hash_alg, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| TPML_PCR_SELECTION pcr_selection; |
| TPM2B_DIGEST pcr_digest; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* 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."); |
| |
| LOGBLOB_DEBUG(&pcr_digest.buffer[0], pcr_digest.size, "PCR Digest"); |
| |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyPCR_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| &pcr_digest, &pcr_selection); |
| return_if_error(r, "Execute PolicyPCR."); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyPCR_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyPCR_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| return r; |
| } |
| |
| /** Execute policy duplicate. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The duplicate policy which will be executed. The policy |
| * digest will be added to the policy. |
| * @param[in] current_hash_alg The hash algorithm wich will be used for |
| * policy computation. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| */ |
| static TSS2_RC |
| execute_policy_duplicate( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYDUPLICATIONSELECT *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| ifapi_policyeval_EXEC_CB *cb = ¤t_policy->callbacks; |
| r = cb->cbdup(&policy->objectName, cb->cbdup_userdata); |
| return_if_error(r, "Get name for policy duplicate select."); |
| |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyDuplicationSelect_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, |
| ESYS_TR_NONE, |
| &policy->objectName, |
| &policy->newParentName, |
| policy->includeObject); |
| return_if_error(r, "Execute PolicyDuplicatonSelect_Async."); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyDuplicationSelect_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyDuplicationselect_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| return r; |
| } |
| |
| /** Execute policy NV. |
| * |
| * A policy based on the contents of an NV Index will be executed. The |
| * NV authorization is done by a callback. For an example callback |
| * implementation see ifapi_policyeval_cbauth() |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The NV policy which will be executed. The policy |
| * digest will be added to the policy. |
| * @param[in] current_hash_alg The hash algorithm wich will be used for |
| * policy computation. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| * @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. |
| * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occured. |
| * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found |
| * during authorization. |
| * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found. |
| * @retval TSS2_FAPI_RC_BAD_PATH if the path is used in inappropriate context |
| * or contains illegal characters. |
| * @retval TSS2_FAPI_RC_NOT_PROVISIONED FAPI was not provisioned. |
| * @retval TSS2_FAPI_RC_IO_ERROR if an error occured while accessing the |
| * object store. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback |
| * is not set. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails. |
| * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest |
| * was not successful. |
| */ |
| static TSS2_RC |
| execute_policy_nv( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYNV *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| r = ifapi_nv_get_name(&policy->nvPublic, ¤t_policy->name); |
| return_if_error(r, "Compute NV name"); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_AUTH_CALLBACK) |
| ifapi_policyeval_EXEC_CB *cb = ¤t_policy->callbacks; |
| |
| /* Authorize NV object. */ |
| r = cb->cbauth(¤t_policy->name, |
| ¤t_policy->object_handle, |
| ¤t_policy->auth_handle, |
| ¤t_policy->auth_session, cb->cbauth_userdata); |
| return_try_again(r); |
| return_if_error(r, "Execute authorized policy."); |
| |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyNV_Async(esys_ctx, |
| current_policy->object_handle, |
| current_policy->auth_handle, |
| current_policy->session, |
| current_policy->auth_session, ESYS_TR_NONE, ESYS_TR_NONE, |
| &policy->operandB, policy->offset, |
| policy->operation); |
| return_if_error(r, "Execute PolicyNV_Async."); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyNV_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyNV_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| return r; |
| } |
| |
| /** Execute policy for signature based authorization. |
| * |
| * A signed authorization is included in this policy. The authorization hash |
| * of the policy data will be signed via a callback. For an example callback |
| * implementation see ifapi_sign_buffer() |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy to be signed which will be executed. The policy |
| * digest will be added to the policy. |
| * @param[in] current_hash_alg The hash algorithm wich will be used for |
| * policy computation. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback |
| * is not set. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| * @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 occured. |
| */ |
| static TSS2_RC |
| execute_policy_signed( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYSIGNED *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| size_t offset = 0; |
| //TPMT_SIGNATURE signature_tpm; |
| size_t signature_size; |
| const uint8_t *signature_ossl = NULL; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT); |
| current_policy->pem_key = NULL; |
| current_policy->object_handle = ESYS_TR_NONE; |
| current_policy->buffer_size = sizeof(INT32) + sizeof(TPM2B_NONCE) |
| + policy->cpHashA.size + policy->policyRef.size; |
| current_policy->buffer = malloc(current_policy->buffer_size); |
| return_if_null(current_policy->buffer, "Out of memory.", TSS2_FAPI_RC_MEMORY); |
| |
| r = Esys_TRSess_GetNonceTPM(esys_ctx, current_policy->session, |
| ¤t_policy->nonceTPM); |
| return_if_error(r, "Get TPM nonce."); |
| |
| /* Concatenate objects needed for the authorization hash */ |
| memcpy(¤t_policy->buffer[offset], ¤t_policy->nonceTPM->buffer[0], |
| current_policy->nonceTPM->size); |
| offset += current_policy->nonceTPM->size; |
| memset(¤t_policy->buffer[offset], 0, sizeof(INT32)); |
| offset += sizeof(INT32); |
| memcpy(¤t_policy->buffer[offset], &policy->cpHashA.buffer[0], |
| policy->cpHashA.size); |
| offset += policy->cpHashA.size; |
| memcpy(¤t_policy->buffer[offset], &policy->policyRef.buffer[0], |
| policy->policyRef.size); |
| offset += policy->policyRef.size; |
| current_policy->buffer_size = offset; |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_CALLBACK); |
| ifapi_policyeval_EXEC_CB *cb = ¤t_policy->callbacks; |
| int pem_key_size; |
| TPM2B_PUBLIC tpm_public; |
| |
| /* Recreate pem key from tpm public key */ |
| if (!current_policy->pem_key) { |
| tpm_public.publicArea = policy->keyPublic; |
| tpm_public.size = 0; |
| r = ifapi_pub_pem_key_from_tpm(&tpm_public, ¤t_policy->pem_key, |
| &pem_key_size); |
| return_if_error(r, "Convert TPM public key into PEM key."); |
| } |
| |
| /* Callback for signing the autorization hash. */ |
| r = cb->cbsign(current_policy->pem_key, policy->publicKeyHint, |
| policy->keyPEMhashAlg, current_policy->buffer, |
| current_policy->buffer_size, |
| &signature_ossl, &signature_size, |
| cb->cbsign_userdata); |
| SAFE_FREE(current_policy->pem_key); |
| SAFE_FREE(current_policy->buffer); |
| try_again_or_error_goto(r, "Execute policy signature callback.", cleanup); |
| |
| /* Convert signature into TPM format */ |
| r = ifapi_der_sig_to_tpm(&policy->keyPublic, signature_ossl, |
| signature_size, policy->keyPEMhashAlg, |
| &policy->signature_tpm); |
| goto_if_error2(r, "Convert der signature into TPM format", cleanup); |
| |
| TPM2B_PUBLIC inPublic; |
| inPublic.size = 0; |
| inPublic.publicArea = policy->keyPublic; |
| |
| /* Prepare the loading of the external public key, user for verificaton. */ |
| r = Esys_LoadExternal_Async(esys_ctx, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| NULL, &inPublic, ESYS_TR_RH_OWNER); |
| goto_if_error(r, "LoadExternal_Async", cleanup); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_LOAD_KEY); |
| r = Esys_LoadExternal_Finish(esys_ctx, ¤t_policy->object_handle); |
| try_again_or_error(r, "Load external key."); |
| |
| /* Prepare the policy execution. */ |
| r = Esys_PolicySigned_Async(esys_ctx, |
| current_policy->object_handle, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| current_policy->nonceTPM, |
| &policy->cpHashA, |
| &policy->policyRef, 0, &policy->signature_tpm); |
| SAFE_FREE(current_policy->nonceTPM); |
| goto_if_error(r, "Execute PolicySigned.", cleanup); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH); |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicySigned_Finish(esys_ctx, NULL, NULL); |
| try_again_or_error(r, "Execute PolicySigned_Finish."); |
| |
| r = Esys_FlushContext_Async(esys_ctx, current_policy->object_handle); |
| goto_if_error(r, "FlushContext_Async", cleanup); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_FLUSH_KEY); |
| r = Esys_FlushContext_Finish(esys_ctx); |
| try_again_or_error(r, "Flush key finish."); |
| |
| current_policy->object_handle = ESYS_TR_NONE; |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| cleanup: |
| SAFE_FREE(current_policy->nonceTPM); |
| SAFE_FREE(current_policy->pem_key); |
| SAFE_FREE(signature_ossl); |
| SAFE_FREE(current_policy->buffer); |
| SAFE_FREE(current_policy->pem_key); |
| /* In error cases object might not have been flushed. */ |
| if (current_policy->object_handle != ESYS_TR_NONE) |
| Esys_FlushContext(esys_ctx, current_policy->object_handle); |
| return r; |
| } |
| |
| /** Execute a policy that was signed by a certain key. |
| * |
| * All policies authorized by the key stored in the policy will be |
| * retrieved and one policy will be selected via a branch selection callback |
| * (see Fapi_SetBranchCB()) if more then one policy was found. |
| * The selected policy will be executed via a callback. For an example callback |
| * implementation see ifapi_exec_auth_policy(). |
| * |
| * For an example callback implementation to executie of an authorized policy |
| * ifapi_exec_auth_policy() |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy which defines the signing key and several |
| * additional parameters (nonce, policyRef ...). The policy |
| * digest will be added to the policy. |
| * @param[in] current_hash_alg The hash algorithm wich will be used for |
| * policy computation. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @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_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occured. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest |
| * was not successful. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback |
| * is not set. |
| * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found |
| * during authorization. |
| * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found. |
| * @retval TSS2_FAPI_RC_BAD_PATH if the path is used in inappropriate context |
| * or contains illegal characters. |
| * @retval TSS2_FAPI_RC_NOT_PROVISIONED FAPI was not provisioned. |
| * @retval TSS2_FAPI_RC_IO_ERROR if an error occured while accessing the |
| * object store. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails. |
| */ |
| static TSS2_RC |
| execute_policy_authorize( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYAUTHORIZE *policy, |
| TPMI_ALG_HASH hash_alg, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| TPM2B_PUBLIC public2b; |
| TPM2B_DIGEST aHash; |
| IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext; |
| size_t hash_size; |
| size_t size; |
| TPMT_TK_VERIFIED *ticket; |
| TPM2B_NAME *tmp_name = NULL; |
| |
| LOG_TRACE("call"); |
| public2b.size = 0; |
| if (!(hash_size = ifapi_hash_get_digest_size(hash_alg))) { |
| goto_error(r, TSS2_FAPI_RC_BAD_VALUE, |
| "Unsupported hash algorithm (%" PRIu16 ")", cleanup, |
| hash_alg); |
| } |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT); |
| current_policy->object_handle = ESYS_TR_NONE; |
| /* Execute authorized policy. */ |
| ifapi_policyeval_EXEC_CB *cb = ¤t_policy->callbacks; |
| r = cb->cbauthpol(&policy->keyPublic, hash_alg, &policy->approvedPolicy, |
| &policy->policyRef, |
| &policy->signature, cb->cbauthpol_userdata); |
| return_try_again(r); |
| goto_if_error(r, "Execute authorized policy.", cleanup); |
| |
| public2b.size = 0; |
| public2b.publicArea = policy->keyPublic; |
| r = Esys_LoadExternal_Async(esys_ctx, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| NULL, &public2b, ESYS_TR_RH_OWNER); |
| goto_if_error(r, "LoadExternal_Async", cleanup); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_LOAD_KEY); |
| r = Esys_LoadExternal_Finish(esys_ctx, ¤t_policy->object_handle); |
| try_again_or_error(r, "Load external key."); |
| |
| /* Save key name for policy execution */ |
| r = Esys_TR_GetName(esys_ctx, current_policy->object_handle, &tmp_name); |
| return_if_error(r, "Get key name."); |
| policy->keyName = *tmp_name; |
| SAFE_FREE(tmp_name); |
| |
| /* Use policyRef and policy to compute authorization hash */ |
| r = ifapi_crypto_hash_start(&cryptoContext, hash_alg); |
| return_if_error(r, "crypto hash start"); |
| |
| HASH_UPDATE_BUFFER(cryptoContext, &policy->approvedPolicy.buffer[0], |
| hash_size, r, cleanup); |
| HASH_UPDATE_BUFFER(cryptoContext, &policy->policyRef.buffer[0], |
| policy->policyRef.size, r, cleanup); |
| r = ifapi_crypto_hash_finish(&cryptoContext, |
| (uint8_t *) &aHash.buffer[0], |
| &size); |
| return_if_error(r, "crypto hash finish"); |
| |
| aHash.size = size; |
| LOGBLOB_TRACE(&policy->policyRef.buffer[0], policy->policyRef.size, "policyRef"); |
| LOGBLOB_TRACE(&aHash.buffer[0], aHash.size, "aHash"); |
| |
| /* Verify the signature retrieved from the authorized policy against |
| the computed ahash. */ |
| r = Esys_VerifySignature_Async(esys_ctx, current_policy->object_handle, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| &aHash, |
| &policy->signature); |
| goto_if_error(r, "Verify signature", cleanup); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_VERIFY); |
| r = Esys_VerifySignature_Finish(esys_ctx, &ticket); |
| try_again_or_error(r, "Load external key."); |
| |
| /* Execute policy authorize */ |
| policy->checkTicket = *ticket; |
| SAFE_FREE(ticket); |
| r = Esys_PolicyAuthorize_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| &policy->approvedPolicy, |
| &policy->policyRef, |
| &policy->keyName, |
| &policy->checkTicket); |
| goto_if_error(r, "Policy Authorize", cleanup); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH); |
| r = Esys_PolicyAuthorize_Finish(esys_ctx); |
| try_again_or_error(r, "Load external key."); |
| |
| r = Esys_FlushContext_Async(esys_ctx, current_policy->object_handle); |
| goto_if_error(r, "FlushContext_Async", cleanup); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_FLUSH_KEY); |
| /* Flush key used for verification. */ |
| r = Esys_FlushContext_Finish(esys_ctx); |
| try_again_or_error(r, "Flush key finish."); |
| |
| current_policy->object_handle = ESYS_TR_NONE; |
| current_policy->state = POLICY_EXECUTE_INIT; |
| break; |
| |
| statecasedefault(current_policy->state); |
| } |
| cleanup: |
| /* In error cases object might not have been flushed. */ |
| if (current_policy->object_handle != ESYS_TR_NONE) |
| Esys_FlushContext(esys_ctx, current_policy->object_handle); |
| |
| return r; |
| } |
| |
| /** Execute a policy whose digest is stored in the NV ram. |
| * |
| * The policy will be retrieved from policy store based on the policy digest |
| * stored in NV ram. |
| * The authorization for the NV object, the policy retrieval, and the execution |
| * is done via a callback. For an example callback implementation see |
| * ifapi_exec_auth_nv_policy(). |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy which defines the policy to be authorized |
| * and the used NV object. |
| * The policy digest will be added to the policy. |
| * @param[in] current_hash_alg The hash algorithm wich will be used for |
| * policy computation. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into |
| * the function. |
| * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest |
| * was not successful. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated. |
| * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occured. |
| * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found |
| * during authorization. |
| * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found. |
| * @retval TSS2_FAPI_RC_BAD_PATH if the path is used in inappropriate context |
| * or contains illegal characters. |
| * @retval TSS2_FAPI_RC_NOT_PROVISIONED FAPI was not provisioned. |
| * @retval TSS2_FAPI_RC_IO_ERROR if an error occured while accessing the |
| * object store. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback |
| * is not set. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails. |
| */ |
| static TSS2_RC |
| execute_policy_authorize_nv( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYAUTHORIZENV *policy, |
| TPMI_ALG_HASH hash_alg, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| ifapi_policyeval_EXEC_CB *cb; |
| |
| LOG_DEBUG("call"); |
| cb = ¤t_policy->callbacks; |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* Execute the policy stored in the NV object. */ |
| r = cb->cbauthnv(&policy->nvPublic, hash_alg, cb->cbauthpol_userdata); |
| try_again_or_error(r, "Execute policy authorize nv callback."); |
| |
| r = ifapi_nv_get_name(&policy->nvPublic, ¤t_policy->name); |
| return_if_error(r, "Compute NV name"); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_AUTH_CALLBACK) |
| /* Authorize the NV object for policy execution. */ |
| r = cb->cbauth(¤t_policy->name, |
| ¤t_policy->object_handle, |
| ¤t_policy->auth_handle, |
| ¤t_policy->auth_session, cb->cbauth_userdata); |
| return_try_again(r); |
| goto_if_error(r, "Execute authorized policy.", cleanup); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXEC_ESYS) |
| LOG_DEBUG("**STATE** POLICY_EXEC_ESYS"); |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyAuthorizeNV_Async(esys_ctx, |
| current_policy->auth_handle, |
| current_policy->object_handle, |
| current_policy->session, |
| current_policy->auth_session, ESYS_TR_NONE, |
| ESYS_TR_NONE); |
| goto_if_error(r, "PolicyAuthorizeNV_Async", cleanup); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_AUTH_SENT) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyAuthorizeNV_Finish(esys_ctx); |
| return_try_again(r); |
| goto_if_error(r, "FAPI PolicyAuthorizeNV_Finish", cleanup); |
| current_policy->state = POLICY_EXECUTE_INIT; |
| break; |
| |
| statecasedefault(current_policy->state); |
| } |
| cleanup: |
| return r; |
| } |
| |
| /** Execute a policy based on a secret-based authorization. |
| * |
| * The policy defines an object whose secret is needed for policy execution. |
| * The authorization of the object is done via a callback. |
| * For an example callback implementation see ifapi_policyeval_cbauth;(). |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy which defines the object whose secret |
| * is needed for policy execution. |
| * The policy digest will be added to the policy. |
| * @param[in] current_hash_alg The hash algorithm wich will be used for |
| * policy computation. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found |
| * during authorization. |
| * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated. |
| * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found. |
| * @retval TSS2_FAPI_RC_BAD_PATH if the path is used in inappropriate context |
| * or contains illegal characters. |
| * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into |
| * the function. |
| * @retval TSS2_FAPI_RC_NOT_PROVISIONED FAPI was not provisioned. |
| * @retval TSS2_FAPI_RC_IO_ERROR if an error occured while accessing the |
| * object store. |
| * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occured. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback |
| * is not set. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails. |
| * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest |
| * was not successful. |
| */ |
| static TSS2_RC |
| execute_policy_secret( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYSECRET *policy, |
| TPMI_ALG_HASH hash_alg, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| (void)hash_alg; |
| |
| LOG_DEBUG("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| ifapi_policyeval_EXEC_CB *cb = ¤t_policy->callbacks; |
| /* Callback for the object authorization. */ |
| r = cb->cbauth(&policy->objectName, |
| ¤t_policy->object_handle, |
| ¤t_policy->auth_handle, |
| ¤t_policy->auth_session, cb->cbauth_userdata); |
| return_try_again(r); |
| goto_if_error(r, "Authorize object callback.", cleanup); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXEC_ESYS) |
| r = Esys_TRSess_GetNonceTPM(esys_ctx, current_policy->session, |
| ¤t_policy->nonceTPM); |
| goto_if_error(r, "Get TPM nonce.", cleanup); |
| |
| policy->nonceTPM = *(current_policy->nonceTPM); |
| SAFE_FREE(current_policy->nonceTPM); |
| |
| /* Prepare the policy execution. */ |
| r = Esys_PolicySecret_Async(esys_ctx, |
| current_policy->auth_handle, |
| current_policy->session, |
| current_policy->auth_session, ESYS_TR_NONE, |
| ESYS_TR_NONE, &policy->nonceTPM, |
| &policy->cpHashA, &policy->policyRef, |
| 0); |
| goto_if_error(r, "PolicySecret_Async", cleanup); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_AUTH_SENT) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicySecret_Finish(esys_ctx, NULL, |
| NULL); |
| return_try_again(r); |
| goto_if_error(r, "FAPI PolicyAuthorizeNV_Finish", error_cleanup); |
| current_policy->state = POLICY_EXECUTE_INIT; |
| break; |
| |
| statecasedefault(current_policy->state); |
| } |
| |
| cleanup: |
| return r; |
| |
| error_cleanup: |
| SAFE_FREE(current_policy->nonceTPM); |
| return r; |
| } |
| |
| /** Execute a policy depending on the TPM timers. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy which defines the values for the comparision |
| * with the TPM timers and the comparision operation. |
| * The policy digest will be added to the policy. |
| * @param[in] current_hash_alg The hash algorithm wich will be used for |
| * policy computation. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| */ |
| static TSS2_RC |
| execute_policy_counter_timer( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYCOUNTERTIMER *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyCounterTimer_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, |
| ESYS_TR_NONE, |
| &policy->operandB, |
| policy->offset, |
| policy->operation); |
| return_if_error(r, "Execute PolicyCounter."); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyCounterTimer_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyCounterTImer_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| return r; |
| } |
| |
| /** Execute a policy depending on physical presence. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy indicating that physical presence is needed. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| */ |
| static TSS2_RC |
| execute_policy_physical_presence( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYPHYSICALPRESENCE *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| (void)policy; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyPhysicalPresence_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, |
| ESYS_TR_NONE); |
| return_if_error(r, "Execute PolicyPhysicalpresence."); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyPhysicalPresence_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyPhysicalPresence_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| return r; |
| } |
| |
| /** Execute a policy for binding a authorization value of the authorized entity. |
| * |
| * The authValue will be included in hmacKey of the session. |
| |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy indicating that a auth value is needed. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| */ |
| static TSS2_RC |
| execute_policy_auth_value( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYAUTHVALUE *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| (void)policy; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyAuthValue_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, |
| ESYS_TR_NONE); |
| return_if_error(r, "Execute PolicyAuthValue."); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyAuthValue_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyAuthValue_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| return r; |
| } |
| |
| /** Execute a policy for binding a authorization value of the authorized object. |
| * |
| * The authValue of the authorized object will be checked when the session is used |
| * for authorization.. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy indicating that a auth value is needed. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| */ |
| static TSS2_RC |
| execute_policy_password( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYPASSWORD *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| (void)policy; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyPassword_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, |
| ESYS_TR_NONE); |
| return_if_error(r, "Execute PolicyPassword."); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyPassword_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyPassword_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| return r; |
| } |
| |
| /** Execute a policy to limit an authorization to a specific command code. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy with the command code used fo limitting. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| */ |
| static TSS2_RC |
| execute_policy_command_code( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYCOMMANDCODE *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyCommandCode_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| policy->code); |
| return_if_error(r, "Execute PolicyCommandCode."); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyCommandCode_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyCommandCode_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state) |
| } |
| return r; |
| } |
| |
| /** Execute a policy for binding the policy to a specific set of TPM entities. |
| * |
| * Up to three entity names can be defined in the policy. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy with the entity names. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| */ |
| static TSS2_RC |
| execute_policy_name_hash( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYNAMEHASH *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyNameHash_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| &policy->nameHash); |
| return_if_error(r, "Execute PolicyNameH."); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyNameHash_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyNameHash_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state) |
| } |
| return r; |
| } |
| |
| /** Execute a policy for binding the policy to command parameters. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy with the cp hash. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| */ |
| static TSS2_RC |
| execute_policy_cp_hash( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYCPHASH *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyCpHash_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| &policy->cpHash); |
| return_if_error(r, "Execute PolicyNameH."); |
| |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyCpHash_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyCpHash_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| return r; |
| } |
| |
| /** Execute a policy for binding the policy to a certain locality. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy with the locality. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| */ |
| static TSS2_RC |
| execute_policy_locality( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYLOCALITY *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyLocality_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| policy->locality); |
| return_if_error(r, "Execute PolicyLocality."); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyLocality_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyNV_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| return r; |
| } |
| |
| /** Execute a policy for binding the policy to the NV written state. |
| * |
| * The state NV written yes or NV written no can be defined in the policy. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy with the NV written switch YES or NO. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| */ |
| static TSS2_RC |
| execute_policy_nv_written( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYNVWRITTEN *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* Prepare the policy execution. */ |
| r = Esys_PolicyNvWritten_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| policy->writtenSet); |
| return_if_error(r, "Execute PolicyNvWritten."); |
| fallthrough; |
| |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyNvWritten_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyNV_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| return r; |
| } |
| |
| /** Execute a policy for binding the policy to the NV written state. |
| * |
| * The state NV written yes or NV written no can be defined in the policy. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy with the NV written switch YES or NO. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into |
| * the function. |
| */ |
| static TSS2_RC |
| execute_policy_or( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYOR *policy, |
| TPMI_ALG_HASH current_hash_alg, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT) |
| /* Prepare the policy execution. */ |
| r = compute_or_digest_list(policy->branches, current_hash_alg, |
| ¤t_policy->digest_list); |
| return_if_error(r, "Compute policy or digest list."); |
| |
| r = Esys_PolicyOR_Async(esys_ctx, |
| current_policy->session, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| ¤t_policy->digest_list); |
| return_if_error(r, "Execute PolicyPCR."); |
| fallthrough; |
| statecase(current_policy->state, POLICY_EXECUTE_FINISH) |
| /* Finalize the policy execution if possible. */ |
| r = Esys_PolicyOR_Finish(esys_ctx); |
| try_again_or_error(r, "Execute PolicyPCR_Finish."); |
| |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| } |
| |
| /** Execute a policy for executing a callback during policy execution. |
| * |
| * The action name stored in the policy name will be passed do the callback |
| * function. The policy action callback has to be set with the function: |
| * Fapi_SetPolicyActionCB(). |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy with action name. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback |
| * is not set. |
| */ |
| static TSS2_RC |
| execute_policy_action( |
| ESYS_CONTEXT *esys_ctx, |
| TPMS_POLICYACTION *policy, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| (void)(esys_ctx); |
| LOG_TRACE("call"); |
| |
| switch (current_policy->state) { |
| statecase(current_policy->state, POLICY_EXECUTE_INIT); |
| ifapi_policyeval_EXEC_CB *cb = ¤t_policy->callbacks; |
| |
| /* Execute the callback and try it again if the callback is not finished. */ |
| r = cb->cbaction(policy->action, cb->cbaction_userdata); |
| try_again_or_error(r, "Execute policy action callback."); |
| current_policy->state = POLICY_EXECUTE_INIT; |
| return r; |
| |
| statecasedefault(current_policy->state); |
| } |
| } |
| |
| /** Execute a policy element depending on the type. |
| * |
| * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the |
| * policy command. |
| * @param[in,out] policy The policy element with the policy to be executed and |
| * the type of the policy. |
| * @param[in,out] current_policy The policy context which stores the state |
| * of the policy execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occured. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found |
| * during authorization. |
| * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated. |
| * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found. |
| * @retval TSS2_FAPI_RC_BAD_PATH if the path is used in inappropriate context |
| * or contains illegal characters. |
| * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into |
| * the function. |
| * @retval TSS2_FAPI_RC_NOT_PROVISIONED FAPI was not provisioned. |
| * @retval TSS2_FAPI_RC_IO_ERROR if an error occured while accessing the |
| * object store. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback |
| * is not set. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails. |
| * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest |
| * was not successful. |
| */ |
| static TSS2_RC |
| execute_policy_element( |
| ESYS_CONTEXT *esys_ctx, |
| TPMT_POLICYELEMENT *policy, |
| TPMI_ALG_HASH hash_alg, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| |
| LOG_TRACE("call"); |
| |
| switch (policy->type) { |
| case POLICYSECRET: |
| r = execute_policy_secret(esys_ctx, |
| &policy->element.PolicySecret, |
| hash_alg, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy authorize", error); |
| break; |
| case POLICYPCR: |
| r = execute_policy_pcr(esys_ctx, |
| &policy->element.PolicyPCR, |
| hash_alg, current_policy); |
| try_again_or_error_goto(r, "Execute policy pcr", error); |
| break; |
| case POLICYAUTHVALUE: |
| r = execute_policy_auth_value(esys_ctx, |
| &policy->element.PolicyAuthValue, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy auth value", error); |
| break; |
| case POLICYOR: |
| r = execute_policy_or(esys_ctx, |
| &policy->element.PolicyOr, |
| hash_alg, current_policy); |
| try_again_or_error_goto(r, "Execute policy or", error); |
| break; |
| case POLICYSIGNED: |
| r = execute_policy_signed(esys_ctx, |
| &policy->element.PolicySigned, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy signed", error); |
| break; |
| case POLICYAUTHORIZE: |
| r = execute_policy_authorize(esys_ctx, |
| &policy->element.PolicyAuthorize, |
| hash_alg, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy authorize", error); |
| break; |
| case POLICYAUTHORIZENV: |
| r = execute_policy_authorize_nv(esys_ctx, |
| &policy->element.PolicyAuthorizeNv, |
| hash_alg, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy authorize", error); |
| break; |
| case POLICYNV: |
| r = execute_policy_nv(esys_ctx, |
| &policy->element.PolicyNV, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy nv", error); |
| break; |
| case POLICYDUPLICATIONSELECT: |
| r = execute_policy_duplicate(esys_ctx, |
| &policy->element.PolicyDuplicationSelect, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy duplicate", error); |
| break; |
| case POLICYNVWRITTEN: |
| r = execute_policy_nv_written(esys_ctx, |
| &policy->element.PolicyNvWritten, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy nv written", error); |
| break; |
| case POLICYLOCALITY: |
| r = execute_policy_locality(esys_ctx, |
| &policy->element.PolicyLocality, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy locality", error); |
| break; |
| case POLICYCOMMANDCODE: |
| r = execute_policy_command_code(esys_ctx, |
| &policy->element.PolicyCommandCode, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy command code", error); |
| break; |
| case POLICYNAMEHASH: |
| r = execute_policy_name_hash(esys_ctx, |
| &policy->element.PolicyNameHash, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy name hash", error); |
| break; |
| case POLICYCPHASH: |
| r = execute_policy_cp_hash(esys_ctx, |
| &policy->element.PolicyCpHash, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy cp hash", error); |
| break; |
| case POLICYPHYSICALPRESENCE: |
| r = execute_policy_physical_presence(esys_ctx, |
| &policy->element.PolicyPhysicalPresence, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy physical presence", error); |
| break; |
| case POLICYPASSWORD: |
| r = execute_policy_password(esys_ctx, |
| &policy->element.PolicyPassword, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy password", error); |
| break; |
| case POLICYCOUNTERTIMER: |
| r = execute_policy_counter_timer(esys_ctx, |
| &policy->element.PolicyCounterTimer, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy counter timer", error); |
| break; |
| case POLICYACTION: |
| r = execute_policy_action(esys_ctx, |
| &policy->element.PolicyAction, |
| current_policy); |
| try_again_or_error_goto(r, "Execute policy action", error); |
| break; |
| |
| default: |
| return_error(TSS2_FAPI_RC_GENERAL_FAILURE, |
| "Policy not implemented"); |
| } |
| return r; |
| error: |
| return r; |
| |
| /* All policies executed successfully */ |
| return r; |
| } |
| |
| /** Compute execution order for policies based on branch selection. |
| * |
| * To simplify asynncronous policy executiion a linked list of the policy structures |
| * needed for execution based on the result of the branch selection callbacks |
| * is computed. |
| * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback |
| * is not set. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails. |
| */ |
| static TSS2_RC |
| compute_policy_list( |
| IFAPI_POLICY_EXEC_CTX *pol_ctx, |
| TPML_POLICYELEMENTS *elements) |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| TPML_POLICYBRANCHES *branches; |
| TPML_POLICYELEMENTS *or_elements; |
| size_t branch_idx, i; |
| |
| for (i = 0; i < elements->count; i++) { |
| if (elements->elements[i].type == POLICYOR) { |
| branches = elements->elements[i].element.PolicyOr.branches; |
| r = pol_ctx->callbacks.cbpolsel(branches, &branch_idx, |
| pol_ctx->callbacks.cbpolsel_userdata); |
| return_if_error(r, "Select policy branch."); |
| or_elements = branches->authorizations[branch_idx].policy; |
| r = compute_policy_list(pol_ctx, or_elements); |
| return_if_error(r, "Compute policy digest list for policy or."); |
| } |
| r = append_object_to_list(&elements->elements[i], &pol_ctx->policy_elements); |
| return_if_error(r, "Extend policy list."); |
| } |
| return r; |
| } |
| |
| /** Initialize policy element list to be executed and store policy in context. |
| * |
| * @param[in] pol_ctx Context for execution of a list of policy elements. |
| * @param[in] hash_alg The hash algorithm used for the policy computation. |
| * @param[in,out] policy The policy to be executed. Some policy elements will |
| * be used to store computed parameters needed for policy |
| * execution. |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN If the callback for branch selection is |
| * not defined. This callback will be needed of or policies have to be |
| * executed. |
| * @retval TSS2_FAPI_RC_BAD_VALUE If the computed branch index deliverd by the |
| * callback does not identify a branch. |
| * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails. |
| */ |
| TSS2_RC |
| ifapi_policyeval_execute_prepare( |
| IFAPI_POLICY_EXEC_CTX *pol_ctx, |
| TPMI_ALG_HASH hash_alg, |
| TPMS_POLICY *policy) |
| { |
| TSS2_RC r; |
| |
| pol_ctx->policy = policy; |
| pol_ctx->hash_alg = hash_alg; |
| r = compute_policy_list(pol_ctx, policy->policy); |
| return_if_error(r, "Compute list of policy elements to be executed."); |
| |
| return TSS2_RC_SUCCESS; |
| } |
| |
| /** Execute all policy commands defined by a list of policy elements. |
| * |
| * @retval TSS2_RC_SUCCESS on success. |
| * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated. |
| * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution. |
| * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy |
| * store. |
| * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was |
| * not successful. |
| * @retval TSS2_FAPI_RC_BAD_TEMPLATE In a invalid policy is loaded during execution. |
| * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and |
| * this function needs to be called again. |
| * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred. |
| * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous |
| * operation already pending. |
| * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed. |
| * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found |
| * during authorization. |
| * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback |
| * is not set. |
| * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails. |
| * @retval TSS2_ESYS_RC_* possible error codes of ESAPI. |
| * @retval TSS2_FAPI_RC_BAD_PATH if the path is used in inappropriate context |
| * or contains illegal characters. |
| * @retval TSS2_FAPI_RC_NOT_PROVISIONED FAPI was not provisioned. |
| */ |
| TSS2_RC |
| ifapi_policyeval_execute( |
| ESYS_CONTEXT *esys_ctx, |
| IFAPI_POLICY_EXEC_CTX *current_policy) |
| |
| { |
| TSS2_RC r = TSS2_RC_SUCCESS; |
| NODE_OBJECT_T *current_policy_element; |
| |
| LOG_DEBUG("call"); |
| |
| while (current_policy->policy_elements) { |
| r = execute_policy_element(esys_ctx, |
| (TPMT_POLICYELEMENT *) |
| current_policy->policy_elements->object, |
| current_policy->hash_alg, |
| current_policy); |
| return_try_again(r); |
| |
| if (r != TSS2_RC_SUCCESS) { |
| Esys_FlushContext(esys_ctx, current_policy->session); |
| current_policy->session = ESYS_TR_NONE; |
| ifapi_free_node_list(current_policy->policy_elements); |
| |
| } |
| return_if_error(r, "Execute policy."); |
| |
| current_policy_element = current_policy->policy_elements; |
| current_policy->policy_elements = current_policy->policy_elements->next; |
| SAFE_FREE(current_policy_element); |
| } |
| return r; |
| |
| } |