blob: ddbfd1414ce5f580f1e4455df1f98bf9077da773 [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 Repp35c121f2018-10-15 17:02:25 +020016#include "util/aux_util.h"
Juergen Reppff821bd2017-12-11 15:21:42 +010017
Juergen Reppadd438d2018-04-09 10:00:19 +020018/** Store command parameters inside the ESYS_CONTEXT for use during _Finish */
Juergen Reppff821bd2017-12-11 15:21:42 +010019static void store_input_parameters (
20 ESYS_CONTEXT *esysContext,
21 const TPMS_CONTEXT *context)
22{
23 if (context == NULL) {
24 esysContext->in.ContextLoad.context = NULL;
25 } else {
26 esysContext->in.ContextLoad.contextData = *context;
27 esysContext->in.ContextLoad.context =
28 &esysContext->in.ContextLoad.contextData;
29 }
30}
31
32/** One-Call function for TPM2_ContextLoad
33 *
34 * This function invokes the TPM2_ContextLoad command in a one-call
35 * variant. This means the function will block until the TPM response is
36 * available. All input parameters are const. The memory for non-simple output
37 * parameters is allocated by the function implementation.
38 *
39 * @param[in,out] esysContext The ESYS_CONTEXT.
Juergen Reppf7e5bd32018-04-26 11:11:32 +020040 * @param[in] context The context blob.
Juergen Reppff821bd2017-12-11 15:21:42 +010041 * @param[out] loadedHandle ESYS_TR handle of ESYS resource for TPMI_DH_CONTEXT.
Juergen Reppc3cf4b62018-08-22 15:27:59 +020042 * @retval TSS2_RC_SUCCESS if the function call was a success.
Juergen Reppf7e5bd32018-04-26 11:11:32 +020043 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input
44 * pointers or required output handle references are NULL.
45 * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected.
46 * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for
47 * internal operations or return parameters.
48 * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous
49 * operation already pending.
50 * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not
51 * at least contain the tag, response length, and response code.
52 * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted.
Juergen Reppc3cf4b62018-08-22 15:27:59 +020053 * @retval TSS2_ESYS_RC_RSP_AUTH_FAILED: if the response HMAC from the TPM
54 did not verify.
Juergen Reppf7e5bd32018-04-26 11:11:32 +020055 * @retval TSS2_RCs produced by lower layers of the software stack may be
56 * returned to the caller unaltered unless handled internally.
Juergen Reppff821bd2017-12-11 15:21:42 +010057 */
58TSS2_RC
59Esys_ContextLoad(
60 ESYS_CONTEXT *esysContext,
Juergen Repp66989272018-09-04 11:13:06 +020061 const TPMS_CONTEXT *context, ESYS_TR *loadedHandle)
Juergen Reppff821bd2017-12-11 15:21:42 +010062{
Juergen Repp3b7b41b2018-03-19 15:58:04 +010063 TSS2_RC r;
Juergen Reppff821bd2017-12-11 15:21:42 +010064
Juergen Repp66989272018-09-04 11:13:06 +020065 r = Esys_ContextLoad_Async(esysContext, context);
Juergen Reppff821bd2017-12-11 15:21:42 +010066 return_if_error(r, "Error in async function");
67
Juergen Reppadd438d2018-04-09 10:00:19 +020068 /* Set the timeout to indefinite for now, since we want _Finish to block */
Juergen Reppff821bd2017-12-11 15:21:42 +010069 int32_t timeouttmp = esysContext->timeout;
70 esysContext->timeout = -1;
71 /*
72 * Now we call the finish function, until return code is not equal to
73 * from TSS2_BASE_RC_TRY_AGAIN.
74 * Note that the finish function may return TSS2_RC_TRY_AGAIN, even if we
75 * have set the timeout to -1. This occurs for example if the TPM requests
76 * a retransmission of the command via TPM2_RC_YIELDED.
77 */
78 do {
Juergen Repp66989272018-09-04 11:13:06 +020079 r = Esys_ContextLoad_Finish(esysContext, loadedHandle);
Juergen Reppff821bd2017-12-11 15:21:42 +010080 /* This is just debug information about the reattempt to finish the
81 command */
82 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
83 LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32
84 " => resubmitting command", r);
85 } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
86
87 /* Restore the timeout value to the original value */
88 esysContext->timeout = timeouttmp;
89 return_if_error(r, "Esys Finish");
90
91 return TSS2_RC_SUCCESS;
92}
93
94/** Asynchronous function for TPM2_ContextLoad
95 *
96 * This function invokes the TPM2_ContextLoad command in a asynchronous
97 * variant. This means the function will return as soon as the command has been
98 * sent downwards the stack to the TPM. All input parameters are const.
Juergen Reppadd438d2018-04-09 10:00:19 +020099 * In order to retrieve the TPM's response call Esys_ContextLoad_Finish.
Juergen Reppff821bd2017-12-11 15:21:42 +0100100 *
101 * @param[in,out] esysContext The ESYS_CONTEXT.
Juergen Reppf7e5bd32018-04-26 11:11:32 +0200102 * @param[in] context The context blob.
103 * @retval ESYS_RC_SUCCESS if the function call was a success.
104 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input
105 * pointers or required output handle references are NULL.
106 * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected.
107 * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for
108 * internal operations or return parameters.
109 * @retval TSS2_RCs produced by lower layers of the software stack may be
110 returned to the caller unaltered unless handled internally.
Juergen Reppff821bd2017-12-11 15:21:42 +0100111 */
112TSS2_RC
Juergen Reppadd438d2018-04-09 10:00:19 +0200113Esys_ContextLoad_Async(
Juergen Reppff821bd2017-12-11 15:21:42 +0100114 ESYS_CONTEXT *esysContext,
115 const TPMS_CONTEXT *context)
116{
Juergen Repp3b7b41b2018-03-19 15:58:04 +0100117 TSS2_RC r;
Andreas Fuchs15bbb672018-03-27 13:21:13 +0200118 LOG_TRACE("context=%p, context=%p",
119 esysContext, context);
Andreas Fuchs1c4a8112018-03-29 16:58:07 +0200120 IESYS_CONTEXT_DATA esyscontextData;
Juergen Reppff821bd2017-12-11 15:21:42 +0100121 TPMS_CONTEXT tpmContext;
122
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100123 /* Check context, sequence correctness and set state to error for now */
Juergen Reppff821bd2017-12-11 15:21:42 +0100124 if (esysContext == NULL) {
125 LOG_ERROR("esyscontext is NULL.");
126 return TSS2_ESYS_RC_BAD_REFERENCE;
127 }
128 r = iesys_check_sequence_async(esysContext);
129 if (r != TSS2_RC_SUCCESS)
130 return r;
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100131 esysContext->state = _ESYS_STATE_INTERNALERROR;
Juergen Repp66989272018-09-04 11:13:06 +0200132 store_input_parameters(esysContext, context);
Juergen Reppff821bd2017-12-11 15:21:42 +0100133 size_t offset = 0;
134
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100135 /*
136 * ESYS Special Handling Code: The context was extended with metadata during
137 * Esys_ContextSave. Here we extract the TPM-parts to pass then to the TPM.
138 */
139 if (context == NULL) {
140 LOG_ERROR("context is NULL.");
141 return TSS2_ESYS_RC_BAD_REFERENCE;
142 }
Juergen Repp47120322018-05-03 12:21:30 +0200143 r = iesys_MU_IESYS_CONTEXT_DATA_Unmarshal (&context->contextBlob.buffer[0],
144 context->contextBlob.size,
145 &offset, &esyscontextData);
Juergen Reppff821bd2017-12-11 15:21:42 +0100146 return_if_error(r, "while unmarshaling context ");
147
148 /* The actual contextBlob for the TPM is embedded inside the
149 ESYS_CONTEXT_DATA. Some of the values at the start of TPMS_CONTEXT
150 need to be kept though. */
151
152 tpmContext.sequence = context->sequence;
153 tpmContext.savedHandle = context->savedHandle;
154 tpmContext.hierarchy = context->hierarchy;
155 tpmContext.contextBlob = esyscontextData.tpmContext;
156
157 /* Now we override the context parameter with the corrected version, since
158 it is nowhere used beyond this point. */
159 context = &tpmContext;
160
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100161
162 /* Initial invocation of SAPI to prepare the command buffer with parameters */
Juergen Repp66989272018-09-04 11:13:06 +0200163 r = Tss2_Sys_ContextLoad_Prepare(esysContext->sys, context);
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100164 return_state_if_error(r, _ESYS_STATE_INIT, "SAPI Prepare returned error.");
165 /* Trigger execution and finish the async invocation */
Juergen Reppff821bd2017-12-11 15:21:42 +0100166 r = Tss2_Sys_ExecuteAsync(esysContext->sys);
Juergen Repp66989272018-09-04 11:13:06 +0200167 return_state_if_error(r, _ESYS_STATE_INTERNALERROR,
168 "Finish (Execute Async)");
Juergen Reppff821bd2017-12-11 15:21:42 +0100169
170 esysContext->state = _ESYS_STATE_SENT;
171
172 return r;
173}
174
175/** Asynchronous finish function for TPM2_ContextLoad
176 *
177 * This function returns the results of a TPM2_ContextLoad command
Juergen Reppadd438d2018-04-09 10:00:19 +0200178 * invoked via Esys_ContextLoad_Finish. All non-simple output parameters
Juergen Reppff821bd2017-12-11 15:21:42 +0100179 * are allocated by the function's implementation. NULL can be passed for every
180 * output parameter if the value is not required.
181 *
182 * @param[in,out] esysContext The ESYS_CONTEXT.
183 * @param[out] loadedHandle ESYS_TR handle of ESYS resource for TPMI_DH_CONTEXT.
184 * @retval TSS2_RC_SUCCESS on success
Juergen Reppf7e5bd32018-04-26 11:11:32 +0200185 * @retval ESYS_RC_SUCCESS if the function call was a success.
186 * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input
187 * pointers or required output handle references are NULL.
188 * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected.
189 * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for
190 * internal operations or return parameters.
191 * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous
192 * operation already pending.
193 * @retval TSS2_ESYS_RC_TRY_AGAIN: if the timeout counter expires before the
194 * TPM response is received.
195 * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not
Juergen Reppc3cf4b62018-08-22 15:27:59 +0200196 * at least contain the tag, response length, and response code.
197 * @retval TSS2_ESYS_RC_RSP_AUTH_FAILED: if the response HMAC from the TPM did
198 * not verify.
Juergen Reppf7e5bd32018-04-26 11:11:32 +0200199 * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted.
200 * @retval TSS2_RCs produced by lower layers of the software stack may be
201 * returned to the caller unaltered unless handled internally.
Juergen Reppff821bd2017-12-11 15:21:42 +0100202 */
203TSS2_RC
Juergen Reppadd438d2018-04-09 10:00:19 +0200204Esys_ContextLoad_Finish(
Juergen Repp66989272018-09-04 11:13:06 +0200205 ESYS_CONTEXT *esysContext, ESYS_TR *loadedHandle)
Juergen Reppff821bd2017-12-11 15:21:42 +0100206{
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100207 TSS2_RC r;
Andreas Fuchs15bbb672018-03-27 13:21:13 +0200208 LOG_TRACE("context=%p, loadedHandle=%p",
209 esysContext, loadedHandle);
210
Juergen Reppff821bd2017-12-11 15:21:42 +0100211 if (esysContext == NULL) {
212 LOG_ERROR("esyscontext is NULL.");
213 return TSS2_ESYS_RC_BAD_REFERENCE;
214 }
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100215
216 /* Check for correct sequence and set sequence to irregular for now */
Juergen Reppff821bd2017-12-11 15:21:42 +0100217 if (esysContext->state != _ESYS_STATE_SENT) {
218 LOG_ERROR("Esys called in bad sequence.");
219 return TSS2_ESYS_RC_BAD_SEQUENCE;
220 }
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100221 esysContext->state = _ESYS_STATE_INTERNALERROR;
Juergen Reppff821bd2017-12-11 15:21:42 +0100222 RSRC_NODE_T *loadedHandleNode = NULL;
223
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100224 /* Allocate memory for response parameters */
Juergen Reppff821bd2017-12-11 15:21:42 +0100225 if (loadedHandle == NULL) {
226 LOG_ERROR("Handle loadedHandle may not be NULL");
227 return TSS2_ESYS_RC_BAD_REFERENCE;
228 }
229 *loadedHandle = esysContext->esys_handle_cnt++;
230 r = esys_CreateResourceObject(esysContext, *loadedHandle, &loadedHandleNode);
231 if (r != TSS2_RC_SUCCESS)
232 return r;
233
Andreas Fuchs1c4a8112018-03-29 16:58:07 +0200234 IESYS_CONTEXT_DATA esyscontextData;
Juergen Reppff821bd2017-12-11 15:21:42 +0100235 size_t offset = 0;
Juergen Repp47120322018-05-03 12:21:30 +0200236 r = iesys_MU_IESYS_CONTEXT_DATA_Unmarshal(&esysContext->in.ContextLoad.context->contextBlob.buffer[0],
237 sizeof(IESYS_CONTEXT_DATA),
238 &offset, &esyscontextData);
Juergen Reppff821bd2017-12-11 15:21:42 +0100239 goto_if_error(r, "while unmarshaling context ", error_cleanup);
240
241 loadedHandleNode->rsrc = esyscontextData.esysMetadata.data;
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100242
243 /*Receive the TPM response and handle resubmissions if necessary. */
Juergen Reppff821bd2017-12-11 15:21:42 +0100244 r = Tss2_Sys_ExecuteFinish(esysContext->sys, esysContext->timeout);
245 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) {
246 LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32, r);
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100247 esysContext->state = _ESYS_STATE_SENT;
Juergen Reppff821bd2017-12-11 15:21:42 +0100248 goto error_cleanup;
249 }
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100250 /* This block handle the resubmission of TPM commands given a certain set of
251 * TPM response codes. */
Juergen Reppff821bd2017-12-11 15:21:42 +0100252 if (r == TPM2_RC_RETRY || r == TPM2_RC_TESTING || r == TPM2_RC_YIELDED) {
253 LOG_DEBUG("TPM returned RETRY, TESTING or YIELDED, which triggers a "
254 "resubmission: %" PRIx32, r);
Andreas Fuchs631d7e62018-03-19 10:54:56 +0100255 if (esysContext->submissionCount >= _ESYS_MAX_SUBMISSIONS) {
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100256 LOG_WARNING("Maximum number of (re)submissions has been reached.");
257 esysContext->state = _ESYS_STATE_INIT;
Juergen Reppff821bd2017-12-11 15:21:42 +0100258 goto error_cleanup;
259 }
260 esysContext->state = _ESYS_STATE_RESUBMISSION;
Juergen Reppadd438d2018-04-09 10:00:19 +0200261 r = Esys_ContextLoad_Async(esysContext,
Juergen Repp66989272018-09-04 11:13:06 +0200262 esysContext->in.ContextLoad.context);
Juergen Reppff821bd2017-12-11 15:21:42 +0100263 if (r != TSS2_RC_SUCCESS) {
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100264 LOG_WARNING("Error attempting to resubmit");
265 /* We do not set esysContext->state here but inherit the most recent
266 * state of the _async function. */
Juergen Reppff821bd2017-12-11 15:21:42 +0100267 goto error_cleanup;
268 }
269 r = TSS2_ESYS_RC_TRY_AGAIN;
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100270 LOG_DEBUG("Resubmission initiated and returning RC_TRY_AGAIN.");
Juergen Reppff821bd2017-12-11 15:21:42 +0100271 goto error_cleanup;
272 }
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100273 /* The following is the "regular error" handling. */
Juergen Repp033da112018-07-10 13:06:18 +0200274 if (iesys_tpm_error(r)) {
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100275 LOG_WARNING("Received TPM Error");
276 esysContext->state = _ESYS_STATE_INIT;
277 goto error_cleanup;
278 } else if (r != TSS2_RC_SUCCESS) {
279 LOG_ERROR("Received a non-TPM Error");
280 esysContext->state = _ESYS_STATE_INTERNALERROR;
Juergen Reppff821bd2017-12-11 15:21:42 +0100281 goto error_cleanup;
282 }
283 r = Tss2_Sys_ContextLoad_Complete(esysContext->sys,
Juergen Repp66989272018-09-04 11:13:06 +0200284 &loadedHandleNode->rsrc.handle);
285 goto_state_if_error(r, _ESYS_STATE_INTERNALERROR,
286 "Received error from SAPI unmarshaling" ,
287 error_cleanup);
288
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100289 esysContext->state = _ESYS_STATE_INIT;
Juergen Reppff821bd2017-12-11 15:21:42 +0100290
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100291 return TSS2_RC_SUCCESS;
Juergen Reppff821bd2017-12-11 15:21:42 +0100292
293error_cleanup:
294 Esys_TR_Close(esysContext, loadedHandle);
Andreas Fuchs4d9961e2018-03-20 15:51:48 +0100295
Juergen Reppff821bd2017-12-11 15:21:42 +0100296 return r;
Philip Tricca910f17c2018-03-15 12:38:37 -0700297}