blob: 575c5fc02200a57f8a09600e0b45b5bb741aeffc [file] [log] [blame]
Angel Pons3ef916f2020-04-02 23:49:13 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Frans Hendriks7c82dbc2019-08-01 15:25:19 +02002
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 */
14EFI_TCG2_EVENT_ALGORITHM_BITMAP tpm2_get_active_pcrs(void)
15{
16 int status;
17 TPML_PCR_SELECTION Pcrs;
18 EFI_TCG2_EVENT_ALGORITHM_BITMAP tpmHashAlgorithmBitmap = 0;
19 uint32_t activePcrBanks = 0;
20 uint32_t index;
21
22 status = tpm2_get_capability_pcrs(&Pcrs);
23 if (status != 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 - 0x%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 tlcl_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_E_IOERROR The command was unsuccessful.
77 */
78int tpm2_get_capability_pcrs(TPML_PCR_SELECTION *Pcrs)
79{
80 TPMS_CAPABILITY_DATA TpmCap;
81 int status;
82 int index;
83
84 status = tlcl_get_capability(TPM_CAP_PCRS, 0, 1, &TpmCap);
85 if (status == 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);
Wim Vervoorn653a66f2019-10-30 17:13:40 +010091 printk(BIOS_DEBUG, "Pcrs->pcrSelections[%d].hash = 0x%x\n", index,
92 Pcrs->pcrSelections[index].hash);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +020093 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 status;
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 *
Frans Hendriks0cc619b2019-11-08 09:56:14 +0100109 * @param[in] flags flags associated with hash data.
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200110 * @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.
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200114 *
115 * @retval TPM_SUCCESS Operation completed successfully.
116 * @retval TPM_E_IOERROR Unexpected device behavior.
117 */
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100118int mboot_hash_extend_log(uint64_t flags, uint8_t *hashData, uint32_t hashDataLen,
119 TCG_PCR_EVENT2_HDR *newEventHdr, uint8_t *eventLog)
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200120{
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200121 TPMT_HA *digest = NULL;
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200122
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100123 printk(BIOS_DEBUG, "%s: Hash Data Length: %zu bytes\n", __func__, (size_t)hashDataLen);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200124
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100125 /* 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);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200130 } else {
Wim Vervoorn82100472020-01-27 15:47:44 +0100131 if (vb2_digest_buffer(hashData, hashDataLen, VB2_HASH_SHA256, digest->digest.sha256,
132 VB2_SHA256_DIGEST_SIZE))
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100133 return TPM_E_IOERROR;
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200134 }
135
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100136 printk(BIOS_DEBUG, "%s: SHA256 Hash Digest:\n", __func__);
137 mboot_print_buffer(digest->digest.sha256, VB2_SHA256_DIGEST_SIZE);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200138
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100139 return (tlcl_extend(newEventHdr->pcrIndex, (uint8_t *)&(newEventHdr->digest), NULL));
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200140}
141
142/*
143 * invalidate_pcrs
144 *
145 * Invalidate PCRs 0-7 with extending 1 after tpm failure.
146 */
147void invalidate_pcrs(void)
148{
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100149 int pcr;
150 int status;
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200151
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100152 TCG_PCR_EVENT2_HDR tcgEventHdr;
153 uint8_t invalidate = 1;
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200154
155 for (pcr = 0; pcr < 8; pcr++) {
156 printk(BIOS_DEBUG, "%s: Invalidating PCR %d\n", __func__, pcr);
157 memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
158 tcgEventHdr.pcrIndex = pcr;
159 tcgEventHdr.eventType = EV_NO_ACTION;
160 tcgEventHdr.eventSize = (uint32_t) sizeof(invalidate);
161
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100162 status = mboot_hash_extend_log(0, (uint8_t *)&invalidate,
163 tcgEventHdr.eventSize, &tcgEventHdr,
164 (uint8_t *)"Invalidate PCR");
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200165 if (status != TPM_SUCCESS)
166 printk(BIOS_DEBUG, "%s: invalidating pcr %d returned"
167 " 0x%x\n", __func__, pcr, status);
168 }
169}
170
171/*
172 * is_zero_buffer
173 *
174 * Check if buffer is all zero.
175 *
176 * @param[in] buffer Buffer to be checked.
177 * @param[in] size Size of buffer to be checked.
178 *
179 * @retval TRUE buffer is all zero.
180 * @retval FALSE buffer is not all zero.
181 */
182int is_zero_buffer(void *buffer, unsigned int size)
183{
184 uint8_t *ptr;
185
186 ptr = buffer;
187 while (size--) {
188 if (*(ptr++) != 0)
189 return false;
190 }
191 return true;
192}
193
194/*
195 * Prints command or response buffer for debugging purposes.
196 *
197 * @param[in] Buffer Buffer to print.
198 * @param[in] BufferSize Buffer data length.
199 *
200 * @retval None
201 */
202void mboot_print_buffer(uint8_t *buffer, uint32_t bufferSize)
203{
204 uint32_t index;
205
206 printk(BIOS_DEBUG, "Buffer Address: 0x%08x, Size: 0x%08x, Value:\n",
207 (unsigned int)*buffer, bufferSize);
208 for (index = 0; index < bufferSize; index++) {
209 printk(BIOS_DEBUG, "%02x ", *(buffer + index));
210 if ((index+1) % 16 == 0)
211 printk(BIOS_DEBUG, "\n");
212 }
213 printk(BIOS_DEBUG, "\n");
214}
215
216/*
217 * measures and logs the specified cbfs file.
218 *
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200219 * @param[in] name name of the cbfs file to measure
220 * @param[in] type data type of the cbfs file.
221 * @param[in] pcr pcr to extend.
222 * @param[in] evenType tcg event type.
223 * @param[in] event_msg description of the event.
224 *
225 * @retval TPM_SUCCESS Operation completed successfully.
226 * @retval TPM_E_IOERROR Unexpected device behavior.
227 */
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100228int mb_measure_log_worker(const char *name, uint32_t type, uint32_t pcr,
229 TCG_EVENTTYPE eventType, const char *event_msg)
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200230{
231 int status;
232 TCG_PCR_EVENT2_HDR tcgEventHdr;
233 uint8_t *base;
234 size_t size;
235
236 printk(BIOS_DEBUG, "%s: Measure %s\n", __func__, name);
Julius Werner834b3ec2020-03-04 16:52:08 -0800237 base = cbfs_map(name, &size);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200238
239 if (base == NULL) {
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100240 printk(BIOS_DEBUG, "%s: CBFS locate fail: %s\n", __func__, name);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200241 return VB2_ERROR_READ_FILE_OPEN;
242 }
243
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100244 printk(BIOS_DEBUG, "%s: CBFS locate success: %s\n", __func__, name);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200245 memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
246 tcgEventHdr.pcrIndex = pcr;
247 tcgEventHdr.eventType = eventType;
248 if (event_msg)
249 tcgEventHdr.eventSize = (uint32_t) strlen(event_msg);
250
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100251 status = mboot_hash_extend_log(0, base, size, &tcgEventHdr, (uint8_t *)event_msg);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200252 return status;
253}
254
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200255/*
256 * Called from early romstage
257 *
258 *mb_entry
259 *
Wim Vervoornd1fb78d2019-10-30 17:14:58 +0100260 * initializes measured boot mechanism, initializes the tpm library and starts the tpm called
261 * by mb_measure
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200262 *
Wim Vervoornd1fb78d2019-10-30 17:14:58 +0100263 * The function can be overridden at the mainboard level my simply creating a function with the
264 * same name there.
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200265 *
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_E_IOERROR Unexpected device behavior.
270**/
271
272int __attribute__((weak)) mb_entry(int wake_from_s3)
273{
274 int status;
275
276 /* Initialize TPM driver. */
277 printk(BIOS_DEBUG, "%s: tlcl_lib_init\n", __func__);
278 if (tlcl_lib_init() != VB2_SUCCESS) {
Wim Vervoornd1fb78d2019-10-30 17:14:58 +0100279 printk(BIOS_ERR, "%s: TPM driver initialization failed.\n", __func__);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200280 return TPM_E_IOERROR;
281 }
282
283 if (wake_from_s3) {
284 printk(BIOS_DEBUG, "%s: tlcl_resume\n", __func__);
285 status = tlcl_resume();
286 } else {
287 printk(BIOS_DEBUG, "%s: tlcl_startup\n", __func__);
288 status = tlcl_startup();
289 }
290
291 if (status)
Wim Vervoornd1fb78d2019-10-30 17:14:58 +0100292 printk(BIOS_ERR, "%s: StartUp failed 0x%x!\n", __func__, status);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200293
294 return status;
295}
296
297/*
298 *
299 * mb_measure
300 *
301 * initial call to the measured boot mechanism, initializes the
302 * tpm library, starts the tpm and performs the measurements defined by
303 * the coreboot platform.
304 *
305 * The pcrs will be invalidated if the measurement fails
306 *
307 * The function can be overridden at the mainboard level my simply creating a
308 * function with the same name there.
309 *
310 * @param[in] wake_from_s3 1 if we are waking from S3, 0 standard boot
311 *
312 * @retval TPM_SUCCESS Operation completed successfully.
313 * @retval TPM_E_IOERROR Unexpected device behavior.
314 */
315
316int __attribute__((weak))mb_measure(int wake_from_s3)
317{
318 uint32_t status;
319
320 status = mb_entry(wake_from_s3);
321 if (status == TPM_SUCCESS) {
322 printk(BIOS_DEBUG, "%s: StartUp, successful!\n", __func__);
323 status = mb_measure_log_start();
324 if (status == TPM_SUCCESS) {
Wim Vervoornd1fb78d2019-10-30 17:14:58 +0100325 printk(BIOS_DEBUG, "%s: Measuring, successful!\n", __func__);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200326 } else {
327 invalidate_pcrs();
Wim Vervoornd1fb78d2019-10-30 17:14:58 +0100328 printk(BIOS_ERR, "%s: Measuring returned 0x%x unsuccessful! PCRs invalidated.\n",
329 __func__, status);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200330 }
331 } else {
332 invalidate_pcrs();
Wim Vervoornd1fb78d2019-10-30 17:14:58 +0100333 printk(BIOS_ERR, "%s: StartUp returned 0x%x, unsuccessful! PCRs invalidated.\n", __func__,
334 status);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200335 }
336 return status;
337}
338
339/*
340 *
341 * mb_measure_log_start
342 *
343 * performs the measurements defined by the the board routines.
344 *
345 * The logging is defined by the mb_log_list structure
346 *
347 * These items need to be defined in the mainboard part of the mboot
348 * implementation
349 *
350 * The function can be overridden at the mainboard level my simply creating a
351 * function with the same name there.
352 *
353 * @param[in] none
354 *
355 * @retval TPM_SUCCESS Operation completed successfully.
356 * @retval TPM_E_IOERROR Unexpected device behavior.
357 */
358int __attribute__((weak))mb_measure_log_start(void)
359{
360 int status;
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200361 uint32_t i;
362
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100363 if ((tpm2_get_active_pcrs() & EFI_TCG2_BOOT_HASH_ALG_SHA256) == 0x0) {
364 printk(BIOS_DEBUG, "%s: SHA256 PCR Bank not active in TPM.\n",
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200365 __func__);
366 return TPM_E_IOERROR;
367 }
368
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100369 status = mb_crtm();
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200370 if (status != TPM_SUCCESS) {
371 printk(BIOS_DEBUG, "%s: Fail! CRTM Version can't be measured."
372 " ABORTING!!!\n", __func__);
373 return status;
374 }
375 printk(BIOS_DEBUG, "%s: Success! CRTM Version measured.\n", __func__);
376
377 /* Log the items defined by the mainboard */
378 for (i = 0; i < ARRAY_SIZE(mb_log_list); i++) {
379 status = mb_measure_log_worker(
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100380 mb_log_list[i].cbfs_name,
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200381 mb_log_list[i].cbfs_type, mb_log_list[i].pcr,
382 mb_log_list[i].eventType,
383 mb_log_list[i].event_msg);
384 if (status != TPM_SUCCESS) {
385 printk(BIOS_DEBUG, "%s: Fail! %s can't be measured."
386 "ABORTING!!!\n", __func__,
387 mb_log_list[i].cbfs_name);
388 return status;
389 }
390 printk(BIOS_DEBUG, "%s: Success! %s measured to pcr"
391 "%d.\n", __func__, mb_log_list[i].cbfs_name,
392 mb_log_list[i].pcr);
393 }
394 return status;
395}
396
397static const uint8_t crtm_version[] =
398 CONFIG_VENDORCODE_ELTAN_CRTM_VERSION_STRING\
399 COREBOOT_VERSION COREBOOT_EXTRA_VERSION " " COREBOOT_BUILD;
400
401/*
402 *
403 * mb_crtm
404 *
405 * measures the crtm version. this consists of a string than can be
406 * defined using make menuconfig and automatically generated version
407 * information.
408 *
409 * The function can be overridden at the mainboard level my simply creating a
410 * function with the same name there.
411 *
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200412 * @retval TPM_SUCCESS Operation completed successfully.
413 * @retval TPM_E_IOERROR Unexpected device behavior.
414**/
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100415int __attribute__((weak))mb_crtm(void)
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200416{
417 int status;
418 TCG_PCR_EVENT2_HDR tcgEventHdr;
419 uint8_t hash[VB2_SHA256_DIGEST_SIZE];
420 uint8_t *msgPtr;
421
422 /* Use FirmwareVersion string to represent CRTM version. */
423 printk(BIOS_DEBUG, "%s: Measure CRTM Version\n", __func__);
424 memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
425 tcgEventHdr.pcrIndex = MBOOT_PCR_INDEX_0;
426 tcgEventHdr.eventType = EV_S_CRTM_VERSION;
427 tcgEventHdr.eventSize = sizeof(crtm_version);
428 printk(BIOS_DEBUG, "%s: EventSize - %u\n", __func__,
429 tcgEventHdr.eventSize);
430
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100431 status = mboot_hash_extend_log(0, (uint8_t *)crtm_version, tcgEventHdr.eventSize,
432 &tcgEventHdr, (uint8_t *)crtm_version);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200433 if (status) {
Wim Vervoornd1fb78d2019-10-30 17:14:58 +0100434 printk(BIOS_DEBUG, "Measure CRTM Version returned 0x%x\n", status);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200435 return status;
436 }
437
438 status = get_intel_me_hash(hash);
439 if (status) {
440 printk(BIOS_DEBUG, "get_intel_me_hash returned 0x%x\n", status);
441 status = TPM_E_IOERROR;
442 return status;
443 }
444
445 /* Add the me hash */
446 printk(BIOS_DEBUG, "%s: Add the hash returned by the ME\n",
447 __func__);
448 memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
449 tcgEventHdr.pcrIndex = MBOOT_PCR_INDEX_0;
450 tcgEventHdr.eventType = EV_S_CRTM_CONTENTS;
451
452 msgPtr = NULL;
453 tcgEventHdr.eventSize = 0;
Wim Vervoorn397ce3c2019-10-30 17:06:58 +0100454 status = mboot_hash_extend_log(MBOOT_HASH_PROVIDED, hash, sizeof(hash), &tcgEventHdr,
455 msgPtr);
Frans Hendriks7c82dbc2019-08-01 15:25:19 +0200456 if (status)
457 printk(BIOS_DEBUG, "Add ME hash returned 0x%x\n", status);
458
459 return status;
460}