Enhance TPM driver to protect TPM physical presence flags.
authorDong Guo <guo.dong@intel.com>
Tue, 3 Sep 2013 07:39:26 +0000 (07:39 +0000)
committergdong1 <gdong1@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 3 Sep 2013 07:39:26 +0000 (07:39 +0000)
Signed-off-by: Dong Guo <guo.dong@intel.com>
Reviewed-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ouyang, Qian <qian.ouyang@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14619 6f19259b-4bc3-4df7-8a09-765794883524

SecurityPkg/Include/Guid/PhysicalPresenceData.h
SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.c
SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.inf
SecurityPkg/Tcg/TcgSmm/TcgSmm.c

index 4db20a7b16aa818f5d36442b6ea64da6325a3f25..942865784c1b14de601adc9a0ad524efbf7d5ab3 100644 (file)
@@ -4,7 +4,7 @@
   cleared after it is processed in the next boot cycle. The TPM response \r
   is saved to variable.\r
 \r
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials \r
 are licensed and made available under the terms and conditions of the BSD License \r
 which accompanies this distribution.  The full text of the license may be found at \r
@@ -29,17 +29,8 @@ typedef struct {
   UINT8   PPRequest;      ///< Physical Presence request command.\r
   UINT8   LastPPRequest;\r
   UINT32  PPResponse;\r
-  UINT8   Flags;\r
 } EFI_PHYSICAL_PRESENCE;\r
 \r
-//\r
-// The definition bit of the flags\r
-//\r
-#define FLAG_NO_PPI_PROVISION                    BIT0\r
-#define FLAG_NO_PPI_CLEAR                        BIT1\r
-#define FLAG_NO_PPI_MAINTENANCE                  BIT2\r
-#define FLAG_RESET_TRACK                         BIT3\r
-\r
 //\r
 // The definition of physical presence operation actions\r
 //\r
