From 1becb0dabecf6d15b0e7d88704fda86b3912be4c Mon Sep 17 00:00:00 2001 From: Andrey Pronin Date: Wed, 6 Jul 2016 19:10:46 -0700 Subject: Stub tlcl implementation for tpm2 case Build a special version of TPM Lightweight Command Library in libvboot_host for TPM2. Create the framework for implementation, stub functions for now. libvboot_host is used by tpmc and other user-space utilities that talk directly to tpm bypassing trunks/trousers. BRANCH=none BUG=chrome-os-partner:54981 BUG=chrome-os-partner:55210 TEST=Boot on kevin, verify that 'tpmc read' works. Change-Id: I4cc41028041193041defc319687697eb9edb1f3e Reviewed-on: https://chromium-review.googlesource.com/358623 Commit-Ready: Andrey Pronin Tested-by: Stephen Barber Tested-by: Andrey Pronin Reviewed-by: Stephen Barber --- Makefile | 49 +++++++++---- firmware/include/tpm2_tss_constants.h | 14 +++- firmware/lib/rollback_index.c | 4 ++ firmware/lib/tpm2_lite/tlcl.c | 128 ++++++++++++++++++++++++++++++++++ firmware/linktest/main.c | 10 +-- utility/tpmc.c | 32 ++++++++- 6 files changed, 218 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index a5460c2c..2cfd2060 100644 --- a/Makefile +++ b/Makefile @@ -385,18 +385,22 @@ BDBLIB_SRCS = \ firmware/bdb/stub.c \ firmware/bdb/nvm.c -# Support real TPM unless BIOS sets MOCK_TPM -ifeq (${MOCK_TPM},) -VBINIT_SRCS += \ - firmware/lib/rollback_index.c +# TPM lightweight command library ifeq (${TPM2_MODE},) -VBINIT_SRCS += \ +TLCL_SRCS = \ firmware/lib/tpm_lite/tlcl.c else -VBINIT_SRCS += \ +TLCL_SRCS = \ firmware/lib/tpm2_lite/tlcl.c \ firmware/lib/tpm2_lite/marshaling.c endif +TLCL_OBJS_FOR_TEST = $(TLCL_SRCS:%.c=${BUILD}/%_for_test.o) + +# Support real TPM unless BIOS sets MOCK_TPM +ifeq (${MOCK_TPM},) +VBINIT_SRCS += \ + firmware/lib/rollback_index.c \ + ${TLCL_SRCS} VBSF_SRCS += \ firmware/lib/tpm_bootmode.c @@ -505,7 +509,7 @@ HOSTLIB_SRCS = \ firmware/lib/cgptlib/crc32.c \ firmware/lib/crc8.c \ firmware/lib/gpt_misc.c \ - firmware/lib/tpm_lite/tlcl.c \ + ${TLCL_SRCS} \ firmware/lib/utility_string.c \ firmware/lib/vboot_nvstorage.c \ firmware/stub/tpm_lite_stub.c \ @@ -607,10 +611,13 @@ UTIL_NAMES_STATIC = \ utility/crossystem UTIL_NAMES = ${UTIL_NAMES_STATIC} \ - utility/tpm_init_temp_fix \ utility/dumpRSAPublicKey \ utility/tpmc +ifeq (${TPM2_MODE},) +UTIL_NAMES += utility/tpm_init_temp_fix +endif + # TODO: Do we still need eficompress and efidecompress for anything? ifeq (${MINIMAL},) UTIL_NAMES += \ @@ -721,7 +728,6 @@ TEST_OBJS += ${TESTLIB_OBJS} # And some compiled tests. TEST_NAMES = \ tests/cgptlib_test \ - tests/rollback_index2_tests \ tests/rollback_index3_tests \ tests/rsa_padding_test \ tests/rsa_utility_tests \ @@ -729,7 +735,6 @@ TEST_NAMES = \ tests/sha_benchmark \ tests/sha_tests \ tests/stateful_util_tests \ - tests/tlcl_tests \ tests/tpm_bootmode_tests \ tests/utility_string_tests \ tests/utility_tests \ @@ -752,6 +757,13 @@ TEST_NAMES = \ tests/vboot_nvstorage_test \ tests/verify_kernel +ifeq (${TPM2_MODE},) +# TODO(apronin): tests for TPM2 case? +TEST_NAMES += \ + tests/tlcl_tests \ + tests/rollback_index2_tests +endif + ifdef REGION_READ TEST_NAMES += tests/vboot_region_tests endif @@ -805,6 +817,7 @@ TESTBDB_NAMES = \ TEST_NAMES += ${TEST2X_NAMES} ${TEST20_NAMES} ${TEST21_NAMES} ${TESTBDB_NAMES} # And a few more... +ifeq (${TPM2_MODE},) TLCL_TEST_NAMES = \ tests/tpm_lite/tpmtest_earlyextend \ tests/tpm_lite/tpmtest_earlynvram \ @@ -817,6 +830,10 @@ TLCL_TEST_NAMES = \ tests/tpm_lite/tpmtest_testsetup \ tests/tpm_lite/tpmtest_timing \ tests/tpm_lite/tpmtest_writelimit +else +# TODO(apronin): tests for TPM2 case? +TLCL_TEST_NAMES = +endif TEST_NAMES += ${TLCL_TEST_NAMES} @@ -1309,17 +1326,20 @@ ${BUILD}/tests/%: CFLAGS += -Xlinker --allow-multiple-definition ${BUILD}/tests/%: LDLIBS += -lrt -luuid ${BUILD}/tests/%: LIBS += ${TESTLIB} +ifeq (${TPM2_MODE},) +# TODO(apronin): tests for TPM2 case? ${BUILD}/tests/rollback_index2_tests: OBJS += \ ${BUILD}/firmware/lib/rollback_index_for_test.o ${BUILD}/tests/rollback_index2_tests: \ ${BUILD}/firmware/lib/rollback_index_for_test.o TEST_OBJS += ${BUILD}/firmware/lib/rollback_index_for_test.o +endif ${BUILD}/tests/tlcl_tests: OBJS += \ - ${BUILD}/firmware/lib/tpm_lite/tlcl_for_test.o + ${TLCL_OBJS_FOR_TEST} ${BUILD}/tests/tlcl_tests: \ - ${BUILD}/firmware/lib/tpm_lite/tlcl_for_test.o -TEST_OBJS += ${BUILD}/firmware/lib/tpm_lite/tlcl_for_test.o + ${TLCL_OBJS_FOR_TEST} +TEST_OBJS += ${TLCL_OBJS_FOR_TEST} ${BUILD}/tests/vboot_audio_tests: OBJS += \ ${BUILD}/firmware/lib/vboot_audio_for_test.o @@ -1327,10 +1347,13 @@ ${BUILD}/tests/vboot_audio_tests: \ ${BUILD}/firmware/lib/vboot_audio_for_test.o TEST_OBJS += ${BUILD}/firmware/lib/vboot_audio_for_test.o +ifeq (${TPM2_MODE},) +# TODO(apronin): tests for TPM2 case? TLCL_TEST_BINS = $(addprefix ${BUILD}/,${TLCL_TEST_NAMES}) ${TLCL_TEST_BINS}: OBJS += ${BUILD}/tests/tpm_lite/tlcl_tests.o ${TLCL_TEST_BINS}: ${BUILD}/tests/tpm_lite/tlcl_tests.o TEST_OBJS += ${BUILD}/tests/tpm_lite/tlcl_tests.o +endif # ---------------------------------------------------------------------------- # Here are the special rules that don't fit in the generic rules. diff --git a/firmware/include/tpm2_tss_constants.h b/firmware/include/tpm2_tss_constants.h index fa341c0f..5a4b49fe 100644 --- a/firmware/include/tpm2_tss_constants.h +++ b/firmware/include/tpm2_tss_constants.h @@ -22,9 +22,13 @@ #define TPM2_NV_WriteLock ((TPM_CC)0x00000138) #define TPM2_NV_Read ((TPM_CC)0x0000014E) -/* TCG Spec defined, verify for TPM2. */ +/* TCG Spec defined, verify for TPM2. + * TODO(apronin): find TPM2 RC substitutes for TPM1.2 error codes. + */ #define TPM_E_BADINDEX ((uint32_t) 0x00000002) #define TPM_E_INVALID_POSTINIT ((uint32_t) 0x00000026) +#define TPM_E_BADTAG ((uint32_t) 0x0000001E) +#define TPM_E_IOERROR ((uint32_t) 0x0000001F) #define TPM_E_MAXNVWRITES ((uint32_t) 0x00000048) #define HR_SHIFT 24 @@ -121,4 +125,12 @@ struct tpm2_response { typedef struct {} TPM_PERMANENT_FLAGS; typedef struct {} TPM_STCLEAR_FLAGS; +/* TODO(apronin): For TPM2 certain properties must be received using + * TPM2_GetCapability instead of being hardcoded as they are now: + * TPM_MAX_COMMAND_SIZE -> use TPM_PT_MAX_COMMAND_SIZE for TPM2. + * TPM_PCR_DIGEST -> use TPM_PT_MAX_DIGEST for TPM2. + */ +#define TPM_MAX_COMMAND_SIZE 4096 +#define TPM_PCR_DIGEST 32 + #endif /* ! __VBOOT_REFERENCE_FIRMWARE_INCLUDE_TPM2_TSS_CONSTANTS_H */ diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c index 232a0a47..5c949dbe 100644 --- a/firmware/lib/rollback_index.c +++ b/firmware/lib/rollback_index.c @@ -353,8 +353,10 @@ uint32_t SetupTPM(int developer_mode, int disable_dev_request, int clear_tpm_owner_request, RollbackSpaceFirmware* rsf) { uint8_t in_flags; +#ifndef TPM2_MODE uint8_t disable; uint8_t deactivated; +#endif uint32_t result; uint32_t versions; @@ -396,6 +398,7 @@ uint32_t SetupTPM(int developer_mode, int disable_dev_request, #endif RETURN_ON_FAILURE(TlclContinueSelfTest()); #endif +#ifndef TPM2_MODE result = TlclAssertPhysicalPresence(); if (result != TPM_SUCCESS) { /* @@ -417,6 +420,7 @@ uint32_t SetupTPM(int developer_mode, int disable_dev_request, VBDEBUG(("TPM: Must reboot to re-enable\n")); return TPM_E_MUST_REBOOT; } +#endif /* Read the firmware space. */ result = ReadSpaceFirmware(rsf); diff --git a/firmware/lib/tpm2_lite/tlcl.c b/firmware/lib/tpm2_lite/tlcl.c index efd73928..f335ffb6 100644 --- a/firmware/lib/tpm2_lite/tlcl.c +++ b/firmware/lib/tpm2_lite/tlcl.c @@ -42,6 +42,65 @@ static struct tpm2_response *tpm_process_command(TPM_CC command, return response; } +uint32_t TlclLibInit(void) +{ + return VbExTpmInit(); +} + +uint32_t TlclLibClose(void) +{ + return VbExTpmClose(); +} + +uint32_t TlclSendReceive(const uint8_t *request, uint8_t *response, + int max_length) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + +int TlclPacketSize(const uint8_t *packet) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return 0; +} + +uint32_t TlclStartup(void) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + +uint32_t TlclSaveState(void) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + +uint32_t TlclResume(void) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + +uint32_t TlclSelfTestFull(void) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + +uint32_t TlclContinueSelfTest(void) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + +int32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + /** * Issue a ForceClear. The TPM error code is returned. */ @@ -63,6 +122,31 @@ uint32_t TlclSetEnable(void) return TPM_SUCCESS; } +uint32_t TlclGetFlags(uint8_t* disable, + uint8_t* deactivated, + uint8_t *nvlocked) +{ + /* For TPM2 the flags are always the same */ + if (disable) + *disable = 0; + if (deactivated) + *deactivated = 0; + if (nvlocked) + *nvlocked = 1; + return TPM_SUCCESS; +} + +int TlclIsOwned(void) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return 0; +} + +uint32_t TlclExtend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} /** * Get the permission bits for the NVRAM space with |index|. @@ -74,6 +158,25 @@ uint32_t TlclGetPermissions(uint32_t index, uint32_t *permissions) return TPM_SUCCESS; } +uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS *pflags) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + +uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS *pflags) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + +uint32_t TlclGetOwnership(uint8_t *owned) +{ + *owned = 0; + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + static uint32_t tlcl_lock_nv_write(uint32_t index) { struct tpm2_response *response; @@ -184,3 +287,28 @@ uint32_t TlclWrite(uint32_t index, const void *data, uint32_t length) return TPM_SUCCESS; } + +int32_t TlclPCRRead(uint32_t index, void *data, uint32_t length) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + +uint32_t TlclWriteLock(uint32_t index) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + +uint32_t TlclReadLock(uint32_t index) +{ + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_SUCCESS; +} + +uint32_t TlclGetRandom(uint8_t *data, uint32_t length, uint32_t *size) +{ + *size = 0; + VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__)); + return TPM_E_IOERROR; +} diff --git a/firmware/linktest/main.c b/firmware/linktest/main.c index b4ef4e5c..aec180e1 100644 --- a/firmware/linktest/main.c +++ b/firmware/linktest/main.c @@ -51,17 +51,19 @@ int main(void) TlclRead(0, 0, 0); TlclWriteLock(0); TlclReadLock(0); - TlclAssertPhysicalPresence(); - TlclSetNvLocked(); TlclIsOwned(); TlclForceClear(); TlclSetEnable(); - TlclClearEnable(); TlclSetDeactivated(0); TlclGetFlags(0, 0, 0); - TlclSetGlobalLock(); TlclExtend(0, 0, 0); TlclGetPermissions(0, 0); +#ifndef TPM2_MODE + TlclAssertPhysicalPresence(); + TlclSetNvLocked(); + TlclClearEnable(); + TlclSetGlobalLock(); +#endif /* vboot_api.h - entry points INTO vboot_reference */ VbInit(0, 0); diff --git a/utility/tpmc.c b/utility/tpmc.c index d7c3e15e..f69bcd07 100644 --- a/utility/tpmc.c +++ b/utility/tpmc.c @@ -103,6 +103,13 @@ uint8_t ErrorCheck(uint32_t result, const char* cmd) { /* Handler functions. These wouldn't exist if C had closures. */ +/* TODO(apronin): stub for selecte flags for TPM2 */ +#ifdef TPM2_MODE +static uint32_t HandlerGetFlags(void) { + fprintf(stderr, "getflags not implemented for TPM2\n"); + return OTHER_ERROR; +} +#else static uint32_t HandlerGetFlags(void) { uint8_t disabled; uint8_t deactivated; @@ -114,7 +121,9 @@ static uint32_t HandlerGetFlags(void) { } return result; } +#endif +#ifndef TPM2_MODE static uint32_t HandlerActivate(void) { return TlclSetDeactivated(0); } @@ -122,6 +131,7 @@ static uint32_t HandlerActivate(void) { static uint32_t HandlerDeactivate(void) { return TlclSetDeactivated(1); } +#endif static uint32_t HandlerDefineSpace(void) { uint32_t index, size, perm; @@ -168,11 +178,13 @@ static uint32_t HandlerWrite(void) { } if (size == 0) { +#ifndef TPM2_MODE if (index == TPM_NV_INDEX_LOCK) { fprintf(stderr, "This would set the nvLocked bit. " "Use \"tpmc setnv\" instead.\n"); exit(OTHER_ERROR); } +#endif printf("warning: zero-length write\n"); } else { printf("writing %d byte%s\n", size, size > 1 ? "s" : ""); @@ -310,6 +322,18 @@ static uint32_t HandlerGetRandom(void) { return result; } +/* TODO(apronin): stubs for permanent and ST_CLEAR flags for TPM2 */ +#ifdef TPM2_MODE +static uint32_t HandlerGetPermanentFlags(void) { + fprintf(stderr, "getpermanentflags not implemented for TPM2\n"); + return OTHER_ERROR; +} + +static uint32_t HandlerGetSTClearFlags(void) { + fprintf(stderr, "getstclearflags not implemented for TPM2\n"); + return OTHER_ERROR; +} +#else static uint32_t HandlerGetPermanentFlags(void) { TPM_PERMANENT_FLAGS pflags; uint32_t result = TlclGetPermanentFlags(&pflags); @@ -354,7 +378,7 @@ static uint32_t HandlerGetSTClearFlags(void) { } return result; } - +#endif /* TPM2_MODE */ static uint32_t HandlerSendRaw(void) { uint8_t request[4096]; @@ -407,6 +431,7 @@ command_record command_table[] = { { "selftestfull", "test", "issue a SelfTestFull command", TlclSelfTestFull }, { "continueselftest", "ctest", "issue a ContinueSelfTest command", TlclContinueSelfTest }, +#ifndef TPM2_MODE { "assertphysicalpresence", "ppon", "assert Physical Presence", TlclAssertPhysicalPresence }, { "physicalpresencecmdenable", "ppcmd", "turn on software PP", @@ -417,13 +442,18 @@ command_record command_table[] = { HandlerActivate }, { "deactivate", "deact", "deactivate the TPM (needs PP, maybe reboot)", HandlerDeactivate }, +#endif { "clear", "clr", "clear the TPM owner (needs PP)", TlclForceClear }, +#ifndef TPM2_MODE { "setnvlocked", "setnv", "set the nvLocked flag permanently (IRREVERSIBLE!)", TlclSetNvLocked }, +#endif { "lockphysicalpresence", "pplock", "lock (turn off) PP until reboot", TlclLockPhysicalPresence }, +#ifndef TPM2_MODE { "setbgloballock", "block", "set the bGlobalLock until reboot", TlclSetGlobalLock }, +#endif { "definespace", "def", "define a space (def )", HandlerDefineSpace }, { "write", "write", "write to a space (write [ ...])", -- cgit v1.2.1