xref: /aosp_15_r20/external/coreboot/src/vendorcode/eltan/security/mboot/mboot.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <mboot.h>
4 #include <assert.h>
5 #include <build.h>
6 #include <vb2_api.h>
7 #include <board_mboot.h>
8 
9 /*
10  * Get the list of currently active PCR banks in TPM.
11  *
12  * @retval A map of active PCR banks.
13  */
tpm2_get_active_pcrs(void)14 EFI_TCG2_EVENT_ALGORITHM_BITMAP tpm2_get_active_pcrs(void)
15 {
16 	tpm_result_t rc;
17 	TPML_PCR_SELECTION Pcrs;
18 	EFI_TCG2_EVENT_ALGORITHM_BITMAP tpmHashAlgorithmBitmap = 0;
19 	uint32_t activePcrBanks = 0;
20 	uint32_t index;
21 
22 	rc = tpm2_get_capability_pcrs(&Pcrs);
23 	if (rc != TPM_SUCCESS) {
24 		tpmHashAlgorithmBitmap = EFI_TCG2_BOOT_HASH_ALG_SHA1;
25 		activePcrBanks = EFI_TCG2_BOOT_HASH_ALG_SHA1;
26 	} else {
27 		for (index = 0; index < Pcrs.count; index++) {
28 			switch (Pcrs.pcrSelections[index].hash) {
29 			case TPM_ALG_SHA1:
30 				tpmHashAlgorithmBitmap |=
31 					EFI_TCG2_BOOT_HASH_ALG_SHA1;
32 				if (!is_zero_buffer(Pcrs.pcrSelections[index].pcrSelect,
33 				  Pcrs.pcrSelections[index].sizeofSelect))
34 					activePcrBanks |=
35 						 EFI_TCG2_BOOT_HASH_ALG_SHA1;
36 				break;
37 			case TPM_ALG_SHA256:
38 				tpmHashAlgorithmBitmap |=
39 					EFI_TCG2_BOOT_HASH_ALG_SHA256;
40 				if (!is_zero_buffer(Pcrs.pcrSelections[index].pcrSelect,
41 				  Pcrs.pcrSelections[index].sizeofSelect))
42 					activePcrBanks |=
43 						EFI_TCG2_BOOT_HASH_ALG_SHA256;
44 				break;
45 			case TPM_ALG_SHA384:
46 			case TPM_ALG_SHA512:
47 			case TPM_ALG_SM3_256:
48 			default:
49 				printk(BIOS_DEBUG, "%s: unsupported algorithm "
50 					"reported - %#x\n", __func__,
51 					Pcrs.pcrSelections[index].hash);
52 				break;
53 			}
54 		}
55 	}
56 	printk(BIOS_DEBUG, "Tcg2 Capability values from TPM\n");
57 	printk(BIOS_DEBUG, "tpmHashAlgorithmBitmap - 0x%08x\n",
58 		tpmHashAlgorithmBitmap);
59 	printk(BIOS_DEBUG, "activePcrBanks         - 0x%08x\n",
60 		activePcrBanks);
61 
62 	return activePcrBanks;
63 }
64 
65 /*
66  * tpm2_get_capability_pcrs
67  *
68  * Return the TPM PCR information.
69  *
70  * This function parses the data got from tlcl2_get_capability and returns the
71  * PcrSelection.
72  *
73  * @param[out] Pcrs		The Pcr Selection
74  *
75  * @retval TPM_SUCCESS		Operation completed successfully.
76  * @retval TPM_IOERROR		The command was unsuccessful.
77  */
tpm2_get_capability_pcrs(TPML_PCR_SELECTION * Pcrs)78 tpm_result_t tpm2_get_capability_pcrs(TPML_PCR_SELECTION *Pcrs)
79 {
80 	TPMS_CAPABILITY_DATA TpmCap;
81 	tpm_result_t rc;
82 	int index;
83 
84 	rc = tlcl2_get_capability(TPM_CAP_PCRS, 0, 1, &TpmCap);
85 	if (rc == TPM_SUCCESS) {
86 		Pcrs->count = TpmCap.data.assignedPCR.count;
87 		printk(BIOS_DEBUG, "Pcrs->count = %d\n", Pcrs->count);
88 		for (index = 0; index < Pcrs->count; index++) {
89 			Pcrs->pcrSelections[index].hash =
90 				swab16(TpmCap.data.assignedPCR.pcrSelections[index].hash);
91 			printk(BIOS_DEBUG, "Pcrs->pcrSelections[%d].hash = %#x\n", index,
92 			       Pcrs->pcrSelections[index].hash);
93 			Pcrs->pcrSelections[index].sizeofSelect =
94 				TpmCap.data.assignedPCR.pcrSelections[index].sizeofSelect;
95 			memcpy(Pcrs->pcrSelections[index].pcrSelect,
96 				TpmCap.data.assignedPCR.pcrSelections[index].pcrSelect,
97 				Pcrs->pcrSelections[index].sizeofSelect);
98 		}
99 	}
100 	return rc;
101 }
102 
103 /*
104  * mboot_hash_extend_log
105  *
106  * Calculates the hash over the data and extends it in active PCR banks and
107  * then logs them in the event log.
108  *
109  * @param[in] flags		flags associated with hash data.
110  * @param[in] hashData		data to be hashed.
111  * @param[in] hashDataLen	length of the data to be hashed.
112  * @param[in] newEventHdr	event header in TCG_PCR_EVENT2 format.
113  * @param[in] eventLog		description of the event.
114  *
115  * @retval TPM_SUCCESS		Operation completed successfully.
116  * @retval TPM_IOERROR		Unexpected device behavior.
117  */
mboot_hash_extend_log(uint64_t flags,uint8_t * hashData,uint32_t hashDataLen,TCG_PCR_EVENT2_HDR * newEventHdr,uint8_t * eventLog)118 tpm_result_t mboot_hash_extend_log(uint64_t flags, uint8_t *hashData, uint32_t hashDataLen,
119 	TCG_PCR_EVENT2_HDR *newEventHdr, uint8_t *eventLog)
120 {
121 	TPMT_HA *digest = NULL;
122 
123 	printk(BIOS_DEBUG, "%s: Hash Data Length: %zu bytes\n", __func__, (size_t)hashDataLen);
124 
125 	/* Generate SHA256 */
126 	digest = &(newEventHdr->digest.digests[0]);
127 	if (flags & MBOOT_HASH_PROVIDED) {
128 		/* The hash is provided as data */
129 		memcpy(digest->digest.sha256, (void *)hashData, hashDataLen);
130 	} else {
131 		struct vb2_hash tmp;
132 		if (vb2_hash_calculate(false, hashData, hashDataLen, VB2_HASH_SHA256, &tmp))
133 			return TPM_IOERROR;
134 		memcpy(digest->digest.sha256, tmp.sha256, sizeof(tmp.sha256));
135 	}
136 
137 	printk(BIOS_DEBUG, "%s: SHA256 Hash Digest:\n", __func__);
138 	mboot_print_buffer(digest->digest.sha256, VB2_SHA256_DIGEST_SIZE);
139 
140 	return (tlcl_extend(newEventHdr->pcrIndex, (uint8_t *)&(newEventHdr->digest),
141 			    VB2_HASH_SHA256));
142 }
143 
144 /*
145  * invalidate_pcrs
146  *
147  * Invalidate PCRs 0-7 with extending 1 after tpm failure.
148  */
invalidate_pcrs(void)149 void invalidate_pcrs(void)
150 {
151 	int pcr;
152 	tpm_result_t rc;
153 
154 	TCG_PCR_EVENT2_HDR tcgEventHdr;
155 	uint8_t invalidate = 1;
156 
157 	for (pcr = 0; pcr < 8; pcr++) {
158 		printk(BIOS_DEBUG, "%s: Invalidating PCR %d\n", __func__, pcr);
159 		memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
160 		tcgEventHdr.pcrIndex  = pcr;
161 		tcgEventHdr.eventType = EV_NO_ACTION;
162 		tcgEventHdr.eventSize = (uint32_t) sizeof(invalidate);
163 
164 		rc = mboot_hash_extend_log(0, (uint8_t *)&invalidate,
165 					       tcgEventHdr.eventSize, &tcgEventHdr,
166 					       (uint8_t *)"Invalidate PCR");
167 		if (rc != TPM_SUCCESS)
168 			printk(BIOS_DEBUG, "%s: invalidating pcr %d returned"
169 				" %#x\n", __func__, pcr, rc);
170 	}
171 }
172 
173 /*
174  * is_zero_buffer
175  *
176  * Check if buffer is all zero.
177  *
178  * @param[in] buffer   Buffer to be checked.
179  * @param[in] size     Size of buffer to be checked.
180  *
181  * @retval TRUE  buffer is all zero.
182  * @retval FALSE buffer is not all zero.
183  */
is_zero_buffer(void * buffer,unsigned int size)184 int is_zero_buffer(void *buffer, unsigned int size)
185 {
186 	uint8_t *ptr;
187 
188 	ptr = buffer;
189 	while (size--) {
190 		if (*(ptr++) != 0)
191 			return false;
192 	}
193 	return true;
194 }
195 
196 /*
197  * Prints command or response buffer for debugging purposes.
198  *
199  * @param[in] Buffer     Buffer to print.
200  * @param[in] BufferSize Buffer data length.
201  *
202  * @retval  None
203  */
mboot_print_buffer(uint8_t * buffer,uint32_t bufferSize)204 void mboot_print_buffer(uint8_t *buffer, uint32_t bufferSize)
205 {
206 	uint32_t index;
207 
208 	printk(BIOS_DEBUG, "Buffer Address: 0x%08x, Size: 0x%08x, Value:\n",
209 		(unsigned int)*buffer, bufferSize);
210 	for (index = 0; index < bufferSize; index++) {
211 		printk(BIOS_DEBUG, "%02x ", *(buffer + index));
212 		if ((index+1) % 16 == 0)
213 			printk(BIOS_DEBUG, "\n");
214 	}
215 	printk(BIOS_DEBUG, "\n");
216 }
217 
218 /*
219  * measures and logs the specified cbfs file.
220  *
221  * @param[in] name		name of the cbfs file to measure
222  * @param[in] type		data type of the cbfs file.
223  * @param[in] pcr		pcr to extend.
224  * @param[in] evenType		tcg event type.
225  * @param[in] event_msg		description of the event.
226  *
227  * @retval TPM_SUCCESS		Operation completed successfully.
228  * @retval TPM_IOERROR		Unexpected device behavior.
229  */
mb_measure_log_worker(const char * name,uint32_t type,uint32_t pcr,TCG_EVENTTYPE eventType,const char * event_msg)230 tpm_result_t mb_measure_log_worker(const char *name, uint32_t type, uint32_t pcr,
231 			  TCG_EVENTTYPE eventType, const char *event_msg)
232 {
233 	TCG_PCR_EVENT2_HDR tcgEventHdr;
234 	uint8_t *base;
235 	size_t size;
236 
237 	printk(BIOS_DEBUG, "%s: Measure %s\n", __func__, name);
238 	base = cbfs_map(name, &size);
239 
240 	if (base == NULL) {
241 		printk(BIOS_DEBUG, "%s: CBFS locate fail: %s\n", __func__, name);
242 		return TPM_IOERROR;
243 	}
244 
245 	printk(BIOS_DEBUG, "%s: CBFS locate success: %s\n", __func__, name);
246 	memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
247 	tcgEventHdr.pcrIndex  = pcr;
248 	tcgEventHdr.eventType = eventType;
249 	if (event_msg)
250 		tcgEventHdr.eventSize = (uint32_t) strlen(event_msg);
251 
252 	return mboot_hash_extend_log(0, base, size, &tcgEventHdr, (uint8_t *)event_msg);
253 }
254 
255 /*
256  * Called from early romstage
257  *
258  *mb_entry
259  *
260  * initializes measured boot mechanism, initializes the tpm library and starts the tpm called
261  * by mb_measure
262  *
263  * The function can be overridden at the mainboard level my simply creating a function with the
264  * same name there.
265  *
266  * @param[in] wake_from_s3	1 if we are waking from S3, 0 standard boot
267  *
268  * @retval TPM_SUCCESS		Operation completed successfully.
269  * @retval TPM_IOERROR		Unexpected device behavior.
270 **/
271 
mb_entry(int wake_from_s3)272 __weak tpm_result_t mb_entry(int wake_from_s3)
273 {
274 	tpm_result_t rc;
275 
276 	/* Initialize TPM driver. */
277 	printk(BIOS_DEBUG, "%s: tlcl_lib_init\n", __func__);
278 	rc = tlcl_lib_init();
279 	if (rc != TPM_SUCCESS) {
280 		printk(BIOS_ERR, "%s: TPM driver initialization failed with error %#x.\n",
281 			__func__, rc);
282 		return rc;
283 	}
284 
285 	if (wake_from_s3) {
286 		printk(BIOS_DEBUG, "%s: tlcl_resume\n", __func__);
287 		rc = tlcl_resume();
288 	} else {
289 		printk(BIOS_DEBUG, "%s: tlcl_startup\n", __func__);
290 		rc = tlcl_startup();
291 	}
292 
293 	if (rc)
294 		printk(BIOS_ERR, "%s: StartUp failed %#x!\n", __func__, rc);
295 
296 	return rc;
297 }
298 
299 /*
300  *
301  * mb_measure
302  *
303  * initial call to the measured boot mechanism, initializes the
304  * tpm library, starts the tpm and performs the measurements defined by
305  * the coreboot platform.
306  *
307  * The pcrs will be invalidated if the measurement fails
308  *
309  * The function can be overridden at the mainboard level my simply creating a
310  * function with the same name there.
311  *
312  * @param[in] wake_from_s3	1 if we are waking from S3, 0 standard boot
313  *
314  * @retval TPM_SUCCESS		Operation completed successfully.
315  * @retval TPM_IOERROR		Unexpected device behavior.
316  */
317 
mb_measure(int wake_from_s3)318 __weak tpm_result_t mb_measure(int wake_from_s3)
319 {
320 	tpm_result_t rc;
321 
322 	rc = mb_entry(wake_from_s3);
323 	if (rc == TPM_SUCCESS) {
324 		printk(BIOS_DEBUG, "%s: StartUp, successful!\n", __func__);
325 		rc = mb_measure_log_start();
326 		if (rc == TPM_SUCCESS) {
327 			printk(BIOS_DEBUG, "%s: Measuring, successful!\n", __func__);
328 		} else {
329 			invalidate_pcrs();
330 			printk(BIOS_ERR, "%s: Measuring returned %#x unsuccessful! PCRs invalidated.\n",
331 			       __func__, rc);
332 		}
333 	} else {
334 		invalidate_pcrs();
335 		printk(BIOS_ERR, "%s: StartUp returned %#x, unsuccessful! PCRs invalidated.\n", __func__,
336 		       rc);
337 	}
338 	return rc;
339 }
340 
341 /*
342  *
343  * mb_measure_log_start
344  *
345  * performs the measurements defined by the board routines.
346  *
347  * The logging is defined by the mb_log_list structure
348  *
349  * These items need to be defined in the mainboard part of the mboot
350  * implementation
351  *
352  * The function can be overridden at the mainboard level my simply creating a
353  * function with the same name there.
354  *
355  * @param[in]  none
356  *
357  * @retval TPM_SUCCESS		Operation completed successfully.
358  * @retval TPM_IOERROR		Unexpected device behavior.
359  */
mb_measure_log_start(void)360 __weak tpm_result_t mb_measure_log_start(void)
361 {
362 	tpm_result_t rc;
363 	uint32_t i;
364 
365 	if ((tpm2_get_active_pcrs() & EFI_TCG2_BOOT_HASH_ALG_SHA256) == 0x0) {
366 		printk(BIOS_DEBUG, "%s: SHA256 PCR Bank not active in TPM.\n",
367 			__func__);
368 		return TPM_IOERROR;
369 	}
370 
371 	rc = mb_crtm();
372 	if (rc) {
373 		printk(BIOS_DEBUG, "%s: Fail! CRTM Version can't be measured."
374 			" Received error %#x, ABORTING!!!\n", __func__, rc);
375 		return rc;
376 	}
377 	printk(BIOS_DEBUG, "%s: Success! CRTM Version measured.\n", __func__);
378 
379 	/* Log the items defined by the mainboard */
380 	for (i = 0; i < ARRAY_SIZE(mb_log_list); i++) {
381 		rc = mb_measure_log_worker(
382 				mb_log_list[i].cbfs_name,
383 				mb_log_list[i].cbfs_type, mb_log_list[i].pcr,
384 				mb_log_list[i].eventType,
385 				mb_log_list[i].event_msg);
386 		if (rc != TPM_SUCCESS) {
387 			printk(BIOS_DEBUG, "%s: Fail! %s can't be measured."
388 				"ABORTING!!!\n", __func__,
389 				mb_log_list[i].cbfs_name);
390 			return rc;
391 		}
392 		printk(BIOS_DEBUG, "%s: Success! %s measured to pcr"
393 			"%d.\n", __func__, mb_log_list[i].cbfs_name,
394 			mb_log_list[i].pcr);
395 	}
396 	return rc;
397 }
398 
399 static const uint8_t crtm_version[] =
400 	CONFIG_VENDORCODE_ELTAN_CRTM_VERSION_STRING\
401 	COREBOOT_VERSION COREBOOT_EXTRA_VERSION " " COREBOOT_BUILD;
402 
403 /*
404  *
405  * mb_crtm
406  *
407  * measures the crtm version. this consists of a string than can be
408  * defined using make menuconfig and automatically generated version
409  * information.
410  *
411  * The function can be overridden at the mainboard level my simply creating a
412  * function with the same name there.
413  *
414  * @retval TPM_SUCCESS		Operation completed successfully.
415  * @retval TPM_IOERROR		Unexpected device behavior.
416 **/
mb_crtm(void)417 __weak tpm_result_t mb_crtm(void)
418 {
419 	tpm_result_t rc;
420 	TCG_PCR_EVENT2_HDR tcgEventHdr;
421 	uint8_t hash[VB2_SHA256_DIGEST_SIZE];
422 	uint8_t *msgPtr;
423 
424 	/* Use FirmwareVersion string to represent CRTM version. */
425 	printk(BIOS_DEBUG, "%s: Measure CRTM Version\n", __func__);
426 	memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
427 	tcgEventHdr.pcrIndex = MBOOT_PCR_INDEX_0;
428 	tcgEventHdr.eventType = EV_S_CRTM_VERSION;
429 	tcgEventHdr.eventSize = sizeof(crtm_version);
430 	printk(BIOS_DEBUG, "%s: EventSize - %u\n", __func__,
431 		tcgEventHdr.eventSize);
432 
433 	rc = mboot_hash_extend_log(0, (uint8_t *)crtm_version, tcgEventHdr.eventSize,
434 				       &tcgEventHdr, (uint8_t *)crtm_version);
435 	if (rc) {
436 		printk(BIOS_DEBUG, "Measure CRTM Version returned %#x\n", rc);
437 		return rc;
438 	}
439 
440 	rc = get_intel_me_hash(hash);
441 	if (rc) {
442 		printk(BIOS_DEBUG, "get_intel_me_hash returned %#x\n", rc);
443 		rc = TPM_IOERROR;
444 		return rc;
445 	}
446 
447 	/* Add the me hash */
448 	printk(BIOS_DEBUG, "%s: Add the hash returned by the ME\n",
449 		__func__);
450 	memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
451 	tcgEventHdr.pcrIndex  = MBOOT_PCR_INDEX_0;
452 	tcgEventHdr.eventType = EV_S_CRTM_CONTENTS;
453 
454 	msgPtr = NULL;
455 	tcgEventHdr.eventSize = 0;
456 	rc = mboot_hash_extend_log(MBOOT_HASH_PROVIDED, hash, sizeof(hash), &tcgEventHdr,
457 				       msgPtr);
458 	if (rc)
459 		printk(BIOS_DEBUG, "Add ME hash returned %#x\n", rc);
460 
461 	return rc;
462 }
463