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 <stdio.h>
12 #include <string.h>
13
14 #include "tss2_fapi.h"
15 #include "fapi_int.h"
16 #include "fapi_util.h"
17 #include "tss2_esys.h"
18 #define LOGMODULE fapi
19 #include "util/log.h"
20 #include "util/aux_util.h"
21
22 /** One-Call function for Fapi_PcrRead
23 *
24 * Reads from a given PCR and returns the value and the event log.
25 *
26 * @param[in,out] context The FAPI_CONTEXT
27 * @param[in] pcrIndex The index of the PCR to read
28 * @param[out] pcrValue The value of the PCR. May be NULL
29 * @param[out] pcrValueSize The size of value in bytes. May be NULL
30 * @param[out] pcrLog The PCR log. May be NULL
31 *
32 * @retval TSS2_RC_SUCCESS: if the function call was a success.
33 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, pcrValue or pcrValueSize
34 * is NULL.
35 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
36 * @retval TSS2_FAPI_RC_BAD_VALUE: if pcrIndex is invalid.
37 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
38 * operation already pending.
39 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
40 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
41 * internal operations or return parameters.
42 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
43 * config file.
44 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
45 * this function needs to be called again.
46 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
47 * is not set.
48 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
49 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
50 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
51 * was not successful.
52 * @retval TSS2_FAPI_RC_NO_CERT if an error did occur during certificate downloading.
53 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
54 * during authorization.
55 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
56 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
57 */
58 TSS2_RC
Fapi_PcrRead(FAPI_CONTEXT * context,uint32_t pcrIndex,uint8_t ** pcrValue,size_t * pcrValueSize,char ** pcrLog)59 Fapi_PcrRead(
60 FAPI_CONTEXT *context,
61 uint32_t pcrIndex,
62 uint8_t **pcrValue,
63 size_t *pcrValueSize,
64 char **pcrLog)
65 {
66 LOG_TRACE("called for context:%p", context);
67
68 TSS2_RC r, r2;
69
70 /* Check for NULL parameters */
71 check_not_null(context);
72
73 /* Check whether TCTI and ESYS are initialized */
74 return_if_null(context->esys, "Command can't be executed in none TPM mode.",
75 TSS2_FAPI_RC_NO_TPM);
76
77 /* If the async state automata of FAPI shall be tested, then we must not set
78 the timeouts of ESYS to blocking mode.
79 During testing, the mssim tcti will ensure multiple re-invocations.
80 Usually however the synchronous invocations of FAPI shall instruct ESYS
81 to block until a result is available. */
82 #ifndef TEST_FAPI_ASYNC
83 r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
84 return_if_error_reset_state(r, "Set Timeout to blocking");
85 #endif /* TEST_FAPI_ASYNC */
86
87 r = Fapi_PcrRead_Async(context, pcrIndex);
88 return_if_error_reset_state(r, "PCR_ReadWithLog");
89
90 do {
91 /* We wait for file I/O to be ready if the FAPI state automata
92 are in a file I/O state. */
93 r = ifapi_io_poll(&context->io);
94 return_if_error(r, "Something went wrong with IO polling");
95
96 /* Repeatedly call the finish function, until FAPI has transitioned
97 through all execution stages / states of this invocation. */
98 r = Fapi_PcrRead_Finish(context, pcrValue, pcrValueSize, pcrLog);
99 } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
100
101 /* Reset the ESYS timeout to non-blocking, immediate response. */
102 r2 = Esys_SetTimeout(context->esys, 0);
103 return_if_error(r2, "Set Timeout to non-blocking");
104
105 return_if_error_reset_state(r, "NV_ReadWithLog");
106
107 LOG_TRACE("finished");
108 return TSS2_RC_SUCCESS;
109 }
110
111 /** Asynchronous function for Fapi_PcrRead
112 *
113 * Reads from a given PCR and returns the value and the event log.
114 *
115 * Call Fapi_PcrRead_Finish to finish the execution of this command.
116 *
117 * @param[in,out] context The FAPI_CONTEXT
118 * @param[in] pcrIndex The index of the PCR to read
119 *
120 * @retval TSS2_RC_SUCCESS: if the function call was a success.
121 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
122 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
123 * @retval TSS2_FAPI_RC_BAD_VALUE: if pcrIndex is invalid.
124 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
125 * operation already pending.
126 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
127 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
128 * internal operations or return parameters.
129 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
130 * config file.
131 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
132 */
133 TSS2_RC
Fapi_PcrRead_Async(FAPI_CONTEXT * context,uint32_t pcrIndex)134 Fapi_PcrRead_Async(
135 FAPI_CONTEXT *context,
136 uint32_t pcrIndex)
137 {
138 LOG_TRACE("called for context:%p", context);
139 LOG_TRACE("pcrIndex: %" PRIu32, pcrIndex);
140
141 TSS2_RC r;
142 TPML_PCR_SELECTION pcr_selection;
143
144 /* Check for NULL parameters */
145 check_not_null(context);
146
147 /* Helpful alias pointers */
148 IFAPI_PCR * command = &context->cmd.pcr;
149
150 /* Reset all context-internal session state information. */
151 r = ifapi_session_init(context);
152 return_if_error(r, "Initialize PcrRead");
153
154 /* Determine the banks to be used for the requested PCR based on
155 the default cryptographic profile. */
156 pcr_selection = context->profiles.default_profile.pcr_selection;
157
158 r = ifapi_filter_pcr_selection_by_index(&pcr_selection, &pcrIndex, 1);
159 return_if_error(r, "PCR selection");
160
161 /* Perform the PCR read operation. */
162 r = Esys_PCR_Read_Async(context->esys,
163 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
164 &pcr_selection);
165 return_if_error(r, "PCR Read");
166
167 /* Used for retrieving the eventlog during finish*/
168 command->pcrIndex = pcrIndex;
169
170 /* Initialize the context state for this operation. */
171 context->state = PCR_READ_READ_PCR;
172
173 LOG_TRACE("finished");
174 return TSS2_RC_SUCCESS;
175 }
176
177 /** Asynchronous finish function for Fapi_PcrRead
178 *
179 * This function should be called after a previous Fapi_PcrRead_Async.
180 *
181 * @param[in,out] context The FAPI_CONTEXT
182 * @param[out] pcrValue The value of the PCR. May be NULL
183 * @param[out] pcrValueSize The size of value in bytes. May be NULL
184 * @param[out] pcrLog The PCR log. May be NULL
185 *
186 * @retval TSS2_RC_SUCCESS: if the function call was a success.
187 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, pcrValue or pcrValueSize
188 * is NULL.
189 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
190 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
191 * operation already pending.
192 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
193 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
194 * internal operations or return parameters.
195 * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
196 * complete. Call this function again later.
197 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
198 * the function.
199 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
200 */
201 TSS2_RC
Fapi_PcrRead_Finish(FAPI_CONTEXT * context,uint8_t ** pcrValue,size_t * pcrValueSize,char ** pcrLog)202 Fapi_PcrRead_Finish(
203 FAPI_CONTEXT *context,
204 uint8_t **pcrValue,
205 size_t *pcrValueSize,
206 char **pcrLog)
207 {
208 LOG_TRACE("called for context:%p", context);
209
210 TSS2_RC r;
211
212 /* Check for NULL parameters */
213 check_not_null(context);
214
215 /* Helpful alias pointers */
216 IFAPI_PCR * command = &context->cmd.pcr;
217
218 command->pcrValues = NULL;
219
220 switch (context->state) {
221 statecase(context->state, PCR_READ_READ_PCR);
222 SAFE_FREE(command->pcrValues);
223 r = Esys_PCR_Read_Finish(context->esys,
224 &command->update_count,
225 NULL,
226 &command->pcrValues);
227 return_try_again(r);
228 goto_if_error_reset_state(r, "PCR_ReadWithLog_Finish", cleanup);
229
230 /* Copy the return values to the output parameters. */
231 if (pcrValueSize)
232 *pcrValueSize = command->pcrValues->digests[0].size;
233 if (pcrValue) {
234 *pcrValue = malloc(command->pcrValues->digests[0].size);
235 goto_if_null2(*pcrValue, "Out of memory.",
236 r, TSS2_FAPI_RC_MEMORY, cleanup);
237
238 memcpy(*pcrValue, &command->pcrValues->digests[0].buffer[0],
239 command->pcrValues->digests[0].size);
240 }
241 SAFE_FREE(command->pcrValues);
242
243 /* If no event log was requested the operation is now complete. */
244 if (!pcrLog) {
245 context->state = _FAPI_STATE_INIT;
246 break;
247 }
248
249 /* Retrieve the eventlog for the requestion PCR. */
250 r = ifapi_eventlog_get_async(&context->eventlog, &context->io,
251 &command->pcrIndex, 1);
252 goto_if_error(r, "Error getting event log", cleanup);
253
254 fallthrough;
255
256 statecase(context->state, PCR_READ_READ_EVENT_LIST);
257 r = ifapi_eventlog_get_finish(&context->eventlog, &context->io, pcrLog);
258 return_try_again(r);
259 goto_if_error(r, "Error getting event log", cleanup);
260
261 context->state = _FAPI_STATE_INIT;
262 break;
263
264 statecasedefault(context->state);
265 }
266
267 cleanup:
268 /* Cleanup any intermediate results and state stored in the context. */
269 SAFE_FREE(command->pcrValues);
270 LOG_TRACE("finished");
271 return r;
272 }
273