]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/AuthVariableLib/AuthService.c
SecurityPkg Tpm2DeviceLibDTpm: Update enum type name to match the one in lib
[mirror_edk2.git] / SecurityPkg / Library / AuthVariableLib / AuthService.c
index f11b86827a8569e030e48e49ef29a73e902bf4b5..213a524f271c797104ad5ae3b03ea0a56ab16129 100644 (file)
@@ -18,7 +18,7 @@
   They will do basic validation for authentication data structure, then call crypto library\r
   to verify the signature.\r
 \r
-Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -36,6 +36,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 //\r
 CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };\r
 \r
+CONST UINT8 mSha256OidValue[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 };\r
+\r
 //\r
 // Requirement for different signature type which have been defined in UEFI spec.\r
 // These data are used to perform SignatureList format check while setting PK/KEK variable.\r
@@ -56,54 +58,6 @@ 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
@@ -182,50 +136,6 @@ AuthServiceInternalUpdateVariable (
            );\r
 }\r
 \r
-/**\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] KeyIndex               Index of associated public key.\r
-  @param[in] MonotonicCount         Value of associated monotonic count.\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
-AuthServiceInternalUpdateVariableWithMonotonicCount (\r
-  IN CHAR16             *VariableName,\r
-  IN EFI_GUID           *VendorGuid,\r
-  IN VOID               *Data,\r
-  IN UINTN              DataSize,\r
-  IN UINT32             Attributes,\r
-  IN UINT32             KeyIndex,\r
-  IN UINT64             MonotonicCount\r
-  )\r
-{\r
-  AUTH_VARIABLE_INFO    AuthVariableInfo;\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.PubKeyIndex = KeyIndex;\r
-  AuthVariableInfo.MonotonicCount = MonotonicCount;\r
-\r
-  return mAuthVarLibContextIn->UpdateVariable (\r
-           &AuthVariableInfo\r
-           );\r
-}\r
-\r
 /**\r
   Update the variable region with Variable information.\r
 \r
@@ -298,1261 +208,176 @@ AuthServiceInternalUpdateVariableWithTimeStamp (
 }\r
 \r
 /**\r
-  Initialize Secure Boot variables.\r
+  Determine whether this operation needs a physical present user.\r
 \r
-  @retval EFI_SUCCESS               The initialization operation is successful.\r
-  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+  @param[in]      VariableName            Name of the Variable.\r
+  @param[in]      VendorGuid              GUID of the Variable.\r
+\r
+  @retval TRUE      This variable is protected, only a physical present user could set this variable.\r
+  @retval FALSE     This variable is not protected.\r
 \r
 **/\r
-EFI_STATUS\r
-InitSecureBootVariables (\r
-  VOID\r
+BOOLEAN\r
+NeedPhysicallyPresent(\r
+  IN     CHAR16         *VariableName,\r
+  IN     EFI_GUID       *VendorGuid\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
+  if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp (VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0))\r
+    || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp (VariableName, EFI_CUSTOM_MODE_NAME) == 0))) {\r
+    return TRUE;\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
+  return FALSE;\r
 }\r
 \r
 /**\r
-  Update SecureBootMode variable.\r
-\r
-  @param[in] NewMode                New Secure Boot Mode.\r
+  Determine whether the platform is operating in Custom 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
+  @retval TRUE           The platform is operating in Custom mode.\r
+  @retval FALSE          The platform is operating in Standard mode.\r
 \r
 **/\r
-EFI_STATUS\r
-UpdateSecureBootMode(\r
-  IN  SECURE_BOOT_MODE_TYPE  NewMode\r
+BOOLEAN\r
+InCustomMode (\r
+  VOID\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
+  EFI_STATUS    Status;\r
+  VOID          *Data;\r
+  UINTN         DataSize;\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
+  Status = AuthServiceInternalFindVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, &Data, &DataSize);\r
+  if (!EFI_ERROR (Status) && (*(UINT8 *) Data == CUSTOM_SECURE_BOOT_MODE)) {\r
+    return TRUE;\r
   }\r
 \r
-  return Status;\r
+  return FALSE;\r
 }\r
 \r
 /**\r
-  Current secure boot mode is AuditMode. This function performs secure boot mode transition\r
-  to a new mode.\r
+  Update platform mode.\r
 \r
-  @param[in] NewMode                New Secure Boot Mode.\r
+  @param[in]      Mode                    SETUP_MODE or USER_MODE.\r
 \r
-  @retval EFI_SUCCESS               The initialization operation is successful.\r
-  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+  @return EFI_INVALID_PARAMETER           Invalid parameter.\r
+  @return EFI_SUCCESS                     Update platform mode successfully.\r
 \r
 **/\r
 EFI_STATUS\r
