diff options
author | Randall Spangler <rspangler@chromium.org> | 2010-07-14 09:10:23 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2010-07-14 09:10:23 -0700 |
commit | 39f66114c03639715cb88774255f066a2d942557 (patch) | |
tree | 35d7d984412a124d252ad399c2b5e87b6e92ebfd /firmware | |
parent | 64aec24de8ac23707b97a8d8505b559dc2b204f1 (diff) | |
download | vboot-39f66114c03639715cb88774255f066a2d942557.tar.gz |
Add tpm lite to vboot reference
Review URL: http://codereview.chromium.org/2919010
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/Makefile | 12 | ||||
-rw-r--r-- | firmware/include/sysincludes.h | 8 | ||||
-rw-r--r-- | firmware/lib/rollback_index.c | 46 | ||||
-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.h | 61 | ||||
-rw-r--r-- | firmware/lib/tpm_lite/include/tlcl_structures.h | 96 | ||||
-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.c | 241 | ||||
-rw-r--r-- | firmware/linktest/main.c | 1 | ||||
-rw-r--r-- | firmware/stub/include/biosincludes.h | 3 | ||||
-rw-r--r-- | firmware/stub/include/tpmextras.h | 30 | ||||
-rw-r--r-- | firmware/stub/tlcl.c | 44 | ||||
-rw-r--r-- | firmware/stub/tpm_lite_stub.c | 178 | ||||
-rw-r--r-- | firmware/version.c | 2 |
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"; |