1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright (c) 2022, Linaro Limited
4  */
5 
6 #include <compiler.h>
7 #include <drivers/tpm2_chip.h>
8 #include <initcall.h>
9 #include <io.h>
10 #include <kernel/tcg.h>
11 #include <kernel/tpm.h>
12 #include <malloc.h>
13 #include <string.h>
14 #include <tpm2.h>
15 #include <trace.h>
16 
17 static struct tcg_pcr_ops *pcr_provider;
18 
tcg_get_pcr_info(uint32_t * selection_mask,uint32_t * active_mask,uint32_t * num_pcr)19 static TEE_Result tcg_get_pcr_info(uint32_t *selection_mask,
20 				   uint32_t *active_mask, uint32_t *num_pcr)
21 {
22 	if (!pcr_provider || !pcr_provider->pcr_info)
23 		return TEE_ERROR_GENERIC;
24 
25 	return pcr_provider->pcr_info(selection_mask, active_mask, num_pcr);
26 }
27 
tcg_pcr_extend(uint32_t pcr_index,struct tpml_digest_values * digest_list)28 static TEE_Result tcg_pcr_extend(uint32_t pcr_index,
29 				 struct tpml_digest_values *digest_list)
30 {
31 	uint32_t i = 0;
32 
33 	if (!pcr_provider || !pcr_provider->pcr_extend)
34 		return TEE_ERROR_GENERIC;
35 
36 	for (i = 0; i < digest_list->count; i++) {
37 		uint32_t alg = digest_list->digests[i].hash_alg;
38 		uint8_t *digest = (uint8_t *)&digest_list->digests[i].digest;
39 
40 		if (pcr_provider->pcr_extend(pcr_index, alg, digest,
41 					     tpm2_get_alg_len(alg))) {
42 			EMSG("Failed to extend PCR");
43 			return TEE_ERROR_COMMUNICATION;
44 		}
45 	}
46 
47 	return TEE_SUCCESS;
48 }
49 
tcg_event_final_size(struct tpml_digest_values * digest_list)50 static uint32_t tcg_event_final_size(struct tpml_digest_values *digest_list)
51 {
52 	uint32_t len = 0;
53 	size_t i = 0;
54 
55 	len = offsetof(struct tcg_pcr_event2, digests);
56 	len += offsetof(struct tpml_digest_values, digests);
57 	for (i = 0; i < digest_list->count; i++) {
58 		uint16_t hash_alg = digest_list->digests[i].hash_alg;
59 
60 		len += offsetof(struct tpmt_ha, digest);
61 		len += tpm2_get_alg_len(hash_alg);
62 	}
63 	len += sizeof(uint32_t); /* tcg_pcr_event2 event_size*/
64 
65 	return len;
66 }
67 
68 /*
69  * tcg_parse_event_log_header() -  Parse and verify the event log header fields
70  *
71  * @buffer:			Pointer to the start of the eventlog
72  * @size:			Size of the eventlog
73  * @pos:			Return offset of the next event in buffer right
74  *				after the event header i.e specID
75  *
76  * Return:	status code
77  */
tcg_parse_event_log_header(void * buffer,uint32_t size,uint32_t * pos)78 static TEE_Result tcg_parse_event_log_header(void *buffer, uint32_t size,
79 					     uint32_t *pos)
80 {
81 	struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
82 	uint32_t i = 0;
83 
84 	if (size < sizeof(*event_header))
85 		return TEE_ERROR_BAD_FORMAT;
86 
87 	if (get_unaligned_le32(&event_header->pcr_index) != 0 ||
88 	    get_unaligned_le32(&event_header->event_type) != EV_NO_ACTION)
89 		return TEE_ERROR_BAD_FORMAT;
90 
91 	for (i = 0; i < sizeof(event_header->digest); i++) {
92 		if (event_header->digest[i])
93 			return TEE_ERROR_BAD_FORMAT;
94 	}
95 
96 	*pos += sizeof(*event_header);
97 
98 	return TEE_SUCCESS;
99 }
100 
101 /*
102  * tcg_parse_specid_event() -  Parse and verify the specID Event in the eventlog
103  *
104  * @buffer:		Pointer to the start of the eventlog
105  * @log_size:		Size of the eventlog
106  * @pos:		[in] Offset of specID event in the eventlog buffer
107  *			[out] Return offset of the next event in the buffer
108  *			after the specID
109  * @digest_list:	list of digests in the event
110  *
111  * Return:		status code
112  */
tcg_parse_specid_event(void * buffer,uint32_t log_size,uint32_t * pos,struct tpml_digest_values * digest_list)113 static TEE_Result tcg_parse_specid_event(void *buffer, uint32_t log_size,
114 					 uint32_t *pos,
115 					 struct tpml_digest_values *digest_list)
116 {
117 	struct tcg_efi_spec_id_event *spec_event = NULL;
118 	struct tcg_pcr_event *event_header = buffer;
119 	uint8_t vendor_sz = 0;
120 	uint16_t hash_alg = 0;
121 	uint32_t active = 0;
122 	uint32_t alg_count = 0;
123 	uint32_t i = 0;
124 	uint32_t pcr_count = 0;
125 	uint32_t spec_active = 0;
126 	uint32_t supported = 0;
127 	size_t spec_event_size = 0;
128 
129 	if ((*pos + sizeof(*spec_event)) > log_size)
130 		return TEE_ERROR_BAD_FORMAT;
131 
132 	/* Check specID event data */
133 	spec_event = (struct tcg_efi_spec_id_event *)((uintptr_t)buffer + *pos);
134 	/* Check for signature */
135 	if (memcmp(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
136 		   sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03))) {
137 		EMSG("specID Event: Signature mismatch");
138 		return TEE_ERROR_BAD_FORMAT;
139 	}
140 
141 	if (spec_event->spec_version_minor !=
142 			TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
143 	    spec_event->spec_version_major !=
144 			TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
145 		return TEE_ERROR_BAD_FORMAT;
146 
147 	if (!spec_event->number_of_algorithms) {
148 		EMSG("specID Event: Number of algorithms incorrect");
149 		return TEE_ERROR_BAD_FORMAT;
150 	}
151 
152 	alg_count = spec_event->number_of_algorithms;
153 
154 	if (alg_count > TPM2_NUM_PCR_BANKS)
155 		return TEE_ERROR_BAD_FORMAT;
156 
157 	if (tcg_get_pcr_info(&supported, &active, &pcr_count))
158 		return TEE_ERROR_COMMUNICATION;
159 
160 	digest_list->count = 0;
161 	/*
162 	 * We have to take care that the sequence of algorithms that we record
163 	 * in digest_list matches the sequence in eventlog.
164 	 */
165 	for (i = 0; i < alg_count; i++) {
166 		hash_alg =
167 		  get_unaligned_le16(&spec_event->digest_sizes[i].algorithm_id);
168 
169 		if (!(supported & tpm2_alg_to_tcg_mask(hash_alg))) {
170 			EMSG("specID Event: Unsupported algorithm");
171 			return TEE_ERROR_BAD_FORMAT;
172 		}
173 		digest_list->digests[digest_list->count++].hash_alg = hash_alg;
174 
175 		spec_active |= tpm2_alg_to_tcg_mask(hash_alg);
176 	}
177 
178 	/*
179 	 * TCG specification expects the event log to have hashes for all
180 	 * active PCR's
181 	 */
182 	if (spec_active != active) {
183 		/*
184 		 * Previous stage bootloader should know all the active PCR's
185 		 * and use them in the Eventlog.
186 		 */
187 		EMSG("specID Event: All active hash alg not present");
188 		return TEE_ERROR_BAD_FORMAT;
189 	}
190 
191 	/*
192 	 * the size of the spec event and placement of vendor_info_size
193 	 * depends on supported algorithms
194 	 */
195 	spec_event_size =
196 		offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
197 		alg_count * sizeof(spec_event->digest_sizes[0]);
198 
199 	if (*pos + spec_event_size >= log_size)
200 		return TEE_ERROR_BAD_FORMAT;
201 
202 	vendor_sz = *(uint8_t *)((uintptr_t)buffer + *pos + spec_event_size);
203 
204 	spec_event_size += sizeof(vendor_sz) + vendor_sz;
205 	*pos += spec_event_size;
206 
207 	if (get_unaligned_le32(&event_header->event_size) != spec_event_size) {
208 		EMSG("specID event: header event size mismatch");
209 		/* Right way to handle this can be to call SetActive PCR's */
210 		return TEE_ERROR_BAD_FORMAT;
211 	}
212 
213 	return TEE_SUCCESS;
214 }
215 
216 /*
217  * tcg_parse_event() -  Parse the event in the eventlog
218  *
219  * @buffer:		Pointer to the start of the eventlog
220  * @log_size:		Size of the eventlog
221  * @offset:		[in] Offset of the event in the eventlog buffer
222  *			[out] Return offset of the next event in the buffer
223  * @digest_list:	list of digests in the event.
224  * @pcr			Index of the PCR in the event
225  *
226  * Return:		status code
227  */
tcg_parse_event(void * buffer,uint32_t log_size,uint32_t * offset,struct tpml_digest_values * digest_list,uint32_t * pcr)228 static TEE_Result tcg_parse_event(void *buffer, uint32_t log_size,
229 				  uint32_t *offset,
230 				  struct tpml_digest_values *digest_list,
231 				  uint32_t *pcr)
232 {
233 	struct tcg_pcr_event2 *event = NULL;
234 	uint32_t count = 0, size = 0, event_size = 0;
235 	uint32_t i = 0;
236 	size_t pos = 0;
237 
238 	event_size = tcg_event_final_size(digest_list);
239 	if (*offset >= log_size || *offset + event_size > log_size) {
240 		EMSG("Event exceeds log size");
241 		return TEE_ERROR_BAD_FORMAT;
242 	}
243 
244 	event = (struct tcg_pcr_event2 *)((uintptr_t)buffer + *offset);
245 	*pcr = get_unaligned_le32(&event->pcr_index);
246 
247 	/* get the count */
248 	count = get_unaligned_le32(&event->digests.count);
249 	if (count != digest_list->count)
250 		return TEE_ERROR_BAD_FORMAT;
251 
252 	/*
253 	 * Element 'digests' of type tpml_digest_values in struct tcg_pcr_event2
254 	 * is a list of digests. The count of digests in this list depends on
255 	 * the number of active PCR banks. Further this list contains elements
256 	 * of type tpmt_ha whose size depends on the hash algorithm. So, the
257 	 * position of each of the element in the list (of type tpmt_ha) needs
258 	 * to be calculated.
259 	 */
260 	pos = offsetof(struct tcg_pcr_event2, digests);
261 
262 	/* Position of first element of type tpmt_ha in the digest list */
263 	pos += offsetof(struct tpml_digest_values, digests);
264 
265 	for (i = 0; i < digest_list->count; i++) {
266 		uint16_t alg = 0;
267 		uint16_t hash_alg = digest_list->digests[i].hash_alg;
268 		uint8_t *digest = (uint8_t *)&digest_list->digests[i].digest;
269 
270 		/* Element hash_alg in struct tpmt_ha */
271 		alg = get_unaligned_le16((void *)((uintptr_t)event + pos));
272 
273 		/*
274 		 * The sequence of algorithm must match that from digest list
275 		 * in spec ID event.
276 		 */
277 		if (alg != hash_alg)
278 			return TEE_ERROR_BAD_FORMAT;
279 
280 		pos += offsetof(struct tpmt_ha, digest);
281 		memcpy(digest, (void *)((uintptr_t)event + pos),
282 		       tpm2_get_alg_len(hash_alg));
283 
284 		/* Calculate position of next tpmt_ha element in the event */
285 		pos += tpm2_get_alg_len(hash_alg);
286 	}
287 
288 	/* WARNING - Since size of digest lists can vary, the
289 	 * position of event and event_size elements in tcg_pcr_event2 needs to
290 	 * be determined dynamically.
291 	 */
292 	size = get_unaligned_le32((void *)((uintptr_t)event + pos));
293 	event_size += size;
294 	pos += sizeof(uint32_t); /* tcg_pcr_event2 event_size*/
295 	pos += size;
296 
297 	/* make sure the calculated buffer is what we checked against */
298 	if (pos != event_size)
299 		return TEE_ERROR_BAD_FORMAT;
300 
301 	if (pos > log_size)
302 		return TEE_ERROR_BAD_FORMAT;
303 
304 	*offset += pos;
305 
306 	return TEE_SUCCESS;
307 }
308 
309 /**
310  * tcg_process_fw_eventlog() - Parse the eventlog and extend the PCR's
311  *
312  * Return:	status code
313  */
tcg_process_fw_eventlog(void)314 TEE_Result tcg_process_fw_eventlog(void)
315 {
316 	void *buffer = NULL;
317 	void *tmp = NULL;
318 	uint32_t i = 0, pcr = 0, pos = 0;
319 	size_t digest_list_sz = 0;
320 	size_t sz = TPM2_EVENT_LOG_SIZE;
321 	TEE_Result ret = TEE_SUCCESS;
322 	struct tpml_digest_values *digest_list = NULL;
323 
324 	if (!pcr_provider) {
325 		EMSG("No provider available for PCR's");
326 		return TEE_ERROR_GENERIC;
327 	}
328 
329 	buffer = malloc(TPM2_EVENT_LOG_SIZE);
330 	if (!buffer) {
331 		EMSG("Error allocating mem");
332 		return TEE_ERROR_OUT_OF_MEMORY;
333 	}
334 
335 	ret = tpm_get_event_log(buffer, &sz);
336 	if (ret == TEE_ERROR_SHORT_BUFFER) {
337 		tmp = realloc(buffer, sz);
338 		if (!tmp)
339 			goto out;
340 
341 		buffer = tmp;
342 		/* Try to get the eventlog again */
343 		ret = tpm_get_event_log(buffer, &sz);
344 	}
345 
346 	if (ret)
347 		goto out;
348 
349 	pos = 0;
350 	/* Parse the eventlog to check for its validity */
351 	ret = tcg_parse_event_log_header(buffer, sz, &pos);
352 	if (ret) {
353 		EMSG("Error parsing event log header");
354 		goto out;
355 	}
356 
357 	digest_list_sz = sizeof(struct tpml_digest_values);
358 	digest_list = malloc(digest_list_sz);
359 	if (!digest_list) {
360 		EMSG("Error allocating mem");
361 		ret = TEE_ERROR_OUT_OF_MEMORY;
362 		goto out;
363 	}
364 
365 	/* Populate the digest_list with digest algs by parsing specid event */
366 	ret = tcg_parse_specid_event(buffer, sz, &pos, digest_list);
367 	if (ret) {
368 		EMSG("Error parsing SPEC ID Event");
369 		goto out;
370 	}
371 
372 	while (pos < sz) {
373 		ret = tcg_parse_event(buffer, sz, &pos, digest_list,
374 				      &pcr);
375 		if (ret) {
376 			EMSG("Error parsing event");
377 			goto out;
378 		}
379 
380 		ret = tcg_pcr_extend(pcr, digest_list);
381 		if (ret != TEE_SUCCESS) {
382 			EMSG("Error in extending PCR");
383 			goto out;
384 		}
385 
386 		/* Clear the digest for next event */
387 		for (i = 0; i < digest_list->count; i++) {
388 			uint16_t hash_alg = digest_list->digests[i].hash_alg;
389 			uint8_t *digest =
390 			   (uint8_t *)&digest_list->digests[i].digest;
391 
392 			/* Clear the digest in the digest_list */
393 			memset(digest, 0, tpm2_get_alg_len(hash_alg));
394 		}
395 	}
396 
397 out:
398 	free(digest_list);
399 	free(buffer);
400 
401 	return ret;
402 }
403 
404 boot_final(tcg_process_fw_eventlog);
405 
register_tcg_pcr_provider(struct tcg_pcr_ops * ops)406 TEE_Result register_tcg_pcr_provider(struct tcg_pcr_ops *ops)
407 {
408 	/* Only 1 PCR provider is supported */
409 	if (pcr_provider) {
410 		EMSG("Provider already registered");
411 		return TEE_ERROR_GENERIC;
412 	}
413 
414 	if (!ops)
415 		return TEE_ERROR_GENERIC;
416 
417 	pcr_provider = ops;
418 
419 	return TEE_SUCCESS;
420 }
421