blob: d59346b4bd4c5aeeb6b33fec13771ee276b8391a [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 <assert.h>
8#include <errno.h>
9#include <string.h>
10
11#include "event_log.h"
12
13/* Running Event Log Pointer */
14static uint8_t *log_ptr;
15
16/* Pointer to the first byte past end of the Event Log buffer */
17static uintptr_t log_end;
18
19/* Hash function for event log operations set by user. */
20static const struct event_log_hash_info *crypto_hash_info;
21
22/* TCG_EfiSpecIdEvent */
23static const id_event_headers_t id_event_header = {
24 .header = { .pcr_index = PCR_0,
25 .event_type = EV_NO_ACTION,
26 .digest = { 0 },
27 .event_size =
28 (uint32_t)(sizeof(id_event_struct_t) +
29 (sizeof(id_event_algorithm_size_t) *
30 HASH_ALG_COUNT)) },
31
32 .struct_header = { .signature = TCG_ID_EVENT_SIGNATURE_03,
33 .platform_class = PLATFORM_CLASS_CLIENT,
34 .spec_version_minor = TCG_SPEC_VERSION_MINOR_TPM2,
35 .spec_version_major = TCG_SPEC_VERSION_MAJOR_TPM2,
36 .spec_errata = TCG_SPEC_ERRATA_TPM2,
37 .uintn_size = (uint8_t)(sizeof(unsigned int) /
38 sizeof(uint32_t)),
39 .number_of_algorithms = HASH_ALG_COUNT }
40};
41
42static const event2_header_t locality_event_header = {
43 /*
44 * All EV_NO_ACTION events SHALL set
45 * TCG_PCR_EVENT2.pcrIndex = 0, unless otherwise specified
46 */
47 .pcr_index = PCR_0,
48
49 /*
50 * All EV_NO_ACTION events SHALL set
51 * TCG_PCR_EVENT2.eventType = 03h
52 */
53 .event_type = EV_NO_ACTION,
54
55 /*
56 * All EV_NO_ACTION events SHALL set TCG_PCR_EVENT2.digests to all
57 * 0x00's for each allocated Hash algorithm
58 */
59 .digests = { .count = HASH_ALG_COUNT }
60};
61
62/* Message digest algorithm */
63enum crypto_md_algo {
64 CRYPTO_MD_SHA256,
65 CRYPTO_MD_SHA384,
66 CRYPTO_MD_SHA512,
67};
68
69int event_log_record(const uint8_t *hash, uint32_t event_type,
70 const event_log_metadata_t *metadata_ptr)
71{
72 void *ptr = log_ptr;
73 uint32_t name_len = 0U;
74
75 /* event_log_buf_init() must have been called prior to this. */
76 if (hash == NULL || metadata_ptr == NULL || log_ptr == NULL) {
77 return -EINVAL;
78 }
79
80 if (metadata_ptr->name != NULL) {
81 name_len = (uint32_t)strlen(metadata_ptr->name) + 1U;
82 }
83
84 /* Check for space in Event Log buffer */
85 if (((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) > log_end) {
86 return -ENOMEM;
87 }
88
89 /*
90 * As per TCG specifications, firmware components that are measured
91 * into PCR[0] must be logged in the event log using the event type
92 * EV_POST_CODE.
93 */
94 /* TCG_PCR_EVENT2.PCRIndex */
95 ((event2_header_t *)ptr)->pcr_index = metadata_ptr->pcr;
96
97 /* TCG_PCR_EVENT2.EventType */
98 ((event2_header_t *)ptr)->event_type = event_type;
99
100 /* TCG_PCR_EVENT2.Digests.Count */
101 ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests);
102 ((tpml_digest_values *)ptr)->count = HASH_ALG_COUNT;
103
104 /* TCG_PCR_EVENT2.Digests[] */
105 ptr = (uint8_t *)((uintptr_t)ptr +
106 offsetof(tpml_digest_values, digests));
107
108 /* TCG_PCR_EVENT2.Digests[].AlgorithmId */
109 ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
110
111 /* TCG_PCR_EVENT2.Digests[].Digest[] */
112 ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
113
114 /* Copy digest */
115 (void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE);
116
117 /* TCG_PCR_EVENT2.EventSize */
118 ptr = (uint8_t *)((uintptr_t)ptr + TCG_DIGEST_SIZE);
119 ((event2_data_t *)ptr)->event_size = name_len;
120
121 /* Copy event data to TCG_PCR_EVENT2.Event */
122 if (metadata_ptr->name != NULL) {
123 (void)memcpy((void *)(((event2_data_t *)ptr)->event),
124 (const void *)metadata_ptr->name, name_len);
125 }
126
127 /* End of event data */
128 log_ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event) +
129 name_len);
130
131 return 0;
132}
133
134int event_log_init(uint8_t *start, uint8_t *finish)
135{
136 if ((start == NULL || finish == NULL) || start > finish) {
137 return -EINVAL;
138 }
139
140 log_ptr = start;
141 log_end = (uintptr_t)finish;
142
143 return 0;
144}
145
146int event_log_write_specid_event(void)
147{
148 void *ptr;
149
150 /* event_log_buf_init() must have been called prior to this. */
151 if (log_ptr == NULL) {
152 return -EFAULT;
153 }
154
155 if (((uintptr_t)log_ptr + ID_EVENT_SIZE) > log_end) {
156 return -ENOMEM;
157 }
158
159 ptr = log_ptr;
160
161 /*
162 * Add Specification ID Event first
163 *
164 * Copy TCG_EfiSpecIDEventStruct structure header
165 */
166 (void)memcpy(ptr, (const void *)&id_event_header,
167 sizeof(id_event_header));
168 ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_header));
169
170 /* TCG_EfiSpecIdEventAlgorithmSize structure */
171 ((id_event_algorithm_size_t *)ptr)->algorithm_id = TPM_ALG_ID;
172 ((id_event_algorithm_size_t *)ptr)->digest_size = TCG_DIGEST_SIZE;
173 ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_algorithm_size_t));
174
175 /*
176 * TCG_EfiSpecIDEventStruct.vendorInfoSize
177 * No vendor data
178 */
179 ((id_event_struct_data_t *)ptr)->vendor_info_size = 0;
180 log_ptr = (uint8_t *)((uintptr_t)ptr +
181 offsetof(id_event_struct_data_t, vendor_info));
182
183 return 0;
184}
185
186int event_log_write_header(void)
187{
188 const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE;
189 void *ptr;
190 int rc;
191
192 rc = event_log_write_specid_event();
193 if (rc < 0) {
194 return rc;
195 }
196
197 if (((uintptr_t)log_ptr + LOC_EVENT_SIZE) > log_end) {
198 return -ENOMEM;
199 }
200
201 ptr = log_ptr;
202
203 /*
204 * The Startup Locality event should be placed in the log before
205 * any event which extends PCR[0].
206 *
207 * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
208 */
209
210 /* Copy Startup Locality Event Header */
211 (void)memcpy(ptr, (const void *)&locality_event_header,
212 sizeof(locality_event_header));
213 ptr = (uint8_t *)((uintptr_t)ptr + sizeof(locality_event_header));
214
215 /* TCG_PCR_EVENT2.Digests[].AlgorithmId */
216 ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
217
218 /* TCG_PCR_EVENT2.Digests[].Digest[] */
219 (void)memset(&((tpmt_ha *)ptr)->digest, 0, TCG_DIGEST_SIZE);
220 ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest) +
221 TCG_DIGEST_SIZE);
222
223 /* TCG_PCR_EVENT2.EventSize */
224 ((event2_data_t *)ptr)->event_size =
225 (uint32_t)sizeof(startup_locality_event_t);
226 ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
227
228 /* TCG_EfiStartupLocalityEvent.Signature */
229 (void)memcpy(ptr, (const void *)locality_signature,
230 sizeof(TCG_STARTUP_LOCALITY_SIGNATURE));
231
232 /*
233 * TCG_EfiStartupLocalityEvent.StartupLocality = 0:
234 * the platform's boot firmware
235 */
236 ((startup_locality_event_t *)ptr)->startup_locality = 0U;
237 log_ptr =
238 (uint8_t *)((uintptr_t)ptr + sizeof(startup_locality_event_t));
239
240 return 0;
241}
242
243int event_log_measure(uintptr_t data_base, uint32_t data_size,
244 unsigned char *hash_data)
245{
246 if (crypto_hash_info == NULL) {
247 return -EINVAL;
248 }
249
250 return crypto_hash_info->func(crypto_hash_info->ids[0],
251 (void *)data_base, data_size, hash_data);
252}
253
254int event_log_init_and_reg(uint8_t *start, uint8_t *finish,
255 const struct event_log_hash_info *hash_info)
256{
257 int rc = event_log_init(start, finish);
258 if (rc < 0) {
259 return rc;
260 }
261
262 if (crypto_hash_info != NULL) {
263 return -EEXIST;
264 }
265
266 if (hash_info == NULL || hash_info->func == NULL ||
267 hash_info->count < 0 || hash_info->count > HASH_ALG_COUNT) {
268 return -EINVAL;
269 }
270
271 crypto_hash_info = hash_info;
272 return 0;
273}
274
275int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size,
276 uint32_t data_id,
277 const event_log_metadata_t *metadata_ptr)
278{
279 unsigned char hash_data[MAX_DIGEST_SIZE];
280 int rc;
281
282 if (metadata_ptr == NULL) {
283 return -EINVAL;
284 }
285
286 /* Get the metadata associated with this image. */
287 while (metadata_ptr->id != data_id) {
288 if (metadata_ptr->id == EVLOG_INVALID_ID) {
289 return -EINVAL;
290 }
291
292 metadata_ptr++;
293 }
294
295 /* Measure the payload with algorithm selected by EventLog driver */
296 rc = event_log_measure(data_base, data_size, hash_data);
297 if (rc != 0) {
298 return rc;
299 }
300
301 rc = event_log_record(hash_data, EV_POST_CODE, metadata_ptr);
302 if (rc != 0) {
303 return rc;
304 }
305
306 return 0;
307}
308
309size_t event_log_get_cur_size(uint8_t *_start)
310{
311 assert(_start != NULL);
312 assert(log_ptr >= _start);
313
314 return (size_t)((uintptr_t)log_ptr - (uintptr_t)_start);
315}