xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/ifapi_eventlog.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1*758e9fbaSOystein Eftevaag /* SPDX-License-Identifier: BSD-2-Clause */
2*758e9fbaSOystein Eftevaag /*******************************************************************************
3*758e9fbaSOystein Eftevaag  * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
4*758e9fbaSOystein Eftevaag  * All rights reserved.
5*758e9fbaSOystein Eftevaag  *******************************************************************************/
6*758e9fbaSOystein Eftevaag 
7*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
8*758e9fbaSOystein Eftevaag #include <config.h>
9*758e9fbaSOystein Eftevaag #endif
10*758e9fbaSOystein Eftevaag 
11*758e9fbaSOystein Eftevaag #include <string.h>
12*758e9fbaSOystein Eftevaag 
13*758e9fbaSOystein Eftevaag #include "ifapi_helpers.h"
14*758e9fbaSOystein Eftevaag #include "ifapi_eventlog.h"
15*758e9fbaSOystein Eftevaag #include "ifapi_json_serialize.h"
16*758e9fbaSOystein Eftevaag 
17*758e9fbaSOystein Eftevaag #define LOGMODULE fapi
18*758e9fbaSOystein Eftevaag #include "util/log.h"
19*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
20*758e9fbaSOystein Eftevaag #include "ifapi_macros.h"
21*758e9fbaSOystein Eftevaag 
22*758e9fbaSOystein Eftevaag /** Initialize the eventlog module of FAPI.
23*758e9fbaSOystein Eftevaag  *
24*758e9fbaSOystein Eftevaag  * @param[in,out] eventlog The context area for the eventlog.
25*758e9fbaSOystein Eftevaag  * @param[in] log_dir The directory where to put the eventlog data.
26*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
27*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
28*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
29*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
30*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
31*758e9fbaSOystein Eftevaag  *         the function.
32*758e9fbaSOystein Eftevaag  */
33*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_eventlog_initialize(IFAPI_EVENTLOG * eventlog,const char * log_dir)34*758e9fbaSOystein Eftevaag ifapi_eventlog_initialize(
35*758e9fbaSOystein Eftevaag     IFAPI_EVENTLOG *eventlog,
36*758e9fbaSOystein Eftevaag     const char *log_dir)
37*758e9fbaSOystein Eftevaag {
38*758e9fbaSOystein Eftevaag     check_not_null(eventlog);
39*758e9fbaSOystein Eftevaag     check_not_null(log_dir);
40*758e9fbaSOystein Eftevaag 
41*758e9fbaSOystein Eftevaag     TSS2_RC r;
42*758e9fbaSOystein Eftevaag 
43*758e9fbaSOystein Eftevaag     r = ifapi_io_check_create_dir(log_dir);
44*758e9fbaSOystein Eftevaag     return_if_error2(r, "Directory check/creation failed for %s", log_dir);
45*758e9fbaSOystein Eftevaag 
46*758e9fbaSOystein Eftevaag     eventlog->log_dir = strdup(log_dir);
47*758e9fbaSOystein Eftevaag     return_if_null(eventlog->log_dir, "Out of memory.", TSS2_FAPI_RC_MEMORY);
48*758e9fbaSOystein Eftevaag 
49*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
50*758e9fbaSOystein Eftevaag }
51*758e9fbaSOystein Eftevaag 
52*758e9fbaSOystein Eftevaag /** Retrieve the eventlog for a given list of pcrs using asynchronous io.
53*758e9fbaSOystein Eftevaag  *
54*758e9fbaSOystein Eftevaag  * Call ifapi_eventlog_get_finish to retrieve the results.
55*758e9fbaSOystein Eftevaag  *
56*758e9fbaSOystein Eftevaag  * @param[in,out] eventlog The context area for the eventlog.
57*758e9fbaSOystein Eftevaag  * @param[in,out] io The context area for the asynchronous io module.
58*758e9fbaSOystein Eftevaag  * @param[in] pcrList The list of PCR indices to retrieve the log for.
59*758e9fbaSOystein Eftevaag  * @param[in] pcrListSize The size of pcrList.
60*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
61*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
62*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
63*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
64*758e9fbaSOystein Eftevaag  *         the function.
65*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
66*758e9fbaSOystein Eftevaag  */
67*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_eventlog_get_async(IFAPI_EVENTLOG * eventlog,IFAPI_IO * io,const TPM2_HANDLE * pcrList,size_t pcrListSize)68*758e9fbaSOystein Eftevaag ifapi_eventlog_get_async(
69*758e9fbaSOystein Eftevaag     IFAPI_EVENTLOG *eventlog,
70*758e9fbaSOystein Eftevaag     IFAPI_IO *io,
71*758e9fbaSOystein Eftevaag     const TPM2_HANDLE *pcrList,
72*758e9fbaSOystein Eftevaag     size_t pcrListSize)
73*758e9fbaSOystein Eftevaag {
74*758e9fbaSOystein Eftevaag     check_not_null(eventlog);
75*758e9fbaSOystein Eftevaag     check_not_null(io);
76*758e9fbaSOystein Eftevaag     check_not_null(pcrList);
77*758e9fbaSOystein Eftevaag 
78*758e9fbaSOystein Eftevaag     if (pcrListSize > TPM2_MAX_PCRS) {
79*758e9fbaSOystein Eftevaag         LOG_ERROR("pcrList too long %zi > %i", pcrListSize, TPM2_MAX_PCRS);
80*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_BAD_VALUE;
81*758e9fbaSOystein Eftevaag     }
82*758e9fbaSOystein Eftevaag 
83*758e9fbaSOystein Eftevaag     LOG_TRACE("called for pcrListSize=%zi", pcrListSize);
84*758e9fbaSOystein Eftevaag 
85*758e9fbaSOystein Eftevaag     memcpy(&eventlog->pcrList, pcrList, pcrListSize * sizeof(TPM2_HANDLE));
86*758e9fbaSOystein Eftevaag     eventlog->pcrListSize = pcrListSize;
87*758e9fbaSOystein Eftevaag     eventlog->pcrListIdx = 0;
88*758e9fbaSOystein Eftevaag 
89*758e9fbaSOystein Eftevaag     eventlog->log = json_object_new_array();
90*758e9fbaSOystein Eftevaag     return_if_null(eventlog->log, "Out of memory", TSS2_FAPI_RC_MEMORY);
91*758e9fbaSOystein Eftevaag 
92*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
93*758e9fbaSOystein Eftevaag }
94*758e9fbaSOystein Eftevaag 
95*758e9fbaSOystein Eftevaag /** Retrieve the eventlog for a given list of pcrs using asynchronous io.
96*758e9fbaSOystein Eftevaag  *
97*758e9fbaSOystein Eftevaag  * Call after ifapi_eventlog_get_async.
98*758e9fbaSOystein Eftevaag  *
99*758e9fbaSOystein Eftevaag  * @param[in,out] eventlog The context area for the eventlog.
100*758e9fbaSOystein Eftevaag  * @param[in,out] io The context area for the asynchronous io module.
101*758e9fbaSOystein Eftevaag  * @param[out] log The event log for the requested PCRs in JSON format
102*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
103*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
104*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
105*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if the I/O operation is not finished yet and this function needs
106*758e9fbaSOystein Eftevaag  *         to be called again.
107*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
108*758e9fbaSOystein Eftevaag  *         the function.
109*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
110*758e9fbaSOystein Eftevaag  *         operation already pending.
111*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
112*758e9fbaSOystein Eftevaag  */
113*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_eventlog_get_finish(IFAPI_EVENTLOG * eventlog,IFAPI_IO * io,char ** log)114*758e9fbaSOystein Eftevaag ifapi_eventlog_get_finish(
115*758e9fbaSOystein Eftevaag     IFAPI_EVENTLOG *eventlog,
116*758e9fbaSOystein Eftevaag     IFAPI_IO *io,
117*758e9fbaSOystein Eftevaag     char **log)
118*758e9fbaSOystein Eftevaag {
119*758e9fbaSOystein Eftevaag     /* eventlog parameter currently not used */
120*758e9fbaSOystein Eftevaag     check_not_null(eventlog);
121*758e9fbaSOystein Eftevaag     check_not_null(io);
122*758e9fbaSOystein Eftevaag     check_not_null(log);
123*758e9fbaSOystein Eftevaag 
124*758e9fbaSOystein Eftevaag     TSS2_RC r;
125*758e9fbaSOystein Eftevaag     char *event_log_file, *logstr;
126*758e9fbaSOystein Eftevaag     json_object *logpart, *event;
127*758e9fbaSOystein Eftevaag 
128*758e9fbaSOystein Eftevaag     LOG_TRACE("called");
129*758e9fbaSOystein Eftevaag 
130*758e9fbaSOystein Eftevaag loop:
131*758e9fbaSOystein Eftevaag     /* If we're dune with adding all eventlogs to the json array, we can serialize it and return
132*758e9fbaSOystein Eftevaag        it to the caller. */
133*758e9fbaSOystein Eftevaag     if (eventlog->pcrListIdx >= eventlog->pcrListSize) {
134*758e9fbaSOystein Eftevaag         LOG_TRACE("Done reading pcrLog");
135*758e9fbaSOystein Eftevaag         *log = strdup(json_object_to_json_string_ext(eventlog->log, JSON_C_TO_STRING_PRETTY));
136*758e9fbaSOystein Eftevaag         check_oom(*log);
137*758e9fbaSOystein Eftevaag         json_object_put(eventlog->log);
138*758e9fbaSOystein Eftevaag         eventlog->log = NULL;
139*758e9fbaSOystein Eftevaag         eventlog->state = IFAPI_EVENTLOG_STATE_INIT;
140*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
141*758e9fbaSOystein Eftevaag     }
142*758e9fbaSOystein Eftevaag 
143*758e9fbaSOystein Eftevaag     switch (eventlog->state) {
144*758e9fbaSOystein Eftevaag     statecase(eventlog->state, IFAPI_EVENTLOG_STATE_INIT)
145*758e9fbaSOystein Eftevaag         /* Construct the filename for the eventlog file */
146*758e9fbaSOystein Eftevaag         r = ifapi_asprintf(&event_log_file, "%s/%s%i",
147*758e9fbaSOystein Eftevaag                            eventlog->log_dir, IFAPI_PCR_LOG_FILE,
148*758e9fbaSOystein Eftevaag                            eventlog->pcrList[eventlog->pcrListIdx]);
149*758e9fbaSOystein Eftevaag         return_if_error(r, "Out of memory.");
150*758e9fbaSOystein Eftevaag 
151*758e9fbaSOystein Eftevaag         if (!ifapi_io_path_exists(event_log_file)) {
152*758e9fbaSOystein Eftevaag             LOG_DEBUG("No event log for pcr %i", eventlog->pcrList[eventlog->pcrListIdx]);
153*758e9fbaSOystein Eftevaag             SAFE_FREE(event_log_file);
154*758e9fbaSOystein Eftevaag             eventlog->pcrListIdx += 1;
155*758e9fbaSOystein Eftevaag             goto loop;
156*758e9fbaSOystein Eftevaag         }
157*758e9fbaSOystein Eftevaag 
158*758e9fbaSOystein Eftevaag         /* Initiate the reading of the eventlog file */
159*758e9fbaSOystein Eftevaag         r = ifapi_io_read_async(io, event_log_file);
160*758e9fbaSOystein Eftevaag         free(event_log_file);
161*758e9fbaSOystein Eftevaag         if (r) {
162*758e9fbaSOystein Eftevaag             LOG_DEBUG("No event log for pcr %i", eventlog->pcrList[eventlog->pcrListIdx]);
163*758e9fbaSOystein Eftevaag             eventlog->pcrListIdx += 1;
164*758e9fbaSOystein Eftevaag             goto loop;
165*758e9fbaSOystein Eftevaag         }
166*758e9fbaSOystein Eftevaag         fallthrough;
167*758e9fbaSOystein Eftevaag 
168*758e9fbaSOystein Eftevaag     statecase(eventlog->state, IFAPI_EVENTLOG_STATE_READING)
169*758e9fbaSOystein Eftevaag         /* Finish the reading of the eventlog file and return it directly to the output parameter */
170*758e9fbaSOystein Eftevaag         r = ifapi_io_read_finish(io, (uint8_t **)&logstr, NULL);
171*758e9fbaSOystein Eftevaag         return_try_again(r);
172*758e9fbaSOystein Eftevaag         return_if_error(r, "read_finish failed");
173*758e9fbaSOystein Eftevaag 
174*758e9fbaSOystein Eftevaag         logpart = json_tokener_parse(logstr);
175*758e9fbaSOystein Eftevaag         SAFE_FREE(logstr);
176*758e9fbaSOystein Eftevaag         return_if_null(log, "JSON parsing error", TSS2_FAPI_RC_BAD_VALUE);
177*758e9fbaSOystein Eftevaag 
178*758e9fbaSOystein Eftevaag         /* Append the log-entry from logpart to the eventlog */
179*758e9fbaSOystein Eftevaag         json_type jso_type = json_object_get_type(logpart);
180*758e9fbaSOystein Eftevaag         if (jso_type != json_type_array) {
181*758e9fbaSOystein Eftevaag             /* libjson-c does not deliver an array if array has only one element */
182*758e9fbaSOystein Eftevaag             json_object_array_add(eventlog->log, logpart);
183*758e9fbaSOystein Eftevaag         } else {
184*758e9fbaSOystein Eftevaag             /* Iterate through the array of logpart and add each item to the eventlog */
185*758e9fbaSOystein Eftevaag             /* The return type of json_object_array_length() was changed, thus the case */
186*758e9fbaSOystein Eftevaag             for (int i = 0; i < (int)json_object_array_length(logpart); i++) {
187*758e9fbaSOystein Eftevaag                 event = json_object_array_get_idx(logpart, i);
188*758e9fbaSOystein Eftevaag                 /* Increment the refcount of event so it does not get freed on put(logpart) below */
189*758e9fbaSOystein Eftevaag                 json_object_get(event);
190*758e9fbaSOystein Eftevaag                 json_object_array_add(eventlog->log, event);
191*758e9fbaSOystein Eftevaag             }
192*758e9fbaSOystein Eftevaag             json_object_put(logpart);
193*758e9fbaSOystein Eftevaag         }
194*758e9fbaSOystein Eftevaag 
195*758e9fbaSOystein Eftevaag         eventlog->pcrListIdx += 1;
196*758e9fbaSOystein Eftevaag         eventlog->state = IFAPI_EVENTLOG_STATE_INIT;
197*758e9fbaSOystein Eftevaag         goto loop;
198*758e9fbaSOystein Eftevaag 
199*758e9fbaSOystein Eftevaag     statecasedefault(eventlog->state);
200*758e9fbaSOystein Eftevaag     }
201*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
202*758e9fbaSOystein Eftevaag }
203*758e9fbaSOystein Eftevaag 
204*758e9fbaSOystein Eftevaag /** Append an event to the existing event log.
205*758e9fbaSOystein Eftevaag  *
206*758e9fbaSOystein Eftevaag  * Call ifapi_eventlog_append_finish to finalize this operation.
207*758e9fbaSOystein Eftevaag  *
208*758e9fbaSOystein Eftevaag  * @param[in,out] eventlog The context area for the eventlog.
209*758e9fbaSOystein Eftevaag  * @param[in,out] io The context area for the asynchronous io module.
210*758e9fbaSOystein Eftevaag  * @param[in] event The event to be appended to the eventlog.
211*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
212*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
213*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
214*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
215*758e9fbaSOystein Eftevaag  *         operation already pending.
216*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
217*758e9fbaSOystein Eftevaag  */
218*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_eventlog_append_async(IFAPI_EVENTLOG * eventlog,IFAPI_IO * io,const IFAPI_EVENT * event)219*758e9fbaSOystein Eftevaag ifapi_eventlog_append_async(
220*758e9fbaSOystein Eftevaag     IFAPI_EVENTLOG *eventlog,
221*758e9fbaSOystein Eftevaag     IFAPI_IO *io,
222*758e9fbaSOystein Eftevaag     const IFAPI_EVENT *event)
223*758e9fbaSOystein Eftevaag {
224*758e9fbaSOystein Eftevaag     check_not_null(eventlog);
225*758e9fbaSOystein Eftevaag     check_not_null(io);
226*758e9fbaSOystein Eftevaag     check_not_null(event);
227*758e9fbaSOystein Eftevaag 
228*758e9fbaSOystein Eftevaag     TSS2_RC r;
229*758e9fbaSOystein Eftevaag     char *event_log_file;
230*758e9fbaSOystein Eftevaag 
231*758e9fbaSOystein Eftevaag     if (eventlog->state != IFAPI_EVENTLOG_STATE_INIT) {
232*758e9fbaSOystein Eftevaag         LOG_ERROR("Wrong state: %i", eventlog->state);
233*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_BAD_SEQUENCE;
234*758e9fbaSOystein Eftevaag     }
235*758e9fbaSOystein Eftevaag 
236*758e9fbaSOystein Eftevaag     eventlog->event = *event;
237*758e9fbaSOystein Eftevaag 
238*758e9fbaSOystein Eftevaag     /* Construct the filename for the eventlog file */
239*758e9fbaSOystein Eftevaag     r = ifapi_asprintf(&event_log_file, "%s/%s%i",
240*758e9fbaSOystein Eftevaag                        eventlog->log_dir, IFAPI_PCR_LOG_FILE, event->pcr);
241*758e9fbaSOystein Eftevaag     return_if_error(r, "Out of memory.");
242*758e9fbaSOystein Eftevaag 
243*758e9fbaSOystein Eftevaag     /* Initiate the reading of the eventlog file */
244*758e9fbaSOystein Eftevaag     r = ifapi_io_read_async(io, event_log_file);
245*758e9fbaSOystein Eftevaag     if (r) {
246*758e9fbaSOystein Eftevaag         LOG_DEBUG("Eventlog file %s could not be opened, creating...", event_log_file);
247*758e9fbaSOystein Eftevaag         free(event_log_file);
248*758e9fbaSOystein Eftevaag         eventlog->state = IFAPI_EVENTLOG_STATE_APPENDING;
249*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
250*758e9fbaSOystein Eftevaag     }
251*758e9fbaSOystein Eftevaag     free(event_log_file);
252*758e9fbaSOystein Eftevaag 
253*758e9fbaSOystein Eftevaag     eventlog->state = IFAPI_EVENTLOG_STATE_READING;
254*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
255*758e9fbaSOystein Eftevaag }
256*758e9fbaSOystein Eftevaag 
257*758e9fbaSOystein Eftevaag /** Append an event to the existing event log.
258*758e9fbaSOystein Eftevaag  *
259*758e9fbaSOystein Eftevaag  * Call after ifapi_eventlog_get_async.
260*758e9fbaSOystein Eftevaag  *
261*758e9fbaSOystein Eftevaag  * @param[in,out] eventlog The context area for the eventlog.
262*758e9fbaSOystein Eftevaag  * @param[in,out] io The context area for the asynchronous io module.
263*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
264*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
265*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
266*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN if the I/O operation is not finished yet and this function needs
267*758e9fbaSOystein Eftevaag  *         to be called again.
268*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
269*758e9fbaSOystein Eftevaag  *         the function.
270*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
271*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
272*758e9fbaSOystein Eftevaag  *         operation already pending.
273*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
274*758e9fbaSOystein Eftevaag  */
275*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_eventlog_append_finish(IFAPI_EVENTLOG * eventlog,IFAPI_IO * io)276*758e9fbaSOystein Eftevaag ifapi_eventlog_append_finish(
277*758e9fbaSOystein Eftevaag     IFAPI_EVENTLOG *eventlog,
278*758e9fbaSOystein Eftevaag     IFAPI_IO *io)
279*758e9fbaSOystein Eftevaag {
280*758e9fbaSOystein Eftevaag     check_not_null(eventlog);
281*758e9fbaSOystein Eftevaag     check_not_null(io);
282*758e9fbaSOystein Eftevaag 
283*758e9fbaSOystein Eftevaag     TSS2_RC r;
284*758e9fbaSOystein Eftevaag     char *logstr = NULL, *event_log_file;
285*758e9fbaSOystein Eftevaag     const char *logstr2 = NULL;
286*758e9fbaSOystein Eftevaag     json_object *log, *event = NULL;
287*758e9fbaSOystein Eftevaag 
288*758e9fbaSOystein Eftevaag     switch (eventlog->state) {
289*758e9fbaSOystein Eftevaag     statecase(eventlog->state, IFAPI_EVENTLOG_STATE_READING)
290*758e9fbaSOystein Eftevaag         /* Finish the reading of the eventlog file and return it directly to the output parameter */
291*758e9fbaSOystein Eftevaag         r = ifapi_io_read_finish(io, (uint8_t **)&logstr, NULL);
292*758e9fbaSOystein Eftevaag         return_try_again(r);
293*758e9fbaSOystein Eftevaag         return_if_error(r, "read_finish failed");
294*758e9fbaSOystein Eftevaag         fallthrough;
295*758e9fbaSOystein Eftevaag 
296*758e9fbaSOystein Eftevaag     statecase(eventlog->state, IFAPI_EVENTLOG_STATE_APPENDING)
297*758e9fbaSOystein Eftevaag         /* If a log was read, we deserialize it to JSON. Otherwise we start a new log. */
298*758e9fbaSOystein Eftevaag         if (logstr) {
299*758e9fbaSOystein Eftevaag             log = json_tokener_parse(logstr);
300*758e9fbaSOystein Eftevaag             SAFE_FREE(logstr);
301*758e9fbaSOystein Eftevaag             return_if_null(log, "JSON parsing error", TSS2_FAPI_RC_BAD_VALUE);
302*758e9fbaSOystein Eftevaag 
303*758e9fbaSOystein Eftevaag              /* libjson-c does not deliver an array if array has only one element */
304*758e9fbaSOystein Eftevaag             json_type jso_type = json_object_get_type(log);
305*758e9fbaSOystein Eftevaag             if (jso_type != json_type_array) {
306*758e9fbaSOystein Eftevaag                 json_object *json_array = json_object_new_array();
307*758e9fbaSOystein Eftevaag                 json_object_array_add(json_array, log);
308*758e9fbaSOystein Eftevaag                 log = json_array;
309*758e9fbaSOystein Eftevaag             }
310*758e9fbaSOystein Eftevaag         } else {
311*758e9fbaSOystein Eftevaag             log = json_object_new_array();
312*758e9fbaSOystein Eftevaag             return_if_null(log, "Out of memory", TSS2_FAPI_RC_MEMORY);
313*758e9fbaSOystein Eftevaag         }
314*758e9fbaSOystein Eftevaag 
315*758e9fbaSOystein Eftevaag         /* Extend the eventlog with the data */
316*758e9fbaSOystein Eftevaag         eventlog->event.recnum = json_object_array_length(log) + 1;
317*758e9fbaSOystein Eftevaag 
318*758e9fbaSOystein Eftevaag         r = ifapi_json_IFAPI_EVENT_serialize(&eventlog->event, &event);
319*758e9fbaSOystein Eftevaag         if (r) {
320*758e9fbaSOystein Eftevaag             json_object_put(log);
321*758e9fbaSOystein Eftevaag             LOG_ERROR("Error serializing event data");
322*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_GENERAL_FAILURE;
323*758e9fbaSOystein Eftevaag         }
324*758e9fbaSOystein Eftevaag 
325*758e9fbaSOystein Eftevaag         json_object_array_add(log, event);
326*758e9fbaSOystein Eftevaag         logstr2 = json_object_to_json_string_ext(log, JSON_C_TO_STRING_PRETTY);
327*758e9fbaSOystein Eftevaag 
328*758e9fbaSOystein Eftevaag         /* Construct the filename for the eventlog file */
329*758e9fbaSOystein Eftevaag         r = ifapi_asprintf(&event_log_file, "%s/%s%i",
330*758e9fbaSOystein Eftevaag                            eventlog->log_dir, IFAPI_PCR_LOG_FILE, eventlog->event.pcr);
331*758e9fbaSOystein Eftevaag         return_if_error(r, "Out of memory.");
332*758e9fbaSOystein Eftevaag 
333*758e9fbaSOystein Eftevaag         /* Start writing the eventlog back to disk */
334*758e9fbaSOystein Eftevaag         r = ifapi_io_write_async(io, event_log_file, (uint8_t *) logstr2, strlen(logstr2));
335*758e9fbaSOystein Eftevaag         free(event_log_file);
336*758e9fbaSOystein Eftevaag         json_object_put(log); /* this also frees logstr2 */
337*758e9fbaSOystein Eftevaag         return_if_error(r, "write_async failed");
338*758e9fbaSOystein Eftevaag         fallthrough;
339*758e9fbaSOystein Eftevaag 
340*758e9fbaSOystein Eftevaag     statecase(eventlog->state, IFAPI_EVENTLOG_STATE_WRITING)
341*758e9fbaSOystein Eftevaag         /* Finish writing the eventlog */
342*758e9fbaSOystein Eftevaag         r = ifapi_io_write_finish(io);
343*758e9fbaSOystein Eftevaag         return_try_again(r);
344*758e9fbaSOystein Eftevaag         return_if_error(r, "read_finish failed");
345*758e9fbaSOystein Eftevaag 
346*758e9fbaSOystein Eftevaag         eventlog->state = IFAPI_EVENTLOG_STATE_INIT;
347*758e9fbaSOystein Eftevaag         break;
348*758e9fbaSOystein Eftevaag 
349*758e9fbaSOystein Eftevaag     statecasedefault(eventlog->state);
350*758e9fbaSOystein Eftevaag     }
351*758e9fbaSOystein Eftevaag 
352*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
353*758e9fbaSOystein Eftevaag }
354*758e9fbaSOystein Eftevaag 
355*758e9fbaSOystein Eftevaag 
356*758e9fbaSOystein Eftevaag /** Free allocated memory for an ifapi event.
357*758e9fbaSOystein Eftevaag  *
358*758e9fbaSOystein Eftevaag  * @param[in,out] event The structure to be cleaned up.
359*758e9fbaSOystein Eftevaag  */
360*758e9fbaSOystein Eftevaag void
ifapi_cleanup_event(IFAPI_EVENT * event)361*758e9fbaSOystein Eftevaag ifapi_cleanup_event(IFAPI_EVENT * event) {
362*758e9fbaSOystein Eftevaag     if (event != NULL) {
363*758e9fbaSOystein Eftevaag         if (event->type == IFAPI_IMA_EVENT_TAG) {
364*758e9fbaSOystein Eftevaag             SAFE_FREE(event->sub_event.ima_event.eventName);
365*758e9fbaSOystein Eftevaag         } else if (event->type == IFAPI_TSS_EVENT_TAG) {
366*758e9fbaSOystein Eftevaag             SAFE_FREE(event->sub_event.tss_event.event);
367*758e9fbaSOystein Eftevaag         }
368*758e9fbaSOystein Eftevaag     }
369*758e9fbaSOystein Eftevaag }
370