diff options
author | Bill Richardson <wfrichar@chromium.org> | 2011-11-09 09:11:34 -0800 |
---|---|---|
committer | Bill Richardson <wfrichar@chromium.org> | 2011-11-10 14:03:56 -0800 |
commit | fa9d7782e837848a1aeb0e95295fa48ac23f7a26 (patch) | |
tree | 567ca898cae73ba4c5c879d1e7f57882b398bb08 | |
parent | 9b717be86ba6155a7542bf1649dd3ab2dbc2dc3b (diff) | |
download | vboot-fa9d7782e837848a1aeb0e95295fa48ac23f7a26.tar.gz |
Dev-mode only boots official kernels by default
Although we're now using a single unified BIOS, it is pretty nice to be able
to get a shell in developer mode while still using verified boot for the
kernel and filesystem. Alex & ZGB implemented this by requiring the dev-mode
user to install a special dev-mode BIOS. We don't do that, but we DO require
setting a special flag with "crossystem" to accomplish the same thing.
In order to allow booting a self-signed kernel, you must boot in developer
mode, open a shell, and run this:
crossystem dev_boot_custom=1
Special note to internal developers: If you're in the habit (as I am) of
booting directly from a USB stick in dev-mode, you'll have to run this:
crossystem dev_boot_custom=1 dev_boot_usb=1
Just using dev_boot_usb=1 is no longer enough, because the USB kernel is
signed using the recovery key and by pressing Ctrl-U, we validate it with
the kernel data key. That worked before this change because any self-signed
kernel was fine, and that's how the USB key was treated. Now it actually
requires a verified signature until you enable dev_boot_custom=1 also.
BUG=chrome-os-partner:5954
TEST=manual
Boot once in normal mode, which clears the special flags. Then switch to
developer mode. You should be able to boot and get a root shell.
Run
crossystem dev_boot_usb=1
Obtain a USB recovery image that's keyed differently. For example, if you're
testing with dev-keys, use a PVT-signed image or vice-versa.
Reboot into dev-mode with the USB recovery stick inserted. At the dev-mode
screen, press Ctrl-U. You should hear a single beep, but it should not boot.
Press Ctrl-D to boot from the hard drive, log in to a shell and run
crossystem dev_boot_custom=1
Repeat the previous test. This time when you press Ctrl-U, it should boot
the recovery image. Turn the system off before it does anything.
That's it.
Change-Id: I1811ee9a188974b3f94c83c52b00b60028b86c69
Reviewed-on: https://gerrit.chromium.org/gerrit/11442
Tested-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r-- | firmware/include/vboot_nvstorage.h | 2 | ||||
-rw-r--r-- | firmware/include/vboot_struct.h | 1 | ||||
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 3 | ||||
-rw-r--r-- | firmware/lib/vboot_display.c | 5 | ||||
-rw-r--r-- | firmware/lib/vboot_kernel.c | 24 | ||||
-rw-r--r-- | firmware/lib/vboot_nvstorage.c | 12 | ||||
-rw-r--r-- | host/lib/crossystem.c | 4 | ||||
-rw-r--r-- | tests/vboot_nvstorage_test.c | 1 | ||||
-rw-r--r-- | utility/crossystem_main.c | 2 |
9 files changed, 46 insertions, 8 deletions
diff --git a/firmware/include/vboot_nvstorage.h b/firmware/include/vboot_nvstorage.h index f010ddcc..28a1a62a 100644 --- a/firmware/include/vboot_nvstorage.h +++ b/firmware/include/vboot_nvstorage.h @@ -54,6 +54,8 @@ typedef enum VbNvParam { VBNV_TEST_ERROR_NUM, /* Allow booting from USB in developer mode. 0=no, 1=yes. */ VBNV_DEV_BOOT_USB, + /* Allow booting self-signed images in developer mode. 0=no, 1=yes. */ + VBNV_DEV_BOOT_CUSTOM, } VbNvParam; diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h index 795523ed..3374d4cc 100644 --- a/firmware/include/vboot_struct.h +++ b/firmware/include/vboot_struct.h @@ -234,6 +234,7 @@ typedef struct VbKernelPreambleHeader { #define VBSD_LKP_CHECK_PREAMBLE_VALID 11 #define VBSD_LKP_CHECK_BODY_ADDRESS 12 #define VBSD_LKP_CHECK_BODY_OFFSET 13 +#define VBSD_LKP_CHECK_SELF_SIGNED 14 #define VBSD_LKP_CHECK_BODY_EXCEEDS_MEM 15 #define VBSD_LKP_CHECK_BODY_EXCEEDS_PART 16 #define VBSD_LKP_CHECK_READ_DATA 17 diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index a8368603..76ab9ae0 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -97,10 +97,11 @@ uint32_t VbTryLoadKernel(VbCommonParams* cparams, LoadKernelParams* p, /* Handle a normal boot. */ VbError_t VbBootNormal(VbCommonParams* cparams, LoadKernelParams* p) { - /* Force dev_boot_usb flag disabled. This ensures the flag will be + /* Force dev_boot_* flags disabled. This ensures they will be * initially disabled if the user later transitions back into * developer mode. */ VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 0); + VbNvSet(&vnc, VBNV_DEV_BOOT_CUSTOM, 0); /* Boot from fixed disk only */ return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED); diff --git a/firmware/lib/vboot_display.c b/firmware/lib/vboot_display.c index c0df16b2..a721b3d5 100644 --- a/firmware/lib/vboot_display.c +++ b/firmware/lib/vboot_display.c @@ -521,6 +521,11 @@ VbError_t VbDisplayDebugInfo(VbCommonParams* cparams, VbNvContext *vncptr) { used += Strncat(buf + used, "\ndev_boot_usb: ", DEBUG_INFO_SIZE - used); used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0); + /* Add dev_boot_custom flag */ + VbNvGet(vncptr, VBNV_DEV_BOOT_CUSTOM, &i); + used += Strncat(buf + used, "\ndev_boot_custom: ", DEBUG_INFO_SIZE - used); + used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0); + /* Add TPM versions */ used += Strncat(buf + used, "\nTPM: fwver=0x", DEBUG_INFO_SIZE - used); used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, diff --git a/firmware/lib/vboot_kernel.c b/firmware/lib/vboot_kernel.c index e38c4704..83c5eca2 100644 --- a/firmware/lib/vboot_kernel.c +++ b/firmware/lib/vboot_kernel.c @@ -121,6 +121,7 @@ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) { /* disable MSVC warning on const logical expression (as in } while(0);) */ __pragma(warning(disable: 4127)) + VbError_t LoadKernel(LoadKernelParams* params) { VbSharedDataHeader* shared = (VbSharedDataHeader*)params->shared_data_blob; VbSharedDataKernelCall* shcall = NULL; @@ -139,6 +140,7 @@ VbError_t LoadKernel(LoadKernelParams* params) { int rec_switch, dev_switch; BootMode boot_mode; uint32_t test_err = 0; + uint32_t allow_self_signed = 0; VbError_t retval = VBERROR_UNKNOWN; int recovery = VBNV_RECOVERY_RO_UNSPECIFIED; @@ -162,12 +164,14 @@ VbError_t LoadKernel(LoadKernelParams* params) { /* Calculate switch positions and boot mode */ rec_switch = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0); dev_switch = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0); - if (rec_switch) + if (rec_switch) { boot_mode = kBootRecovery; - else if (dev_switch) + } else if (dev_switch) { boot_mode = kBootDev; - else + VbNvGet(vnc, VBNV_DEV_BOOT_CUSTOM, &allow_self_signed); + } else { boot_mode = kBootNormal; + } /* Set up tracking for this call. This wraps around if called many times, * so we need to initialize the call entry each time. */ @@ -250,7 +254,7 @@ VbError_t LoadKernel(LoadKernelParams* params) { int key_block_valid = 1; VBDEBUG(("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n", - part_start, part_size)); + part_start, part_size)); /* Set up tracking for this partition. This wraps around if called * many times, so initialize the partition entry each time. */ @@ -293,8 +297,14 @@ VbError_t LoadKernel(LoadKernelParams* params) { if (kBootDev != boot_mode) goto bad_kernel; - /* In developer mode, we can continue if the SHA-512 hash of the key - * block is valid. */ + /* In developer mode, we have to explictly allow self-signed kernels */ + if (!allow_self_signed) { + VBDEBUG(("Self-signed custom kernels are not enabled.\n")); + shpart->check_result = VBSD_LKP_CHECK_SELF_SIGNED; + goto bad_kernel; + } + + /* Allow the kernel if the SHA-512 hash of the key block is valid. */ if (0 != KeyBlockVerify(key_block, KBUF_SIZE, kernel_subkey, 1)) { VBDEBUG(("Verifying key block hash failed.\n")); shpart->check_result = VBSD_LKP_CHECK_KEY_BLOCK_HASH; @@ -489,7 +499,7 @@ VbError_t LoadKernel(LoadKernelParams* params) { /* Continue, so that we skip the error handling code below */ continue; - bad_kernel: + bad_kernel: /* Handle errors parsing this kernel */ if (NULL != data_key) RSAPublicKeyFree(data_key); diff --git a/firmware/lib/vboot_nvstorage.c b/firmware/lib/vboot_nvstorage.c index 86fafb04..75910ed0 100644 --- a/firmware/lib/vboot_nvstorage.c +++ b/firmware/lib/vboot_nvstorage.c @@ -28,6 +28,7 @@ #define DEV_FLAGS_OFFSET 4 #define DEV_BOOT_USB_MASK 0x01 +#define DEV_BOOT_CUSTOM_MASK 0x02 #define FIRMWARE_FLAGS_OFFSET 5 #define FIRMWARE_TEST_ERR_FUNC_MASK 0x38 @@ -142,6 +143,10 @@ int VbNvGet(VbNvContext* context, VbNvParam param, uint32_t* dest) { *dest = (raw[DEV_FLAGS_OFFSET] & DEV_BOOT_USB_MASK ? 1 : 0); return 0; + case VBNV_DEV_BOOT_CUSTOM: + *dest = (raw[DEV_FLAGS_OFFSET] & DEV_BOOT_CUSTOM_MASK ? 1 : 0); + return 0; + default: return 1; } @@ -227,6 +232,13 @@ int VbNvSet(VbNvContext* context, VbNvParam param, uint32_t value) { raw[DEV_FLAGS_OFFSET] &= ~DEV_BOOT_USB_MASK; break; + case VBNV_DEV_BOOT_CUSTOM: + if (value) + raw[DEV_FLAGS_OFFSET] |= DEV_BOOT_CUSTOM_MASK; + else + raw[DEV_FLAGS_OFFSET] &= ~DEV_BOOT_CUSTOM_MASK; + break; + default: return 1; } diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c index ef3c6d1c..5bd4c62b 100644 --- a/host/lib/crossystem.c +++ b/host/lib/crossystem.c @@ -390,6 +390,8 @@ int VbGetSystemPropertyInt(const char* name) { value = VbGetNvStorage(VBNV_LOCALIZATION_INDEX); } else if (!strcasecmp(name,"dev_boot_usb")) { value = VbGetNvStorage(VBNV_DEV_BOOT_USB); + } else if (!strcasecmp(name,"dev_boot_custom")) { + value = VbGetNvStorage(VBNV_DEV_BOOT_CUSTOM); } /* Other parameters */ else if (!strcasecmp(name,"cros_debug")) { @@ -469,6 +471,8 @@ int VbSetSystemPropertyInt(const char* name, int value) { return VbSetNvStorage(VBNV_LOCALIZATION_INDEX, value); } else if (!strcasecmp(name,"dev_boot_usb")) { return VbSetNvStorage(VBNV_DEV_BOOT_USB, value); + } else if (!strcasecmp(name,"dev_boot_custom")) { + return VbSetNvStorage(VBNV_DEV_BOOT_CUSTOM, value); } return -1; diff --git a/tests/vboot_nvstorage_test.c b/tests/vboot_nvstorage_test.c index ae42c0b2..be600fa0 100644 --- a/tests/vboot_nvstorage_test.c +++ b/tests/vboot_nvstorage_test.c @@ -32,6 +32,7 @@ static VbNvField nvfields[] = { {VBNV_TEST_ERROR_FUNC, 0, 1, 7, "verified boot test error func"}, {VBNV_TEST_ERROR_NUM, 0, 3, 6, "verified boot test error number"}, {VBNV_DEV_BOOT_USB, 0, 1, 0, "dev boot usb"}, + {VBNV_DEV_BOOT_CUSTOM, 0, 1, 0, "dev boot custom"}, {0, 0, 0, 0, NULL} }; diff --git a/utility/crossystem_main.c b/utility/crossystem_main.c index b914d62d..3972073f 100644 --- a/utility/crossystem_main.c +++ b/utility/crossystem_main.c @@ -39,6 +39,8 @@ const Param sys_param_list[] = { {"dbg_reset", CAN_WRITE, "Debug reset mode request (writable)"}, {"dev_boot_usb", CAN_WRITE, "Enable developer mode boot from USB/SD (writable)"}, + {"dev_boot_custom", CAN_WRITE, + "Enable developer mode boot using self-signed kernels (writable)"}, {"devsw_boot", 0, "Developer switch position at boot"}, {"devsw_cur", 0, "Developer switch current position"}, {"ecfw_act", IS_STRING, "Active EC firmware"}, |