diff options
author | Joel Kitching <kitching@google.com> | 2020-03-06 14:56:14 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-03-09 08:43:37 +0000 |
commit | cebb4f5912d2a72f86e43d9552edcf881806c6b9 (patch) | |
tree | 8ff44bf028a1a98f81ea62684876e224f5d35985 /tests | |
parent | 4da0add3b390e9aecd2113375abae874318c7cf4 (diff) | |
download | vboot-cebb4f5912d2a72f86e43d9552edcf881806c6b9.tar.gz |
vboot: create 2kernel.c for kernel-related functions
Create 2kernel.c for kernel-related functions (including
both internal and API-facing).
Relocate functions which are currently in active use from
lib20/api_kernel.c to 2lib/2kernel.c.
Create vb2_kernel_tests.c and move appropriate tests there.
Tests for vb2_normal_boot (previously VbBootNormal) will
be added in a subsequent CL.
BUG=b:124141368, chromium:968464
TEST=make clean && make runtests
BRANCH=none
Change-Id: I153ea318ba238b7b30bf871105388437f63075d1
Signed-off-by: Joel Kitching <kitching@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2091126
Reviewed-by: Joel Kitching <kitching@chromium.org>
Commit-Queue: Joel Kitching <kitching@chromium.org>
Tested-by: Joel Kitching <kitching@chromium.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/vb20_api_kernel_tests.c | 115 | ||||
-rw-r--r-- | tests/vb2_kernel_tests.c | 270 | ||||
-rw-r--r-- | tests/vboot_legacy_clamshell_tests.c | 17 | ||||
-rw-r--r-- | tests/vboot_legacy_menu_tests.c | 3 |
4 files changed, 281 insertions, 124 deletions
diff --git a/tests/vb20_api_kernel_tests.c b/tests/vb20_api_kernel_tests.c index dad612f0..aa7686b0 100644 --- a/tests/vb20_api_kernel_tests.c +++ b/tests/vb20_api_kernel_tests.c @@ -223,120 +223,6 @@ vb2_error_t vb2_verify_digest(const struct vb2_public_key *key, /* Tests */ -static void phase1_tests(void) -{ - struct vb2_packed_key *k; - uint32_t wb_used_before; - - /* Test successful call */ - reset_common_data(FOR_PHASE1); - TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 good"); - /* Make sure normal key was loaded */ - TEST_EQ(sd->kernel_key_offset, sd->preamble_offset + - offsetof(struct vb2_fw_preamble, kernel_subkey), - " workbuf key offset"); - k = vb2_member_of(sd, sd->kernel_key_offset); - TEST_EQ(sd->kernel_key_size, k->key_offset + k->key_size, - " workbuf key size"); - TEST_EQ(sd->workbuf_used, - vb2_wb_round_up(sd->kernel_key_offset + - sd->kernel_key_size), - " workbuf used"); - TEST_EQ(k->algorithm, 7, " key algorithm"); - TEST_EQ(k->key_size, sizeof(fw_kernel_key_data), " key_size"); - TEST_EQ(memcmp((uint8_t *)k + k->key_offset, fw_kernel_key_data, - k->key_size), 0, " key data"); - TEST_EQ(sd->kernel_version_secdata, 0x20002, - " secdata_kernel version"); - - /* Test successful call in recovery mode */ - reset_common_data(FOR_PHASE1); - ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; - /* No preamble needed in recovery mode */ - sd->workbuf_used = sd->preamble_offset; - sd->preamble_offset = sd->preamble_size = 0; - wb_used_before = sd->workbuf_used; - TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 rec good"); - /* Make sure recovery key was loaded */ - TEST_EQ(sd->kernel_key_offset, wb_used_before, - " workbuf key offset"); - k = vb2_member_of(sd, sd->kernel_key_offset); - TEST_EQ(sd->kernel_key_size, k->key_offset + k->key_size, - " workbuf key size"); - TEST_EQ(sd->workbuf_used, - vb2_wb_round_up(sd->kernel_key_offset + - sd->kernel_key_size), - " workbuf used"); - TEST_EQ(k->algorithm, 11, " key algorithm"); - TEST_EQ(k->key_size, sizeof(mock_gbb.recovery_key_data), " key_size"); - TEST_EQ(memcmp((uint8_t *)k + k->key_offset, - mock_gbb.recovery_key_data, k->key_size), 0, - " key data"); - TEST_EQ(sd->kernel_version_secdata, 0x20002, - " secdata_kernel version"); - - /* Bad secdata_kernel causes failure in normal mode only */ - reset_common_data(FOR_PHASE1); - ctx->secdata_kernel[2] ^= 0x33; /* 3rd byte is CRC */ - TEST_EQ(vb2api_kernel_phase1(ctx), VB2_ERROR_SECDATA_KERNEL_CRC, - "phase1 bad secdata_kernel"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), - VB2_RECOVERY_SECDATA_KERNEL_INIT, " recovery reason"); - - reset_common_data(FOR_PHASE1); - ctx->secdata_kernel[0] ^= 0x33; - ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; - TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 bad secdata_kernel rec"); - TEST_EQ(sd->kernel_version_secdata, 0, " secdata_kernel version"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), - VB2_RECOVERY_NOT_REQUESTED, " no recovery"); - - /* Bad secdata_fwmp causes failure in normal mode only */ - reset_common_data(FOR_PHASE1); - mock_secdata_fwmp_check_retval = VB2_ERROR_SECDATA_FWMP_CRC; - TEST_EQ(vb2api_kernel_phase1(ctx), mock_secdata_fwmp_check_retval, - "phase1 bad secdata_fwmp"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), - VB2_RECOVERY_SECDATA_FWMP_INIT, " recovery reason"); - - reset_common_data(FOR_PHASE1); - mock_secdata_fwmp_check_retval = VB2_ERROR_SECDATA_FWMP_CRC; - ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; - TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 bad secdata_fwmp rec"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), - VB2_RECOVERY_NOT_REQUESTED, " no recovery"); - - /* Failures while reading recovery key */ - reset_common_data(FOR_PHASE1); - ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; - mock_gbb.h.recovery_key_size = sd->workbuf_size - 1; - mock_gbb.recovery_key.key_size = - mock_gbb.h.recovery_key_size - sizeof(mock_gbb.recovery_key); - TEST_EQ(vb2api_kernel_phase1(ctx), VB2_SUCCESS, - "phase1 rec workbuf key"); - TEST_EQ(sd->kernel_key_offset, 0, " workbuf key offset"); - TEST_EQ(sd->kernel_key_size, 0, " workbuf key size"); - mock_gbb.h.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY; - TEST_ABORT(vb2api_kernel_phase1(ctx), " fatal for manual recovery"); - - reset_common_data(FOR_PHASE1); - ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; - mock_read_res_fail_on_call = 1; - TEST_EQ(vb2api_kernel_phase1(ctx), VB2_SUCCESS, - "phase1 rec gbb read key"); - TEST_EQ(sd->kernel_key_offset, 0, " workbuf key offset"); - TEST_EQ(sd->kernel_key_size, 0, " workbuf key size"); - mock_gbb.h.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY; - mock_read_res_fail_on_call = 1; - TEST_ABORT(vb2api_kernel_phase1(ctx), " fatal for manual recovery"); - - /* Failures while parsing subkey from firmware preamble */ - reset_common_data(FOR_PHASE1); - sd->preamble_size = 0; - TEST_EQ(vb2api_kernel_phase1(ctx), VB2_ERROR_API_KPHASE1_PREAMBLE, - "phase1 fw preamble"); -} - static void load_kernel_vblock_tests(void) { reset_common_data(FOR_PHASE1); @@ -472,7 +358,6 @@ static void phase3_tests(void) int main(int argc, char* argv[]) { - phase1_tests(); load_kernel_vblock_tests(); get_kernel_size_tests(); verify_kernel_data_tests(); diff --git a/tests/vb2_kernel_tests.c b/tests/vb2_kernel_tests.c new file mode 100644 index 00000000..bd64fb08 --- /dev/null +++ b/tests/vb2_kernel_tests.c @@ -0,0 +1,270 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Tests for kernel selection, loading, verification, and booting. + */ + +#include "2api.h" +#include "2common.h" +#include "2misc.h" +#include "2nvstorage.h" +#include "2rsa.h" +#include "2secdata.h" +#include "2sysincludes.h" +#include "test_common.h" +#include "vb2_common.h" +#include "vboot_struct.h" + +/* Common context for tests */ +static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] + __attribute__((aligned(VB2_WORKBUF_ALIGN))); +static struct vb2_context *ctx; +static struct vb2_shared_data *sd; +static struct vb2_fw_preamble *fwpre; +static const char fw_kernel_key_data[36] = "Test kernel key data"; + +/* Mocked function data */ + +static struct { + struct vb2_gbb_header h; + struct vb2_packed_key recovery_key; + char recovery_key_data[32]; +} mock_gbb; + +static int mock_read_res_fail_on_call; +static int mock_secdata_fwmp_check_retval; + +/* Type of test to reset for */ +enum reset_type { + FOR_PHASE1, +}; + +static void reset_common_data(enum reset_type t) +{ + struct vb2_packed_key *k; + + memset(workbuf, 0xaa, sizeof(workbuf)); + + TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), + "vb2api_init failed"); + + sd = vb2_get_sd(ctx); + vb2_nv_init(ctx); + + vb2api_secdata_kernel_create(ctx); + vb2_secdata_kernel_init(ctx); + vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS, 0x20002); + + mock_read_res_fail_on_call = 0; + mock_secdata_fwmp_check_retval = VB2_SUCCESS; + + /* Recovery key in mock GBB */ + memset(&mock_gbb, 0, sizeof(mock_gbb)); + mock_gbb.recovery_key.algorithm = 11; + mock_gbb.recovery_key.key_offset = + vb2_offset_of(&mock_gbb.recovery_key, + &mock_gbb.recovery_key_data); + mock_gbb.recovery_key.key_size = sizeof(mock_gbb.recovery_key_data); + strcpy(mock_gbb.recovery_key_data, "The recovery key"); + mock_gbb.h.recovery_key_offset = + vb2_offset_of(&mock_gbb, &mock_gbb.recovery_key); + mock_gbb.h.recovery_key_size = + mock_gbb.recovery_key.key_offset + + mock_gbb.recovery_key.key_size; + + + if (t == FOR_PHASE1) { + uint8_t *kdata; + + /* Create mock firmware preamble in the context */ + sd->preamble_offset = sd->workbuf_used; + fwpre = (struct vb2_fw_preamble *) + vb2_member_of(sd, sd->preamble_offset); + k = &fwpre->kernel_subkey; + kdata = (uint8_t *)fwpre + sizeof(*fwpre); + memcpy(kdata, fw_kernel_key_data, sizeof(fw_kernel_key_data)); + k->algorithm = 7; + k->key_offset = vb2_offset_of(k, kdata); + k->key_size = sizeof(fw_kernel_key_data); + sd->preamble_size = sizeof(*fwpre) + k->key_size; + vb2_set_workbuf_used(ctx, + sd->preamble_offset + sd->preamble_size); + + /* Needed to check that secdata_kernel initialization is + performed by phase1 function. */ + sd->status &= ~VB2_SD_STATUS_SECDATA_KERNEL_INIT; + + } +}; + +/* Mocked functions */ + +vb2_error_t vb2api_secdata_fwmp_check(struct vb2_context *c, uint8_t *size) +{ + return mock_secdata_fwmp_check_retval; +} + +struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) +{ + return &mock_gbb.h; +} + +vb2_error_t vb2ex_read_resource(struct vb2_context *c, + enum vb2_resource_index index, uint32_t offset, + void *buf, uint32_t size) +{ + uint8_t *rptr; + uint32_t rsize; + + if (--mock_read_res_fail_on_call == 0) + return VB2_ERROR_MOCK; + + switch(index) { + case VB2_RES_GBB: + rptr = (uint8_t *)&mock_gbb; + rsize = sizeof(mock_gbb); + break; + default: + return VB2_ERROR_EX_READ_RESOURCE_INDEX; + } + + if (offset > rsize || offset + size > rsize) + return VB2_ERROR_EX_READ_RESOURCE_SIZE; + + memcpy(buf, rptr + offset, size); + return VB2_SUCCESS; +} + +/* Tests */ + +static void phase1_tests(void) +{ + struct vb2_packed_key *k; + uint32_t wb_used_before; + + /* Test successful call */ + reset_common_data(FOR_PHASE1); + TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 good"); + /* Make sure normal key was loaded */ + TEST_EQ(sd->kernel_key_offset, sd->preamble_offset + + offsetof(struct vb2_fw_preamble, kernel_subkey), + " workbuf key offset"); + k = vb2_member_of(sd, sd->kernel_key_offset); + TEST_EQ(sd->kernel_key_size, k->key_offset + k->key_size, + " workbuf key size"); + TEST_EQ(sd->workbuf_used, + vb2_wb_round_up(sd->kernel_key_offset + + sd->kernel_key_size), + " workbuf used"); + TEST_EQ(k->algorithm, 7, " key algorithm"); + TEST_EQ(k->key_size, sizeof(fw_kernel_key_data), " key_size"); + TEST_EQ(memcmp((uint8_t *)k + k->key_offset, fw_kernel_key_data, + k->key_size), 0, " key data"); + TEST_EQ(sd->kernel_version_secdata, 0x20002, + " secdata_kernel version"); + + /* Test successful call in recovery mode */ + reset_common_data(FOR_PHASE1); + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + /* No preamble needed in recovery mode */ + sd->workbuf_used = sd->preamble_offset; + sd->preamble_offset = sd->preamble_size = 0; + wb_used_before = sd->workbuf_used; + TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 rec good"); + /* Make sure recovery key was loaded */ + TEST_EQ(sd->kernel_key_offset, wb_used_before, + " workbuf key offset"); + k = vb2_member_of(sd, sd->kernel_key_offset); + TEST_EQ(sd->kernel_key_size, k->key_offset + k->key_size, + " workbuf key size"); + TEST_EQ(sd->workbuf_used, + vb2_wb_round_up(sd->kernel_key_offset + + sd->kernel_key_size), + " workbuf used"); + TEST_EQ(k->algorithm, 11, " key algorithm"); + TEST_EQ(k->key_size, sizeof(mock_gbb.recovery_key_data), " key_size"); + TEST_EQ(memcmp((uint8_t *)k + k->key_offset, + mock_gbb.recovery_key_data, k->key_size), 0, + " key data"); + TEST_EQ(sd->kernel_version_secdata, 0x20002, + " secdata_kernel version"); + + /* Bad secdata_kernel causes failure in normal mode only */ + reset_common_data(FOR_PHASE1); + ctx->secdata_kernel[2] ^= 0x33; /* 3rd byte is CRC */ + TEST_EQ(vb2api_kernel_phase1(ctx), VB2_ERROR_SECDATA_KERNEL_CRC, + "phase1 bad secdata_kernel"); + TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), + VB2_RECOVERY_SECDATA_KERNEL_INIT, " recovery reason"); + + reset_common_data(FOR_PHASE1); + ctx->secdata_kernel[0] ^= 0x33; + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 bad secdata_kernel rec"); + TEST_EQ(sd->kernel_version_secdata, 0, " secdata_kernel version"); + TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), + VB2_RECOVERY_NOT_REQUESTED, " no recovery"); + + /* Bad secdata_fwmp causes failure in normal mode only */ + reset_common_data(FOR_PHASE1); + mock_secdata_fwmp_check_retval = VB2_ERROR_SECDATA_FWMP_CRC; + TEST_EQ(vb2api_kernel_phase1(ctx), mock_secdata_fwmp_check_retval, + "phase1 bad secdata_fwmp"); + TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), + VB2_RECOVERY_SECDATA_FWMP_INIT, " recovery reason"); + + reset_common_data(FOR_PHASE1); + mock_secdata_fwmp_check_retval = VB2_ERROR_SECDATA_FWMP_CRC; + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 bad secdata_fwmp rec"); + TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), + VB2_RECOVERY_NOT_REQUESTED, " no recovery"); + + /* Failures while reading recovery key */ + reset_common_data(FOR_PHASE1); + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + mock_gbb.h.recovery_key_size = sd->workbuf_size - 1; + mock_gbb.recovery_key.key_size = + mock_gbb.h.recovery_key_size - sizeof(mock_gbb.recovery_key); + TEST_EQ(vb2api_kernel_phase1(ctx), VB2_SUCCESS, + "phase1 rec workbuf key"); + TEST_EQ(sd->kernel_key_offset, 0, " workbuf key offset"); + TEST_EQ(sd->kernel_key_size, 0, " workbuf key size"); + mock_gbb.h.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY; + TEST_ABORT(vb2api_kernel_phase1(ctx), " fatal for manual recovery"); + + reset_common_data(FOR_PHASE1); + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + mock_read_res_fail_on_call = 1; + TEST_EQ(vb2api_kernel_phase1(ctx), VB2_SUCCESS, + "phase1 rec gbb read key"); + TEST_EQ(sd->kernel_key_offset, 0, " workbuf key offset"); + TEST_EQ(sd->kernel_key_size, 0, " workbuf key size"); + mock_gbb.h.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY; + mock_read_res_fail_on_call = 1; + TEST_ABORT(vb2api_kernel_phase1(ctx), " fatal for manual recovery"); + + /* Failures while parsing subkey from firmware preamble */ + reset_common_data(FOR_PHASE1); + sd->preamble_size = 0; + TEST_EQ(vb2api_kernel_phase1(ctx), VB2_ERROR_API_KPHASE1_PREAMBLE, + "phase1 fw preamble"); +} + +static void normal_boot_tests(void) +{ + /* + * TODO: vb2_normal_boot() tests go here. Relocate from + * vboot_legacy_clamshell_tests.c, and remove comment in + * vboot_legacy_menu_tests.c. + */ +} + +int main(int argc, char* argv[]) +{ + phase1_tests(); + normal_boot_tests(); + + return gTestSuccess ? 0 : 255; +} diff --git a/tests/vboot_legacy_clamshell_tests.c b/tests/vboot_legacy_clamshell_tests.c index 9c7e0c71..4f0849d3 100644 --- a/tests/vboot_legacy_clamshell_tests.c +++ b/tests/vboot_legacy_clamshell_tests.c @@ -6,6 +6,7 @@ */ #include "2common.h" +#include "2kernel.h" #include "2misc.h" #include "2nvstorage.h" #include "2secdata.h" @@ -484,25 +485,25 @@ static void VbBootTest(void) ResetMocks(); vbtlk_expect_fixed = 1; vbtlk_retval = VB2_SUCCESS; - TEST_EQ(VbBootNormal(ctx), VB2_SUCCESS, - "VbBootNormal() returns VB2_SUCCESS"); + TEST_EQ(vb2_normal_boot(ctx), VB2_SUCCESS, + "vb2_normal_boot() returns VB2_SUCCESS"); ResetMocks(); vbtlk_expect_fixed = 1; - TEST_EQ(VbBootNormal(ctx), VB2_ERROR_MOCK, - "VbBootNormal() returns VB2_ERROR_MOCK"); + TEST_EQ(vb2_normal_boot(ctx), VB2_ERROR_MOCK, + "vb2_normal_boot() returns VB2_ERROR_MOCK"); ResetMocks(); vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 1); - TEST_EQ(VbBootNormal(ctx), VBERROR_REBOOT_REQUIRED, - "VbBootNormal() reboot to reset NVRAM display request"); + TEST_EQ(vb2_normal_boot(ctx), VBERROR_REBOOT_REQUIRED, + "vb2_normal_boot() reboot to reset NVRAM display request"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST), 0, " display request reset"); ResetMocks(); vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1); - TEST_EQ(VbBootNormal(ctx), VBERROR_REBOOT_REQUIRED, - "VbBootNormal() reboot to reset NVRAM diag request"); + TEST_EQ(vb2_normal_boot(ctx), VBERROR_REBOOT_REQUIRED, + "vb2_normal_boot() reboot to reset NVRAM diag request"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0, " diag request reset"); } diff --git a/tests/vboot_legacy_menu_tests.c b/tests/vboot_legacy_menu_tests.c index a9af7ddd..57dcb4a6 100644 --- a/tests/vboot_legacy_menu_tests.c +++ b/tests/vboot_legacy_menu_tests.c @@ -235,7 +235,8 @@ vb2_error_t vb2_enable_developer_mode(struct vb2_context *c) /* Tests */ /* - * VbBootNormal tests: Please see VbBootTest in vboot_legacy_clamshell_tests.c + * vb2_normal_boot tests: Please see VbBootTest in + * vboot_legacy_clamshell_tests.c. */ static void VbBootDevTest(void) |