diff options
author | Randall Spangler <rspangler@chromium.org> | 2011-08-26 12:53:16 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2011-08-26 14:15:26 -0700 |
commit | cb3313e8cb6a95e5ad02860222fed18db82b37af (patch) | |
tree | be58c53d790ea79516445f922bec04c6ab087ddc /tests | |
parent | c0911e27b93eae772088ed09d7a41561b7a5b0b6 (diff) | |
download | vboot-cb3313e8cb6a95e5ad02860222fed18db82b37af.tar.gz |
Partial unit tests for rollback_index
BUG=chromium-os:17564
TEST=make && make runtests
Change-Id: I8ea6bcc15f277e10c5b8539f2ea19ad90be34889
Reviewed-on: http://gerrit.chromium.org/gerrit/6770
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Stefan Reinauer <reinauer@chromium.org>
Tested-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile | 5 | ||||
-rw-r--r-- | tests/rollback_index2_tests.c | 256 | ||||
-rw-r--r-- | tests/test_common.c | 31 | ||||
-rw-r--r-- | tests/test_common.h | 10 |
4 files changed, 293 insertions, 9 deletions
diff --git a/tests/Makefile b/tests/Makefile index b81825bc..f602b1e8 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -11,6 +11,7 @@ INCLUDES += -I./include \ BUILD_ROOT = ${BUILD}/tests TEST_NAMES = cgptlib_test \ + rollback_index2_tests \ rsa_padding_test \ rsa_verify_benchmark \ sha_benchmark \ @@ -30,7 +31,8 @@ TEST_LIB = ${BUILD_ROOT}/test.a TEST_LIB_SRCS = test_common.c timer_utils.c crc32_test.c TEST_LIB_OBJS = $(TEST_LIB_SRCS:%.c=${BUILD_ROOT}/%.o) ALL_DEPS = $(addsuffix .d,${TEST_BINS} ${TEST_LIB_OBJS}) -CFLAGS += -MMD -MF $@.d +# Allow multiple definitions, so tests can mock functions from other libraries +CFLAGS += -MMD -MF $@.d -Xlinker --allow-multiple-definition LIBS := ${TEST_LIB} $(HOSTLIB) @@ -94,6 +96,7 @@ runcryptotests: # Run other misc tests runmisctests: ./run_vbutil_tests.sh + ${BUILD_ROOT}/rollback_index2_tests ${BUILD_ROOT}/stateful_util_tests ${BUILD_ROOT}/tpm_bootmode_tests ${BUILD_ROOT}/utility_string_tests diff --git a/tests/rollback_index2_tests.c b/tests/rollback_index2_tests.c new file mode 100644 index 00000000..cd5fcb90 --- /dev/null +++ b/tests/rollback_index2_tests.c @@ -0,0 +1,256 @@ +/* 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 rollback_index functions + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define _STUB_IMPLEMENTATION_ /* So we can use memset() ourselves */ + +#include "rollback_index.h" +#include "test_common.h" +#include "tlcl.h" +#include "utility.h" +#include "vboot_common.h" + +static char calls[16384]; +static char *cnext = calls; +static int ccount = 0; +static int cfail = 0; +static uint32_t cfail_err = TPM_SUCCESS; + +static TPM_PERMANENT_FLAGS mock_pflags; +static RollbackSpaceFirmware mock_rsf; +static RollbackSpaceKernel mock_rsk; + +static void ResetMocks(int fail_on_call, uint32_t fail_with_err) { + cnext = calls; + ccount = 0; + cfail = fail_on_call; + cfail_err = fail_with_err; + + Memset(&mock_pflags, 0, sizeof(mock_pflags)); + Memset(&mock_rsf, 0, sizeof(mock_rsf)); + Memset(&mock_rsk, 0, sizeof(mock_rsk)); +} + +/****************************************************************************/ +/* Mocks for tlcl functions which log the calls made to calls[]. */ + +uint32_t TlclForceClear(void) { + cnext += sprintf(cnext, "TlclForceClear()\n"); + return (++ccount == cfail) ? cfail_err : TPM_SUCCESS; +} + +uint32_t TlclSetEnable(void) { + cnext += sprintf(cnext, "TlclSetEnable()\n"); + return (++ccount == cfail) ? cfail_err : TPM_SUCCESS; +} + +uint32_t TlclSetDeactivated(uint8_t flag) { + cnext += sprintf(cnext, "TlclSetDeactivated(%d)\n", flag); + return (++ccount == cfail) ? cfail_err : TPM_SUCCESS; +} + +uint32_t TlclWrite(uint32_t index, const void* data, uint32_t length) { + cnext += sprintf(cnext, "TlclWrite(0x%x, %d)\n", index, length); + + if (FIRMWARE_NV_INDEX == index) { + TEST_EQ(length, sizeof(mock_rsf), "TlclWrite rsf size"); + Memcpy(&mock_rsf, data, length); + } else if (KERNEL_NV_INDEX == index) { + TEST_EQ(length, sizeof(mock_rsk), "TlclWrite rsk size"); + Memcpy(&mock_rsk, data, length); + } + + return (++ccount == cfail) ? cfail_err : TPM_SUCCESS; +} + +uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) { + cnext += sprintf(cnext, "TlclDefineSpace(0x%x, 0x%x, %d)\n", + index, perm, size); + return (++ccount == cfail) ? cfail_err : TPM_SUCCESS; +} + +uint32_t TlclSelfTestFull(void) { + cnext += sprintf(cnext, "TlclSelfTestFull()\n"); + return (++ccount == cfail) ? cfail_err : TPM_SUCCESS; +} + +uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS* pflags) { + cnext += sprintf(cnext, "TlclGetPermanentFlags()\n"); + Memcpy(pflags, &mock_pflags, sizeof(mock_pflags)); + return (++ccount == cfail) ? cfail_err : TPM_SUCCESS; +} + +uint32_t TlclFinalizePhysicalPresence(void) { + cnext += sprintf(cnext, "TlclFinalizePhysicalPresence()\n"); + mock_pflags.physicalPresenceLifetimeLock = 1; + return (++ccount == cfail) ? cfail_err : TPM_SUCCESS; +} + +uint32_t TlclSetNvLocked(void) { + cnext += sprintf(cnext, "TlclSetNvLocked()\n"); + mock_pflags.nvLocked = 1; + return (++ccount == cfail) ? cfail_err : TPM_SUCCESS; +} + +/****************************************************************************/ +/* Tests for misc helper functions */ + +static void MiscTest(void) { + uint8_t buf[8]; + + ResetMocks(0, 0); + TEST_EQ(TPMClearAndReenable(), 0, "TPMClearAndReenable()"); + TEST_STR_EQ(calls, + "TlclForceClear()\n" + "TlclSetEnable()\n" + "TlclSetDeactivated(0)\n", + "tlcl calls"); + + ResetMocks(0, 0); + TEST_EQ(SafeWrite(0x123, buf, 8), 0, "SafeWrite()"); + TEST_STR_EQ(calls, + "TlclWrite(0x123, 8)\n", + "tlcl calls"); + + ResetMocks(1, TPM_E_BADINDEX); + TEST_EQ(SafeWrite(0x123, buf, 8), TPM_E_BADINDEX, "SafeWrite() bad"); + TEST_STR_EQ(calls, + "TlclWrite(0x123, 8)\n", + "tlcl calls"); + + ResetMocks(1, TPM_E_MAXNVWRITES); + TEST_EQ(SafeWrite(0x123, buf, 8), 0, "SafeWrite() retry max writes"); + TEST_STR_EQ(calls, + "TlclWrite(0x123, 8)\n" + "TlclForceClear()\n" + "TlclSetEnable()\n" + "TlclSetDeactivated(0)\n" + "TlclWrite(0x123, 8)\n", + "tlcl calls"); + + ResetMocks(0, 0); + TEST_EQ(SafeDefineSpace(0x123, 6, 8), 0, "SafeDefineSpace()"); + TEST_STR_EQ(calls, + "TlclDefineSpace(0x123, 0x6, 8)\n", + "tlcl calls"); + + ResetMocks(1, TPM_E_BADINDEX); + TEST_EQ(SafeDefineSpace(0x123, 6, 8), TPM_E_BADINDEX, + "SafeDefineSpace() bad"); + TEST_STR_EQ(calls, + "TlclDefineSpace(0x123, 0x6, 8)\n", + "tlcl calls"); + + ResetMocks(1, TPM_E_MAXNVWRITES); + TEST_EQ(SafeDefineSpace(0x123, 6, 8), 0, + "SafeDefineSpace() retry max writes"); + TEST_STR_EQ(calls, + "TlclDefineSpace(0x123, 0x6, 8)\n" + "TlclForceClear()\n" + "TlclSetEnable()\n" + "TlclSetDeactivated(0)\n" + "TlclDefineSpace(0x123, 0x6, 8)\n", + "tlcl calls"); +} + +/****************************************************************************/ + +/* Tests for one-time initialization */ +static void OneTimeInitTest(void) { + RollbackSpaceFirmware rsf; + RollbackSpaceKernel rsk; + + /* Complete initialization */ + ResetMocks(0, 0); + TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()"); + TEST_STR_EQ(calls, + "TlclSelfTestFull()\n" + "TlclGetPermanentFlags()\n" + "TlclFinalizePhysicalPresence()\n" + "TlclSetNvLocked()\n" + "TlclForceClear()\n" + "TlclSetEnable()\n" + "TlclSetDeactivated(0)\n" + /* kernel space */ + "TlclDefineSpace(0x1008, 0x1, 13)\n" + "TlclWrite(0x1008, 13)\n" + /* firmware space */ + "TlclDefineSpace(0x1007, 0x8001, 10)\n" + "TlclWrite(0x1007, 10)\n", + "tlcl calls"); + TEST_EQ(mock_rsf.struct_version, ROLLBACK_SPACE_FIRMWARE_VERSION, "rsf ver"); + TEST_EQ(mock_rsf.flags, 0, "rsf flags"); + TEST_EQ(mock_rsf.fw_versions, 0, "rsf fw_versions"); + TEST_EQ(mock_rsk.struct_version, ROLLBACK_SPACE_KERNEL_VERSION, "rsk ver"); + TEST_EQ(mock_rsk.uid, ROLLBACK_SPACE_KERNEL_UID, "rsk uid"); + TEST_EQ(mock_rsk.kernel_versions, 0, "rsk kernel_versions"); + + /* Physical presence already initialized */ + ResetMocks(0, 0); + mock_pflags.physicalPresenceLifetimeLock = 1; + TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()"); + TEST_STR_EQ(calls, + "TlclSelfTestFull()\n" + "TlclGetPermanentFlags()\n" + "TlclSetNvLocked()\n" + "TlclForceClear()\n" + "TlclSetEnable()\n" + "TlclSetDeactivated(0)\n" + /* kernel space */ + "TlclDefineSpace(0x1008, 0x1, 13)\n" + "TlclWrite(0x1008, 13)\n" + /* firmware space */ + "TlclDefineSpace(0x1007, 0x8001, 10)\n" + "TlclWrite(0x1007, 10)\n", + "tlcl calls"); + + /* NV locking already initialized */ + ResetMocks(0, 0); + mock_pflags.nvLocked = 1; + TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()"); + TEST_STR_EQ(calls, + "TlclSelfTestFull()\n" + "TlclGetPermanentFlags()\n" + "TlclFinalizePhysicalPresence()\n" + "TlclForceClear()\n" + "TlclSetEnable()\n" + "TlclSetDeactivated(0)\n" + /* kernel space */ + "TlclDefineSpace(0x1008, 0x1, 13)\n" + "TlclWrite(0x1008, 13)\n" + /* firmware space */ + "TlclDefineSpace(0x1007, 0x8001, 10)\n" + "TlclWrite(0x1007, 10)\n", + "tlcl calls"); + + /* Self test error */ + ResetMocks(1, TPM_E_IOERROR); + TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), TPM_E_IOERROR, + "OneTimeInitializeTPM() selftest"); + TEST_STR_EQ(calls, + "TlclSelfTestFull()\n", + "tlcl calls"); +} + + +/* disable MSVC warnings on unused arguments */ +__pragma(warning (disable: 4100)) + +int main(int argc, char* argv[]) { + int error_code = 0; + + MiscTest(); + OneTimeInitTest(); + + if (!gTestSuccess) + error_code = 255; + + return error_code; +} diff --git a/tests/test_common.c b/tests/test_common.c index 6521fa0f..bb094e0f 100644 --- a/tests/test_common.c +++ b/tests/test_common.c @@ -8,6 +8,7 @@ #include "test_common.h" #include <stdio.h> +#include <string.h> #include "cryptolib.h" #include "file_keys.h" @@ -20,8 +21,7 @@ int TEST_EQ(int result, int expected_result, char* testname) { if (result == expected_result) { fprintf(stderr, "%s Test " COL_GREEN "PASSED\n" COL_STOP, testname); return 1; - } - else { + } else { fprintf(stderr, "%s Test " COL_RED "FAILED\n" COL_STOP, testname); fprintf(stderr, " Expected: %d, got: %d\n", expected_result, result); gTestSuccess = 0; @@ -33,8 +33,7 @@ int TEST_NEQ(int result, int not_expected_result, char* testname) { if (result != not_expected_result) { fprintf(stderr, "%s Test " COL_GREEN "PASSED\n" COL_STOP, testname); return 1; - } - else { + } else { fprintf(stderr, "%s Test " COL_RED "FAILED\n" COL_STOP, testname); fprintf(stderr, " Didn't expect %d, but got it.\n", not_expected_result); gTestSuccess = 0; @@ -47,8 +46,7 @@ int TEST_PTR_EQ(const void* result, const void* expected_result, if (result == expected_result) { fprintf(stderr, "%s Test " COL_GREEN "PASSED\n" COL_STOP, testname); return 1; - } - else { + } else { fprintf(stderr, "%s Test " COL_RED "FAILED\n" COL_STOP, testname); fprintf(stderr, " Expected: 0x%lx, got: 0x%lx\n", (long)expected_result, (long)result); @@ -56,3 +54,24 @@ int TEST_PTR_EQ(const void* result, const void* expected_result, return 0; } } + +int TEST_STR_EQ(const char* result, const char* expected_result, + char* testname) { + + if (!result || !expected_result) { + fprintf(stderr, "%s Test " COL_RED "FAILED\n" COL_STOP, testname); + fprintf(stderr, " String compare with NULL\n"); + gTestSuccess = 0; + return 0; + } else if (!strcmp(result, expected_result)) { + fprintf(stderr, "%s Test " COL_GREEN "PASSED\n" COL_STOP, testname); + return 1; + } else { + fprintf(stderr, "%s Test " COL_RED "FAILED\n" COL_STOP, testname); + fprintf(stderr, " Expected: \"%s\", got: \"%s\"\n", expected_result, + result); + gTestSuccess = 0; + return 0; + } + +} diff --git a/tests/test_common.h b/tests/test_common.h index 532e7b2f..47ffa2a4 100644 --- a/tests/test_common.h +++ b/tests/test_common.h @@ -17,11 +17,17 @@ int TEST_EQ(int result, int expected_result, char* testname); * Also update the global gTestSuccess flag if test fails. */ int TEST_NEQ(int result, int not_expected_result, char* testname); -/* Return 1 if result is equal to expected_result, else return 0. - * Also update the global gTestSuccess flag if test fails. */ +/* 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); +/* 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); + /* ANSI Color coding sequences. * * Don't use \e as MSC does not recognize it as a valid escape sequence. |