]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.c
Enhance TPM driver to protect TPM physical presence flags.
[mirror_edk2.git] / SecurityPkg / Library / DxeTcgPhysicalPresenceLib / DxeTcgPhysicalPresenceLib.c
index 2130b2b43c706fcb9d815f71d6713abad1b0e06f..427cc8d66bcda4a5f0e67550f52c778c1bbf6e16 100644 (file)
@@ -8,7 +8,7 @@
 \r
   ExecutePendingTpmRequest() will receive untrusted input and do validation.\r
 \r
-Copyright (c) 2006 - 2012, 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
@@ -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
@@ -896,7 +897,7 @@ UserConfirm (
   Check if there is a valid physical presence command request. Also updates parameter value \r
   to whether the requested physical presence command already confirmed by user\r
  \r
-   @param[in]  TcgProtocol                 EFI TCG Protocol instance\r
+   @param[in]  TcgPpData                 EFI TCG Physical Presence request data\r
    @param[out] RequestConfirmed            If the physical presence operation command required user confirm from UI.\r
                                              True, it indicates the command doesn't require user confirm, or already confirmed \r
                                                    in last boot cycle by user.\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,21 +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 (TcgPpData->PPRequest == PHYSICAL_PRESENCE_NO_ACTION) {\r
-    //\r
-    // No operation request\r
-    //\r
-    return;\r
-  }\r
-\r
-  if (!HaveValidTpmRequest(TcgPpData, &RequestConfirmed)) {\r
+  if (!HaveValidTpmRequest(TcgPpData, Flags, &RequestConfirmed)) {\r
     //\r
     // Invalid operation request.\r
     //\r
@@ -1046,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
@@ -1130,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
@@ -1150,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
@@ -1163,7 +1217,14 @@ 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
+    // No operation request\r
+    //\r
+    return;\r
+  }\r
 \r
   Status = GetTpmCapability (TcgProtocol, &LifetimeLock, &CmdEnable);\r
   if (EFI_ERROR (Status)) {\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