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