-TransitionFromAuditMode(\r
-  IN  SECURE_BOOT_MODE_TYPE               NewMode\r
+UpdatePlatformMode (\r
+  IN  UINT32                    Mode\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  VOID        *AuditVarData;\r
-  VOID        *DeployedVarData;\r
-  VOID        *SetupVarData;\r
-  VOID        *SecureBootVarData;\r
-  UINT8       SecureBootEnable;\r
-  UINTN       DataSize;\r
+  EFI_STATUS              Status;\r
+  VOID                    *Data;\r
+  UINTN                   DataSize;\r
+  UINT8                   SecureBootMode;\r
+  UINT8                   SecureBootEnable;\r
+  UINTN                   VariableDataSize;\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
+             EFI_SETUP_MODE_NAME,\r
              &gEfiGlobalVariableGuid,\r
-             &AuditVarData,\r
+             &Data,\r
              &DataSize\r
              );\r
   if (EFI_ERROR (Status)) {\r
-    ASSERT(FALSE);\r
+    return Status;\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
+  // 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_SETUP_MODE_NAME,\r
+             EFI_SECURE_BOOT_MODE_NAME,\r
              &gEfiGlobalVariableGuid,\r
-             &SetupVarData,\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
-    ASSERT(FALSE);\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 = AuthServiceInternalFindVariable (\r
-             EFI_SECURE_BOOT_MODE_NAME,\r
-             &gEfiGlobalVariableGuid,\r
-             &SecureBootVarData,\r
-             &DataSize\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
-    ASSERT(FALSE);\r
+    return Status;\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
+  // Check "SecureBootEnable" variable's existence. It can enable/disable secure boot feature.\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
+  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 "SecureBootEnable" variable  as secure boot is enabled.\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
+    VariableDataSize = sizeof (SecureBootEnable);\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
-  VOID        *DeployedVarData;\r
-  VOID        *SetupVarData;\r
-  VOID        *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
-  VOID         *AuditVarData;\r
-  VOID         *DeployedVarData;\r
-  VOID         *SetupVarData;\r
-  VOID         *PkVarData;\r
-  VOID         *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
-  VOID         *AuditVarData;\r
-  VOID         *SetupVarData;\r
-  VOID         *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] CurMode                Current Secure Boot Mode.\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
-  @retval EFI_INVALID_PARAMETER     The Current Secure Boot Mode is wrong.\r
-\r
-**/\r
-EFI_STATUS\r
-SecureBootModeTransition(\r
-  IN  SECURE_BOOT_MODE_TYPE  CurMode,\r
-  IN  SECURE_BOOT_MODE_TYPE  NewMode\r
-  )\r
-{\r
-  EFI_STATUS Status;\r
-\r
-  //\r
-  // SecureBootMode transition\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
-  return Status;\r
-\r
-}\r
-\r
-/**\r
-  Determine whether this operation needs a physical present user.\r
-\r
-  @param[in]      VariableName            Name of the Variable.\r
-  @param[in]      VendorGuid              GUID of the Variable.\r
-\r
-  @retval TRUE      This variable is protected, only a physical present user could set this variable.\r
-  @retval FALSE     This variable is not protected.\r
-\r
-**/\r
-BOOLEAN\r
-NeedPhysicallyPresent(\r
-  IN     CHAR16         *VariableName,\r
-  IN     EFI_GUID       *VendorGuid\r
-  )\r
-{\r
-  if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp (VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0))\r
-    || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp (VariableName, EFI_CUSTOM_MODE_NAME) == 0))) {\r
-    return TRUE;\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
-/**\r
-  Determine whether the platform is operating in Custom Secure Boot mode.\r
-\r
-  @retval TRUE           The platform is operating in Custom mode.\r
-  @retval FALSE          The platform is operating in Standard mode.\r
-\r
-**/\r
-BOOLEAN\r
-InCustomMode (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS    Status;\r
-  VOID          *Data;\r
-  UINTN         DataSize;\r
-\r
-  Status = AuthServiceInternalFindVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, &Data, &DataSize);\r
-  if (!EFI_ERROR (Status) && (*(UINT8 *) Data == CUSTOM_SECURE_BOOT_MODE)) {\r
-    return TRUE;\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
-/**\r
-  Get available public key index.\r
-\r
-  @param[in] PubKey     Pointer to Public Key data.\r
-\r
-  @return Public key index, 0 if no any public key index available.\r
-\r
-**/\r
-UINT32\r
-GetAvailableKeyIndex (\r
-  IN  UINT8             *PubKey\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  UINT8                 *Data;\r
-  UINTN                 DataSize;\r
-  UINT8                 *Ptr;\r
-  UINT32                Index;\r
-  BOOLEAN               IsFound;\r
-  EFI_GUID              VendorGuid;\r
-  CHAR16                Name[1];\r
-  AUTH_VARIABLE_INFO    AuthVariableInfo;\r
-  UINT32                KeyIndex;\r
-\r
-  Status = AuthServiceInternalFindVariable (\r
-             AUTHVAR_KEYDB_NAME,\r
-             &gEfiAuthenticatedVariableGuid,\r
-             (VOID **) &Data,\r
-             &DataSize\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Get public key database variable failure, Status = %r\n", Status));\r
-    return 0;\r
-  }\r
-\r
-  if (mPubKeyNumber == mMaxKeyNumber) {\r
-    Name[0] = 0;\r
-    AuthVariableInfo.VariableName = Name;\r
-    ZeroMem (&VendorGuid, sizeof (VendorGuid));\r
-    AuthVariableInfo.VendorGuid = &VendorGuid;\r
-    mPubKeyNumber = 0;\r
-    //\r
-    // Collect valid key data.\r
-    //\r
-    do {\r
-      Status = mAuthVarLibContextIn->FindNextVariable (AuthVariableInfo.VariableName, AuthVariableInfo.VendorGuid, &AuthVariableInfo);\r
-      if (!EFI_ERROR (Status)) {\r
-        if (AuthVariableInfo.PubKeyIndex != 0) {\r
-          for (Ptr = Data; Ptr < (Data + DataSize); Ptr += sizeof (AUTHVAR_KEY_DB_DATA)) {\r
-            if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) Ptr)->KeyIndex)) == AuthVariableInfo.PubKeyIndex) {\r
-              //\r
-              // Check if the key data has been collected.\r
-              //\r
-              for (Index = 0; Index < mPubKeyNumber; Index++) {\r
-                if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + Index)->KeyIndex)) == AuthVariableInfo.PubKeyIndex) {\r
-                  break;\r
-                }\r
-              }\r
-              if (Index == mPubKeyNumber) {\r
-                //\r
-                // New key data.\r
-                //\r
-                CopyMem ((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + mPubKeyNumber, Ptr, sizeof (AUTHVAR_KEY_DB_DATA));\r
-                mPubKeyNumber++;\r
-              }\r
-              break;\r
-            }\r
-          }\r
-        }\r
-      }\r
-    } while (Status != EFI_NOT_FOUND);\r
-\r
-    //\r
-    // No available space to add new public key.\r
-    //\r
-    if (mPubKeyNumber == mMaxKeyNumber) {\r
-      return 0;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Find available public key index.\r
-  //\r
-  for (KeyIndex = 1; KeyIndex <= mMaxKeyNumber; KeyIndex++) {\r
-    IsFound = FALSE;\r
-    for (Ptr = mPubKeyStore; Ptr < (mPubKeyStore + mPubKeyNumber * sizeof (AUTHVAR_KEY_DB_DATA)); Ptr += sizeof (AUTHVAR_KEY_DB_DATA)) {\r
-      if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) Ptr)->KeyIndex)) == KeyIndex) {\r
-        IsFound = TRUE;\r
-        break;\r
-      }\r
-    }\r
-    if (!IsFound) {\r
-      break;\r
-    }\r
-  }\r
-\r
-  return KeyIndex;\r
-}\r
-\r
-/**\r
-  Add public key in store and return its index.\r
-\r
-  @param[in] PubKey             Input pointer to Public Key data.\r
-  @param[in] VariableDataEntry  The variable data entry.\r
-\r
-  @return Index of new added public key.\r
-\r
-**/\r
-UINT32\r
-AddPubKeyInStore (\r
-  IN  UINT8                        *PubKey,\r
-  IN  VARIABLE_ENTRY_CONSISTENCY   *VariableDataEntry\r
-  )\r
-{\r
-  EFI_STATUS                       Status;\r
-  UINT32                           Index;\r
-  VARIABLE_ENTRY_CONSISTENCY       PublicKeyEntry;\r
-  UINT32                           Attributes;\r
-  UINT32                           KeyIndex;\r
-\r
-  if (PubKey == NULL) {\r
-    return 0;\r
-  }\r
-\r
-  //\r
-  // Check whether the public key entry does exist.\r
-  //\r
-  for (Index = 0; Index < mPubKeyNumber; Index++) {\r
-    if (CompareMem (((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + Index)->KeyData, PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {\r
-      return ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + Index)->KeyIndex));\r
-    }\r
-  }\r
-\r
-  KeyIndex = GetAvailableKeyIndex (PubKey);\r
-  if (KeyIndex == 0) {\r
-    return 0;\r
-  }\r
-\r
-  //\r
-  // Check the variable space for both public key and variable data.\r
-  //\r
-  PublicKeyEntry.VariableSize = (mPubKeyNumber + 1) * sizeof (AUTHVAR_KEY_DB_DATA);\r
-  PublicKeyEntry.Guid         = &gEfiAuthenticatedVariableGuid;\r
-  PublicKeyEntry.Name         = AUTHVAR_KEYDB_NAME;\r
-  Attributes = VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;\r
-\r
-  if (!mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (Attributes, &PublicKeyEntry, VariableDataEntry, NULL)) {\r
-    //\r
-    // No enough variable space.\r
-    //\r
-    return 0;\r
-  }\r
-\r
-  WriteUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + mPubKeyNumber)->KeyIndex), KeyIndex);\r
-  CopyMem (((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + mPubKeyNumber)->KeyData, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);\r
-  mPubKeyNumber++;\r
-\r
-  //\r
-  // Update public key database variable.\r
-  //\r
-  Status = AuthServiceInternalUpdateVariable (\r
-             AUTHVAR_KEYDB_NAME,\r
-             &gEfiAuthenticatedVariableGuid,\r
-             mPubKeyStore,\r
-             mPubKeyNumber * sizeof (AUTHVAR_KEY_DB_DATA),\r
-             Attributes\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Update public key database variable failure, Status = %r\n", Status));\r
-    return 0;\r
-  }\r
-\r
-  return KeyIndex;\r
-}\r
-\r
-/**\r
-  Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256_GUID type.\r
-  Follow the steps in UEFI2.2.\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
-\r
-  @param[in]      Data                    Pointer to data with AuthInfo.\r
-  @param[in]      DataSize                Size of Data.\r
-  @param[in]      PubKey                  Public key used for verification.\r
-\r
-  @retval EFI_INVALID_PARAMETER       Invalid parameter.\r
-  @retval EFI_SECURITY_VIOLATION      If authentication failed.\r
-  @retval EFI_SUCCESS                 Authentication successful.\r
-\r
-**/\r
-EFI_STATUS\r
-VerifyCounterBasedPayload (\r
-  IN     UINT8          *Data,\r
-  IN     UINTN          DataSize,\r
-  IN     UINT8          *PubKey\r
-  )\r
-{\r
-  BOOLEAN                         Status;\r
-  EFI_VARIABLE_AUTHENTICATION     *CertData;\r
-  EFI_CERT_BLOCK_RSA_2048_SHA256  *CertBlock;\r
-  UINT8                           Digest[SHA256_DIGEST_SIZE];\r
-  VOID                            *Rsa;\r
-  UINTN                           PayloadSize;\r
-\r
-  PayloadSize = DataSize - AUTHINFO_SIZE;\r
-  Rsa         = NULL;\r
-  CertData    = NULL;\r
-  CertBlock   = NULL;\r
-\r
-  if (Data == NULL || PubKey == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  CertData  = (EFI_VARIABLE_AUTHENTICATION *) Data;\r
-  CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);\r
-\r
-  //\r
-  // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.\r
-  // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256_GUID.\r
-  //\r
-  if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||\r
-      !CompareGuid (&CertData->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid)) {\r
     //\r
-    // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.\r
+    // Delete the "SecureBootEnable" variable if this variable exist as "SecureBoot"\r
+    // variable is not in secure boot state.\r
     //\r
-    return EFI_SECURITY_VIOLATION;\r
-  }\r
-  //\r
-  // Hash data payload with SHA256.\r
-  //\r
-  ZeroMem (Digest, SHA256_DIGEST_SIZE);\r
-  Status  = Sha256Init (mHashCtx);\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  Status  = Sha256Update (mHashCtx, Data + AUTHINFO_SIZE, PayloadSize);\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  //\r
-  // Hash Size.\r
-  //\r
-  Status  = Sha256Update (mHashCtx, &PayloadSize, sizeof (UINTN));\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  //\r
-  // Hash Monotonic Count.\r
-  //\r
-  Status  = Sha256Update (mHashCtx, &CertData->MonotonicCount, sizeof (UINT64));\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  Status  = Sha256Final (mHashCtx, Digest);\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  //\r
-  // Generate & Initialize RSA Context.\r
-  //\r
-  Rsa = RsaNew ();\r
-  ASSERT (Rsa != NULL);\r
-  //\r
-  // Set RSA Key Components.\r
-  // NOTE: Only N and E are needed to be set as RSA public key for signature verification.\r
-  //\r
-  Status = RsaSetKey (Rsa, RsaKeyN, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  //\r
-  // Verify the signature.\r
-  //\r
-  Status = RsaPkcs1Verify (\r
-             Rsa,\r
-             Digest,\r
-             SHA256_DIGEST_SIZE,\r
-             CertBlock->Signature,\r
-             EFI_CERT_TYPE_RSA2048_SHA256_SIZE\r
-             );\r
-\r
-Done:\r
-  if (Rsa != NULL) {\r
-    RsaFree (Rsa);\r
-  }\r
-  if (Status) {\r
-    return EFI_SUCCESS;\r
-  } else {\r
-    return EFI_SECURITY_VIOLATION;\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_SUCCESS;\r
+    }\r
+    SecureBootEnable = SECURE_BOOT_DISABLE;\r
+    VariableDataSize = 0;\r
   }\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
