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