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