• 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 <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