]> git.proxmox.com Git - mirror_edk2.git/commitdiff
SecurityPkg: AuthVariableLib: Customized SecureBoot Mode transition.
authorChao Zhang <chao.b.zhang@intel.com>
Mon, 7 Dec 2015 06:20:02 +0000 (06:20 +0000)
committerczhang46 <czhang46@Edk2>
Mon, 7 Dec 2015 06:20:02 +0000 (06:20 +0000)
  Implement Customized SecureBoot Mode transition logic according to Mantis 1263, including AuditMode/DeployedMode/PK update management.
  Also implement image verification logic in AuditMode. Image Certificate & Hash are recorded to EFI Image Execution Table.
  https://mantis.uefi.org/mantis/view.php?id=1263

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
Reviewed-by: Zeng Star <star.zeng@intel.com>
Reviewed-by: Long Qin <qin.long@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19133 6f19259b-4bc3-4df7-8a09-765794883524

SecurityPkg/Library/AuthVariableLib/AuthService.c
SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h
SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c
SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c

index 1f9ba15384f2ce16084d7c148f5f4f86c1939d3a..5546c2e5c9065082ba5d850db9e35305537798b3 100644 (file)
@@ -56,6 +56,54 @@ EFI_SIGNATURE_ITEM mSupportSigItem[] = {
   {EFI_CERT_X509_SHA512_GUID,     0,               80           }\r
 };\r
 \r
