diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/vb2_gbb_tests.c | 350 | ||||
-rw-r--r-- | tests/vb2_misc_tests.c | 9 | ||||
-rw-r--r-- | tests/vboot_api_kernel5_tests.c | 23 | ||||
-rw-r--r-- | tests/vboot_display_tests.c | 82 | ||||
-rw-r--r-- | tests/vboot_kernel_tests.c | 21 |
5 files changed, 401 insertions, 84 deletions
diff --git a/tests/vb2_gbb_tests.c b/tests/vb2_gbb_tests.c new file mode 100644 index 00000000..0c5eff5e --- /dev/null +++ b/tests/vb2_gbb_tests.c @@ -0,0 +1,350 @@ +/* Copyright 2019 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 GBB library. + */ + +#include "2common.h" +#include "2misc.h" +#include "test_common.h" + +/* Mock data */ +static char gbb_data[4096 + sizeof(struct vb2_gbb_header)]; +static struct vb2_gbb_header *gbb = (struct vb2_gbb_header *)gbb_data; +static struct vb2_packed_key *rootkey; +static struct vb2_context ctx; +static struct vb2_workbuf wb; +static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]; + +static void set_gbb_hwid(const char *hwid, size_t size) +{ + memcpy(gbb_data + gbb->hwid_offset, hwid, size); + gbb->hwid_size = size; +} + +static void reset_common_data(void) +{ + int gbb_used; + + memset(gbb_data, 0, sizeof(gbb_data)); + gbb->header_size = sizeof(*gbb); + gbb->major_version = VB2_GBB_MAJOR_VER; + gbb->minor_version = VB2_GBB_MINOR_VER; + gbb->flags = 0; + gbb_used = sizeof(struct vb2_gbb_header); + + gbb->recovery_key_offset = gbb_used; + gbb->recovery_key_size = 64; + gbb_used += gbb->recovery_key_size; + gbb->rootkey_offset = gbb_used; + gbb->rootkey_size = sizeof(struct vb2_packed_key); + gbb_used += gbb->rootkey_size; + + rootkey = ((void *)gbb + gbb->rootkey_offset); + rootkey->key_offset = sizeof(*rootkey); + + gbb->hwid_offset = gbb_used; + const char hwid_src[] = "Test HWID"; + set_gbb_hwid(hwid_src, sizeof(hwid_src)); + + memset(workbuf, 0, sizeof(workbuf)); + memset(&ctx, 0, sizeof(ctx)); + ctx.workbuf = workbuf; + ctx.workbuf_size = sizeof(workbuf); + vb2_init_context(&ctx); + vb2_workbuf_from_ctx(&ctx, &wb); +} + +/* Mocks */ +struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) +{ + return gbb; +} + +int 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; + + switch(index) { + case VB2_RES_GBB: + rptr = (uint8_t *)&gbb_data; + rsize = sizeof(gbb_data); + 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 key_tests(void) +{ + /* Assume that root key and recovery key are dealt with using the same + code in our GBB library functions. */ + struct vb2_packed_key *keyp; + struct vb2_workbuf wborig; + const char key_data[] = "HELLOWORLD"; + uint32_t size; + + /* gbb.offset < sizeof(vb2_gbb_header) */ + reset_common_data(); + wborig = wb; + gbb->rootkey_offset = sizeof(*gbb) - 1; + TEST_EQ(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + VB2_ERROR_GBB_INVALID, + "gbb.rootkey offset too small"); + TEST_TRUE(wb.buf == wborig.buf, + " workbuf restored on error"); + + /* gbb.offset > gbb_data */ + reset_common_data(); + wborig = wb; + gbb->rootkey_offset = sizeof(gbb_data) + 1; + TEST_EQ(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + VB2_ERROR_EX_READ_RESOURCE_SIZE, + "gbb.rootkey offset too large"); + TEST_TRUE(wb.buf == wborig.buf, + " workbuf restored on error"); + + /* gbb.size < sizeof(vb2_packed_key) */ + reset_common_data(); + wborig = wb; + gbb->rootkey_size = sizeof(*rootkey) - 1; + TEST_EQ(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + VB2_ERROR_GBB_INVALID, + "gbb.rootkey size too small"); + TEST_TRUE(wb.buf == wborig.buf, + " workbuf restored on error"); + + /* sizeof(vb2_packed_key) > workbuf.size */ + reset_common_data(); + wborig = wb; + wb.size = sizeof(*rootkey) - 1; + TEST_EQ(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + VB2_ERROR_GBB_WORKBUF, + "workbuf size too small for vb2_packed_key header"); + TEST_TRUE(wb.buf == wborig.buf, + " workbuf restored on error"); + + /* packed_key.offset < sizeof(vb2_packed_key) */ + reset_common_data(); + wborig = wb; + rootkey->key_size = 1; + rootkey->key_offset = sizeof(*rootkey) - 1; + TEST_EQ(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + VB2_ERROR_INSIDE_DATA_OVERLAP, + "rootkey offset too small"); + TEST_TRUE(wb.buf == wborig.buf, + " workbuf restored on error"); + + /* packed_key.offset > gbb_data */ + reset_common_data(); + wborig = wb; + rootkey->key_size = 1; + rootkey->key_offset = sizeof(gbb_data) + 1; + gbb->rootkey_size = rootkey->key_offset + rootkey->key_size; + TEST_EQ(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + VB2_ERROR_EX_READ_RESOURCE_SIZE, + "rootkey size too large"); + TEST_TRUE(wb.buf == wborig.buf, + " workbuf restored on error"); + + /* packed_key.size > workbuf.size */ + reset_common_data(); + wborig = wb; + rootkey->key_size = wb.size + 1; + gbb->rootkey_size = rootkey->key_offset + rootkey->key_size + 1; + TEST_EQ(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + VB2_ERROR_GBB_WORKBUF, + "workbuf size too small for vb2_packed_key contents"); + TEST_TRUE(wb.buf == wborig.buf, + " workbuf restored on error"); + + /* gbb.size < sizeof(vb2_packed_key) + packed_key.size */ + reset_common_data(); + wborig = wb; + rootkey->key_size = 2; + gbb->rootkey_size = rootkey->key_offset + rootkey->key_size - 1; + TEST_EQ(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + VB2_ERROR_INSIDE_DATA_OUTSIDE, + "rootkey size exceeds gbb.rootkey size"); + TEST_TRUE(wb.buf == wborig.buf, + " workbuf restored on error"); + + /* gbb.size == sizeof(vb2_packed_key) + packed_key.size */ + reset_common_data(); + wborig = wb; + rootkey->key_size = sizeof(key_data); + memcpy((void *)rootkey + rootkey->key_offset, + key_data, sizeof(key_data)); + gbb->rootkey_size = rootkey->key_offset + rootkey->key_size; + TEST_SUCC(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + "succeeds when gbb.rootkey and rootkey sizes agree"); + TEST_TRUE(wb.size < wborig.size, + " workbuf shrank on success"); + TEST_EQ(memcmp(rootkey, keyp, rootkey->key_offset + rootkey->key_size), + 0, " copied key data successfully"); + TEST_EQ(size, rootkey->key_offset + rootkey->key_size, + " correct size returned"); + + /* gbb.size > sizeof(vb2_packed_key) + packed_key.size + packed_key.offset = +0 */ + reset_common_data(); + wborig = wb; + rootkey->key_size = 1; + gbb->rootkey_size = rootkey->key_offset + rootkey->key_size + 1; + TEST_SUCC(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + "succeeds when gbb.rootkey is padded after key"); + TEST_TRUE(wb.size < wborig.size, + " workbuf shrank on success"); + TEST_EQ(size, rootkey->key_offset + rootkey->key_size, + " correct size returned"); + + /* gbb.size > sizeof(vb2_packed_key) + packed_key.size + packed_key.offset = +1 */ + reset_common_data(); + wborig = wb; + rootkey->key_offset = sizeof(*rootkey) + 1; + rootkey->key_size = 1; + gbb->rootkey_size = rootkey->key_offset + rootkey->key_size; + TEST_SUCC(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + "succeeds when gbb.rootkey is padded before key"); + TEST_TRUE(wb.size < wborig.size, + " workbuf shrank on success"); + TEST_EQ(size, rootkey->key_offset + rootkey->key_size, + " correct size returned"); + + /* packed_key.size = 0, packed_key.offset = +1 */ + reset_common_data(); + wborig = wb; + rootkey->key_offset = sizeof(*rootkey) + 1; + rootkey->key_size = 0; + gbb->rootkey_size = rootkey->key_offset + rootkey->key_size + 1; + TEST_SUCC(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + "succeeds when gbb.rootkey is padded; empty test key"); + TEST_TRUE(wb.size < wborig.size, + " workbuf shrank on success"); + TEST_EQ(size, rootkey->key_offset + rootkey->key_size, + " correct size returned"); + + /* packed_key.size = 0, packed_key.offset = -1 */ + reset_common_data(); + wborig = wb; + rootkey->key_offset = sizeof(*rootkey) - 1; + rootkey->key_size = 0; + gbb->rootkey_size = sizeof(*rootkey) + rootkey->key_size + 1; + TEST_SUCC(vb2_gbb_read_root_key(&ctx, &keyp, &size, &wb), + "succeeds when gbb.rootkey is padded; empty test key"); + TEST_TRUE(wb.size < wborig.size, + " workbuf shrank on success"); + TEST_EQ(size, sizeof(*rootkey), " correct size returned"); +} + +static void hwid_tests(void) +{ + char hwid[VB2_GBB_HWID_MAX_SIZE]; + uint32_t size; + + /* GBB HWID size = 0 */ + { + reset_common_data(); + gbb->hwid_size = 0; + size = VB2_GBB_HWID_MAX_SIZE; + TEST_EQ(vb2api_gbb_read_hwid(&ctx, hwid, &size), + VB2_ERROR_GBB_INVALID, + "GBB HWID size invalid (HWID missing)"); + } + + /* GBB HWID offset > GBB size */ + { + reset_common_data(); + gbb->hwid_offset = sizeof(gbb_data) + 1; + size = VB2_GBB_HWID_MAX_SIZE; + TEST_EQ(vb2api_gbb_read_hwid(&ctx, hwid, &size), + VB2_ERROR_EX_READ_RESOURCE_SIZE, + "GBB HWID offset invalid"); + } + + /* buffer size < HWID size */ + { + const char hwid_src[] = "Test HWID"; + reset_common_data(); + set_gbb_hwid(hwid_src, sizeof(hwid_src)); + size = sizeof(hwid_src) - 1; + TEST_EQ(vb2api_gbb_read_hwid(&ctx, hwid, &size), + VB2_ERROR_INVALID_PARAMETER, + "HWID too large for buffer"); + } + + /* GBB HWID size < HWID size */ + { + const char hwid_src[] = "Test HWID"; + reset_common_data(); + set_gbb_hwid(hwid_src, sizeof(hwid_src) - 1); + size = sizeof(hwid_src); + TEST_EQ(vb2api_gbb_read_hwid(&ctx, hwid, &size), + VB2_ERROR_INVALID_PARAMETER, + "HWID larger than GBB HWID size"); + } + + /* buffer size == HWID size */ + { + const char hwid_src[] = "Test HWID"; + reset_common_data(); + set_gbb_hwid(hwid_src, sizeof(hwid_src)); + size = sizeof(hwid_src); + TEST_SUCC(vb2api_gbb_read_hwid(&ctx, hwid, &size), + "read normal HWID"); + TEST_EQ(strcmp(hwid, "Test HWID"), 0, " HWID correct"); + TEST_EQ(strlen(hwid) + 1, size, " HWID size consistent"); + TEST_EQ(strlen(hwid), strlen("Test HWID"), + " HWID size correct"); + } + + /* buffer size > HWID size */ + { + const char hwid_src[] = "Test HWID"; + reset_common_data(); + set_gbb_hwid(hwid_src, sizeof(hwid_src)); + size = sizeof(hwid_src) + 1; + TEST_SUCC(vb2api_gbb_read_hwid(&ctx, hwid, &size), + "read normal HWID"); + TEST_EQ(strcmp(hwid, "Test HWID"), 0, " HWID correct"); + TEST_EQ(strlen(hwid) + 1, size, " HWID size consistent"); + TEST_EQ(strlen(hwid), strlen("Test HWID"), + " HWID size correct"); + } + + /* HWID with garbage */ + { + const char hwid_src[] = "Test HWID\0garbagegarbage"; + reset_common_data(); + set_gbb_hwid(hwid_src, sizeof(hwid_src)); + size = VB2_GBB_HWID_MAX_SIZE; + TEST_SUCC(vb2api_gbb_read_hwid(&ctx, hwid, &size), + "read HWID with garbage"); + TEST_EQ(strcmp(hwid, "Test HWID"), 0, " HWID correct"); + TEST_EQ(strlen(hwid) + 1, size, " HWID size consistent"); + TEST_EQ(strlen(hwid), strlen("Test HWID"), + " HWID size correct"); + } +} + +int main(int argc, char* argv[]) +{ + key_tests(); + hwid_tests(); + + return gTestSuccess ? 0 : 255; +} diff --git a/tests/vb2_misc_tests.c b/tests/vb2_misc_tests.c index d36dd44f..3c262633 100644 --- a/tests/vb2_misc_tests.c +++ b/tests/vb2_misc_tests.c @@ -52,6 +52,10 @@ static void reset_common_data(void) }; /* Mocked functions */ +struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) +{ + return &gbb; +} int vb2ex_read_resource(struct vb2_context *c, enum vb2_resource_index index, @@ -77,11 +81,6 @@ int vb2ex_tpm_clear_owner(struct vb2_context *c) } /* Tests */ -struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) -{ - return &gbb; -} - static void init_context_tests(void) { /* Use our own context struct so we can re-init it */ diff --git a/tests/vboot_api_kernel5_tests.c b/tests/vboot_api_kernel5_tests.c index 42cc8e36..efaef8bd 100644 --- a/tests/vboot_api_kernel5_tests.c +++ b/tests/vboot_api_kernel5_tests.c @@ -34,6 +34,7 @@ static VbSelectAndLoadKernelParams kparams; static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; static struct vb2_gbb_header gbb; +static struct vb2_packed_key mock_key; static uint8_t kernel_buffer[80000]; static int key_block_verify_fail; /* 0=ok, 1=sig, 2=hash */ @@ -58,7 +59,9 @@ static void ResetMocks(void) gbb.minor_version = VB2_GBB_MINOR_VER; gbb.flags = 0; gbb.rootkey_offset = sizeof(gbb); - gbb.rootkey_size = sizeof(VbPublicKey); + gbb.rootkey_size = sizeof(struct vb2_packed_key); + + memset(&mock_key, 0, sizeof(mock_key)); /* ctx.workbuf will be initialized by VbVerifyMemoryBootImage. */ memset(&ctx, 0, sizeof(ctx)); @@ -121,6 +124,24 @@ int vb2ex_read_resource(struct vb2_context *c, return VB2_SUCCESS; } +int vb2_gbb_read_root_key(struct vb2_context *c, + struct vb2_packed_key **keyp, + uint32_t *size, + struct vb2_workbuf *wb) +{ + *keyp = &mock_key; + return VB2_SUCCESS; +} + +int vb2_gbb_read_recovery_key(struct vb2_context *c, + struct vb2_packed_key **keyp, + uint32_t *size, + struct vb2_workbuf *wb) +{ + *keyp = &mock_key; + return VB2_SUCCESS; +} + int vb2_unpack_key_buffer(struct vb2_public_key *key, const uint8_t *buf, uint32_t size) diff --git a/tests/vboot_display_tests.c b/tests/vboot_display_tests.c index 3d65825e..c509e365 100644 --- a/tests/vboot_display_tests.c +++ b/tests/vboot_display_tests.c @@ -15,7 +15,6 @@ #include "2misc.h" #include "2nvstorage.h" #include "2struct.h" -#include "gbb_access.h" #include "host_common.h" #include "test_common.h" #include "vboot_common.h" @@ -25,11 +24,9 @@ /* Mock data */ static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; -static char gbb_data[4096 + sizeof(struct vb2_gbb_header)]; -static struct vb2_gbb_header *gbb = (struct vb2_gbb_header *)gbb_data; static char debug_info[4096]; static struct vb2_context ctx; -struct vb2_shared_data *sd; +static struct vb2_shared_data *sd; static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]; static uint32_t mock_localization_count; static uint32_t mock_altfw_mask; @@ -37,30 +34,9 @@ static uint32_t mock_altfw_mask; /* Reset mock data (for use before each test) */ static void ResetMocks(void) { - int gbb_used; - - memset(gbb_data, 0, sizeof(gbb_data)); - gbb->major_version = VB2_GBB_MAJOR_VER; - gbb->minor_version = VB2_GBB_MINOR_VER; - gbb->flags = 0; - gbb_used = sizeof(struct vb2_gbb_header); - - gbb->hwid_offset = gbb_used; - strcpy(gbb_data + gbb->hwid_offset, "Test HWID"); - gbb->hwid_size = strlen(gbb_data + gbb->hwid_offset) + 1; - gbb_used = (gbb_used + gbb->hwid_size + 7) & ~7; - mock_localization_count = 3; mock_altfw_mask = 3 << 1; /* This mask selects 1 and 2 */ - gbb->header_size = sizeof(*gbb); - gbb->rootkey_offset = gbb_used; - gbb->rootkey_size = 64; - gbb_used += 64; - gbb->recovery_key_offset = gbb_used; - gbb->recovery_key_size = 64; - gbb_used += 64; - memset(&ctx, 0, sizeof(ctx)); ctx.workbuf = workbuf; ctx.workbuf_size = sizeof(workbuf); @@ -77,36 +53,6 @@ static void ResetMocks(void) } /* Mocks */ -struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) -{ - return gbb; -} - -int 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; - - switch(index) { - case VB2_RES_GBB: - rptr = (uint8_t *)&gbb_data; - rsize = sizeof(gbb_data); - 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; -} - VbError_t VbExGetLocalizationCount(uint32_t *count) { if (mock_localization_count == 0xffffffff) @@ -130,37 +76,17 @@ VbError_t VbExDisplayDebugInfo(const char *info_str, int full_info) /* Test displaying debug info */ static void DebugInfoTest(void) { - char hwid[256]; int i; /* Recovery string should be non-null for any code */ for (i = 0; i < 0x100; i++) TEST_PTR_NEQ(RecoveryReasonString(i), NULL, "Non-null reason"); - /* HWID should come from the gbb */ - ResetMocks(); - VbGbbReadHWID(&ctx, hwid, sizeof(hwid)); - TEST_EQ(strcmp(hwid, "Test HWID"), 0, "HWID"); - - ResetMocks(); - gbb->hwid_size = 0; - VbGbbReadHWID(&ctx, hwid, sizeof(hwid)); - TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID missing"); - - ResetMocks(); - gbb->hwid_offset = sizeof(gbb_data) + 1; - VbGbbReadHWID(&ctx, hwid, sizeof(hwid)); - TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID past end"); - - ResetMocks(); - gbb->hwid_size = sizeof(gbb_data); - VbGbbReadHWID(&ctx, hwid, sizeof(hwid)); - TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID overflow"); - /* Display debug info */ ResetMocks(); - VbDisplayDebugInfo(&ctx); - TEST_NEQ(*debug_info, '\0', "Some debug info was displayed"); + TEST_SUCC(VbDisplayDebugInfo(&ctx), + "Display debug info"); + TEST_NEQ(*debug_info, '\0', " Some debug info was displayed"); } /* Test display key checking */ diff --git a/tests/vboot_kernel_tests.c b/tests/vboot_kernel_tests.c index 1711ceed..1c7440cf 100644 --- a/tests/vboot_kernel_tests.c +++ b/tests/vboot_kernel_tests.c @@ -75,6 +75,7 @@ static GptHeader *mock_gpt_secondary = static uint8_t mock_digest[VB2_SHA256_DIGEST_SIZE] = {12, 34, 56, 78}; static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]; static struct vb2_context ctx; +static struct vb2_packed_key mock_key; /** * Prepare a valid GPT header that will pass CheckHeader() tests @@ -178,6 +179,8 @@ static void ResetMocks(void) ctx.workbuf_size = sizeof(workbuf); vb2_nv_init(&ctx); + memset(&mock_key, 0, sizeof(mock_key)); + struct vb2_shared_data *sd = vb2_get_sd(&ctx); sd->vbsd = shared; @@ -200,6 +203,24 @@ int vb2ex_read_resource(struct vb2_context *c, return VB2_SUCCESS; } +int vb2_gbb_read_root_key(struct vb2_context *c, + struct vb2_packed_key **keyp, + uint32_t *size, + struct vb2_workbuf *wb) +{ + *keyp = &mock_key; + return VB2_SUCCESS; +} + +int vb2_gbb_read_recovery_key(struct vb2_context *c, + struct vb2_packed_key **keyp, + uint32_t *size, + struct vb2_workbuf *wb) +{ + *keyp = &mock_key; + return VB2_SUCCESS; +} + VbError_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start, uint64_t lba_count, void *buffer) { |