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>
This commit is contained in:
Bill Richardson
2011-11-09 09:11:34 -08:00
parent 9b717be86b
commit fa9d7782e8
9 changed files with 46 additions and 8 deletions

View File

@@ -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);