1*758e9fbaSOystein Eftevaag /* SPDX-License-Identifier: BSD-2-Clause */
2*758e9fbaSOystein Eftevaag /*******************************************************************************
3*758e9fbaSOystein Eftevaag * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
4*758e9fbaSOystein Eftevaag * All rights reserved.
5*758e9fbaSOystein Eftevaag *******************************************************************************/
6*758e9fbaSOystein Eftevaag
7*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
8*758e9fbaSOystein Eftevaag #include <config.h>
9*758e9fbaSOystein Eftevaag #endif
10*758e9fbaSOystein Eftevaag
11*758e9fbaSOystein Eftevaag #include <string.h>
12*758e9fbaSOystein Eftevaag #include <stdlib.h>
13*758e9fbaSOystein Eftevaag
14*758e9fbaSOystein Eftevaag #include "tss2_mu.h"
15*758e9fbaSOystein Eftevaag #include "fapi_util.h"
16*758e9fbaSOystein Eftevaag #include "fapi_int.h"
17*758e9fbaSOystein Eftevaag #include "fapi_crypto.h"
18*758e9fbaSOystein Eftevaag #include "fapi_policy.h"
19*758e9fbaSOystein Eftevaag #include "ifapi_policy_instantiate.h"
20*758e9fbaSOystein Eftevaag #include "ifapi_policy_callbacks.h"
21*758e9fbaSOystein Eftevaag #include "ifapi_helpers.h"
22*758e9fbaSOystein Eftevaag #include "ifapi_json_deserialize.h"
23*758e9fbaSOystein Eftevaag #include "tpm_json_deserialize.h"
24*758e9fbaSOystein Eftevaag #include "ifapi_policy_store.h"
25*758e9fbaSOystein Eftevaag #define LOGMODULE fapi
26*758e9fbaSOystein Eftevaag #include "util/log.h"
27*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
28*758e9fbaSOystein Eftevaag
29*758e9fbaSOystein Eftevaag /** Compute policy digest for a policy tree.
30*758e9fbaSOystein Eftevaag *
31*758e9fbaSOystein Eftevaag * A policy or a policy path can be passed. If a policy is passed the
32*758e9fbaSOystein Eftevaag * policy is computed directly from the policy otherwise the policy has to be
33*758e9fbaSOystein Eftevaag * retrieved from policy store to determine the policy.
34*758e9fbaSOystein Eftevaag *
35*758e9fbaSOystein Eftevaag * @param[in,out] context The FAPI_CONTEXT.
36*758e9fbaSOystein Eftevaag * @param[in] policyPath The policy path for policy store.
37*758e9fbaSOystein Eftevaag * @param[in] policy The result of policy deserialization.
38*758e9fbaSOystein Eftevaag * @param[in] hash_alg The used hash alg for policy digest computations.
39*758e9fbaSOystein Eftevaag * @param[out] digest_idx The index of the current digest. The policy digest can be
40*758e9fbaSOystein Eftevaag * computed for several hash algorithms the digets index is a reverence
41*758e9fbaSOystein Eftevaag * to the current digest values.
42*758e9fbaSOystein Eftevaag * @param[out] hash_size The size of the current policy digest.
43*758e9fbaSOystein Eftevaag *
44*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
45*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
46*758e9fbaSOystein Eftevaag * not covered by other return codes.
47*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during policy calculation.
48*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
49*758e9fbaSOystein Eftevaag * store.
50*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If an object needed for policy calculation was
51*758e9fbaSOystein Eftevaag * not found.
52*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
53*758e9fbaSOystein Eftevaag * not successful.
54*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
55*758e9fbaSOystein Eftevaag * this function needs to be called again.
56*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
57*758e9fbaSOystein Eftevaag * operation already pending.
58*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
59*758e9fbaSOystein Eftevaag * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
60*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
61*758e9fbaSOystein Eftevaag */
62*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_calculate_tree(FAPI_CONTEXT * context,const char * policyPath,TPMS_POLICY * policy,TPMI_ALG_HASH hash_alg,size_t * digest_idx,size_t * hash_size)63*758e9fbaSOystein Eftevaag ifapi_calculate_tree(
64*758e9fbaSOystein Eftevaag FAPI_CONTEXT *context,
65*758e9fbaSOystein Eftevaag const char *policyPath,
66*758e9fbaSOystein Eftevaag TPMS_POLICY *policy,
67*758e9fbaSOystein Eftevaag TPMI_ALG_HASH hash_alg,
68*758e9fbaSOystein Eftevaag size_t *digest_idx,
69*758e9fbaSOystein Eftevaag size_t *hash_size)
70*758e9fbaSOystein Eftevaag {
71*758e9fbaSOystein Eftevaag size_t i;
72*758e9fbaSOystein Eftevaag TSS2_RC r = TSS2_RC_SUCCESS;
73*758e9fbaSOystein Eftevaag bool already_computed = false;
74*758e9fbaSOystein Eftevaag IFAPI_POLICY_EVAL_INST_CTX *eval_ctx = NULL;
75*758e9fbaSOystein Eftevaag ifapi_policyeval_INST_CB *callbacks;
76*758e9fbaSOystein Eftevaag
77*758e9fbaSOystein Eftevaag if (context->policy.state == POLICY_INIT && !policyPath)
78*758e9fbaSOystein Eftevaag /* Skip policy reading */
79*758e9fbaSOystein Eftevaag context->policy.state = POLICY_INSTANTIATE_PREPARE;
80*758e9fbaSOystein Eftevaag
81*758e9fbaSOystein Eftevaag switch (context->policy.state) {
82*758e9fbaSOystein Eftevaag statecase(context->policy.state, POLICY_INIT);
83*758e9fbaSOystein Eftevaag fallthrough;
84*758e9fbaSOystein Eftevaag
85*758e9fbaSOystein Eftevaag statecase(context->policy.state, POLICY_READ);
86*758e9fbaSOystein Eftevaag r = ifapi_policy_store_load_async(&context->pstore, &context->io, policyPath);
87*758e9fbaSOystein Eftevaag goto_if_error2(r, "Can't open: %s", cleanup, policyPath);
88*758e9fbaSOystein Eftevaag fallthrough;
89*758e9fbaSOystein Eftevaag
90*758e9fbaSOystein Eftevaag statecase(context->policy.state, POLICY_READ_FINISH);
91*758e9fbaSOystein Eftevaag r = ifapi_policy_store_load_finish(&context->pstore, &context->io, policy);
92*758e9fbaSOystein Eftevaag return_try_again(r);
93*758e9fbaSOystein Eftevaag return_if_error_reset_state(r, "read_finish failed");
94*758e9fbaSOystein Eftevaag fallthrough;
95*758e9fbaSOystein Eftevaag
96*758e9fbaSOystein Eftevaag statecase(context->policy.state, POLICY_INSTANTIATE_PREPARE);
97*758e9fbaSOystein Eftevaag eval_ctx = &context->policy.eval_ctx;
98*758e9fbaSOystein Eftevaag callbacks = &eval_ctx->callbacks;
99*758e9fbaSOystein Eftevaag callbacks->cbname = ifapi_get_object_name;
100*758e9fbaSOystein Eftevaag callbacks->cbname_userdata = context;
101*758e9fbaSOystein Eftevaag callbacks->cbpublic = ifapi_get_key_public;
102*758e9fbaSOystein Eftevaag callbacks->cbpublic_userdata = context;
103*758e9fbaSOystein Eftevaag callbacks->cbnvpublic = ifapi_get_nv_public;
104*758e9fbaSOystein Eftevaag callbacks->cbnvpublic_userdata = context;
105*758e9fbaSOystein Eftevaag callbacks->cbpcr = ifapi_read_pcr;
106*758e9fbaSOystein Eftevaag callbacks->cbpcr_userdata = context;
107*758e9fbaSOystein Eftevaag
108*758e9fbaSOystein Eftevaag r = ifapi_policyeval_instantiate_async(eval_ctx, policy, callbacks);
109*758e9fbaSOystein Eftevaag goto_if_error(r, "Instantiate policy.", cleanup);
110*758e9fbaSOystein Eftevaag fallthrough;
111*758e9fbaSOystein Eftevaag
112*758e9fbaSOystein Eftevaag statecase(context->policy.state, POLICY_INSTANTIATE);
113*758e9fbaSOystein Eftevaag r = ifapi_policyeval_instantiate_finish(&context->policy.eval_ctx);
114*758e9fbaSOystein Eftevaag FAPI_SYNC(r, "Instantiate policy.", cleanup);
115*758e9fbaSOystein Eftevaag ifapi_free_node_list(context->policy.eval_ctx.policy_elements);
116*758e9fbaSOystein Eftevaag if (!(*hash_size = ifapi_hash_get_digest_size(hash_alg))) {
117*758e9fbaSOystein Eftevaag goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
118*758e9fbaSOystein Eftevaag "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
119*758e9fbaSOystein Eftevaag hash_alg);
120*758e9fbaSOystein Eftevaag }
121*758e9fbaSOystein Eftevaag
122*758e9fbaSOystein Eftevaag for (i = 0; i < policy->policyDigests.count; i++) {
123*758e9fbaSOystein Eftevaag if (policy->policyDigests.digests[i].hashAlg == hash_alg) {
124*758e9fbaSOystein Eftevaag /* Digest already computed */
125*758e9fbaSOystein Eftevaag *digest_idx = i;
126*758e9fbaSOystein Eftevaag already_computed = true;
127*758e9fbaSOystein Eftevaag }
128*758e9fbaSOystein Eftevaag }
129*758e9fbaSOystein Eftevaag if (already_computed)
130*758e9fbaSOystein Eftevaag break;
131*758e9fbaSOystein Eftevaag
132*758e9fbaSOystein Eftevaag if (i > TPM2_NUM_PCR_BANKS) {
133*758e9fbaSOystein Eftevaag return_error(TSS2_FAPI_RC_BAD_VALUE, "Table overflow");
134*758e9fbaSOystein Eftevaag }
135*758e9fbaSOystein Eftevaag *digest_idx = i;
136*758e9fbaSOystein Eftevaag policy->policyDigests.count += 1;
137*758e9fbaSOystein Eftevaag policy->policyDigests.digests[i].hashAlg = hash_alg;
138*758e9fbaSOystein Eftevaag
139*758e9fbaSOystein Eftevaag memset(&policy->policyDigests.digests[*digest_idx].digest, 0,
140*758e9fbaSOystein Eftevaag sizeof(TPMU_HA));
141*758e9fbaSOystein Eftevaag
142*758e9fbaSOystein Eftevaag r = ifapi_calculate_policy(policy->policy,
143*758e9fbaSOystein Eftevaag &policy->policyDigests, hash_alg,
144*758e9fbaSOystein Eftevaag *hash_size, *digest_idx);
145*758e9fbaSOystein Eftevaag goto_if_error(r, "Compute policy.", cleanup);
146*758e9fbaSOystein Eftevaag
147*758e9fbaSOystein Eftevaag break;
148*758e9fbaSOystein Eftevaag statecasedefault(context->policy.state);
149*758e9fbaSOystein Eftevaag }
150*758e9fbaSOystein Eftevaag cleanup:
151*758e9fbaSOystein Eftevaag context->policy.state = POLICY_INIT;
152*758e9fbaSOystein Eftevaag return r;
153*758e9fbaSOystein Eftevaag }
154