From c3d488d155961d2849dfdaa4f0461df1aa95c2ca Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Mon, 28 Jan 2013 16:23:48 -0800 Subject: Add tlcl tests Verifies the right TPM commands are called, but doesn't check at a detailed level that they're packed properly. BUG=chromium-os:38139 BRANCH=none TEST=make runtests Change-Id: I6c14db083ac0a40d4738582d200d9687cddb99de Signed-off-by: Randall Spangler Reviewed-on: https://gerrit.chromium.org/gerrit/42261 Reviewed-by: Bill Richardson --- Makefile | 7 + firmware/include/tlcl.h | 2 + firmware/lib/tpm_lite/tlcl.c | 5 + tests/tlcl_tests.c | 351 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 365 insertions(+) create mode 100644 tests/tlcl_tests.c diff --git a/Makefile b/Makefile index b14e8ef3..6129697b 100644 --- a/Makefile +++ b/Makefile @@ -411,6 +411,7 @@ TEST_NAMES = \ sha_benchmark \ sha_tests \ stateful_util_tests \ + tlcl_tests \ tpm_bootmode_tests \ utility_string_tests \ utility_tests \ @@ -838,6 +839,11 @@ ${BUILD}/tests/rollback_index2_tests: OBJS += \ ${BUILD}/tests/rollback_index2_tests: \ ${BUILD}/firmware/lib/rollback_index_for_test.o +${BUILD}/tests/tlcl_tests: OBJS += \ + ${BUILD}/firmware/lib/tpm_lite/tlcl_for_test.o +${BUILD}/tests/tlcl_tests: \ + ${BUILD}/firmware/lib/tpm_lite/tlcl_for_test.o + ${BUILD}/tests/vboot_audio_tests: OBJS += \ ${BUILD}/firmware/lib/vboot_audio_for_test.o ${BUILD}/tests/vboot_audio_tests: \ @@ -933,6 +939,7 @@ runmisctests: test_setup ${RUNTEST} ${BUILD_RUN}/tests/rsa_utility_tests ${RUNTEST} ${BUILD_RUN}/tests/sha_tests ${RUNTEST} ${BUILD_RUN}/tests/stateful_util_tests + ${RUNTEST} ${BUILD_RUN}/tests/tlcl_tests ${RUNTEST} ${BUILD_RUN}/tests/tpm_bootmode_tests ${RUNTEST} ${BUILD_RUN}/tests/utility_string_tests ${RUNTEST} ${BUILD_RUN}/tests/utility_tests diff --git a/firmware/include/tlcl.h b/firmware/include/tlcl.h index ca4e47f7..5ce05638 100644 --- a/firmware/include/tlcl.h +++ b/firmware/include/tlcl.h @@ -134,6 +134,8 @@ uint32_t TlclPhysicalPresenceCMDEnable(void); */ uint32_t TlclFinalizePhysicalPresence(void); +uint32_t TlclAssertPhysicalPresenceResult(void); + /** * Turn off physical presence and locks it off until next reboot. The TPM * error code is returned. diff --git a/firmware/lib/tpm_lite/tlcl.c b/firmware/lib/tpm_lite/tlcl.c index ce5614e1..7acca9a1 100644 --- a/firmware/lib/tpm_lite/tlcl.c +++ b/firmware/lib/tpm_lite/tlcl.c @@ -21,6 +21,11 @@ #include "utility.h" #include "vboot_api.h" +#ifdef FOR_TEST +/* Allow unit testing implementation of TlclSendReceive() */ +#undef CHROMEOS_ENVIRONMENT +#endif + /* Sets the size field of a TPM command. */ static INLINE void SetTpmCommandSize(uint8_t* buffer, uint32_t size) { ToTpmUint32(buffer + sizeof(uint16_t), size); diff --git a/tests/tlcl_tests.c b/tests/tlcl_tests.c new file mode 100644 index 00000000..4765cff3 --- /dev/null +++ b/tests/tlcl_tests.c @@ -0,0 +1,351 @@ +/* Copyright (c) 2013 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 TPM lite library + */ + +#include +#include +#include + +#include +/* Don't use the vboot constants, since they conflict with the TCS lib */ +#define VBOOT_REFERENCE_TSS_CONSTANTS_H_ + +#include "host_common.h" +#include "test_common.h" +#include "tlcl.h" +#include "tlcl_internal.h" +#include "vboot_common.h" + +/* Mock data */ +static char debug_info[4096]; +static VbError_t mock_retval; + +/* Call to mocked VbExTpmSendReceive() */ +struct srcall +{ + const uint8_t *req; /* Request */ + uint8_t *rsp; /* Response */ + uint8_t rsp_buf[32]; /* Default response buffer, if not overridden */ + int req_size; /* Request size */ + uint32_t req_cmd; /* Request command code */ + int rsp_size; /* Response size */ + VbError_t retval; /* Value to return */ +}; + +#define MAXCALLS 8 +static struct srcall calls[MAXCALLS]; +static int ncalls; + +/** + * Reset mock data (for use before each test) + */ +static void ResetMocks(void) +{ + int i; + + *debug_info = 0; + mock_retval = VBERROR_SUCCESS; + + memset(calls, 0, sizeof(calls)); + for (i = 0; i < MAXCALLS; i++) + calls[i].rsp = calls[i].rsp_buf; + ncalls = 0; +} + +/** + * Set response code and length for call . + */ +static void SetResponse(int call_idx, uint32_t response_code, int rsp_size) +{ + struct srcall *c = calls + call_idx; + + c->rsp_size = rsp_size; + ToTpmUint32(c->rsp_buf + 6, response_code); +} + +/* Mocks */ + +VbError_t VbExTpmInit(void) +{ + return mock_retval; +} + + +VbError_t VbExTpmClose(void) +{ + return mock_retval; +} + +VbError_t VbExTpmSendReceive(const uint8_t *request, uint32_t request_length, + uint8_t *response, uint32_t *response_length) +{ + struct srcall *c = calls + ncalls++; + + c->req = request; + c->req_size = request_length; + + /* Parse out the command code */ + FromTpmUint32(request + 6, &c->req_cmd); + + // KLUDGE - remove + printf("TSR [%d] 0x%x\n", ncalls-1, c->req_cmd); + + memset(response, 0, *response_length); + if (c->rsp_size) + memcpy(response, c->rsp, c->rsp_size); + *response_length = c->rsp_size; + + return c->retval; +} + +/** + * Test assorted tlcl functions + */ +static void TlclTest(void) +{ + uint8_t buf[32], buf2[32]; + + ResetMocks(); + TEST_EQ(TlclLibInit(), VBERROR_SUCCESS, "Init"); + + ResetMocks(); + mock_retval = VBERROR_SIMULATED; + TEST_EQ(TlclLibInit(), mock_retval, "Init bad"); + + ResetMocks(); + TEST_EQ(TlclLibClose(), VBERROR_SUCCESS, "Close"); + + ResetMocks(); + mock_retval = VBERROR_SIMULATED; + TEST_EQ(TlclLibClose(), mock_retval, "Close bad"); + + ResetMocks(); + ToTpmUint32(buf + 2, 123); + TEST_EQ(TlclPacketSize(buf), 123, "TlclPacketSize"); + + ResetMocks(); + ToTpmUint32(buf + 2, 10); + TEST_EQ(TlclSendReceive(buf, buf2, sizeof(buf2)), 0, "SendReceive"); + TEST_PTR_EQ(calls[0].req, buf, "SendReceive req ptr"); + TEST_EQ(calls[0].req_size, 10, "SendReceive size"); + + ResetMocks(); + calls[0].retval = VBERROR_SIMULATED; + ToTpmUint32(buf + 2, 10); + TEST_EQ(TlclSendReceive(buf, buf2, sizeof(buf2)), VBERROR_SIMULATED, + "SendReceive fail"); + + ResetMocks(); + SetResponse(0, 123, 10); + ToTpmUint32(buf + 2, 10); + TEST_EQ(TlclSendReceive(buf, buf2, sizeof(buf2)), 123, + "SendReceive error response"); + + // TODO: continue self test (if needed or doing) + // TODO: then retry doing self test + +} + + +/** + * Test send-command functions + */ +static void SendCommandTest(void) +{ + ResetMocks(); + TEST_EQ(TlclStartup(), 0, "SaveState"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_Startup, " cmd"); + + ResetMocks(); + TEST_EQ(TlclSaveState(), 0, "SaveState"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_SaveState, " cmd"); + + ResetMocks(); + TEST_EQ(TlclResume(), 0, "Resume"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_Startup, " cmd"); + + ResetMocks(); + TEST_EQ(TlclSelfTestFull(), 0, "SelfTestFull"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_SelfTestFull, " cmd"); + + ResetMocks(); + TEST_EQ(TlclContinueSelfTest(), 0, "ContinueSelfTest"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_ContinueSelfTest, " cmd"); + + ResetMocks(); + TEST_EQ(TlclAssertPhysicalPresence(), 0, + "AssertPhysicalPresence"); + TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, " cmd"); + + ResetMocks(); + TEST_EQ(TlclPhysicalPresenceCMDEnable(), 0, + "PhysicalPresenceCMDEnable"); + TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, " cmd"); + + ResetMocks(); + TEST_EQ(TlclFinalizePhysicalPresence(), 0, + "FinalizePhysicalPresence"); + TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, " cmd"); + + ResetMocks(); + TEST_EQ(TlclAssertPhysicalPresenceResult(), 0, + "AssertPhysicalPresenceResult"); + TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, " cmd"); + + ResetMocks(); + TEST_EQ(TlclLockPhysicalPresence(), 0, + "LockPhysicalPresence"); + TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, " cmd"); + + ResetMocks(); + TEST_EQ(TlclIsOwned(), 0, "IsOwned"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_ReadPubek, " cmd"); + ResetMocks(); + calls[0].retval = VBERROR_SIMULATED; + TEST_NEQ(TlclIsOwned(), 0, "IsOwned"); + + ResetMocks(); + TEST_EQ(TlclForceClear(), 0, "ForceClear"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_ForceClear, " cmd"); + + ResetMocks(); + TEST_EQ(TlclSetEnable(), 0, "SetEnable"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_PhysicalEnable, " cmd"); + + ResetMocks(); + TEST_EQ(TlclClearEnable(), 0, "ClearEnable"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_PhysicalDisable, " cmd"); + + ResetMocks(); + TEST_EQ(TlclSetDeactivated(0), 0, "SetDeactivated"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_PhysicalSetDeactivated, " cmd"); +} + +/** + * NV spaces test + * + * TODO: check params/data read/written. + */ +static void ReadWriteTest(void) +{ + uint8_t buf[32]; + + ResetMocks(); + TEST_EQ(TlclDefineSpace(1, 2, 3), 0, "DefineSpace"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_DefineSpace, " cmd"); + + ResetMocks(); + TEST_EQ(TlclSetNvLocked(), 0, "SetNvLocked"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_DefineSpace, " cmd"); + + ResetMocks(); + TEST_EQ(TlclWrite(1, buf, 3), 0, "Write"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_WriteValue, " cmd"); + + ResetMocks(); + TEST_EQ(TlclRead(1, buf, 3), 0, "Read"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_ReadValue, " cmd"); + + ResetMocks(); + TEST_EQ(TlclWriteLock(1), 0, "WriteLock"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_WriteValue, " cmd"); + + ResetMocks(); + TEST_EQ(TlclReadLock(1), 0, "ReadLock"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_ReadValue, " cmd"); + + ResetMocks(); + TEST_EQ(TlclSetGlobalLock(), 0, "SetGlobalLock"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_NV_WriteValue, " cmd"); +} + +/** + * Test PCR funcs + * + * TODO: check params/data read/written. + */ +static void PcrTest(void) +{ + uint8_t buf[kPcrDigestLength], buf2[kPcrDigestLength]; + + ResetMocks(); + TEST_EQ(TlclPCRRead(1, buf, kPcrDigestLength), 0, "PCRRead"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_PcrRead, " cmd"); + + ResetMocks(); + TEST_EQ(TlclPCRRead(1, buf, kPcrDigestLength - 1), TPM_E_IOERROR, + "PCRRead too small"); + + ResetMocks(); + TEST_EQ(TlclExtend(1, buf, buf2), 0, "Extend"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_Extend, " cmd"); +} + +/** + * Test flags / capabilities + * + * TODO: check params/data read/written. + */ +static void FlagsTest(void) +{ + TPM_PERMANENT_FLAGS pflags; + TPM_STCLEAR_FLAGS vflags; + uint8_t disable = 0, deactivated = 0, nvlocked = 0; + uint32_t u; + uint8_t buf[32]; + + ResetMocks(); + TEST_EQ(TlclGetPermanentFlags(&pflags), 0, "GetPermanentFlags"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd"); + + ResetMocks(); + TEST_EQ(TlclGetSTClearFlags(&vflags), 0, "GetSTClearFlags"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd"); + + ResetMocks(); + TEST_EQ(TlclGetFlags(NULL, NULL, NULL), 0, "GetFlags NULL"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd"); + ResetMocks(); + TEST_EQ(TlclGetFlags(&disable, &deactivated, &nvlocked), 0, "GetFlags"); + + ResetMocks(); + TEST_EQ(TlclGetPermissions(1, &u), 0, "GetPermissions"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd"); + + ResetMocks(); + TEST_EQ(TlclGetOwnership(buf), 0, "GetOwnership"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd"); +} + +/** + * Test random + * + * TODO: check params/data read/written. + * TODO: check overflow tests. + */ +static void RandomTest(void) +{ + uint8_t buf[32]; + uint32_t size; + + ResetMocks(); + size = sizeof(buf); + TEST_EQ(TlclGetRandom(buf, sizeof(buf), &size), 0, "GetRandom"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_GetRandom, " cmd"); + TEST_EQ(size, 0, " size 0"); +} + +int main(void) +{ + TlclTest(); + SendCommandTest(); + ReadWriteTest(); + PcrTest(); + FlagsTest(); + RandomTest(); + + return gTestSuccess ? 0 : 255; +} -- cgit v1.2.1