Enhance TPM driver to protect TPM physical presence flags.
[mirror_edk2.git] / SecurityPkg / Library / DxeTcgPhysicalPresenceLib / DxeTcgPhysicalPresenceLib.c
index 3414cd2..427cc8d 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