blob: c88275caf850e5d98e45dcd1b896c8ff4d752fd4 [file] [log] [blame]
Juergen Reppff821bd2017-12-11 15:21:42 +01001/*******************************************************************************
2 * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 * THE POSSIBILITY OF SUCH DAMAGE.
26 ******************************************************************************/
27
Philip Tricca910f17c2018-03-15 12:38:37 -070028#include "tss2_mu.h"
29#include "tss2_sys.h"
Tadeusz Struka3e03742018-02-26 15:27:39 -080030#ifndef TSS2_API_VERSION_1_2_1_108
Juergen Reppff821bd2017-12-11 15:21:42 +010031#error Version missmatch among TSS2 header files !
Tadeusz Struka3e03742018-02-26 15:27:39 -080032#endif /* TSS2_API_VERSION_1_2_1_108 */
Juergen Reppff821bd2017-12-11 15:21:42 +010033#include "esys_types.h"
Philip Tricca8ffd3c42018-03-09 16:27:24 -080034#include "tss2_esys.h"
Juergen Reppff821bd2017-12-11 15:21:42 +010035#include "esys_iutil.h"
36#include "esys_mu.h"
Philip Tricca8ffd3c42018-03-09 16:27:24 -080037#include "tss2_sys.h"
Juergen Reppff821bd2017-12-11 15:21:42 +010038#define LOGMODULE esys
Philip Triccaa7c51ce2018-03-10 18:28:25 -080039#include "util/log.h"
Juergen Reppff821bd2017-12-11 15:21:42 +010040
41/** Store command parameters inside the ESYS_CONTEXT for use during _finish */
42static void store_input_parameters (
43 ESYS_CONTEXT *esysContext,
44 ESYS_TR policySession)
45{
46 esysContext->in.PolicyAuthValue.policySession = policySession;
47}
48
49/** One-Call function for TPM2_PolicyAuthValue
50 *
51 * This function invokes the TPM2_PolicyAuthValue command in a one-call
52 * variant. This means the function will block until the TPM response is
53 * available. All input parameters are const. The memory for non-simple output
54 * parameters is allocated by the function implementation.
55 *
56 * @param[in,out] esysContext The ESYS_CONTEXT.
57 * @param[in] policySession Input handle of type ESYS_TR for
58 * object with handle type TPMI_SH_POLICY.
59 * @param[in] shandle1 First session handle.
60 * @param[in] shandle2 Second session handle.
61 * @param[in] shandle3 Third session handle.
62 * @retval TSS2_RC_SUCCESS on success
63 * @retval TSS2_RC_BAD_SEQUENCE if context is not ready for this function
64 * \todo add further error RCs to documentation
65 */
66TSS2_RC
67Esys_PolicyAuthValue(
68 ESYS_CONTEXT *esysContext,
69 ESYS_TR policySession,
70 ESYS_TR shandle1,
71 ESYS_TR shandle2,
72 ESYS_TR shandle3)
73{
74 TSS2_RC r = TSS2_RC_SUCCESS;
75
76 r = Esys_PolicyAuthValue_async(esysContext,
77 policySession,
78 shandle1,
79 shandle2,
80 shandle3);
81 return_if_error(r, "Error in async function");
82
83 /* Set the timeout to indefinite for now, since we want _finish to block */
84 int32_t timeouttmp = esysContext->timeout;
85 esysContext->timeout = -1;
86 /*
87 * Now we call the finish function, until return code is not equal to
88 * from TSS2_BASE_RC_TRY_AGAIN.
89 * Note that the finish function may return TSS2_RC_TRY_AGAIN, even if we
90 * have set the timeout to -1. This occurs for example if the TPM requests
91 * a retransmission of the command via TPM2_RC_YIELDED.
92 */
93 do {
94 r = Esys_PolicyAuthValue_finish(esysContext);
95 /* This is just debug information about the reattempt to finish the
96 command */
97 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
98 LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32
99 " => resubmitting command", r);
100 } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
101
102 /* Restore the timeout value to the original value */
103 esysContext->timeout = timeouttmp;
104 return_if_error(r, "Esys Finish");
105
106 return TSS2_RC_SUCCESS;
107}
108
109/** Asynchronous function for TPM2_PolicyAuthValue
110 *
111 * This function invokes the TPM2_PolicyAuthValue command in a asynchronous
112 * variant. This means the function will return as soon as the command has been
113 * sent downwards the stack to the TPM. All input parameters are const.
114 * In order to retrieve the TPM's response call Esys_PolicyAuthValue_finish.
115 *
116 * @param[in,out] esysContext The ESYS_CONTEXT.
117 * @param[in] policySession Input handle of type ESYS_TR for
118 * object with handle type TPMI_SH_POLICY.
119 * @param[in] shandle1 First session handle.
120 * @param[in] shandle2 Second session handle.
121 * @param[in] shandle3 Third session handle.
122 * @retval TSS2_RC_SUCCESS on success
123 * @retval TSS2_RC_BAD_SEQUENCE if context is not ready for this function
124 * \todo add further error RCs to documentation
125 */
126TSS2_RC
127Esys_PolicyAuthValue_async(
128 ESYS_CONTEXT *esysContext,
129 ESYS_TR policySession,
130 ESYS_TR shandle1,
131 ESYS_TR shandle2,
132 ESYS_TR shandle3)
133{
134 TSS2_RC r = TSS2_RC_SUCCESS;
135 TSS2L_SYS_AUTH_COMMAND auths = { 0 };
136 RSRC_NODE_T *policySessionNode;
137
138 if (esysContext == NULL) {
139 LOG_ERROR("esyscontext is NULL.");
140 return TSS2_ESYS_RC_BAD_REFERENCE;
141 }
142 r = iesys_check_sequence_async(esysContext);
143 if (r != TSS2_RC_SUCCESS)
144 return r;
145 r = check_session_feasability(shandle1, shandle2, shandle3, 0);
146 return_if_error(r, "Check session usage");
147
148 store_input_parameters(esysContext, policySession);
149 r = esys_GetResourceObject(esysContext, policySession, &policySessionNode);
150 if (r != TPM2_RC_SUCCESS)
151 return r;
152 r = Tss2_Sys_PolicyAuthValue_Prepare(esysContext->sys,
153 (policySessionNode == NULL) ? TPM2_RH_NULL : policySessionNode->rsrc.handle);
154 if (r != TSS2_RC_SUCCESS) {
155 LOG_ERROR("Error async PolicyAuthValue");
156 return r;
157 }
158 r = init_session_tab(esysContext, shandle1, shandle2, shandle3);
159 return_if_error(r, "Initialize session resources");
160
161 iesys_compute_session_value(esysContext->session_tab[0], NULL, NULL);
162 r = iesys_gen_auths(esysContext, policySessionNode, NULL, NULL, &auths);
163 return_if_error(r, "Error in computation of auth values");
164
165 esysContext->authsCount = auths.count;
166 r = Tss2_Sys_SetCmdAuths(esysContext->sys, &auths);
167 if (r != TSS2_RC_SUCCESS) {
168 return r;
169 }
170
171 r = Tss2_Sys_ExecuteAsync(esysContext->sys);
172 return_if_error(r, "Finish (Execute Async)");
173
174 esysContext->state = _ESYS_STATE_SENT;
175
176 return r;
177}
178
179/** Asynchronous finish function for TPM2_PolicyAuthValue
180 *
181 * This function returns the results of a TPM2_PolicyAuthValue command
182 * invoked via Esys_PolicyAuthValue_finish. All non-simple output parameters
183 * are allocated by the function's implementation. NULL can be passed for every
184 * output parameter if the value is not required.
185 *
186 * @param[in,out] esysContext The ESYS_CONTEXT.
187 * @retval TSS2_RC_SUCCESS on success
188 * @retval TSS2_RC_BAD_SEQUENCE if context is not ready for this function.
189 * \todo add further error RCs to documentation
190 */
191TSS2_RC
192Esys_PolicyAuthValue_finish(
193 ESYS_CONTEXT *esysContext)
194{
195 LOG_TRACE("complete");
196 if (esysContext == NULL) {
197 LOG_ERROR("esyscontext is NULL.");
198 return TSS2_ESYS_RC_BAD_REFERENCE;
199 }
200 if (esysContext->state != _ESYS_STATE_SENT) {
201 LOG_ERROR("Esys called in bad sequence.");
202 return TSS2_ESYS_RC_BAD_SEQUENCE;
203 }
204 TSS2_RC r = TSS2_RC_SUCCESS;
Juergen Reppff821bd2017-12-11 15:21:42 +0100205 r = Tss2_Sys_ExecuteFinish(esysContext->sys, esysContext->timeout);
206 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) {
207 LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32, r);
208 return r;
209 }
210 if (r == TPM2_RC_RETRY || r == TPM2_RC_TESTING || r == TPM2_RC_YIELDED) {
211 LOG_DEBUG("TPM returned RETRY, TESTING or YIELDED, which triggers a "
212 "resubmission: %" PRIx32, r);
213 if (esysContext->submissionCount > _ESYS_MAX_SUMBISSIONS) {
214 LOG_WARNING("Maximum number of resubmissions has been reached.");
215 esysContext->state = _ESYS_STATE_ERRORRESPONSE;
216 return r;
217 }
218 esysContext->state = _ESYS_STATE_RESUBMISSION;
219 r = Esys_PolicyAuthValue_async(esysContext,
220 esysContext->in.PolicyAuthValue.policySession,
221 esysContext->session_type[0],
222 esysContext->session_type[1],
223 esysContext->session_type[2]);
224 if (r != TSS2_RC_SUCCESS) {
225 LOG_ERROR("Error attempting to resubmit");
226 return r;
227 }
228 r = TSS2_ESYS_RC_TRY_AGAIN;
229 return r;
230 }
231 if (r != TSS2_RC_SUCCESS) {
232 LOG_ERROR("Error finish (ExecuteFinish) PolicyAuthValue");
233 return r;
234 }
235 /*
236 * Now the verification of the response (hmac check) and if necessary the
237 * parameter decryption have to be done
238 */
Juergen Repp109de7d2018-02-23 13:42:08 +0100239 r = iesys_check_response(esysContext);
240 return_if_error(r, "Error: check response");
Juergen Reppff821bd2017-12-11 15:21:42 +0100241 /*
242 * After the verification of the response we call the complete function
243 * to deliver the result.
244 */
245 r = Tss2_Sys_PolicyAuthValue_Complete(esysContext->sys);
246 if (r != TSS2_RC_SUCCESS) {
247 LOG_ERROR("Error finish (ExecuteFinish) PolicyAuthValue: %" PRIx32, r);
248 esysContext->state = _ESYS_STATE_ERRORRESPONSE;
249 return r;;
250 }
251 ESYS_TR policySession = esysContext->in.PolicyAuthValue.policySession;
252 RSRC_NODE_T *policySessionNode;
253 r = esys_GetResourceObject(esysContext, policySession, &policySessionNode);
254 return_if_error(r, "get resource");
255
256 if (policySessionNode != NULL)
257 policySessionNode->rsrc.misc.rsrc_session.type_policy_session = POLICY_AUTH;
258 esysContext->state = _ESYS_STATE_FINISHED;
259
260 return r;
Philip Tricca910f17c2018-03-15 12:38:37 -0700261}