Stub tlcl implementation for tpm2 case
authorAndrey Pronin <apronin@google.com>
Thu, 7 Jul 2016 02:10:46 +0000 (19:10 -0700)
committerchrome-bot <chrome-bot@chromium.org>
Sat, 16 Jul 2016 02:23:56 +0000 (19:23 -0700)
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 <apronin@chromium.org>
Tested-by: Stephen Barber <smbarber@chromium.org>
Tested-by: Andrey Pronin <apronin@chromium.org>
Reviewed-by: Stephen Barber <smbarber@chromium.org>
Makefile
firmware/include/tpm2_tss_constants.h
firmware/lib/rollback_index.c
firmware/lib/tpm2_lite/tlcl.c
firmware/linktest/main.c
utility/tpmc.c

index a5460c2..2cfd206 100644 (file)
--- 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.
index fa341c0..5a4b49f 100644 (file)
 #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 */
index 232a0a4..5c949db 100644 (file)
@@ -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);
index efd7392..f335ffb 100644 (file)
@@ -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;
+}
index b4ef4e5..aec180e 100644 (file)
@@ -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);
index d7c3e15..f69bcd0 100644 (file)
@@ -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 <index> <size> <perm>)",
     HandlerDefineSpace },
   { "write", "write", "write to a space (write <index> [<byte0> <byte1> ...])",