@@ -67,6 +58,20 @@ typedef struct {
 #define PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR                   21\r
 #define PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE   22\r
 \r
+//\r
+// This variable is used to save TPM Management Flags and corresponding operations.\r
+// It should be protected from malicious software (e.g. Set it as read-only variable). \r
+//\r
+#define PHYSICAL_PRESENCE_FLAGS_VARIABLE  L"PhysicalPresenceFlags"\r
+\r
+//\r
+// The definition bit of the TPM Management Flags\r
+//\r
+#define FLAG_NO_PPI_PROVISION                    BIT0\r
+#define FLAG_NO_PPI_CLEAR                        BIT1\r
+#define FLAG_NO_PPI_MAINTENANCE                  BIT2\r
+#define FLAG_RESET_TRACK                         BIT3\r
+\r
 extern EFI_GUID  gEfiPhysicalPresenceGuid;\r
 \r
 #endif\r
index 3414cd2ea42559c11839f4f0d30f0c0e5ebc5ecf..427cc8d66bcda4a5f0e67550f52c778c1bbf6e16 100644 (file)
@@ -22,6 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <PiDxe.h>\r
 \r
 #include <Protocol/TcgService.h>\r
+#include <Protocol/VariableLock.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/UefiRuntimeServicesTableLib.h>\r
@@ -909,12 +910,11 @@ UserConfirm (
 BOOLEAN\r
 HaveValidTpmRequest  (\r
   IN      EFI_PHYSICAL_PRESENCE     *TcgPpData,\r
+  IN      UINT8                     Flags,\r
   OUT     BOOLEAN                   *RequestConfirmed\r
   )\r
 {\r
-  UINT8                             Flags;\r
-  \r
-  Flags = TcgPpData->Flags;\r
+\r
   *RequestConfirmed = FALSE;\r
 \r
   switch (TcgPpData->PPRequest) {\r
@@ -1003,14 +1003,16 @@ HaveValidTpmRequest  (
 VOID\r
 ExecutePendingTpmRequest (\r
   IN      EFI_TCG_PROTOCOL          *TcgProtocol,\r
-  IN      EFI_PHYSICAL_PRESENCE     *TcgPpData\r
+  IN      EFI_PHYSICAL_PRESENCE     *TcgPpData,\r
+  IN      UINT8                     Flags\r
   )\r
 {\r
   EFI_STATUS                        Status;\r
   UINTN                             DataSize;\r
   BOOLEAN                           RequestConfirmed;\r
+  UINT8                             NewFlags;\r
 \r
-  if (!HaveValidTpmRequest(TcgPpData, &RequestConfirmed)) {\r
+  if (!HaveValidTpmRequest(TcgPpData, Flags, &RequestConfirmed)) {\r
     //\r
     // Invalid operation request.\r
     //\r
@@ -1039,14 +1041,29 @@ ExecutePendingTpmRequest (
   // Execute requested physical presence command\r
   //\r
   TcgPpData->PPResponse = TPM_PP_USER_ABORT;\r
+  NewFlags = Flags;\r
   if (RequestConfirmed) {\r
-    TcgPpData->PPResponse = ExecutePhysicalPresence (TcgProtocol, TcgPpData->PPRequest, &TcgPpData->Flags);\r
+    TcgPpData->PPResponse = ExecutePhysicalPresence (TcgProtocol, TcgPpData->PPRequest, &NewFlags);\r
   }\r
 \r
+  //\r
+  // Save the flags if it is updated.\r
+  //\r
+  if (Flags != NewFlags) {\r
+    Status   = gRT->SetVariable (\r
+                      PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                      &gEfiPhysicalPresenceGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      sizeof (UINT8),\r
+                      &NewFlags\r
+                      ); \r
+  }\r
+\r
+\r
   //\r
   // Clear request\r
   //\r
-  if ((TcgPpData->Flags & FLAG_RESET_TRACK) == 0) {\r
+  if ((NewFlags & FLAG_RESET_TRACK) == 0) {\r
     TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
     TcgPpData->PPRequest = PHYSICAL_PRESENCE_NO_ACTION;    \r
   }\r
@@ -1123,11 +1140,56 @@ TcgPhysicalPresenceLibProcessRequest (
   UINTN                             DataSize;\r
   EFI_PHYSICAL_PRESENCE             TcgPpData;\r
   EFI_TCG_PROTOCOL                  *TcgProtocol;\r
+  EDKII_VARIABLE_LOCK_PROTOCOL      *VariableLockProtocol;\r
+  UINT8                             PpiFlags;\r
   \r
   Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);\r
   if (EFI_ERROR (Status)) {\r
     return ;\r
   }\r
+\r
+  //\r
+  // Initialize physical presence flags.\r
+  //\r
+  DataSize = sizeof (UINT8);\r
+  Status = gRT->GetVariable (\r
+                  PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                  &gEfiPhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &PpiFlags\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_NOT_FOUND) {\r
+      PpiFlags = FLAG_NO_PPI_PROVISION;\r
+      Status   = gRT->SetVariable (\r
+                        PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                        &gEfiPhysicalPresenceGuid,\r
+                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                        sizeof (UINT8),\r
+                        &PpiFlags\r
+                        );\r
+    }\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+      DEBUG ((EFI_D_ERROR, "[TPM] PpiFlags = %x, Status = %r\n", PpiFlags, Status));\r
+\r
+  //\r
+  // This flags variable controls whether physical presence is required for TPM command. \r
+  // It should be protected from malicious software. We set it as read-only variable here.\r
+  //\r
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = VariableLockProtocol->RequestToLock (\r
+                                     VariableLockProtocol,\r
+                                     PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                                     &gEfiPhysicalPresenceGuid\r
+                                     );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "[TPM] Error when lock variable %s, Status = %r\n", PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
   \r
   //\r
   // Initialize physical presence variable.\r
@@ -1143,7 +1205,6 @@ TcgPhysicalPresenceLibProcessRequest (
   if (EFI_ERROR (Status)) {\r
     if (Status == EFI_NOT_FOUND) {\r
       ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));\r
-      TcgPpData.Flags |= FLAG_NO_PPI_PROVISION;\r
       DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
       Status   = gRT->SetVariable (\r
                         PHYSICAL_PRESENCE_VARIABLE,\r
@@ -1156,7 +1217,7 @@ TcgPhysicalPresenceLibProcessRequest (
     ASSERT_EFI_ERROR (Status);\r
   }\r
 \r
-  DEBUG ((EFI_D_INFO, "[TPM] Flags=%x, PPRequest=%x\n", TcgPpData.Flags, TcgPpData.PPRequest));\r
+  DEBUG ((EFI_D_INFO, "[TPM] Flags=%x, PPRequest=%x\n", PpiFlags, TcgPpData.PPRequest));\r
 \r
   if (TcgPpData.PPRequest == PHYSICAL_PRESENCE_NO_ACTION) {\r
     //\r
@@ -1191,7 +1252,7 @@ TcgPhysicalPresenceLibProcessRequest (
   //\r
   // Execute pending TPM request.\r
   //  \r
-  ExecutePendingTpmRequest (TcgProtocol, &TcgPpData);\r
+  ExecutePendingTpmRequest (TcgProtocol, &TcgPpData, PpiFlags);\r
   DEBUG ((EFI_D_INFO, "[TPM] PPResponse = %x\n", TcgPpData.PPResponse));\r
 \r
   //\r
@@ -1223,7 +1284,8 @@ TcgPhysicalPresenceLibNeedUserConfirm(
   BOOLEAN                 LifetimeLock;\r
   BOOLEAN                 CmdEnable;\r
   EFI_TCG_PROTOCOL        *TcgProtocol;\r
-\r
+  UINT8                   PpiFlags;\r
+  \r
   Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);\r
   if (EFI_ERROR (Status)) {\r
     return FALSE;\r
@@ -1244,6 +1306,18 @@ TcgPhysicalPresenceLibNeedUserConfirm(
     return FALSE;\r
   }\r
 \r
+  DataSize = sizeof (UINT8);\r
+  Status = gRT->GetVariable (\r
+                  PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                  &gEfiPhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &PpiFlags\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+  \r
   if (TcgPpData.PPRequest == PHYSICAL_PRESENCE_NO_ACTION) {\r
     //\r
     // No operation request\r
@@ -1251,7 +1325,7 @@ TcgPhysicalPresenceLibNeedUserConfirm(
     return FALSE;\r
   }\r
 \r
-  if (!HaveValidTpmRequest(&TcgPpData, &RequestConfirmed)) {\r
+  if (!HaveValidTpmRequest(&TcgPpData, PpiFlags, &RequestConfirmed)) {\r
     //\r
     // Invalid operation request.\r
     //\r
index 0a197fd31c35e15edfbd469c7d3fc5ddc416eb93..d700ed2e83caaf7ea5bf1115649dc78dfdd2dea1 100644 (file)
@@ -6,7 +6,7 @@
 #  This driver will have external input - variable.\r
 #  This external input must be validated carefully to avoid security issue.\r
 #\r
-# Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution. The full text of the license may be found at\r
@@ -53,6 +53,7 @@
 \r
 [Protocols]\r
   gEfiTcgProtocolGuid\r
+  gEdkiiVariableLockProtocolGuid\r
 \r
 [Guids]\r
   gEfiPhysicalPresenceGuid\r
index 7a16b9ca26278adedd2a3598c89adad2c1d7c723..97cd916d0711f5d1768e946b48e48e621e3c667e 100644 (file)
@@ -8,7 +8,7 @@
 \r
   PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.\r
 \r
-Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials \r
 are licensed and made available under the terms and conditions of the BSD License \r
 which accompanies this distribution.  The full text of the license may be found at \r
@@ -103,7 +103,22 @@ PhysicalPresenceCallback (
     }\r
     mTcgNvs->PhysicalPresence.ReturnCode = PP_SUBMIT_REQUEST_SUCCESS;\r
   } else if (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {\r
-    Flags = PpData.Flags;  \r
+    //\r
+    // Get the Physical Presence flags\r
+    //\r
+    DataSize = sizeof (UINT8);\r
+    Status = mSmmVariable->SmmGetVariable (\r
+                             PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                             &gEfiPhysicalPresenceGuid,\r
+                             NULL,\r
+                             &DataSize,\r
+                             &Flags\r
+                             );\r
+    if (EFI_ERROR (Status)) {\r
+      mTcgNvs->PhysicalPresence.ReturnCode = PP_SUBMIT_REQUEST_GENERAL_FAILURE;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
     RequestConfirmed = FALSE;\r
 \r
     switch (mTcgNvs->PhysicalPresence.Request) {\r