From 2642b761e92fda84473d57d4c2ab117e425e3fbd Mon Sep 17 00:00:00 2001 From: Juergen Repp Date: Mon, 5 Dec 2022 11:17:45 +0100 Subject: [PATCH] FAPI: Add Policy Template. The instantiation and execution of policy template is added. Fixes: #2509 Signed-off-by: Juergen Repp --- src/tss2-fapi/ifapi_policy_calculate.c | 98 +++++++++++++++++++++ src/tss2-fapi/ifapi_policy_execute.c | 90 +++++++++++++++++++ src/tss2-fapi/ifapi_policy_json_serialize.c | 4 +- 3 files changed, 190 insertions(+), 2 deletions(-) diff --git a/src/tss2-fapi/ifapi_policy_calculate.c b/src/tss2-fapi/ifapi_policy_calculate.c index 7bbd916f3..fcf214cd4 100644 --- a/src/tss2-fapi/ifapi_policy_calculate.c +++ b/src/tss2-fapi/ifapi_policy_calculate.c @@ -1198,6 +1198,95 @@ ifapi_calculate_policy_or( return r; } +/** Calculate a policy digest for policy template. + * + * The template hash will be derived from template_public if no template hash + * is provided. + * + * @param[in] policy The policy with the template hash or the public data used to + * compute the template hash. + * @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_template( + TPMS_POLICYTEMPLATE *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_DIGEST computed_template_hash; + TPM2B_DIGEST *used_template_hash; + IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL; + uint8_t buffer[sizeof(TPM2B_PUBLIC)]; + size_t offset = 0; + size_t digest_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."); + + if (policy->templateHash.size == 0) { + used_template_hash = &computed_template_hash; + r = Tss2_MU_TPMT_PUBLIC_Marshal(&policy->templatePublic.publicArea, + &buffer[0], sizeof(TPMT_PUBLIC), &offset); + return_if_error(r, "Marshaling TPMT_PUBLIC"); + + r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg); + return_if_error(r, "crypto hash start"); + + HASH_UPDATE_BUFFER(cryptoContext, + &buffer[0], offset, + r, cleanup); + r = ifapi_crypto_hash_finish(&cryptoContext, + &used_template_hash->buffer[0], + &digest_size); + goto_if_error(r, "crypto hash finish", cleanup); + used_template_hash->size = digest_size; + } else { + used_template_hash = &policy->templateHash; + } + + LOG_TRACE("Compute policy template"); + r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg); + return_if_error(r, "crypto hash start"); + + HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyTemplate, r, + cleanup); + HASH_UPDATE_BUFFER(cryptoContext, &used_template_hash->buffer[0], + used_template_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"); + + 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; +} + /** Compute policy digest for a list of policies. * * Every policy in the list will update the previous policy. Thus the final @@ -1362,6 +1451,15 @@ ifapi_calculate_policy( /* This does not alter the policyDigest */ break; + case POLICYTEMPLATE: + r = ifapi_calculate_policy_template(&policy->elements[i].element. + PolicyTemplate, + &policy->elements[i]. + policyDigests, hash_alg); + return_if_error(r, "Compute policy template"); + + break; + default: return_error(TSS2_FAPI_RC_BAD_VALUE, "Policy not implemented"); diff --git a/src/tss2-fapi/ifapi_policy_execute.c b/src/tss2-fapi/ifapi_policy_execute.c index 38145c7d2..278c82dea 100644 --- a/src/tss2-fapi/ifapi_policy_execute.c +++ b/src/tss2-fapi/ifapi_policy_execute.c @@ -1505,6 +1505,89 @@ execute_policy_action( } } +/** Execute policy template. + * + * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the + * policy command. + * @param[in,out] policy The policy with the template digest or the public data + * used to compute the template digest. + * @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_template( + ESYS_CONTEXT *esys_ctx, + TPMS_POLICYTEMPLATE *policy, + IFAPI_POLICY_EXEC_CTX *current_policy) +{ + TSS2_RC r = TSS2_RC_SUCCESS; + + LOG_TRACE("call"); + + TPM2B_DIGEST computed_template_hash; + TPM2B_DIGEST *used_template_hash; + IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL; + uint8_t buffer[sizeof(TPM2B_PUBLIC)]; + size_t offset = 0; + size_t digest_size; + + + switch (current_policy->state) { + statecase(current_policy->state, POLICY_EXECUTE_INIT) + if (policy->templateHash.size == 0) { + used_template_hash = &computed_template_hash; + r = Tss2_MU_TPMT_PUBLIC_Marshal(&policy->templatePublic.publicArea, + &buffer[0], sizeof(TPMT_PUBLIC), &offset); + return_if_error(r, "Marshaling TPMT_PUBLIC"); + + r = ifapi_crypto_hash_start(&cryptoContext, current_policy->hash_alg); + return_if_error(r, "crypto hash start"); + + HASH_UPDATE_BUFFER(cryptoContext, + &buffer[0], offset, + r, cleanup); + r = ifapi_crypto_hash_finish(&cryptoContext, + &used_template_hash->buffer[0], + &digest_size); + goto_if_error(r, "crypto hash finish", cleanup); + used_template_hash->size = digest_size; + + } else { + used_template_hash = &policy->templateHash; + } + + /* Prepare the policy execution. */ + r = Esys_PolicyTemplate_Async(esys_ctx, + current_policy->session, + ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + used_template_hash); + return_if_error(r, "Execute PolicyTemplate."); + fallthrough; + + statecase(current_policy->state, POLICY_EXECUTE_FINISH) + /* Finalize the policy execution if possible. */ + r = Esys_PolicyTemplate_Finish(esys_ctx); + try_again_or_error(r, "Execute PolicyTemplate_Finish."); + + current_policy->state = POLICY_EXECUTE_INIT; + return r; + + statecasedefault(current_policy->state) + } + return r; + + cleanup: + if (cryptoContext) + ifapi_crypto_hash_abort(&cryptoContext); + return r; +} + /** Execute a policy element depending on the type. * * @param[in,out] *esys_ctx The ESAPI context which is needed to execute the @@ -1657,6 +1740,13 @@ execute_policy_element( try_again_or_error_goto(r, "Execute policy action", error); break; + case POLICYTEMPLATE: + r = execute_policy_template(esys_ctx, + &policy->element.PolicyTemplate, + current_policy); + try_again_or_error_goto(r, "Execute policy template", error); + break; + default: return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "Policy not implemented"); diff --git a/src/tss2-fapi/ifapi_policy_json_serialize.c b/src/tss2-fapi/ifapi_policy_json_serialize.c index 926bfead0..f8ee4e42d 100644 --- a/src/tss2-fapi/ifapi_policy_json_serialize.c +++ b/src/tss2-fapi/ifapi_policy_json_serialize.c @@ -803,10 +803,10 @@ ifapi_json_TPMS_POLICYTEMPLATE_serialize(const TPMS_POLICYTEMPLATE *in, json_object_object_add(*jso, "templateHash", jso2); } - if (in->templatePublic.size != 0) { + if (in->templatePublic.publicArea.type) { jso2 = NULL; cond_cnt++; - r = ifapi_json_TPM2B_PUBLIC_serialize(&in->templatePublic, &jso2); + r = ifapi_json_TPMT_PUBLIC_serialize(&in->templatePublic.publicArea, &jso2); return_if_error(r, "Serialize TPM2B_PUBLIC"); json_object_object_add(*jso, "templatePublic", jso2);