summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Reinauer <reinauer@chromium.org>2011-12-20 14:11:14 -0800
committerStefan Reinauer <reinauer@chromium.org>2011-12-20 14:49:13 -0800
commit59bcc6a23ac0beea5af8f71579f0b2540d0f696a (patch)
treecaf0c7cff77a829687089b7f4d8a84f82291baff
parent6d09577f7dc0f7cc58c1f3368f9e167446581a0b (diff)
downloadvboot-59bcc6a23ac0beea5af8f71579f0b2540d0f696a.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. Reviewed-on: https://gerrit.chromium.org/gerrit/11442 Tested-by: Bill Richardson <wfrichar@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> (cherry picked from commit fa9d7782e837848a1aeb0e95295fa48ac23f7a26) Change-Id: Ief751c0181426bf304db883abc0b2aaf030f85ef Reviewed-on: https://gerrit.chromium.org/gerrit/13257 Reviewed-by: Randall Spangler <rspangler@chromium.org> Tested-by: Stefan Reinauer <reinauer@chromium.org>
-rw-r--r--firmware/include/vboot_nvstorage.h2
-rw-r--r--firmware/include/vboot_struct.h1
-rw-r--r--firmware/lib/vboot_api_kernel.c3
-rw-r--r--firmware/lib/vboot_display.c5
-rw-r--r--firmware/lib/vboot_kernel.c24
-rw-r--r--firmware/lib/vboot_nvstorage.c12
-rw-r--r--host/lib/crossystem.c4
-rw-r--r--tests/vboot_nvstorage_test.c1
-rw-r--r--utility/crossystem_main.c2
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 bf906412..52bcacc7 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -106,10 +106,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 6e015441..120f7be6 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"},