summaryrefslogtreecommitdiff
path: root/tests/rollback_index2_tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/rollback_index2_tests.c')
-rw-r--r--tests/rollback_index2_tests.c256
1 files changed, 256 insertions, 0 deletions
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;
+}