@@ -1712,121 +537,6 @@ 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
-  VOID          *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 (*(UINT8 *)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
@@ -1865,7 +575,6 @@ 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
@@ -1880,51 +589,18 @@ ProcessVarWithPk (
   // Init state of Del. State may change due to secure check\r
   //\r
   Del = FALSE;\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
+  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
 \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
@@ -1937,17 +613,10 @@ ProcessVarWithPk (
       return Status;\r
     }\r
 \r
-    if (((mSecureBootMode != SecureBootModeTypeSetupMode) && (mSecureBootMode != SecureBootModeTypeAuditMode)) || IsPk) {\r
+    if ((mPlatformMode != SETUP_MODE) || IsPk) {\r
       Status = VendorKeyIsModified ();\r
     }\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
+  } else if (mPlatformMode == USER_MODE) {\r
     //\r
     // Verify against X509 Cert in PK database.\r
     //\r
@@ -1962,19 +631,8 @@ 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
@@ -1987,30 +645,16 @@ ProcessVarWithPk (
   }\r
 \r
   if (!EFI_ERROR(Status) && IsPk) {\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
+    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
   }\r
 \r
@@ -2063,8 +707,7 @@ ProcessVarWithKek (
   }\r
 \r
   Status = EFI_SUCCESS;\r
-  if ((mSecureBootMode == SecureBootModeTypeUserMode || mSecureBootMode == SecureBootModeTypeDeployedMode)\r
-   && !(InCustomMode() && UserPhysicalPresent())) {\r
+  if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) {\r
     //\r
     // Time-based, verify against X509 Cert KEK.\r
     //\r
@@ -2101,7 +744,7 @@ ProcessVarWithKek (
       return Status;\r
     }\r
 \r
-    if ((mSecureBootMode != SecureBootModeTypeSetupMode) && (mSecureBootMode != SecureBootModeTypeAuditMode)) {\r
+    if (mPlatformMode != SETUP_MODE) {\r
       Status = VendorKeyIsModified ();\r
     }\r
   }\r
@@ -2159,7 +802,7 @@ IsDeleteAuthVariable (
 }\r
 \r
 /**\r
-  Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set\r
+  Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set\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
@@ -2176,9 +819,9 @@ IsDeleteAuthVariable (
 \r
   @return EFI_INVALID_PARAMETER           Invalid parameter.\r
   @return EFI_WRITE_PROTECTED             Variable is write-protected and needs authentication with\r
-                                          EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.\r
+                                          EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.\r
   @return EFI_OUT_OF_RESOURCES            The Database to save the public key is full.\r
-  @return EFI_SECURITY_VIOLATION          The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\r
+  @return EFI_SECURITY_VIOLATION          The variable is with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\r
                                           set, but the AuthInfo does NOT pass the validation\r
                                           check carried out by the firmware.\r
   @return EFI_SUCCESS                     Variable is not write-protected or pass validation successfully.\r
@@ -2194,22 +837,8 @@ ProcessVariable (
   )\r
 {\r
   EFI_STATUS                      Status;\r
-  BOOLEAN                         IsDeletion;\r
-  BOOLEAN                         IsFirstTime;\r
-  UINT8                           *PubKey;\r
-  EFI_VARIABLE_AUTHENTICATION     *CertData;\r
-  EFI_CERT_BLOCK_RSA_2048_SHA256  *CertBlock;\r
-  UINT32                          KeyIndex;\r
-  UINT64                          MonotonicCount;\r
-  VARIABLE_ENTRY_CONSISTENCY      VariableDataEntry;\r
-  UINT32                          Index;\r
   AUTH_VARIABLE_INFO              OrgVariableInfo;\r
 \r
-  KeyIndex    = 0;\r
-  CertData    = NULL;\r
-  CertBlock   = NULL;\r
-  PubKey      = NULL;\r
-  IsDeletion  = FALSE;\r
   Status      = EFI_SUCCESS;\r
 \r
   ZeroMem (&OrgVariableInfo, sizeof (OrgVariableInfo));\r
@@ -2221,7 +850,7 @@ ProcessVariable (
 \r
   if ((!EFI_ERROR (Status)) && IsDeleteAuthVariable (OrgVariableInfo.Attributes, Data, DataSize, Attributes) && UserPhysicalPresent()) {\r
     //\r
-    // Allow the delete operation of common authenticated variable at user physical presence.\r
+    // Allow the delete operation of common authenticated variable(AT or AW) at user physical presence.\r
     //\r
     Status = AuthServiceInternalUpdateVariable (\r
               VariableName,\r
@@ -2245,25 +874,15 @@ ProcessVariable (
   }\r
 \r
   //\r
-  // A time-based authenticated variable and a count-based authenticated variable\r
-  // can't be updated by each other.\r
-  //\r
-  if (OrgVariableInfo.Data != NULL) {\r
-    if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) &&\r
-        ((OrgVariableInfo.Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0)) {\r
-      return EFI_SECURITY_VIOLATION;\r
-    }\r
-\r
-    if (((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) &&\r
-        ((OrgVariableInfo.Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0)) {\r
-      return EFI_SECURITY_VIOLATION;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Process Time-based Authenticated variable.\r
-  //\r
-  if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+  if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+    //\r
+    // Reject Counter Based Auth Variable processing request.\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  } else if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+    //\r
+    // Process Time-based Authenticated variable.\r
+    //\r
     return VerifyTimeBasedPayloadAndUpdate (\r
              VariableName,\r
              VendorGuid,\r
@@ -2275,117 +894,20 @@ ProcessVariable (
              );\r
   }\r
 \r
-  //\r
-  // Determine if first time SetVariable with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS.\r
-  //\r
-  if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
-    //\r
-    // Determine current operation type.\r
-    //\r
-    if (DataSize == AUTHINFO_SIZE) {\r
-      IsDeletion = TRUE;\r
-    }\r
-    //\r
-    // Determine whether this is the first time with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.\r
-    //\r
-    if (OrgVariableInfo.Data == NULL) {\r
-      IsFirstTime = TRUE;\r
-    } else if ((OrgVariableInfo.Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {\r
-      IsFirstTime = TRUE;\r
-    } else {\r
-      KeyIndex   = OrgVariableInfo.PubKeyIndex;\r
-      IsFirstTime = FALSE;\r
-    }\r
-  } else if ((OrgVariableInfo.Data != NULL) &&\r
-             ((OrgVariableInfo.Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) != 0)\r
-            ) {\r
+  if ((OrgVariableInfo.Data != NULL) &&\r
+     ((OrgVariableInfo.Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) != 0)) {\r
     //\r
     // If the variable is already write-protected, it always needs authentication before update.\r
     //\r
     return EFI_WRITE_PROTECTED;\r
-  } else {\r
-    //\r
-    // If without EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, set and attributes collision.\r
-    // That means it is not authenticated variable, just update variable as usual.\r
-    //\r
-    Status = AuthServiceInternalUpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes);\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Get PubKey and check Monotonic Count value corresponding to the variable.\r
-  //\r
-  CertData  = (EFI_VARIABLE_AUTHENTICATION *) Data;\r
-  CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);\r
-  PubKey    = CertBlock->PublicKey;\r
-\r
-  //\r
-  // Update Monotonic Count value.\r
-  //\r
-  MonotonicCount = CertData->MonotonicCount;\r
-\r
-  if (!IsFirstTime) {\r
-    //\r
-    // 2 cases need to check here\r
-    //   1. Internal PubKey variable. PubKeyIndex is always 0\r
-    //   2. Other counter-based AuthVariable. Check input PubKey.\r
-    //\r
-    if (KeyIndex == 0) {\r
-      return EFI_SECURITY_VIOLATION;\r
-    }\r
-    for (Index = 0; Index < mPubKeyNumber; Index++) {\r
-      if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + Index)->KeyIndex)) == KeyIndex) {\r
-        if (CompareMem (((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + Index)->KeyData, PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {\r
-          break;\r
-        } else {\r
-          return EFI_SECURITY_VIOLATION;\r
-        }\r
-      }\r
-    }\r
-    if (Index == mPubKeyNumber) {\r
-      return EFI_SECURITY_VIOLATION;\r
-    }\r
-\r
-    //\r
-    // Compare the current monotonic count and ensure that it is greater than the last SetVariable\r
-    // operation with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute set.\r
-    //\r
-    if (MonotonicCount <= OrgVariableInfo.MonotonicCount) {\r
-      //\r
-      // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.\r
-      //\r
-      return EFI_SECURITY_VIOLATION;\r
-    }\r
-  }\r
-  //\r
-  // Verify the certificate in Data payload.\r
-  //\r
-  Status = VerifyCounterBasedPayload (Data, DataSize, PubKey);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
   }\r
 \r
   //\r
-  // Now, the signature has been verified!\r
+  // Not authenticated variable, just update variable as usual.\r
   //\r
-  if (IsFirstTime && !IsDeletion) {\r
-    VariableDataEntry.VariableSize = DataSize - AUTHINFO_SIZE;\r
-    VariableDataEntry.Guid         = VendorGuid;\r
-    VariableDataEntry.Name         = VariableName;\r
-\r
-    //\r
-    // Update public key database variable if need.\r
-    //\r
-    KeyIndex = AddPubKeyInStore (PubKey, &VariableDataEntry);\r
-    if (KeyIndex == 0) {\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-  }\r
+  Status = AuthServiceInternalUpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes);\r
+  return Status;\r
 \r
-  //\r
-  // Verification pass.\r
-  //\r
-  return AuthServiceInternalUpdateVariableWithMonotonicCount (VariableName, VendorGuid, (UINT8*)Data + AUTHINFO_SIZE, DataSize - AUTHINFO_SIZE, Attributes, KeyIndex, MonotonicCount);\r
 }\r
 \r
 /**\r
@@ -2542,6 +1064,89 @@ AuthServiceInternalCompareTimeStamp (
   return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);\r
 }\r
 \r
+/**\r
+  Calculate SHA256 digest of SignerCert CommonName + ToplevelCert tbsCertificate\r
+  SignerCert and ToplevelCert are inside the signer certificate chain.\r
+\r
+  @param[in]  SignerCert          A pointer to SignerCert data.\r
+  @param[in]  SignerCertSize      Length of SignerCert data.\r
+  @param[in]  TopLevelCert        A pointer to TopLevelCert data.\r
+  @param[in]  TopLevelCertSize    Length of TopLevelCert data.\r
+  @param[out] Sha256Digest       Sha256 digest calculated.\r
+\r
+  @return EFI_ABORTED          Digest process failed.\r
+  @return EFI_SUCCESS          SHA256 Digest is succesfully calculated.\r
+\r
+**/\r
+EFI_STATUS\r
+CalculatePrivAuthVarSignChainSHA256Digest(\r
+  IN     UINT8            *SignerCert,\r
+  IN     UINTN            SignerCertSize,\r
+  IN     UINT8            *TopLevelCert,\r
+  IN     UINTN            TopLevelCertSize,\r
+  OUT    UINT8            *Sha256Digest\r
+  )\r
+{\r
+  UINT8                   *TbsCert;\r
+  UINTN                   TbsCertSize;\r
+  CHAR8                   CertCommonName[128];\r
+  UINTN                   CertCommonNameSize;\r
+  BOOLEAN                 CryptoStatus;\r
+  EFI_STATUS              Status;\r
+\r
+  CertCommonNameSize = sizeof(CertCommonName);\r
+\r
+  //\r
+  // Get SignerCert CommonName\r
+  //\r
+  Status = X509GetCommonName(SignerCert, SignerCertSize, CertCommonName, &CertCommonNameSize);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG((DEBUG_INFO, "%a Get SignerCert CommonName failed with status %x\n", __FUNCTION__, Status));\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  //\r
+  // Get TopLevelCert tbsCertificate\r
+  //\r
+  if (!X509GetTBSCert(TopLevelCert, TopLevelCertSize, &TbsCert, &TbsCertSize)) {\r
+    DEBUG((DEBUG_INFO, "%a Get Top-level Cert tbsCertificate failed!\n", __FUNCTION__));\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  //\r
+  // Digest SignerCert CN + TopLevelCert tbsCertificate\r
+  //\r
+  ZeroMem (Sha256Digest, SHA256_DIGEST_SIZE);\r
+  CryptoStatus = Sha256Init (mHashCtx);\r
+  if (!CryptoStatus) {\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  //\r
+  // '\0' is forced in CertCommonName. No overflow issue\r
+  //\r
+  CryptoStatus = Sha256Update (\r
+                   mHashCtx,\r
+                   CertCommonName,\r
+                   AsciiStrLen (CertCommonName)\r
+                   );\r
+  if (!CryptoStatus) {\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  CryptoStatus = Sha256Update (mHashCtx, TbsCert, TbsCertSize);\r
+  if (!CryptoStatus) {\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  CryptoStatus  = Sha256Final (mHashCtx, Sha256Digest);\r
+  if (!CryptoStatus) {\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Find matching signer's certificates for common authenticated variable\r
   by corresponding VariableName and VendorGuid from "certdb" or "certdbv".\r
@@ -2885,13 +1490,16 @@ DeleteCertsFromDb (
 /**\r
   Insert signer's certificates for common authenticated variable with VariableName\r
   and VendorGuid in AUTH_CERT_DB_DATA to "certdb" or "certdbv" according to\r
-  time based authenticated variable attributes.\r
+  time based authenticated variable attributes. CertData is the SHA256 digest of\r
+  SignerCert CommonName + TopLevelCert tbsCertificate.\r
 \r
-  @param[in]  VariableName   Name of authenticated Variable.\r
-  @param[in]  VendorGuid     Vendor GUID of authenticated Variable.\r
-  @param[in]  Attributes     Attributes of authenticated variable.\r
-  @param[in]  CertData       Pointer to signer's certificates.\r
-  @param[in]  CertDataSize   Length of CertData in bytes.\r
+  @param[in]  VariableName      Name of authenticated Variable.\r
+  @param[in]  VendorGuid        Vendor GUID of authenticated Variable.\r
+  @param[in]  Attributes        Attributes of authenticated variable.\r
+  @param[in]  SignerCert        Signer certificate data.\r
+  @param[in]  SignerCertSize    Length of signer certificate.\r
+  @param[in]  TopLevelCert      Top-level certificate data.\r
+  @param[in]  TopLevelCertSize  Length of top-level certificate.\r
 \r
   @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.\r
   @retval  EFI_ACCESS_DENIED     An AUTH_CERT_DB_DATA entry with same VariableName\r
@@ -2905,8 +1513,10 @@ InsertCertsToDb (
   IN     CHAR16           *VariableName,\r
   IN     EFI_GUID         *VendorGuid,\r
   IN     UINT32           Attributes,\r
-  IN     UINT8            *CertData,\r
-  IN     UINTN            CertDataSize\r
+  IN     UINT8            *SignerCert,\r
+  IN     UINTN            SignerCertSize,\r
+  IN     UINT8            *TopLevelCert,\r
+  IN     UINTN            TopLevelCertSize\r
   )\r
 {\r
   EFI_STATUS              Status;\r
@@ -2917,10 +1527,12 @@ InsertCertsToDb (
   UINT32                  NewCertDbSize;\r
   UINT32                  CertNodeSize;\r
   UINT32                  NameSize;\r
+  UINT32                  CertDataSize;\r
   AUTH_CERT_DB_DATA       *Ptr;\r
   CHAR16                  *DbName;\r
+  UINT8                   Sha256Digest[SHA256_DIGEST_SIZE];\r
 \r
-  if ((VariableName == NULL) || (VendorGuid == NULL) || (CertData == NULL)) {\r
+  if ((VariableName == NULL) || (VendorGuid == NULL) || (SignerCert == NULL) ||(TopLevelCert == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -2980,11 +1592,24 @@ InsertCertsToDb (
   // Construct new data content of variable "certdb" or "certdbv".\r
   //\r
   NameSize      = (UINT32) StrLen (VariableName);\r
+  CertDataSize  = sizeof(Sha256Digest);\r
   CertNodeSize  = sizeof (AUTH_CERT_DB_DATA) + (UINT32) CertDataSize + NameSize * sizeof (CHAR16);\r
   NewCertDbSize = (UINT32) DataSize + CertNodeSize;\r
   if (NewCertDbSize > mMaxCertDbSize) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+\r
+  Status = CalculatePrivAuthVarSignChainSHA256Digest(\r
+             SignerCert,\r
+             SignerCertSize,\r
+             TopLevelCert,\r
+             TopLevelCertSize,\r
+             Sha256Digest\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   NewCertDb     = (UINT8*) mCertDbStore;\r
 \r
   //\r
@@ -3012,7 +1637,7 @@ InsertCertsToDb (
 \r
   CopyMem (\r
     (UINT8 *) Ptr +  sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16),\r
-    CertData,\r
+    Sha256Digest,\r
     CertDataSize\r
     );\r
 \r
@@ -3115,7 +1740,7 @@ CleanCertsFromDb (
                                        &AuthVariableInfo\r
                                        );\r
 \r
-      if (EFI_ERROR(Status)) {\r
+      if (EFI_ERROR(Status) || (AuthVariableInfo.Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {\r
         Status      = DeleteCertsFromDb(\r
                         VariableName,\r
                         &AuthVarGuid,\r
@@ -3194,20 +1819,30 @@ VerifyTimeBasedPayload (
   UINTN                            NewDataSize;\r
   UINT8                            *Buffer;\r
   UINTN                            Length;\r
-  UINT8                            *RootCert;\r
-  UINTN                            RootCertSize;\r
+  UINT8                            *TopLevelCert;\r
+  UINTN                            TopLevelCertSize;\r
+  UINT8                            *TrustedCert;\r
+  UINTN                            TrustedCertSize;\r
   UINT8                            *SignerCerts;\r
   UINTN                            CertStackSize;\r
   UINT8                            *CertsInCertDb;\r
   UINT32                           CertsSizeinDb;\r
+  UINT8                            Sha256Digest[SHA256_DIGEST_SIZE];\r
+  EFI_CERT_DATA                    *CertDataPtr;\r
 \r
+  //\r
+  // 1. TopLevelCert is the top-level issuer certificate in signature Signer Cert Chain\r
+  // 2. TrustedCert is the certificate which firmware trusts. It could be saved in protected\r
+  //     storage or PK payload on PK init\r
+  //\r
   VerifyStatus           = FALSE;\r
   CertData               = NULL;\r
   NewData                = NULL;\r
   Attr                   = Attributes;\r
   SignerCerts            = NULL;\r
-  RootCert               = NULL;\r
+  TopLevelCert           = NULL;\r
   CertsInCertDb          = NULL;\r
+  CertDataPtr            = NULL;\r
 \r
   //\r
   // When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is\r
@@ -3259,6 +1894,29 @@ VerifyTimeBasedPayload (
   SigData = CertData->AuthInfo.CertData;\r
   SigDataSize = CertData->AuthInfo.Hdr.dwLength - (UINT32) (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData));\r
 \r
+  //\r
+  // SignedData.digestAlgorithms shall contain the digest algorithm used when preparing the\r
+  // signature. Only a digest algorithm of SHA-256 is accepted.\r
+  //\r
+  //    According to PKCS#7 Definition:\r
+  //        SignedData ::= SEQUENCE {\r
+  //            version Version,\r
+  //            digestAlgorithms DigestAlgorithmIdentifiers,\r
+  //            contentInfo ContentInfo,\r
+  //            .... }\r
+  //    The DigestAlgorithmIdentifiers can be used to determine the hash algorithm \r
+  //    in VARIABLE_AUTHENTICATION_2 descriptor.\r
+  //    This field has the fixed offset (+13) and be calculated based on two bytes of length encoding.\r
+  //\r
+  if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+    if (SigDataSize >= (13 + sizeof (mSha256OidValue))) {\r
+      if (((*(SigData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) || \r
+           (CompareMem (SigData + 13, &mSha256OidValue, sizeof (mSha256OidValue)) != 0)) {\r
+          return EFI_SECURITY_VIOLATION;\r
+        }\r
+    }\r
+  }\r
+\r
   //\r
   // Find out the new data payload which follows Pkcs7 SignedData directly.\r
   //\r
@@ -3315,8 +1973,8 @@ VerifyTimeBasedPayload (
                      SigDataSize,\r
                      &SignerCerts,\r
                      &CertStackSize,\r
-                     &RootCert,\r
-                     &RootCertSize\r
+                     &TopLevelCert,\r
+                     &TopLevelCertSize\r
                      );\r
     if (!VerifyStatus) {\r
       goto Exit;\r
@@ -3338,8 +1996,8 @@ VerifyTimeBasedPayload (
     }\r
     CertList = (EFI_SIGNATURE_LIST *) Data;\r
     Cert     = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
-    if ((RootCertSize != (CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1))) ||\r
-        (CompareMem (Cert->SignatureData, RootCert, RootCertSize) != 0)) {\r
+    if ((TopLevelCertSize != (CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1))) ||\r
+        (CompareMem (Cert->SignatureData, TopLevelCert, TopLevelCertSize) != 0)) {\r
       VerifyStatus = FALSE;\r
       goto Exit;\r
     }\r
@@ -3350,8 +2008,8 @@ VerifyTimeBasedPayload (
     VerifyStatus = Pkcs7Verify (\r
                      SigData,\r
                      SigDataSize,\r
-                     RootCert,\r
-                     RootCertSize,\r
+                     TopLevelCert,\r
+                     TopLevelCertSize,\r
                      NewData,\r
                      NewDataSize\r
                      );\r
@@ -3384,8 +2042,8 @@ VerifyTimeBasedPayload (
           //\r
           // Iterate each Signature Data Node within this CertList for a verify\r
           //\r
-          RootCert      = Cert->SignatureData;\r
-          RootCertSize  = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
+          TrustedCert      = Cert->SignatureData;\r
+          TrustedCertSize  = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
 \r
           //\r
           // Verify Pkcs7 SignedData via Pkcs7Verify library.\r
@@ -3393,8 +2051,8 @@ VerifyTimeBasedPayload (
           VerifyStatus = Pkcs7Verify (\r
                            SigData,\r
                            SigDataSize,\r
-                           RootCert,\r
-                           RootCertSize,\r
+                           TrustedCert,\r
+                           TrustedCertSize,\r
                            NewData,\r
                            NewDataSize\r
                            );\r
@@ -3418,8 +2076,8 @@ VerifyTimeBasedPayload (
                      SigDataSize,\r
                      &SignerCerts,\r
                      &CertStackSize,\r
-                     &RootCert,\r
-                     &RootCertSize\r
+                     &TopLevelCert,\r
+                     &TopLevelCertSize\r
                      );\r
     if (!VerifyStatus) {\r
       goto Exit;\r
@@ -3438,17 +2096,37 @@ VerifyTimeBasedPayload (
         goto Exit;\r
       }\r
 \r
-      if ((CertStackSize != CertsSizeinDb) ||\r
-          (CompareMem (SignerCerts, CertsInCertDb, CertsSizeinDb) != 0)) {\r
-        goto Exit;\r
+      if (CertsSizeinDb == SHA256_DIGEST_SIZE) {\r
+        //\r
+        // Check hash of signer cert CommonName + Top-level issuer tbsCertificate against data in CertDb\r
+        //\r
+        CertDataPtr = (EFI_CERT_DATA *)(SignerCerts + 1);\r
+        Status = CalculatePrivAuthVarSignChainSHA256Digest(\r
+                   CertDataPtr->CertDataBuffer,\r
+                   ReadUnaligned32 ((UINT32 *)&(CertDataPtr->CertDataLength)),\r
+                   TopLevelCert,\r
+                   TopLevelCertSize,\r
+                   Sha256Digest\r
+                   );\r
+        if (EFI_ERROR(Status) || CompareMem (Sha256Digest, CertsInCertDb, CertsSizeinDb) != 0){\r
+          goto Exit;\r
+        }\r
+      } else {\r
+         //\r
+         // Keep backward compatible with previous solution which saves whole signer certs stack in CertDb\r
+         //\r
+         if ((CertStackSize != CertsSizeinDb) ||\r
+             (CompareMem (SignerCerts, CertsInCertDb, CertsSizeinDb) != 0)) {\r
+              goto Exit;\r
+         }\r
       }\r
     }\r
 \r
     VerifyStatus = Pkcs7Verify (\r
                      SigData,\r
                      SigDataSize,\r
-                     RootCert,\r
-                     RootCertSize,\r
+                     TopLevelCert,\r
+                     TopLevelCertSize,\r
                      NewData,\r
                      NewDataSize\r
                      );\r
@@ -3458,9 +2136,18 @@ VerifyTimeBasedPayload (
 \r
     if ((OrgTimeStamp == NULL) && (PayloadSize != 0)) {\r
       //\r
-      // Insert signer's certificates when adding a new common authenticated variable.\r
+      // When adding a new common authenticated variable, always save Hash of cn of signer cert + tbsCertificate of Top-level issuer\r
       //\r
-      Status = InsertCertsToDb (VariableName, VendorGuid, Attributes, SignerCerts, CertStackSize);\r
+      CertDataPtr = (EFI_CERT_DATA *)(SignerCerts + 1);\r
+      Status = InsertCertsToDb (\r
+                 VariableName,\r
+                 VendorGuid,\r
+                 Attributes,\r
+                 CertDataPtr->CertDataBuffer,\r
+                 ReadUnaligned32 ((UINT32 *)&(CertDataPtr->CertDataLength)),\r
+                 TopLevelCert,\r
+                 TopLevelCertSize\r
+                 );\r
       if (EFI_ERROR (Status)) {\r
         VerifyStatus = FALSE;\r
         goto Exit;\r
@@ -3469,16 +2156,16 @@ VerifyTimeBasedPayload (
   } else if (AuthVarType == AuthVarTypePayload) {\r
     CertList = (EFI_SIGNATURE_LIST *) PayloadPtr;\r
     Cert     = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
-    RootCert      = Cert->SignatureData;\r
-    RootCertSize  = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
+    TrustedCert     = Cert->SignatureData;\r
+    TrustedCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
     //\r
     // Verify Pkcs7 SignedData via Pkcs7Verify library.\r
     //\r
     VerifyStatus = Pkcs7Verify (\r
                      SigData,\r
                      SigDataSize,\r
-                     RootCert,\r
-                     RootCertSize,\r
+                     TrustedCert,\r
+                     TrustedCertSize,\r
                      NewData,\r
                      NewDataSize\r
                      );\r
@@ -3489,7 +2176,7 @@ VerifyTimeBasedPayload (
 Exit:\r
 \r
   if (AuthVarType == AuthVarTypePk || AuthVarType == AuthVarTypePriv) {\r
-    Pkcs7FreeSigners (RootCert);\r
+    Pkcs7FreeSigners (TopLevelCert);\r
     Pkcs7FreeSigners (SignerCerts);\r
   }\r
 \r