diff options
author | Daisuke Nojiri <dnojiri@chromium.org> | 2019-10-22 15:37:14 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-03-05 02:40:39 +0000 |
commit | 5059062dd352e3864fb68f8a061e87bd7055d12a (patch) | |
tree | e2897970757ee3337d1c2e9cc506084e0d382709 | |
parent | 1b4affa3650261efa2684a6e551030291fe00590 (diff) | |
download | vboot-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.c | 103 | ||||
-rw-r--r-- | firmware/2lib/2misc.c | 3 | ||||
-rw-r--r-- | firmware/2lib/include/2api.h | 5 | ||||
-rw-r--r-- | firmware/2lib/include/2recovery_reasons.h | 6 | ||||
-rw-r--r-- | firmware/2lib/include/2return_codes.h | 3 | ||||
-rw-r--r-- | firmware/include/tss_constants.h | 1 | ||||
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 16 | ||||
-rw-r--r-- | firmware/lib/vboot_display.c | 4 | ||||
-rw-r--r-- | tests/vb2_ec_sync_tests.c | 101 | ||||
-rw-r--r-- | tests/vboot_api_kernel4_tests.c | 2 |
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) |