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