summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2019-10-22 15:37:14 -0700
committerCommit Bot <commit-bot@chromium.org>2020-03-05 02:40:39 +0000
commit5059062dd352e3864fb68f8a061e87bd7055d12a (patch)
treee2897970757ee3337d1c2e9cc506084e0d382709
parent1b4affa3650261efa2684a6e551030291fe00590 (diff)
downloadvboot-5059062dd352e3864fb68f8a061e87bd7055d12a.tar.gz
EFS: Implement EFS2 and NO_BOOT mode
EFS v1 allowed Chromeboxes to verify RW without AP. EFS v2 will bring the benefts to Chromebooks, which are: - Reduce RO dependency and presence. Allow more code to be updated in the fields. - Remove jumptag and workarounds needed for late sysjump. Major imporvements over v1 are: - No A/B slot required. - No signature in RW or public key in RO. - Rollback-attack protection. For battery-equipped devices, additional benefts are: - Immediate boot on drained battery. - Support recovery mode regardless of battery condition. - Faster charge in S5/G3. EC-Cr50 communication is based on the shared UART (go/ec-cr50-comm). EFS2 is documented in go/ec-efs2. BUG=chromium:1020578,chromium:1045217 TEST=Boot Helios in NORMAL/RECOVERY/NO_BOOT mode. TEST=Verify EC is updated by software sync in Depthcharge. Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Change-Id: Ie07e6f6ce46c0955a6a0adf595633e65c4ffe724 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/1901868
-rw-r--r--firmware/2lib/2ec_sync.c103
-rw-r--r--firmware/2lib/2misc.c3
-rw-r--r--firmware/2lib/include/2api.h5
-rw-r--r--firmware/2lib/include/2recovery_reasons.h6
-rw-r--r--firmware/2lib/include/2return_codes.h3
-rw-r--r--firmware/include/tss_constants.h1
-rw-r--r--firmware/lib/vboot_api_kernel.c16
-rw-r--r--firmware/lib/vboot_display.c4
-rw-r--r--tests/vb2_ec_sync_tests.c101
-rw-r--r--tests/vboot_api_kernel4_tests.c2
10 files changed, 196 insertions, 48 deletions
diff --git a/firmware/2lib/2ec_sync.c b/firmware/2lib/2ec_sync.c
index cba6782e..1871b50c 100644
--- a/firmware/2lib/2ec_sync.c
+++ b/firmware/2lib/2ec_sync.c
@@ -9,10 +9,12 @@
#include "2common.h"
#include "2misc.h"
#include "2nvstorage.h"
+#include "2secdata.h"
#include "2sysincludes.h"
#include "vboot_api.h"
#include "vboot_display.h"
#include "vboot_kernel.h"
+#include "vboot_test.h"
#define SYNC_FLAG(select) \
((select) == VB_SELECT_FIRMWARE_READONLY ? \
@@ -61,12 +63,9 @@ static vb2_error_t protect_ec(struct vb2_context *ctx,
* @param hash_size Size of the hash in bytes
* @param desc Description of what's being hashed
*/
-static void print_hash(const uint8_t *hash, uint32_t hash_size,
- const char *desc)
+static void print_hash(const uint8_t *hash, uint32_t hash_size)
{
int i;
-
- VB2_DEBUG("%s hash: ", desc);
for (i = 0; i < hash_size; i++)
VB2_DEBUG_RAW("%02x", hash[i]);
VB2_DEBUG_RAW("\n");
@@ -97,36 +96,70 @@ static vb2_error_t check_ec_hash(struct vb2_context *ctx,
enum vb2_firmware_selection select)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
+ const uint8_t *hexp = NULL;
+ const uint8_t *hmir = NULL;
+ const uint8_t *heff = NULL;
+ int hexp_len, heff_len;
+ const int hmir_len = VB2_SHA256_DIGEST_SIZE;
+ vb2_error_t rv;
- /* Get current EC hash. */
- const uint8_t *ec_hash = NULL;
- int ec_hash_size;
- vb2_error_t rv = vb2ex_ec_hash_image(select, &ec_hash, &ec_hash_size);
+ /*
+ * Get expected EC hash and length.
+ */
+ rv = vb2ex_ec_get_expected_image_hash(select, &hexp, &hexp_len);
+ if (rv) {
+ VB2_DEBUG("vb2ex_ec_get_expected_image_hash() returned %#x\n",
+ rv);
+ request_recovery(ctx, VB2_RECOVERY_EC_EXPECTED_HASH);
+ return VB2_ERROR_EC_HASH_EXPECTED;
+ }
+ VB2_DEBUG("Hexp %10s: ", image_name_to_string(select));
+ print_hash(hexp, hexp_len);
+
+ /*
+ * Get mirrored EC hash. This returns NULL on old systems. On new
+ * systems without EFS2, Hmir will be updated but unused.
+ *
+ * If it's called from update_ec, Hmir and Hexp are already synced.
+ */
+ hmir = vb2_secdata_kernel_get_ec_hash(ctx);
+ if (hmir && select == VB_SELECT_FIRMWARE_EC_ACTIVE) {
+ VB2_DEBUG(" %10s: ", "Hmir");
+ print_hash(hmir, hmir_len);
+ if (hmir_len != hexp_len) {
+ VB2_DEBUG("Hmir size (%d) != Hexp size (%d)\n",
+ hmir_len, hexp_len);
+ request_recovery(ctx, VB2_RECOVERY_EC_HASH_SIZE);
+ return VB2_ERROR_EC_HASH_SIZE;
+ }
+ if (vb2_safe_memcmp(hmir, hexp, hexp_len)) {
+ VB2_DEBUG("Hmir != Hexp. Update Hmir.\n");
+ vb2_secdata_kernel_set_ec_hash(ctx, hexp);
+ }
+ }
+
+ /*
+ * Get effective EC hash and length.
+ */
+ rv = vb2ex_ec_hash_image(select, &heff, &heff_len);
if (rv) {
VB2_DEBUG("vb2ex_ec_hash_image() returned %#x\n", rv);
request_recovery(ctx, VB2_RECOVERY_EC_HASH_FAILED);
return VB2_ERROR_EC_HASH_IMAGE;
}
- print_hash(ec_hash, ec_hash_size, image_name_to_string(select));
+ VB2_DEBUG("Heff %10s: ", image_name_to_string(select));
+ print_hash(heff, heff_len);
- /* Get expected EC hash. */
- const uint8_t *hash = NULL;
- int hash_size;
- rv = vb2ex_ec_get_expected_image_hash(select, &hash, &hash_size);
- if (rv) {
- VB2_DEBUG("vb2ex_ec_get_expected_image_hash() returned %#x\n", rv);
- request_recovery(ctx, VB2_RECOVERY_EC_EXPECTED_HASH);
- return VB2_ERROR_EC_HASH_EXPECTED;
- }
- if (ec_hash_size != hash_size) {
- VB2_DEBUG("EC uses %d-byte hash, but AP-RW contains %d bytes\n",
- ec_hash_size, hash_size);
+ /* Lengths should match. */
+ if (heff_len != hexp_len) {
+ VB2_DEBUG("EC uses %d-byte hash but AP-RW contains %d bytes\n",
+ heff_len, hexp_len);
request_recovery(ctx, VB2_RECOVERY_EC_HASH_SIZE);
return VB2_ERROR_EC_HASH_SIZE;
}
- if (vb2_safe_memcmp(ec_hash, hash, hash_size)) {
- print_hash(hash, hash_size, "Expected");
+ if (vb2_safe_memcmp(heff, hexp, hexp_len)) {
+ VB2_DEBUG("Heff != Hexp. Schedule update\n");
sd->flags |= SYNC_FLAG(select);
}
@@ -177,6 +210,8 @@ static vb2_error_t update_ec(struct vb2_context *ctx,
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
}
+ VB2_DEBUG("Updated %s successfully\n", image_name_to_string(select));
+
return VB2_SUCCESS;
}
@@ -226,21 +261,23 @@ static vb2_error_t sync_ec(struct vb2_context *ctx)
const enum vb2_firmware_selection select_rw = EC_EFS ?
VB_SELECT_FIRMWARE_EC_UPDATE :
VB_SELECT_FIRMWARE_EC_ACTIVE;
- VB2_DEBUG("select_rw=%d\n", select_rw);
+ VB2_DEBUG("select_rw=%s\n", image_name_to_string(select_rw));
/* Update the RW Image */
if (sd->flags & SYNC_FLAG(select_rw)) {
if (VB2_SUCCESS != update_ec(ctx, select_rw))
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- /* Updated successfully. Cold reboot to switch to the new RW.
- * TODO: Switch slot and proceed if EC is still in RO. */
- if (EC_EFS) {
+ /* Updated successfully. Cold reboot to switch to the new RW. */
+ if (ctx->flags & VB2_CONTEXT_NO_BOOT) {
VB2_DEBUG("Rebooting to jump to new EC-RW\n");
+ return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
+ } else if (EC_EFS) {
+ VB2_DEBUG("Rebooting to switch to new EC-RW\n");
return VBERROR_EC_REBOOT_TO_SWITCH_RW;
}
}
- /* Tell EC to jump to its RW image */
+ /* Tell EC to jump to RW. It should already be in RW for EFS2. */
if (!(sd->flags & VB2_SD_FLAG_ECSYNC_EC_IN_RW)) {
VB2_DEBUG("jumping to EC-RW\n");
rv = vb2ex_ec_jump_to_rw();
@@ -344,9 +381,10 @@ static vb2_error_t ec_sync_phase1(struct vb2_context *ctx)
if (check_ec_active(ctx))
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- /* Check if we need to update RW. Failures trigger recovery mode. */
+ /* Check if we need to update RW. Failures trigger recovery mode. */
if (check_ec_hash(ctx, VB_SELECT_FIRMWARE_EC_ACTIVE))
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
+
/* See if we need to update EC-RO. */
if (vb2_nv_get(ctx, VB2_NV_TRY_RO_SYNC) &&
check_ec_hash(ctx, VB_SELECT_FIRMWARE_READONLY)) {
@@ -360,7 +398,7 @@ static vb2_error_t ec_sync_phase1(struct vb2_context *ctx)
* If EC supports RW-A/B slots, we can proceed but we need
* to jump to the new RW version later.
*/
- if ((sd->flags & VB2_SD_FLAG_ECSYNC_EC_RW) &&
+ if ((sd->flags & SYNC_FLAG(VB_SELECT_FIRMWARE_EC_ACTIVE)) &&
(sd->flags & VB2_SD_FLAG_ECSYNC_EC_IN_RW) && !EC_EFS) {
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
}
@@ -382,8 +420,9 @@ static int ec_will_update_slowly(struct vb2_context *ctx)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
- return (((sd->flags & VB2_SD_FLAG_ECSYNC_EC_RO) ||
- (sd->flags & VB2_SD_FLAG_ECSYNC_EC_RW)) && EC_SLOW_UPDATE);
+ return (((sd->flags & SYNC_FLAG(VB_SELECT_FIRMWARE_READONLY)) ||
+ (sd->flags & SYNC_FLAG(VB_SELECT_FIRMWARE_EC_ACTIVE)))
+ && EC_SLOW_UPDATE);
}
/**
diff --git a/firmware/2lib/2misc.c b/firmware/2lib/2misc.c
index e64f4380..7a8c295f 100644
--- a/firmware/2lib/2misc.c
+++ b/firmware/2lib/2misc.c
@@ -401,6 +401,9 @@ vb2_error_t vb2_enable_developer_mode(struct vb2_context *ctx)
test_mockable
int vb2_allow_recovery(struct vb2_context *ctx)
{
+ if (ctx->flags & VB2_CONTEXT_NO_BOOT)
+ return 0;
+
/* VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY forces this to always return
true. */
if (vb2_get_gbb(ctx)->flags & VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY)
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h
index 9bd07297..2a9a476e 100644
--- a/firmware/2lib/include/2api.h
+++ b/firmware/2lib/include/2api.h
@@ -192,6 +192,11 @@ enum vb2_context_flags {
* Deprecated with CL:1975390.
*/
VB2_CONTEXT_DEPRECATED_DETACHABLE_UI = (1 << 22),
+
+ /*
+ * NO_BOOT means the OS is not allowed to boot. Only relevant for EFS2.
+ */
+ VB2_CONTEXT_NO_BOOT = (1 << 23),
};
/* Helper for aligning fields in vb2_context. */
diff --git a/firmware/2lib/include/2recovery_reasons.h b/firmware/2lib/include/2recovery_reasons.h
index ba7beb8f..99ed4789 100644
--- a/firmware/2lib/include/2recovery_reasons.h
+++ b/firmware/2lib/include/2recovery_reasons.h
@@ -234,6 +234,12 @@ enum vb2_nv_recovery {
/* FWMP secure data initialization error */
VB2_RECOVERY_SECDATA_FWMP_INIT = 0x62,
+ /* Failed to get boot mode from TPM/Cr50 */
+ VB2_RECOVERY_CR50_BOOT_MODE = 0x63,
+
+ /* Attempt to escape from NO_BOOT mode was detected */
+ VB2_RECOVERY_ESCAPE_NO_BOOT = 0x64,
+
/* Unspecified/unknown error in rewritable firmware */
VB2_RECOVERY_RW_UNSPECIFIED = 0x7f,
diff --git a/firmware/2lib/include/2return_codes.h b/firmware/2lib/include/2return_codes.h
index 5e5e5266..79b1a122 100644
--- a/firmware/2lib/include/2return_codes.h
+++ b/firmware/2lib/include/2return_codes.h
@@ -630,6 +630,9 @@ enum vb2_return_code {
/* Problem with workbuf validity (see vb2api_init and vb2api_reinit) */
VB2_ERROR_WORKBUF_INVALID,
+ /* Escape from NO_BOOT mode is detected. */
+ VB2_ERROR_ESCAPE_NO_BOOT,
+
/**********************************************************************
* API-level errors
*/
diff --git a/firmware/include/tss_constants.h b/firmware/include/tss_constants.h
index e73b4ef1..0dd3ab08 100644
--- a/firmware/include/tss_constants.h
+++ b/firmware/include/tss_constants.h
@@ -26,6 +26,7 @@
#define TPM_E_INTERNAL_ERROR ((uint32_t) 0x0000500d) /* vboot local */
#define TPM_E_INVALID_RESPONSE ((uint32_t) 0x0000500e) /* vboot local */
#define TPM_E_BUFFER_SIZE ((uint32_t) 0x0000500f) /* vboot local */
+#define TPM_E_NO_SUCH_COMMAND ((uint32_t) 0x00005010) /* vboot local */
/*
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 2f0b4b70..42dded12 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -310,6 +310,15 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
* entering either manual recovery UI or BROKEN screen shortly.
*/
vb2ex_commit_data(ctx);
+ /*
+ * In EFS2, recovery mode can be entered even when battery is
+ * drained or damaged. EC-RO sets NO_BOOT flag in such case and
+ * uses PD power to boot AP.
+ *
+ * TODO: Inform user why recovery failed to start.
+ */
+ if (ctx->flags & VB2_CONTEXT_NO_BOOT)
+ VB2_DEBUG("NO_BOOT in RECOVERY mode\n");
/* Recovery boot. This has UI. */
if (LEGACY_MENU_UI)
@@ -344,6 +353,13 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
rv = VbBootNormal(ctx);
}
+ if (VB2_SUCCESS == rv && (ctx->flags & VB2_CONTEXT_NO_BOOT)) {
+ /* Stop all cases returning SUCCESS against NO_BOOT flag. */
+ VB2_DEBUG("Blocking boot in NO_BOOT mode.\n");
+ vb2api_fail(ctx, VB2_RECOVERY_RW_INVALID_OS, rv);
+ rv = VB2_ERROR_ESCAPE_NO_BOOT;
+ }
+
if (rv == VB2_SUCCESS)
vb2_kernel_fill_kparams(ctx, kparams);
diff --git a/firmware/lib/vboot_display.c b/firmware/lib/vboot_display.c
index 6e531988..258619fb 100644
--- a/firmware/lib/vboot_display.c
+++ b/firmware/lib/vboot_display.c
@@ -200,6 +200,10 @@ const char *RecoveryReasonString(uint8_t code)
return "Failed to disable TPM before running untrusted code";
case VB2_RECOVERY_ALTFW_HASH_FAILED:
return "Verification of alternative firmware payload failed";
+ case VB2_RECOVERY_CR50_BOOT_MODE:
+ return "Failed to get boot mode from Cr50";
+ case VB2_RECOVERY_ESCAPE_NO_BOOT:
+ return "Attempt to escape from NO_BOOT mode was detected";
case VB2_RECOVERY_RW_UNSPECIFIED:
return "Unspecified/unknown error in RW firmware";
case VB2_RECOVERY_US_TEST:
diff --git a/tests/vb2_ec_sync_tests.c b/tests/vb2_ec_sync_tests.c
index eae83b0c..26be9baf 100644
--- a/tests/vb2_ec_sync_tests.c
+++ b/tests/vb2_ec_sync_tests.c
@@ -8,6 +8,7 @@
#include "2common.h"
#include "2misc.h"
#include "2nvstorage.h"
+#include "2secdata.h"
#include "2sysincludes.h"
#include "host_common.h"
#include "load_kernel_fw.h"
@@ -22,7 +23,7 @@ static int ec_ro_updated;
static int ec_rw_updated;
static int ec_ro_protected;
static int ec_rw_protected;
-static int ec_run_image;
+static int ec_run_image; /* 0 = RO, 1 = RW */
static vb2_error_t in_rw_retval;
static int protect_retval;
@@ -38,11 +39,12 @@ static uint32_t screens_count = 0;
static uint8_t mock_ec_ro_hash[32];
static uint8_t mock_ec_rw_hash[32];
+static uint8_t hmir[32];
static int mock_ec_ro_hash_size;
static int mock_ec_rw_hash_size;
-static uint8_t want_ec_hash[32];
+static uint8_t hexp[32];
static uint8_t update_hash;
-static int want_ec_hash_size;
+static int hexp_size;
static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
__attribute__((aligned(VB2_WORKBUF_ALIGN)));
static struct vb2_context *ctx;
@@ -53,7 +55,7 @@ static struct vb2_gbb_header gbb;
static void ResetMocks(void)
{
TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
- "vb2api_init failed");
+ "vb2api_init passed");
ctx->flags = VB2_CONTEXT_EC_SYNC_SUPPORTED;
vb2_nv_init(ctx);
@@ -67,7 +69,7 @@ static void ResetMocks(void)
ec_rw_updated = 0;
ec_ro_protected = 0;
ec_rw_protected = 0;
- ec_run_image = 0; /* 0 = RO, 1 = RW */
+ ec_run_image = 0;
in_rw_retval = VB2_SUCCESS;
protect_retval = VB2_SUCCESS;
@@ -86,14 +88,21 @@ static void ResetMocks(void)
mock_ec_rw_hash[0] = 42;
mock_ec_rw_hash_size = sizeof(mock_ec_rw_hash);
- memset(want_ec_hash, 0, sizeof(want_ec_hash));
- want_ec_hash[0] = 42;
- want_ec_hash_size = sizeof(want_ec_hash);
+ memset(hexp, 0, sizeof(hexp));
+ hexp[0] = 42;
+ hexp_size = sizeof(hexp);
update_hash = 42;
memset(screens_displayed, 0, sizeof(screens_displayed));
screens_count = 0;
+
+ vb2api_secdata_kernel_create(ctx);
+ vb2_secdata_kernel_init(ctx);
+
+ memset(hmir, 0, sizeof(hmir));
+ hmir[0] = 42;
+ vb2_secdata_kernel_set_ec_hash(ctx, hmir);
}
/* Mock functions */
@@ -162,10 +171,10 @@ vb2_error_t vb2ex_ec_hash_image(enum vb2_firmware_selection select,
vb2_error_t vb2ex_ec_get_expected_image_hash(enum vb2_firmware_selection select,
const uint8_t **hash, int *hash_size)
{
- *hash = want_ec_hash;
- *hash_size = want_ec_hash_size;
+ *hash = hexp;
+ *hash_size = hexp_size;
- return want_ec_hash_size ? VB2_SUCCESS : VB2_ERROR_MOCK;
+ return hexp_size ? VB2_SUCCESS : VB2_ERROR_MOCK;
}
vb2_error_t vb2ex_ec_update_image(enum vb2_firmware_selection select)
@@ -204,6 +213,11 @@ static void test_ssync(vb2_error_t retval, int recovery_reason,
TEST_EQ(vb2api_ec_sync(ctx), retval, desc);
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
recovery_reason, " recovery reason");
+ struct vb2_secdata_kernel_v1 *sec = (void *)ctx->secdata_kernel;
+ if (sec->struct_version >= VB2_SECDATA_KERNEL_VERSION_V10) {
+ const uint8_t *hash = vb2_secdata_kernel_get_ec_hash(ctx);
+ TEST_EQ(memcmp(hash, hexp, sizeof(hexp)), 0, "Hmir synced");
+ }
}
/* Tests */
@@ -212,7 +226,7 @@ static void VbSoftwareSyncTest(void)
{
/* Check flag toggling */
ResetMocks();
- test_ssync(VB2_SUCCESS, 0, "Normal sync");
+ test_ssync(VB2_SUCCESS, 0, "Normal (no) sync");
TEST_NEQ(sd->status & VB2_SD_STATUS_EC_SYNC_COMPLETE, 0,
" EC sync complete");
TEST_EQ(ec_ro_updated, 0, " ec ro updated");
@@ -292,7 +306,7 @@ static void VbSoftwareSyncTest(void)
TEST_EQ(ec_run_image, 0, " ec run image");
ResetMocks();
- want_ec_hash_size = 0;
+ hexp_size = 0;
test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
VB2_RECOVERY_EC_EXPECTED_HASH, "Bad precalculated hash");
TEST_EQ(ec_ro_updated, 0, " ec ro updated");
@@ -302,7 +316,7 @@ static void VbSoftwareSyncTest(void)
TEST_EQ(ec_run_image, 0, " ec run image");
ResetMocks();
- want_ec_hash_size = 16;
+ hexp_size = 16;
test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
VB2_RECOVERY_EC_HASH_SIZE,
"Hash size mismatch");
@@ -313,9 +327,22 @@ static void VbSoftwareSyncTest(void)
TEST_EQ(ec_run_image, 0, " ec run image");
ResetMocks();
- want_ec_hash_size = 4;
+ hexp_size = 4;
mock_ec_rw_hash_size = 4;
- test_ssync(0, 0, "Custom hash size");
+ test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, VB2_RECOVERY_EC_HASH_SIZE,
+ "Custom hash size secdata_kernel v1");
+ TEST_EQ(ec_ro_updated, 0, " ec ro updated");
+ TEST_EQ(ec_rw_updated, 0, " ec rw updated");
+ TEST_EQ(ec_ro_protected, 0, " ec ro protected");
+ TEST_EQ(ec_rw_protected, 0, " ec rw protected");
+ TEST_EQ(ec_run_image, 0, " ec run image");
+
+ ResetMocks();
+ vb2api_secdata_kernel_create_v0(ctx);
+ vb2_secdata_kernel_init(ctx);
+ hexp_size = 4;
+ mock_ec_rw_hash_size = 4;
+ test_ssync(0, 0, "Custom hash size secdata_kernel v0");
TEST_EQ(ec_ro_updated, 0, " ec ro updated");
TEST_EQ(ec_rw_updated, 0, " ec rw updated");
TEST_EQ(ec_ro_protected, 1, " ec ro protected");
@@ -334,6 +361,48 @@ static void VbSoftwareSyncTest(void)
TEST_EQ(ec_rw_protected, 0, " ec rw protected");
TEST_EQ(ec_run_image, 1, " ec run image");
+ /* Hexp != Hmir == Heff */
+ ResetMocks();
+ hmir[0] = 43;
+ vb2_secdata_kernel_set_ec_hash(ctx, hmir);
+ ec_run_image = 1;
+ mock_ec_rw_hash[0] = 43;
+ test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
+ 0, "Reboot after synching Hmir");
+ TEST_EQ(ec_ro_updated, 0, " ec ro updated");
+ TEST_EQ(ec_rw_updated, 0, " ec rw updated");
+ TEST_EQ(ec_ro_protected, 0, " ec ro protected");
+ TEST_EQ(ec_rw_protected, 0, " ec rw protected");
+ TEST_EQ(ec_run_image, 1, " ec run image");
+
+ /* Hexp == Hmir != Heff */
+ ResetMocks();
+ ec_run_image = 0;
+ ctx->flags |= VB2_CONTEXT_NO_BOOT;
+ mock_ec_rw_hash[0] = 43;
+ test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
+ 0, "Reboot after synching Heff");
+ TEST_EQ(ec_ro_updated, 0, " ec ro updated");
+ TEST_EQ(ec_rw_updated, 1, " ec rw updated");
+ TEST_EQ(ec_ro_protected, 0, " ec ro protected");
+ TEST_EQ(ec_rw_protected, 0, " ec rw protected");
+ TEST_EQ(ec_run_image, 0, " ec run image");
+
+ /* Hexp != Hmir != Heff */
+ ResetMocks();
+ hmir[0] = 44;
+ vb2_secdata_kernel_set_ec_hash(ctx, hmir);
+ ec_run_image = 0;
+ ctx->flags |= VB2_CONTEXT_NO_BOOT;
+ mock_ec_rw_hash[0] = 43;
+ test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
+ 0, "Reboot after synching Hmir and Heff");
+ TEST_EQ(ec_ro_updated, 0, " ec ro updated");
+ TEST_EQ(ec_rw_updated, 1, " ec rw updated");
+ TEST_EQ(ec_ro_protected, 0, " ec ro protected");
+ TEST_EQ(ec_rw_protected, 0, " ec rw protected");
+ TEST_EQ(ec_run_image, 0, " ec run image");
+
ResetMocks();
mock_ec_rw_hash[0]++;
vb2_nv_set(ctx, VB2_NV_TRY_RO_SYNC, 1);
diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c
index a7c088c0..38d70552 100644
--- a/tests/vboot_api_kernel4_tests.c
+++ b/tests/vboot_api_kernel4_tests.c
@@ -73,6 +73,8 @@ static void reset_common_data(void)
memset(mock_presence, 0, sizeof(mock_presence));
mock_presence_count = 0;
+
+ sd->status |= VB2_SD_STATUS_SECDATA_KERNEL_INIT;
}
static void test_slk(vb2_error_t retval, int recovery_reason, const char *desc)