]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.c
Fix the return status when physical presence variable and MemoryOverwriteRequestContr...
[mirror_edk2.git] / SecurityPkg / Library / DxeTcgPhysicalPresenceLib / DxeTcgPhysicalPresenceLib.c
index 44845b0f854dbb4c9dbdbb7afb7d0f2acc7e5820..8a5e7d17c6fca9850ba1ae0be1bd982ef769652c 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 - 2014, 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,11 +897,12 @@ 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]  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
-                                             False, it indicates the command need user confirm from UI.\r
+   @param[in]  TcgPpData           EFI TCG Physical Presence request data.\r
+   @param[in]  Flags               The physical presence interface flags. \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
+                                   False, it indicates the command need user confirm from UI.\r
 \r
    @retval  TRUE        Physical Presence operation command is valid.\r
    @retval  FALSE       Physical Presence operation command is invalid.\r
@@ -909,12 +911,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
@@ -998,26 +999,22 @@ HaveValidTpmRequest  (
 \r
   @param[in] TcgProtocol          EFI TCG Protocol instance. \r
   @param[in] TcgPpData            Point to the physical presence NV variable.\r
+  @param[in] Flags                The physical presence interface flags.\r
 \r
 **/\r
 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 +1043,32 @@ 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
+    if (EFI_ERROR (Status)) {\r
+      return;\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 +1145,57 @@ 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
+    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
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "[TPM] Set physical presence flag failed, Status = %r\n", Status));\r
+      return ;\r
+    }\r
+  }\r
+  DEBUG ((EFI_D_INFO, "[TPM] PpiFlags = %x\n", PpiFlags));\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
@@ -1148,22 +1209,29 @@ TcgPhysicalPresenceLibProcessRequest (
                   &TcgPpData\r
                   );\r
   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
-                        &gEfiPhysicalPresenceGuid,\r
-                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
-                        DataSize,\r
-                        &TcgPpData\r
-                        );\r
+    ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));\r
+    DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
+    Status   = gRT->SetVariable (\r
+                      PHYSICAL_PRESENCE_VARIABLE,\r
+                      &gEfiPhysicalPresenceGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      DataSize,\r
+                      &TcgPpData\r
+                      );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "[TPM] Set physical presence variable failed, Status = %r\n", Status));\r
+      return;\r
     }\r
-    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 +1259,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 +1291,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 +1313,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 +1332,7 @@ TcgPhysicalPresenceLibNeedUserConfirm(
     return FALSE;\r
   }\r
 \r
-  if (!HaveValidTpmRequest(&TcgPpData, &RequestConfirmed)) {\r
+  if (!HaveValidTpmRequest(&TcgPpData, PpiFlags, &RequestConfirmed)) {\r
     //\r
     // Invalid operation request.\r
     //\r