blob: 6029548a20477b8cf94b84bedfe12f82211fabac [file] [log] [blame]
Harrison Mutai762d4942025-05-06 13:06:41 +00001/*
2 * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <errno.h>
8#include <stdbool.h>
Harrison Mutai762d4942025-05-06 13:06:41 +00009#include <string.h>
10
Harrison Mutai88d6ec82025-08-12 14:32:58 +000011#include "debug.h"
12#include "digest.h"
Harrison Mutai762d4942025-05-06 13:06:41 +000013#include "event_log.h"
14
Harrison Mutai88d6ec82025-08-12 14:32:58 +000015#include <stddef.h>
16#include <stdint.h>
17
18/**
19 * @brief Pretty-print a digest as 16-byte spaced hex rows with a
20 * header/continuation prefix.
21 *
22 * Emits one or more lines through the NOTICE() logging macro.
23 * Each line renders up to 16 bytes as "aa bb …".
24 *
25 * @param[in] buf Byte array to print.
26 * @param[in] buf_len Number of bytes in @p digest.
27 * @param[in] prefix Prefix to append to the byte array (e.g. 'VendorInfo :').
28 *
29 */
30static void event_log_print_spaced_hex(const uint8_t *buf, size_t buf_len,
31 const char *prefix)
32{
33 char output_buf[256];
34 const size_t cap = sizeof(output_buf);
35 size_t pos = 0U;
36 size_t chunk;
37
38 /* Start from just after the prefix */
39 event_log_append_str(output_buf, cap, &pos, prefix);
40
41 for (size_t off = 0; off < buf_len; off += 16U) {
42 chunk = (buf_len - off >= 16U) ? 16U : (buf_len - off);
43
44 /* write the 16-byte (or tail) chunk */
45 pos += event_log_write_hex_spaced(output_buf + pos,
46 (pos < cap) ? (cap - pos) : 0,
47 chunk, buf + off);
48
49 NOTICE(" %s\n", output_buf);
50
51 /* prepare next line: reset to prefix only */
52 pos = 0;
53 output_buf[0] = '\0';
54 event_log_append_str(output_buf, cap, &pos, "\t\t : ");
55 }
56}
57
58static void event_log_print_digest(const uint8_t *digest, size_t digest_len)
59{
60 event_log_print_spaced_hex(digest, digest_len, "Digest : ");
61}
62
Harrison Mutai762d4942025-05-06 13:06:41 +000063/**
64 * Print a TCG_EfiSpecIDEventStruct entry from the event log.
65 *
66 * This function extracts and prints a TCG_EfiSpecIDEventStruct
67 * entry from the event log for debugging or auditing purposes.
68 *
69 * @param[in,out] log_addr Pointer to the current position in the Event Log.
70 * Updated to the next entry after processing.
71 * @param[in,out] log_size Pointer to the remaining Event Log size.
72 * Updated to reflect the remaining bytes.
73 *
74 * @return 0 on success, or a negative error code on failure.
75 */
76static int event_log_print_id_event(uint8_t **log_addr, size_t *log_size)
77{
78 unsigned int i;
79 uint8_t info_size, *info_size_ptr;
80 void *ptr = *log_addr;
81 id_event_headers_t *event = (id_event_headers_t *)ptr;
82 id_event_algorithm_size_t *alg_ptr;
83 uint32_t event_size, number_of_algorithms;
84 size_t digest_len;
85 const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
Harrison Mutai88d6ec82025-08-12 14:32:58 +000086 const struct event_log_algorithm *algo_info;
Harrison Mutai762d4942025-05-06 13:06:41 +000087
88 if (*log_size < sizeof(id_event_headers_t)) {
89 return -EINVAL;
90 }
91
92 /* The fields of the event log header are defined to be PCRIndex of 0,
93 * EventType of EV_NO_ACTION, Digest of 20 bytes of 0, and
94 * Event content defined as TCG_EfiSpecIDEventStruct.
95 */
Harrison Mutai88d6ec82025-08-12 14:32:58 +000096 NOTICE("TCG_EfiSpecIDEvent:\n");
97 NOTICE(" PCRIndex : %u\n", event->header.pcr_index);
Harrison Mutai762d4942025-05-06 13:06:41 +000098 if (event->header.pcr_index != (uint32_t)PCR_0) {
99 return -EINVAL;
100 }
101
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000102 NOTICE(" EventType : %u\n", event->header.event_type);
Harrison Mutai762d4942025-05-06 13:06:41 +0000103 if (event->header.event_type != EV_NO_ACTION) {
104 return -EINVAL;
105 }
106
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000107 event_log_print_digest(event->header.digest,
108 sizeof(event->header.digest));
Harrison Mutai762d4942025-05-06 13:06:41 +0000109
110 /* EventSize */
111 event_size = event->header.event_size;
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000112 NOTICE(" EventSize : %u\n", event_size);
Harrison Mutai762d4942025-05-06 13:06:41 +0000113
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000114 NOTICE(" Signature : %s\n", event->struct_header.signature);
115 NOTICE(" PlatformClass : %u\n",
Harrison Mutai762d4942025-05-06 13:06:41 +0000116 event->struct_header.platform_class);
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000117 NOTICE(" SpecVersion : %u.%u.%u\n",
Harrison Mutai762d4942025-05-06 13:06:41 +0000118 event->struct_header.spec_version_major,
119 event->struct_header.spec_version_minor,
120 event->struct_header.spec_errata);
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000121 NOTICE(" UintnSize : %u\n", event->struct_header.uintn_size);
Harrison Mutai762d4942025-05-06 13:06:41 +0000122
123 /* NumberOfAlgorithms */
124 number_of_algorithms = event->struct_header.number_of_algorithms;
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000125 NOTICE(" NumberOfAlgorithms : %u\n", number_of_algorithms);
Harrison Mutai762d4942025-05-06 13:06:41 +0000126
127 /* Address of DigestSizes[] */
128 alg_ptr = event->struct_header.digest_size;
129
130 /* Size of DigestSizes[] */
131 digest_len = number_of_algorithms * sizeof(id_event_algorithm_size_t);
132 if (digest_len > (uintptr_t)end_ptr - (uintptr_t)alg_ptr) {
133 return -EFAULT;
134 }
135
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000136 NOTICE(" DigestSizes :\n");
Harrison Mutai762d4942025-05-06 13:06:41 +0000137
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000138 for (i = 0U; i < number_of_algorithms; ++i) {
139 uint16_t algorithm_id = alg_ptr[i].algorithm_id;
140 algo_info = event_log_algorithm_lookup(algorithm_id);
141
142 if (algo_info == NULL) {
143 ERROR(" #%u AlgorithmId : %d (unknown)\n", i,
144 algorithm_id);
Harrison Mutai762d4942025-05-06 13:06:41 +0000145 return -ENOENT;
146 }
147
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000148 NOTICE(" #%u AlgorithmId : %s\n", i, algo_info->name);
149 NOTICE(" DigestSize : %u\n", alg_ptr[i].digest_size);
Harrison Mutai762d4942025-05-06 13:06:41 +0000150 }
151
152 /* Address of VendorInfoSize */
153 info_size_ptr = (uint8_t *)((uintptr_t)alg_ptr + digest_len);
154 if ((uintptr_t)info_size_ptr > (uintptr_t)end_ptr) {
155 return -EFAULT;
156 }
157
158 info_size = *info_size_ptr++;
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000159 NOTICE(" VendorInfoSize : %u\n", info_size);
Harrison Mutai762d4942025-05-06 13:06:41 +0000160
161 /* Check VendorInfo end address */
162 if (((uintptr_t)info_size_ptr + info_size) > (uintptr_t)end_ptr) {
163 return -EFAULT;
164 }
165
166 /* Check EventSize */
167 if (event_size !=
168 (sizeof(id_event_struct_t) + digest_len + info_size)) {
169 return -EFAULT;
170 }
171
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000172 event_log_print_spaced_hex(info_size_ptr, info_size,
173 " VendorInfo : ");
Harrison Mutai762d4942025-05-06 13:06:41 +0000174
175 *log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr;
176 *log_addr = info_size_ptr;
177
178 return 0;
179}
180
181/**
182 * Print a TCG_PCR_EVENT2 entry from the event log.
183 *
184 * This function extracts and prints a TCG_PCR_EVENT2 structure
185 * from the event log for debugging or auditing purposes.
186 *
187 * @param[in,out] log_addr Pointer to the current position in the Event Log.
188 * Updated to the next entry after processing.
189 * @param[in,out] log_size Pointer to the remaining Event Log size.
190 * Updated to reflect the remaining bytes.
191 *
192 * @return 0 on success, or a negative error code on failure.
193 */
194static int event_log_print_pcr_event2(uint8_t **log_addr, size_t *log_size)
195{
196 uint32_t event_size, count;
Harrison Mutai762d4942025-05-06 13:06:41 +0000197 void *ptr = *log_addr;
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000198 const struct event_log_algorithm *algo_info;
Harrison Mutai762d4942025-05-06 13:06:41 +0000199 const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
200
201 if (*log_size < sizeof(event2_header_t)) {
202 return -EINVAL;
203 }
204
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000205 NOTICE("PCR_Event2:\n");
206 NOTICE(" PCRIndex : %u\n",
Harrison Mutai762d4942025-05-06 13:06:41 +0000207 ((event2_header_t *)ptr)->pcr_index);
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000208 NOTICE(" EventType : %u\n",
Harrison Mutai762d4942025-05-06 13:06:41 +0000209 ((event2_header_t *)ptr)->event_type);
210
211 count = ((event2_header_t *)ptr)->digests.count;
212 if (count < 1U) {
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000213 NOTICE("Invalid Digests Count : %u\n", count);
Harrison Mutai762d4942025-05-06 13:06:41 +0000214 return -EINVAL;
215 }
216
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000217 NOTICE(" Digests Count : %u\n", count);
Harrison Mutai762d4942025-05-06 13:06:41 +0000218
219 /* Address of TCG_PCR_EVENT2.Digests[] */
220 ptr = (uint8_t *)ptr + sizeof(event2_header_t);
221 if ((uintptr_t)ptr > (uintptr_t)end_ptr) {
222 return -EFAULT;
223 }
224
225 for (unsigned int i = 0U; i < count; ++i) {
226 /* Check AlgorithmId address */
227 if (((uintptr_t)ptr + offsetof(tpmt_ha, digest)) >
228 (uintptr_t)end_ptr) {
229 return -EFAULT;
230 }
231
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000232 algo_info = event_log_algorithm_lookup(
233 ((tpmt_ha *)ptr)->algorithm_id);
234
235 if (algo_info == NULL) {
236 ERROR(" #%u AlgorithmId : %d (unknown)\n", i,
237 ((tpmt_ha *)ptr)->algorithm_id);
Harrison Mutai762d4942025-05-06 13:06:41 +0000238 return -ENOENT;
239 }
240
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000241 NOTICE(" #%u AlgorithmId : %s\n", i, algo_info->name);
242
Harrison Mutai762d4942025-05-06 13:06:41 +0000243 /* End of Digest[] */
244 ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000245 if (((uintptr_t)ptr + algo_info->size) > (uintptr_t)end_ptr) {
Harrison Mutai762d4942025-05-06 13:06:41 +0000246 return -EFAULT;
247 }
248
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000249 event_log_print_digest(ptr, algo_info->size);
250 ptr += algo_info->size;
Harrison Mutai762d4942025-05-06 13:06:41 +0000251 }
252
253 /* TCG_PCR_EVENT2.EventSize */
254 if (((uintptr_t)ptr + offsetof(event2_data_t, event)) >
255 (uintptr_t)end_ptr) {
256 return -EFAULT;
257 }
258
259 event_size = ((event2_data_t *)ptr)->event_size;
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000260 NOTICE(" EventSize : %u\n", event_size);
Harrison Mutai762d4942025-05-06 13:06:41 +0000261
262 /* Address of TCG_PCR_EVENT2.Event[EventSize] */
263 ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
264
265 /* End of TCG_PCR_EVENT2.Event[EventSize] */
266 if (((uintptr_t)ptr + event_size) > (uintptr_t)end_ptr) {
267 return -EFAULT;
268 }
269
270 if ((event_size == sizeof(startup_locality_event_t)) &&
271 (strcmp((const char *)ptr, TCG_STARTUP_LOCALITY_SIGNATURE) == 0)) {
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000272 NOTICE(" Signature : %s\n",
Harrison Mutai762d4942025-05-06 13:06:41 +0000273 ((startup_locality_event_t *)ptr)->signature);
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000274 NOTICE(" StartupLocality : %u\n",
Harrison Mutai762d4942025-05-06 13:06:41 +0000275 ((startup_locality_event_t *)ptr)->startup_locality);
276 } else {
Harrison Mutai88d6ec82025-08-12 14:32:58 +0000277 NOTICE(" Event : %s\n", (uint8_t *)ptr);
Harrison Mutai762d4942025-05-06 13:06:41 +0000278 }
279
280 *log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr;
281 *log_addr = (uint8_t *)ptr + event_size;
282
283 return 0;
284}
285
286int event_log_dump(uint8_t *log_addr, size_t log_size)
287{
288 int rc;
289
290 if (log_addr == NULL) {
291 return -EINVAL;
292 }
293
294 /* Print TCG_EfiSpecIDEvent */
295 rc = event_log_print_id_event(&log_addr, &log_size);
296
297 if (rc < 0) {
298 return rc;
299 }
300
301 while (log_size != 0U) {
302 rc = event_log_print_pcr_event2(&log_addr, &log_size);
303 if (rc < 0) {
304 return rc;
305 }
306 }
307 return 0;
308}