blob: 485192b7e8bfd8c0fa1d3a2dd2ee05507730c66d [file] [log] [blame]
Peter Huewed5a36f62018-06-12 00:59:26 +02001/* SPDX-License-Identifier: BSD-2 */
Juergen Reppff821bd2017-12-11 15:21:42 +01002/*******************************************************************************
3 * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
4 * All rights reserved.
Juergen Reppff821bd2017-12-11 15:21:42 +01005 ******************************************************************************/
6
Philip Tricca910f17c2018-03-15 12:38:37 -07007#include "tss2_mu.h"
8#include "tss2_sys.h"
Philip Tricca8ffd3c42018-03-09 16:27:24 -08009#include "tss2_esys.h"
Juergen Repped6e6e22018-03-19 17:34:32 +010010
11#include "esys_types.h"
Juergen Reppff821bd2017-12-11 15:21:42 +010012#include "esys_iutil.h"
13#include "esys_mu.h"
Juergen Reppff821bd2017-12-11 15:21:42 +010014#define LOGMODULE esys
Philip Triccaa7c51ce2018-03-10 18:28:25 -080015#include "util/log.h"
Juergen Reppff821bd2017-12-11 15:21:42 +010016
Juergen Reppadd438d2018-04-09 10:00:19 +020017/** Store command parameters inside the ESYS_CONTEXT for use during _Finish */
Juergen Reppff821bd2017-12-11 15:21:42 +010018/** One-Call function for TPM2_ReadClock
19 *
20 * This function invokes the TPM2_ReadClock command in a one-call
21 * variant. This means the function will block until the TPM response is
22 * available. All input parameters are const. The memory for non-simple output
23 * parameters is allocated by the function implementation.
24 *
25 * @param[in,out] esysContext The ESYS_CONTEXT.
Juergen Reppf7e5bd32018-04-26 11:11:32 +020026 * @param[in] shandle1 First session handle.
27 * @param[in] shandle2 Second session handle.
28 * @param[in] shandle3 Third session handle.
29 * @param[out] currentTime .
30 * (callee-allocated)
Juergen Reppc3cf4b62018-08-22 15:27:59 +020031 * @retval TSS2_RC_SUCCESS if the function call was a success.
Juergen Reppf7e5bd32018-04-26 11:11:32 +020032 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input
33 * pointers or required output handle references are NULL.
34 * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected.
35 * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for
36 * internal operations or return parameters.
37 * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous
38 * operation already pending.
39 * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not
40 * at least contain the tag, response length, and response code.
41 * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted.
Juergen Reppc3cf4b62018-08-22 15:27:59 +020042 * @retval TSS2_ESYS_RC_RSP_AUTH_FAILED: if the response HMAC from the TPM
43 did not verify.
Juergen Reppf7e5bd32018-04-26 11:11:32 +020044 * @retval TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS: if more than one session has
45 * the 'decrypt' attribute bit set.
46 * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS: if more than one session has
47 * the 'encrypt' attribute bit set.
48 * @retval TSS2_ESYS_RC_NO_DECRYPT_PARAM: if one of the sessions has the
49 * 'decrypt' attribute set and the command does not support encryption
50 * of the first command parameter.
51 * @retval TSS2_ESYS_RC_NO_ENCRYPT_PARAM: if one of the sessions has the
52 * 'encrypt' attribute set and the command does not support encryption
53 * of the first response parameter.
54 * @retval TSS2_RCs produced by lower layers of the software stack may be
55 * returned to the caller unaltered unless handled internally.
Juergen Reppff821bd2017-12-11 15:21:42 +010056 */
57TSS2_RC
58Esys_ReadClock(
59 ESYS_CONTEXT *esysContext,
60 ESYS_TR shandle1,
61 ESYS_TR shandle2,
62 ESYS_TR shandle3,
63 TPMS_TIME_INFO **currentTime)
64{
Juergen Repp3b7b41b2018-03-19 15:58:04 +010065 TSS2_RC r;
Juergen Reppff821bd2017-12-11 15:21:42 +010066
Juergen Repp66989272018-09-04 11:13:06 +020067 r = Esys_ReadClock_Async(esysContext, shandle1, shandle2, shandle3);
Juergen Reppff821bd2017-12-11 15:21:42 +010068 return_if_error(r, "Error in async function");
69
Juergen Reppadd438d2018-04-09 10:00:19 +020070 /* Set the timeout to indefinite for now, since we want _Finish to block */
Juergen Reppff821bd2017-12-11 15:21:42 +010071 int32_t timeouttmp = esysContext->timeout;
72 esysContext->timeout = -1;
73 /*
74 * Now we call the finish function, until return code is not equal to
75 * from TSS2_BASE_RC_TRY_AGAIN.
76 * Note that the finish function may return TSS2_RC_TRY_AGAIN, even if we
77 * have set the timeout to -1. This occurs for example if the TPM requests
78 * a retransmission of the command via TPM2_RC_YIELDED.
79 */
80 do {
Juergen Repp66989272018-09-04 11:13:06 +020081 r = Esys_ReadClock_Finish(esysContext, currentTime);
Juergen Reppff821bd2017-12-11 15:21:42 +010082 /* This is just debug information about the reattempt to finish the
83 command */
84 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
85 LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32
86 " => resubmitting command", r);
87 } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
88
89 /* Restore the timeout value to the original value */
90 esysContext->timeout = timeouttmp;
91 return_if_error(r, "Esys Finish");
92
93 return TSS2_RC_SUCCESS;
94}
95
96/** Asynchronous function for TPM2_ReadClock
97 *
98 * This function invokes the TPM2_ReadClock command in a asynchronous
99 * variant. This means the function will return as soon as the command has been
100 * sent downwards the stack to the TPM. All input parameters are const.
Juergen Reppadd438d2018-04-09 10:00:19 +0200101 * In order to retrieve the TPM's response call Esys_ReadClock_Finish.
Juergen Reppff821bd2017-12-11 15:21:42 +0100102 *
103 * @param[in,out] esysContext The ESYS_CONTEXT.
Juergen Reppf7e5bd32018-04-26 11:11:32 +0200104 * @param[in] shandle1 First session handle.
105 * @param[in] shandle2 Second session handle.
106 * @param[in] shandle3 Third session handle.
107 * @retval ESYS_RC_SUCCESS if the function call was a success.
108 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input
109 * pointers or required output handle references are NULL.
110 * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected.
111 * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for
112 * internal operations or return parameters.
113 * @retval TSS2_RCs produced by lower layers of the software stack may be
114 returned to the caller unaltered unless handled internally.
115 * @retval TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS: if more than one session has
116 * the 'decrypt' attribute bit set.
117 * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS: if more than one session has
118 * the 'encrypt' attribute bit set.
119 * @retval TSS2_ESYS_RC_NO_DECRYPT_PARAM: if one of the sessions has the
120 * 'decrypt' attribute set and the command does not support encryption
121 * of the first command parameter.
122 * @retval TSS2_ESYS_RC_NO_ENCRYPT_PARAM: if one of the sessions has the
123 * 'encrypt' attribute set and the command does not support encryption
124 * of the first response parameter.
Juergen Reppff821bd2017-12-11 15:21:42 +0100125 */
126TSS2_RC
Juergen Reppadd438d2018-04-09 10:00:19 +0200127Esys_ReadClock_Async(
Juergen Reppff821bd2017-12-11 15:21:42 +0100128 ESYS_CONTEXT *esysContext,
129 ESYS_TR shandle1,
130 ESYS_TR shandle2,
131 ESYS_TR shandle3)
132{
Juergen Repp3b7b41b2018-03-19 15:58:04 +0100133 TSS2_RC r;
Andreas Fuchs15bbb672018-03-27 13:21:13 +0200134 LOG_TRACE("context=%p",
135 esysContext);
Andreas Fuchsc5a73eb2018-03-19 16:01:00 +0100136 TSS2L_SYS_AUTH_COMMAND auths;
Juergen Reppff821bd2017-12-11 15:21:42 +0100137
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100138 /* Check context, sequence correctness and set state to error for now */
Juergen Reppff821bd2017-12-11 15:21:42 +0100139 if (esysContext == NULL) {
140 LOG_ERROR("esyscontext is NULL.");
141 return TSS2_ESYS_RC_BAD_REFERENCE;
142 }
143 r = iesys_check_sequence_async(esysContext);
144 if (r != TSS2_RC_SUCCESS)
145 return r;
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100146 esysContext->state = _ESYS_STATE_INTERNALERROR;
147
148 /* Check and store input parameters */
dantpmf6ef2472018-04-06 15:21:59 -0700149 r = check_session_feasibility(shandle1, shandle2, shandle3, 0);
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100150 return_state_if_error(r, _ESYS_STATE_INIT, "Check session usage");
151
152 /* Initial invocation of SAPI to prepare the command buffer with parameters */
Juergen Reppff821bd2017-12-11 15:21:42 +0100153 r = Tss2_Sys_ReadClock_Prepare(esysContext->sys);
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100154 return_state_if_error(r, _ESYS_STATE_INIT, "SAPI Prepare returned error.");
155
156 /* Calculate the cpHash Values */
Juergen Reppff821bd2017-12-11 15:21:42 +0100157 r = init_session_tab(esysContext, shandle1, shandle2, shandle3);
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100158 return_state_if_error(r, _ESYS_STATE_INIT, "Initialize session resources");
159 iesys_compute_session_value(esysContext->session_tab[0], NULL, NULL);
160 iesys_compute_session_value(esysContext->session_tab[1], NULL, NULL);
161 iesys_compute_session_value(esysContext->session_tab[2], NULL, NULL);
Juergen Reppff821bd2017-12-11 15:21:42 +0100162
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100163 /* Generate the auth values and set them in the SAPI command buffer */
Juergen Reppff821bd2017-12-11 15:21:42 +0100164 r = iesys_gen_auths(esysContext, NULL, NULL, NULL, &auths);
Juergen Repp66989272018-09-04 11:13:06 +0200165 return_state_if_error(r, _ESYS_STATE_INIT,
166 "Error in computation of auth values");
167
Juergen Reppff821bd2017-12-11 15:21:42 +0100168 esysContext->authsCount = auths.count;
169 r = Tss2_Sys_SetCmdAuths(esysContext->sys, &auths);
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100170 return_state_if_error(r, _ESYS_STATE_INIT, "SAPI error on SetCmdAuths");
Juergen Reppff821bd2017-12-11 15:21:42 +0100171
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100172 /* Trigger execution and finish the async invocation */
Juergen Reppff821bd2017-12-11 15:21:42 +0100173 r = Tss2_Sys_ExecuteAsync(esysContext->sys);
Juergen Repp66989272018-09-04 11:13:06 +0200174 return_state_if_error(r, _ESYS_STATE_INTERNALERROR,
175 "Finish (Execute Async)");
Juergen Reppff821bd2017-12-11 15:21:42 +0100176
177 esysContext->state = _ESYS_STATE_SENT;
178
179 return r;
180}
181
182/** Asynchronous finish function for TPM2_ReadClock
183 *
184 * This function returns the results of a TPM2_ReadClock command
Juergen Reppadd438d2018-04-09 10:00:19 +0200185 * invoked via Esys_ReadClock_Finish. All non-simple output parameters
Juergen Reppff821bd2017-12-11 15:21:42 +0100186 * are allocated by the function's implementation. NULL can be passed for every
187 * output parameter if the value is not required.
188 *
189 * @param[in,out] esysContext The ESYS_CONTEXT.
Juergen Reppf7e5bd32018-04-26 11:11:32 +0200190 * @param[out] currentTime .
191 * (callee-allocated)
Juergen Reppff821bd2017-12-11 15:21:42 +0100192 * @retval TSS2_RC_SUCCESS on success
Juergen Reppf7e5bd32018-04-26 11:11:32 +0200193 * @retval ESYS_RC_SUCCESS if the function call was a success.
194 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input
195 * pointers or required output handle references are NULL.
196 * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected.
197 * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for
198 * internal operations or return parameters.
199 * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous
200 * operation already pending.
201 * @retval TSS2_ESYS_RC_TRY_AGAIN: if the timeout counter expires before the
202 * TPM response is received.
203 * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not
Juergen Reppc3cf4b62018-08-22 15:27:59 +0200204 * at least contain the tag, response length, and response code.
205 * @retval TSS2_ESYS_RC_RSP_AUTH_FAILED: if the response HMAC from the TPM did
206 * not verify.
Juergen Reppf7e5bd32018-04-26 11:11:32 +0200207 * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted.
208 * @retval TSS2_RCs produced by lower layers of the software stack may be
209 * returned to the caller unaltered unless handled internally.
Juergen Reppff821bd2017-12-11 15:21:42 +0100210 */
211TSS2_RC
Juergen Reppadd438d2018-04-09 10:00:19 +0200212Esys_ReadClock_Finish(
Juergen Reppff821bd2017-12-11 15:21:42 +0100213 ESYS_CONTEXT *esysContext,
214 TPMS_TIME_INFO **currentTime)
215{
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100216 TSS2_RC r;
Andreas Fuchs15bbb672018-03-27 13:21:13 +0200217 LOG_TRACE("context=%p, currentTime=%p",
218 esysContext, currentTime);
219
Juergen Reppff821bd2017-12-11 15:21:42 +0100220 if (esysContext == NULL) {
221 LOG_ERROR("esyscontext is NULL.");
222 return TSS2_ESYS_RC_BAD_REFERENCE;
223 }
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100224
225 /* Check for correct sequence and set sequence to irregular for now */
Juergen Reppff821bd2017-12-11 15:21:42 +0100226 if (esysContext->state != _ESYS_STATE_SENT) {
227 LOG_ERROR("Esys called in bad sequence.");
228 return TSS2_ESYS_RC_BAD_SEQUENCE;
229 }
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100230 esysContext->state = _ESYS_STATE_INTERNALERROR;
231
232 /* Allocate memory for response parameters */
Juergen Reppff821bd2017-12-11 15:21:42 +0100233 if (currentTime != NULL) {
234 *currentTime = calloc(sizeof(TPMS_TIME_INFO), 1);
235 if (*currentTime == NULL) {
236 return_error(TSS2_ESYS_RC_MEMORY, "Out of memory");
237 }
238 }
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100239
240 /*Receive the TPM response and handle resubmissions if necessary. */
Juergen Reppff821bd2017-12-11 15:21:42 +0100241 r = Tss2_Sys_ExecuteFinish(esysContext->sys, esysContext->timeout);
242 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) {
243 LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32, r);
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100244 esysContext->state = _ESYS_STATE_SENT;
Juergen Reppff821bd2017-12-11 15:21:42 +0100245 goto error_cleanup;
246 }
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100247 /* This block handle the resubmission of TPM commands given a certain set of
248 * TPM response codes. */
Juergen Reppff821bd2017-12-11 15:21:42 +0100249 if (r == TPM2_RC_RETRY || r == TPM2_RC_TESTING || r == TPM2_RC_YIELDED) {
250 LOG_DEBUG("TPM returned RETRY, TESTING or YIELDED, which triggers a "
251 "resubmission: %" PRIx32, r);
Andreas Fuchs631d7e62018-03-19 10:54:56 +0100252 if (esysContext->submissionCount >= _ESYS_MAX_SUBMISSIONS) {
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100253 LOG_WARNING("Maximum number of (re)submissions has been reached.");
254 esysContext->state = _ESYS_STATE_INIT;
Juergen Reppff821bd2017-12-11 15:21:42 +0100255 goto error_cleanup;
256 }
257 esysContext->state = _ESYS_STATE_RESUBMISSION;
Juergen Repp66989272018-09-04 11:13:06 +0200258 r = Esys_ReadClock_Async(esysContext, esysContext->session_type[0],
259 esysContext->session_type[1],
260 esysContext->session_type[2]);
Juergen Reppff821bd2017-12-11 15:21:42 +0100261 if (r != TSS2_RC_SUCCESS) {
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100262 LOG_WARNING("Error attempting to resubmit");
263 /* We do not set esysContext->state here but inherit the most recent
264 * state of the _async function. */
Juergen Reppff821bd2017-12-11 15:21:42 +0100265 goto error_cleanup;
266 }
267 r = TSS2_ESYS_RC_TRY_AGAIN;
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100268 LOG_DEBUG("Resubmission initiated and returning RC_TRY_AGAIN.");
Juergen Reppff821bd2017-12-11 15:21:42 +0100269 goto error_cleanup;
270 }
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100271 /* The following is the "regular error" handling. */
Juergen Repp033da112018-07-10 13:06:18 +0200272 if (iesys_tpm_error(r)) {
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100273 LOG_WARNING("Received TPM Error");
274 esysContext->state = _ESYS_STATE_INIT;
275 goto error_cleanup;
276 } else if (r != TSS2_RC_SUCCESS) {
277 LOG_ERROR("Received a non-TPM Error");
278 esysContext->state = _ESYS_STATE_INTERNALERROR;
Juergen Reppff821bd2017-12-11 15:21:42 +0100279 goto error_cleanup;
280 }
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100281
Juergen Reppff821bd2017-12-11 15:21:42 +0100282 /*
283 * Now the verification of the response (hmac check) and if necessary the
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100284 * parameter decryption have to be done.
Juergen Reppff821bd2017-12-11 15:21:42 +0100285 */
Juergen Repp109de7d2018-02-23 13:42:08 +0100286 r = iesys_check_response(esysContext);
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100287 goto_state_if_error(r, _ESYS_STATE_INTERNALERROR, "Error: check response",
Juergen Repp66989272018-09-04 11:13:06 +0200288 error_cleanup);
289
Juergen Reppff821bd2017-12-11 15:21:42 +0100290 /*
291 * After the verification of the response we call the complete function
292 * to deliver the result.
293 */
294 r = Tss2_Sys_ReadClock_Complete(esysContext->sys,
Juergen Repp66989272018-09-04 11:13:06 +0200295 (currentTime != NULL) ? *currentTime
296 : NULL);
297 goto_state_if_error(r, _ESYS_STATE_INTERNALERROR,
298 "Received error from SAPI unmarshaling" ,
299 error_cleanup);
300
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100301 esysContext->state = _ESYS_STATE_INIT;
Juergen Reppff821bd2017-12-11 15:21:42 +0100302
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100303 return TSS2_RC_SUCCESS;
Juergen Reppff821bd2017-12-11 15:21:42 +0100304
305error_cleanup:
306 if (currentTime != NULL)
307 SAFE_FREE(*currentTime);
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100308
Juergen Reppff821bd2017-12-11 15:21:42 +0100309 return r;
Philip Tricca910f17c2018-03-15 12:38:37 -0700310}