• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020, 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.h>
16 #include <mbedtls/md.h>
17 
18 #include <plat/common/platform.h>
19 
20 /* Event Log data */
21 static uint8_t event_log[EVENT_LOG_SIZE];
22 
23 /* End of Event Log */
24 #define	EVENT_LOG_END	((uintptr_t)event_log + sizeof(event_log) - 1U)
25 
26 CASSERT(sizeof(event_log) >= LOG_MIN_SIZE, assert_event_log_size);
27 
28 /* Pointer in event_log[] */
29 static uint8_t *log_ptr = event_log;
30 
31 /* Pointer to measured_boot_data_t */
32 const static measured_boot_data_t *plat_data_ptr;
33 
34 static uintptr_t tos_fw_config_base;
35 static uintptr_t nt_fw_config_base;
36 
37 /* TCG_EfiSpecIdEvent */
38 static const id_event_headers_t id_event_header = {
39 	.header = {
40 		.pcr_index = PCR_0,
41 		.event_type = EV_NO_ACTION,
42 		.digest = {0},
43 		.event_size = (uint32_t)(sizeof(id_event_struct_t) +
44 				(sizeof(id_event_algorithm_size_t) *
45 				HASH_ALG_COUNT))
46 	},
47 
48 	.struct_header = {
49 		.signature = TCG_ID_EVENT_SIGNATURE_03,
50 		.platform_class = PLATFORM_CLASS_CLIENT,
51 		.spec_version_minor = TCG_SPEC_VERSION_MINOR_TPM2,
52 		.spec_version_major = TCG_SPEC_VERSION_MAJOR_TPM2,
53 		.spec_errata = TCG_SPEC_ERRATA_TPM2,
54 		.uintn_size = (uint8_t)(sizeof(unsigned int) /
55 					sizeof(uint32_t)),
56 		.number_of_algorithms = HASH_ALG_COUNT
57 	}
58 };
59 
60 static const event2_header_t locality_event_header = {
61 		/*
62 		 * All EV_NO_ACTION events SHALL set
63 		 * TCG_PCR_EVENT2.pcrIndex = 0, unless otherwise specified
64 		 */
65 		.pcr_index = PCR_0,
66 
67 		/*
68 		 * All EV_NO_ACTION events SHALL set
69 		 * TCG_PCR_EVENT2.eventType = 03h
70 		 */
71 		.event_type = EV_NO_ACTION,
72 
73 		/*
74 		 * All EV_NO_ACTION events SHALL set
75 		 * TCG_PCR_EVENT2.digests to all
76 		 * 0x00's for each allocated Hash algorithm
77 		 */
78 		.digests = {
79 			.count = HASH_ALG_COUNT
80 		}
81 };
82 
83 /* Platform's table with platform specific image IDs, names and PCRs */
84 static const image_data_t plat_images_data[] = {
85 	{ BL2_IMAGE_ID, BL2_STRING, PCR_0 },		/* Reserved for BL2 */
86 	{ INVALID_ID, NULL, (unsigned int)(-1) }	/* Terminator */
87 };
88 
89 static const measured_boot_data_t plat_measured_boot_data = {
90 	plat_images_data,
91 	NULL,	/* platform_set_nt_fw_info */
92 	NULL	/* platform_set_tos_fw_info */
93 };
94 
95 /*
96  * Function retuns pointer to platform's measured_boot_data_t structure
97  *
98  * Must be overridden in the platform code
99  */
100 #pragma weak plat_get_measured_boot_data
101 
plat_get_measured_boot_data(void)102 const measured_boot_data_t *plat_get_measured_boot_data(void)
103 {
104 	return &plat_measured_boot_data;
105 }
106 
107 /*
108  * Add TCG_PCR_EVENT2 event
109  *
110  * @param[in] hash	Pointer to hash data of TCG_DIGEST_SIZE bytes
111  * @param[in] image_ptr	Pointer to image_data_t structure
112  * @return:
113  *	0 = success
114  *    < 0 = error code
115  */
add_event2(const uint8_t * hash,const image_data_t * image_ptr)116 static int add_event2(const uint8_t *hash, const image_data_t *image_ptr)
117 {
118 	void *ptr = log_ptr;
119 	uint32_t name_len;
120 	uint32_t size_of_event;
121 
122 	assert(image_ptr != NULL);
123 	assert(image_ptr->name != NULL);
124 
125 	name_len = (uint32_t)strlen(image_ptr->name) + 1U;
126 	size_of_event = name_len + (uint32_t)EVENT2_HDR_SIZE;
127 
128 	/* Check for space in Event Log buffer */
129 	if (((uintptr_t)ptr + size_of_event) > EVENT_LOG_END) {
130 		ERROR("%s(): Event Log is short of memory", __func__);
131 		return -ENOMEM;
132 	}
133 
134 	/*
135 	 * As per TCG specifications, firmware components that are measured
136 	 * into PCR[0] must be logged in the event log using the event type
137 	 * EV_POST_CODE.
138 	 */
139 	/* TCG_PCR_EVENT2.PCRIndex */
140 	((event2_header_t *)ptr)->pcr_index = image_ptr->pcr;
141 
142 	/* TCG_PCR_EVENT2.EventType */
143 	((event2_header_t *)ptr)->event_type = EV_POST_CODE;
144 
145 	/* TCG_PCR_EVENT2.Digests.Count */
146 	ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests);
147 	((tpml_digest_values *)ptr)->count = HASH_ALG_COUNT;
148 
149 	/* TCG_PCR_EVENT2.Digests[] */
150 	ptr = (uint8_t *)((uintptr_t)ptr +
151 			offsetof(tpml_digest_values, digests));
152 
153 	/* TCG_PCR_EVENT2.Digests[].AlgorithmId */
154 	((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
155 
156 	/* TCG_PCR_EVENT2.Digests[].Digest[] */
157 	ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
158 
159 	/* Check for space in Event Log buffer */
160 	if (((uintptr_t)ptr + TCG_DIGEST_SIZE) > EVENT_LOG_END) {
161 		ERROR("%s(): Event Log is short of memory", __func__);
162 		return -ENOMEM;
163 	}
164 
165 	if (hash == NULL) {
166 		/* Get BL2 hash from DTB */
167 		bl2_plat_get_hash(ptr);
168 	} else {
169 		/* Copy digest */
170 		(void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE);
171 	}
172 
173 	/* TCG_PCR_EVENT2.EventSize */
174 	ptr = (uint8_t *)((uintptr_t)ptr + TCG_DIGEST_SIZE);
175 	((event2_data_t *)ptr)->event_size = name_len;
176 
177 	/* Copy event data to TCG_PCR_EVENT2.Event */
178 	(void)memcpy((void *)(((event2_data_t *)ptr)->event),
179 			(const void *)image_ptr->name, name_len);
180 
181 	/* End of event data */
182 	log_ptr = (uint8_t *)((uintptr_t)ptr +
183 			offsetof(event2_data_t, event) + name_len);
184 
185 	return 0;
186 }
187 
188 /*
189  * Init Event Log
190  *
191  * Initialises Event Log by writing Specification ID and
192  * Startup Locality events.
193  */
event_log_init(void)194 void event_log_init(void)
195 {
196 	const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE;
197 	const uint8_t *start_ptr;
198 	void *ptr = event_log;
199 
200 	/* Get pointer to platform's measured_boot_data_t structure */
201 	plat_data_ptr = plat_get_measured_boot_data();
202 
203 	/*
204 	 * Add Specification ID Event first
205 	 *
206 	 * Copy TCG_EfiSpecIDEventStruct structure header
207 	 */
208 	(void)memcpy(ptr, (const void *)&id_event_header,
209 			sizeof(id_event_header));
210 	ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_header));
211 
212 	/* TCG_EfiSpecIdEventAlgorithmSize structure */
213 	((id_event_algorithm_size_t *)ptr)->algorithm_id = TPM_ALG_ID;
214 	((id_event_algorithm_size_t *)ptr)->digest_size = TCG_DIGEST_SIZE;
215 	ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_algorithm_size_t));
216 
217 	/*
218 	 * TCG_EfiSpecIDEventStruct.vendorInfoSize
219 	 * No vendor data
220 	 */
221 	((id_event_struct_data_t *)ptr)->vendor_info_size = 0;
222 	ptr = (uint8_t *)((uintptr_t)ptr +
223 			offsetof(id_event_struct_data_t, vendor_info));
224 	if ((uintptr_t)ptr != ((uintptr_t)event_log + ID_EVENT_SIZE)) {
225 		panic();
226 	}
227 
228 	start_ptr = (uint8_t *)ptr;
229 
230 	/*
231 	 * The Startup Locality event should be placed in the log before
232 	 * any event which extends PCR[0].
233 	 *
234 	 * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
235 	 */
236 
237 	/* Copy Startup Locality Event Header */
238 	(void)memcpy(ptr, (const void *)&locality_event_header,
239 			sizeof(locality_event_header));
240 	ptr = (uint8_t *)((uintptr_t)ptr + sizeof(locality_event_header));
241 
242 	/* TCG_PCR_EVENT2.Digests[].AlgorithmId */
243 	((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
244 
245 	/* TCG_PCR_EVENT2.Digests[].Digest[] */
246 	(void)memset(&((tpmt_ha *)ptr)->digest, 0, TPM_ALG_ID);
247 	ptr = (uint8_t *)((uintptr_t)ptr +
248 			offsetof(tpmt_ha, digest) + TCG_DIGEST_SIZE);
249 
250 	/* TCG_PCR_EVENT2.EventSize */
251 	((event2_data_t *)ptr)->event_size =
252 		(uint32_t)sizeof(startup_locality_event_t);
253 	ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
254 
255 	/* TCG_EfiStartupLocalityEvent.Signature */
256 	(void)memcpy(ptr, (const void *)locality_signature,
257 		sizeof(TCG_STARTUP_LOCALITY_SIGNATURE));
258 
259 	/*
260 	 * TCG_EfiStartupLocalityEvent.StartupLocality = 0:
261 	 * the platform's boot firmware
262 	 */
263 	((startup_locality_event_t *)ptr)->startup_locality = 0U;
264 	ptr = (uint8_t *)((uintptr_t)ptr + sizeof(startup_locality_event_t));
265 	if ((uintptr_t)ptr != ((uintptr_t)start_ptr + LOC_EVENT_SIZE)) {
266 		panic();
267 	}
268 
269 	log_ptr = (uint8_t *)ptr;
270 
271 	/* Add BL2 event */
272 	if (add_event2(NULL, plat_data_ptr->images_data) != 0) {
273 		panic();
274 	}
275 }
276 
277 /*
278  * Calculate and write hash of image, configuration data, etc.
279  * to Event Log.
280  *
281  * @param[in] data_base		Address of data
282  * @param[in] data_size		Size of data
283  * @param[in] data_id		Data ID
284  * @return:
285  *	0 = success
286  *    < 0 = error
287  */
tpm_record_measurement(uintptr_t data_base,uint32_t data_size,uint32_t data_id)288 int tpm_record_measurement(uintptr_t data_base, uint32_t data_size,
289 			   uint32_t data_id)
290 {
291 	const image_data_t *data_ptr = plat_data_ptr->images_data;
292 	unsigned char hash_data[MBEDTLS_MD_MAX_SIZE];
293 	int rc;
294 
295 	/* Check if image_id is supported */
296 	while (data_ptr->id != data_id) {
297 		if ((data_ptr++)->id == INVALID_ID) {
298 			ERROR("%s(): image_id %u not supported\n",
299 				__func__, data_id);
300 			return -EINVAL;
301 		}
302 	}
303 
304 	if (data_id == TOS_FW_CONFIG_ID) {
305 		tos_fw_config_base = data_base;
306 	} else if (data_id == NT_FW_CONFIG_ID) {
307 		nt_fw_config_base = data_base;
308 	} else {
309 		/* No action */
310 	}
311 
312 	/* Calculate hash */
313 	rc = crypto_mod_calc_hash((unsigned int)MBEDTLS_MD_ID,
314 				(void *)data_base, data_size, hash_data);
315 	if (rc != 0) {
316 		return rc;
317 	}
318 
319 	return add_event2(hash_data, data_ptr);
320 }
321 
322 /*
323  * Finalise Event Log
324  *
325  * @param[out] log_addr	Pointer to return Event Log address
326  * @param[out] log_size	Pointer to return Event Log size
327  * @return:
328  *	0 = success
329  *    < 0 = error code
330  */
event_log_finalise(uint8_t ** log_addr,size_t * log_size)331 int event_log_finalise(uint8_t **log_addr, size_t *log_size)
332 {
333 	/* Event Log size */
334 	size_t num_bytes = (uintptr_t)log_ptr - (uintptr_t)event_log;
335 	int rc;
336 
337 	assert(log_addr != NULL);
338 	assert(log_size != NULL);
339 
340 	if (nt_fw_config_base == 0UL) {
341 		ERROR("%s(): %s_FW_CONFIG not loaded\n", __func__, "NT");
342 		return -ENOENT;
343 	}
344 
345 	/*
346 	 * Set Event Log data in NT_FW_CONFIG and
347 	 * get Event Log address in Non-Secure memory
348 	 */
349 	if (plat_data_ptr->set_nt_fw_info != NULL) {
350 
351 		/* Event Log address in Non-Secure memory */
352 		uintptr_t ns_log_addr;
353 
354 		rc = plat_data_ptr->set_nt_fw_info(
355 				nt_fw_config_base,
356 #ifdef SPD_opteed
357 				(uintptr_t)event_log,
358 #endif
359 				num_bytes, &ns_log_addr);
360 		if (rc != 0) {
361 			ERROR("%s(): Unable to update %s_FW_CONFIG\n",
362 						__func__, "NT");
363 			return rc;
364 		}
365 
366 		/* Copy Event Log to Non-secure memory */
367 		(void)memcpy((void *)ns_log_addr, (const void *)event_log,
368 				num_bytes);
369 
370 		/* Ensure that the Event Log is visible in Non-secure memory */
371 		flush_dcache_range(ns_log_addr, num_bytes);
372 
373 		/* Return Event Log address in Non-Secure memory */
374 		*log_addr = (uint8_t *)ns_log_addr;
375 
376 	} else {
377 		INFO("%s(): set_%s_fw_info not set\n", __func__, "nt");
378 
379 		/* Return Event Log address in Secure memory */
380 		*log_addr = event_log;
381 	}
382 
383 	if (tos_fw_config_base != 0UL) {
384 		if (plat_data_ptr->set_tos_fw_info != NULL) {
385 
386 			/* Set Event Log data in TOS_FW_CONFIG */
387 			rc = plat_data_ptr->set_tos_fw_info(
388 						tos_fw_config_base,
389 						(uintptr_t)event_log,
390 						num_bytes);
391 			if (rc != 0) {
392 				ERROR("%s(): Unable to update %s_FW_CONFIG\n",
393 						__func__, "TOS");
394 				return rc;
395 			}
396 		} else {
397 			INFO("%s(): set_%s_fw_info not set\n", __func__, "tos");
398 		}
399 	} else {
400 		INFO("%s(): %s_FW_CONFIG not loaded\n", __func__, "TOS");
401 	}
402 
403 	/* Ensure that the Event Log is visible in Secure memory */
404 	flush_dcache_range((uintptr_t)event_log, num_bytes);
405 
406 	/* Return Event Log size */
407 	*log_size = num_bytes;
408 
409 	return 0;
410 }
411