• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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