diff options
-rw-r--r-- | firmware/include/gbb_header.h | 7 | ||||
-rw-r--r-- | firmware/lib/vboot_api_init.c | 4 | ||||
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 4 | ||||
-rw-r--r-- | firmware/lib/vboot_firmware.c | 27 | ||||
-rw-r--r-- | tests/vboot_api_init_tests.c | 15 | ||||
-rw-r--r-- | tests/vboot_firmware_tests.c | 19 |
6 files changed, 62 insertions, 14 deletions
diff --git a/firmware/include/gbb_header.h b/firmware/include/gbb_header.h index 7f9b0005..a3204e32 100644 --- a/firmware/include/gbb_header.h +++ b/firmware/include/gbb_header.h @@ -43,6 +43,13 @@ /* The factory flow may need the BIOS to boot a non-ChromeOS kernel if the * dev-switch is on. This flag allows that. */ #define GBB_FLAG_ENABLE_ALTERNATE_OS 0x00000004 +/* Force dev switch on, regardless of physical/keyboard dev switch position. */ +#define GBB_FLAG_FORCE_DEV_SWITCH_ON 0x00000008 +/* Allow booting from USB in dev mode even if dev_boot_usb=0. */ +#define GBB_FLAG_FORCE_DEV_BOOT_USB 0x00000010 +/* Disable firmware rollback protection. */ +#define GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK 0x00000020 + #ifdef __cplusplus extern "C" { diff --git a/firmware/lib/vboot_api_init.c b/firmware/lib/vboot_api_init.c index bff57bd5..78f451fd 100644 --- a/firmware/lib/vboot_api_init.c +++ b/firmware/lib/vboot_api_init.c @@ -127,7 +127,9 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) { /* We may be asked to clear the virtual dev-switch at boot. */ VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &disable_dev_request); - /* FIXME: How about a GBB flag to force dev-switch on? */ + /* Allow GBB flag to override dev switch */ + if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) + is_hw_dev = 1; VBPERFSTART("VB_TPMI"); /* Initialize the TPM. If the developer mode state has changed since the diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index b0a04ac4..6e02380e 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -116,6 +116,7 @@ VbError_t VbBootNormal(VbCommonParams* cparams, LoadKernelParams* p) { /* Handle a developer-mode boot */ VbError_t VbBootDeveloper(VbCommonParams* cparams, LoadKernelParams* p) { + GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)cparams->gbb_data; uint32_t allow_usb = 0; VbAudioContext* audio = 0; @@ -123,6 +124,9 @@ VbError_t VbBootDeveloper(VbCommonParams* cparams, LoadKernelParams* p) { /* Check if USB booting is allowed */ VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &allow_usb); + /* Handle GBB flag override */ + if (gbb->flags & GBB_FLAG_FORCE_DEV_BOOT_USB) + allow_usb = 1; /* Show the dev mode warning screen */ VbDisplayScreen(cparams, VB_SCREEN_DEVELOPER_WARNING, 0, &vnc); diff --git a/firmware/lib/vboot_firmware.c b/firmware/lib/vboot_firmware.c index 3f9f64fc..ed9d3bc0 100644 --- a/firmware/lib/vboot_firmware.c +++ b/firmware/lib/vboot_firmware.c @@ -131,17 +131,19 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams, /* Check for rollback of key version. */ key_version = key_block->data_key.key_version; - if (key_version < (shared->fw_version_tpm >> 16)) { - VBDEBUG(("Key rollback detected.\n")); - *check_result = VBSD_LF_CHECK_KEY_ROLLBACK; - continue; - } - if (key_version > 0xFFFF) { - /* Key version is stored in 16 bits in the TPM, so key versions greater - * than 0xFFFF can't be stored properly. */ - VBDEBUG(("Key version > 0xFFFF.\n")); - *check_result = VBSD_LF_CHECK_KEY_ROLLBACK; - continue; + if (!(gbb->flags & GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK)) { + if (key_version < (shared->fw_version_tpm >> 16)) { + VBDEBUG(("Key rollback detected.\n")); + *check_result = VBSD_LF_CHECK_KEY_ROLLBACK; + continue; + } + if (key_version > 0xFFFF) { + /* Key version is stored in 16 bits in the TPM, so key versions greater + * than 0xFFFF can't be stored properly. */ + VBDEBUG(("Key version > 0xFFFF.\n")); + *check_result = VBSD_LF_CHECK_KEY_ROLLBACK; + continue; + } } /* Get the key for preamble/data verification from the key block. */ @@ -170,7 +172,8 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams, /* Check for rollback of firmware version. */ combined_version = (uint32_t)((key_version << 16) | (preamble->firmware_version & 0xFFFF)); - if (combined_version < shared->fw_version_tpm) { + if (combined_version < shared->fw_version_tpm && + !(gbb->flags & GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK)) { VBDEBUG(("Firmware version rollback detected.\n")); *check_result = VBSD_LF_CHECK_FW_ROLLBACK; RSAPublicKeyFree(data_key); diff --git a/tests/vboot_api_init_tests.c b/tests/vboot_api_init_tests.c index ec1e7fa9..28a43d88 100644 --- a/tests/vboot_api_init_tests.c +++ b/tests/vboot_api_init_tests.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -211,6 +211,19 @@ static void VbInitTest(void) { VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags"); TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags"); + /* Developer mode forced by GBB flag */ + ResetMocks(); + iparams.flags = 0; + gbb.flags = GBB_FLAG_FORCE_DEV_SWITCH_ON; + TestVbInit(0, 0, "Dev mode via GBB"); + TEST_EQ(shared->recovery_reason, 0, " recovery reason"); + TEST_EQ(iparams.out_flags, + VB_INIT_OUT_CLEAR_RAM | + VB_INIT_OUT_ENABLE_DISPLAY | + VB_INIT_OUT_ENABLE_USB_STORAGE | + VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags"); + TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags"); + /* Recovery mode from NV storage */ ResetMocks(); VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123); diff --git a/tests/vboot_firmware_tests.c b/tests/vboot_firmware_tests.c index 7a023226..0443b061 100644 --- a/tests/vboot_firmware_tests.c +++ b/tests/vboot_firmware_tests.c @@ -253,6 +253,14 @@ static void LoadFirmwareTest(void) { TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_DATA_KEY_PARSE, "Data key invalid"); + /* Test invalid key version with GBB bypass-rollback flag */ + ResetMocks(); + vblock[0].data_key.key_version = 1; /* Simulate rollback */ + gbb->flags = GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK; + TestLoadFirmware(VBERROR_SUCCESS, 0, "Key version check + GBB override"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID, + "Key version rollback + GBB override"); + /* Test invalid preamble with A */ ResetMocks(); mpreamble[0].header_version_major = 1; /* Simulate failure */ @@ -277,6 +285,17 @@ static void LoadFirmwareTest(void) { TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_FW_ROLLBACK, "Firmware version overflow"); + /* Test invalid firmware versions with GBB bypass-rollback flag */ + ResetMocks(); + mpreamble[0].firmware_version = 3; /* Simulate rollback */ + mpreamble[1].firmware_version = 0x10001; /* Check overflow */ + gbb->flags = GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK; + TestLoadFirmware(VBERROR_SUCCESS, 0, "Firmware version check + GBB bypass"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID, + "Firmware version rollback + GBB override"); + TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_HEADER_VALID, + "Firmware version overflow + GBB override"); + /* Test RO normal with A */ ResetMocks(); mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL; |