Modify 'tpmc block' to lock only the FW index
authorAndrey Pronin <apronin@google.com>
Sat, 23 Jul 2016 01:45:37 +0000 (18:45 -0700)
committerchrome-bot <chrome-bot@chromium.org>
Wed, 27 Jul 2016 06:54:28 +0000 (23:54 -0700)
As discussed in https://chromium-review.googlesource.com/#/c/361381/,
instead of being a synonym to 'tpmc pplock', the 'tpmc block' command
should protect just the FW index using WriteLock.

Additionally, both TlclSetGlobalLock and TlclLockPhysicalPresence in
tlcl (which are used by 'tpmc block' and 'tpmc pplock') are updated
to first check if the platform hierarchy is already disabled and
return success, if so. That's needed to prevent command failures
when rollback protection is already on.

BRANCH=none
BUG=chrome-os-partner:55210
BUG=chrome-os-partner:55250
TEST=boot on kevin, verify that 'tpmc block' and 'tpmc pplock'
     work as expected:
     - pplock is possible after block
     - pplock and block succeed both for enabled and disabled PH
     - block locks FW index
     - pplock disables PH

Change-Id: I32bff2b590a51315b11da361b97c684dcce8ab36
Reviewed-on: https://chromium-review.googlesource.com/362772
Commit-Ready: Andrey Pronin <apronin@chromium.org>
Tested-by: Andrey Pronin <apronin@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
firmware/include/tpm2_marshaling.h
firmware/lib/tpm2_lite/marshaling.c
firmware/lib/tpm2_lite/tlcl.c
firmware/linktest/main.c
utility/tpmc.c

index 2022986..3d6fb8a 100644 (file)
@@ -50,11 +50,22 @@ struct tpm2_response *tpm_unmarshal_response(TPM_CC command,
  * tpm_set_ph_disabled
  *
  * Sets the flag that indicates if platform hierarchy is disabled.
- * certain commands, like NV_Read, may need to use different
+ * Certain commands, like NV_Read, may need to use different
  * authorization if platform hierarchy is disabled.
  *
  * @flag: 1 if platform hierarchy is disabled, 0 otherwise
  */
 void tpm_set_ph_disabled(int flag);
 
+/**
+ * tpm_is_ph_disabled
+ *
+ * Gets the flag that indicates if platform hierarchy is disabled.
+ * Certain commands, like NV_Read, may need to use different
+ * authorization if platform hierarchy is disabled.
+ *
+ * Returns 1 if platform hierarchy is disabled, 0 otherwise
+ */
+int tpm_is_ph_disabled(void);
+
 #endif // __SRC_LIB_TPM2_MARSHALING_H
index 73285c3..037e696 100644 (file)
@@ -520,3 +520,8 @@ void tpm_set_ph_disabled(int flag)
 {
        ph_disabled = flag;
 }
+
+int tpm_is_ph_disabled(void)
+{
+       return ph_disabled;
+}
index a03125d..efc528d 100644 (file)
@@ -277,6 +277,23 @@ static uint32_t tlcl_disable_platform_hierarchy(void)
 }
 
 /**
+ * The name of the function was kept to maintain the existing TPM API, but
+ * TPM2.0 does not use the global lock to protect the FW rollback counter.
+ * Instead it calls WriteLock for the FW NVRAM index to prevent future
+ * writes to it.
+ *
+ * It first checks if the platform hierarchy is already disabled, and does
+ * nothing, if so. Otherwise, WriteLock for the index obviously fails.
+ */
+uint32_t TlclSetGlobalLock(void)
+{
+       if (tpm_is_ph_disabled())
+               return TPM_SUCCESS;
+       else
+               return tlcl_lock_nv_write(FIRMWARE_NV_INDEX);
+}
+
+/**
  * Turn off physical presence and locks it off until next reboot.  The TPM
  * error code is returned.
  *
@@ -292,6 +309,9 @@ uint32_t TlclLockPhysicalPresence(void)
 {
        uint32_t rv;
 
+       if (tpm_is_ph_disabled())
+               return TPM_SUCCESS;
+
        rv = tlcl_lock_nv_write(KERNEL_NV_INDEX);
        if (rv == TPM_SUCCESS)
                rv = tlcl_disable_platform_hierarchy();
index 1c9b614..9dca957 100644 (file)
@@ -44,13 +44,13 @@ int main(void)
        TlclSetEnable();
        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 */
index beb739f..d7c76f0 100644 (file)
@@ -452,15 +452,20 @@ command_record command_table[] = {
   { "setnvlocked", "setnv", "set the nvLocked flag permanently (IRREVERSIBLE!)",
     TlclSetNvLocked },
 #endif
-  { "lockphysicalpresence", "pplock", "lock (turn off) PP until reboot",
-    TlclLockPhysicalPresence },
+  { "lockphysicalpresence", "pplock",
 #ifdef TPM2_MODE
-  { "setbgloballock", "block", "set rollback protection lock until reboot",
+    "set rollback protection lock for kernel image until reboot",
+#else
+    "lock (turn off) PP until reboot",
+#endif
     TlclLockPhysicalPresence },
+  { "setbgloballock", "block",
+#ifdef TPM2_MODE
+    "set rollback protection lock for R/W firmware until reboot",
 #else
-  { "setbgloballock", "block", "set the bGlobalLock until reboot",
-    TlclSetGlobalLock },
+    "set the bGlobalLock until reboot",
 #endif
+    TlclSetGlobalLock },
   { "definespace", "def", "define a space (def <index> <size> <perm>)",
     HandlerDefineSpace },
   { "write", "write", "write to a space (write <index> [<byte0> <byte1> ...])",