Additional cases for the test suite, and more commands added to TLCL
to support the new cases.
Review URL: http://codereview.chromium.org/1056001
diff --git a/src/include/tlcl.h b/src/include/tlcl.h
index 30c7350..e0b5626 100644
--- a/src/include/tlcl.h
+++ b/src/include/tlcl.h
@@ -26,6 +26,7 @@
/* Outputs an error message and quits the program.
*/
+POSSIBLY_UNUSED
static void error(const char *format, ...) {
va_list ap;
va_start(ap, format);
@@ -99,4 +100,20 @@
*/
int TlclIsOwned(void);
+/* Issues a ForceClear.
+ */
+void TlclForceClear(void);
+
+/* Issues a PhysicalEnable.
+ */
+void TlclPhysicalEnable(void);
+
+/* Issues a PhysicalSetDeactivated. Pass 0 to activate. Returns result code.
+ */
+int TlclPhysicalSetDeactivated(uint8_t flag);
+
+/* Gets some permanent flags of interest. (Add more here as needed.)
+ */
+int TlclGetFlags(uint8_t* disable, uint8_t* deactivated);
+
#endif /* TPM_LITE_TLCL_H_ */
diff --git a/src/testsuite/Makefile b/src/testsuite/Makefile
index 0211af5..0858671 100644
--- a/src/testsuite/Makefile
+++ b/src/testsuite/Makefile
@@ -23,7 +23,7 @@
CFLAGS += -Werror -Wall
#CFLAGS += -pedantic -ansi
-TESTS = tpmtest_readonly
+TESTS = tpmtest_readonly tpmtest_clear tpmtest_writelimit tpmtest_lock
all: $(TESTS)
diff --git a/src/testsuite/clear.c b/src/testsuite/clear.c
new file mode 100644
index 0000000..0042ed6
--- /dev/null
+++ b/src/testsuite/clear.c
@@ -0,0 +1,45 @@
+/* Copyright (c) 2010 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.
+ */
+
+/* Testing: ownership testing code, ForceClear, and nvram write limit.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <tss/tcs.h>
+
+#include "tlcl.h"
+
+/* These index values are used to create NVRAM spaces. They only need to be
+ * unique.
+ */
+#define INDEX0 0xda70
+#define INDEX1 0xda71
+#define INDEX2 0xda72
+#define INDEX3 0xda73
+
+int main(void) {
+ int owned;
+
+ TlclLibinit();
+
+#if !USE_TPM_EMULATOR
+ /* The emulator does these itself. */
+ TlclStartup();
+ TlclSelftestfull();
+#endif
+
+ TlclAssertPhysicalPresence();
+
+ owned = TlclIsOwned();
+ printf("tpm is %sowned\n", owned? "" : "NOT ");
+ if (owned) {
+ TlclForceClear();
+ printf("tpm was cleared\n");
+ }
+
+ return 0;
+}
diff --git a/src/testsuite/lock.c b/src/testsuite/lock.c
new file mode 100644
index 0000000..9b7cf75
--- /dev/null
+++ b/src/testsuite/lock.c
@@ -0,0 +1,31 @@
+/* Copyright (c) 2010 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.
+ */
+
+/* Test of locking, to see if locks count as writes. (They should.)
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <tss/tcs.h>
+
+#include "tlcl.h"
+
+#define INDEX0 0xda70
+
+
+int main(void) {
+ TlclLibinit();
+
+ TlclStartup();
+ TlclSelftestfull();
+
+ TlclAssertPhysicalPresence();
+
+ TlclWriteLock(INDEX0);
+
+ printf("Locked 0x%x\n", INDEX0);
+ exit(0);
+}
diff --git a/src/testsuite/writelimit.c b/src/testsuite/writelimit.c
new file mode 100644
index 0000000..b2a251a
--- /dev/null
+++ b/src/testsuite/writelimit.c
@@ -0,0 +1,60 @@
+/* Copyright (c) 2010 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.
+ */
+
+/* Test of recovery when we hit the NVRAM write limit for an unowned TPM.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <tss/tcs.h>
+
+#include "tlcl.h"
+
+#define INDEX0 0xda70
+#define TPM_MAX_NV_WRITES_NOOWNER 64
+
+int main(void) {
+ int i;
+ uint32_t result;
+ uint8_t disable, deactivated; /* the TPM specs use these exact names */
+
+ TlclLibinit();
+
+ TlclStartup();
+ TlclSelftestfull();
+
+ TlclAssertPhysicalPresence();
+
+ result = TlclGetFlags(&disable, &deactivated);
+ printf("disable is %d, deactivated is %d\n", disable, deactivated);
+
+ if (disable || deactivated) {
+ TlclPhysicalEnable();
+ (void) TlclPhysicalSetDeactivated(0);
+ printf("TPM will be active after next reboot\n");
+ exit(0);
+ }
+
+ for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
+ printf("writing %d\n", i);
+ if ((result = TlclWrite(INDEX0, (uint8_t*)&i, sizeof(i))) != TPM_SUCCESS) {
+ switch (result) {
+ case TPM_E_MAXNVWRITES:
+ printf("Max NV writes exceeded - forcing clear\n");
+ TlclForceClear();
+ printf("Please reboot and run this program again\n");
+ exit(0);
+ default:
+ error("unexpected error code %d (0x%x)\n");
+ }
+ }
+ }
+
+ /* Done for now.
+ */
+ printf("Test completed successfully\n");
+ exit(0);
+}
diff --git a/src/tlcl/generator.c b/src/tlcl/generator.c
index 1e48481..a1bc46b 100644
--- a/src/tlcl/generator.c
+++ b/src/tlcl/generator.c
@@ -204,6 +204,47 @@
return cmd;
}
+Command* BuildForceClearCommand(void) {
+ int size = kTpmRequestHeaderLength;
+ Command* cmd = newCommand(TPM_ORD_ForceClear, size);
+ cmd->name = "tpm_forceclear_cmd";
+ return cmd;
+}
+
+Command* BuildPhysicalEnableCommand(void) {
+ int size = kTpmRequestHeaderLength;
+ Command* cmd = newCommand(TPM_ORD_PhysicalEnable, size);
+ cmd->name = "tpm_physicalenable_cmd";
+ return cmd;
+}
+
+Command* BuildPhysicalSetDeactivatedCommand(void) {
+ int size = kTpmRequestHeaderLength + sizeof(uint8_t);
+ Command* cmd = newCommand(TPM_ORD_PhysicalSetDeactivated, size);
+ cmd->name = "tpm_physicalsetdeactivated_cmd";
+ AddVisibleField(cmd, "deactivated", kTpmRequestHeaderLength);
+ return cmd;
+}
+
+Command* BuildGetCapabilityCommand(void) {
+ int size = (kTpmRequestHeaderLength +
+ sizeof(TPM_CAPABILITY_AREA) + /* capArea */
+ sizeof(uint32_t) + /* subCapSize */
+ sizeof(uint32_t)); /* subCap */
+
+ Command* cmd = newCommand(TPM_ORD_GetCapability, size);
+ cmd->name = "tpm_getcapability_cmd";
+ AddInitializedField(cmd, kTpmRequestHeaderLength,
+ sizeof(TPM_CAPABILITY_AREA), TPM_CAP_FLAG);
+ AddInitializedField(cmd, kTpmRequestHeaderLength +
+ sizeof(TPM_CAPABILITY_AREA),
+ sizeof(uint32_t), sizeof(uint32_t));
+ AddInitializedField(cmd, kTpmRequestHeaderLength +
+ sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t),
+ sizeof(uint32_t), TPM_CAP_FLAG_PERMANENT);
+ return cmd;
+}
+
/* Output the fields of a structure.
*/
void OutputFields(Field* fld) {
@@ -307,6 +348,10 @@
BuildStartupCommand,
BuildSelftestfullCommand,
BuildReadPubekCommand,
+ BuildForceClearCommand,
+ BuildPhysicalEnableCommand,
+ BuildPhysicalSetDeactivatedCommand,
+ BuildGetCapabilityCommand,
};
static void FreeFields(Field* fld) {
diff --git a/src/tlcl/tlcl.c b/src/tlcl/tlcl.c
index 22d3613..7dc800b 100644
--- a/src/tlcl/tlcl.c
+++ b/src/tlcl/tlcl.c
@@ -150,9 +150,11 @@
printf("response (%d bytes): ", y);
PrintBytes(response, 10);
PrintBytes(response + 10, y - 10);
+#if !USE_TPM_EMULATOR
printf("execution time: %dms\n",
(int) ((after.tv_sec - before.tv_sec) * 1000 +
(after.tv_usec - before.tv_usec) / 1000));
+#endif
}
/* sanity checks */
@@ -273,3 +275,48 @@
result = TpmReturnCode(response);
return (result != TPM_SUCCESS);
}
+
+void TlclForceClear(void) {
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
+ uint32_t result;
+ SendReceive(tpm_forceclear_cmd.buffer, response, sizeof(response));
+ result = TpmReturnCode(response);
+ if (result != TPM_SUCCESS) {
+ warning("ForceClear failed with code %d (0x%x)\n", result, result);
+ }
+}
+
+void TlclPhysicalEnable(void) {
+ Send(tpm_physicalenable_cmd.buffer);
+}
+
+int TlclPhysicalSetDeactivated(uint8_t flag) {
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
+ uint32_t result;
+ *((uint8_t*)tpm_physicalsetdeactivated_cmd.deactivated) = flag;
+ SendReceive(tpm_physicalsetdeactivated_cmd.buffer,
+ response, sizeof(response));
+ result = TpmReturnCode(response);
+ return result;
+}
+
+int TlclGetFlags(uint8_t* disable, uint8_t* deactivated) {
+
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
+ TPM_PERMANENT_FLAGS* pflags;
+ uint32_t result;
+ uint32_t size;
+
+ SendReceive(tpm_getcapability_cmd.buffer, response, sizeof(response));
+ result = TpmReturnCode(response);
+ if (result != TPM_SUCCESS) {
+ return result;
+ }
+ FromTpmUint32(response + kTpmResponseHeaderLength, &size);
+ assert(size == sizeof(TPM_PERMANENT_FLAGS));
+ pflags =
+ (TPM_PERMANENT_FLAGS*) (response + kTpmResponseHeaderLength + sizeof(size));
+ *disable = pflags->disable;
+ *deactivated = pflags->deactivated;
+ return result;
+}