Philipp Deppenwiese (zaolin.daisuki@googlemail.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14135
-gerrit
commit e09664eac833a5ff420af941385f9bf512cddf5b Author: Philipp Deppenwiese zaolin@das-labor.org Date: Mon Mar 14 18:53:09 2016 +0100
util/tss-generator: WIP - Add TSS generator
Change-Id: I93ef112111b403a23c0dce4cf109b9e87424bc1a Signed-off-by: Philipp Deppenwiese zaolin@das-labor.org --- src/include/tpm/tss_constants.h | 174 +++++++++--- util/tss-generator/Makefile | 16 ++ util/tss-generator/Makefile.inc | 19 ++ util/tss-generator/tss-generator.c | 560 +++++++++++++++++++++++++++++++++++++ util/tss-generator/tss_extras.h | 27 ++ util/tss-generator/tss_internal.h | 61 ++++ 6 files changed, 824 insertions(+), 33 deletions(-)
diff --git a/src/include/tpm/tss_constants.h b/src/include/tpm/tss_constants.h index afd2593..2417356 100644 --- a/src/include/tpm/tss_constants.h +++ b/src/include/tpm/tss_constants.h @@ -18,37 +18,40 @@
#define TPM_E_NON_FATAL 0x800
-#define TPM_SUCCESS ((uint32_t)0x00000000) - -#define TPM_E_AREA_LOCKED ((uint32_t)0x0000003c) -#define TPM_E_BADINDEX ((uint32_t)0x00000002) -#define TPM_E_BAD_PRESENCE ((uint32_t)0x0000002d) -#define TPM_E_IOERROR ((uint32_t)0x0000001f) -#define TPM_E_INVALID_POSTINIT ((uint32_t)0x00000026) -#define TPM_E_MAXNVWRITES ((uint32_t)0x00000048) -#define TPM_E_OWNER_SET ((uint32_t)0x00000014) - -#define TPM_E_NEEDS_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 1)) -#define TPM_E_DOING_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 2)) - -#define TPM_E_ALREADY_INITIALIZED ((uint32_t)0x00005000) /* vboot local */ -#define TPM_E_INTERNAL_INCONSISTENCY ((uint32_t)0x00005001) /* vboot local */ -#define TPM_E_MUST_REBOOT ((uint32_t)0x00005002) /* vboot local */ -#define TPM_E_CORRUPTED_STATE ((uint32_t)0x00005003) /* vboot local */ -#define TPM_E_COMMUNICATION_ERROR ((uint32_t)0x00005004) /* vboot local */ -#define TPM_E_RESPONSE_TOO_LARGE ((uint32_t)0x00005005) /* vboot local */ -#define TPM_E_NO_DEVICE ((uint32_t)0x00005006) /* vboot local */ -#define TPM_E_INPUT_TOO_SMALL ((uint32_t)0x00005007) /* vboot local */ -#define TPM_E_WRITE_FAILURE ((uint32_t)0x00005008) /* vboot local */ -#define TPM_E_READ_EMPTY ((uint32_t)0x00005009) /* vboot local */ -#define TPM_E_READ_FAILURE ((uint32_t)0x0000500a) /* vboot local */ - -#define TPM_NV_INDEX0 ((uint32_t)0x00000000) -#define TPM_NV_INDEX_LOCK ((uint32_t)0xffffffff) -#define TPM_NV_PER_GLOBALLOCK (((uint32_t)1)<<15) -#define TPM_NV_PER_PPWRITE (((uint32_t)1)<<0) -#define TPM_NV_PER_READ_STCLEAR (((uint32_t)1)<<31) -#define TPM_NV_PER_WRITE_STCLEAR (((uint32_t)1)<<14) +#define TPM_SUCCESS ((uint32_t) 0x00000000) + +#define TPM_E_AREA_LOCKED ((uint32_t) 0x0000003c) +#define TPM_E_BADINDEX ((uint32_t) 0x00000002) +#define TPM_E_BAD_PRESENCE ((uint32_t) 0x0000002d) +#define TPM_E_IOERROR ((uint32_t) 0x0000001f) +#define TPM_E_INVALID_POSTINIT ((uint32_t) 0x00000026) +#define TPM_E_MAXNVWRITES ((uint32_t) 0x00000048) +#define TPM_E_OWNER_SET ((uint32_t) 0x00000014) + +#define TPM_E_NEEDS_SELFTEST ((uint32_t) (TPM_E_NON_FATAL + 1)) +#define TPM_E_DOING_SELFTEST ((uint32_t) (TPM_E_NON_FATAL + 2)) + +#define TPM_E_ALREADY_INITIALIZED ((uint32_t) 0x00005000) /* vboot local */ +#define TPM_E_INTERNAL_INCONSISTENCY ((uint32_t) 0x00005001) /* vboot local */ +#define TPM_E_MUST_REBOOT ((uint32_t) 0x00005002) /* vboot local */ +#define TPM_E_CORRUPTED_STATE ((uint32_t) 0x00005003) /* vboot local */ +#define TPM_E_COMMUNICATION_ERROR ((uint32_t) 0x00005004) /* vboot local */ +#define TPM_E_RESPONSE_TOO_LARGE ((uint32_t) 0x00005005) /* vboot local */ +#define TPM_E_NO_DEVICE ((uint32_t) 0x00005006) /* vboot local */ +#define TPM_E_INPUT_TOO_SMALL ((uint32_t) 0x00005007) /* vboot local */ +#define TPM_E_WRITE_FAILURE ((uint32_t) 0x00005008) /* vboot local */ +#define TPM_E_READ_EMPTY ((uint32_t) 0x00005009) /* vboot local */ +#define TPM_E_READ_FAILURE ((uint32_t) 0x0000500a) /* vboot local */ + +#define TPM_NV_INDEX0 ((uint32_t) 0x00000000) +#define TPM_NV_INDEX_LOCK ((uint32_t) 0xffffffff) +#define TPM_NV_PER_GLOBALLOCK (((uint32_t) 1) << 15) +#define TPM_NV_PER_PPWRITE (((uint32_t) 1) << 0) +#define TPM_NV_PER_READ_STCLEAR (((uint32_t)1) << 31) +#define TPM_NV_PER_WRITE_STCLEAR (((uint32_t)1) << 14) + +#define TPM_TAG_NV_ATTRIBUTES ((uint16_t) 0x0017) +#define TPM_TAG_NV_DATA_PUBLIC ((uint16_t) 0x0018)
#define TPM_TAG_RQU_COMMAND ((uint16_t) 0xc1) #define TPM_TAG_RQU_AUTH1_COMMAND ((uint16_t) 0xc2) @@ -59,9 +62,75 @@ #define TPM_TAG_RSP_AUTH2_COMMAND ((uint16_t) 0xc6)
typedef uint8_t TSS_BOOL; +typedef uint8_t TPM_BOOL; +typedef uint16_t TPM_TAG; typedef uint16_t TPM_STRUCTURE_TAG; +typedef uint32_t TPM_NV_INDEX; +typedef uint32_t TPM_NV_PER_ATTRIBUTES; +typedef uint8_t TPM_LOCALITY_SELECTION; +typedef uint32_t TPM_COMMAND_CODE; +typedef uint16_t TPM_PHYSICAL_PRESENCE; +typedef uint16_t TPM_STARTUP_TYPE; +typedef uint32_t TPM_CAPABILITY_AREA; + +#define TPM_CAP_FLAG ((uint32_t) 0x00000004) +#define TPM_CAP_FLAG_PERMANENT ((uint32_t) 0x00000108) +#define TPM_CAP_FLAG_VOLATILE ((uint32_t) 0x00000109) + +#define TPM_CAP_PROPERTY ((uint32_t) 0x00000005) +#define TPM_CAP_PROP_OWNER ((uint32_t) 0x00000111) +#define TPM_CAP_NV_INDEX ((uint32_t) 0x00000011) + +#define TPM_ST_CLEAR ((uint16_t) 0x0001) +#define TPM_ST_STATE ((uint16_t) 0x0002) +#define TPM_ST_DEACTIVATED ((uint16_t) 0x0003) + +#define TPM_LOC_FOUR (((uint32_t)1)<<4) +#define TPM_LOC_THREE (((uint32_t)1)<<3) +#define TPM_LOC_TWO (((uint32_t)1)<<2) +#define TPM_LOC_ONE (((uint32_t)1)<<1) +#define TPM_LOC_ZERO (((uint32_t)1)<<0) + +#define TPM_PHYSICAL_PRESENCE_LOCK ((uint16_t) 0x0004) +#define TPM_PHYSICAL_PRESENCE_PRESENT ((uint16_t) 0x0008) +#define TPM_PHYSICAL_PRESENCE_NOTPRESENT ((uint16_t) 0x0010) +#define TPM_PHYSICAL_PRESENCE_CMD_ENABLE ((uint16_t) 0x0020) +#define TPM_PHYSICAL_PRESENCE_HW_ENABLE ((uint16_t) 0x0040) +#define TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK ((uint16_t) 0x0080) +#define TPM_PHYSICAL_PRESENCE_CMD_DISABLE ((uint16_t) 0x0100) +#define TPM_PHYSICAL_PRESENCE_HW_DISABLE ((uint16_t) 0x0200) + +#define TPM_SHA1_160_HASH_LEN 0x14 +#define TPM_SHA1BASED_NONCE_LEN TPM_SHA1_160_HASH_LEN
-typedef struct tdTPM_PERMANENT_FLAGS { +typedef struct tdTPM_DIGEST +{ + uint8_t digest[TPM_SHA1_160_HASH_LEN]; +} TPM_DIGEST; + +typedef TPM_DIGEST TPM_COMPOSITE_HASH; + +typedef struct tdTPM_PCR_SELECTION +{ + uint16_t sizeOfSelect; + uint8_t *pcrSelect; +} TPM_PCR_SELECTION; + +typedef struct tdTPM_NV_ATTRIBUTES +{ + TPM_STRUCTURE_TAG tag; + TPM_NV_PER_ATTRIBUTES attributes; +} TPM_NV_ATTRIBUTES; + +typedef struct tdTPM_PCR_INFO_SHORT +{ + TPM_PCR_SELECTION pcrSelection; + TPM_LOCALITY_SELECTION localityAtRelease; + TPM_COMPOSITE_HASH digestAtRelease; +} TPM_PCR_INFO_SHORT; + +typedef struct tdTPM_PERMANENT_FLAGS +{ TPM_STRUCTURE_TAG tag; TSS_BOOL disable; TSS_BOOL ownership; @@ -94,4 +163,43 @@ typedef struct tdTPM_STCLEAR_FLAGS { TSS_BOOL bGlobalLock; } TPM_STCLEAR_FLAGS;
-#endif /* TPM_TSS_CONSTANTS_H */ +typedef struct tdTPM_NV_DATA_PUBLIC +{ + TPM_STRUCTURE_TAG tag; + TPM_NV_INDEX nvIndex; + TPM_PCR_INFO_SHORT pcrInfoRead; + TPM_PCR_INFO_SHORT pcrInfoWrite; + TPM_NV_ATTRIBUTES permission; + TPM_BOOL bReadSTClear; + TPM_BOOL bWriteSTClear; + TPM_BOOL bWriteDefine; + uint32_t dataSize; +} TPM_NV_DATA_PUBLIC; + +typedef struct tdTPM_NONCE +{ + uint8_t nonce[TPM_SHA1BASED_NONCE_LEN]; +} TPM_NONCE; + +/* Ordinals */ + +#define TPM_ORD_ContinueSelfTest ((uint32_t) 0x00000053) +#define TPM_ORD_Extend ((uint32_t) 0x00000014) +#define TPM_ORD_ForceClear ((uint32_t) 0x0000005D) +#define TPM_ORD_GetCapability ((uint32_t) 0x00000065) +#define TPM_ORD_GetRandom ((uint32_t) 0x00000046) +#define TPM_ORD_NV_DefineSpace ((uint32_t) 0x000000CC) +#define TPM_ORD_NV_ReadValue ((uint32_t) 0x000000CF) +#define TPM_ORD_NV_WriteValue ((uint32_t) 0x000000CD) +#define TPM_ORD_PcrRead ((uint32_t) 0x00000015) +#define TPM_ORD_PhysicalEnable ((uint32_t) 0x0000006F) +#define TPM_ORD_PhysicalDisable ((uint32_t) 0x00000070) +#define TSC_ORD_PhysicalPresence ((uint32_t) 0x4000000A) +#define TPM_ORD_PhysicalSetDeactivated ((uint32_t) 0x00000072) +#define TPM_ORD_ReadPubek ((uint32_t) 0x0000007C) +#define TPM_ORD_SaveState ((uint32_t) 0x00000098) +#define TPM_ORD_SelfTestFull ((uint32_t) 0x00000050) +#define TPM_ORD_Startup ((uint32_t) 0x00000099) + + +#endif /* TPM_TSS_CONSTANTS_H */ diff --git a/util/tss-generator/Makefile b/util/tss-generator/Makefile new file mode 100644 index 0000000..63e3d69 --- /dev/null +++ b/util/tss-generator/Makefile @@ -0,0 +1,16 @@ +top ?= $(abspath ../..) +objutil ?= $(top)/util +arch ?= $(ARCH) + +HOSTCC ?= $(CC) + +.PHONY: all +all: $(objutil)/tss-generator/tss-generator + +.PHONY: clean +clean: + $(RM) $(objutil)/tss-generator/tss-generator $(tssobj) + +.SILENT: + +include Makefile.inc diff --git a/util/tss-generator/Makefile.inc b/util/tss-generator/Makefile.inc new file mode 100644 index 0000000..c3f44e5 --- /dev/null +++ b/util/tss-generator/Makefile.inc @@ -0,0 +1,19 @@ +tssobj := +tssobj += tss-generator.o + +TOOLCFLAGS := -Werror -Wall -Wextra +TOOLCFLAGS += -I$(top)/src/include/tpm +TOOLCFLAGS += -I$(top)/src/commonlib/include +TOOLCFLAGS += -I$(objutil)/tss-generator + +$(objutil)/tss-generator/%.o: $(objutil)/tss-generator/%.c + printf " HOSTCC $(subst $(objutil)/,,$(@))\n" + $(HOSTCC) $(TOOLCFLAGS) $(HOSTCFLAGS) -c -o $@ $< + +$(objutil)/tss-generator/%.o: $(top)/util/tss-generator/%.c + printf " HOSTCC $(subst $(objutil)/,,$(@))\n" + $(HOSTCC) $(TOOLCFLAGS) $(HOSTCFLAGS) -c -o $@ $< + +$(objutil)/tss-generator/tss-generator: $(addprefix $(objutil)/tss-generator/,$(tssobj)) + printf " HOSTCC $(subst $(objutil)/,,$(@)) (link)\n" + $(HOSTCC) -o $@ $(addprefix $(objutil)/tss-generator/,$(tssobj)) diff --git a/util/tss-generator/tss-generator.c b/util/tss-generator/tss-generator.c new file mode 100644 index 0000000..44b7869 --- /dev/null +++ b/util/tss-generator/tss-generator.c @@ -0,0 +1,560 @@ +/* Copyright (c) 2012 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. + */ + +/* This program generates partially filled TPM datagrams and other compile-time + * constants (e.g. structure sizes and offsets). Compile this file---and ONLY + * this file---with -fpack-struct. We take advantage of the fact that the + * (packed) TPM structures layout (mostly) match the TPM request and response + * datagram layout. When they don't completely match, some fixing is necessary + * (see PCR_SELECTION_FIX below). + */ + +#include <assert.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> + +#include <inttypes.h> /* For PRIu64 */ +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> + +#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN) +#include <byteswap.h> +#include <memory.h> +#endif + +#include "tss_internal.h" +#include "tss_extras.h" +#include <tss_constants.h> + +/* See struct Command below. This structure represent a field in a TPM + * command. [name] is the field name. [visible] is 1 if the field is + * modified by the run-time. Non-visible fields are initialized at build time + * and remain constant. [size] is the field size in bytes. [value] is the + * fixed value of non-visible fields. + */ +typedef struct Field { + const char* name; + int visible; + int offset; + int size; + uint32_t value; /* large enough for all initializers */ + struct Field* next; +} Field; + +/* This structure is used to build (at build time) and manipulate (at firmware + * or emulation run time) buffers containing TPM datagrams. [name] is the name + * of a TPM command. [size] is the size of the command buffer in bytes, when + * known. [max_size] is the maximum size allowed for variable-length commands + * (such as Read and Write). [fields] is a link-list of command fields. + */ +typedef struct Command { + const char* name; + int size; + int max_size; + Field* fields; + struct Command* next; +} Command; + +/* Adds a field to a command, and makes its offset visible. The fields must be + * added at increasing offsets. + */ +static void AddVisibleField(Command* cmd, const char* name, int offset) { + Field* fld = (Field*) calloc(1, sizeof(Field)); + if (cmd->fields != NULL) { + assert(offset > fld->offset); + } + fld->next = cmd->fields; + cmd->fields = fld; + fld->name = name; + fld->visible = 1; + fld->offset = offset; +} + +/* Adds a constant field with its value. The fields must be added at + * increasing offsets. + */ +static void AddInitializedField(Command* cmd, int offset, + int size, uint32_t value) { + Field* fld = (Field*) calloc(1, sizeof(Field)); + fld->next = cmd->fields; + cmd->fields = fld; + fld->name = NULL; + fld->visible = 0; + fld->size = size; + fld->offset = offset; + fld->value = value; +} + +/* Create a structure representing a TPM command datagram. + */ +Command* newCommand(TPM_COMMAND_CODE code, int size) { + Command* cmd = (Command*) calloc(1, sizeof(Command)); + cmd->size = size; + AddInitializedField(cmd, 0, sizeof(TPM_TAG), TPM_TAG_RQU_COMMAND); + AddInitializedField(cmd, sizeof(TPM_TAG), sizeof(uint32_t), size); + AddInitializedField(cmd, sizeof(TPM_TAG) + sizeof(uint32_t), + sizeof(TPM_COMMAND_CODE), code); + return cmd; +} + +/* The TPM_PCR_SELECTION structure in /usr/include/tss/tpm.h contains a pointer + * instead of an array[3] of bytes, so we need to adjust sizes and offsets + * accordingly. + */ +#define PCR_SELECTION_FIX (3 - sizeof(char *)) + +/* BuildXXX builds TPM command XXX. + */ +Command* BuildDefineSpaceCommand(void) { + int nv_data_public = kTpmRequestHeaderLength; + int nv_index = nv_data_public + offsetof(TPM_NV_DATA_PUBLIC, nvIndex); + int nv_pcr_info_read = nv_data_public + + offsetof(TPM_NV_DATA_PUBLIC, pcrInfoRead); + /* + * Here we need to carefully add PCR_SELECTION_FIX (or twice that much) in + * all the places where the offset calculation would be wrong without it. + * The mismatch occurs in the TPM_PCR_SELECTION structure, and it must be + * accounted for in all the structures that include it, directly or + * indirectly. + */ + int read_locality = nv_pcr_info_read + + offsetof(TPM_PCR_INFO_SHORT, localityAtRelease) + PCR_SELECTION_FIX; + int nv_pcr_info_write = nv_data_public + + offsetof(TPM_NV_DATA_PUBLIC, pcrInfoWrite) + PCR_SELECTION_FIX; + int write_locality = nv_pcr_info_write + + offsetof(TPM_PCR_INFO_SHORT, localityAtRelease) + PCR_SELECTION_FIX; + int nv_permission = nv_data_public + + offsetof(TPM_NV_DATA_PUBLIC, permission) + 2 * PCR_SELECTION_FIX; + int nv_permission_tag = + nv_permission + offsetof(TPM_NV_ATTRIBUTES, tag); + int nv_permission_attributes = + nv_permission + offsetof(TPM_NV_ATTRIBUTES, attributes); + int nv_datasize = nv_data_public + + offsetof(TPM_NV_DATA_PUBLIC, dataSize) + 2 * PCR_SELECTION_FIX; + + int size = kTpmRequestHeaderLength + sizeof(TPM_NV_DATA_PUBLIC) + + 2 * PCR_SELECTION_FIX + kEncAuthLength; + Command* cmd = newCommand(TPM_ORD_NV_DefineSpace, size); + cmd->name = "tpm_nv_definespace_cmd"; + + AddVisibleField(cmd, "index", nv_index); + AddVisibleField(cmd, "perm", nv_permission_attributes); + AddVisibleField(cmd, "size", nv_datasize); + + AddInitializedField(cmd, nv_data_public, sizeof(uint16_t), + TPM_TAG_NV_DATA_PUBLIC); + AddInitializedField(cmd, nv_pcr_info_read, sizeof(uint16_t), 3); + AddInitializedField(cmd, read_locality, sizeof(TPM_LOCALITY_SELECTION), + TPM_ALL_LOCALITIES); + AddInitializedField(cmd, nv_pcr_info_write, sizeof(uint16_t), 3); + AddInitializedField(cmd, write_locality, sizeof(TPM_LOCALITY_SELECTION), + TPM_ALL_LOCALITIES); + AddInitializedField(cmd, nv_permission_tag, sizeof(TPM_STRUCTURE_TAG), + TPM_TAG_NV_ATTRIBUTES); + return cmd; +} + +/* BuildXXX builds TPM command XXX. + */ +Command* BuildWriteCommand(void) { + Command* cmd = newCommand(TPM_ORD_NV_WriteValue, 0); + cmd->name = "tpm_nv_write_cmd"; + cmd->max_size = TPM_LARGE_ENOUGH_COMMAND_SIZE; + AddVisibleField(cmd, "index", kTpmRequestHeaderLength); + AddVisibleField(cmd, "length", kTpmRequestHeaderLength + 8); + AddVisibleField(cmd, "data", kTpmRequestHeaderLength + 12); + return cmd; +} + +Command* BuildReadCommand(void) { + int size = kTpmRequestHeaderLength + kTpmReadInfoLength; + Command* cmd = newCommand(TPM_ORD_NV_ReadValue, size); + cmd->name = "tpm_nv_read_cmd"; + AddVisibleField(cmd, "index", kTpmRequestHeaderLength); + AddVisibleField(cmd, "length", kTpmRequestHeaderLength + 8); + return cmd; +} + +Command* BuildPCRReadCommand(void) { + int size = kTpmRequestHeaderLength + sizeof(uint32_t); + Command* cmd = newCommand(TPM_ORD_PcrRead, size); + cmd->name = "tpm_pcr_read_cmd"; + AddVisibleField(cmd, "pcrNum", kTpmRequestHeaderLength); + return cmd; +} + +Command* BuildPPAssertCommand(void) { + int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE); + Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size); + cmd->name = "tpm_ppassert_cmd"; + AddInitializedField(cmd, kTpmRequestHeaderLength, + sizeof(TPM_PHYSICAL_PRESENCE), + TPM_PHYSICAL_PRESENCE_PRESENT); + return cmd; +} + +Command* BuildPPEnableCommand(void) { + int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE); + Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size); + cmd->name = "tpm_ppenable_cmd"; + AddInitializedField(cmd, kTpmRequestHeaderLength, + sizeof(TPM_PHYSICAL_PRESENCE), + TPM_PHYSICAL_PRESENCE_CMD_ENABLE); + return cmd; +} + +Command* BuildFinalizePPCommand(void) { + int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE); + Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size); + cmd->name = "tpm_finalizepp_cmd"; + AddInitializedField(cmd, kTpmRequestHeaderLength, + sizeof(TPM_PHYSICAL_PRESENCE), + TPM_PHYSICAL_PRESENCE_CMD_ENABLE | + TPM_PHYSICAL_PRESENCE_HW_DISABLE | + TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK); + return cmd; +} + +Command* BuildPPLockCommand(void) { + int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE); + Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size); + cmd->name = "tpm_pplock_cmd"; + AddInitializedField(cmd, kTpmRequestHeaderLength, + sizeof(TPM_PHYSICAL_PRESENCE), + TPM_PHYSICAL_PRESENCE_LOCK); + return cmd; +} + +Command* BuildStartupCommand(void) { + int size = kTpmRequestHeaderLength + sizeof(TPM_STARTUP_TYPE); + Command* cmd = newCommand(TPM_ORD_Startup, size); + cmd->name = "tpm_startup_cmd"; + AddInitializedField(cmd, kTpmRequestHeaderLength, + sizeof(TPM_STARTUP_TYPE), + TPM_ST_CLEAR); + return cmd; +} + +Command* BuildSaveStateCommand(void) { + int size = kTpmRequestHeaderLength; + Command* cmd = newCommand(TPM_ORD_SaveState, size); + cmd->name = "tpm_savestate_cmd"; + return cmd; +} + +Command* BuildResumeCommand(void) { + int size = kTpmRequestHeaderLength + sizeof(TPM_STARTUP_TYPE); + Command* cmd = newCommand(TPM_ORD_Startup, size); + cmd->name = "tpm_resume_cmd"; + AddInitializedField(cmd, kTpmRequestHeaderLength, + sizeof(TPM_STARTUP_TYPE), + TPM_ST_STATE); + return cmd; +} + +Command* BuildSelftestfullCommand(void) { + int size = kTpmRequestHeaderLength; + Command* cmd = newCommand(TPM_ORD_SelfTestFull, size); + cmd->name = "tpm_selftestfull_cmd"; + return cmd; +} + +Command* BuildContinueSelfTestCommand(void) { + int size = kTpmRequestHeaderLength; + Command* cmd = newCommand(TPM_ORD_ContinueSelfTest, size); + cmd->name = "tpm_continueselftest_cmd"; + return cmd; +} + +Command* BuildReadPubekCommand(void) { + int size = kTpmRequestHeaderLength + sizeof(TPM_NONCE); + Command* cmd = newCommand(TPM_ORD_ReadPubek, size); + cmd->name = "tpm_readpubek_cmd"; + 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* BuildPhysicalDisableCommand(void) { + int size = kTpmRequestHeaderLength; + Command* cmd = newCommand(TPM_ORD_PhysicalDisable, size); + cmd->name = "tpm_physicaldisable_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* BuildExtendCommand(void) { + int size = kTpmRequestHeaderLength + sizeof(uint32_t) + kPcrDigestLength; + Command* cmd = newCommand(TPM_ORD_Extend, size); + cmd->name = "tpm_extend_cmd"; + AddVisibleField(cmd, "pcrNum", kTpmRequestHeaderLength); + AddVisibleField(cmd, "inDigest", kTpmRequestHeaderLength + sizeof(uint32_t)); + return cmd; +} + +Command* BuildGetFlagsCommand(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_getflags_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; +} + +Command* BuildGetSTClearFlagsCommand(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_getstclearflags_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_VOLATILE); + return cmd; +} + +Command* BuildGetPermissionsCommand(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_getpermissions_cmd"; + AddInitializedField(cmd, kTpmRequestHeaderLength, + sizeof(TPM_CAPABILITY_AREA), TPM_CAP_NV_INDEX); + AddInitializedField(cmd, kTpmRequestHeaderLength + + sizeof(TPM_CAPABILITY_AREA), + sizeof(uint32_t), sizeof(uint32_t)); + AddVisibleField(cmd, "index", kTpmRequestHeaderLength + + sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t)); + return cmd; +} + +Command* BuildGetOwnershipCommand(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_getownership_cmd"; + AddInitializedField(cmd, kTpmRequestHeaderLength, + sizeof(TPM_CAPABILITY_AREA), TPM_CAP_PROPERTY); + 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_PROP_OWNER); + return cmd; +} + +Command* BuildGetRandomCommand(void) { + int size = kTpmRequestHeaderLength + sizeof(uint32_t); + Command* cmd = newCommand(TPM_ORD_GetRandom, size); + cmd->name = "tpm_get_random_cmd"; + AddVisibleField(cmd, "bytesRequested", kTpmRequestHeaderLength); + return cmd; +} + +/* Output the fields of a structure. + */ +void OutputFields(Field* fld) { + /* + * Field order is reversed. + */ + if (fld != NULL) { + OutputFields(fld->next); + if (fld->visible) { + printf(" uint16_t %s;\n", fld->name); + } + } +} + +/* Outputs a structure initializer. + */ +int OutputBytes_(Command* cmd, Field* fld) { + int cursor = 0; + int i; + /* + * Field order is reversed. + */ + if (fld != NULL) { + cursor = OutputBytes_(cmd, fld->next); + } else { + return 0; + } + if (!fld->visible) { + /* + * Catch up missing fields. + */ + assert(fld->offset >= cursor); + for (i = 0; i < fld->offset - cursor; i++) { + printf("0, "); + } + cursor = fld->offset; + switch (fld->size) { + case 1: + printf("0x%x, ", fld->value); + cursor += 1; + break; + case 2: + printf("0x%x, 0x%x, ", fld->value >> 8, fld->value & 0xff); + cursor += 2; + break; + case 4: + printf("0x%x, 0x%x, 0x%x, 0x%x, ", fld->value >> 24, + (fld->value >> 16) & 0xff, + (fld->value >> 8) & 0xff, + fld->value & 0xff); + cursor += 4; + break; + default: + fprintf(stderr, "invalid field size %d\n", fld->size); + exit(1); + break; + } + } + return cursor; +} + +/* Helper to output a structure initializer. + */ +void OutputBytes(Command* cmd) { + (void) OutputBytes_(cmd, cmd->fields); +} + +void OutputFieldPointers(Command* cmd, Field* fld) { + if (fld == NULL) { + return; + } else { + OutputFieldPointers(cmd, fld->next); + if (fld->visible) { + printf("%d, ", fld->offset); + } + } +} + +/* Outputs the structure initializers for all commands. + */ +void OutputCommands(Command* cmd) { + if (cmd == NULL) { + return; + } else { + printf("const struct s_%s{\n uint8_t buffer[%d];\n", + cmd->name, cmd->size == 0 ? cmd->max_size : cmd->size); + OutputFields(cmd->fields); + printf("} %s = {{", cmd->name); + OutputBytes(cmd); + printf("},\n"); + OutputFieldPointers(cmd, cmd->fields); + printf("};\n\n"); + } + OutputCommands(cmd->next); +} + +Command* (*builders[])(void) = { + BuildDefineSpaceCommand, + BuildWriteCommand, + BuildReadCommand, + BuildPCRReadCommand, + BuildPPAssertCommand, + BuildPPEnableCommand, + BuildPPLockCommand, + BuildFinalizePPCommand, + BuildStartupCommand, + BuildSaveStateCommand, + BuildResumeCommand, + BuildSelftestfullCommand, + BuildContinueSelfTestCommand, + BuildReadPubekCommand, + BuildForceClearCommand, + BuildPhysicalDisableCommand, + BuildPhysicalEnableCommand, + BuildPhysicalSetDeactivatedCommand, + BuildGetFlagsCommand, + BuildGetSTClearFlagsCommand, + BuildGetPermissionsCommand, + BuildGetOwnershipCommand, + BuildGetRandomCommand, + BuildExtendCommand, +}; + +static void FreeFields(Field* fld) { + if (fld != NULL) { + Field* next_field = fld->next; + free(fld); + FreeFields(next_field); + } +} + +static void FreeCommands(Command* cmd) { + if (cmd != NULL) { + Command* next_command = cmd->next; + FreeFields(cmd->fields); + free(cmd); + FreeCommands(next_command); + } +} + +int main(void) { + Command* commands = NULL; + uint32_t i; + for (i = 0; i < sizeof(builders) / sizeof(builders[0]); i++) { + Command* cmd = builders[i](); + cmd->next = commands; + commands = cmd; + } + + printf("/* This file is automatically generated */\n\n"); + OutputCommands(commands); + printf("const int kWriteInfoLength = %d;\n", (int) sizeof(TPM_WRITE_INFO)); + printf("const int kNvDataPublicPermissionsOffset = %d;\n", + (int) (offsetof(TPM_NV_DATA_PUBLIC, permission) + + 2 * PCR_SELECTION_FIX + + offsetof(TPM_NV_ATTRIBUTES, attributes))); + + FreeCommands(commands); + return 0; +} diff --git a/util/tss-generator/tss_extras.h b/util/tss-generator/tss_extras.h new file mode 100644 index 0000000..0fe0982 --- /dev/null +++ b/util/tss-generator/tss_extras.h @@ -0,0 +1,27 @@ +/* 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_ + +#define TPM_MAX_COMMAND_SIZE 4096 +#define TPM_LARGE_ENOUGH_COMMAND_SIZE 256 /* saves space in the firmware */ +#define TPM_ENCAUTH_SIZE 20 +#define TPM_PUBEK_SIZE 256 + +#define TPM_ALL_LOCALITIES (TPM_LOC_ZERO | TPM_LOC_ONE | TPM_LOC_TWO \ + | TPM_LOC_THREE | TPM_LOC_FOUR) /* 0x1f */ + +typedef struct tdTPM_WRITE_INFO { + uint32_t nvIndex; + uint32_t offset; + uint32_t dataSize; +} TPM_WRITE_INFO; + +#endif diff --git a/util/tss-generator/tss_internal.h b/util/tss-generator/tss_internal.h new file mode 100644 index 0000000..51fe6ef --- /dev/null +++ b/util/tss-generator/tss_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. + */ +__attribute__((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. + */ +__attribute__((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. + */ +__attribute__((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. + */ +__attribute__((unused)) +static inline void FromTpmUint16(const uint8_t *buffer, uint16_t *x) { + *x = (buffer[0] << 8) | buffer[1]; +} + +#endif /* TPM_LITE_TLCL_INTERNAL_H_ */