+//\r
+// Secure Boot Mode state machine\r
+//\r
+SECURE_BOOT_MODE mSecureBootState[SecureBootModeTypeMax] = {\r
+  // USER MODE\r
+  {\r
+      AUDIT_MODE_DISABLE,                        // AuditMode\r
+      FALSE,                                     // IsAuditModeRO, AuditMode is RW\r
+      DEPLOYED_MODE_DISABLE,                     // DeployedMode\r
+      FALSE,                                     // IsDeployedModeRO, DeployedMode is RW\r
+      SETUP_MODE_DISABLE,                        // SetupMode\r
+                                                 // SetupMode is always RO\r
+      SECURE_BOOT_MODE_ENABLE                    // SecureBoot\r
+  },\r
+  // SETUP MODE\r
+  {\r
+      AUDIT_MODE_DISABLE,                        // AuditMode\r
+      FALSE,                                     // IsAuditModeRO, AuditMode is RW\r
+      DEPLOYED_MODE_DISABLE,                     // DeployedMode\r
+      TRUE,                                      // IsDeployedModeRO, DeployedMode is RO\r
+      SETUP_MODE_ENABLE,                         // SetupMode\r
+                                                 // SetupMode is always RO\r
+      SECURE_BOOT_MODE_DISABLE                   // SecureBoot\r
+  },\r
+  // AUDIT MODE\r
+  {\r
+      AUDIT_MODE_ENABLE,                         // AuditMode\r
+      TRUE,                                      // AuditModeValAttr RO, AuditMode is RO\r
+      DEPLOYED_MODE_DISABLE,                     // DeployedMode\r
+      TRUE,                                      // DeployedModeValAttr RO, DeployedMode is RO\r
+      SETUP_MODE_ENABLE,                         // SetupMode\r
+                                                 // SetupMode is always RO\r
+      SECURE_BOOT_MODE_DISABLE                   // SecureBoot\r
+  },\r
+  // DEPLOYED MODE\r
+  {\r
+      AUDIT_MODE_DISABLE,                        // AuditMode, AuditMode is RO\r
+      TRUE,                                      // AuditModeValAttr RO\r
+      DEPLOYED_MODE_ENABLE,                      // DeployedMode\r
+      TRUE,                                      // DeployedModeValAttr RO, DeployedMode is RO\r
+      SETUP_MODE_DISABLE,                        // SetupMode\r
+                                                 // SetupMode is always RO\r
+      SECURE_BOOT_MODE_ENABLE                    // SecureBoot\r
+  }\r
+};\r
+\r
+SECURE_BOOT_MODE_TYPE  mSecureBootMode;\r
+\r
 /**\r
   Finds variable in storage blocks of volatile and non-volatile storage areas.\r
 \r
@@ -179,74 +227,982 @@ AuthServiceInternalUpdateVariableWithMonotonicCount (
 }\r
 \r
 /**\r
-  Update the variable region with Variable information.\r
+  Update the variable region with Variable information.\r
+\r
+  @param[in] VariableName           Name of variable.\r
+  @param[in] VendorGuid             Guid of variable.\r
+  @param[in] Data                   Data pointer.\r
+  @param[in] DataSize               Size of Data.\r
+  @param[in] Attributes             Attribute value of the variable.\r
+  @param[in] TimeStamp              Value of associated TimeStamp.\r
+\r
+  @retval EFI_SUCCESS               The update operation is success.\r
+  @retval EFI_INVALID_PARAMETER     Invalid parameter.\r
+  @retval EFI_WRITE_PROTECTED       Variable is write-protected.\r
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+\r
+**/\r
+EFI_STATUS\r
+AuthServiceInternalUpdateVariableWithTimeStamp (\r
+  IN CHAR16             *VariableName,\r
+  IN EFI_GUID           *VendorGuid,\r
+  IN VOID               *Data,\r
+  IN UINTN              DataSize,\r
+  IN UINT32             Attributes,\r
+  IN EFI_TIME           *TimeStamp\r
+  )\r
+{\r
+  EFI_STATUS            FindStatus;\r
+  VOID                  *OrgData;\r
+  UINTN                 OrgDataSize;\r
+  AUTH_VARIABLE_INFO    AuthVariableInfo;\r
+\r
+  FindStatus = AuthServiceInternalFindVariable (\r
+                 VariableName,\r
+                 VendorGuid,\r
+                 &OrgData,\r
+                 &OrgDataSize\r
+                 );\r
+\r
+  //\r
+  // EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable\r
+  //\r
+  if (!EFI_ERROR (FindStatus) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0)) {\r
+    if ((CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&\r
+        ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) ||\r
+        (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0))) ||\r
+        (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) {\r
+      //\r
+      // For variables with formatted as EFI_SIGNATURE_LIST, the driver shall not perform an append of\r
+      // EFI_SIGNATURE_DATA values that are already part of the existing variable value.\r
+      //\r
+      FilterSignatureList (\r
+        OrgData,\r
+        OrgDataSize,\r
+        Data,\r
+        &DataSize\r
+        );\r
+    }\r
+  }\r
+\r
+  ZeroMem (&AuthVariableInfo, sizeof (AuthVariableInfo));\r
+  AuthVariableInfo.VariableName = VariableName;\r
+  AuthVariableInfo.VendorGuid = VendorGuid;\r
+  AuthVariableInfo.Data = Data;\r
+  AuthVariableInfo.DataSize = DataSize;\r
+  AuthVariableInfo.Attributes = Attributes;\r
+  AuthVariableInfo.TimeStamp = TimeStamp;\r
+  return mAuthVarLibContextIn->UpdateVariable (\r
+           &AuthVariableInfo\r
+           );\r
+}\r
+\r
+/**\r
+  Initialize Secure Boot variables.\r
+\r
+  @retval EFI_SUCCESS               The initialization operation is successful.\r
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+\r
+**/\r
+EFI_STATUS\r
+InitSecureBootVariables (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS             Status;\r
+  UINT8                  *Data;\r
+  UINTN                  DataSize;\r
+  UINT32                 SecureBoot;\r
+  UINT8                  SecureBootEnable;\r
+  SECURE_BOOT_MODE_TYPE  SecureBootMode;\r
+  BOOLEAN                IsPkPresent;\r
+\r
+  //\r
+  // Find "PK" variable\r
+  //\r
+  Status = AuthServiceInternalFindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize);\r
+  if (EFI_ERROR (Status)) {\r
+    IsPkPresent = FALSE;\r
+    DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME));\r
+  } else {\r
+    IsPkPresent = TRUE;\r
+    DEBUG ((EFI_D_INFO, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME));\r
+  }\r
+\r
+  //\r
+  // Init "SecureBootMode" variable.\r
+  // Initial case\r
+  //   SecureBootMode doesn't exist. Init it with PK state\r
+  // 3 inconsistency cases need to sync\r
+  //   1.1 Add PK     -> system break -> update SecureBootMode Var\r
+  //   1.2 Delete PK  -> system break -> update SecureBootMode Var\r
+  //   1.3 Set AuditMode ->Delete PK  -> system break -> Update SecureBootMode Var\r
+  //\r
+  Status = AuthServiceInternalFindVariable (EDKII_SECURE_BOOT_MODE_NAME, &gEdkiiSecureBootModeGuid, (VOID **)&Data, &DataSize);\r
+  if (EFI_ERROR(Status)) {\r
+    //\r
+    // Variable driver Initial Case\r
+    //\r
+    if (IsPkPresent) {\r
+      SecureBootMode = SecureBootModeTypeUserMode;\r
+    } else {\r
+      SecureBootMode = SecureBootModeTypeSetupMode;\r
+    }\r
+  } else {\r
+    //\r
+    // 3 inconsistency cases need to sync\r
+    //\r
+    SecureBootMode = (SECURE_BOOT_MODE_TYPE)*Data;\r
+    ASSERT(SecureBootMode < SecureBootModeTypeMax);\r
+\r
+    if (IsPkPresent) {\r
+      //\r
+      // 3.1 Add PK     -> system break -> update SecureBootMode Var\r
+      //\r
+      if (SecureBootMode == SecureBootModeTypeSetupMode) {\r
+        SecureBootMode = SecureBootModeTypeUserMode;\r
+      } else if (SecureBootMode == SecureBootModeTypeAuditMode) {\r
+        SecureBootMode = SecureBootModeTypeDeployedMode;\r
+      }\r
+    } else {\r
+      //\r
+      // 3.2 Delete PK -> system break -> update SecureBootMode Var\r
+      // 3.3 Set AuditMode ->Delete PK  -> system break -> Update SecureBootMode Var. Reinit to be SetupMode\r
+      //\r
+      if ((SecureBootMode == SecureBootModeTypeUserMode) || (SecureBootMode == SecureBootModeTypeDeployedMode)) {\r
+        SecureBootMode = SecureBootModeTypeSetupMode;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (EFI_ERROR(Status) || (SecureBootMode != (SECURE_BOOT_MODE_TYPE)*Data)) {\r
+    //\r
+    // Update SecureBootMode Var\r
+    //\r
+    Status = AuthServiceInternalUpdateVariable (\r
+               EDKII_SECURE_BOOT_MODE_NAME,\r
+               &gEdkiiSecureBootModeGuid,\r
+               &SecureBootMode,\r
+               sizeof (UINT8),\r
+               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
+               );\r
+    if (EFI_ERROR(Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Init "AuditMode"\r
+  //\r
+  Status = AuthServiceInternalUpdateVariable (\r
+             EFI_AUDIT_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &mSecureBootState[SecureBootMode].AuditMode,\r
+             sizeof(UINT8),\r
+             EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
+             );\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Init "DeployedMode"\r
+  //\r
+  Status = AuthServiceInternalUpdateVariable (\r
+             EFI_DEPLOYED_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &mSecureBootState[SecureBootMode].DeployedMode,\r
+             sizeof(UINT8),\r
+             EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
+             );\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Init "SetupMode"\r
+  //\r
+  Status = AuthServiceInternalUpdateVariable (\r
+             EFI_SETUP_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &mSecureBootState[SecureBootMode].SetupMode,\r
+             sizeof(UINT8),\r
+             EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
+             );\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // If "SecureBootEnable" variable exists, then update "SecureBoot" variable.\r
+  // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in User Mode or Deployed Mode, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.\r
+  // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.\r
+  //\r
+  SecureBootEnable = SECURE_BOOT_DISABLE;\r
+  Status = AuthServiceInternalFindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID **)&Data, &DataSize);\r
+  if (!EFI_ERROR(Status)) {\r
+    if (!IsPkPresent) {\r
+      //\r
+      // PK is cleared in runtime. "SecureBootMode" is not updated before reboot\r
+      // Delete "SecureBootMode"\r
+      //\r
+      Status = AuthServiceInternalUpdateVariable (\r
+                 EFI_SECURE_BOOT_ENABLE_NAME,\r
+                 &gEfiSecureBootEnableDisableGuid,\r
+                 &SecureBootEnable,\r
+                 0,\r
+                 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
+                 );\r
+    } else {\r
+      SecureBootEnable = *Data;\r
+    }\r
+  } else if ((SecureBootMode == SecureBootModeTypeUserMode) || (SecureBootMode == SecureBootModeTypeDeployedMode)) {\r
+    //\r
+    // "SecureBootEnable" not exist, initialize it in User Mode or Deployed Mode.\r
+    //\r
+    SecureBootEnable = SECURE_BOOT_ENABLE;\r
+    Status = AuthServiceInternalUpdateVariable (\r
+               EFI_SECURE_BOOT_ENABLE_NAME,\r
+               &gEfiSecureBootEnableDisableGuid,\r
+               &SecureBootEnable,\r
+               sizeof (UINT8),\r
+               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Create "SecureBoot" variable with BS+RT attribute set.\r
+  //\r
+  if ((SecureBootEnable == SECURE_BOOT_ENABLE) \r
+  && ((SecureBootMode == SecureBootModeTypeUserMode) || (SecureBootMode == SecureBootModeTypeDeployedMode))) {\r
+    SecureBoot = SECURE_BOOT_MODE_ENABLE;\r
+  } else {\r
+    SecureBoot = SECURE_BOOT_MODE_DISABLE;\r
+  }\r
+  Status = AuthServiceInternalUpdateVariable (\r
+             EFI_SECURE_BOOT_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &SecureBoot,\r
+             sizeof (UINT8),\r
+             EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
+             );\r
+\r
+  DEBUG ((EFI_D_INFO, "SecureBootMode is %x\n", SecureBootMode));\r
+  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME, SecureBoot));\r
+  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable));\r
+\r
+  //\r
+  // Save SecureBootMode in global space\r
+  //\r
+  mSecureBootMode = SecureBootMode;\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Update SecureBootMode variable.\r
+\r
+  @param[in] NewMode                New Secure Boot Mode.\r
+\r
+  @retval EFI_SUCCESS               The initialization operation is successful.\r
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateSecureBootMode(\r
+  IN  SECURE_BOOT_MODE_TYPE  NewMode\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+  //\r
+  // Update "SecureBootMode" variable to new Secure Boot Mode\r
+  //\r
+  Status = AuthServiceInternalUpdateVariable (\r
+             EDKII_SECURE_BOOT_MODE_NAME,\r
+             &gEdkiiSecureBootModeGuid,\r
+             &NewMode,\r
+             sizeof (UINT8),\r
+             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
+             );\r
+\r
+  if (!EFI_ERROR(Status)) {\r
+    DEBUG((EFI_D_INFO, "SecureBootMode Update to %x\n", NewMode));\r
+    mSecureBootMode = NewMode;\r
+  } else {\r
+    DEBUG((EFI_D_ERROR, "SecureBootMode Update failure %x\n", Status));\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Current secure boot mode is AuditMode. This function performs secure boot mode transition\r
+  to a new mode.\r
+\r
+  @param[in] NewMode                New Secure Boot Mode.\r
+\r
+  @retval EFI_SUCCESS               The initialization operation is successful.\r
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+\r
+**/\r
+EFI_STATUS\r
+TransitionFromAuditMode(\r
+  IN  SECURE_BOOT_MODE_TYPE               NewMode\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       *AuditVarData;\r
+  UINT8       *DeployedVarData;\r
+  UINT8       *SetupVarData;\r
+  UINT8       *SecureBootVarData;\r
+  UINT8       SecureBootEnable;\r
+  UINTN       DataSize;\r
+\r
+  //\r
+  // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver\r
+  // they can be RW. but can't be deleted. so they can always be found.\r
+  //\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_AUDIT_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &AuditVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_DEPLOYED_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &DeployedVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_SETUP_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &SetupVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_SECURE_BOOT_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &SecureBootVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  //\r
+  // Make Secure Boot Mode transition ATOMIC\r
+  // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow.\r
+  // other tranisition logic are all memory operations.\r
+  //\r
+  Status = UpdateSecureBootMode(NewMode);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status));\r
+  }\r
+\r
+  if (NewMode == SecureBootModeTypeDeployedMode) {\r
+    //\r
+    // Since PK is enrolled, can't rollback, always update SecureBootMode in memory\r
+    //\r
+    mSecureBootMode = NewMode;\r
+    Status          = EFI_SUCCESS;\r
+\r
+    //\r
+    // AuditMode ----> DeployedMode\r
+    // Side Effects\r
+    //   AuditMode =: 0 / DeployedMode := 1 / SetupMode := 0\r
+    //\r
+    // Update the value of AuditMode variable by a simple mem copy, this could avoid possible\r
+    // variable storage reclaim at runtime.\r
+    //\r
+    CopyMem (AuditVarData, &mSecureBootState[NewMode].AuditMode, sizeof(UINT8));\r
+    //\r
+    // Update the value of DeployedMode variable by a simple mem copy, this could avoid possible\r
+    // variable storage reclaim at runtime.\r
+    //\r
+    CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8));\r
+    //\r
+    // Update the value of SetupMode variable by a simple mem copy, this could avoid possible\r
+    // variable storage reclaim at runtime.\r
+    //\r
+    CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8));\r
+\r
+    if (mAuthVarLibContextIn->AtRuntime ()) {\r
+      //\r
+      // SecureBoot Variable indicates whether the platform firmware is operating\r
+      // in Secure boot mode (1) or not (0), so we should not change SecureBoot\r
+      // Variable in runtime.\r
+      //\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible\r
+    // variable storage reclaim at runtime.\r
+    //\r
+    CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8));\r
+\r
+    //\r
+    // Create "SecureBootEnable" variable  as secure boot is enabled.\r
+    //\r
+    SecureBootEnable = SECURE_BOOT_ENABLE;\r
+    AuthServiceInternalUpdateVariable (\r
+      EFI_SECURE_BOOT_ENABLE_NAME,\r
+      &gEfiSecureBootEnableDisableGuid,\r
+      &SecureBootEnable,\r
+      sizeof (SecureBootEnable),\r
+      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
+      );\r
+  } else {\r
+    DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeAuditMode, NewMode));\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Current secure boot mode is DeployedMode. This function performs secure boot mode transition\r
+  to a new mode.\r
+\r
+  @param[in] NewMode                New Secure Boot Mode.\r
+\r
+  @retval EFI_SUCCESS               The initialization operation is successful.\r
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+\r
+**/\r
+EFI_STATUS\r
+TransitionFromDeployedMode(\r
+  IN  SECURE_BOOT_MODE_TYPE               NewMode\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       *DeployedVarData;\r
+  UINT8       *SetupVarData;\r
+  UINT8       *SecureBootVarData;\r
+  UINT8       SecureBootEnable;\r
+  UINTN       DataSize;\r
+\r
+  //\r
+  // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver\r
+  // they can be RW. but can't be deleted. so they can always be found.\r
+  //\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_DEPLOYED_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &DeployedVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_SETUP_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &SetupVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_SECURE_BOOT_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &SecureBootVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  //\r
+  // Make Secure Boot Mode transition ATOMIC\r
+  // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow.\r
+  // other tranisition logic are all memory operations.\r
+  //\r
+  Status = UpdateSecureBootMode(NewMode);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status));\r
+  }\r
+\r
+  switch(NewMode) {\r
+    case SecureBootModeTypeUserMode:\r
+      //\r
+      // DeployedMode ----> UserMode\r
+      // Side Effects\r
+      //   DeployedMode := 0\r
+      //\r
+      // Platform Specific DeployedMode clear. UpdateSecureBootMode fails and no other variables are updated before. rollback this transition\r
+      //\r
+      if (EFI_ERROR(Status)) {\r
+        return Status;\r
+      }\r
+      CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8));\r
+\r
+      break;\r
+\r
+    case SecureBootModeTypeSetupMode:\r
+      //\r
+      // Since PK is processed before, can't rollback, still update SecureBootMode in memory\r
+      //\r
+      mSecureBootMode = NewMode;\r
+      Status          = EFI_SUCCESS;\r
+\r
+      //\r
+      // DeployedMode ----> SetupMode\r
+      //\r
+      // Platform Specific PKpub clear or Delete Pkpub\r
+      // Side Effects\r
+      //   DeployedMode := 0 / SetupMode := 1 / SecureBoot := 0\r
+      //\r
+      // Update the value of DeployedMode variable by a simple mem copy, this could avoid possible\r
+      // variable storage reclaim at runtime.\r
+      //\r
+      CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8));\r
+      //\r
+      // Update the value of SetupMode variable by a simple mem copy, this could avoid possible\r
+      // variable storage reclaim at runtime.\r
+      //\r
+      CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8));\r
+\r
+      if (mAuthVarLibContextIn->AtRuntime ()) {\r
+        //\r
+        // SecureBoot Variable indicates whether the platform firmware is operating\r
+        // in Secure boot mode (1) or not (0), so we should not change SecureBoot\r
+        // Variable in runtime.\r
+        //\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible\r
+      // variable storage reclaim at runtime.\r
+      //\r
+      CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8));\r
+\r
+      //\r
+      // Delete the "SecureBootEnable" variable as secure boot is Disabled.\r
+      //\r
+      SecureBootEnable = SECURE_BOOT_DISABLE;\r
+      AuthServiceInternalUpdateVariable (\r
+        EFI_SECURE_BOOT_ENABLE_NAME,\r
+        &gEfiSecureBootEnableDisableGuid,\r
+        &SecureBootEnable,\r
+        0,\r
+        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
+        );\r
+      break;\r
+\r
+    default:\r
+      DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeDeployedMode, NewMode));\r
+      ASSERT(FALSE);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Current secure boot mode is UserMode. This function performs secure boot mode transition\r
+  to a new mode.\r
+\r
+  @param[in] NewMode                New Secure Boot Mode.\r
+\r
+  @retval EFI_SUCCESS               The initialization operation is successful.\r
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+\r
+**/\r
+EFI_STATUS\r
+TransitionFromUserMode(\r
+  IN  SECURE_BOOT_MODE_TYPE               NewMode\r
+  )\r
+{\r
+  EFI_STATUS   Status;\r
+  UINT8        *AuditVarData;\r
+  UINT8        *DeployedVarData;\r
+  UINT8        *SetupVarData;\r
+  UINT8        *PkVarData;\r
+  UINT8        *SecureBootVarData;\r
+  UINT8        SecureBootEnable;\r
+  UINTN        DataSize;\r
+  VARIABLE_ENTRY_CONSISTENCY  VariableEntry;\r
+\r
+  //\r
+  // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver\r
+  // they can be RW. but can't be deleted. so they can always be found.\r
+  //\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_AUDIT_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &AuditVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_DEPLOYED_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &DeployedVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_SETUP_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &SetupVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_SECURE_BOOT_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &SecureBootVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  //\r
+  // Make Secure Boot Mode transition ATOMIC\r
+  // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow. \r
+  // Other tranisition logic are all memory operations and PK delete is assumed to be always successful.\r
+  //\r
+  if (NewMode != SecureBootModeTypeAuditMode) {\r
+    Status = UpdateSecureBootMode(NewMode);\r
+    if (EFI_ERROR(Status)) {\r
+      DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status));\r
+    }\r
+  } else {\r
+    //\r
+    // UserMode -----> AuditMode. Check RemainingSpace for SecureBootMode var first.\r
+    // Will update SecureBootMode after DeletePK logic\r
+    //\r
+    VariableEntry.VariableSize = sizeof(UINT8);\r
+    VariableEntry.Guid         = &gEdkiiSecureBootModeGuid;\r
+    VariableEntry.Name         = EDKII_SECURE_BOOT_MODE_NAME;\r
+    if (!mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry, NULL)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+\r
+  switch(NewMode) {\r
+    case SecureBootModeTypeDeployedMode:\r
+      //\r
+      // UpdateSecureBootMode fails and no other variables are updated before. rollback this transition\r
+      //\r
+      if (EFI_ERROR(Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // UserMode ----> DeployedMode\r
+      // Side Effects\r
+      //   DeployedMode := 1\r
+      //\r
+      CopyMem (DeployedVarData, &mSecureBootState[NewMode].DeployedMode, sizeof(UINT8));\r
+      break;\r
+\r
+    case SecureBootModeTypeAuditMode:\r
+      //\r
+      // UserMode ----> AuditMode\r
+      // Side Effects\r
+      //   Delete PKpub / SetupMode := 1 / SecureBoot := 0\r
+      //\r
+      // Delete PKpub without verification. Should always succeed.\r
+      //\r
+      PkVarData = NULL;\r
+      Status = AuthServiceInternalUpdateVariable (\r
+                 EFI_PLATFORM_KEY_NAME,\r
+                 &gEfiGlobalVariableGuid,\r
+                 PkVarData,\r
+                 0,\r
+                 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\r
+                 );\r
+      if (EFI_ERROR(Status)) {\r
+        DEBUG((EFI_D_ERROR, "UserMode -> AuditMode. Delete PK fail %x\n", Status));\r
+        ASSERT(FALSE);\r
+      }\r
+\r
+      //\r
+      // Update Private NV SecureBootMode Variable\r
+      //\r
+      Status = UpdateSecureBootMode(NewMode);\r
+      if (EFI_ERROR(Status)) {\r
+        //\r
+        // Since PK is deleted successfully, Doesn't break, continue to update other variable.\r
+        //\r
+        DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status));\r
+      }\r
+      CopyMem (AuditVarData, &mSecureBootState[NewMode].AuditMode, sizeof(UINT8));\r
+\r
+      //\r
+      // Fall into SetupMode logic\r
+      //\r
+    case SecureBootModeTypeSetupMode:\r
+      //\r
+      // Since PK is deleted before , can't rollback, still update SecureBootMode in memory\r
+      //\r
+      mSecureBootMode = NewMode;\r
+      Status          = EFI_SUCCESS;\r
+\r
+      //\r
+      // UserMode ----> SetupMode\r
+      //  Side Effects\r
+      //    DeployedMode :=0 / SetupMode :=1 / SecureBoot :=0\r
+      //\r
+      // Update the value of SetupMode variable by a simple mem copy, this could avoid possible\r
+      // variable storage reclaim at runtime.\r
+      //\r
+      CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8));\r
+\r
+      if (mAuthVarLibContextIn->AtRuntime ()) {\r
+        //\r
+        // SecureBoot Variable indicates whether the platform firmware is operating\r
+        // in Secure boot mode (1) or not (0), so we should not change SecureBoot\r
+        // Variable in runtime.\r
+        //\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible\r
+      // variable storage reclaim at runtime.\r
+      //\r
+      CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8));\r
+\r
+      //\r
+      // Delete the "SecureBootEnable" variable as secure boot is Disabled.\r
+      //\r
+      SecureBootEnable = SECURE_BOOT_DISABLE;\r
+      AuthServiceInternalUpdateVariable (\r
+        EFI_SECURE_BOOT_ENABLE_NAME,\r
+        &gEfiSecureBootEnableDisableGuid,\r
+        &SecureBootEnable,\r
+        0,\r
+        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
+        );\r
+\r
+      break;\r
+\r
+    default:\r
+      DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeUserMode, NewMode));\r
+      ASSERT(FALSE);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Current secure boot mode is SetupMode. This function performs secure boot mode transition\r
+  to a new mode.\r
+\r
+  @param[in] NewMode                New Secure Boot Mode.\r
+\r
+  @retval EFI_SUCCESS               The initialization operation is successful.\r
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+\r
+**/\r
+EFI_STATUS\r
+TransitionFromSetupMode(\r
+  IN  SECURE_BOOT_MODE_TYPE              NewMode\r
+  )\r
+{\r
+  EFI_STATUS   Status;\r
+  UINT8        *AuditVarData;\r
+  UINT8        *SetupVarData;\r
+  UINT8        *SecureBootVarData;\r
+  UINT8        SecureBootEnable;\r
+  UINTN        DataSize;\r
+\r
+  //\r
+  // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver\r
+  // they can be RW. but can't be deleted. so they can always be found.\r
+  //\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_AUDIT_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &AuditVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_SETUP_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &SetupVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  Status = AuthServiceInternalFindVariable (\r
+             EFI_SECURE_BOOT_MODE_NAME,\r
+             &gEfiGlobalVariableGuid,\r
+             &SecureBootVarData,\r
+             &DataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  //\r
+  // Make Secure Boot Mode transition ATOMIC\r
+  // Update Private NV SecureBootMode Variable first, because it may fail due to NV range overflow.\r
+  // Other tranisition logic are all memory operations and PK delete is assumed to be always successful.\r
+  //\r
+  Status = UpdateSecureBootMode(NewMode);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG((EFI_D_ERROR, "Update SecureBootMode Variable fail %x\n", Status));\r
+  }\r
+\r
+  switch(NewMode) {\r
+    case SecureBootModeTypeAuditMode:\r
+      //\r
+      // UpdateSecureBootMode fails and no other variables are updated before. rollback this transition\r
+      //\r
+      if (EFI_ERROR(Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // SetupMode ----> AuditMode\r
+      // Side Effects\r
+      //   AuditMode := 1\r
+      //\r
+      // Update the value of AuditMode variable by a simple mem copy, this could avoid possible\r
+      // variable storage reclaim at runtime.\r
+      //\r
+      CopyMem (AuditVarData, &mSecureBootState[NewMode].AuditMode, sizeof(UINT8));\r
+      break;\r
+\r
+    case SecureBootModeTypeUserMode:\r
+      //\r
+      // Since PK is enrolled before, can't rollback, still update SecureBootMode in memory\r
+      //\r
+      mSecureBootMode = NewMode;\r
+      Status          = EFI_SUCCESS;\r
+\r
+      //\r
+      // SetupMode ----> UserMode\r
+      // Side Effects\r
+      //   SetupMode := 0 / SecureBoot := 1\r
+      //\r
+      // Update the value of AuditMode variable by a simple mem copy, this could avoid possible\r
+      // variable storage reclaim at runtime.\r
+      //\r
+      CopyMem (SetupVarData, &mSecureBootState[NewMode].SetupMode, sizeof(UINT8));\r
+\r
+      if (mAuthVarLibContextIn->AtRuntime ()) {\r
+        //\r
+        // SecureBoot Variable indicates whether the platform firmware is operating\r
+        // in Secure boot mode (1) or not (0), so we should not change SecureBoot\r
+        // Variable in runtime.\r
+        //\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Update the value of SecureBoot variable by a simple mem copy, this could avoid possible\r
+      // variable storage reclaim at runtime.\r
+      //\r
+      CopyMem (SecureBootVarData, &mSecureBootState[NewMode].SecureBoot, sizeof(UINT8));\r
+\r
+      //\r
+      // Create the "SecureBootEnable" variable as secure boot is enabled.\r
+      //\r
+      SecureBootEnable = SECURE_BOOT_ENABLE;\r
+      AuthServiceInternalUpdateVariable (\r
+        EFI_SECURE_BOOT_ENABLE_NAME,\r
+        &gEfiSecureBootEnableDisableGuid,\r
+        &SecureBootEnable,\r
+        sizeof (SecureBootEnable),\r
+        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
+        );\r
+      break;\r
+\r
+    default:\r
+      DEBUG((EFI_D_ERROR, "Invalid state tranition from %x to %x\n", SecureBootModeTypeSetupMode, NewMode));\r
+      ASSERT(FALSE);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function performs main secure boot mode transition logic.\r
 \r
-  @param[in] VariableName           Name of variable.\r
-  @param[in] VendorGuid             Guid of variable.\r
-  @param[in] Data                   Data pointer.\r
-  @param[in] DataSize               Size of Data.\r
-  @param[in] Attributes             Attribute value of the variable.\r
-  @param[in] TimeStamp              Value of associated TimeStamp.\r
+  @param[in] CurMode                Current Secure Boot Mode.\r
+  @param[in] NewMode                New Secure Boot Mode.\r
 \r
-  @retval EFI_SUCCESS               The update operation is success.\r
-  @retval EFI_INVALID_PARAMETER     Invalid parameter.\r
-  @retval EFI_WRITE_PROTECTED       Variable is write-protected.\r
+  @retval EFI_SUCCESS               The initialization operation is successful.\r
   @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+  @retval EFI_INVALID_PARAMETER     The Current Secure Boot Mode is wrong.\r
 \r
 **/\r
 EFI_STATUS\r
-AuthServiceInternalUpdateVariableWithTimeStamp (\r
-  IN CHAR16             *VariableName,\r
-  IN EFI_GUID           *VendorGuid,\r
-  IN VOID               *Data,\r
-  IN UINTN              DataSize,\r
-  IN UINT32             Attributes,\r
-  IN EFI_TIME           *TimeStamp\r
+SecureBootModeTransition(\r
+  IN  SECURE_BOOT_MODE_TYPE  CurMode,\r
+  IN  SECURE_BOOT_MODE_TYPE  NewMode\r
   )\r
 {\r
-  EFI_STATUS            FindStatus;\r
-  VOID                  *OrgData;\r
-  UINTN                 OrgDataSize;\r
-  AUTH_VARIABLE_INFO    AuthVariableInfo;\r
-\r
-  FindStatus = AuthServiceInternalFindVariable (\r
-                 VariableName,\r
-                 VendorGuid,\r
-                 &OrgData,\r
-                 &OrgDataSize\r
-                 );\r
+  EFI_STATUS Status;\r
 \r
   //\r
-  // EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable\r
+  // SecureBootMode transition\r
   //\r
-  if (!EFI_ERROR (FindStatus) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0)) {\r
-    if ((CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&\r
-        ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) ||\r
-        (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0))) ||\r
-        (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) {\r
-      //\r
-      // For variables with formatted as EFI_SIGNATURE_LIST, the driver shall not perform an append of\r
-      // EFI_SIGNATURE_DATA values that are already part of the existing variable value.\r
-      //\r
-      FilterSignatureList (\r
-        OrgData,\r
-        OrgDataSize,\r
-        Data,\r
-        &DataSize\r
-        );\r
-    }\r
+  switch (CurMode) {\r
+    case SecureBootModeTypeUserMode:\r
+      Status = TransitionFromUserMode(NewMode);\r
+      break;\r
+\r
+    case SecureBootModeTypeSetupMode:\r
+      Status = TransitionFromSetupMode(NewMode);\r
+      break;\r
+\r
+    case SecureBootModeTypeAuditMode:\r
+      Status = TransitionFromAuditMode(NewMode);\r
+      break;\r
+\r
+    case SecureBootModeTypeDeployedMode:\r
+      Status = TransitionFromDeployedMode(NewMode);\r
+      break;\r
+\r
+    default:\r
+      Status = EFI_INVALID_PARAMETER;\r
+      ASSERT(FALSE);\r
   }\r
 \r
-  ZeroMem (&AuthVariableInfo, sizeof (AuthVariableInfo));\r
-  AuthVariableInfo.VariableName = VariableName;\r
-  AuthVariableInfo.VendorGuid = VendorGuid;\r
-  AuthVariableInfo.Data = Data;\r
-  AuthVariableInfo.DataSize = DataSize;\r
-  AuthVariableInfo.Attributes = Attributes;\r
-  AuthVariableInfo.TimeStamp = TimeStamp;\r
-  return mAuthVarLibContextIn->UpdateVariable (\r
-           &AuthVariableInfo\r
-           );\r
+  return Status;\r
+\r
 }\r
 \r
 /**\r
@@ -597,129 +1553,6 @@ Done:
   }\r
 }\r
 \r
-/**\r
-  Update platform mode.\r
-\r
-  @param[in]      Mode                    SETUP_MODE or USER_MODE.\r
-\r
-  @return EFI_INVALID_PARAMETER           Invalid parameter.\r
-  @return EFI_SUCCESS                     Update platform mode successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-UpdatePlatformMode (\r
-  IN  UINT32                    Mode\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  VOID                    *Data;\r
-  UINTN                   DataSize;\r
-  UINT8                   SecureBootMode;\r
-  UINT8                   SecureBootEnable;\r
-  UINTN                   VariableDataSize;\r
-\r
-  Status = AuthServiceInternalFindVariable (\r
-             EFI_SETUP_MODE_NAME,\r
-             &gEfiGlobalVariableGuid,\r
-             &Data,\r
-             &DataSize\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Update the value of SetupMode variable by a simple mem copy, this could avoid possible\r
-  // variable storage reclaim at runtime.\r
-  //\r
-  mPlatformMode = (UINT8) Mode;\r
-  CopyMem (Data, &mPlatformMode, sizeof(UINT8));\r
-\r
-  if (mAuthVarLibContextIn->AtRuntime ()) {\r
-    //\r
-    // SecureBoot Variable indicates whether the platform firmware is operating\r
-    // in Secure boot mode (1) or not (0), so we should not change SecureBoot\r
-    // Variable in runtime.\r
-    //\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Check "SecureBoot" variable's existence.\r
-  // If it doesn't exist, firmware has no capability to perform driver signing verification,\r
-  // then set "SecureBoot" to 0.\r
-  //\r
-  Status = AuthServiceInternalFindVariable (\r
-             EFI_SECURE_BOOT_MODE_NAME,\r
-             &gEfiGlobalVariableGuid,\r
-             &Data,\r
-             &DataSize\r
-             );\r
-  //\r
-  // If "SecureBoot" variable exists, then check "SetupMode" variable update.\r
-  // If "SetupMode" variable is USER_MODE, "SecureBoot" variable is set to 1.\r
-  // If "SetupMode" variable is SETUP_MODE, "SecureBoot" variable is set to 0.\r
-  //\r
-  if (EFI_ERROR (Status)) {\r
-    SecureBootMode = SECURE_BOOT_MODE_DISABLE;\r
-  } else {\r
-    if (mPlatformMode == USER_MODE) {\r
-      SecureBootMode = SECURE_BOOT_MODE_ENABLE;\r
-    } else if (mPlatformMode == SETUP_MODE) {\r
-      SecureBootMode = SECURE_BOOT_MODE_DISABLE;\r
-    } else {\r
-      return EFI_NOT_FOUND;\r
-    }\r
-  }\r
-\r
-  Status  = AuthServiceInternalUpdateVariable (\r
-              EFI_SECURE_BOOT_MODE_NAME,\r
-              &gEfiGlobalVariableGuid,\r
-              &SecureBootMode,\r
-              sizeof(UINT8),\r
-              EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
-              );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Check "SecureBootEnable" variable's existence. It can enable/disable secure boot feature.\r
-  //\r
-  Status = AuthServiceInternalFindVariable (\r
-             EFI_SECURE_BOOT_ENABLE_NAME,\r
-             &gEfiSecureBootEnableDisableGuid,\r
-             &Data,\r
-             &DataSize\r
-             );\r
-\r
-  if (SecureBootMode == SECURE_BOOT_MODE_ENABLE) {\r
-    //\r
-    // Create the "SecureBootEnable" variable as secure boot is enabled.\r
-    //\r
-    SecureBootEnable = SECURE_BOOT_ENABLE;\r
-    VariableDataSize = sizeof (SecureBootEnable);\r
-  } else {\r
-    //\r
-    // Delete the "SecureBootEnable" variable if this variable exist as "SecureBoot"\r
-    // variable is not in secure boot state.\r
-    //\r
-    if (EFI_ERROR (Status)) {\r
-      return EFI_SUCCESS;\r
-    }\r
-    SecureBootEnable = SECURE_BOOT_DISABLE;\r
-    VariableDataSize = 0;\r
-  }\r
-\r
-  Status = AuthServiceInternalUpdateVariable (\r
-             EFI_SECURE_BOOT_ENABLE_NAME,\r
-             &gEfiSecureBootEnableDisableGuid,\r
-             &SecureBootEnable,\r
-             VariableDataSize,\r
-             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
-             );\r
-  return Status;\r
-}\r
 \r
 /**\r
   Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK/db/dbx/dbt variable.\r
@@ -879,6 +1712,121 @@ VendorKeyIsModified (
            );\r
 }\r
 \r
+/**\r
+  Process Secure Boot Mode variable.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  This function may be invoked in SMM mode, and datasize and data are external input.\r
+  This function will do basic validation, before parse the data.\r
+  This function will parse the authentication carefully to avoid security issues, like\r
+  buffer overflow, integer overflow.\r
+  This function will check attribute carefully to avoid authentication bypass.\r
+\r
+  @param[in]  VariableName                Name of Variable to be found.\r
+  @param[in]  VendorGuid                  Variable vendor GUID.\r
+  @param[in]  Data                        Data pointer.\r
+  @param[in]  DataSize                    Size of Data found. If size is less than the\r
+                                          data, this value contains the required size.\r
+  @param[in]  Attributes                  Attribute value of the variable\r
+\r
+  @return EFI_INVALID_PARAMETER           Invalid parameter\r
+  @return EFI_SECURITY_VIOLATION          The variable does NOT pass the validation\r
+                                          check carried out by the firmware.\r
+  @return EFI_WRITE_PROTECTED             Variable is Read-Only.\r
+  @return EFI_SUCCESS                     Variable passed validation successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessSecureBootModeVar (\r
+  IN  CHAR16         *VariableName,\r
+  IN  EFI_GUID       *VendorGuid,\r
+  IN  VOID           *Data,\r
+  IN  UINTN          DataSize,\r
+  IN  UINT32         Attributes OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  UINT8         *VarData;\r
+  UINTN         VarDataSize;\r
+\r
+  //\r
+  // Check "AuditMode", "DeployedMode" Variable ReadWrite Attributes\r
+  //  if in Runtime,  Always RO\r
+  //  if in Boottime, Depends on current Secure Boot Mode\r
+  //\r
+  if (mAuthVarLibContextIn->AtRuntime()) {\r
+    return EFI_WRITE_PROTECTED;\r
+  }\r
+\r
+  //\r
+  // Delete not OK\r
+  //\r
+  if ((DataSize != sizeof(UINT8)) || (Attributes == 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (StrCmp (VariableName, EFI_AUDIT_MODE_NAME) == 0) {\r
+    if(mSecureBootState[mSecureBootMode].IsAuditModeRO) {\r
+      return EFI_WRITE_PROTECTED;\r
+    }\r
+  } else {\r
+    //\r
+    // Platform specific deployedMode clear. Set DeployedMode = RW\r
+    //\r
+    if (!InCustomMode() || !UserPhysicalPresent() || mSecureBootMode != SecureBootModeTypeDeployedMode) {\r
+      if(mSecureBootState[mSecureBootMode].IsDeployedModeRO) {\r
+        return EFI_WRITE_PROTECTED;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (*(UINT8 *)Data != 0 && *(UINT8 *)Data != 1) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // AuditMode/DeployedMode/SetupMode/SecureBoot are all NON_NV variable maintained by Variable driver\r
+  // they can be RW. but can't be deleted. so they can always be found.\r
+  //\r
+  Status = AuthServiceInternalFindVariable (\r
+             VariableName,\r
+             VendorGuid,\r
+             &VarData,\r
+             &VarDataSize\r
+             );\r
+  if (EFI_ERROR(Status)) {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  //\r
+  // If AuditMode/DeployedMode is assigned same value. Simply return EFI_SUCCESS\r
+  //\r
+  if (*VarData == *(UINT8 *)Data) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Perform SecureBootMode transition\r
+  //\r
+  if (StrCmp (VariableName, EFI_AUDIT_MODE_NAME) == 0) {\r
+    DEBUG((EFI_D_INFO, "Current SecureBootMode %x Transfer to SecureBootMode %x\n", mSecureBootMode, SecureBootModeTypeAuditMode));\r
+    return SecureBootModeTransition(mSecureBootMode, SecureBootModeTypeAuditMode);\r
+  } else if (StrCmp (VariableName, EFI_DEPLOYED_MODE_NAME) == 0) {\r
+    if (mSecureBootMode == SecureBootModeTypeDeployedMode) {\r
+      //\r
+      // Platform specific DeployedMode clear. InCustomMode() && UserPhysicalPresent() is checked before\r
+      //\r
+      DEBUG((EFI_D_INFO, "Current SecureBootMode %x. Transfer to SecureBootMode %x\n", mSecureBootMode, SecureBootModeTypeUserMode));\r
+      return SecureBootModeTransition(mSecureBootMode, SecureBootModeTypeUserMode);\r
+    } else {\r
+      DEBUG((EFI_D_INFO, "Current SecureBootMode %x. Transfer to SecureBootMode %x\n", mSecureBootMode, SecureBootModeTypeDeployedMode));\r
+      return SecureBootModeTransition(mSecureBootMode, SecureBootModeTypeDeployedMode);\r
+    }\r
+  }\r
+\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
 /**\r
   Process variable with platform key for verification.\r
 \r
@@ -917,6 +1865,7 @@ ProcessVarWithPk (
   BOOLEAN                     Del;\r
   UINT8                       *Payload;\r
   UINTN                       PayloadSize;\r
+  VARIABLE_ENTRY_CONSISTENCY  VariableEntry[2];\r
 \r
   if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0 ||\r
       (Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {\r
@@ -927,19 +1876,55 @@ ProcessVarWithPk (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  //\r
+  // Init state of Del. State may change due to secure check\r
+  //\r
   Del = FALSE;\r
-  if ((InCustomMode() && UserPhysicalPresent()) || (mPlatformMode == SETUP_MODE && !IsPk)) {\r
-    Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);\r
-    PayloadSize = DataSize - AUTHINFO2_SIZE (Data);\r
-    if (PayloadSize == 0) {\r
-      Del = TRUE;\r
-    }\r
+  Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);\r
+  PayloadSize = DataSize - AUTHINFO2_SIZE (Data);\r
+  if (PayloadSize == 0) {\r
+    Del = TRUE;\r
+  }\r
+\r
+  //\r
+  // Check the variable space for both PKpub and SecureBootMode variable.\r
+  //\r
+  VariableEntry[0].VariableSize = PayloadSize;\r
+  VariableEntry[0].Guid         = &gEfiGlobalVariableGuid;\r
+  VariableEntry[0].Name         = EFI_PLATFORM_KEY_NAME;\r
+\r
+  VariableEntry[1].VariableSize = sizeof(UINT8);\r
+  VariableEntry[1].Guid         = &gEdkiiSecureBootModeGuid;\r
+  VariableEntry[1].Name         = EDKII_SECURE_BOOT_MODE_NAME;\r
+\r
+  if ((InCustomMode() && UserPhysicalPresent()) || \r
+      (((mSecureBootMode == SecureBootModeTypeSetupMode) || (mSecureBootMode == SecureBootModeTypeAuditMode)) && !IsPk)) {\r
 \r
     Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, PayloadSize);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
 \r
+    //\r
+    // If delete PKpub, only check for "SecureBootMode" only\r
+    // if update / add PKpub, check both NewPKpub & "SecureBootMode"\r
+    //\r
+    if (IsPk) {\r
+      //\r
+      // Delete PKpub\r
+      //\r
+      if (Del && ((mSecureBootMode == SecureBootModeTypeUserMode) || (mSecureBootMode == SecureBootModeTypeDeployedMode)) \r
+          && !mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[1], NULL)){\r
+        return EFI_OUT_OF_RESOURCES;\r
+      //\r
+      // Add PKpub\r
+      //\r
+      } else if (!Del && ((mSecureBootMode == SecureBootModeTypeSetupMode) || (mSecureBootMode == SecureBootModeTypeAuditMode))\r
+                 && !mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+    }\r
+\r
     Status = AuthServiceInternalUpdateVariableWithTimeStamp (\r
                VariableName,\r
                VendorGuid,\r
@@ -952,10 +1937,17 @@ ProcessVarWithPk (
       return Status;\r
     }\r
 \r
-    if ((mPlatformMode != SETUP_MODE) || IsPk) {\r
+    if (((mSecureBootMode != SecureBootModeTypeSetupMode) && (mSecureBootMode != SecureBootModeTypeAuditMode)) || IsPk) {\r
       Status = VendorKeyIsModified ();\r
     }\r
-  } else if (mPlatformMode == USER_MODE) {\r
+  } else if (mSecureBootMode == SecureBootModeTypeUserMode || mSecureBootMode == SecureBootModeTypeDeployedMode) {\r
+    //\r
+    // If delete PKpub, check "SecureBootMode" only\r
+    //\r
+    if (IsPk && Del && !mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[1], NULL)){\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
     //\r
     // Verify against X509 Cert in PK database.\r
     //\r
@@ -970,8 +1962,19 @@ ProcessVarWithPk (
                );\r
   } else {\r
     //\r
+    // SetupMode or  AuditMode to add PK\r
     // Verify against the certificate in data payload.\r
     //\r
+    //\r
+    // Check PKpub & SecureBootMode variable space consistency\r
+    //\r
+    if (!mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {\r
+      //\r
+      // No enough variable space to set PK successfully.\r
+      //\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
     Status = VerifyTimeBasedPayloadAndUpdate (\r
                VariableName,\r
                VendorGuid,\r
@@ -984,16 +1987,30 @@ ProcessVarWithPk (
   }\r
 \r
   if (!EFI_ERROR(Status) && IsPk) {\r
-    if (mPlatformMode == SETUP_MODE && !Del) {\r
-      //\r
-      // If enroll PK in setup mode, need change to user mode.\r
-      //\r
-      Status = UpdatePlatformMode (USER_MODE);\r
-    } else if (mPlatformMode == USER_MODE && Del){\r
-      //\r
-      // If delete PK in user mode, need change to setup mode.\r
-      //\r
-      Status = UpdatePlatformMode (SETUP_MODE);\r
+    //\r
+    // Delete or Enroll PK causes SecureBootMode change\r
+    //\r
+    if (!Del) {\r
+      if (mSecureBootMode == SecureBootModeTypeSetupMode) {\r
+        //\r
+        // If enroll PK in setup mode,  change to user mode.\r
+        //\r
+        Status = SecureBootModeTransition (mSecureBootMode, SecureBootModeTypeUserMode);\r
+      } else if (mSecureBootMode == SecureBootModeTypeAuditMode) {\r
+        //\r
+        // If enroll PK in Audit mode,  change to Deployed mode.\r
+        //\r
+        Status = SecureBootModeTransition (mSecureBootMode, SecureBootModeTypeDeployedMode);\r
+      } else {\r
+        DEBUG((EFI_D_INFO, "PK is updated in %x mode. No SecureBootMode change.\n", mSecureBootMode));\r
+      }\r
+    } else {\r
+      if ((mSecureBootMode == SecureBootModeTypeUserMode) || (mSecureBootMode == SecureBootModeTypeDeployedMode)) {\r
+        //\r
+        // If delete PK in User Mode or DeployedMode,  change to Setup Mode.\r
+        //\r
+        Status = SecureBootModeTransition (mSecureBootMode, SecureBootModeTypeSetupMode);\r
+      }\r
     }\r
   }\r
 \r
@@ -1046,7 +2063,8 @@ ProcessVarWithKek (
   }\r
 \r
   Status = EFI_SUCCESS;\r
-  if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) {\r
+  if ((mSecureBootMode == SecureBootModeTypeUserMode || mSecureBootMode == SecureBootModeTypeDeployedMode)\r
+   && !(InCustomMode() && UserPhysicalPresent())) {\r
     //\r
     // Time-based, verify against X509 Cert KEK.\r
     //\r
@@ -1083,7 +2101,7 @@ ProcessVarWithKek (
       return Status;\r
     }\r
 \r
-    if (mPlatformMode != SETUP_MODE) {\r
+    if ((mSecureBootMode != SecureBootModeTypeSetupMode) && (mSecureBootMode != SecureBootModeTypeAuditMode)) {\r
       Status = VendorKeyIsModified ();\r
     }\r
   }\r
index add05c21cce4fe424d9765fb2dc7ffc7fe471a94..ec4b3d97f59f0141e2ef1d04d53fb8f27741386d 100644 (file)
@@ -117,6 +117,54 @@ typedef struct {
 } AUTH_CERT_DB_DATA;\r
 #pragma pack()\r
 \r
+///\r
+/// "SecureBootMode" variable stores current secure boot mode.\r
+/// The value type is SECURE_BOOT_MODE_TYPE.\r
+///\r
+#define EDKII_SECURE_BOOT_MODE_NAME    L"SecureBootMode"\r
+\r
+typedef enum { \r
+  SecureBootModeTypeUserMode,\r
+  SecureBootModeTypeSetupMode,\r
+  SecureBootModeTypeAuditMode,\r
+  SecureBootModeTypeDeployedMode,\r
+  SecureBootModeTypeMax\r
+} SECURE_BOOT_MODE_TYPE;\r
+\r
+//\r
+// Record status info of Customized Secure Boot Mode.\r
+//\r
+typedef struct {\r
+  ///\r
+  /// AuditMode variable value\r
+  ///\r
+  UINT8   AuditMode;\r
+  ///\r
+  /// AuditMode variable RW\r
+  ///\r
+  BOOLEAN IsAuditModeRO;\r
+  ///\r
+  /// DeployedMode variable value\r
+  ///\r
+  UINT8   DeployedMode;\r
+  ///\r
+  /// AuditMode variable RW\r
+  ///\r
+  BOOLEAN IsDeployedModeRO;\r
+  ///\r
+  /// SetupMode variable value\r
+  ///\r
+  UINT8   SetupMode;\r
+  /// \r
+  /// SetupMode is always RO. Skip IsSetupModeRO;              \r
+  ///\r
+\r
+  ///\r
+  /// SecureBoot variable value\r
+  ///\r
+  UINT8   SecureBoot;\r
+} SECURE_BOOT_MODE;\r
+\r
 extern UINT8    *mPubKeyStore;\r
 extern UINT32   mPubKeyNumber;\r
 extern UINT32   mMaxKeyNumber;\r
@@ -130,6 +178,18 @@ extern VOID     *mHashCtx;
 \r
 extern AUTH_VAR_LIB_CONTEXT_IN *mAuthVarLibContextIn;\r
 \r
+/**\r
+  Initialize Secure Boot variables.\r
+\r
+  @retval EFI_SUCCESS               The initialization operation is successful.\r
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+\r
+**/\r
+EFI_STATUS \r
+InitSecureBootVariables (\r
+  VOID\r
+  );\r
+\r
 /**\r
   Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set\r
 \r
@@ -219,6 +279,39 @@ FilterSignatureList (
   IN OUT UINTN      *NewDataSize\r
   );\r
 \r
+/**\r
+  Process Secure Boot Mode variable.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  This function may be invoked in SMM mode, and datasize and data are external input.\r
+  This function will do basic validation, before parse the data.\r
+  This function will parse the authentication carefully to avoid security issues, like\r
+  buffer overflow, integer overflow.\r
+  This function will check attribute carefully to avoid authentication bypass.\r
+\r
+  @param[in]  VariableName                Name of Variable to be found.\r
+  @param[in]  VendorGuid                  Variable vendor GUID.\r
+  @param[in]  Data                        Data pointer.\r
+  @param[in]  DataSize                    Size of Data found. If size is less than the\r
+                                          data, this value contains the required size.\r
+  @param[in]  Attributes                  Attribute value of the variable\r
+\r
+  @return EFI_INVALID_PARAMETER           Invalid parameter\r
+  @return EFI_SECURITY_VIOLATION          The variable does NOT pass the validation\r
+                                          check carried out by the firmware.\r
+  @return EFI_WRITE_PROTECTED             Variable is Read-Only.\r
+  @return EFI_SUCCESS                     Variable passed validation successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessSecureBootModeVar (\r
+  IN  CHAR16         *VariableName,\r
+  IN  EFI_GUID       *VendorGuid,\r
+  IN  VOID           *Data,\r
+  IN  UINTN          DataSize,\r
+  IN  UINT32         Attributes OPTIONAL\r
+  );\r
+\r
 /**\r
   Process variable with platform key for verification.\r
 \r
index a54eaaa066bb53b744dc1a6c4bee61d3d2d25c78..dee5e1dd9d85fdaa70c2fc60f64ff69b86e6c696 100644 (file)
@@ -33,7 +33,6 @@ UINT32   mMaxKeyNumber;
 UINT32   mMaxKeyDbSize;\r
 UINT8    *mCertDbStore;\r
 UINT32   mMaxCertDbSize;\r
-UINT32   mPlatformMode;\r
 UINT8    mVendorKeyState;\r
 \r
 EFI_GUID mSignatureSupport[] = {EFI_CERT_SHA1_GUID, EFI_CERT_SHA256_GUID, EFI_CERT_RSA2048_GUID, EFI_CERT_X509_GUID};\r
@@ -99,6 +98,17 @@ VARIABLE_ENTRY_PROPERTY mAuthVarEntry[] = {
       MAX_UINTN\r
     }\r
   },\r
+  {\r
+    &gEdkiiSecureBootModeGuid,\r
+    L"SecureBootMode",\r
+    {\r
+      VAR_CHECK_VARIABLE_PROPERTY_REVISION,\r
+      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,\r
+      VARIABLE_ATTRIBUTE_NV_BS_RT,\r
+      sizeof (UINT8),\r
+      sizeof (UINT8)\r
+    }\r
+  }\r
 };\r
 \r
 VOID **mAuthVarAddressPointer[10];\r
@@ -132,8 +142,6 @@ AuthVariableLibInitialize (
   UINT8                 *Data;\r
   UINTN                 DataSize;\r
   UINTN                 CtxSize;\r
-  UINT8                 SecureBootMode;\r
-  UINT8                 SecureBootEnable;\r
   UINT8                 CustomMode;\r
   UINT32                ListSize;\r
 \r
@@ -208,31 +216,11 @@ AuthVariableLibInitialize (
     mPubKeyNumber = (UINT32) (DataSize / sizeof (AUTHVAR_KEY_DB_DATA));\r
   }\r
 \r
-  Status = AuthServiceInternalFindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME));\r
-  } else {\r
-    DEBUG ((EFI_D_INFO, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME));\r
-  }\r
-\r
   //\r
-  // Create "SetupMode" variable with BS+RT attribute set.\r
+  // Init Secure Boot variables\r
   //\r
-  if (EFI_ERROR (Status)) {\r
-    mPlatformMode = SETUP_MODE;\r
-  } else {\r
-    mPlatformMode = USER_MODE;\r
-  }\r
-  Status = AuthServiceInternalUpdateVariable (\r
-             EFI_SETUP_MODE_NAME,\r
-             &gEfiGlobalVariableGuid,\r
-             &mPlatformMode,\r
-             sizeof(UINT8),\r
-             EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
+  Status = InitSecureBootVariables ();\r
+\r
 \r
   //\r
   // Create "SignatureSupport" variable with BS+RT attribute set.\r
@@ -248,69 +236,6 @@ AuthVariableLibInitialize (
     return Status;\r
   }\r
 \r
-  //\r
-  // If "SecureBootEnable" variable exists, then update "SecureBoot" variable.\r
-  // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in USER_MODE, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.\r
-  // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.\r
-  //\r
-  SecureBootEnable = SECURE_BOOT_DISABLE;\r
-  Status = AuthServiceInternalFindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID **) &Data, &DataSize);\r
-  if (!EFI_ERROR (Status)) {\r
-    if (mPlatformMode == SETUP_MODE){\r
-      //\r
-      // PK is cleared in runtime. "SecureBootMode" is not updated before reboot\r
-      // Delete "SecureBootMode" in SetupMode\r
-      //\r
-      Status = AuthServiceInternalUpdateVariable (\r
-                 EFI_SECURE_BOOT_ENABLE_NAME,\r
-                 &gEfiSecureBootEnableDisableGuid,\r
-                 &SecureBootEnable,\r
-                 0,\r
-                 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
-                 );\r
-    } else {\r
-      SecureBootEnable = *(UINT8 *) Data;\r
-    }\r
-  } else if (mPlatformMode == USER_MODE) {\r
-    //\r
-    // "SecureBootEnable" not exist, initialize it in USER_MODE.\r
-    //\r
-    SecureBootEnable = SECURE_BOOT_ENABLE;\r
-    Status = AuthServiceInternalUpdateVariable (\r
-               EFI_SECURE_BOOT_ENABLE_NAME,\r
-               &gEfiSecureBootEnableDisableGuid,\r
-               &SecureBootEnable,\r
-               sizeof (UINT8),\r
-               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Create "SecureBoot" variable with BS+RT attribute set.\r
-  //\r
-  if (SecureBootEnable == SECURE_BOOT_ENABLE && mPlatformMode == USER_MODE) {\r
-    SecureBootMode = SECURE_BOOT_MODE_ENABLE;\r
-  } else {\r
-    SecureBootMode = SECURE_BOOT_MODE_DISABLE;\r
-  }\r
-  Status = AuthServiceInternalUpdateVariable (\r
-             EFI_SECURE_BOOT_MODE_NAME,\r
-             &gEfiGlobalVariableGuid,\r
-             &SecureBootMode,\r
-             sizeof (UINT8),\r
-             EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SETUP_MODE_NAME, mPlatformMode));\r
-  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME, SecureBootMode));\r
-  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable));\r
-\r
   //\r
   // Initialize "CustomMode" in STANDARD_SECURE_BOOT_MODE state.\r
   //\r
@@ -455,10 +380,16 @@ AuthVariableLibProcessVariable (
 {\r
   EFI_STATUS        Status;\r
 \r
+  //\r
+  // Process PK, KEK, Sigdb, AuditMode, DeployedMode separately.\r
+  //\r
   if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_PLATFORM_KEY_NAME) == 0)){\r
     Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, Attributes, TRUE);\r
   } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) {\r
     Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, Attributes, FALSE);\r
+  } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) \r
+          && (StrCmp (VariableName, EFI_AUDIT_MODE_NAME) == 0 || StrCmp (VariableName, EFI_DEPLOYED_MODE_NAME) == 0)) {\r
+    Status = ProcessSecureBootModeVar(VariableName, VendorGuid, Data, DataSize, Attributes);\r
   } else if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&\r
              ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE)  == 0) ||\r
               (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) ||\r
index 3709f7baae0ba43d464506d0bf1df1468dc6c70f..07a3ed541932dd0923d7f616790fdd6800c6811b 100644 (file)
   ## PRODUCES            ## Variable:L"AuthVarKeyDatabase"\r
   gEfiAuthenticatedVariableGuid\r
 \r
+  ## CONSUMES            ## Variable:L"SecureBootMode"\r
+  ## PRODUCES            ## Variable:L"SecureBootMode"\r
+  gEdkiiSecureBootModeGuid\r
+\r
   gEfiCertTypeRsa2048Sha256Guid  ## SOMETIMES_CONSUMES   ## GUID  # Unique ID for the type of the certificate.\r
   gEfiCertPkcs7Guid              ## SOMETIMES_CONSUMES   ## GUID  # Unique ID for the type of the certificate.\r
   gEfiCertX509Guid               ## SOMETIMES_CONSUMES   ## GUID  # Unique ID for the type of the signature.\r
index 5cb9f8144e2a261454f12a2e438eac07040f247e..4b4d3bf77de53eefdbe0e9221e95434fd1d003aa 100644 (file)
@@ -711,6 +711,58 @@ GetImageExeInfoTableSize (
   return TotalSize;\r
 }\r
 \r
+/**\r
+  Create signature list based on input signature data and certificate type GUID. Caller is reposible \r
+  to free new created SignatureList.\r
+\r
+  @param[in]   SignatureData           Signature data in SignatureList.\r
+  @param[in]   SignatureDataSize       Signature data size.\r
+  @param[in]   CertType                Certificate Type.\r
+  @param[out]  SignatureList           Created SignatureList.\r
+  @param[out]  SignatureListSize       Created SignatureListSize.\r
+\r
+  @return EFI_OUT_OF_RESOURCES         The operation is failed due to lack of resources.\r
+  @retval EFI_SUCCESS          Successfully create signature list.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateSignatureList(\r
+  IN UINT8                *SignatureData,\r
+  IN UINTN                SignatureDataSize,\r
+  IN EFI_GUID             *CertType,\r
+  OUT EFI_SIGNATURE_LIST  **SignatureList,\r
+  OUT UINTN               *SignatureListSize\r
+  )\r
+{\r
+  EFI_SIGNATURE_LIST   *SignList;\r
+  UINTN                SignListSize;\r
+  EFI_SIGNATURE_DATA   *Signature;\r
+\r
+  SignList       = NULL;\r
+  *SignatureList = NULL;\r
+\r
+  SignListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + SignatureDataSize;\r
+  SignList     = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignListSize);\r
+  if (SignList == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  SignList->SignatureHeaderSize = 0;\r
+  SignList->SignatureListSize   = (UINT32) SignListSize;\r
+  SignList->SignatureSize       = (UINT32) SignatureDataSize + sizeof (EFI_SIGNATURE_DATA) - 1;\r
+  CopyMem (&SignList->SignatureType, CertType, sizeof (EFI_GUID));\r
+\r
+  DEBUG((EFI_D_INFO, "SignatureDataSize %x\n", SignatureDataSize));\r
+  Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignList + sizeof (EFI_SIGNATURE_LIST));\r
+  CopyMem (Signature->SignatureData, SignatureData, SignatureDataSize);\r
+\r
+  *SignatureList     = SignList;\r
+  *SignatureListSize = SignListSize;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
 /**\r
   Create an Image Execution Information Table entry and add it to system configuration table.\r
 \r
@@ -737,11 +789,13 @@ AddImageExeInfo (
   UINTN                           NewImageExeInfoEntrySize;\r
   UINTN                           NameStringLen;\r
   UINTN                           DevicePathSize;\r
+  CHAR16                          *NameStr;\r
 \r
   ImageExeInfoTable     = NULL;\r
   NewImageExeInfoTable  = NULL;\r
   ImageExeInfoEntry     = NULL;\r
   NameStringLen         = 0;\r
+  NameStr               = NULL;\r
 \r
   if (DevicePath == NULL) {\r
     return ;\r
@@ -769,7 +823,12 @@ AddImageExeInfo (
   }\r
 \r
   DevicePathSize            = GetDevicePathSize (DevicePath);\r
-  NewImageExeInfoEntrySize  = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;\r
+\r
+  //\r
+  // Signature size can be odd. Pad after signature to ensure next EXECUTION_INFO entry align\r
+  //\r
+  NewImageExeInfoEntrySize = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;\r
+\r
   NewImageExeInfoTable      = (EFI_IMAGE_EXECUTION_INFO_TABLE *) AllocateRuntimePool (ImageExeInfoTableSize + NewImageExeInfoEntrySize);\r
   if (NewImageExeInfoTable == NULL) {\r
     return ;\r
@@ -788,19 +847,21 @@ AddImageExeInfo (
   WriteUnaligned32 ((UINT32 *) ImageExeInfoEntry, Action);\r
   WriteUnaligned32 ((UINT32 *) ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION)), (UINT32) NewImageExeInfoEntrySize);\r
 \r
+  NameStr = (CHAR16 *)(ImageExeInfoEntry + 1);\r
   if (Name != NULL) {\r
-    CopyMem ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32), Name, NameStringLen);\r
+    CopyMem ((UINT8 *) NameStr, Name, NameStringLen);\r
   } else {\r
-    ZeroMem ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32), sizeof (CHAR16));\r
+    ZeroMem ((UINT8 *) NameStr, sizeof (CHAR16));\r
   }\r
+\r
   CopyMem (\r
-    (UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32) + NameStringLen,\r
+    (UINT8 *) NameStr + NameStringLen,\r
     DevicePath,\r
     DevicePathSize\r
     );\r
   if (Signature != NULL) {\r
     CopyMem (\r
-      (UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32) + NameStringLen + DevicePathSize,\r
+      (UINT8 *) NameStr + NameStringLen + DevicePathSize,\r
       Signature,\r
       SignatureSize\r
       );\r
@@ -1087,6 +1148,53 @@ IsTimeZero (
   return FALSE;\r
 }\r
 \r
+/**\r
+  Record multiple certificate list & verification state of a verified image to \r
+  IMAGE_EXECUTION_TABLE.\r
+\r
+  @param[in]  CertBuf              Certificate list buffer.\r
+  @param[in]  CertBufLength        Certificate list buffer.\r
+  @param[in]  Action               Certificate list action to be record.\r
+  @param[in]  ImageName            Image name.\r
+  @param[in]  ImageDevicePath      Image device path.\r
+\r
+**/\r
+VOID \r
+RecordCertListToImageExeuctionTable(\r
+  IN UINT8                          *CertBuf,\r
+  IN UINTN                           CertBufLength,\r
+  IN EFI_IMAGE_EXECUTION_ACTION      Action,\r
+  IN CHAR16                         *ImageName OPTIONAL,\r
+  IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL\r
+  )\r
+{\r
+  UINT8               CertNumber;\r
+  UINT8               *CertPtr;\r
+  UINTN               Index;\r
+  UINT8               *Cert;\r
+  UINTN               CertSize;\r
+  EFI_STATUS          Status;\r
+  EFI_SIGNATURE_LIST  *SignatureList;\r
+  UINTN               SignatureListSize;\r
+\r
+  CertNumber = (UINT8) (*CertBuf);\r
+  CertPtr    = CertBuf + 1;\r
+  for (Index = 0; Index < CertNumber; Index++) {\r
+    CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr);\r
+    Cert     = (UINT8 *)CertPtr + sizeof (UINT32);\r
+\r
+    //\r
+    // Record all cert in cert chain to be passed\r
+    //\r
+    Status = CreateSignatureList(Cert, CertSize, &gEfiCertX509Guid, &SignatureList, &SignatureListSize);\r
+    if (!EFI_ERROR(Status)) {\r
+      AddImageExeInfo (Action, ImageName, ImageDevicePath, SignatureList, SignatureListSize);\r
+      FreePool (SignatureList);\r
+    }\r
+  }\r
+}\r
+\r
+\r
 /**\r
   Check whether the timestamp signature is valid and the signing time is also earlier than \r
   the revocation time.\r
@@ -1197,8 +1305,11 @@ Done:
   Check whether the image signature is forbidden by the forbidden database (dbx).\r
   The image is forbidden to load if any certificates for signing are revoked before signing time.\r
 \r
-  @param[in]  AuthData      Pointer to the Authenticode signature retrieved from the signed image.\r
-  @param[in]  AuthDataSize  Size of the Authenticode signature in bytes.\r
+  @param[in]  AuthData             Pointer to the Authenticode signature retrieved from the signed image.\r
+  @param[in]  AuthDataSize         Size of the Authenticode signature in bytes.\r
+  @param[in]  IsAuditMode          Whether system Secure Boot Mode is in AuditMode.\r
+  @param[in]  ImageName            Name of the image to verify.\r
+  @param[in]  ImageDevicePath      DevicePath of the image to verify.\r
 \r
   @retval TRUE              Image is forbidden by dbx.\r
   @retval FALSE             Image is not forbidden by dbx.\r
@@ -1206,8 +1317,11 @@ Done:
 **/\r
 BOOLEAN\r
 IsForbiddenByDbx (\r
-  IN UINT8                  *AuthData,\r
-  IN UINTN                  AuthDataSize\r
+  IN UINT8                          *AuthData,\r
+  IN UINTN                          AuthDataSize,\r
+  IN BOOLEAN                        IsAuditMode,\r
+  IN CHAR16                         *ImageName OPTIONAL,\r
+  IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL\r
   )\r
 {\r
   EFI_STATUS                Status;\r
@@ -1230,7 +1344,10 @@ IsForbiddenByDbx (
   UINT8                     *Cert;\r
   UINTN                     CertSize;\r
   EFI_TIME                  RevocationTime;\r
-\r
+  UINT8                     *SignerCert;\r
+  UINTN                     SignerCertLength;\r
+  UINT8                     *UnchainCert;\r
+  UINTN                     UnchainCertLength;\r
   //\r
   // Variable Initialization\r
   //\r
@@ -1245,6 +1362,10 @@ IsForbiddenByDbx (
   BufferLength      = 0;\r
   TrustedCert       = NULL;\r
   TrustedCertLength = 0;\r
+  SignerCert        = NULL;\r
+  SignerCertLength  = 0;\r
+  UnchainCert       = NULL;\r
+  UnchainCertLength = 0;\r
 \r
   //\r
   // The image will not be forbidden if dbx can't be got.\r
@@ -1352,21 +1473,54 @@ IsForbiddenByDbx (
   }\r
 \r
 Done:\r
+  if (IsForbidden && IsAuditMode) {\r
+    Pkcs7GetCertificatesList(AuthData, AuthDataSize, &SignerCert, &SignerCertLength, &UnchainCert, &UnchainCertLength);\r
+\r
+    //\r
+    // Record all certs in image to be failed\r
+    //\r
+    if ((SignerCertLength != 0) && (SignerCert != NULL)) {\r
+      RecordCertListToImageExeuctionTable(\r
+        SignerCert,\r
+        SignerCertLength,\r
+        EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
+        ImageName,\r
+        ImageDevicePath\r
+        );\r
+    }\r
+\r
+    if ((UnchainCertLength != 0) && (UnchainCert != NULL)) {\r
+      RecordCertListToImageExeuctionTable(\r
+        UnchainCert,\r
+        UnchainCertLength,\r
+        EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
+        ImageName,\r
+        ImageDevicePath\r
+        );\r
+    }\r
+  }\r
+\r
   if (Data != NULL) {\r
     FreePool (Data);\r
   }\r
 \r
   Pkcs7FreeSigners (CertBuffer);\r
   Pkcs7FreeSigners (TrustedCert);\r
+  Pkcs7FreeSigners (SignerCert);\r
+  Pkcs7FreeSigners (UnchainCert);\r
 \r
   return IsForbidden;\r
 }\r
 \r
+\r
 /**\r
   Check whether the image signature can be verified by the trusted certificates in DB database.\r
 \r
-  @param[in]  AuthData      Pointer to the Authenticode signature retrieved from signed image.\r
-  @param[in]  AuthDataSize  Size of the Authenticode signature in bytes.\r
+  @param[in]  AuthData              Pointer to the Authenticode signature retrieved from signed image.\r
+  @param[in]  AuthDataSize          Size of the Authenticode signature in bytes.\r
+  @param[in]  IsAuditMode           Whether system Secure Boot Mode is in AuditMode.\r
+  @param[in]  ImageName             Name of the image to verify.\r
+  @param[in]  ImageDevicePath       DevicePath of the image to verify.\r
 \r
   @retval TRUE         Image passed verification using certificate in db.\r
   @retval FALSE        Image didn't pass verification using certificate in db.\r
@@ -1374,14 +1528,17 @@ Done:
 **/\r
 BOOLEAN\r
 IsAllowedByDb (\r
-  IN UINT8              *AuthData,\r
-  IN UINTN              AuthDataSize\r
+  IN UINT8                          *AuthData,\r
+  IN UINTN                          AuthDataSize,\r
+  IN BOOLEAN                        IsAuditMode,\r
+  IN CHAR16                         *ImageName OPTIONAL,\r
+  IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL\r
   )\r
 {\r
   EFI_STATUS                Status;\r
   BOOLEAN                   VerifyStatus;\r
   EFI_SIGNATURE_LIST        *CertList;\r
-  EFI_SIGNATURE_DATA        *Cert;\r
+  EFI_SIGNATURE_DATA        *CertData;\r
   UINTN                     DataSize;\r
   UINT8                     *Data;\r
   UINT8                     *RootCert;\r
@@ -1391,14 +1548,22 @@ IsAllowedByDb (
   UINTN                     DbxDataSize;\r
   UINT8                     *DbxData;\r
   EFI_TIME                  RevocationTime;\r
+  UINT8                     *SignerCert;\r
+  UINTN                     SignerCertLength;\r
+  UINT8                     *UnchainCert;\r
+  UINTN                     UnchainCertLength;\r
 \r
-  Data         = NULL;\r
-  CertList     = NULL;\r
-  Cert         = NULL;\r
-  RootCert     = NULL;\r
-  DbxData      = NULL;\r
-  RootCertSize = 0;\r
-  VerifyStatus = FALSE;\r
+  Data              = NULL;\r
+  CertList          = NULL;\r
+  CertData          = NULL;\r
+  RootCert          = NULL;\r
+  DbxData           = NULL;\r
+  RootCertSize      = 0;\r
+  VerifyStatus      = FALSE;\r
+  SignerCert        = NULL;\r
+  SignerCertLength  = 0;\r
+  UnchainCert       = NULL;\r
+  UnchainCertLength = 0;\r
 \r
   DataSize = 0;\r
   Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
@@ -1419,14 +1584,14 @@ IsAllowedByDb (
     CertList = (EFI_SIGNATURE_LIST *) Data;\r
     while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
       if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
-        Cert       = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
-        CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+        CertData  = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+        CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
 \r
         for (Index = 0; Index < CertCount; Index++) {\r
           //\r
           // Iterate each Signature Data Node within this CertList for verify.\r
           //\r
-          RootCert     = Cert->SignatureData;\r
+          RootCert     = CertData->SignatureData;\r
           RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
 \r
           //\r
@@ -1468,7 +1633,7 @@ IsAllowedByDb (
             goto Done;\r
           }\r
 \r
-          Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
+          CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);\r
         }\r
       }\r
 \r
@@ -1478,10 +1643,67 @@ IsAllowedByDb (
   }\r
 \r
 Done:\r
+\r
   if (VerifyStatus) {\r
-    SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
+    SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, CertData);\r
+  }\r
+\r
+  if (IsAuditMode) {\r
+\r
+    Pkcs7GetCertificatesList(AuthData, AuthDataSize, &SignerCert, &SignerCertLength, &UnchainCert, &UnchainCertLength);\r
+    if (VerifyStatus) {\r
+      if ((SignerCertLength != 0) && (SignerCert != NULL)) {\r
+        //\r
+        // Record all cert in signer's cert chain to be passed\r
+        //\r
+        RecordCertListToImageExeuctionTable(\r
+          SignerCert,\r
+          SignerCertLength,\r
+          EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
+          ImageName,\r
+          ImageDevicePath\r
+          );\r
+      }\r
+\r
+      if ((UnchainCertLength != 0) && (UnchainCert != NULL)) {\r
+        //\r
+        // Record all certs in unchained certificates lists to be failed\r
+        //\r
+        RecordCertListToImageExeuctionTable(\r
+          UnchainCert,\r
+          UnchainCertLength,\r
+          EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
+          ImageName,\r
+          ImageDevicePath\r
+          );\r
+      }\r
+    } else {\r
+      //\r
+      // Record all certs in image to be failed\r
+      //\r
+      if ((SignerCertLength != 0) && (SignerCert != NULL)) {\r
+        RecordCertListToImageExeuctionTable(\r
+          SignerCert,\r
+          SignerCertLength,\r
+          EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
+          ImageName,\r
+          ImageDevicePath\r
+          );\r
+      }\r
+\r
+      if ((UnchainCertLength != 0) && (UnchainCert != NULL)) {\r
+        RecordCertListToImageExeuctionTable(\r
+          UnchainCert,\r
+          UnchainCertLength,\r
+          EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
+          ImageName,\r
+          ImageDevicePath\r
+          );\r
+      }\r
+    }\r
   }\r
 \r
+\r
   if (Data != NULL) {\r
     FreePool (Data);\r
   }\r
@@ -1489,9 +1711,369 @@ Done:
     FreePool (DbxData);\r
   }\r
 \r
+  Pkcs7FreeSigners (SignerCert);\r
+  Pkcs7FreeSigners (UnchainCert);\r
+\r
   return VerifyStatus;\r
 }\r
 \r
+/**\r
+  Provide verification service for signed images in AuditMode, which include both signature validation\r
+  and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and\r
+  MSFT Authenticode type signatures are supported. \r
+\r
+  In this implementation, only verify external executables when in AuditMode.\r
+  Executables from FV is bypass, so pass in AuthenticationStatus is ignored. Other authentication status\r
+  are record into IMAGE_EXECUTION_TABLE.\r
+\r
+  The image verification policy is:\r
+    If the image is signed,\r
+      At least one valid signature or at least one hash value of the image must match a record\r
+      in the security database "db", and no valid signature nor any hash value of the image may\r
+      be reflected in the security database "dbx".\r
+    Otherwise, the image is not signed,\r
+      The SHA256 hash value of the image must match a record in the security database "db", and\r
+      not be reflected in the security data base "dbx".\r
+\r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will validate its data structure\r
+  within this image buffer before use.\r
+\r
+  @param[in]    AuthenticationStatus\r
+                           This is the authentication status returned from the security\r
+                           measurement services for the input file.\r
+  @param[in]    File       This is a pointer to the device path of the file that is\r
+                           being dispatched. This will optionally be used for logging.\r
+  @param[in]    FileBuffer File buffer matches the input file device path.\r
+  @param[in]    FileSize   Size of File buffer matches the input file device path.\r
+  @param[in]    BootPolicy A boot policy that was used to call LoadImage() UEFI service.\r
+\r
+  @retval EFI_SUCCESS            The authenticate info is sucessfully stored for the file \r
+                                 specified by DevicePath and non-NULL FileBuffer \r
+  @retval EFI_ACCESS_DENIED      The file specified by File and FileBuffer did not\r
+                                 authenticate, and the platform policy dictates that the DXE\r
+                                 Foundation many not use File.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ImageVerificationInAuditMode (\r
+  IN  UINT32                           AuthenticationStatus,\r
+  IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,\r
+  IN  VOID                             *FileBuffer,\r
+  IN  UINTN                            FileSize,\r
+  IN  BOOLEAN                          BootPolicy\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  UINT16                               Magic;\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  EFI_SIGNATURE_LIST                   *SignatureList;\r
+  EFI_IMAGE_EXECUTION_ACTION           Action;\r
+  WIN_CERTIFICATE                      *WinCertificate;\r
+  UINT32                               Policy;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;\r
+  UINT32                               NumberOfRvaAndSizes;\r
+  WIN_CERTIFICATE_EFI_PKCS             *PkcsCertData;\r
+  WIN_CERTIFICATE_UEFI_GUID            *WinCertUefiGuid;\r
+  UINT8                                *AuthData;\r
+  UINTN                                AuthDataSize;\r
+  EFI_IMAGE_DATA_DIRECTORY             *SecDataDir;\r
+  UINT32                               OffSet;\r
+  CHAR16                               *FilePathStr;\r
+  UINTN                                SignatureListSize;\r
+\r
+  SignatureList     = NULL;\r
+  WinCertificate    = NULL;\r
+  SecDataDir        = NULL;\r
+  PkcsCertData      = NULL;\r
+  FilePathStr       = NULL;\r
+  Action            = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED;\r
+  Status            = EFI_ACCESS_DENIED;\r
+\r
+\r
+  //\r
+  // Check the image type and get policy setting.\r
+  //\r
+  switch (GetImageType (File)) {\r
+\r
+  case IMAGE_FROM_FV:\r
+    Policy = ALWAYS_EXECUTE;\r
+    break;\r
+\r
+  case IMAGE_FROM_OPTION_ROM:\r
+    Policy = PcdGet32 (PcdOptionRomImageVerificationPolicy);\r
+    break;\r
+\r
+  case IMAGE_FROM_REMOVABLE_MEDIA:\r
+    Policy = PcdGet32 (PcdRemovableMediaImageVerificationPolicy);\r
+    break;\r
+\r
+  case IMAGE_FROM_FIXED_MEDIA:\r
+    Policy = PcdGet32 (PcdFixedMediaImageVerificationPolicy);\r
+    break;\r
+\r
+  default:\r
+    Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;\r
+    break;\r
+  }\r
+\r
+  //\r
+  // If policy is always/never execute, return directly.\r
+  //\r
+  if (Policy == ALWAYS_EXECUTE) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Get Image Device Path Str\r
+  //\r
+  FilePathStr = ConvertDevicePathToText (File, FALSE, TRUE);\r
+\r
+  //\r
+  // Authentication failed because of (unspecified) firmware security policy\r
+  //\r
+  if (Policy == NEVER_EXECUTE) {\r
+    //\r
+    // No signature, record FilePath/FilePathStr only\r
+    //\r
+    AddImageExeInfo (EFI_IMAGE_EXECUTION_POLICY_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED, FilePathStr, File, NULL, 0);\r
+    goto END;\r
+  }\r
+\r
+  //\r
+  // The policy QUERY_USER_ON_SECURITY_VIOLATION and ALLOW_EXECUTE_ON_SECURITY_VIOLATION\r
+  // violates the UEFI spec and has been removed.\r
+  //\r
+  ASSERT (Policy != QUERY_USER_ON_SECURITY_VIOLATION && Policy != ALLOW_EXECUTE_ON_SECURITY_VIOLATION);\r
+  if (Policy == QUERY_USER_ON_SECURITY_VIOLATION || Policy == ALLOW_EXECUTE_ON_SECURITY_VIOLATION) {\r
+    CpuDeadLoop ();\r
+  }\r
+\r
+  //\r
+  // Read the Dos header.\r
+  //\r
+  if (FileBuffer == NULL) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto END;\r
+  }\r
+\r
+  mImageBase  = (UINT8 *) FileBuffer;\r
+  mImageSize  = FileSize;\r
+\r
+  ZeroMem (&ImageContext, sizeof (ImageContext));\r
+  ImageContext.Handle    = (VOID *) FileBuffer;\r
+  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeImageVerificationLibImageRead;\r
+\r
+  //\r
+  // Get information about the image being loaded\r
+  //\r
+  Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // The information can't be got from the invalid PeImage\r
+    //\r
+    goto END;\r
+  }\r
+\r
+\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;\r
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+    //\r
+    // DOS image header is present,\r
+    // so read the PE header after the DOS image header.\r
+    //\r
+    mPeCoffHeaderOffset = DosHdr->e_lfanew;\r
+  } else {\r
+    mPeCoffHeaderOffset = 0;\r
+  }\r
+\r
+  //\r
+  // Check PE/COFF image.\r
+  //\r
+  mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (mImageBase + mPeCoffHeaderOffset);\r
+  if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+    //\r
+    // It is not a valid Pe/Coff file.\r
+    //\r
+    Status = EFI_ACCESS_DENIED;\r
+    goto END;\r
+  }\r
+\r
+  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
+    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
+    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
+    //\r
+    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+  } else {\r
+    //\r
+    // Get the magic value from the PE/COFF Optional Header\r
+    //\r
+    Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
+  }\r
+\r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Use PE32 offset.\r
+    //\r
+    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+    }\r
+  } else {\r
+    //\r
+    // Use PE32+ offset.\r
+    //\r
+    NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+    }\r
+  }\r
+\r
+  //\r
+  // Start Image Validation.\r
+  //\r
+  if (SecDataDir == NULL || SecDataDir->Size == 0) {\r
+    //\r
+    // This image is not signed. The SHA256 hash value of the image must match a record in the security database "db",\r
+    // and not be reflected in the security data base "dbx".\r
+    //\r
+    if (!HashPeImage (HASHALG_SHA256)) {\r
+      Status = EFI_ACCESS_DENIED;\r
+      goto END;\r
+    }\r
+\r
+    //\r
+    // Image Hash is in forbidden database (DBX).\r
+    //\r
+    if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\r
+      //\r
+      // Image Hash is in allowed database (DB).\r
+      //\r
+      if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {\r
+        Action = EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Add HASH digest for image without signature\r
+    //\r
+    Status = CreateSignatureList(mImageDigest, mImageDigestSize, &mCertType, &SignatureList, &SignatureListSize);\r
+    if (!EFI_ERROR(Status)) {\r
+      AddImageExeInfo (Action, FilePathStr, File, SignatureList, SignatureListSize);\r
+      FreePool (SignatureList);\r
+    }\r
+    goto END;\r
+  }\r
+\r
+  //\r
+  // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7\r
+  // "Attribute Certificate Table".\r
+  // The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.\r
+  //\r
+  for (OffSet = SecDataDir->VirtualAddress;\r
+       OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);\r
+       OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength))) {\r
+    WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);\r
+    if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||\r
+        (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.\r
+    //\r
+    if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
+      //\r
+      // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the\r
+      // Authenticode specification.\r
+      //\r
+      PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;\r
+      if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {\r
+        break;\r
+      }\r
+      AuthData   = PkcsCertData->CertData;\r
+      AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);\r
+    } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {\r
+      //\r
+      // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.\r
+      //\r
+      WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;\r
+      if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {\r
+        break;\r
+      }\r
+      if (!CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {\r
+        continue;\r
+      }\r
+      AuthData = WinCertUefiGuid->CertData;\r
+      AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);\r
+    } else {\r
+      if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {\r
+        break;\r
+      }\r
+      continue;\r
+    }\r
+\r
+    Status = HashPeImageByType (AuthData, AuthDataSize);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED;\r
+\r
+    //\r
+    // Check the digital signature against the revoked certificate in forbidden database (dbx).\r
+    // Check the digital signature against the valid certificate in allowed database (db).\r
+    //\r
+    if (!IsForbiddenByDbx (AuthData, AuthDataSize, TRUE, FilePathStr, File)) {\r
+      IsAllowedByDb (AuthData, AuthDataSize, TRUE, FilePathStr, File);\r
+    }\r
+\r
+    //\r
+    // Check the image's hash value.\r
+    //\r
+    if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\r
+      if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {\r
+        Action = EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED; \r
+      }\r
+    }\r
+\r
+    //\r
+    // Add HASH digest for image with signature\r
+    //\r
+    Status = CreateSignatureList(mImageDigest, mImageDigestSize, &mCertType, &SignatureList, &SignatureListSize);\r
+\r
+    if (!EFI_ERROR(Status)) {\r
+      AddImageExeInfo (Action, FilePathStr, File, SignatureList, SignatureListSize);\r
+      FreePool (SignatureList);\r
+    } else {\r
+      goto END;\r
+    }\r
+  }\r
+\r
+\r
+  if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {\r
+    //\r
+    // The Size in Certificate Table or the attribute certicate table is corrupted.\r
+    //\r
+    Status = EFI_ACCESS_DENIED;\r
+  } else {\r
+    Status = EFI_SUCCESS;\r
+  }\r
+\r
+END:\r
+\r
+  if (FilePathStr != NULL) {\r
+    FreePool(FilePathStr);\r
+    FilePathStr = NULL;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Provide verification service for signed images, which include both signature validation\r
   and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and\r
@@ -1559,7 +2141,9 @@ DxeImageVerificationHandler (
   EFI_IMAGE_EXECUTION_ACTION           Action;\r
   WIN_CERTIFICATE                      *WinCertificate;\r
   UINT32                               Policy;\r
-  UINT8                                *SecureBoot;\r
+  UINT8                                *VarData;\r
+  UINT8                                SecureBoot;\r
+  UINT8                                AuditMode;\r
   PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;\r
   UINT32                               NumberOfRvaAndSizes;\r
   WIN_CERTIFICATE_EFI_PKCS             *PkcsCertData;\r
@@ -1579,6 +2163,20 @@ DxeImageVerificationHandler (
   Status            = EFI_ACCESS_DENIED;\r
   VerifyStatus      = EFI_ACCESS_DENIED;\r
 \r
+  GetEfiGlobalVariable2 (EFI_AUDIT_MODE_NAME, (VOID**)&VarData, NULL);\r
+  //\r
+  // Skip verification if AuditMode variable doesn't exist. AuditMode should always exist\r
+  //\r
+  if (VarData == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  AuditMode = *VarData;\r
+  FreePool(VarData);\r
+\r
+  if (AuditMode == AUDIT_MODE_ENABLE) {\r
+    return ImageVerificationInAuditMode(AuthenticationStatus, File, FileBuffer, FileSize, BootPolicy);\r
+  }\r
+\r
   //\r
   // Check the image type and get policy setting.\r
   //\r
@@ -1622,22 +2220,22 @@ DxeImageVerificationHandler (
     CpuDeadLoop ();\r
   }\r
 \r
-  GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL);\r
+  GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&VarData, NULL);\r
   //\r
   // Skip verification if SecureBoot variable doesn't exist.\r
   //\r
-  if (SecureBoot == NULL) {\r
+  if (VarData == NULL) {\r
     return EFI_SUCCESS;\r
   }\r
+  SecureBoot = *VarData;\r
+  FreePool(VarData);\r
 \r
   //\r
-  // Skip verification if SecureBoot is disabled.\r
+  // Skip verification if SecureBoot is disabled but not AuditMode\r
   //\r
-  if (*SecureBoot == SECURE_BOOT_MODE_DISABLE) {\r
-    FreePool (SecureBoot);\r
+  if (SecureBoot == SECURE_BOOT_MODE_DISABLE) {\r
     return EFI_SUCCESS;\r
   }\r
-  FreePool (SecureBoot);\r
 \r
   //\r
   // Read the Dos header.\r
@@ -1808,7 +2406,7 @@ DxeImageVerificationHandler (
     //\r
     // Check the digital signature against the revoked certificate in forbidden database (dbx).\r
     //\r
-    if (IsForbiddenByDbx (AuthData, AuthDataSize)) {\r
+    if (IsForbiddenByDbx (AuthData, AuthDataSize, FALSE, NULL, NULL)) {\r
       Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;\r
       VerifyStatus = EFI_ACCESS_DENIED;\r
       break;\r
@@ -1818,7 +2416,7 @@ DxeImageVerificationHandler (
     // Check the digital signature against the valid certificate in allowed database (db).\r
     //\r
     if (EFI_ERROR (VerifyStatus)) {\r
-      if (IsAllowedByDb (AuthData, AuthDataSize)) {\r
+      if (IsAllowedByDb (AuthData, AuthDataSize, FALSE, NULL, NULL)) {\r
         VerifyStatus = EFI_SUCCESS;\r
       }\r
     }\r