diff options
author | Randall Spangler <rspangler@chromium.org> | 2011-08-31 11:34:29 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2011-09-01 09:05:04 -0700 |
commit | 6c6babc51b5a500af4c37a6a691cd2a4b5612345 (patch) | |
tree | c5c7b7c2e76f3cec71539bb196ccac51ecec741a /tests | |
parent | 9c9606b7a6e2fe7a2d8147c0d61c2d3f5b98956d (diff) | |
download | vboot-6c6babc51b5a500af4c37a6a691cd2a4b5612345.tar.gz |
Add tests for vboot_firmware.c
Yaay, LoadFirmware() finally has unit tests!
Fix minor memory leak in LoadFirmware().
BUG=chromium-os:17564
TEST=make && make runtests
Change-Id: I7eabc14484271f488b77f286e846781ccc22b8f2
(cherry picked from commit 2b7c5635d7069c55a1d96d11b99d02291b7e308b)
Reviewed-on: http://gerrit.chromium.org/gerrit/7052
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Tested-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile | 2 | ||||
-rw-r--r-- | tests/test_common.c | 10 | ||||
-rw-r--r-- | tests/test_common.h | 10 | ||||
-rw-r--r-- | tests/vboot_firmware_tests.c | 427 |
4 files changed, 439 insertions, 10 deletions
diff --git a/tests/Makefile b/tests/Makefile index 63303295..ca21aefb 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -24,6 +24,7 @@ TEST_NAMES = cgptlib_test \ vboot_common_tests \ vboot_common2_tests \ vboot_common3_tests \ + vboot_firmware_tests \ vboot_nvstorage_test TEST_BINS = $(addprefix ${BUILD_ROOT}/,$(TEST_NAMES)) @@ -114,6 +115,7 @@ runmisctests: ${BUILD_ROOT}/tpm_bootmode_tests ${BUILD_ROOT}/utility_string_tests ${BUILD_ROOT}/utility_tests + ${BUILD_ROOT}/vboot_firmware_tests #This will exercise vbutil_kernel and vbutil_firmware runfuzztests: diff --git a/tests/test_common.c b/tests/test_common.c index 20d8131b..48ee7fd0 100644 --- a/tests/test_common.c +++ b/tests/test_common.c @@ -17,7 +17,7 @@ /* Global test success flag. */ int gTestSuccess = 1; -int TEST_EQ(int result, int expected_result, char* testname) { +int TEST_EQ(int result, int expected_result, const char* testname) { if (result == expected_result) { fprintf(stderr, "%s Test " COL_GREEN "PASSED\n" COL_STOP, testname); return 1; @@ -29,7 +29,7 @@ int TEST_EQ(int result, int expected_result, char* testname) { } } -int TEST_NEQ(int result, int not_expected_result, char* testname) { +int TEST_NEQ(int result, int not_expected_result, const char* testname) { if (result != not_expected_result) { fprintf(stderr, "%s Test " COL_GREEN "PASSED\n" COL_STOP, testname); return 1; @@ -42,7 +42,7 @@ int TEST_NEQ(int result, int not_expected_result, char* testname) { } int TEST_PTR_EQ(const void* result, const void* expected_result, - char* testname) { + const char* testname) { if (result == expected_result) { fprintf(stderr, "%s Test " COL_GREEN "PASSED\n" COL_STOP, testname); return 1; @@ -56,7 +56,7 @@ int TEST_PTR_EQ(const void* result, const void* expected_result, } int TEST_PTR_NEQ(const void* result, const void* not_expected_result, - char* testname) { + const char* testname) { if (result != not_expected_result) { fprintf(stderr, "%s Test " COL_GREEN "PASSED\n" COL_STOP, testname); return 1; @@ -70,7 +70,7 @@ int TEST_PTR_NEQ(const void* result, const void* not_expected_result, } int TEST_STR_EQ(const char* result, const char* expected_result, - char* testname) { + const char* testname) { if (!result || !expected_result) { fprintf(stderr, "%s Test " COL_RED "FAILED\n" COL_STOP, testname); diff --git a/tests/test_common.h b/tests/test_common.h index 7a64ed38..6f594f93 100644 --- a/tests/test_common.h +++ b/tests/test_common.h @@ -11,28 +11,28 @@ extern int gTestSuccess; /* Return 1 if result is equal to expected_result, else return 0. * Also update the global gTestSuccess flag if test fails. */ -int TEST_EQ(int result, int expected_result, char* testname); +int TEST_EQ(int result, int expected_result, const char* testname); /* Return 0 if result is equal to not_expected_result, else return 1. * Also update the global gTestSuccess flag if test fails. */ -int TEST_NEQ(int result, int not_expected_result, char* testname); +int TEST_NEQ(int result, int not_expected_result, const char* testname); /* Return 1 if result pointer is equal to expected_result pointer, * else return 0. Does not check pointer contents, only the pointer * itself. Also update the global gTestSuccess flag if test fails. */ int TEST_PTR_EQ(const void* result, const void* expected_result, - char* testname); + const char* testname); /* Return 1 if result pointer is not equal to expected_result pointer, * else return 0. Does not check pointer contents, only the pointer * itself. Also update the global gTestSuccess flag if test fails. */ int TEST_PTR_NEQ(const void* result, const void* expected_result, - char* testname); + const char* testname); /* Return 1 if result string is equal to expected_result string, * else return 0. Also update the global gTestSuccess flag if test fails. */ int TEST_STR_EQ(const char* result, const char* expected_result, - char* testname); + const char* testname); /* ANSI Color coding sequences. * diff --git a/tests/vboot_firmware_tests.c b/tests/vboot_firmware_tests.c new file mode 100644 index 00000000..f5925f06 --- /dev/null +++ b/tests/vboot_firmware_tests.c @@ -0,0 +1,427 @@ +/* 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_firmware library. + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "gbb_header.h" +#include "host_common.h" +#include "load_firmware_fw.h" +#include "test_common.h" +#include "vboot_common.h" +#include "vboot_nvstorage.h" +#include "vboot_struct.h" + +/* Mock data */ +static VbCommonParams cparams; +static VbSelectFirmwareParams fparams; +static VbKeyBlockHeader vblock[2]; +static VbFirmwarePreambleHeader mpreamble[2]; +static VbNvContext vnc; +static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; +static VbSharedDataHeader* shared = (VbSharedDataHeader*)shared_data; +static uint8_t gbb_data[sizeof(GoogleBinaryBlockHeader) + 2048]; +static GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)gbb_data; +static RSAPublicKey data_key; +static uint32_t digest_size; +static uint8_t* digest_returned; +static uint8_t* digest_expect_ptr; +static int hash_fw_index; + +/* Reset mock data (for use before each test) */ +static void ResetMocks(void) { + int i; + + Memset(&cparams, 0, sizeof(cparams)); + cparams.shared_data_blob = shared_data; + cparams.gbb_data = gbb_data; + + Memset(&fparams, 0, sizeof(fparams)); + fparams.verification_block_A = vblock; + fparams.verification_size_A = sizeof(VbKeyBlockHeader); + fparams.verification_block_B = vblock + 1; + fparams.verification_size_B = sizeof(VbKeyBlockHeader); + + Memset(vblock, 0, sizeof(vblock)); + Memset(mpreamble, 0, sizeof(mpreamble)); + for (i = 0; i < 2; i++) { + /* Default verification blocks to working in all modes */ + vblock[i].key_block_flags = 0x0F; + vblock[i].data_key.key_version = 2; + /* Fix up offsets to preambles */ + vblock[i].key_block_size = + (uint8_t*)(mpreamble + i) - (uint8_t*)(vblock + i); + + mpreamble[i].header_version_minor = 1; /* Supports preamble flags */ + mpreamble[i].firmware_version = 4; + /* Point kernel subkey to some data following the key header */ + PublicKeyInit(&mpreamble[i].kernel_subkey, + (uint8_t*)&mpreamble[i].body_signature, 20); + mpreamble[i].kernel_subkey.algorithm = 7 + i; + mpreamble[i].body_signature.data_size = 20000 + 1000 * i; + } + + Memset(&vnc, 0, sizeof(vnc)); + VbNvSetup(&vnc); + + Memset(&shared_data, 0, sizeof(shared_data)); + VbSharedDataInit(shared, sizeof(shared_data)); + shared->fw_version_tpm = 0x00020004; + + Memset(&gbb_data, 0, sizeof(gbb_data)); + gbb->rootkey_offset = sizeof(GoogleBinaryBlockHeader); + + Memset(&data_key, 0, sizeof(data_key)); + + digest_size = 1234; + digest_returned = NULL; + digest_expect_ptr = NULL; + hash_fw_index = -1; +} + +/****************************************************************************/ +/* Mocked verification functions */ + +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"); + TEST_NEQ(block==vblock || block==vblock+1, 0, " Verify a valid key block"); + + /* Mock uses header_version_major to hold return value */ + return block->header_version_major; +} + +int VerifyFirmwarePreamble(const VbFirmwarePreambleHeader* preamble, + uint64_t size, const RSAPublicKey* key) { + TEST_PTR_EQ(key, &data_key, " Verify preamble data key"); + TEST_NEQ(preamble==mpreamble || preamble==mpreamble+1, 0, + " Verify a valid preamble"); + + /* Mock uses header_version_major to hold return value */ + return preamble->header_version_major; +} + +RSAPublicKey* PublicKeyToRSA(const VbPublicKey* key) { + /* Mock uses algorithm!0 to mean invalid key */ + if (key->algorithm) + return NULL; + /* Mock uses data key len to hold number of alloc'd keys */ + data_key.len++; + return &data_key; +} + +void RSAPublicKeyFree(RSAPublicKey* key) { + TEST_PTR_EQ(key, &data_key, " RSA data key"); + data_key.len--; +} + +void DigestInit(DigestContext* ctx, int sig_algorithm) { + digest_size = 0; +} + +void DigestUpdate(DigestContext* ctx, const uint8_t* data, uint32_t len) { + TEST_PTR_EQ(data, digest_expect_ptr, " Digesting expected data"); + digest_size += len; +} + +uint8_t* DigestFinal(DigestContext* ctx) { + digest_returned = (uint8_t*)VbExMalloc(4); + return digest_returned; +} + +VbError_t VbExHashFirmwareBody(VbCommonParams* cparams, + uint32_t firmware_index) { + if (VB_SELECT_FIRMWARE_A == firmware_index) + hash_fw_index = 0; + else if (VB_SELECT_FIRMWARE_B == firmware_index) + hash_fw_index = 1; + else + return VBERROR_INVALID_PARAMETER; + + digest_expect_ptr = (uint8_t*)(vblock + hash_fw_index) + 5; + VbUpdateFirmwareBodyHash( + cparams, digest_expect_ptr, + mpreamble[hash_fw_index].body_signature.data_size - 1024); + VbUpdateFirmwareBodyHash(cparams, digest_expect_ptr, 1024); + + /* If signature offset is 42, hash the wrong amount and return success */ + if (42 == mpreamble[hash_fw_index].body_signature.sig_offset) { + VbUpdateFirmwareBodyHash(cparams, digest_expect_ptr, 4); + return VBERROR_SUCCESS; + } + + /* Otherwise, mocked function uses body signature offset as returned value */ + return mpreamble[hash_fw_index].body_signature.sig_offset; +} + +int VerifyDigest(const uint8_t* digest, const VbSignature *sig, + const RSAPublicKey* key) { + TEST_PTR_EQ(digest, digest_returned, "Verifying expected digest"); + TEST_PTR_EQ(key, &data_key, "Verifying using data key"); + TEST_PTR_EQ(sig, &mpreamble[hash_fw_index].body_signature, "Verifying sig"); + /* Mocked function uses sig size as return value for verifying digest */ + return sig->sig_size; +} + +/****************************************************************************/ +/* Test LoadFirmware() and check expected return value and recovery reason */ +static void TestLoadFirmware(VbError_t expected_retval, + uint8_t expected_recovery, const char* desc) { + uint32_t rr = 256; + + TEST_EQ(LoadFirmware(&cparams, &fparams, &vnc), expected_retval, desc); + VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &rr); + TEST_EQ(rr, expected_recovery, " recovery reason"); + TEST_EQ(data_key.len, 0, " Data key free must be paired with alloc"); +} + +/****************************************************************************/ + +static void LoadFirmwareTest(void) { + uint32_t u; + + /* Test error should cause abort */ + ResetMocks(); + VbNvSet(&vnc, VBNV_TEST_ERROR_FUNC, VBNV_TEST_ERROR_LOAD_FIRMWARE); + VbNvSet(&vnc, VBNV_TEST_ERROR_NUM, 1); + TestLoadFirmware(VBERROR_SIMULATED, VBNV_RECOVERY_RO_TEST_LF, + "Simulated error"); + TEST_EQ(shared->firmware_index, 0xFF, "Error means no firmware index"); + + /* Require GBB */ + ResetMocks(); + cparams.gbb_data = NULL; + TestLoadFirmware(VBERROR_INVALID_GBB, VBNV_RECOVERY_RO_UNSPECIFIED, + "No GBB"); + + /* Key block flags must match */ + /* Normal boot */ + ResetMocks(); + vblock[0].key_block_flags = KEY_BLOCK_FLAG_DEVELOPER_1; + vblock[1].key_block_flags = + KEY_BLOCK_FLAG_DEVELOPER_0 | KEY_BLOCK_FLAG_RECOVERY_1; + TestLoadFirmware(VBERROR_LOAD_FIRMWARE, + (VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + + VBSD_LF_CHECK_REC_MISMATCH), + "Flags mismatch dev=0"); + TEST_EQ(shared->flags & VBSD_LF_DEV_SWITCH_ON, 0, + "Dev flag in shared.flags dev=0"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_DEV_MISMATCH, + "Key block flag mismatch for dev=0"); + TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_REC_MISMATCH, + "Key block flag mismatch for rec=0"); + /* Developer boot */ + ResetMocks(); + shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; + vblock[0].key_block_flags = KEY_BLOCK_FLAG_DEVELOPER_0; + vblock[1].key_block_flags = + KEY_BLOCK_FLAG_DEVELOPER_1 | KEY_BLOCK_FLAG_RECOVERY_1; + TestLoadFirmware(VBERROR_LOAD_FIRMWARE, + (VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + + VBSD_LF_CHECK_REC_MISMATCH), + "Flags mismatch dev=1"); + TEST_NEQ(shared->flags & VBSD_LF_DEV_SWITCH_ON, 0, + "Dev flag in shared.flags dev=1"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_DEV_MISMATCH, + "Key block flag mismatch for dev=1"); + TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_REC_MISMATCH, + "Key block flag mismatch for rec=1"); + + /* Test key block verification with A and key version rollback with B */ + ResetMocks(); + vblock[0].header_version_major = 1; /* Simulate failure */ + vblock[1].data_key.key_version = 1; /* Simulate rollback */ + TestLoadFirmware(VBERROR_LOAD_FIRMWARE, + (VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + + VBSD_LF_CHECK_KEY_ROLLBACK), + "Key block invalid / key version rollback"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VERIFY_KEYBLOCK, + "Key block invalid"); + TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_KEY_ROLLBACK, + "Key version rollback "); + TEST_EQ(shared->fw_version_lowest, 0, "Lowest valid version"); + TEST_EQ(shared->fw_version_tpm, 0x20004, "TPM version"); + + /* Test invalid key version with A and bad data key with B */ + ResetMocks(); + vblock[0].data_key.key_version = 0x10003; /* Version > 0xFFFF is invalid */ + vblock[1].data_key.algorithm = 1; /* Simulate invalid data key */ + TestLoadFirmware(VBERROR_LOAD_FIRMWARE, + (VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + + VBSD_LF_CHECK_DATA_KEY_PARSE), + "Key version overflow / invalid data key"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_KEY_ROLLBACK, + "Key version overflow"); + TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_DATA_KEY_PARSE, + "Data key invalid"); + + /* Test invalid preamble with A */ + ResetMocks(); + mpreamble[0].header_version_major = 1; /* Simulate failure */ + vblock[1].key_block_flags = 0; /* Invalid */ + TestLoadFirmware(VBERROR_LOAD_FIRMWARE, + (VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + + VBSD_LF_CHECK_VERIFY_PREAMBLE), + "Preamble invalid"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VERIFY_PREAMBLE, + "Preamble invalid A"); + + /* Test invalid firmware versions */ + ResetMocks(); + mpreamble[0].firmware_version = 3; /* Simulate rollback */ + mpreamble[1].firmware_version = 0x10001; /* Check overflow */ + TestLoadFirmware(VBERROR_LOAD_FIRMWARE, + (VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + + VBSD_LF_CHECK_FW_ROLLBACK), + "Firmware version check"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_FW_ROLLBACK, + "Firmware version rollback"); + TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_FW_ROLLBACK, + "Firmware version overflow"); + + /* Test RO normal with A */ + ResetMocks(); + mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL; + vblock[1].key_block_flags = 0; /* Invalid */ + TestLoadFirmware(VBERROR_LOAD_FIRMWARE, + (VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + + VBSD_LF_CHECK_NO_RO_NORMAL), + "Preamble asked for RO normal but fw doesn't support it"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_NO_RO_NORMAL, + "No RO normal A"); + + /* If RO normal is supported, don't need to verify the firmware body */ + ResetMocks(); + mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL; + /* Mock bad sig, to ensure we didn't use it */ + mpreamble[0].body_signature.sig_size = 1; + shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT; + vblock[1].key_block_flags = 0; /* Invalid */ + TestLoadFirmware(VBERROR_SUCCESS, 0, "RO normal A"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID, "RO normal A valid"); + TEST_EQ(shared->firmware_index, 0, "Boot A shared index"); + TEST_EQ(shared->fw_keyblock_flags, vblock[0].key_block_flags, + "Copy key block flags"); + TEST_EQ(shared->kernel_subkey.algorithm, 7, "Copy kernel subkey"); + + /* If both A and B are valid and same version as TPM, A is selected + * and B isn't attempted. */ + ResetMocks(); + mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL; + mpreamble[1].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL; + shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT; + TestLoadFirmware(VBERROR_SUCCESS, 0, "Check A then B"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID, "RO normal A valid"); + TEST_EQ(shared->check_fw_b_result, 0, "RO normal B not checked "); + TEST_EQ(shared->firmware_index, 0, "Boot A"); + TEST_EQ(shared->flags & VBSD_FWB_TRIED, 0, "Didn't try firmware B"); + TEST_EQ(shared->kernel_subkey.algorithm, 7, "Copy kernel subkey"); + /* But if try B flag is set, B is selected and A not attempted */ + ResetMocks(); + mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL; + mpreamble[1].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL; + shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT; + VbNvSet(&vnc, VBNV_TRY_B_COUNT, 5); + TestLoadFirmware(VBERROR_SUCCESS, 0, "Check B then A"); + TEST_EQ(shared->check_fw_a_result, 0, "RO normal A not checked "); + TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_VALID, "RO normal B valid"); + TEST_EQ(shared->firmware_index, 1, "Boot B"); + TEST_NEQ(shared->flags & VBSD_FWB_TRIED, 0, "Tried firmware B"); + TEST_EQ(shared->kernel_subkey.algorithm, 8, "Copy kernel subkey"); + VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u); + TEST_EQ(u, 4, "Used up a try"); + + /* If both A and B are valid and grater version than TPM, A is + * selected and B preamble (but not body) is verified. */ + ResetMocks(); + mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL; + mpreamble[1].flags = 0; + mpreamble[0].firmware_version = 5; + mpreamble[1].firmware_version = 6; + shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT; + TestLoadFirmware(VBERROR_SUCCESS, 0, "Check A then B advancing version"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID, "RO normal A valid"); + TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_HEADER_VALID, + "RO normal B header valid"); + TEST_EQ(shared->firmware_index, 0, "Boot A"); + TEST_EQ(shared->fw_keyblock_flags, vblock[0].key_block_flags, "Key block A"); + TEST_EQ(shared->kernel_subkey.algorithm, 7, "Copy kernel subkey"); + TEST_EQ(shared->fw_version_lowest, 0x20005, "Lowest valid version"); + TEST_EQ(shared->fw_version_tpm, 0x20005, "TPM version advanced"); + + /* Verify firmware data */ + ResetMocks(); + vblock[1].key_block_flags = 0; /* Invalid */ + TestLoadFirmware(VBERROR_SUCCESS, 0, "Verify firmware body"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID, + "Firmware body A valid"); + TEST_EQ(shared->firmware_index, 0, "Boot A shared index"); + TEST_EQ(hash_fw_index, 0, "Hash firmware data A"); + TEST_EQ(digest_size, mpreamble[0].body_signature.data_size, + "Verified all data expected"); + + /* Test error getting firmware body */ + ResetMocks(); + mpreamble[0].body_signature.sig_offset = VBERROR_UNKNOWN; + vblock[1].key_block_flags = 0; /* Invalid */ + TestLoadFirmware(VBERROR_LOAD_FIRMWARE, + (VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + + VBSD_LF_CHECK_GET_FW_BODY), + "Error getting firmware body"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_GET_FW_BODY, + "Firmware body A"); + + /* Test digesting the wrong amount */ + ResetMocks(); + mpreamble[0].body_signature.sig_offset = 42; /* Mock hashing wrong amount */ + vblock[1].key_block_flags = 0; /* Invalid */ + TestLoadFirmware(VBERROR_LOAD_FIRMWARE, + (VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + + VBSD_LF_CHECK_HASH_WRONG_SIZE), + "Hash wrong size"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_HASH_WRONG_SIZE, + "Firmware hash wrong size A"); + + /* Test bad signature */ + ResetMocks(); + mpreamble[0].body_signature.sig_size = 1; /* Mock bad sig */ + vblock[1].key_block_flags = 0; /* Invalid */ + TestLoadFirmware(VBERROR_LOAD_FIRMWARE, + (VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + + VBSD_LF_CHECK_VERIFY_BODY), + "Bad signature"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VERIFY_BODY, + "Bad signature A"); + + /* Test unable to store kernel data key */ + ResetMocks(); + mpreamble[0].kernel_subkey.key_size = VB_SHARED_DATA_MIN_SIZE + 1; + vblock[1].key_block_flags = 0; /* Invalid */ + TestLoadFirmware(VBERROR_LOAD_FIRMWARE, + (VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + + VBSD_LF_CHECK_VALID), + "Kernel key too big"); + TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID, + "Kernel key too big"); +} + + +/* disable MSVC warnings on unused arguments */ +__pragma(warning (disable: 4100)) + +int main(int argc, char* argv[]) { + int error_code = 0; + + LoadFirmwareTest(); + + if (!gTestSuccess) + error_code = 255; + + return error_code; +} |