summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2010-07-14 09:10:23 -0700
committerRandall Spangler <rspangler@chromium.org>2010-07-14 09:10:23 -0700
commit39f66114c03639715cb88774255f066a2d942557 (patch)
tree35d7d984412a124d252ad399c2b5e87b6e92ebfd /firmware
parent64aec24de8ac23707b97a8d8505b559dc2b204f1 (diff)
downloadvboot-39f66114c03639715cb88774255f066a2d942557.tar.gz
Add tpm lite to vboot reference
Review URL: http://codereview.chromium.org/2919010
Diffstat (limited to 'firmware')
-rw-r--r--firmware/Makefile12
-rw-r--r--firmware/include/sysincludes.h8
-rw-r--r--firmware/lib/rollback_index.c46
-rw-r--r--firmware/lib/tpm_lite/include/tlcl.h (renamed from firmware/include/tlcl.h)56
-rw-r--r--firmware/lib/tpm_lite/include/tlcl_internal.h61
-rw-r--r--firmware/lib/tpm_lite/include/tlcl_structures.h96
-rw-r--r--firmware/lib/tpm_lite/include/tss_constants.h (renamed from firmware/lib/include/tss_constants.h)9
-rw-r--r--firmware/lib/tpm_lite/tlcl.c241
-rw-r--r--firmware/linktest/main.c1
-rw-r--r--firmware/stub/include/biosincludes.h3
-rw-r--r--firmware/stub/include/tpmextras.h30
-rw-r--r--firmware/stub/tlcl.c44
-rw-r--r--firmware/stub/tpm_lite_stub.c178
-rw-r--r--firmware/version.c2
14 files changed, 708 insertions, 79 deletions
diff --git a/firmware/Makefile b/firmware/Makefile
index 38eb24f8..67ed1565 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -7,15 +7,20 @@ LIBDIR = $(FWTOP)/lib
STUBDIR = $(FWTOP)/stub
TESTDIR = $(FWTOP)/linktest
BUILD_ROOT := ${BUILD}/$(shell basename ${FWTOP})
+LIBS = $(FWLIB) # Firmware library must be self-contained
+
+# Disable rollback TPM when compiling locally, since otherwise
+# load_kernel_test attempts to talk to the TPM.
+CFLAGS += -DDISABLE_ROLLBACK_TPM
INCLUDES = \
-I$(FWTOP)/include \
-I$(LIBDIR)/include \
-I$(LIBDIR)/cgptlib/include \
-I$(LIBDIR)/cryptolib/include \
+ -I$(LIBDIR)/tpm_lite/include \
-I$(STUBDIR)/include
-
# find ./lib -iname '*.c' | sort
LIB_SRCS = \
./lib/cgptlib/cgptlib.c \
@@ -29,6 +34,7 @@ LIB_SRCS = \
./lib/cryptolib/sha_utility.c \
./lib/rollback_index.c \
./lib/stateful_util.c \
+ ./lib/tpm_lite/tlcl.c \
./lib/vboot_common.c \
./lib/vboot_firmware.c \
./lib/vboot_kernel.c
@@ -36,14 +42,14 @@ LIB_SRCS = \
STUB_SRCS = \
./stub/boot_device_stub.c \
./stub/load_firmware_stub.c \
- ./stub/tlcl.c \
+ ./stub/tpm_lite_stub.c \
./stub/utility_stub.c
ALL_SRCS = ${LIB_SRCS} ${STUB_SRCS} version.c
test : $(FWLIB) update-version
$(CC) $(CFLAGS) $(INCLUDES) -o $(BUILD_ROOT)/a.out \
- $(TESTDIR)/main.c $(FWLIB)
+ $(TESTDIR)/main.c $(LIBS)
# This is executed at every make, to see if anything has changed
update-version :
diff --git a/firmware/include/sysincludes.h b/firmware/include/sysincludes.h
index ff24e4c3..1560291e 100644
--- a/firmware/include/sysincludes.h
+++ b/firmware/include/sysincludes.h
@@ -26,6 +26,14 @@
#include <memory.h>
#endif
+#define POSSIBLY_UNUSED __attribute__((unused))
+
+#ifdef __STRICT_ANSI__
+#define INLINE
+#else
+#define INLINE inline
+#endif
+
#else
#include "biosincludes.h"
#endif
diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c
index 4a02782b..5cbb8378 100644
--- a/firmware/lib/rollback_index.c
+++ b/firmware/lib/rollback_index.c
@@ -245,8 +245,7 @@ static uint32_t CheckDeveloperModeTransition(uint32_t current_developer) {
* to the TPM flashram at every reboot or wake-up, because of concerns about
* the durability of the NVRAM.
*/
-static uint32_t SetupTPM(int recovery_mode,
- int developer_mode) {
+uint32_t SetupTPM(int recovery_mode, int developer_mode) {
uint8_t disable;
uint8_t deactivated;
uint32_t result;
@@ -290,6 +289,47 @@ static uint32_t SetupTPM(int recovery_mode,
/* disable MSVC warnings on unused arguments */
__pragma(warning (disable: 4100))
+
+#ifdef DISABLE_ROLLBACK_TPM
+
+/* Dummy implementations which don't call into the tpm_lite library */
+
+uint32_t RollbackFirmwareSetup(int developer_mode) {
+ return TPM_SUCCESS;
+}
+
+uint32_t RollbackFirmwareRead(uint16_t* key_version, uint16_t* version) {
+ *key_version = *version = 0;
+ return TPM_SUCCESS;
+}
+
+uint32_t RollbackFirmwareWrite(uint16_t key_version, uint16_t version) {
+ return TPM_SUCCESS;
+}
+
+uint32_t RollbackFirmwareLock(void) {
+ return TPM_SUCCESS;
+}
+
+uint32_t RollbackKernelRecovery(int developer_mode) {
+ return TPM_SUCCESS;
+}
+
+uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version) {
+ *key_version = *version = 0;
+ return TPM_SUCCESS;
+}
+
+uint32_t RollbackKernelWrite(uint16_t key_version, uint16_t version) {
+ return TPM_SUCCESS;
+}
+
+uint32_t RollbackKernelLock(void) {
+ return TPM_SUCCESS;
+}
+
+#else
+
uint32_t RollbackFirmwareSetup(int developer_mode) {
return SetupTPM(0, developer_mode);
}
@@ -365,3 +405,5 @@ uint32_t RollbackKernelLock(void) {
return TPM_SUCCESS;
}
}
+
+#endif // DISABLE_ROLLBACK_TPM
diff --git a/firmware/include/tlcl.h b/firmware/lib/tpm_lite/include/tlcl.h
index 5bdbaa38..5dfd7ef7 100644
--- a/firmware/include/tlcl.h
+++ b/firmware/lib/tpm_lite/include/tlcl.h
@@ -8,27 +8,16 @@
* A low-level library for interfacing to TPM hardware or an emulator.
*/
-/* FIXME(gauravsh):
- * NOTE: This file is copied over from
- * src/platform/tpm_lite/src/tlcl/tlcl.h
- * Ideally, we want to directly include it without having two maintain
- * duplicate copies in sync. But in the current model, this is hard
- * to do without breaking standalone compilation.
- * Eventually tpm_lite should be moved into vboot_reference.
- *
- * FURTHER NOTE: The subset of TPM error codes relevant to verified boot
- * (TPM_SUCCESS, etc.) are in tss_constants.h. A full list of TPM error codes
- * are in /usr/include/tss/tpm_error.h, from the trousers package.
- */
-
#ifndef TPM_LITE_TLCL_H_
#define TPM_LITE_TLCL_H_
#include "sysincludes.h"
-/* Call this first.
- */
-void TlclLibInit(void);
+/*****************************************************************************/
+/* Functions to be implemented by the stub library */
+
+/* Initialize the stub library */
+void TlclStubInit(void);
/* Close and open the device. This is needed for running more complex commands
* at user level, such as TPM_TakeOwnership, since the TPM device can be opened
@@ -37,9 +26,27 @@ void TlclLibInit(void);
void TlclCloseDevice(void);
void TlclOpenDevice(void);
-/* Sends a TPM_Startup(ST_CLEAR). Note that this is a no-op for the emulator,
- * because it runs this command during initialization. The TPM error code is
- * returned (0 for success).
+void TlclStubSendReceive(uint8_t* request, int request_length,
+ uint8_t* response, int max_length);
+
+/*****************************************************************************/
+/* Functions implemented in tlcl.c */
+
+/* Call this first.
+ */
+void TlclLibInit(void);
+
+
+/* Logs to stdout. Arguments like printf.
+ */
+void TlclLog(char* format, ...);
+
+/* Sets the log level. 0 is quietest.
+ */
+void TlclSetLogLevel(int level);
+
+/* Sends a TPM_Startup(ST_CLEAR). The TPM error code is returned (0
+ * for success).
*/
uint32_t TlclStartup(void);
@@ -48,7 +55,7 @@ uint32_t TlclStartup(void);
*/
uint32_t TlclSelftestfull(void);
-/* Runs the self test in the background. The TPM error code is returned.
+/* Runs the self test in the background.
*/
uint32_t TlclContinueSelfTest(void);
@@ -57,6 +64,11 @@ uint32_t TlclContinueSelfTest(void);
*/
uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size);
+/* Defines a space with permission [perm]. [index] is the index for the space,
+ * [size] the usable data size. Returns the TPM error code.
+ */
+uint32_t TlclDefineSpaceResult(uint32_t index, uint32_t perm, uint32_t size);
+
/* Writes [length] bytes of [data] to space at [index]. The TPM error code is
* returned.
*/
@@ -118,6 +130,10 @@ uint32_t TlclGetFlags(uint8_t* disable, uint8_t* deactivated);
*/
uint32_t TlclSetGlobalLock(void);
+/* Performs a TPM_Extend.
+ */
+uint32_t TlclExtend(int pcr_num, uint8_t* in_digest, uint8_t* out_digest);
+
/* Gets the permission bits for the NVRAM space with |index|.
*/
uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions);
diff --git a/firmware/lib/tpm_lite/include/tlcl_internal.h b/firmware/lib/tpm_lite/include/tlcl_internal.h
new file mode 100644
index 00000000..91d3ee15
--- /dev/null
+++ b/firmware/lib/tpm_lite/include/tlcl_internal.h
@@ -0,0 +1,61 @@
+/* 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.
+ */
+
+#ifndef TPM_LITE_TLCL_INTERNAL_H_
+#define TPM_LITE_TLCL_INTERNAL_H_
+
+/*
+ * These numbers derive from adding the sizes of command fields as shown in the
+ * TPM commands manual.
+ */
+#define kTpmRequestHeaderLength 10
+#define kTpmResponseHeaderLength 10
+#define kTpmReadInfoLength 12
+#define kEncAuthLength 20
+#define kPcrDigestLength 20
+
+
+/*
+ * Conversion functions. ToTpmTYPE puts a value of type TYPE into a TPM
+ * command buffer. FromTpmTYPE gets a value of type TYPE from a TPM command
+ * buffer into a variable.
+ */
+POSSIBLY_UNUSED
+static INLINE void ToTpmUint32(uint8_t *buffer, uint32_t x) {
+ buffer[0] = (uint8_t)(x >> 24);
+ buffer[1] = (uint8_t)((x >> 16) & 0xff);
+ buffer[2] = (uint8_t)((x >> 8) & 0xff);
+ buffer[3] = (uint8_t)(x & 0xff);
+}
+
+/*
+ * See comment for above function.
+ */
+POSSIBLY_UNUSED
+static INLINE void FromTpmUint32(const uint8_t *buffer, uint32_t *x) {
+ *x = ((buffer[0] << 24) |
+ (buffer[1] << 16) |
+ (buffer[2] << 8) |
+ buffer[3]);
+}
+
+/*
+ * See comment for above function.
+ */
+POSSIBLY_UNUSED
+static INLINE void ToTpmUint16(uint8_t *buffer, uint16_t x) {
+ buffer[0] = (uint8_t)(x >> 8);
+ buffer[1] = (uint8_t)(x & 0xff);
+}
+
+/*
+ * See comment for above function.
+ */
+POSSIBLY_UNUSED
+static INLINE void FromTpmUint16(const uint8_t *buffer, uint16_t *x) {
+ *x = (buffer[0] << 8) | buffer[1];
+}
+
+#endif /* TPM_LITE_TLCL_INTERNAL_H_ */
diff --git a/firmware/lib/tpm_lite/include/tlcl_structures.h b/firmware/lib/tpm_lite/include/tlcl_structures.h
new file mode 100644
index 00000000..85754bb2
--- /dev/null
+++ b/firmware/lib/tpm_lite/include/tlcl_structures.h
@@ -0,0 +1,96 @@
+/* This file is automatically generated */
+
+struct {
+ uint8_t buffer[34];
+ uint8_t* pcrNum;
+ uint8_t* inDigest;
+} tpm_extend_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14, },
+tpm_extend_cmd.buffer + 10, tpm_extend_cmd.buffer + 14, };
+
+struct {
+ uint8_t buffer[22];
+ uint8_t* index;
+} tpm_getpermissions_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x4, },
+tpm_getpermissions_cmd.buffer + 18, };
+
+struct {
+ uint8_t buffer[22];
+} tpm_getflags_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x8, },
+};
+
+struct {
+ uint8_t buffer[11];
+ uint8_t* deactivated;
+} tpm_physicalsetdeactivated_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72, },
+tpm_physicalsetdeactivated_cmd.buffer + 10, };
+
+struct {
+ uint8_t buffer[10];
+} tpm_physicalenable_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f, },
+};
+
+struct {
+ uint8_t buffer[10];
+} tpm_physicaldisable_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70, },
+};
+
+struct {
+ uint8_t buffer[10];
+} tpm_forceclear_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d, },
+};
+
+struct {
+ uint8_t buffer[30];
+} tpm_readpubek_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c, },
+};
+
+struct {
+ uint8_t buffer[10];
+} tpm_continueselftest_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53, },
+};
+
+struct {
+ uint8_t buffer[10];
+} tpm_selftestfull_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, },
+};
+
+struct {
+ uint8_t buffer[12];
+} tpm_startup_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1, },
+};
+
+struct {
+ uint8_t buffer[12];
+} tpm_pplock_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x4, },
+};
+
+struct {
+ uint8_t buffer[12];
+} tpm_ppassert_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x8, },
+};
+
+struct {
+ uint8_t buffer[22];
+ uint8_t* index;
+ uint8_t* length;
+} tpm_nv_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf, },
+tpm_nv_read_cmd.buffer + 10, tpm_nv_read_cmd.buffer + 18, };
+
+struct {
+ uint8_t buffer[256];
+ uint8_t* index;
+ uint8_t* length;
+ uint8_t* data;
+} tpm_nv_write_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, },
+tpm_nv_write_cmd.buffer + 10, tpm_nv_write_cmd.buffer + 18, tpm_nv_write_cmd.buffer + 22, };
+
+struct {
+ uint8_t buffer[101];
+ uint8_t* index;
+ uint8_t* perm;
+ uint8_t* size;
+} tpm_nv_definespace_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0xcc, 0x0, 0x18, 0, 0, 0, 0, 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x17, },
+tpm_nv_definespace_cmd.buffer + 12, tpm_nv_definespace_cmd.buffer + 70, tpm_nv_definespace_cmd.buffer + 77, };
+
+const int kWriteInfoLength = 12;
+const int kNvDataPublicPermissionsOffset = 60;
diff --git a/firmware/lib/include/tss_constants.h b/firmware/lib/tpm_lite/include/tss_constants.h
index b035ebdc..aaeacbea 100644
--- a/firmware/lib/include/tss_constants.h
+++ b/firmware/lib/tpm_lite/include/tss_constants.h
@@ -6,15 +6,6 @@
* the firmware
*/
-/* FIXME(gauravsh):
- * NOTE: This file is copied over from
- * src/platform/tpm_lite/src/tlcl/tss_constants.h
- * Ideally, we want to directly include it without having two maintain
- * duplicate copies in sync. But in the current model, this is hard
- * to do without breaking standalone compilation.
- * Eventually tpm_lite should be moved into vboot_reference.
- */
-
#ifndef TPM_LITE_TSS_CONSTANTS_H_
#define TPM_LITE_TSS_CONSTANTS_H_
diff --git a/firmware/lib/tpm_lite/tlcl.c b/firmware/lib/tpm_lite/tlcl.c
new file mode 100644
index 00000000..4ca8b87e
--- /dev/null
+++ b/firmware/lib/tpm_lite/tlcl.c
@@ -0,0 +1,241 @@
+/* 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.
+ */
+
+/* A lightweight TPM command library.
+ *
+ * The general idea is that TPM commands are array of bytes whose
+ * fields are mostly compile-time constant. The goal is to build much
+ * of the commands at compile time (or build time) and change some of
+ * the fields at run time as needed. The code in
+ * utility/tlcl_generator.c builds structures containing the commands,
+ * as well as the offsets of the fields that need to be set at run
+ * time.
+ */
+
+#include "sysincludes.h"
+#include "tlcl.h"
+#include "tlcl_internal.h"
+#include "tlcl_structures.h"
+#include "tss_constants.h"
+#include "utility.h"
+
+
+/* Sets the size field of a TPM command. */
+static INLINE void SetTpmCommandSize(uint8_t* buffer, uint32_t size) {
+ ToTpmUint32(buffer + sizeof(uint16_t), size);
+}
+
+/* Gets the size field of a TPM command. */
+POSSIBLY_UNUSED static INLINE int TpmCommandSize(const uint8_t* buffer) {
+ uint32_t size;
+ FromTpmUint32(buffer + sizeof(uint16_t), &size);
+ return (int) size;
+}
+
+/* Gets the code field of a TPM command. */
+static INLINE int TpmCommandCode(const uint8_t* buffer) {
+ uint32_t code;
+ FromTpmUint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code);
+ return code;
+}
+
+/* Gets the return code field of a TPM result. */
+static INLINE int TpmReturnCode(const uint8_t* buffer) {
+ return TpmCommandCode(buffer);
+}
+
+/* Checks for errors in a TPM response. */
+static void CheckResult(uint8_t* request, uint8_t* response, int warn_only) {
+ int command = TpmCommandCode(request);
+ int result = TpmReturnCode(response);
+ if (result != TPM_SUCCESS) {
+ if (warn_only)
+ VBDEBUG(("TPM command %d 0x%x failed: %d 0x%x\n",
+ command, command, result, result));
+ else
+ error("TPM command %d 0x%x failed: %d 0x%x\n",
+ command, command, result, result);
+ }
+}
+
+/* Sends a TPM command and gets a response. */
+static void TlclSendReceive(uint8_t* request, uint8_t* response,
+ int max_length) {
+ TlclStubSendReceive(request, TpmCommandSize(request),
+ response, max_length);
+}
+
+
+/* Sends a command and returns the error code. */
+static uint32_t Send(uint8_t* command) {
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
+ TlclSendReceive(command, response, sizeof(response));
+ return TpmReturnCode(response);
+}
+
+/* Exported functions. */
+
+void TlclLibInit(void) {
+ TlclStubInit();
+}
+
+uint32_t TlclStartup(void) {
+ return Send(tpm_startup_cmd.buffer);
+}
+
+uint32_t TlclSelftestfull(void) {
+ return Send(tpm_selftestfull_cmd.buffer);
+}
+
+uint32_t TlclContinueSelfTest(void) {
+ return Send(tpm_continueselftest_cmd.buffer);
+}
+
+uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) {
+ ToTpmUint32(tpm_nv_definespace_cmd.index, index);
+ ToTpmUint32(tpm_nv_definespace_cmd.perm, perm);
+ ToTpmUint32(tpm_nv_definespace_cmd.size, size);
+ return Send(tpm_nv_definespace_cmd.buffer);
+}
+
+uint32_t TlclWrite(uint32_t index, uint8_t* data, uint32_t length) {
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
+ const int total_length =
+ kTpmRequestHeaderLength + kWriteInfoLength + length;
+
+ assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE);
+ SetTpmCommandSize(tpm_nv_write_cmd.buffer, total_length);
+
+ ToTpmUint32(tpm_nv_write_cmd.index, index);
+ ToTpmUint32(tpm_nv_write_cmd.length, length);
+ Memcpy(tpm_nv_write_cmd.data, data, length);
+
+ TlclSendReceive(tpm_nv_write_cmd.buffer, response, sizeof(response));
+ CheckResult(tpm_nv_write_cmd.buffer, response, 1);
+
+ return TpmReturnCode(response);
+}
+
+uint32_t TlclRead(uint32_t index, uint8_t* data, uint32_t length) {
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
+ uint32_t result_length;
+ uint32_t result;
+
+ ToTpmUint32(tpm_nv_read_cmd.index, index);
+ ToTpmUint32(tpm_nv_read_cmd.length, length);
+
+ TlclSendReceive(tpm_nv_read_cmd.buffer, response, sizeof(response));
+ result = TpmReturnCode(response);
+ if (result == TPM_SUCCESS && length > 0) {
+ uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength;
+ FromTpmUint32(nv_read_cursor, &result_length);
+ nv_read_cursor += sizeof(uint32_t);
+ Memcpy(data, nv_read_cursor, result_length);
+ }
+
+ return result;
+}
+
+uint32_t TlclWriteLock(uint32_t index) {
+ return TlclWrite(index, NULL, 0);
+}
+
+uint32_t TlclReadLock(uint32_t index) {
+ return TlclRead(index, NULL, 0);
+}
+
+uint32_t TlclAssertPhysicalPresence(void) {
+ return Send(tpm_ppassert_cmd.buffer);
+}
+
+uint32_t TlclAssertPhysicalPresenceResult(void) {
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
+ TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response));
+ return TpmReturnCode(response);
+}
+
+uint32_t TlclLockPhysicalPresence(void) {
+ return Send(tpm_pplock_cmd.buffer);
+}
+
+uint32_t TlclSetNvLocked(void) {
+ return TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0);
+}
+
+int TlclIsOwned(void) {
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE];
+ uint32_t result;
+ TlclSendReceive(tpm_readpubek_cmd.buffer, response, sizeof(response));
+ result = TpmReturnCode(response);
+ return (result != TPM_SUCCESS);
+}
+
+uint32_t TlclForceClear(void) {
+ return Send(tpm_forceclear_cmd.buffer);
+}
+
+uint32_t TlclSetEnable(void) {
+ return Send(tpm_physicalenable_cmd.buffer);
+}
+
+uint32_t TlclClearEnable(void) {
+ return Send(tpm_physicaldisable_cmd.buffer);
+}
+
+uint32_t TlclSetDeactivated(uint8_t flag) {
+ *((uint8_t*)tpm_physicalsetdeactivated_cmd.deactivated) = flag;
+ return Send(tpm_physicalsetdeactivated_cmd.buffer);
+}
+
+uint32_t 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;
+
+ TlclSendReceive(tpm_getflags_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;
+}
+
+uint32_t TlclSetGlobalLock(void) {
+ uint32_t x;
+ return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0);
+}
+
+uint32_t TlclExtend(int pcr_num, uint8_t* in_digest, uint8_t* out_digest) {
+ uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength];
+ ToTpmUint32(tpm_extend_cmd.pcrNum, pcr_num);
+ Memcpy(tpm_extend_cmd.inDigest, in_digest, kPcrDigestLength);
+ TlclSendReceive(tpm_extend_cmd.buffer, response, sizeof(response));
+ Memcpy(out_digest, response + kTpmResponseHeaderLength, kPcrDigestLength);
+ return TpmReturnCode(response);
+}
+
+uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) {
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
+ uint8_t* nvdata;
+ uint32_t result;
+ uint32_t size;
+
+ ToTpmUint32(tpm_getpermissions_cmd.index, index);
+ TlclSendReceive(tpm_getpermissions_cmd.buffer, response, sizeof(response));
+ result = TpmReturnCode(response);
+ if (result != TPM_SUCCESS) {
+ return result;
+ }
+ nvdata = response + kTpmResponseHeaderLength + sizeof(size);
+ FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions);
+ return result;
+}
diff --git a/firmware/linktest/main.c b/firmware/linktest/main.c
index 5e900a96..e726db32 100644
--- a/firmware/linktest/main.c
+++ b/firmware/linktest/main.c
@@ -7,6 +7,7 @@
#include "vboot_common.h"
#include "vboot_kernel.h"
+
int main(void)
{
uint16_t x, y;
diff --git a/firmware/stub/include/biosincludes.h b/firmware/stub/include/biosincludes.h
index ac0159d8..fe49d24b 100644
--- a/firmware/stub/include/biosincludes.h
+++ b/firmware/stub/include/biosincludes.h
@@ -29,6 +29,9 @@ typedef unsigned size_t;
#define PRIu64 "%ll"
extern void debug(const char *format, ...);
+#define POSSIBLY_UNUSED
+#define INLINE
+
#endif
#endif /*CHROMEOS_SRC_PLATFORM_VBOOT_REFERENCE_FIRMWARE_STUB_BIOSINCLUDES_H_*/
diff --git a/firmware/stub/include/tpmextras.h b/firmware/stub/include/tpmextras.h
new file mode 100644
index 00000000..abd58377
--- /dev/null
+++ b/firmware/stub/include/tpmextras.h
@@ -0,0 +1,30 @@
+/* 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.
+ */
+
+/*
+ * TPM definitions not available in any TSS include file :-(
+ */
+
+#ifndef TPM_LITE_TPMEXTRAS_H_
+#define TPM_LITE_TPMEXTRAS_H_
+
+#include <tss/tcs.h>
+
+#define TPM_MAX_COMMAND_SIZE 4096
+#define TPM_LARGE_ENOUGH_COMMAND_SIZE 256 /* saves space in the firmware */
+
+typedef struct tdTPM_WRITE_INFO {
+ uint32_t nvIndex;
+ uint32_t offset;
+ uint32_t dataSize;
+} TPM_WRITE_INFO;
+
+#define TPM_ALL_LOCALITIES (TPM_LOC_ZERO | TPM_LOC_ONE | TPM_LOC_TWO \
+ | TPM_LOC_THREE | TPM_LOC_FOUR) /* 0x1f */
+
+#define TPM_ENCAUTH_SIZE 20
+#define TPM_PUBEK_SIZE 256
+
+#endif
diff --git a/firmware/stub/tlcl.c b/firmware/stub/tlcl.c
deleted file mode 100644
index 1a44ea1c..00000000
--- a/firmware/stub/tlcl.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* 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.
- *
- * Stub implementations of TPM Lite Library.
- */
-
-#include "tss_constants.h"
-
-/* disable MSVC warnings on unused arguments */
-__pragma(warning (disable: 4100))
-
-void TlclLibInit(void) { return; }
-void TlclCloseDevice(void) { return; }
-void TlclOpenDevice(void) { return; }
-uint32_t TlclStartup(void) { return TPM_SUCCESS; }
-uint32_t TlclSelftestfull(void) { return TPM_SUCCESS; }
-uint32_t TlclContinueSelfTest(void) { return TPM_SUCCESS; }
-uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) {
- return TPM_SUCCESS;
-}
-uint32_t TlclWrite(uint32_t index, uint8_t *data, uint32_t length) {
- return TPM_SUCCESS;
-}
-uint32_t TlclRead(uint32_t index, uint8_t *data, uint32_t length) {
- return TPM_SUCCESS;
-}
-uint32_t TlclWriteLock(uint32_t index) { return TPM_SUCCESS; }
-uint32_t TlclReadLock(uint32_t index) { return TPM_SUCCESS; }
-uint32_t TlclAssertPhysicalPresence(void) { return TPM_SUCCESS; }
-uint32_t TlclLockPhysicalPresence(void) { return TPM_SUCCESS; }
-uint32_t TlclSetNvLocked(void) { return TPM_SUCCESS; }
-int TlclIsOwned(void) { return TPM_SUCCESS; }
-uint32_t TlclForceClear(void) { return TPM_SUCCESS; }
-uint32_t TlclSetEnable(void) { return TPM_SUCCESS; }
-uint32_t TlclClearEnable(void) { return TPM_SUCCESS; }
-uint32_t TlclSetDeactivated(int deactivated) { return TPM_SUCCESS; }
-uint32_t TlclSetGlobalLock(void) { return TPM_SUCCESS; }
-uint32_t TlclGetFlags(uint8_t* disable, uint8_t* deactivated) {
- return TPM_SUCCESS;
-}
-uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) {
- return TPM_SUCCESS;
-}
diff --git a/firmware/stub/tpm_lite_stub.c b/firmware/stub/tpm_lite_stub.c
new file mode 100644
index 00000000..ee1cbf13
--- /dev/null
+++ b/firmware/stub/tpm_lite_stub.c
@@ -0,0 +1,178 @@
+/* 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.
+ *
+ * Stub implementations of utility functions which call their linux-specific
+ * equivalents.
+ */
+
+#define _STUB_IMPLEMENTATION_
+#include "tlcl.h"
+#include "tlcl_internal.h"
+#include "utility.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <tss/tcs.h>
+#include "tpmextras.h"
+#define TPM_DEVICE_PATH "/dev/tpm0"
+
+/* TODO: these functions should pass errors back rather than returning void */
+/* TODO: if the only callers to these are just wrappers, should just
+ * remove the wrappers and call us directly. */
+
+
+/* The file descriptor for the TPM device.
+ */
+static int tpm_fd = -1;
+
+
+/* Print |n| bytes from array |a|, with newlines.
+ */
+POSSIBLY_UNUSED static void PrintBytes(uint8_t* a, int n) {
+ int i;
+ for (i = 0; i < n; i++) {
+ VBDEBUG(("%02x ", a[i]));
+ if ((i + 1) % 16 == 0) {
+ VBDEBUG(("\n"));
+ }
+ }
+ if (i % 16 != 0) {
+ VBDEBUG(("\n"));
+ }
+}
+
+
+/* Executes a command on the TPM.
+ */
+static void TpmExecute(const uint8_t *in, const uint32_t in_len,
+ uint8_t *out, uint32_t *pout_len) {
+ uint8_t response[TPM_MAX_COMMAND_SIZE];
+ if (in_len <= 0) {
+ error("invalid command length %d\n", in_len);
+ } else if (tpm_fd < 0) {
+ error("the TPM device was not opened. Forgot to call TlclLibInit?\n");
+ } else {
+ int n = write(tpm_fd, in, in_len);
+ if (n != in_len) {
+ error("write failure to TPM device: %s\n", strerror(errno));
+ }
+ n = read(tpm_fd, response, sizeof(response));
+ if (n == 0) {
+ error("null read from TPM device\n");
+ } else if (n < 0) {
+ error("read failure from TPM device: %s\n", strerror(errno));
+ } else {
+ if (n > *pout_len) {
+ error("TPM response too long for output buffer\n");
+ } else {
+ *pout_len = n;
+ Memcpy(out, response, n);
+ }
+ }
+ }
+}
+
+
+/* Gets the tag field of a TPM command.
+ */
+POSSIBLY_UNUSED static INLINE int TpmTag(uint8_t* buffer) {
+ uint16_t tag;
+ FromTpmUint16(buffer, &tag);
+ return (int) tag;
+}
+
+
+/* Gets the size field of a TPM command.
+ */
+POSSIBLY_UNUSED static INLINE int TpmResponseSize(const uint8_t* buffer) {
+ uint32_t size;
+ FromTpmUint32(buffer + sizeof(uint16_t), &size);
+ return (int) size;
+}
+
+
+void TlclStubInit(void) {
+ TlclOpenDevice();
+}
+
+
+void TlclCloseDevice(void) {
+ close(tpm_fd);
+ tpm_fd = -1;
+}
+
+
+void TlclOpenDevice(void) {
+ if (tpm_fd >= 0)
+ return; /* Already open */
+
+ tpm_fd = open(TPM_DEVICE_PATH, O_RDWR);
+ if (tpm_fd < 0) {
+ error("cannot open TPM device %s: %s\n", TPM_DEVICE_PATH, strerror(errno));
+ }
+}
+
+
+void TlclStubSendReceive(uint8_t* request, int request_length,
+ uint8_t* response, int max_length) {
+ /*
+ * In a real firmware implementation, this function should contain
+ * the equivalent API call for the firmware TPM driver which takes a
+ * raw sequence of bytes as input command and a pointer to the
+ * output buffer for putting in the results.
+ *
+ * For EFI firmwares, this can make use of the EFI TPM driver as
+ * follows (based on page 16, of TCG EFI Protocol Specs Version 1.20
+ * availaible from the TCG website):
+ *
+ * EFI_STATUS status;
+ * status = TcgProtocol->EFI_TCG_PASS_THROUGH_TO_TPM(TpmCommandSize(request),
+ * request,
+ * max_length,
+ * response);
+ * // Error checking depending on the value of the status above
+ */
+ uint32_t response_length = max_length;
+ int tag, response_tag;
+
+ struct timeval before, after;
+ gettimeofday(&before, NULL);
+ TpmExecute(request, request_length, response, &response_length);
+ gettimeofday(&after, NULL);
+
+#ifdef VBOOT_DEBUG
+ {
+ int x = request_length;
+ int y = response_length;
+ VBDEBUG(("request (%d bytes): ", x));
+ PrintBytes(request, 10);
+ PrintBytes(request + 10, x - 10);
+ VBDEBUG(("response (%d bytes): ", y));
+ PrintBytes(response, 10);
+ PrintBytes(response + 10, y - 10);
+ VBDEBUG(("execution time: %dms\n",
+ (int) ((after.tv_sec - before.tv_sec) * 1000 +
+ (after.tv_usec - before.tv_usec) / 1000)));
+ }
+#endif
+
+ /* sanity checks */
+ tag = TpmTag(request);
+ response_tag = TpmTag(response);
+ assert(
+ (tag == TPM_TAG_RQU_COMMAND &&
+ response_tag == TPM_TAG_RSP_COMMAND) ||
+ (tag == TPM_TAG_RQU_AUTH1_COMMAND &&
+ response_tag == TPM_TAG_RSP_AUTH1_COMMAND) ||
+ (tag == TPM_TAG_RQU_AUTH2_COMMAND &&
+ response_tag == TPM_TAG_RSP_AUTH2_COMMAND));
+ assert(response_length == TpmResponseSize(response));
+}
diff --git a/firmware/version.c b/firmware/version.c
index 2761cd25..d6fde5da 100644
--- a/firmware/version.c
+++ b/firmware/version.c
@@ -1 +1 @@
-char* VbootVersion = "VBOOv=c61037c4";
+char* VbootVersion = "VBOOv=43853f81";