17993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2d183644564ec27c106a3eb1931f565fae167a058Randall Spangler * Use of this source code is governed by a BSD-style license that can be
3d183644564ec27c106a3eb1931f565fae167a058Randall Spangler * found in the LICENSE file.
4d183644564ec27c106a3eb1931f565fae167a058Randall Spangler *
5d183644564ec27c106a3eb1931f565fae167a058Randall Spangler * High-level firmware API for loading and verifying rewritable firmware.
6d183644564ec27c106a3eb1931f565fae167a058Randall Spangler * (Firmware portion)
7d183644564ec27c106a3eb1931f565fae167a058Randall Spangler */
8d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
90c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "sysincludes.h"
100c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson
11527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "region.h"
12527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "gbb_access.h"
1395c4031ce903258036beeed0705d25c7e9d25da0Randall Spangler#include "gbb_header.h"
14d183644564ec27c106a3eb1931f565fae167a058Randall Spangler#include "load_firmware_fw.h"
15d183644564ec27c106a3eb1931f565fae167a058Randall Spangler#include "utility.h"
16e49e8af65fce38da7a308305566f8a14f102254aRandall Spangler#include "vboot_api.h"
17d183644564ec27c106a3eb1931f565fae167a058Randall Spangler#include "vboot_common.h"
18c4d21025bb57d78c512c014b694ea148cea18d7eRandall Spangler#include "vboot_nvstorage.h"
19d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
207993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler/*
217993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Static variables for UpdateFirmwareBodyHash().  It's less than optimal to
227993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * have static variables in a library, but in UEFI the caller is deep inside a
237993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * different firmware stack and doesn't have a good way to pass the params
247993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * struct back to us.
257993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */
26a55e5ca76c5054c02dcc0628be0950c07b49d38cRandall Spanglertypedef struct VbLoadFirmwareInternal {
277993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	DigestContext body_digest_context;
287993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	uint32_t body_size_accum;
29a55e5ca76c5054c02dcc0628be0950c07b49d38cRandall Spangler} VbLoadFirmwareInternal;
30d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
317993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spanglervoid VbUpdateFirmwareBodyHash(VbCommonParams *cparams, uint8_t *data,
327993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			      uint32_t size)
337993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler{
347993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	VbLoadFirmwareInternal *lfi =
357993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		(VbLoadFirmwareInternal*)cparams->vboot_context;
3639ed88efe91432eab9e5fff6099aa1652ab2bf2eRandall Spangler
377993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	DigestUpdate(&lfi->body_digest_context, data, size);
387993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	lfi->body_size_accum += size;
39d183644564ec27c106a3eb1931f565fae167a058Randall Spangler}
40d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
417993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spanglerint LoadFirmware(VbCommonParams *cparams, VbSelectFirmwareParams *fparams,
427993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler                 VbNvContext *vnc)
437993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler{
447993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	VbSharedDataHeader *shared =
457993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		(VbSharedDataHeader *)cparams->shared_data_blob;
46527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	GoogleBinaryBlockHeader *gbb = cparams->gbb;
47527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	VbPublicKey *root_key = NULL;
487993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	VbLoadFirmwareInternal *lfi;
497993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
507993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	uint32_t try_b_count;
517993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	uint32_t lowest_version = 0xFFFFFFFF;
527993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	int good_index = -1;
537993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	int is_dev;
547993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	int index;
557993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	int i;
567993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
577993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	int retval = VBERROR_UNKNOWN;
587993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	int recovery = VBNV_RECOVERY_RO_UNSPECIFIED;
597993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
607993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	/* Clear output params in case we fail */
617993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	shared->firmware_index = 0xFF;
627993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
637993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	VBDEBUG(("LoadFirmware started...\n"));
647993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
657993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	/* Must have a root key from the GBB */
66527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	retval = VbGbbReadRootKey(cparams, &root_key);
67527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	if (retval) {
687993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		VBDEBUG(("No GBB\n"));
697993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		retval = VBERROR_INVALID_GBB;
707993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		goto LoadFirmwareExit;
717993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	}
727993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
737993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	/* Parse flags */
747993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	is_dev = (shared->flags & VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0);
757993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	if (is_dev)
767993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		shared->flags |= VBSD_LF_DEV_SWITCH_ON;
777993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
787993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	/* Read try-b count and decrement if necessary */
797993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	VbNvGet(vnc, VBNV_TRY_B_COUNT, &try_b_count);
807993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	if (0 != try_b_count) {
817993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		VbNvSet(vnc, VBNV_TRY_B_COUNT, try_b_count - 1);
827993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		shared->flags |= VBSD_FWB_TRIED;
837993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	}
847993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
857993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	/* Allocate our internal data */
867993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	lfi = (VbLoadFirmwareInternal *)
877993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		VbExMalloc(sizeof(VbLoadFirmwareInternal));
887993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	cparams->vboot_context = lfi;
897993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
907993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	/* Loop over indices */
917993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	for (i = 0; i < 2; i++) {
927993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		VbKeyBlockHeader *key_block;
937993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		uint32_t vblock_size;
947993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		VbFirmwarePreambleHeader *preamble;
957993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		RSAPublicKey *data_key;
967993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		uint64_t key_version;
977993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		uint32_t combined_version;
987993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		uint8_t *body_digest;
997993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		uint8_t *check_result;
1007993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
1017993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* If try B count is non-zero try firmware B first */
1027993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		index = (try_b_count ? 1 - i : i);
1037993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (0 == index) {
1047993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			key_block = (VbKeyBlockHeader *)
1057993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				fparams->verification_block_A;
1067993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			vblock_size = fparams->verification_size_A;
1077993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			check_result = &shared->check_fw_a_result;
1087993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		} else {
1097993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			key_block = (VbKeyBlockHeader *)
1107993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				fparams->verification_block_B;
1117993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			vblock_size = fparams->verification_size_B;
1127993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			check_result = &shared->check_fw_b_result;
1137993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		}
1147993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
1157993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/*
1167993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 * Check the key block flags against the current boot mode.  Do
1177993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 * this before verifying the key block, since flags are faster
1187993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 * to check than the RSA signature.
1197993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 */
1207993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (!(key_block->key_block_flags &
1217993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		      (is_dev ? KEY_BLOCK_FLAG_DEVELOPER_1 :
1227993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		       KEY_BLOCK_FLAG_DEVELOPER_0))) {
1237993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			VBDEBUG(("Developer flag mismatch.\n"));
1247993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			*check_result = VBSD_LF_CHECK_DEV_MISMATCH;
1257993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			continue;
1267993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		}
1277993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
1287993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* RW firmware never runs in recovery mode. */
1297993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (!(key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)) {
1307993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			VBDEBUG(("Recovery flag mismatch.\n"));
1317993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			*check_result = VBSD_LF_CHECK_REC_MISMATCH;
1327993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			continue;
1337993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		}
1347993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
1357993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* Verify the key block */
1367993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if ((0 != KeyBlockVerify(key_block, vblock_size,
1377993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					 root_key, 0))) {
1387993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			VBDEBUG(("Key block verification failed.\n"));
1397993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			*check_result = VBSD_LF_CHECK_VERIFY_KEYBLOCK;
1407993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			continue;
1417993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		}
1427993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
1437993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* Check for rollback of key version. */
1447993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		key_version = key_block->data_key.key_version;
1457993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (!(gbb->flags & GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK)) {
1467993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			if (key_version < (shared->fw_version_tpm >> 16)) {
1477993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				VBDEBUG(("Key rollback detected.\n"));
1487993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				*check_result = VBSD_LF_CHECK_KEY_ROLLBACK;
1497993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				continue;
1507993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			}
1517993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			if (key_version > 0xFFFF) {
1527993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				/*
1537993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				 * Key version is stored in 16 bits in the TPM,
1547993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				 * so key versions greater than 0xFFFF can't be
1557993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				 * stored properly.
1567993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				 */
1577993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				VBDEBUG(("Key version > 0xFFFF.\n"));
1587993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				*check_result = VBSD_LF_CHECK_KEY_ROLLBACK;
1597993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				continue;
1607993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			}
1617993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		}
1627993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
1637993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* Get key for preamble/data verification from the key block. */
1647993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		data_key = PublicKeyToRSA(&key_block->data_key);
1657993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (!data_key) {
1667993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			VBDEBUG(("Unable to parse data key.\n"));
1677993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			*check_result = VBSD_LF_CHECK_DATA_KEY_PARSE;
1687993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			continue;
1697993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		}
1707993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
1717993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* Verify the preamble, which follows the key block. */
1727993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		preamble = (VbFirmwarePreambleHeader *)
1737993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			((uint8_t *)key_block + key_block->key_block_size);
1747993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if ((0 != VerifyFirmwarePreamble(
1757993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					preamble,
1767993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					vblock_size - key_block->key_block_size,
1777993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					data_key))) {
1787993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			VBDEBUG(("Preamble verfication failed.\n"));
1797993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			*check_result = VBSD_LF_CHECK_VERIFY_PREAMBLE;
1807993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			RSAPublicKeyFree(data_key);
1817993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			continue;
1827993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		}
1837993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
1847993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* Check for rollback of firmware version. */
1857993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		combined_version = (uint32_t)((key_version << 16) |
1867993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				(preamble->firmware_version & 0xFFFF));
1877993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (combined_version < shared->fw_version_tpm &&
1887993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		    !(gbb->flags & GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK)) {
1897993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			VBDEBUG(("Firmware version rollback detected.\n"));
1907993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			*check_result = VBSD_LF_CHECK_FW_ROLLBACK;
1917993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			RSAPublicKeyFree(data_key);
1927993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			continue;
1937993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		}
1947993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
1957993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* Header for this firmware is valid */
1967993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		*check_result = VBSD_LF_CHECK_HEADER_VALID;
1977993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
1987993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* Check for lowest key version from a valid header. */
1997993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (lowest_version > combined_version)
2007993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			lowest_version = combined_version;
2017993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
2027993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/*
2037993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 * If we already have good firmware, no need to read another
2047993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 * one; we only needed to look at the versions to check for
2057993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 * rollback.
2067993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 */
2077993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (-1 != good_index) {
2087993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			RSAPublicKeyFree(data_key);
2097993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			continue;
2107993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		}
2117993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
2127993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* Handle preamble flag for using the RO normal/dev code path */
213981cb2acdc2f26ae27732a4e590c326787936381Simon Glass		VBDEBUG(("Preamble flags %#x\n", VbGetFirmwarePreambleFlags(preamble)));
2147993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (VbGetFirmwarePreambleFlags(preamble) &
2157993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		    VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
2167993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
2177993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			/* Fail if calling firmware doesn't support RO normal */
2187993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			if (!(shared->flags & VBSD_BOOT_RO_NORMAL_SUPPORT)) {
219981cb2acdc2f26ae27732a4e590c326787936381Simon Glass				VBDEBUG(("No RO normal support.\n"));
2207993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				*check_result = VBSD_LF_CHECK_NO_RO_NORMAL;
2217993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				RSAPublicKeyFree(data_key);
2227993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				continue;
2237993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			}
2247993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
2257993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			/* Use the RO normal code path */
2267993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			shared->flags |= VBSD_LF_USE_RO_NORMAL;
2277993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
2287993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		} else {
2297993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			VbError_t rv;
2307993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
2317993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			/* Read the firmware data */
2327993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			DigestInit(&lfi->body_digest_context,
2337993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				   data_key->algorithm);
2347993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			lfi->body_size_accum = 0;
2357993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			rv = VbExHashFirmwareBody(
2367993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					cparams,
2377993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					(index ? VB_SELECT_FIRMWARE_B :
2387993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					 VB_SELECT_FIRMWARE_A));
2397993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			if (VBERROR_SUCCESS != rv) {
2407993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				VBDEBUG(("VbExHashFirmwareBody() failed for "
2417993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					 "index %d\n", index));
2427993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				*check_result = VBSD_LF_CHECK_GET_FW_BODY;
2437993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				RSAPublicKeyFree(data_key);
2447993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				continue;
2457993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			}
2467993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			if (lfi->body_size_accum !=
2477993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			    preamble->body_signature.data_size) {
2487993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				VBDEBUG(("Hashed %d bytes but expected %d\n",
2497993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					 (int)lfi->body_size_accum,
2507993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					 (int)preamble->body_signature.data_size));
2517993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				*check_result = VBSD_LF_CHECK_HASH_WRONG_SIZE;
2527993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				RSAPublicKeyFree(data_key);
2537993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				continue;
2547993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			}
2557993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
2567993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			/* Verify firmware data */
2577993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			body_digest = DigestFinal(&lfi->body_digest_context);
2587993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			if (0 != VerifyDigest(body_digest,
2597993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					      &preamble->body_signature,
2607993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					      data_key)) {
2617993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				VBDEBUG(("FW body verification failed.\n"));
2627993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				*check_result = VBSD_LF_CHECK_VERIFY_BODY;
2637993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				RSAPublicKeyFree(data_key);
2647993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				VbExFree(body_digest);
2657993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				continue;
2667993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			}
2677993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			VbExFree(body_digest);
2687993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		}
2697993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
2707993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* Done with the data key, so can free it now */
2717993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		RSAPublicKeyFree(data_key);
2727993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
2737993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* If we're still here, the firmware is valid. */
2747993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		VBDEBUG(("Firmware %d is valid.\n", index));
2757993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		*check_result = VBSD_LF_CHECK_VALID;
2767993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (-1 == good_index) {
2777993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			/* Save the key we actually used */
2787993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			if (0 != VbSharedDataSetKernelKey(
2797993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler					shared, &preamble->kernel_subkey)) {
2807993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				/*
2817993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				 * The firmware signature was good, but the
2827993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				 * public key was bigger that the caller can
2837993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				 * handle.
2847993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				 */
2857993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				VBDEBUG(("Unable to save kernel subkey.\n"));
2867993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				continue;
2877993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			}
2887993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
2897993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			/*
2907993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			 * Save the good index, now that we're sure we can
2917993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			 * actually use this firmware.  That's the one we'll
2927993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			 * boot.
2937993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			 */
2947993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			good_index = index;
2957993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			shared->firmware_index = (uint8_t)index;
2967993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			shared->fw_keyblock_flags = key_block->key_block_flags;
2977993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
2987993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			/*
2997993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			 * If the good firmware's key version is the same as
3007993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			 * the tpm, then the TPM doesn't need updating; we can
3017993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			 * stop now.  Otherwise, we'll check all the other
3027993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			 * headers to see if they contain a newer key.
3037993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			 */
3047993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			if (combined_version == shared->fw_version_tpm)
3057993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler				break;
3067993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		}
3077993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	}
3087993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
3097993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	/* Free internal data */
3107993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	VbExFree(lfi);
3117993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	cparams->vboot_context = NULL;
3127993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
3137993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	/* Handle finding good firmware */
3147993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	if (good_index >= 0) {
3157993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
3167993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* Save versions we found */
3177993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		shared->fw_version_lowest = lowest_version;
3187993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (lowest_version > shared->fw_version_tpm)
3197993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			shared->fw_version_tpm = lowest_version;
3207993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
3217993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* Success */
3227993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		VBDEBUG(("Will boot firmware index %d\n",
3237993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			 (int)shared->firmware_index));
3247993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		retval = VBERROR_SUCCESS;
3257993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
3267993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	} else {
3277993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		uint8_t a = shared->check_fw_a_result;
3287993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		uint8_t b = shared->check_fw_b_result;
3297993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		uint8_t best_check;
3307993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
3317993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/* No good firmware, so go to recovery mode. */
3327993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		VBDEBUG(("Alas, no good firmware.\n"));
3337993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		recovery = VBNV_RECOVERY_RO_INVALID_RW;
3347993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		retval = VBERROR_LOAD_FIRMWARE;
3357993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
3367993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		/*
3377993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 * If the best check result fits in the range of recovery
3387993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 * reasons, provide more detail on how far we got in
3397993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 * validation.
3407993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		 */
3417993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		best_check = (a > b ? a : b) +
3427993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN;
3437993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		if (best_check >= VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN &&
3447993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		    best_check <= VBNV_RECOVERY_RO_INVALID_RW_CHECK_MAX)
3457993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler			recovery = best_check;
3467993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	}
3477993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
3487993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler LoadFirmwareExit:
349527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	VbExFree(root_key);
350527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass
3517993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	/* Store recovery request, if any */
3527993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	VbNvSet(vnc, VBNV_RECOVERY_REQUEST, VBERROR_SUCCESS != retval ?
3537993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler		recovery : VBNV_RECOVERY_NOT_REQUESTED);
354952c2d32452fc582900cc542edd75c7da6b3f830Aaron Durbin	/* If the system does not support RO_NORMAL and LoadFirmware()
355952c2d32452fc582900cc542edd75c7da6b3f830Aaron Durbin	 * encountered an error, update the shared recovery reason if
356952c2d32452fc582900cc542edd75c7da6b3f830Aaron Durbin	 * recovery was not previously requested. */
357952c2d32452fc582900cc542edd75c7da6b3f830Aaron Durbin	if (!(shared->flags & VBSD_BOOT_RO_NORMAL_SUPPORT) &&
358952c2d32452fc582900cc542edd75c7da6b3f830Aaron Durbin	    VBNV_RECOVERY_NOT_REQUESTED == shared->recovery_reason &&
359981cb2acdc2f26ae27732a4e590c326787936381Simon Glass	    VBERROR_SUCCESS != retval) {
360981cb2acdc2f26ae27732a4e590c326787936381Simon Glass		VBDEBUG(("RO normal but we got an error.\n"));
361952c2d32452fc582900cc542edd75c7da6b3f830Aaron Durbin		shared->recovery_reason = recovery;
362981cb2acdc2f26ae27732a4e590c326787936381Simon Glass	}
3637993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler
3647993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler	return retval;
365d183644564ec27c106a3eb1931f565fae167a058Randall Spangler}
366