diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/vboot_api_devmode_tests.c | 1 | ||||
-rw-r--r-- | tests/vboot_api_firmware_tests.c | 7 | ||||
-rw-r--r-- | tests/vboot_api_init_tests.c | 1 | ||||
-rw-r--r-- | tests/vboot_api_kernel2_tests.c | 1 | ||||
-rw-r--r-- | tests/vboot_api_kernel4_tests.c | 1 | ||||
-rw-r--r-- | tests/vboot_api_kernel_tests.c | 2 | ||||
-rw-r--r-- | tests/vboot_audio_tests.c | 1 | ||||
-rw-r--r-- | tests/vboot_display_tests.c | 55 | ||||
-rw-r--r-- | tests/vboot_firmware_tests.c | 24 | ||||
-rw-r--r-- | tests/vboot_kernel_tests.c | 114 | ||||
-rw-r--r-- | tests/vboot_region_tests.c | 213 |
11 files changed, 366 insertions, 54 deletions
diff --git a/tests/vboot_api_devmode_tests.c b/tests/vboot_api_devmode_tests.c index b10bba67..61f0de14 100644 --- a/tests/vboot_api_devmode_tests.c +++ b/tests/vboot_api_devmode_tests.c @@ -153,6 +153,7 @@ static void ResetMocks(void) { cparams.shared_data_size = sizeof(shared_data); cparams.shared_data_blob = shared_data; cparams.gbb_data = &gbb; + cparams.gbb = &gbb; Memset(&lkparams, 0, sizeof(lkparams)); diff --git a/tests/vboot_api_firmware_tests.c b/tests/vboot_api_firmware_tests.c index 9e7c441d..4a97b930 100644 --- a/tests/vboot_api_firmware_tests.c +++ b/tests/vboot_api_firmware_tests.c @@ -9,6 +9,7 @@ #include <stdio.h> #include <stdlib.h> +#include "gbb_header.h" #include "host_common.h" #include "rollback_index.h" #include "test_common.h" @@ -23,6 +24,7 @@ /* Mock data */ static VbCommonParams cparams; static VbSelectFirmwareParams fparams; +static GoogleBinaryBlockHeader gbb; static VbNvContext vnc; static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; static VbSharedDataHeader* shared = (VbSharedDataHeader*)shared_data; @@ -49,6 +51,11 @@ static void ResetMocks(void) { Memset(&fparams, 0, sizeof(fparams)); + Memset(&gbb, 0, sizeof(gbb)); + cparams.gbb_data = &gbb; + cparams.gbb_size = sizeof(gbb); + cparams.gbb = &gbb; + Memset(&vnc, 0, sizeof(vnc)); VbNvSetup(&vnc); VbNvTeardown(&vnc); /* So CRC gets generated */ diff --git a/tests/vboot_api_init_tests.c b/tests/vboot_api_init_tests.c index 6451bd81..9aa34b41 100644 --- a/tests/vboot_api_init_tests.c +++ b/tests/vboot_api_init_tests.c @@ -40,6 +40,7 @@ static void ResetMocks(void) cparams.shared_data_size = sizeof(shared_data); cparams.shared_data_blob = shared_data; cparams.gbb_data = &gbb; + cparams.gbb_size = sizeof(gbb); Memset(&gbb, 0, sizeof(gbb)); gbb.major_version = GBB_MAJOR_VER; diff --git a/tests/vboot_api_kernel2_tests.c b/tests/vboot_api_kernel2_tests.c index c1572c2f..323f5f66 100644 --- a/tests/vboot_api_kernel2_tests.c +++ b/tests/vboot_api_kernel2_tests.c @@ -49,6 +49,7 @@ static void ResetMocks(void) cparams.shared_data_size = sizeof(shared_data); cparams.shared_data_blob = shared_data; cparams.gbb_data = &gbb; + cparams.gbb = &gbb; Memset(&gbb, 0, sizeof(gbb)); gbb.major_version = GBB_MAJOR_VER; diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c index e2155f56..82b15016 100644 --- a/tests/vboot_api_kernel4_tests.c +++ b/tests/vboot_api_kernel4_tests.c @@ -41,6 +41,7 @@ static void ResetMocks(void) cparams.shared_data_size = sizeof(shared_data); cparams.shared_data_blob = shared_data; cparams.gbb_data = &gbb; + cparams.gbb_size = sizeof(gbb); Memset(&kparams, 0, sizeof(kparams)); diff --git a/tests/vboot_api_kernel_tests.c b/tests/vboot_api_kernel_tests.c index 87dc6cfa..8cfc1cb4 100644 --- a/tests/vboot_api_kernel_tests.c +++ b/tests/vboot_api_kernel_tests.c @@ -269,7 +269,7 @@ VbError_t VbExDiskFreeInfo(VbDiskInfo *infos, return VBERROR_SUCCESS; } -VbError_t LoadKernel(LoadKernelParams *params) +VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams) { got_find_disk = (const char *)params->disk_handle; VBDEBUG(("%s(%d): got_find_disk = %s\n", __FUNCTION__, diff --git a/tests/vboot_audio_tests.c b/tests/vboot_audio_tests.c index 23667b1e..d674931d 100644 --- a/tests/vboot_audio_tests.c +++ b/tests/vboot_audio_tests.c @@ -62,6 +62,7 @@ static void ResetMocks(void) { VBDEBUG(("ResetMocks()\n")); Memset(&cparams, 0, sizeof(cparams)); cparams.gbb_data = &gbb; + cparams.gbb = &gbb; Memset(&gbb, 0, sizeof(gbb)); gbb.major_version = GBB_MAJOR_VER; gbb.minor_version = GBB_MINOR_VER; diff --git a/tests/vboot_display_tests.c b/tests/vboot_display_tests.c index 8e4a3a27..8086d319 100644 --- a/tests/vboot_display_tests.c +++ b/tests/vboot_display_tests.c @@ -13,9 +13,11 @@ #include "bmpblk_font.h" #include "gbb_header.h" #include "host_common.h" +#include "region.h" #include "test_common.h" #include "vboot_common.h" #include "vboot_display.h" +#include "vboot_kernel.h" #include "vboot_nvstorage.h" /* Mock data */ @@ -59,6 +61,20 @@ static void ResetMocks(void) cparams.gbb_data = gbb; cparams.gbb_size = sizeof(gbb_data); + /* + * Note, VbApiKernelFree() expects this to be allocated by + * VbExMalloc(), so we cannot just assign it staticly. + */ + cparams.gbb = VbExMalloc(sizeof(*gbb)); + 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; + memcpy(cparams.gbb, gbb, sizeof(*gbb)); + Memset(&vnc, 0, sizeof(vnc)); VbNvSetup(&vnc); VbNvTeardown(&vnc); /* So CRC gets generated */ @@ -81,6 +97,7 @@ VbError_t VbExDisplayDebugInfo(const char *info_str) /* Test displaying debug info */ static void DebugInfoTest(void) { + char hwid[VB_REGION_HWID_LEN]; int i; /* Recovery string should be non-null for any code */ @@ -89,28 +106,39 @@ static void DebugInfoTest(void) /* HWID should come from the gbb */ ResetMocks(); - TEST_EQ(strcmp(VbHWID(&cparams), "Test HWID"), 0, "HWID"); + VbRegionReadHWID(&cparams, hwid, sizeof(hwid)); + TEST_EQ(strcmp(hwid, "Test HWID"), 0, "HWID"); + VbApiKernelFree(&cparams); ResetMocks(); cparams.gbb_size = 0; - TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID bad gbb"); + VbRegionReadHWID(&cparams, hwid, sizeof(hwid)); + TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID bad gbb"); + VbApiKernelFree(&cparams); ResetMocks(); - gbb->hwid_size = 0; - TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID missing"); + cparams.gbb->hwid_size = 0; + VbRegionReadHWID(&cparams, hwid, sizeof(hwid)); + TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID missing"); + VbApiKernelFree(&cparams); ResetMocks(); - gbb->hwid_offset = cparams.gbb_size + 1; - TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID past end"); + cparams.gbb->hwid_offset = cparams.gbb_size + 1; + VbRegionReadHWID(&cparams, hwid, sizeof(hwid)); + TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID past end"); + VbApiKernelFree(&cparams); ResetMocks(); - gbb->hwid_size = cparams.gbb_size; - TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID overflow"); + cparams.gbb->hwid_size = cparams.gbb_size; + VbRegionReadHWID(&cparams, hwid, sizeof(hwid)); + TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID overflow"); + VbApiKernelFree(&cparams); /* Display debug info */ ResetMocks(); VbDisplayDebugInfo(&cparams, &vnc); TEST_NEQ(*debug_info, '\0', "Some debug info was displayed"); + VbApiKernelFree(&cparams); } /* Test localization */ @@ -119,21 +147,23 @@ static void LocalizationTest(void) uint32_t count = 6; ResetMocks(); - gbb->bmpfv_size = 0; + cparams.gbb->bmpfv_size = 0; TEST_EQ(VbGetLocalizationCount(&cparams, &count), VBERROR_INVALID_GBB, "VbGetLocalizationCount bad gbb"); TEST_EQ(count, 0, " count"); + VbApiKernelFree(&cparams); ResetMocks(); bhdr->signature[0] ^= 0x5a; TEST_EQ(VbGetLocalizationCount(&cparams, &count), VBERROR_INVALID_BMPFV, "VbGetLocalizationCount bad bmpfv"); + VbApiKernelFree(&cparams); ResetMocks(); TEST_EQ(VbGetLocalizationCount(&cparams, &count), 0, "VbGetLocalizationCount()"); TEST_EQ(count, 3, " count"); - + VbApiKernelFree(&cparams); } /* Test display key checking */ @@ -144,10 +174,12 @@ static void DisplayKeyTest(void) ResetMocks(); VbCheckDisplayKey(&cparams, 'q', &vnc); TEST_EQ(*debug_info, '\0', "DisplayKey q = does nothing"); + VbApiKernelFree(&cparams); ResetMocks(); VbCheckDisplayKey(&cparams, '\t', &vnc); TEST_NEQ(*debug_info, '\0', "DisplayKey tab = display"); + VbApiKernelFree(&cparams); /* Toggle localization */ ResetMocks(); @@ -165,6 +197,7 @@ static void DisplayKeyTest(void) VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc); VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u); TEST_EQ(u, 0, "DisplayKey up"); + VbApiKernelFree(&cparams); /* Reset localization if localization count is invalid */ ResetMocks(); @@ -174,7 +207,7 @@ static void DisplayKeyTest(void) VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc); VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u); TEST_EQ(u, 0, "DisplayKey invalid"); - + VbApiKernelFree(&cparams); } static void FontTest(void) diff --git a/tests/vboot_firmware_tests.c b/tests/vboot_firmware_tests.c index f6b96fec..724e7f8b 100644 --- a/tests/vboot_firmware_tests.c +++ b/tests/vboot_firmware_tests.c @@ -8,6 +8,7 @@ #include <stdint.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "gbb_header.h" #include "host_common.h" @@ -33,13 +34,20 @@ static uint8_t* digest_returned; static uint8_t* digest_expect_ptr; static int hash_fw_index; +#define TEST_KEY_DATA \ + "Test contents for the root key this should be 64 chars long." + /* Reset mock data (for use before each test) */ static void ResetMocks(void) { + VbPublicKey *root_key; + uint8_t *root_key_data; int i; Memset(&cparams, 0, sizeof(cparams)); cparams.shared_data_blob = shared_data; cparams.gbb_data = gbb_data; + cparams.gbb_size = sizeof(gbb_data); + cparams.gbb = gbb; Memset(&fparams, 0, sizeof(fparams)); fparams.verification_block_A = vblock; @@ -75,6 +83,14 @@ static void ResetMocks(void) { Memset(&gbb_data, 0, sizeof(gbb_data)); gbb->rootkey_offset = sizeof(GoogleBinaryBlockHeader); + root_key = (VbPublicKey *)(gbb_data + gbb->rootkey_offset); + root_key_data = (uint8_t *)(root_key + 1); + strcpy((char *)root_key_data, TEST_KEY_DATA); + PublicKeyInit(root_key, (uint8_t *)root_key_data, sizeof(TEST_KEY_DATA)); + + gbb->major_version = GBB_MAJOR_VER; + gbb->minor_version = GBB_MINOR_VER; + gbb->flags = 0; Memset(&data_key, 0, sizeof(data_key)); @@ -91,7 +107,13 @@ int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size, const VbPublicKey *key, int hash_only) { TEST_EQ(hash_only, 0, " Don't verify firmware with hash"); - TEST_PTR_EQ(key, gbb_data + gbb->rootkey_offset, " Verify with root key"); + + /* + * We cannot check the address of key, since it will be allocated. We + * check the contents instead. + */ + TEST_STR_EQ((char *)GetPublicKeyDataC(key), TEST_KEY_DATA, + " Verify with root key"); TEST_NEQ(block==vblock || block==vblock+1, 0, " Verify a valid key block"); /* Mock uses header_version_major to hold return value */ diff --git a/tests/vboot_kernel_tests.c b/tests/vboot_kernel_tests.c index 6992e94a..8dde9cb6 100644 --- a/tests/vboot_kernel_tests.c +++ b/tests/vboot_kernel_tests.c @@ -47,7 +47,8 @@ static int verify_data_fail; static RSAPublicKey *mock_data_key; static int mock_data_key_allocated; -static GoogleBinaryBlockHeader gbb; +static uint8_t gbb_data[sizeof(GoogleBinaryBlockHeader) + 2048]; +static GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader*)gbb_data; static VbExDiskHandle_t handle; static VbNvContext vnc; static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; @@ -55,6 +56,7 @@ static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; static LoadKernelParams lkp; static VbKeyBlockHeader kbh; static VbKernelPreambleHeader kph; +static VbCommonParams cparams; static void ResetCallLog(void) { @@ -79,10 +81,15 @@ static void ResetMocks(void) mock_data_key = (RSAPublicKey *)"TestDataKey"; mock_data_key_allocated = 0; - memset(&gbb, 0, sizeof(gbb)); - gbb.major_version = GBB_MAJOR_VER; - gbb.minor_version = GBB_MINOR_VER; - gbb.flags = 0; + memset(gbb, 0, sizeof(gbb)); + gbb->major_version = GBB_MAJOR_VER; + gbb->minor_version = GBB_MINOR_VER; + gbb->flags = 0; + + memset(&cparams, '\0', sizeof(cparams)); + cparams.gbb = gbb; + cparams.gbb_data = gbb; + cparams.gbb_size = sizeof(gbb_data); memset(&vnc, 0, sizeof(vnc)); VbNvSetup(&vnc); @@ -95,7 +102,8 @@ static void ResetMocks(void) memset(&lkp, 0, sizeof(lkp)); lkp.nv_context = &vnc; lkp.shared_data_blob = shared; - lkp.gbb_data = &gbb; + lkp.gbb_data = gbb; + lkp.gbb_size = sizeof(gbb_data); lkp.bytes_per_lba = 512; lkp.ending_lba = 1023; lkp.kernel_buffer = kernel_buffer; @@ -129,6 +137,8 @@ VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, if ((int)lba_start == disk_read_to_fail) return VBERROR_SIMULATED; + /* Keep valgrind happy */ + Memset(buffer, '\0', lba_count); return VBERROR_SUCCESS; } @@ -238,6 +248,11 @@ static void ReadWriteGptTest(void) "VbExDiskRead(h, 991, 32)\n" "VbExDiskRead(h, 1023, 1)\n"); ResetCallLog(); + /* + * Valgrind complains about access to uninitialized memory here, so + * zero the primary header before each test. + */ + Memset(g.primary_header, '\0', g.sector_bytes); TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree"); TEST_CALLS(""); @@ -246,6 +261,7 @@ static void ReadWriteGptTest(void) AllocAndReadGptData(handle, &g); g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1; ResetCallLog(); + Memset(g.primary_header, '\0', g.sector_bytes); TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" "VbExDiskWrite(h, 2, 32)\n"); @@ -255,6 +271,7 @@ static void ReadWriteGptTest(void) AllocAndReadGptData(handle, &g); g.modified = -1; ResetCallLog(); + Memset(g.primary_header, '\0', g.sector_bytes); TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all"); TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" "VbExDiskWrite(h, 2, 32)\n" @@ -276,21 +293,25 @@ static void ReadWriteGptTest(void) ResetMocks(); disk_read_to_fail = 1; TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + Memset(g.primary_header, '\0', g.sector_bytes); WriteAndFreeGptData(handle, &g); ResetMocks(); disk_read_to_fail = 2; TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + Memset(g.primary_header, '\0', g.sector_bytes); WriteAndFreeGptData(handle, &g); ResetMocks(); disk_read_to_fail = 991; TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + Memset(g.primary_header, '\0', g.sector_bytes); WriteAndFreeGptData(handle, &g); ResetMocks(); disk_read_to_fail = 1023; TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + Memset(g.primary_header, '\0', g.sector_bytes); WriteAndFreeGptData(handle, &g); /* Error writing */ @@ -298,24 +319,28 @@ static void ReadWriteGptTest(void) disk_write_to_fail = 1; AllocAndReadGptData(handle, &g); g.modified = -1; + Memset(g.primary_header, '\0', g.sector_bytes); TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); ResetMocks(); disk_write_to_fail = 2; AllocAndReadGptData(handle, &g); g.modified = -1; + Memset(g.primary_header, '\0', g.sector_bytes); TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); ResetMocks(); disk_write_to_fail = 991; AllocAndReadGptData(handle, &g); g.modified = -1; + Memset(g.primary_header, '\0', g.sector_bytes); TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); ResetMocks(); disk_write_to_fail = 1023; AllocAndReadGptData(handle, &g); g.modified = -1; + Memset(g.primary_header, '\0', g.sector_bytes); TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); } @@ -327,23 +352,28 @@ static void InvalidParamsTest(void) { ResetMocks(); lkp.bytes_per_lba = 0; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_PARAMETER, "Bad lba size"); + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER, + "Bad lba size"); ResetMocks(); lkp.ending_lba = 0; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_PARAMETER, "Bad lba count"); + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER, + "Bad lba count"); ResetMocks(); lkp.bytes_per_lba = 128*1024; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_PARAMETER, "Huge lba size"); + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER, + "Huge lba size"); ResetMocks(); disk_read_to_fail = 1; - TEST_EQ(LoadKernel(&lkp), VBERROR_NO_KERNEL_FOUND, "Can't read disk"); + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND, + "Can't read disk"); ResetMocks(); gpt_init_fail = 1; - TEST_EQ(LoadKernel(&lkp), VBERROR_NO_KERNEL_FOUND, "Bad GPT"); + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND, + "Bad GPT"); } static void LoadKernelTest(void) @@ -351,7 +381,7 @@ static void LoadKernelTest(void) uint32_t u; ResetMocks(); - TEST_EQ(LoadKernel(&lkp), 0, "First kernel good"); + TEST_EQ(LoadKernel(&lkp, &cparams), 0, "First kernel good"); TEST_EQ(lkp.partition_number, 1, " part num"); TEST_EQ(lkp.bootloader_address, 0xbeadd008, " bootloader addr"); TEST_EQ(lkp.bootloader_size, 0x1234, " bootloader size"); @@ -362,46 +392,46 @@ static void LoadKernelTest(void) ResetMocks(); mock_parts[1].start = 300; mock_parts[1].size = 150; - TEST_EQ(LoadKernel(&lkp), 0, "Two good kernels"); + TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two good kernels"); TEST_EQ(lkp.partition_number, 1, " part num"); TEST_EQ(mock_part_next, 1, " didn't read second one"); /* Fail if no kernels found */ ResetMocks(); mock_parts[0].size = 0; - TEST_EQ(LoadKernel(&lkp), VBERROR_NO_KERNEL_FOUND, "No kernels"); + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND, "No kernels"); VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u); TEST_EQ(u, VBNV_RECOVERY_RW_NO_OS, " recovery request"); /* Skip kernels which are too small */ ResetMocks(); mock_parts[0].size = 10; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, "Too small"); + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Too small"); VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u); TEST_EQ(u, VBNV_RECOVERY_RW_INVALID_OS, " recovery request"); ResetMocks(); disk_read_to_fail = 100; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Fail reading kernel start"); ResetMocks(); key_block_verify_fail = 1; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Fail key block sig"); /* In dev mode, fail if hash is bad too */ ResetMocks(); lkp.boot_flags |= BOOT_FLAG_DEVELOPER; key_block_verify_fail = 2; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Fail key block dev hash"); /* But just bad sig is ok */ ResetMocks(); lkp.boot_flags |= BOOT_FLAG_DEVELOPER; key_block_verify_fail = 1; - TEST_EQ(LoadKernel(&lkp), 0, "Succeed key block dev sig"); + TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed key block dev sig"); /* In dev mode and requiring signed kernel, fail if sig is bad */ ResetMocks(); @@ -409,124 +439,126 @@ static void LoadKernelTest(void) VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1); VbNvTeardown(&vnc); key_block_verify_fail = 1; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Fail key block dev sig"); /* Check key block flag mismatches */ ResetMocks(); kbh.key_block_flags = KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_1; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Key block dev flag mismatch"); ResetMocks(); kbh.key_block_flags = KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Key block rec flag mismatch"); ResetMocks(); lkp.boot_flags |= BOOT_FLAG_RECOVERY; kbh.key_block_flags = KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_1; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Key block recdev flag mismatch"); ResetMocks(); lkp.boot_flags |= BOOT_FLAG_RECOVERY | BOOT_FLAG_DEVELOPER; kbh.key_block_flags = KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Key block rec!dev flag mismatch"); ResetMocks(); kbh.data_key.key_version = 1; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Key block kernel key rollback"); ResetMocks(); kbh.data_key.key_version = 0x10000; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Key block kernel key version too big"); ResetMocks(); kbh.data_key.key_version = 3; - TEST_EQ(LoadKernel(&lkp), 0, "Key block version roll forward"); + TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key block version roll forward"); TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version"); ResetMocks(); kbh.data_key.key_version = 3; mock_parts[1].start = 300; mock_parts[1].size = 150; - TEST_EQ(LoadKernel(&lkp), 0, "Two kernels roll forward"); + TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two kernels roll forward"); TEST_EQ(mock_part_next, 2, " read both"); TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version"); ResetMocks(); kbh.data_key.key_version = 1; lkp.boot_flags |= BOOT_FLAG_DEVELOPER; - TEST_EQ(LoadKernel(&lkp), 0, "Key version ignored in dev mode"); + TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in dev mode"); ResetMocks(); kbh.data_key.key_version = 1; lkp.boot_flags |= BOOT_FLAG_RECOVERY; - TEST_EQ(LoadKernel(&lkp), 0, "Key version ignored in rec mode"); + TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in rec mode"); ResetMocks(); mock_data_key = NULL; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, "Bad data key"); + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, + "Bad data key"); ResetMocks(); preamble_verify_fail = 1; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, "Bad preamble"); + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, + "Bad preamble"); ResetMocks(); kph.kernel_version = 0; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Kernel version rollback"); ResetMocks(); kph.kernel_version = 0; lkp.boot_flags |= BOOT_FLAG_DEVELOPER; - TEST_EQ(LoadKernel(&lkp), 0, "Kernel version ignored in dev mode"); + TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in dev mode"); ResetMocks(); kph.kernel_version = 0; lkp.boot_flags |= BOOT_FLAG_RECOVERY; - TEST_EQ(LoadKernel(&lkp), 0, "Kernel version ignored in rec mode"); + TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in rec mode"); ResetMocks(); kph.preamble_size |= 0x07; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Kernel body offset"); /* Check getting kernel load address from header */ ResetMocks(); kph.body_load_address = (size_t)kernel_buffer; lkp.kernel_buffer = NULL; - TEST_EQ(LoadKernel(&lkp), 0, "Get load address from preamble"); + TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Get load address from preamble"); TEST_PTR_EQ(lkp.kernel_buffer, kernel_buffer, " address"); /* Size is rounded up to nearest sector */ TEST_EQ(lkp.kernel_buffer_size, 70144, " size"); ResetMocks(); lkp.kernel_buffer_size = 8192; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Kernel too big for buffer"); ResetMocks(); mock_parts[0].size = 130; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Kernel too big for partition"); ResetMocks(); disk_read_to_fail = 108; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Fail reading kernel data"); ResetMocks(); verify_data_fail = 1; - TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, "Bad data"); + TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Bad data"); } int main(void) diff --git a/tests/vboot_region_tests.c b/tests/vboot_region_tests.c new file mode 100644 index 00000000..1293136e --- /dev/null +++ b/tests/vboot_region_tests.c @@ -0,0 +1,213 @@ +/* Copyright (c) 2011 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 vboot region API + */ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "bmpblk_font.h" +#include "gbb_header.h" +#include "host_common.h" +#include "rollback_index.h" +#include "test_common.h" +#include "vboot_common.h" +#include "vboot_nvstorage.h" +#include "vboot_struct.h" + +/* Mock data */ +static VbCommonParams cparams; +static VbNvContext vnc; +static VbSelectFirmwareParams fparams; +VbSelectAndLoadKernelParams kparams; +static char gbb_data[4096 + sizeof(GoogleBinaryBlockHeader)]; +static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; +static VbSharedDataHeader* shared = (VbSharedDataHeader*)shared_data; +/* Mock TPM versions */ +static uint32_t mock_tpm_version; +static uint32_t mock_lf_tpm_version; /* TPM version set by LoadFirmware() */ +static uint32_t mock_seen_region; +/* Mock return values, so we can simulate errors */ +static VbError_t mock_lf_retval; + +#define COMPRESSED_SIZE 200 +#define ORIGINAL_SIZE 400 + +/* Reset mock data (for use before each test) */ +static void ResetMocks(void) { + GoogleBinaryBlockHeader *gbb; + BmpBlockHeader *bhdr; + ImageInfo *image_info; + ScreenLayout *layout; + int gbb_used; + + Memset(&vnc, 0, sizeof(vnc)); + VbNvSetup(&vnc); + VbNvTeardown(&vnc); /* So CRC gets generated */ + + Memset(&cparams, 0, sizeof(cparams)); + cparams.shared_data_size = sizeof(shared_data); + cparams.shared_data_blob = shared_data; + + Memset(&fparams, 0, sizeof(fparams)); + + Memset(gbb_data, 0, sizeof(gbb_data)); + gbb = (GoogleBinaryBlockHeader *)gbb_data; + gbb->major_version = GBB_MAJOR_VER; + gbb->minor_version = GBB_MINOR_VER; + gbb->flags = 0; + gbb_used = sizeof(GoogleBinaryBlockHeader); + + 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; + + gbb->bmpfv_offset = gbb_used; + bhdr = (BmpBlockHeader *)(gbb_data + gbb->bmpfv_offset); + gbb->bmpfv_size = sizeof(BmpBlockHeader); + gbb_used = (gbb_used + gbb->bmpfv_size + 7) & ~7; + memcpy(bhdr->signature, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE); + bhdr->major_version = BMPBLOCK_MAJOR_VERSION; + bhdr->minor_version = BMPBLOCK_MINOR_VERSION; + bhdr->number_of_localizations = 3; + bhdr->number_of_screenlayouts = 1; + + layout = (ScreenLayout *)(gbb_data + gbb_used); + gbb_used += sizeof(*layout); + layout->images[0].x = 1; + layout->images[0].image_info_offset = gbb_used - gbb->bmpfv_offset; + + /* First image is uncompressed */ + image_info = (ImageInfo *)(gbb_data + gbb_used); + image_info->format = FORMAT_BMP; + image_info->compressed_size = ORIGINAL_SIZE; + image_info->original_size = ORIGINAL_SIZE; + image_info->compression = COMPRESS_NONE; + gbb_used += sizeof(*image_info); + strcpy(gbb_data + gbb_used, "original"); + gbb_used += ORIGINAL_SIZE; + + /* Second image is compressed */ + layout->images[1].image_info_offset = gbb_used - gbb->bmpfv_offset; + layout->images[1].x = 2; + image_info = (ImageInfo *)(gbb_data + gbb_used); + image_info->format = FORMAT_BMP; + image_info->compressed_size = COMPRESSED_SIZE; + image_info->original_size = ORIGINAL_SIZE; + image_info->compression = COMPRESS_LZMA1; + gbb_used += sizeof(*image_info) + COMPRESSED_SIZE; + + Memset(&shared_data, 0, sizeof(shared_data)); + VbSharedDataInit(shared, sizeof(shared_data)); + shared->fw_keyblock_flags = 0xABCDE0; + + mock_tpm_version = mock_lf_tpm_version = 0x20004; + shared->fw_version_tpm_start = mock_tpm_version; + mock_lf_retval = 0; + mock_seen_region = 0; +} + +/****************************************************************************/ +/* Mocked verification functions */ + +uint32_t SetTPMBootModeState(int developer_mode, int recovery_mode, + uint64_t fw_keyblock_flags) { + return VBERROR_SUCCESS; +} + +VbError_t VbExNvStorageRead(uint8_t* buf) { + Memcpy(buf, vnc.raw, sizeof(vnc.raw)); + return VBERROR_SUCCESS; +} + +VbError_t VbExNvStorageWrite(const uint8_t* buf) { + Memcpy(vnc.raw, buf, sizeof(vnc.raw)); + return VBERROR_SUCCESS; +} + +VbError_t VbExRegionRead(VbCommonParams *cparams, + enum vb_firmware_region region, uint32_t offset, + uint32_t size, void *buf) +{ + if (region != VB_REGION_GBB) + return VBERROR_UNSUPPORTED_REGION; + mock_seen_region |= 1 << region; + if (offset + size > sizeof(gbb_data)) + return VBERROR_REGION_READ_INVALID; + memcpy(buf, gbb_data + offset, size); + return VBERROR_SUCCESS; +} + +VbError_t VbExDisplayImage(uint32_t x, uint32_t y, + void *buffer, uint32_t buffersize) +{ + switch (x) { + case 1: + TEST_STR_EQ(buffer, "original", " uncompressed image"); + break; + case 2: + TEST_STR_EQ(buffer, "decompressed", " compressed image"); + break; + default: + TEST_STR_EQ(buffer, "invalid", " correct image"); + break; + } + return VBERROR_SUCCESS; +} + +VbError_t VbExDecompress(void *inbuf, uint32_t in_size, + uint32_t compression_type, + void *outbuf, uint32_t *out_size) +{ + *out_size = ORIGINAL_SIZE; + strcpy(outbuf, "decompressed"); + return VBERROR_SUCCESS; +} + +int LoadFirmware(VbCommonParams *cparams, VbSelectFirmwareParams *fparams, + VbNvContext *vnc) { + shared->fw_version_tpm = mock_lf_tpm_version; + TEST_PTR_NEQ(cparams->gbb, NULL, " GBB allocated"); + return mock_lf_retval; +} + +/****************************************************************************/ + +static void VbRegionReadTest(void) { + /* Should read GBB */ + ResetMocks(); + TEST_TRUE(1, "Normal call"); + TEST_EQ(VbSelectFirmware(&cparams, &fparams), VBERROR_SUCCESS, + " Success"); + TEST_EQ(mock_seen_region, 1 << VB_REGION_GBB, " GBB region"); + TEST_PTR_EQ(cparams.gbb, NULL, " GBB free"); + + ResetMocks(); + TEST_EQ(VbSelectAndLoadKernel(&cparams, &kparams), + VBERROR_NO_DISK_FOUND, "Kernel"); + TEST_PTR_EQ(cparams.gbb, NULL, " GBB free"); + TEST_PTR_EQ(cparams.bmp, NULL, " BMP free"); + + ResetMocks(); + shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; + TEST_EQ(VbSelectAndLoadKernel(&cparams, &kparams), + VBERROR_NO_DISK_FOUND, "Kernel"); +} + +int main(int argc, char* argv[]) { + int error_code = 0; + + VbRegionReadTest(); + + if (vboot_api_stub_check_memory()) + error_code = 255; + if (!gTestSuccess) + error_code = 255; + + return error_code; +} |