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