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 <string.h>
9 
10 #include <common/debug.h>
11 #include <drivers/measured_boot/event_log.h>
12 
13 #if LOG_LEVEL >= EVENT_LOG_LEVEL
14 
15 /*
16  * Print TCG_EfiSpecIDEventStruct
17  *
18  * @param[in/out] log_addr	Pointer to Event Log
19  * @param[in/out] log_size	Pointer to Event Log size
20  */
id_event_print(uint8_t ** log_addr,size_t * log_size)21 static void id_event_print(uint8_t **log_addr, size_t *log_size)
22 {
23 	unsigned int i;
24 	uint8_t info_size, *info_size_ptr;
25 	void *ptr = *log_addr;
26 	id_event_headers_t *event = (id_event_headers_t *)ptr;
27 	id_event_algorithm_size_t *alg_ptr;
28 	uint32_t event_size, number_of_algorithms;
29 	size_t digest_len;
30 #if ENABLE_ASSERTIONS
31 	const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
32 	bool valid = true;
33 #endif
34 
35 	assert(*log_size >= sizeof(id_event_headers_t));
36 
37 	/* The fields of the event log header are defined to be PCRIndex of 0,
38 	 * EventType of EV_NO_ACTION, Digest of 20 bytes of 0, and
39 	 * Event content defined as TCG_EfiSpecIDEventStruct.
40 	 */
41 	LOG_EVENT("TCG_EfiSpecIDEvent:\n");
42 	LOG_EVENT("  PCRIndex           : %u\n", event->header.pcr_index);
43 	assert(event->header.pcr_index == (uint32_t)PCR_0);
44 
45 	LOG_EVENT("  EventType          : %u\n", event->header.event_type);
46 	assert(event->header.event_type == EV_NO_ACTION);
47 
48 	LOG_EVENT("  Digest             :");
49 	for (i = 0U; i < sizeof(event->header.digest); ++i) {
50 		uint8_t val = event->header.digest[i];
51 
52 		(void)printf(" %02x", val);
53 		if ((i & U(0xF)) == 0U) {
54 			(void)printf("\n");
55 			LOG_EVENT("\t\t      :");
56 		}
57 #if ENABLE_ASSERTIONS
58 		if (val != 0U) {
59 			valid = false;
60 		}
61 #endif
62 	}
63 	if ((i & U(0xF)) != 0U) {
64 		(void)printf("\n");
65 	}
66 
67 	assert(valid);
68 
69 	/* EventSize */
70 	event_size = event->header.event_size;
71 	LOG_EVENT("  EventSize          : %u\n", event_size);
72 
73 	LOG_EVENT("  Signature          : %s\n",
74 			event->struct_header.signature);
75 	LOG_EVENT("  PlatformClass      : %u\n",
76 			event->struct_header.platform_class);
77 	LOG_EVENT("  SpecVersion        : %u.%u.%u\n",
78 			event->struct_header.spec_version_major,
79 			event->struct_header.spec_version_minor,
80 			event->struct_header.spec_errata);
81 	LOG_EVENT("  UintnSize          : %u\n",
82 			event->struct_header.uintn_size);
83 
84 	/* NumberOfAlgorithms */
85 	number_of_algorithms = event->struct_header.number_of_algorithms;
86 	LOG_EVENT("  NumberOfAlgorithms : %u\n", number_of_algorithms);
87 
88 	/* Address of DigestSizes[] */
89 	alg_ptr = event->struct_header.digest_size;
90 
91 	/* Size of DigestSizes[] */
92 	digest_len = number_of_algorithms * sizeof(id_event_algorithm_size_t);
93 	assert(((uintptr_t)alg_ptr + digest_len) <= (uintptr_t)end_ptr);
94 
95 	LOG_EVENT("  DigestSizes        :\n");
96 	for (i = 0U; i < number_of_algorithms; ++i) {
97 		LOG_EVENT("    #%u AlgorithmId   : SHA", i);
98 		uint16_t algorithm_id = alg_ptr[i].algorithm_id;
99 
100 		switch (algorithm_id) {
101 		case TPM_ALG_SHA256:
102 			(void)printf("256\n");
103 			break;
104 		case TPM_ALG_SHA384:
105 			(void)printf("384\n");
106 			break;
107 		case TPM_ALG_SHA512:
108 			(void)printf("512\n");
109 			break;
110 		default:
111 			(void)printf("?\n");
112 			ERROR("Algorithm 0x%x not found\n", algorithm_id);
113 			assert(false);
114 		}
115 
116 		LOG_EVENT("       DigestSize    : %u\n",
117 					alg_ptr[i].digest_size);
118 	}
119 
120 	/* Address of VendorInfoSize */
121 	info_size_ptr = (uint8_t *)((uintptr_t)alg_ptr + digest_len);
122 	assert((uintptr_t)info_size_ptr <= (uintptr_t)end_ptr);
123 
124 	info_size = *info_size_ptr++;
125 	LOG_EVENT("  VendorInfoSize     : %u\n", info_size);
126 
127 	/* Check VendorInfo end address */
128 	assert(((uintptr_t)info_size_ptr + info_size) <= (uintptr_t)end_ptr);
129 
130 	/* Check EventSize */
131 	assert(event_size == (sizeof(id_event_struct_t) +
132 				digest_len + info_size));
133 	if (info_size != 0U) {
134 		LOG_EVENT("  VendorInfo         :");
135 		for (i = 0U; i < info_size; ++i) {
136 			(void)printf(" %02x", *info_size_ptr++);
137 		}
138 		(void)printf("\n");
139 	}
140 
141 	*log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr;
142 	*log_addr = info_size_ptr;
143 }
144 
145 /*
146  * Print TCG_PCR_EVENT2
147  *
148  * @param[in/out] log_addr	Pointer to Event Log
149  * @param[in/out] log_size	Pointer to Event Log size
150  */
event2_print(uint8_t ** log_addr,size_t * log_size)151 static void event2_print(uint8_t **log_addr, size_t *log_size)
152 {
153 	uint32_t event_size, count;
154 	size_t sha_size, digests_size = 0U;
155 	void *ptr = *log_addr;
156 #if ENABLE_ASSERTIONS
157 	const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
158 #endif
159 
160 	assert(*log_size >= sizeof(event2_header_t));
161 
162 	LOG_EVENT("PCR_Event2:\n");
163 	LOG_EVENT("  PCRIndex           : %u\n",
164 			((event2_header_t *)ptr)->pcr_index);
165 	LOG_EVENT("  EventType          : %u\n",
166 			((event2_header_t *)ptr)->event_type);
167 
168 	count = ((event2_header_t *)ptr)->digests.count;
169 	LOG_EVENT("  Digests Count      : %u\n", count);
170 
171 	/* Address of TCG_PCR_EVENT2.Digests[] */
172 	ptr = (uint8_t *)ptr + sizeof(event2_header_t);
173 	assert(((uintptr_t)ptr <= (uintptr_t)end_ptr) && (count != 0U));
174 
175 	for (unsigned int i = 0U; i < count; ++i) {
176 		/* Check AlgorithmId address */
177 		assert(((uintptr_t)ptr +
178 			offsetof(tpmt_ha, digest)) <= (uintptr_t)end_ptr);
179 
180 		LOG_EVENT("    #%u AlgorithmId   : SHA", i);
181 		switch (((tpmt_ha *)ptr)->algorithm_id) {
182 		case TPM_ALG_SHA256:
183 			sha_size = SHA256_DIGEST_SIZE;
184 			(void)printf("256\n");
185 			break;
186 		case TPM_ALG_SHA384:
187 			sha_size = SHA384_DIGEST_SIZE;
188 			(void)printf("384\n");
189 			break;
190 		case TPM_ALG_SHA512:
191 			sha_size = SHA512_DIGEST_SIZE;
192 			(void)printf("512\n");
193 			break;
194 		default:
195 			(void)printf("?\n");
196 			ERROR("Algorithm 0x%x not found\n",
197 				((tpmt_ha *)ptr)->algorithm_id);
198 			panic();
199 		}
200 
201 		/* End of Digest[] */
202 		ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
203 		assert(((uintptr_t)ptr + sha_size) <= (uintptr_t)end_ptr);
204 
205 		/* Total size of all digests */
206 		digests_size += sha_size;
207 
208 		LOG_EVENT("       Digest        :");
209 		for (unsigned int j = 0U; j < sha_size; ++j) {
210 			(void)printf(" %02x", *(uint8_t *)ptr++);
211 			if ((j & U(0xF)) == U(0xF)) {
212 				(void)printf("\n");
213 				if (j < (sha_size - 1U)) {
214 					LOG_EVENT("\t\t      :");
215 				}
216 			}
217 		}
218 	}
219 
220 	/* TCG_PCR_EVENT2.EventSize */
221 	assert(((uintptr_t)ptr + offsetof(event2_data_t, event)) <= (uintptr_t)end_ptr);
222 
223 	event_size = ((event2_data_t *)ptr)->event_size;
224 	LOG_EVENT("  EventSize          : %u\n", event_size);
225 
226 	/* Address of TCG_PCR_EVENT2.Event[EventSize] */
227 	ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
228 
229 	/* End of TCG_PCR_EVENT2.Event[EventSize] */
230 	assert(((uintptr_t)ptr + event_size) <= (uintptr_t)end_ptr);
231 
232 	if ((event_size == sizeof(startup_locality_event_t)) &&
233 	     (strcmp((const char *)ptr, TCG_STARTUP_LOCALITY_SIGNATURE) == 0)) {
234 		LOG_EVENT("  Signature          : %s\n",
235 			((startup_locality_event_t *)ptr)->signature);
236 		LOG_EVENT("  StartupLocality    : %u\n",
237 			((startup_locality_event_t *)ptr)->startup_locality);
238 	} else {
239 		LOG_EVENT("  Event              : %s\n", (uint8_t *)ptr);
240 	}
241 
242 	*log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr;
243 	*log_addr = (uint8_t *)ptr + event_size;
244 }
245 #endif	/* LOG_LEVEL >= EVENT_LOG_LEVEL */
246 
247 /*
248  * Print Event Log
249  *
250  * @param[in]	log_addr	Pointer to Event Log
251  * @param[in]	log_size	Event Log size
252  */
dump_event_log(uint8_t * log_addr,size_t log_size)253 void dump_event_log(uint8_t *log_addr, size_t log_size)
254 {
255 #if LOG_LEVEL >= EVENT_LOG_LEVEL
256 	assert(log_addr != NULL);
257 
258 	/* Print TCG_EfiSpecIDEvent */
259 	id_event_print(&log_addr, &log_size);
260 
261 	while (log_size != 0U) {
262 		event2_print(&log_addr, &log_size);
263 	}
264 #endif
265 }
266