What to do:
1. Implement AuthVariableLib library instance.
2. Temporarily add VARIABLE_ENTRY_CONSISTENCY and
variable attribute combinations definitions to
AuthenticatedVariableFormat.h for git bisect.

Why to do:
1. Share code.
Separate auth variable service from Auth Variable driver in
SecurityPkg to AuthVariableLib. Then the AuthVariableLib could benefit
and be used by different implementation of Auth Variable drivers.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.z...@intel.com>
Reviewed-by: Jiewen Yao <jiewen....@intel.com>
Reviewed-by: Liming Gao <liming....@intel.com>
---
 .../Include/Guid/AuthenticatedVariableFormat.h     |   17 +
 SecurityPkg/Library/AuthVariableLib/AuthService.c  | 2432 ++++++++++++++++++++
 .../Library/AuthVariableLib/AuthServiceInternal.h  |  411 ++++
 .../Library/AuthVariableLib/AuthVariableLib.c      |  460 ++++
 .../Library/AuthVariableLib/AuthVariableLib.inf    |   86 +
 .../Library/AuthVariableLib/AuthVariableLib.uni    |  Bin 0 -> 1670 bytes
 SecurityPkg/SecurityPkg.dsc                        |    4 +-
 .../VariableAuthenticated/RuntimeDxe/Variable.h    |    6 -
 8 files changed, 3409 insertions(+), 7 deletions(-)
 create mode 100644 SecurityPkg/Library/AuthVariableLib/AuthService.c
 create mode 100644 SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h
 create mode 100644 SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c
 create mode 100644 SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
 create mode 100644 SecurityPkg/Library/AuthVariableLib/AuthVariableLib.uni

diff --git a/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h 
b/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h
index 66947e1..c7cd34a 100644
--- a/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h
+++ b/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h
@@ -147,6 +147,17 @@ typedef struct {
 #define VAR_ADDED                     0x3f  ///< Variable has been completely 
added.
 
 ///
+/// Variable Attribute combinations.
+///
+#define VARIABLE_ATTRIBUTE_NV_BS        (EFI_VARIABLE_NON_VOLATILE | 
EFI_VARIABLE_BOOTSERVICE_ACCESS)
+#define VARIABLE_ATTRIBUTE_BS_RT        (EFI_VARIABLE_BOOTSERVICE_ACCESS | 
EFI_VARIABLE_RUNTIME_ACCESS)
+#define VARIABLE_ATTRIBUTE_AT_AW        
(EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
+#define VARIABLE_ATTRIBUTE_NV_BS_RT     (VARIABLE_ATTRIBUTE_BS_RT | 
EFI_VARIABLE_NON_VOLATILE)
+#define VARIABLE_ATTRIBUTE_NV_BS_RT_HR  (VARIABLE_ATTRIBUTE_NV_BS_RT | 
EFI_VARIABLE_HARDWARE_ERROR_RECORD)
+#define VARIABLE_ATTRIBUTE_NV_BS_RT_AT  (VARIABLE_ATTRIBUTE_NV_BS_RT | 
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
+#define VARIABLE_ATTRIBUTE_NV_BS_RT_AW  (VARIABLE_ATTRIBUTE_NV_BS_RT | 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
+#define VARIABLE_ATTRIBUTE_NV_BS_RT_HR_AT_AW    
(VARIABLE_ATTRIBUTE_NV_BS_RT_HR | VARIABLE_ATTRIBUTE_AT_AW)
+
 /// Single Variable Data Header Structure.
 ///
 typedef struct {
@@ -189,6 +200,12 @@ typedef struct {
   EFI_GUID    VendorGuid;
 } VARIABLE_HEADER;
 
+typedef struct {
+  EFI_GUID    *Guid;
+  CHAR16      *Name;
+  UINTN       VariableSize;
+} VARIABLE_ENTRY_CONSISTENCY;
+
 #pragma pack()
 
 typedef struct _VARIABLE_INFO_ENTRY  VARIABLE_INFO_ENTRY;
diff --git a/SecurityPkg/Library/AuthVariableLib/AuthService.c 
b/SecurityPkg/Library/AuthVariableLib/AuthService.c
new file mode 100644
index 0000000..415befb
--- /dev/null
+++ b/SecurityPkg/Library/AuthVariableLib/AuthService.c
@@ -0,0 +1,2432 @@
+/** @file
+  Implement authentication services for the authenticated variables.
+
+  Caution: This module requires additional review when modified.
+  This driver will have external input - variable data. It may be input in SMM 
mode.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+  Variable attribute should also be checked to avoid authentication bypass.
+     The whole SMM authentication variable design relies on the integrity of 
flash part and SMM.
+  which is assumed to be protected by platform.  All variable code and 
metadata in flash/SMM Memory
+  may not be modified without authorization. If platform fails to protect 
these resources,
+  the authentication service provided in this driver will be broken, and the 
behavior is undefined.
+
+  ProcessVarWithPk(), ProcessVarWithKek() and ProcessVariable() are the 
function to do
+  variable authentication.
+
+  VerifyTimeBasedPayloadAndUpdate() and VerifyCounterBasedPayload() are sub 
function to do verification.
+  They will do basic validation for authentication data structure, then call 
crypto library
+  to verify the signature.
+
+Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "AuthServiceInternal.h"
+
+//
+// Public Exponent of RSA Key.
+//
+CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
+
+//
+// Requirement for different signature type which have been defined in UEFI 
spec.
+// These data are used to perform SignatureList format check while setting 
PK/KEK variable.
+//
+EFI_SIGNATURE_ITEM mSupportSigItem[] = {
+//{SigType,                       SigHeaderSize,   SigDataSize  }
+  {EFI_CERT_SHA256_GUID,          0,               32           },
+  {EFI_CERT_RSA2048_GUID,         0,               256          },
+  {EFI_CERT_RSA2048_SHA256_GUID,  0,               256          },
+  {EFI_CERT_SHA1_GUID,            0,               20           },
+  {EFI_CERT_RSA2048_SHA1_GUID,    0,               256          },
+  {EFI_CERT_X509_GUID,            0,               ((UINT32) ~0)},
+  {EFI_CERT_SHA224_GUID,          0,               28           },
+  {EFI_CERT_SHA384_GUID,          0,               48           },
+  {EFI_CERT_SHA512_GUID,          0,               64           },
+  {EFI_CERT_X509_SHA256_GUID,     0,               48           },
+  {EFI_CERT_X509_SHA384_GUID,     0,               64           },
+  {EFI_CERT_X509_SHA512_GUID,     0,               80           }
+};
+
+/**
+  Finds variable in storage blocks of volatile and non-volatile storage areas.
+
+  This code finds variable in storage blocks of volatile and non-volatile 
storage areas.
+  If VariableName is an empty string, then we just return the first
+  qualified variable without comparing VariableName and VendorGuid.
+
+  @param[in]  VariableName          Name of the variable to be found.
+  @param[in]  VendorGuid            Variable vendor GUID to be found.
+  @param[out] Data                  Pointer to data address.
+  @param[out] DataSize              Pointer to data size.
+
+  @retval EFI_INVALID_PARAMETER     If VariableName is not an empty string,
+                                    while VendorGuid is NULL.
+  @retval EFI_SUCCESS               Variable successfully found.
+  @retval EFI_NOT_FOUND             Variable not found
+
+**/
+EFI_STATUS
+AuthServiceInternalFindVariable (
+  IN  CHAR16            *VariableName,
+  IN  EFI_GUID          *VendorGuid,
+  OUT VOID              **Data,
+  OUT UINTN             *DataSize
+  )
+{
+  EFI_STATUS            Status;
+  AUTH_VARIABLE_INFO    AuthVariableInfo;
+
+  ZeroMem (&AuthVariableInfo, sizeof (AuthVariableInfo));
+  Status = mAuthVarLibContextIn->FindVariable (
+           VariableName,
+           VendorGuid,
+           &AuthVariableInfo
+           );
+  *Data = AuthVariableInfo.Data;
+  *DataSize = AuthVariableInfo.DataSize;
+  return Status;
+}
+
+/**
+  Update the variable region with Variable information.
+
+  @param[in] VariableName           Name of variable.
+  @param[in] VendorGuid             Guid of variable.
+  @param[in] Data                   Data pointer.
+  @param[in] DataSize               Size of Data.
+  @param[in] Attributes             Attribute value of the variable.
+
+  @retval EFI_SUCCESS               The update operation is success.
+  @retval EFI_INVALID_PARAMETER     Invalid parameter.
+  @retval EFI_WRITE_PROTECTED       Variable is write-protected.
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.
+
+**/
+EFI_STATUS
+AuthServiceInternalUpdateVariable (
+  IN CHAR16             *VariableName,
+  IN EFI_GUID           *VendorGuid,
+  IN VOID               *Data,
+  IN UINTN              DataSize,
+  IN UINT32             Attributes
+  )
+{
+  AUTH_VARIABLE_INFO    AuthVariableInfo;
+
+  ZeroMem (&AuthVariableInfo, sizeof (AuthVariableInfo));
+  AuthVariableInfo.VariableName = VariableName;
+  AuthVariableInfo.VendorGuid = VendorGuid;
+  AuthVariableInfo.Data = Data;
+  AuthVariableInfo.DataSize = DataSize;
+  AuthVariableInfo.Attributes = Attributes;
+
+  return mAuthVarLibContextIn->UpdateVariable (
+           &AuthVariableInfo
+           );
+}
+
+/**
+  Update the variable region with Variable information.
+
+  @param[in] VariableName           Name of variable.
+  @param[in] VendorGuid             Guid of variable.
+  @param[in] Data                   Data pointer.
+  @param[in] DataSize               Size of Data.
+  @param[in] Attributes             Attribute value of the variable.
+  @param[in] KeyIndex               Index of associated public key.
+  @param[in] MonotonicCount         Value of associated monotonic count.
+
+  @retval EFI_SUCCESS               The update operation is success.
+  @retval EFI_INVALID_PARAMETER     Invalid parameter.
+  @retval EFI_WRITE_PROTECTED       Variable is write-protected.
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.
+
+**/
+EFI_STATUS
+AuthServiceInternalUpdateVariableWithMonotonicCount (
+  IN CHAR16             *VariableName,
+  IN EFI_GUID           *VendorGuid,
+  IN VOID               *Data,
+  IN UINTN              DataSize,
+  IN UINT32             Attributes,
+  IN UINT32             KeyIndex,
+  IN UINT64             MonotonicCount
+  )
+{
+  AUTH_VARIABLE_INFO    AuthVariableInfo;
+
+  ZeroMem (&AuthVariableInfo, sizeof (AuthVariableInfo));
+  AuthVariableInfo.VariableName = VariableName;
+  AuthVariableInfo.VendorGuid = VendorGuid;
+  AuthVariableInfo.Data = Data;
+  AuthVariableInfo.DataSize = DataSize;
+  AuthVariableInfo.Attributes = Attributes;
+  AuthVariableInfo.PubKeyIndex = KeyIndex;
+  AuthVariableInfo.MonotonicCount = MonotonicCount;
+
+  return mAuthVarLibContextIn->UpdateVariable (
+           &AuthVariableInfo
+           );
+}
+
+/**
+  Update the variable region with Variable information.
+
+  @param[in] VariableName           Name of variable.
+  @param[in] VendorGuid             Guid of variable.
+  @param[in] Data                   Data pointer.
+  @param[in] DataSize               Size of Data.
+  @param[in] Attributes             Attribute value of the variable.
+  @param[in] TimeStamp              Value of associated TimeStamp.
+
+  @retval EFI_SUCCESS               The update operation is success.
+  @retval EFI_INVALID_PARAMETER     Invalid parameter.
+  @retval EFI_WRITE_PROTECTED       Variable is write-protected.
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.
+
+**/
+EFI_STATUS
+AuthServiceInternalUpdateVariableWithTimeStamp (
+  IN CHAR16             *VariableName,
+  IN EFI_GUID           *VendorGuid,
+  IN VOID               *Data,
+  IN UINTN              DataSize,
+  IN UINT32             Attributes,
+  IN EFI_TIME           *TimeStamp
+  )
+{
+  EFI_STATUS            FindStatus;
+  VOID                  *OrgData;
+  UINTN                 OrgDataSize;
+  AUTH_VARIABLE_INFO    AuthVariableInfo;
+
+  FindStatus = AuthServiceInternalFindVariable (
+                 VariableName,
+                 VendorGuid,
+                 &OrgData,
+                 &OrgDataSize
+                 );
+
+  //
+  // EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable
+  //
+  if (!EFI_ERROR (FindStatus) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 
0)) {
+    if ((CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
+        ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp 
(VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) ||
+        (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0))) ||
+        (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp 
(VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) {
+      //
+      // For variables with formatted as EFI_SIGNATURE_LIST, the driver shall 
not perform an append of
+      // EFI_SIGNATURE_DATA values that are already part of the existing 
variable value.
+      //
+      FilterSignatureList (
+        OrgData,
+        OrgDataSize,
+        Data,
+        &DataSize
+        );
+    }
+  }
+
+  ZeroMem (&AuthVariableInfo, sizeof (AuthVariableInfo));
+  AuthVariableInfo.VariableName = VariableName;
+  AuthVariableInfo.VendorGuid = VendorGuid;
+  AuthVariableInfo.Data = Data;
+  AuthVariableInfo.DataSize = DataSize;
+  AuthVariableInfo.Attributes = Attributes;
+  AuthVariableInfo.TimeStamp = TimeStamp;
+  return mAuthVarLibContextIn->UpdateVariable (
+           &AuthVariableInfo
+           );
+}
+
+/**
+  Determine whether this operation needs a physical present user.
+
+  @param[in]      VariableName            Name of the Variable.
+  @param[in]      VendorGuid              GUID of the Variable.
+
+  @retval TRUE      This variable is protected, only a physical present user 
could set this variable.
+  @retval FALSE     This variable is not protected.
+
+**/
+BOOLEAN
+NeedPhysicallyPresent(
+  IN     CHAR16         *VariableName,
+  IN     EFI_GUID       *VendorGuid
+  )
+{
+  if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp 
(VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0))
+    || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp 
(VariableName, EFI_CUSTOM_MODE_NAME) == 0))) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Determine whether the platform is operating in Custom Secure Boot mode.
+
+  @retval TRUE           The platform is operating in Custom mode.
+  @retval FALSE          The platform is operating in Standard mode.
+
+**/
+BOOLEAN
+InCustomMode (
+  VOID
+  )
+{
+  EFI_STATUS    Status;
+  VOID          *Data;
+  UINTN         DataSize;
+
+  Status = AuthServiceInternalFindVariable (EFI_CUSTOM_MODE_NAME, 
&gEfiCustomModeEnableGuid, &Data, &DataSize);
+  if (!EFI_ERROR (Status) && (*(UINT8 *) Data == CUSTOM_SECURE_BOOT_MODE)) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Get available public key index.
+
+  @param[in] PubKey     Pointer to Public Key data.
+
+  @return Public key index, 0 if no any public key index available.
+
+**/
+UINT32
+GetAvailableKeyIndex (
+  IN  UINT8             *PubKey
+  )
+{
+  EFI_STATUS            Status;
+  UINT8                 *Data;
+  UINTN                 DataSize;
+  UINT8                 *Ptr;
+  UINT32                Index;
+  BOOLEAN               IsFound;
+  EFI_GUID              VendorGuid;
+  CHAR16                Name[1];
+  AUTH_VARIABLE_INFO    AuthVariableInfo;
+  UINT32                KeyIndex;
+
+  Status = AuthServiceInternalFindVariable (
+             AUTHVAR_KEYDB_NAME,
+             &gEfiAuthenticatedVariableGuid,
+             (VOID **) &Data,
+             &DataSize
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Get public key database variable failure, Status = 
%r\n", Status));
+    return 0;
+  }
+
+  if (mPubKeyNumber == mMaxKeyNumber) {
+    Name[0] = 0;
+    AuthVariableInfo.VariableName = Name;
+    ZeroMem (&VendorGuid, sizeof (VendorGuid));
+    AuthVariableInfo.VendorGuid = &VendorGuid;
+    mPubKeyNumber = 0;
+    //
+    // Collect valid key data.
+    //
+    do {
+      Status = mAuthVarLibContextIn->FindNextVariable 
(AuthVariableInfo.VariableName, AuthVariableInfo.VendorGuid, &AuthVariableInfo);
+      if (!EFI_ERROR (Status)) {
+        if (AuthVariableInfo.PubKeyIndex != 0) {
+          for (Ptr = Data; Ptr < (Data + DataSize); Ptr += sizeof 
(AUTHVAR_KEY_DB_DATA)) {
+            if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) Ptr)->KeyIndex)) 
== AuthVariableInfo.PubKeyIndex) {
+              //
+              // Check if the key data has been collected.
+              //
+              for (Index = 0; Index < mPubKeyNumber; Index++) {
+                if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + 
Index)->KeyIndex)) == AuthVariableInfo.PubKeyIndex) {
+                  break;
+                }
+              }
+              if (Index == mPubKeyNumber) {
+                //
+                // New key data.
+                //
+                CopyMem ((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + mPubKeyNumber, 
Ptr, sizeof (AUTHVAR_KEY_DB_DATA));
+                mPubKeyNumber++;
+              }
+              break;
+            }
+          }
+        }
+      }
+    } while (Status != EFI_NOT_FOUND);
+
+    //
+    // No available space to add new public key.
+    //
+    if (mPubKeyNumber == mMaxKeyNumber) {
+      return 0;
+    }
+  }
+
+  //
+  // Find available public key index.
+  //
+  for (KeyIndex = 1; KeyIndex <= mMaxKeyNumber; KeyIndex++) {
+    IsFound = FALSE; 
+    for (Ptr = mPubKeyStore; Ptr < (mPubKeyStore + mPubKeyNumber * sizeof 
(AUTHVAR_KEY_DB_DATA)); Ptr += sizeof (AUTHVAR_KEY_DB_DATA)) {
+      if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) Ptr)->KeyIndex)) == 
KeyIndex) {
+        IsFound = TRUE;
+        break;
+      }
+    }
+    if (!IsFound) {
+      break;
+    }
+  }
+
+  return KeyIndex;
+}
+
+/**
+  Add public key in store and return its index.
+
+  @param[in] PubKey             Input pointer to Public Key data.
+  @param[in] VariableDataEntry  The variable data entry.
+
+  @return Index of new added public key.
+
+**/
+UINT32
+AddPubKeyInStore (
+  IN  UINT8                        *PubKey,
+  IN  VARIABLE_ENTRY_CONSISTENCY   *VariableDataEntry
+  )
+{
+  EFI_STATUS                       Status;
+  UINT32                           Index;
+  VARIABLE_ENTRY_CONSISTENCY       PublicKeyEntry;
+  UINT32                           Attributes;
+  UINT32                           KeyIndex;
+
+  if (PubKey == NULL) {
+    return 0;
+  }
+
+  //
+  // Check whether the public key entry does exist.
+  //
+  for (Index = 0; Index < mPubKeyNumber; Index++) {
+    if (CompareMem (((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + Index)->KeyData, 
PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
+      return ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + 
Index)->KeyIndex));
+    }
+  }
+
+  KeyIndex = GetAvailableKeyIndex (PubKey);
+  if (KeyIndex == 0) {
+    return 0;
+  }
+
+  //
+  // Check the variable space for both public key and variable data.
+  //
+  PublicKeyEntry.VariableSize = (mPubKeyNumber + 1) * sizeof 
(AUTHVAR_KEY_DB_DATA);
+  PublicKeyEntry.Guid         = &gEfiAuthenticatedVariableGuid;
+  PublicKeyEntry.Name         = AUTHVAR_KEYDB_NAME;
+  Attributes = VARIABLE_ATTRIBUTE_NV_BS_RT | 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
+
+  if (!mAuthVarLibContextIn->CheckRemainingSpaceForConsistency (Attributes, 
&PublicKeyEntry, VariableDataEntry, NULL)) {
+    //
+    // No enough variable space.
+    //
+    return 0;
+  }
+
+  WriteUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + 
mPubKeyNumber)->KeyIndex), KeyIndex);
+  CopyMem (((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + mPubKeyNumber)->KeyData, 
PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
+  mPubKeyNumber++;
+
+  //
+  // Update public key database variable.
+  //
+  Status = AuthServiceInternalUpdateVariable (
+             AUTHVAR_KEYDB_NAME,
+             &gEfiAuthenticatedVariableGuid,
+             mPubKeyStore,
+             mPubKeyNumber * sizeof (AUTHVAR_KEY_DB_DATA),
+             Attributes
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Update public key database variable failure, Status 
= %r\n", Status));
+    return 0;
+  }
+
+  return KeyIndex;
+}
+
+/**
+  Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256_GUID type.
+  Follow the steps in UEFI2.2.
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode, and datasize and data are external 
input.
+  This function will do basic validation, before parse the data.
+  This function will parse the authentication carefully to avoid security 
issues, like
+  buffer overflow, integer overflow.
+
+  @param[in]      Data                    Pointer to data with AuthInfo.
+  @param[in]      DataSize                Size of Data.
+  @param[in]      PubKey                  Public key used for verification.
+
+  @retval EFI_INVALID_PARAMETER       Invalid parameter.
+  @retval EFI_SECURITY_VIOLATION      If authentication failed.
+  @retval EFI_SUCCESS                 Authentication successful.
+
+**/
+EFI_STATUS
+VerifyCounterBasedPayload (
+  IN     UINT8          *Data,
+  IN     UINTN          DataSize,
+  IN     UINT8          *PubKey
+  )
+{
+  BOOLEAN                         Status;
+  EFI_VARIABLE_AUTHENTICATION     *CertData;
+  EFI_CERT_BLOCK_RSA_2048_SHA256  *CertBlock;
+  UINT8                           Digest[SHA256_DIGEST_SIZE];
+  VOID                            *Rsa;
+  UINTN                           PayloadSize;
+
+  PayloadSize = DataSize - AUTHINFO_SIZE;
+  Rsa         = NULL;
+  CertData    = NULL;
+  CertBlock   = NULL;
+
+  if (Data == NULL || PubKey == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CertData  = (EFI_VARIABLE_AUTHENTICATION *) Data;
+  CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
+
+  //
+  // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
+  // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256_GUID.
+  //
+  if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||
+      !CompareGuid (&CertData->AuthInfo.CertType, 
&gEfiCertTypeRsa2048Sha256Guid)) {
+    //
+    // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
+    //
+    return EFI_SECURITY_VIOLATION;
+  }
+  //
+  // Hash data payload with SHA256.
+  //
+  ZeroMem (Digest, SHA256_DIGEST_SIZE);
+  Status  = Sha256Init (mHashCtx);
+  if (!Status) {
+    goto Done;
+  }
+  Status  = Sha256Update (mHashCtx, Data + AUTHINFO_SIZE, PayloadSize);
+  if (!Status) {
+    goto Done;
+  }
+  //
+  // Hash Size.
+  //
+  Status  = Sha256Update (mHashCtx, &PayloadSize, sizeof (UINTN));
+  if (!Status) {
+    goto Done;
+  }
+  //
+  // Hash Monotonic Count.
+  //
+  Status  = Sha256Update (mHashCtx, &CertData->MonotonicCount, sizeof 
(UINT64));
+  if (!Status) {
+    goto Done;
+  }
+  Status  = Sha256Final (mHashCtx, Digest);
+  if (!Status) {
+    goto Done;
+  }
+  //
+  // Generate & Initialize RSA Context.
+  //
+  Rsa = RsaNew ();
+  ASSERT (Rsa != NULL);
+  //
+  // Set RSA Key Components.
+  // NOTE: Only N and E are needed to be set as RSA public key for signature 
verification.
+  //
+  Status = RsaSetKey (Rsa, RsaKeyN, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
+  if (!Status) {
+    goto Done;
+  }
+  Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
+  if (!Status) {
+    goto Done;
+  }
+  //
+  // Verify the signature.
+  //
+  Status = RsaPkcs1Verify (
+             Rsa,
+             Digest,
+             SHA256_DIGEST_SIZE,
+             CertBlock->Signature,
+             EFI_CERT_TYPE_RSA2048_SHA256_SIZE
+             );
+
+Done:
+  if (Rsa != NULL) {
+    RsaFree (Rsa);
+  }
+  if (Status) {
+    return EFI_SUCCESS;
+  } else {
+    return EFI_SECURITY_VIOLATION;
+  }
+}
+
+/**
+  Update platform mode.
+
+  @param[in]      Mode                    SETUP_MODE or USER_MODE.
+
+  @return EFI_INVALID_PARAMETER           Invalid parameter.
+  @return EFI_SUCCESS                     Update platform mode successfully.
+
+**/
+EFI_STATUS
+UpdatePlatformMode (
+  IN  UINT32                    Mode
+  )
+{
+  EFI_STATUS              Status;
+  VOID                    *Data;
+  UINTN                   DataSize;
+  UINT8                   SecureBootMode;
+  UINT8                   SecureBootEnable;
+  UINTN                   VariableDataSize;
+
+  Status = AuthServiceInternalFindVariable (
+             EFI_SETUP_MODE_NAME,
+             &gEfiGlobalVariableGuid,
+             &Data,
+             &DataSize
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Update the value of SetupMode variable by a simple mem copy, this could 
avoid possible
+  // variable storage reclaim at runtime.
+  //
+  mPlatformMode = (UINT8) Mode;
+  CopyMem (Data, &mPlatformMode, sizeof(UINT8));
+
+  if (mAuthVarLibContextIn->AtRuntime ()) {
+    //
+    // SecureBoot Variable indicates whether the platform firmware is operating
+    // in Secure boot mode (1) or not (0), so we should not change SecureBoot
+    // Variable in runtime.
+    //
+    return Status;
+  }
+
+  //
+  // Check "SecureBoot" variable's existence.
+  // If it doesn't exist, firmware has no capability to perform driver signing 
verification,
+  // then set "SecureBoot" to 0.
+  //
+  Status = AuthServiceInternalFindVariable (
+             EFI_SECURE_BOOT_MODE_NAME,
+             &gEfiGlobalVariableGuid,
+             &Data,
+             &DataSize
+             );
+  //
+  // If "SecureBoot" variable exists, then check "SetupMode" variable update.
+  // If "SetupMode" variable is USER_MODE, "SecureBoot" variable is set to 1.
+  // If "SetupMode" variable is SETUP_MODE, "SecureBoot" variable is set to 0.
+  //
+  if (EFI_ERROR (Status)) {
+    SecureBootMode = SECURE_BOOT_MODE_DISABLE;
+  } else {
+    if (mPlatformMode == USER_MODE) {
+      SecureBootMode = SECURE_BOOT_MODE_ENABLE;
+    } else if (mPlatformMode == SETUP_MODE) {
+      SecureBootMode = SECURE_BOOT_MODE_DISABLE;
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  }
+
+  Status  = AuthServiceInternalUpdateVariable (
+              EFI_SECURE_BOOT_MODE_NAME,
+              &gEfiGlobalVariableGuid,
+              &SecureBootMode,
+              sizeof(UINT8),
+              EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
+              );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Check "SecureBootEnable" variable's existence. It can enable/disable 
secure boot feature.
+  //
+  Status = AuthServiceInternalFindVariable (
+             EFI_SECURE_BOOT_ENABLE_NAME,
+             &gEfiSecureBootEnableDisableGuid,
+             &Data,
+             &DataSize
+             );
+
+  if (SecureBootMode == SECURE_BOOT_MODE_ENABLE) {
+    //
+    // Create the "SecureBootEnable" variable as secure boot is enabled.
+    //
+    SecureBootEnable = SECURE_BOOT_ENABLE;
+    VariableDataSize = sizeof (SecureBootEnable);
+  } else {
+    //
+    // Delete the "SecureBootEnable" variable if this variable exist as 
"SecureBoot"
+    // variable is not in secure boot state.
+    //
+    if (EFI_ERROR (Status)) {
+      return EFI_SUCCESS;
+    }
+    SecureBootEnable = SECURE_BOOT_DISABLE;
+    VariableDataSize = 0;
+  }
+
+  Status = AuthServiceInternalUpdateVariable (
+             EFI_SECURE_BOOT_ENABLE_NAME,
+             &gEfiSecureBootEnableDisableGuid,
+             &SecureBootEnable,
+             VariableDataSize,
+             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS
+             );
+  return Status;
+}
+
+/**
+  Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for 
PK/KEK/db/dbx/dbt variable.
+
+  @param[in]  VariableName                Name of Variable to be check.
+  @param[in]  VendorGuid                  Variable vendor GUID.
+  @param[in]  Data                        Point to the variable data to be 
checked.
+  @param[in]  DataSize                    Size of Data.
+
+  @return EFI_INVALID_PARAMETER           Invalid signature list format.
+  @return EFI_SUCCESS                     Passed signature list format check 
successfully.
+
+**/
+EFI_STATUS
+CheckSignatureListFormat(
+  IN  CHAR16                    *VariableName,
+  IN  EFI_GUID                  *VendorGuid,
+  IN  VOID                      *Data,
+  IN  UINTN                     DataSize
+  )
+{
+  EFI_SIGNATURE_LIST     *SigList;
+  UINTN                  SigDataSize;
+  UINT32                 Index;
+  UINT32                 SigCount;
+  BOOLEAN                IsPk;
+  VOID                   *RsaContext;
+  EFI_SIGNATURE_DATA     *CertData;
+  UINTN                  CertLen;
+
+  if (DataSize == 0) {
+    return EFI_SUCCESS;
+  }
+
+  ASSERT (VariableName != NULL && VendorGuid != NULL && Data != NULL);
+
+  if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp 
(VariableName, EFI_PLATFORM_KEY_NAME) == 0)){
+    IsPk = TRUE;
+  } else if ((CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp 
(VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) ||
+             (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
+             ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || 
(StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) ||
+              (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0)))) {
+    IsPk = FALSE;
+  } else {
+    return EFI_SUCCESS;
+  }
+
+  SigCount = 0;
+  SigList  = (EFI_SIGNATURE_LIST *) Data;
+  SigDataSize  = DataSize;
+  RsaContext = NULL;
+
+  //
+  // Walk throuth the input signature list and check the data format.
+  // If any signature is incorrectly formed, the whole check will fail.
+  //
+  while ((SigDataSize > 0) && (SigDataSize >= SigList->SignatureListSize)) {
+    for (Index = 0; Index < (sizeof (mSupportSigItem) / sizeof 
(EFI_SIGNATURE_ITEM)); Index++ ) {
+      if (CompareGuid (&SigList->SignatureType, 
&mSupportSigItem[Index].SigType)) {
+        //
+        // The value of SignatureSize should always be 16 (size of 
SignatureOwner
+        // component) add the data length according to signature type.
+        //
+        if (mSupportSigItem[Index].SigDataSize != ((UINT32) ~0) &&
+          (SigList->SignatureSize - sizeof (EFI_GUID)) != 
mSupportSigItem[Index].SigDataSize) {
+          return EFI_INVALID_PARAMETER;
+        }
+        if (mSupportSigItem[Index].SigHeaderSize != ((UINT32) ~0) &&
+          SigList->SignatureHeaderSize != 
mSupportSigItem[Index].SigHeaderSize) {
+          return EFI_INVALID_PARAMETER;
+        }
+        break;
+      }
+    }
+
+    if (Index == (sizeof (mSupportSigItem) / sizeof (EFI_SIGNATURE_ITEM))) {
+      //
+      // Undefined signature type.
+      //
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if (CompareGuid (&SigList->SignatureType, &gEfiCertX509Guid)) {
+      //
+      // Try to retrieve the RSA public key from the X.509 certificate.
+      // If this operation fails, it's not a valid certificate.
+      //
+      RsaContext = RsaNew ();
+      if (RsaContext == NULL) {
+        return EFI_INVALID_PARAMETER;
+      }
+      CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof 
(EFI_SIGNATURE_LIST) + SigList->SignatureHeaderSize);
+      CertLen = SigList->SignatureSize - sizeof (EFI_GUID);
+      if (!RsaGetPublicKeyFromX509 (CertData->SignatureData, CertLen, 
&RsaContext)) {
+        RsaFree (RsaContext);
+        return EFI_INVALID_PARAMETER;
+      }
+      RsaFree (RsaContext);
+    }
+
+    if ((SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - 
SigList->SignatureHeaderSize) % SigList->SignatureSize != 0) {
+      return EFI_INVALID_PARAMETER;
+    }
+    SigCount += (SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - 
SigList->SignatureHeaderSize) / SigList->SignatureSize;
+
+    SigDataSize -= SigList->SignatureListSize;
+    SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + 
SigList->SignatureListSize);
+  }
+
+  if (((UINTN) SigList - (UINTN) Data) != DataSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (IsPk && SigCount > 1) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Update "VendorKeys" variable to record the out of band secure boot key 
modification.
+
+  @return EFI_SUCCESS           Variable is updated successfully.
+  @return Others                Failed to update variable.
+
+**/
+EFI_STATUS
+VendorKeyIsModified (
+  VOID
+  )
+{
+  EFI_STATUS              Status;
+
+  if (mVendorKeyState == VENDOR_KEYS_MODIFIED) {
+    return EFI_SUCCESS;
+  }
+  mVendorKeyState = VENDOR_KEYS_MODIFIED;
+
+  Status = AuthServiceInternalUpdateVariable (
+             EFI_VENDOR_KEYS_NV_VARIABLE_NAME,
+             &gEfiVendorKeysNvGuid,
+             &mVendorKeyState,
+             sizeof (UINT8),
+             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | 
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return AuthServiceInternalUpdateVariable (
+           EFI_VENDOR_KEYS_VARIABLE_NAME,
+           &gEfiGlobalVariableGuid,
+           &mVendorKeyState,
+           sizeof (UINT8),
+           EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
+           );
+}
+
+/**
+  Process variable with platform key for verification.
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode, and datasize and data are external 
input.
+  This function will do basic validation, before parse the data.
+  This function will parse the authentication carefully to avoid security 
issues, like
+  buffer overflow, integer overflow.
+  This function will check attribute carefully to avoid authentication bypass.
+
+  @param[in]  VariableName                Name of Variable to be found.
+  @param[in]  VendorGuid                  Variable vendor GUID.
+  @param[in]  Data                        Data pointer.
+  @param[in]  DataSize                    Size of Data found. If size is less 
than the
+                                          data, this value contains the 
required size.
+  @param[in]  Attributes                  Attribute value of the variable
+  @param[in]  IsPk                        Indicate whether it is to process pk.
+
+  @return EFI_INVALID_PARAMETER           Invalid parameter.
+  @return EFI_SECURITY_VIOLATION          The variable does NOT pass the 
validation.
+                                          check carried out by the firmware.
+  @return EFI_SUCCESS                     Variable passed validation 
successfully.
+
+**/
+EFI_STATUS
+ProcessVarWithPk (
+  IN  CHAR16                    *VariableName,
+  IN  EFI_GUID                  *VendorGuid,
+  IN  VOID                      *Data,
+  IN  UINTN                     DataSize,
+  IN  UINT32                    Attributes OPTIONAL,
+  IN  BOOLEAN                   IsPk
+  )
+{
+  EFI_STATUS                  Status;
+  BOOLEAN                     Del;
+  UINT8                       *Payload;
+  UINTN                       PayloadSize;
+
+  if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0 ||
+      (Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {
+    //
+    // PK, KEK and db/dbx/dbt should set EFI_VARIABLE_NON_VOLATILE attribute 
and should be a time-based
+    // authenticated variable.
+    //
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Del = FALSE;
+  if ((InCustomMode() && UserPhysicalPresent()) || (mPlatformMode == 
SETUP_MODE && !IsPk)) {
+    Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);
+    PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
+    if (PayloadSize == 0) {
+      Del = TRUE;
+    }
+
+    Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, 
PayloadSize);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Status = AuthServiceInternalUpdateVariableWithTimeStamp (
+               VariableName,
+               VendorGuid,
+               Payload,
+               PayloadSize,
+               Attributes,
+               &((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp
+               );
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+
+    if ((mPlatformMode != SETUP_MODE) || IsPk) {
+      Status = VendorKeyIsModified ();
+    }
+  } else if (mPlatformMode == USER_MODE) {
+    //
+    // Verify against X509 Cert in PK database.
+    //
+    Status = VerifyTimeBasedPayloadAndUpdate (
+               VariableName,
+               VendorGuid,
+               Data,
+               DataSize,
+               Attributes,
+               AuthVarTypePk,
+               &Del
+               );
+  } else {
+    //
+    // Verify against the certificate in data payload.
+    //
+    Status = VerifyTimeBasedPayloadAndUpdate (
+               VariableName,
+               VendorGuid,
+               Data,
+               DataSize,
+               Attributes,
+               AuthVarTypePayload,
+               &Del
+               );
+  }
+
+  if (!EFI_ERROR(Status) && IsPk) {
+    if (mPlatformMode == SETUP_MODE && !Del) {
+      //
+      // If enroll PK in setup mode, need change to user mode.
+      //
+      Status = UpdatePlatformMode (USER_MODE);
+    } else if (mPlatformMode == USER_MODE && Del){
+      //
+      // If delete PK in user mode, need change to setup mode.
+      //
+      Status = UpdatePlatformMode (SETUP_MODE);
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Process variable with key exchange key for verification.
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode, and datasize and data are external 
input.
+  This function will do basic validation, before parse the data.
+  This function will parse the authentication carefully to avoid security 
issues, like
+  buffer overflow, integer overflow.
+  This function will check attribute carefully to avoid authentication bypass.
+
+  @param[in]  VariableName                Name of Variable to be found.
+  @param[in]  VendorGuid                  Variable vendor GUID.
+  @param[in]  Data                        Data pointer.
+  @param[in]  DataSize                    Size of Data found. If size is less 
than the
+                                          data, this value contains the 
required size.
+  @param[in]  Attributes                  Attribute value of the variable.
+
+  @return EFI_INVALID_PARAMETER           Invalid parameter.
+  @return EFI_SECURITY_VIOLATION          The variable does NOT pass the 
validation
+                                          check carried out by the firmware.
+  @return EFI_SUCCESS                     Variable pass validation 
successfully.
+
+**/
+EFI_STATUS
+ProcessVarWithKek (
+  IN  CHAR16                               *VariableName,
+  IN  EFI_GUID                             *VendorGuid,
+  IN  VOID                                 *Data,
+  IN  UINTN                                DataSize,
+  IN  UINT32                               Attributes OPTIONAL
+  )
+{
+  EFI_STATUS                      Status;
+  UINT8                           *Payload;
+  UINTN                           PayloadSize;
+
+  if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0 ||
+      (Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {
+    //
+    // DB, DBX and DBT should set EFI_VARIABLE_NON_VOLATILE attribute and 
should be a time-based
+    // authenticated variable.
+    //
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = EFI_SUCCESS;
+  if (mPlatformMode == USER_MODE && !(InCustomMode() && 
UserPhysicalPresent())) {
+    //
+    // Time-based, verify against X509 Cert KEK.
+    //
+    return VerifyTimeBasedPayloadAndUpdate (
+             VariableName,
+             VendorGuid,
+             Data,
+             DataSize,
+             Attributes,
+             AuthVarTypeKek,
+             NULL
+             );
+  } else {
+    //
+    // If in setup mode or custom secure boot mode, no authentication needed.
+    //
+    Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);
+    PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
+
+    Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, 
PayloadSize);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Status = AuthServiceInternalUpdateVariableWithTimeStamp (
+               VariableName,
+               VendorGuid,
+               Payload,
+               PayloadSize,
+               Attributes,
+               &((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    if (mPlatformMode != SETUP_MODE) {
+      Status = VendorKeyIsModified ();
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Check if it is to delete auth variable.
+
+  @param[in] OrgAttributes      Original attribute value of the variable.
+  @param[in] Data               Data pointer.
+  @param[in] DataSize           Size of Data.
+  @param[in] Attributes         Attribute value of the variable.
+
+  @retval TRUE                  It is to delete auth variable.
+  @retval FALSE                 It is not to delete auth variable.
+
+**/
+BOOLEAN
+IsDeleteAuthVariable (
+  IN  UINT32                    OrgAttributes,
+  IN  VOID                      *Data,
+  IN  UINTN                     DataSize,
+  IN  UINT32                    Attributes
+  )
+{
+  BOOLEAN                       Del;
+  UINTN                         PayloadSize;
+
+  Del = FALSE;
+
+  //
+  // To delete a variable created with the 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
+  // or the EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute,
+  // SetVariable must be used with attributes matching the existing variable
+  // and the DataSize set to the size of the AuthInfo descriptor.
+  //
+  if ((Attributes == OrgAttributes) &&
+      ((Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | 
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) != 0)) {
+    if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 
0) {
+      PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
+      if (PayloadSize == 0) {
+        Del = TRUE;
+      }
+    } else {
+      PayloadSize = DataSize - AUTHINFO_SIZE;
+      if (PayloadSize == 0) {
+        Del = TRUE;
+      }
+    }
+  }
+
+  return Del;
+}
+
+/**
+  Process variable with 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
 set
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode, and datasize and data are external 
input.
+  This function will do basic validation, before parse the data.
+  This function will parse the authentication carefully to avoid security 
issues, like
+  buffer overflow, integer overflow.
+  This function will check attribute carefully to avoid authentication bypass.
+
+  @param[in]  VariableName                Name of the variable.
+  @param[in]  VendorGuid                  Variable vendor GUID.
+  @param[in]  Data                        Data pointer.
+  @param[in]  DataSize                    Size of Data.
+  @param[in]  Attributes                  Attribute value of the variable.
+
+  @return EFI_INVALID_PARAMETER           Invalid parameter.
+  @return EFI_WRITE_PROTECTED             Variable is write-protected and 
needs authentication with
+                                          
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
+  @return EFI_OUT_OF_RESOURCES            The Database to save the public key 
is full.
+  @return EFI_SECURITY_VIOLATION          The variable is with 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
+                                          set, but the AuthInfo does NOT pass 
the validation
+                                          check carried out by the firmware.
+  @return EFI_SUCCESS                     Variable is not write-protected or 
pass validation successfully.
+
+**/
+EFI_STATUS
+ProcessVariable (
+  IN     CHAR16                             *VariableName,
+  IN     EFI_GUID                           *VendorGuid,
+  IN     VOID                               *Data,
+  IN     UINTN                              DataSize,
+  IN     UINT32                             Attributes OPTIONAL
+  )
+{
+  EFI_STATUS                      Status;
+  BOOLEAN                         IsDeletion;
+  BOOLEAN                         IsFirstTime;
+  UINT8                           *PubKey;
+  EFI_VARIABLE_AUTHENTICATION     *CertData;
+  EFI_CERT_BLOCK_RSA_2048_SHA256  *CertBlock;
+  UINT32                          KeyIndex;
+  UINT64                          MonotonicCount;
+  VARIABLE_ENTRY_CONSISTENCY      VariableDataEntry;
+  UINT32                          Index;
+  AUTH_VARIABLE_INFO              OrgVariableInfo;
+
+  KeyIndex    = 0;
+  CertData    = NULL;
+  CertBlock   = NULL;
+  PubKey      = NULL;
+  IsDeletion  = FALSE;
+  Status      = EFI_SUCCESS;
+
+  ZeroMem (&OrgVariableInfo, sizeof (OrgVariableInfo));
+  Status = mAuthVarLibContextIn->FindVariable (
+             VariableName,
+             VendorGuid,
+             &OrgVariableInfo
+             );
+
+  if ((!EFI_ERROR (Status)) && IsDeleteAuthVariable 
(OrgVariableInfo.Attributes, Data, DataSize, Attributes) && 
UserPhysicalPresent()) {
+    //
+    // Allow the delete operation of common authenticated variable at user 
physical presence.
+    //
+    if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 
0) {
+      Status = DeleteCertsFromDb (VariableName, VendorGuid);
+    }
+    if (!EFI_ERROR (Status)) {
+      Status = AuthServiceInternalUpdateVariable (
+                 VariableName,
+                 VendorGuid,
+                 NULL,
+                 0,
+                 0
+                 );
+    }
+    return Status;
+  }
+
+  if (NeedPhysicallyPresent (VariableName, VendorGuid) && 
!UserPhysicalPresent()) {
+    //
+    // This variable is protected, only physical present user could modify its 
value.
+    //
+    return EFI_SECURITY_VIOLATION;
+  }
+
+  //
+  // A time-based authenticated variable and a count-based authenticated 
variable
+  // can't be updated by each other.
+  //
+  if (OrgVariableInfo.Data != NULL) {
+    if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) &&
+        ((OrgVariableInfo.Attributes & 
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0)) {
+      return EFI_SECURITY_VIOLATION;
+    }
+
+    if (((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 
0) &&
+        ((OrgVariableInfo.Attributes & 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0)) {
+      return EFI_SECURITY_VIOLATION;
+    }
+  }
+
+  //
+  // Process Time-based Authenticated variable.
+  //
+  if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
+    return VerifyTimeBasedPayloadAndUpdate (
+             VariableName,
+             VendorGuid,
+             Data,
+             DataSize,
+             Attributes,
+             AuthVarTypePriv,
+             NULL
+             );
+  }
+
+  //
+  // Determine if first time SetVariable with the 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS.
+  //
+  if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
+    //
+    // Determine current operation type.
+    //
+    if (DataSize == AUTHINFO_SIZE) {
+      IsDeletion = TRUE;
+    }
+    //
+    // Determine whether this is the first time with 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
+    //
+    if (OrgVariableInfo.Data == NULL) {
+      IsFirstTime = TRUE;
+    } else if ((OrgVariableInfo.Attributes & 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
+      IsFirstTime = TRUE;
+    } else {
+      KeyIndex   = OrgVariableInfo.PubKeyIndex;
+      IsFirstTime = FALSE;
+    }
+  } else if ((OrgVariableInfo.Data != NULL) &&
+             ((OrgVariableInfo.Attributes & 
(EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | 
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) != 0)
+            ) {
+    //
+    // If the variable is already write-protected, it always needs 
authentication before update.
+    //
+    return EFI_WRITE_PROTECTED;
+  } else {
+    //
+    // If without EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, set and attributes 
collision.
+    // That means it is not authenticated variable, just update variable as 
usual.
+    //
+    Status = AuthServiceInternalUpdateVariable (VariableName, VendorGuid, 
Data, DataSize, Attributes);
+    return Status;
+  }
+
+  //
+  // Get PubKey and check Monotonic Count value corresponding to the variable.
+  //
+  CertData  = (EFI_VARIABLE_AUTHENTICATION *) Data;
+  CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
+  PubKey    = CertBlock->PublicKey;
+
+  //
+  // Update Monotonic Count value.
+  //
+  MonotonicCount = CertData->MonotonicCount;
+
+  if (!IsFirstTime) {
+    //
+    // 2 cases need to check here
+    //   1. Internal PubKey variable. PubKeyIndex is always 0
+    //   2. Other counter-based AuthVariable. Check input PubKey.
+    //
+    if (KeyIndex == 0) {
+      return EFI_SECURITY_VIOLATION;
+    }
+    for (Index = 0; Index < mPubKeyNumber; Index++) {
+      if (ReadUnaligned32 (&(((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + 
Index)->KeyIndex)) == KeyIndex) {
+        if (CompareMem (((AUTHVAR_KEY_DB_DATA *) mPubKeyStore + 
Index)->KeyData, PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
+          break;
+        } else {
+          return EFI_SECURITY_VIOLATION;
+        }
+      }
+    }
+    if (Index == mPubKeyNumber) {
+      return EFI_SECURITY_VIOLATION;
+    }
+
+    //
+    // Compare the current monotonic count and ensure that it is greater than 
the last SetVariable
+    // operation with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute 
set.
+    //
+    if (MonotonicCount <= OrgVariableInfo.MonotonicCount) {
+      //
+      // Monotonic count check fail, suspicious replay attack, return 
EFI_SECURITY_VIOLATION.
+      //
+      return EFI_SECURITY_VIOLATION;
+    }
+  }
+  //
+  // Verify the certificate in Data payload.
+  //
+  Status = VerifyCounterBasedPayload (Data, DataSize, PubKey);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Now, the signature has been verified!
+  //
+  if (IsFirstTime && !IsDeletion) {
+    VariableDataEntry.VariableSize = DataSize - AUTHINFO_SIZE;
+    VariableDataEntry.Guid         = VendorGuid;
+    VariableDataEntry.Name         = VariableName;
+
+    //
+    // Update public key database variable if need.
+    //
+    KeyIndex = AddPubKeyInStore (PubKey, &VariableDataEntry);
+    if (KeyIndex == 0) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  }
+
+  //
+  // Verification pass.
+  //
+  return AuthServiceInternalUpdateVariableWithMonotonicCount (VariableName, 
VendorGuid, (UINT8*)Data + AUTHINFO_SIZE, DataSize - AUTHINFO_SIZE, Attributes, 
KeyIndex, MonotonicCount);
+}
+
+/**
+  Filter out the duplicated EFI_SIGNATURE_DATA from the new data by comparing 
to the original data.
+
+  @param[in]        Data          Pointer to original EFI_SIGNATURE_LIST.
+  @param[in]        DataSize      Size of Data buffer.
+  @param[in, out]   NewData       Pointer to new EFI_SIGNATURE_LIST.
+  @param[in, out]   NewDataSize   Size of NewData buffer.
+
+**/
+EFI_STATUS
+FilterSignatureList (
+  IN     VOID       *Data,
+  IN     UINTN      DataSize,
+  IN OUT VOID       *NewData,
+  IN OUT UINTN      *NewDataSize
+  )
+{
+  EFI_SIGNATURE_LIST    *CertList;
+  EFI_SIGNATURE_DATA    *Cert;
+  UINTN                 CertCount;
+  EFI_SIGNATURE_LIST    *NewCertList;
+  EFI_SIGNATURE_DATA    *NewCert;
+  UINTN                 NewCertCount;
+  UINTN                 Index;
+  UINTN                 Index2;
+  UINTN                 Size;
+  UINT8                 *Tail;
+  UINTN                 CopiedCount;
+  UINTN                 SignatureListSize;
+  BOOLEAN               IsNewCert;
+  UINT8                 *TempData;
+  UINTN                 TempDataSize;
+  EFI_STATUS            Status;
+
+  if (*NewDataSize == 0) {
+    return EFI_SUCCESS;
+  }
+
+  TempDataSize = *NewDataSize;
+  Status = mAuthVarLibContextIn->GetScratchBuffer (&TempDataSize, (VOID **) 
&TempData);
+  if (EFI_ERROR (Status)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Tail = TempData;
+
+  NewCertList = (EFI_SIGNATURE_LIST *) NewData;
+  while ((*NewDataSize > 0) && (*NewDataSize >= 
NewCertList->SignatureListSize)) {
+    NewCert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) NewCertList + sizeof 
(EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize);
+    NewCertCount = (NewCertList->SignatureListSize - sizeof 
(EFI_SIGNATURE_LIST) - NewCertList->SignatureHeaderSize) / 
NewCertList->SignatureSize;
+
+    CopiedCount = 0;
+    for (Index = 0; Index < NewCertCount; Index++) {
+      IsNewCert = TRUE;
+
+      Size = DataSize;
+      CertList = (EFI_SIGNATURE_LIST *) Data;
+      while ((Size > 0) && (Size >= CertList->SignatureListSize)) {
+        if (CompareGuid (&CertList->SignatureType, 
&NewCertList->SignatureType) &&
+           (CertList->SignatureSize == NewCertList->SignatureSize)) {
+          Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof 
(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+          CertCount = (CertList->SignatureListSize - sizeof 
(EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+          for (Index2 = 0; Index2 < CertCount; Index2++) {
+            //
+            // Iterate each Signature Data in this Signature List.
+            //
+            if (CompareMem (NewCert, Cert, CertList->SignatureSize) == 0) {
+              IsNewCert = FALSE;
+              break;
+            }
+            Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + 
CertList->SignatureSize);
+          }
+        }
+
+        if (!IsNewCert) {
+          break;
+        }
+        Size -= CertList->SignatureListSize;
+        CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + 
CertList->SignatureListSize);
+      }
+
+      if (IsNewCert) {
+        //
+        // New EFI_SIGNATURE_DATA, keep it.
+        //
+        if (CopiedCount == 0) {
+          //
+          // Copy EFI_SIGNATURE_LIST header for only once.
+          //
+          CopyMem (Tail, NewCertList, sizeof (EFI_SIGNATURE_LIST) + 
NewCertList->SignatureHeaderSize);
+          Tail = Tail + sizeof (EFI_SIGNATURE_LIST) + 
NewCertList->SignatureHeaderSize;
+        }
+
+        CopyMem (Tail, NewCert, NewCertList->SignatureSize);
+        Tail += NewCertList->SignatureSize;
+        CopiedCount++;
+      }
+
+      NewCert = (EFI_SIGNATURE_DATA *) ((UINT8 *) NewCert + 
NewCertList->SignatureSize);
+    }
+
+    //
+    // Update SignatureListSize in the kept EFI_SIGNATURE_LIST.
+    //
+    if (CopiedCount != 0) {
+      SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + 
NewCertList->SignatureHeaderSize + (CopiedCount * NewCertList->SignatureSize);
+      CertList = (EFI_SIGNATURE_LIST *) (Tail - SignatureListSize);
+      CertList->SignatureListSize = (UINT32) SignatureListSize;
+    }
+
+    *NewDataSize -= NewCertList->SignatureListSize;
+    NewCertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) NewCertList + 
NewCertList->SignatureListSize);
+  }
+
+  TempDataSize = (Tail - (UINT8 *) TempData);
+
+  CopyMem (NewData, TempData, TempDataSize);
+  *NewDataSize = TempDataSize;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Compare two EFI_TIME data.
+
+
+  @param FirstTime           A pointer to the first EFI_TIME data.
+  @param SecondTime          A pointer to the second EFI_TIME data.
+
+  @retval  TRUE              The FirstTime is not later than the SecondTime.
+  @retval  FALSE             The FirstTime is later than the SecondTime.
+
+**/
+BOOLEAN
+AuthServiceInternalCompareTimeStamp (
+  IN EFI_TIME               *FirstTime,
+  IN EFI_TIME               *SecondTime
+  )
+{
+  if (FirstTime->Year != SecondTime->Year) {
+    return (BOOLEAN) (FirstTime->Year < SecondTime->Year);
+  } else if (FirstTime->Month != SecondTime->Month) {
+    return (BOOLEAN) (FirstTime->Month < SecondTime->Month);
+  } else if (FirstTime->Day != SecondTime->Day) {
+    return (BOOLEAN) (FirstTime->Day < SecondTime->Day);
+  } else if (FirstTime->Hour != SecondTime->Hour) {
+    return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);
+  } else if (FirstTime->Minute != SecondTime->Minute) {
+    return (BOOLEAN) (FirstTime->Minute < SecondTime->Minute);
+  }
+
+  return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);
+}
+
+/**
+  Find matching signer's certificates for common authenticated variable
+  by corresponding VariableName and VendorGuid from "certdb".
+
+  The data format of "certdb":
+  //
+  //     UINT32 CertDbListSize;
+  // /// AUTH_CERT_DB_DATA Certs1[];
+  // /// AUTH_CERT_DB_DATA Certs2[];
+  // /// ...
+  // /// AUTH_CERT_DB_DATA Certsn[];
+  //
+
+  @param[in]  VariableName   Name of authenticated Variable.
+  @param[in]  VendorGuid     Vendor GUID of authenticated Variable.
+  @param[in]  Data           Pointer to variable "certdb".
+  @param[in]  DataSize       Size of variable "certdb".
+  @param[out] CertOffset     Offset of matching CertData, from starting of 
Data.
+  @param[out] CertDataSize   Length of CertData in bytes.
+  @param[out] CertNodeOffset Offset of matching AUTH_CERT_DB_DATA , from
+                             starting of Data.
+  @param[out] CertNodeSize   Length of AUTH_CERT_DB_DATA in bytes.
+
+  @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.
+  @retval  EFI_NOT_FOUND         Fail to find matching certs.
+  @retval  EFI_SUCCESS           Find matching certs and output parameters.
+
+**/
+EFI_STATUS
+FindCertsFromDb (
+  IN     CHAR16           *VariableName,
+  IN     EFI_GUID         *VendorGuid,
+  IN     UINT8            *Data,
+  IN     UINTN            DataSize,
+  OUT    UINT32           *CertOffset,    OPTIONAL
+  OUT    UINT32           *CertDataSize,  OPTIONAL
+  OUT    UINT32           *CertNodeOffset,OPTIONAL
+  OUT    UINT32           *CertNodeSize   OPTIONAL
+  )
+{
+  UINT32                  Offset;
+  AUTH_CERT_DB_DATA       *Ptr;
+  UINT32                  CertSize;
+  UINT32                  NameSize;
+  UINT32                  NodeSize;
+  UINT32                  CertDbListSize;
+
+  if ((VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check whether DataSize matches recorded CertDbListSize.
+  //
+  if (DataSize < sizeof (UINT32)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CertDbListSize = ReadUnaligned32 ((UINT32 *) Data);
+
+  if (CertDbListSize != (UINT32) DataSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Offset = sizeof (UINT32);
+
+  //
+  // Get corresponding certificates by VendorGuid and VariableName.
+  //
+  while (Offset < (UINT32) DataSize) {
+    Ptr = (AUTH_CERT_DB_DATA *) (Data + Offset);
+    //
+    // Check whether VendorGuid matches.
+    //
+    if (CompareGuid (&Ptr->VendorGuid, VendorGuid)) {
+      NodeSize = ReadUnaligned32 (&Ptr->CertNodeSize);
+      NameSize = ReadUnaligned32 (&Ptr->NameSize);
+      CertSize = ReadUnaligned32 (&Ptr->CertDataSize);
+
+      if (NodeSize != sizeof (EFI_GUID) + sizeof (UINT32) * 3 + CertSize +
+          sizeof (CHAR16) * NameSize) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      Offset = Offset + sizeof (EFI_GUID) + sizeof (UINT32) * 3;
+      //
+      // Check whether VariableName matches.
+      //
+      if ((NameSize == StrLen (VariableName)) &&
+          (CompareMem (Data + Offset, VariableName, NameSize * sizeof 
(CHAR16)) == 0)) {
+        Offset = Offset + NameSize * sizeof (CHAR16);
+
+        if (CertOffset != NULL) {
+          *CertOffset = Offset;
+        }
+
+        if (CertDataSize != NULL) {
+          *CertDataSize = CertSize;
+        }
+
+        if (CertNodeOffset != NULL) {
+          *CertNodeOffset = (UINT32) ((UINT8 *) Ptr - Data);
+        }
+
+        if (CertNodeSize != NULL) {
+          *CertNodeSize = NodeSize;
+        }
+
+        return EFI_SUCCESS;
+      } else {
+        Offset = Offset + NameSize * sizeof (CHAR16) + CertSize;
+      }
+    } else {
+      NodeSize = ReadUnaligned32 (&Ptr->CertNodeSize);
+      Offset   = Offset + NodeSize;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Retrieve signer's certificates for common authenticated variable
+  by corresponding VariableName and VendorGuid from "certdb".
+
+  @param[in]  VariableName   Name of authenticated Variable.
+  @param[in]  VendorGuid     Vendor GUID of authenticated Variable.
+  @param[out] CertData       Pointer to signer's certificates.
+  @param[out] CertDataSize   Length of CertData in bytes.
+
+  @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.
+  @retval  EFI_NOT_FOUND         Fail to find "certdb" or matching certs.
+  @retval  EFI_SUCCESS           Get signer's certificates successfully.
+
+**/
+EFI_STATUS
+GetCertsFromDb (
+  IN     CHAR16           *VariableName,
+  IN     EFI_GUID         *VendorGuid,
+  OUT    UINT8            **CertData,
+  OUT    UINT32           *CertDataSize
+  )
+{
+  EFI_STATUS              Status;
+  UINT8                   *Data;
+  UINTN                   DataSize;
+  UINT32                  CertOffset;
+
+  if ((VariableName == NULL) || (VendorGuid == NULL) || (CertData == NULL) || 
(CertDataSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Get variable "certdb".
+  //
+  Status = AuthServiceInternalFindVariable (
+             EFI_CERT_DB_NAME,
+             &gEfiCertDbGuid,
+             (VOID **) &Data,
+             &DataSize
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if ((DataSize == 0) || (Data == NULL)) {
+    ASSERT (FALSE);
+    return EFI_NOT_FOUND;
+  }
+
+  Status = FindCertsFromDb (
+             VariableName,
+             VendorGuid,
+             Data,
+             DataSize,
+             &CertOffset,
+             CertDataSize,
+             NULL,
+             NULL
+             );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *CertData = Data + CertOffset;
+  return EFI_SUCCESS;
+}
+
+/**
+  Delete matching signer's certificates when deleting common authenticated
+  variable by corresponding VariableName and VendorGuid from "certdb".
+
+  @param[in]  VariableName   Name of authenticated Variable.
+  @param[in]  VendorGuid     Vendor GUID of authenticated Variable.
+
+  @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.
+  @retval  EFI_NOT_FOUND         Fail to find "certdb" or matching certs.
+  @retval  EFI_OUT_OF_RESOURCES  The operation is failed due to lack of 
resources.
+  @retval  EFI_SUCCESS           The operation is completed successfully.
+
+**/
+EFI_STATUS
+DeleteCertsFromDb (
+  IN     CHAR16           *VariableName,
+  IN     EFI_GUID         *VendorGuid
+  )
+{
+  EFI_STATUS              Status;
+  UINT8                   *Data;
+  UINTN                   DataSize;
+  UINT32                  VarAttr;
+  UINT32                  CertNodeOffset;
+  UINT32                  CertNodeSize;
+  UINT8                   *NewCertDb;
+  UINT32                  NewCertDbSize;
+
+  if ((VariableName == NULL) || (VendorGuid == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Get variable "certdb".
+  //
+  Status = AuthServiceInternalFindVariable (
+             EFI_CERT_DB_NAME,
+             &gEfiCertDbGuid,
+             (VOID **) &Data,
+             &DataSize
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if ((DataSize == 0) || (Data == NULL)) {
+    ASSERT (FALSE);
+    return EFI_NOT_FOUND;
+  }
+
+  if (DataSize == sizeof (UINT32)) {
+    //
+    // There is no certs in certdb.
+    //
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Get corresponding cert node from certdb.
+  //
+  Status = FindCertsFromDb (
+             VariableName,
+             VendorGuid,
+             Data,
+             DataSize,
+             NULL,
+             NULL,
+             &CertNodeOffset,
+             &CertNodeSize
+             );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (DataSize < (CertNodeOffset + CertNodeSize)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Construct new data content of variable "certdb".
+  //
+  NewCertDbSize = (UINT32) DataSize - CertNodeSize;
+  NewCertDb     = (UINT8*) mCertDbStore;
+
+  //
+  // Copy the DB entries before deleting node.
+  //
+  CopyMem (NewCertDb, Data, CertNodeOffset);
+  //
+  // Update CertDbListSize.
+  //
+  CopyMem (NewCertDb, &NewCertDbSize, sizeof (UINT32));
+  //
+  // Copy the DB entries after deleting node.
+  //
+  if (DataSize > (CertNodeOffset + CertNodeSize)) {
+    CopyMem (
+      NewCertDb + CertNodeOffset,
+      Data + CertNodeOffset + CertNodeSize,
+      DataSize - CertNodeOffset - CertNodeSize
+      );
+  }
+
+  //
+  // Set "certdb".
+  //
+  VarAttr  = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | 
EFI_VARIABLE_BOOTSERVICE_ACCESS | 
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+  Status   = AuthServiceInternalUpdateVariable (
+               EFI_CERT_DB_NAME,
+               &gEfiCertDbGuid,
+               NewCertDb,
+               NewCertDbSize,
+               VarAttr
+               );
+
+  return Status;
+}
+
+/**
+  Insert signer's certificates for common authenticated variable with 
VariableName
+  and VendorGuid in AUTH_CERT_DB_DATA to "certdb".
+
+  @param[in]  VariableName   Name of authenticated Variable.
+  @param[in]  VendorGuid     Vendor GUID of authenticated Variable.
+  @param[in]  CertData       Pointer to signer's certificates.
+  @param[in]  CertDataSize   Length of CertData in bytes.
+
+  @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.
+  @retval  EFI_ACCESS_DENIED     An AUTH_CERT_DB_DATA entry with same 
VariableName
+                                 and VendorGuid already exists.
+  @retval  EFI_OUT_OF_RESOURCES  The operation is failed due to lack of 
resources.
+  @retval  EFI_SUCCESS           Insert an AUTH_CERT_DB_DATA entry to "certdb"
+
+**/
+EFI_STATUS
+InsertCertsToDb (
+  IN     CHAR16           *VariableName,
+  IN     EFI_GUID         *VendorGuid,
+  IN     UINT8            *CertData,
+  IN     UINTN            CertDataSize
+  )
+{
+  EFI_STATUS              Status;
+  UINT8                   *Data;
+  UINTN                   DataSize;
+  UINT32                  VarAttr;
+  UINT8                   *NewCertDb;
+  UINT32                  NewCertDbSize;
+  UINT32                  CertNodeSize;
+  UINT32                  NameSize;
+  AUTH_CERT_DB_DATA       *Ptr;
+
+  if ((VariableName == NULL) || (VendorGuid == NULL) || (CertData == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Get variable "certdb".
+  //
+  Status = AuthServiceInternalFindVariable (
+             EFI_CERT_DB_NAME,
+             &gEfiCertDbGuid,
+             (VOID **) &Data,
+             &DataSize
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if ((DataSize == 0) || (Data == NULL)) {
+    ASSERT (FALSE);
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Find whether matching cert node already exists in "certdb".
+  // If yes return error.
+  //
+  Status = FindCertsFromDb (
+             VariableName,
+             VendorGuid,
+             Data,
+             DataSize,
+             NULL,
+             NULL,
+             NULL,
+             NULL
+             );
+
+  if (!EFI_ERROR (Status)) {
+    ASSERT (FALSE);
+    return EFI_ACCESS_DENIED;
+  }
+
+  //
+  // Construct new data content of variable "certdb".
+  //
+  NameSize      = (UINT32) StrLen (VariableName);
+  CertNodeSize  = sizeof (AUTH_CERT_DB_DATA) + (UINT32) CertDataSize + 
NameSize * sizeof (CHAR16);
+  NewCertDbSize = (UINT32) DataSize + CertNodeSize;
+  if (NewCertDbSize > mMaxCertDbSize) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  NewCertDb     = (UINT8*) mCertDbStore;
+
+  //
+  // Copy the DB entries before inserting node.
+  //
+  CopyMem (NewCertDb, Data, DataSize);
+  //
+  // Update CertDbListSize.
+  //
+  CopyMem (NewCertDb, &NewCertDbSize, sizeof (UINT32));
+  //
+  // Construct new cert node.
+  //
+  Ptr = (AUTH_CERT_DB_DATA *) (NewCertDb + DataSize);
+  CopyGuid (&Ptr->VendorGuid, VendorGuid);
+  CopyMem (&Ptr->CertNodeSize, &CertNodeSize, sizeof (UINT32));
+  CopyMem (&Ptr->NameSize, &NameSize, sizeof (UINT32));
+  CopyMem (&Ptr->CertDataSize, &CertDataSize, sizeof (UINT32));
+
+  CopyMem (
+    (UINT8 *) Ptr + sizeof (AUTH_CERT_DB_DATA),
+    VariableName,
+    NameSize * sizeof (CHAR16)
+    );
+
+  CopyMem (
+    (UINT8 *) Ptr +  sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16),
+    CertData,
+    CertDataSize
+    );
+
+  //
+  // Set "certdb".
+  //
+  VarAttr  = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | 
EFI_VARIABLE_BOOTSERVICE_ACCESS | 
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+  Status   = AuthServiceInternalUpdateVariable (
+               EFI_CERT_DB_NAME,
+               &gEfiCertDbGuid,
+               NewCertDb,
+               NewCertDbSize,
+               VarAttr
+               );
+
+  return Status;
+}
+
+/**
+  Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode, and datasize and data are external 
input.
+  This function will do basic validation, before parse the data.
+  This function will parse the authentication carefully to avoid security 
issues, like
+  buffer overflow, integer overflow.
+
+  @param[in]  VariableName                Name of Variable to be found.
+  @param[in]  VendorGuid                  Variable vendor GUID.
+  @param[in]  Data                        Data pointer.
+  @param[in]  DataSize                    Size of Data found. If size is less 
than the
+                                          data, this value contains the 
required size.
+  @param[in]  Attributes                  Attribute value of the variable.
+  @param[in]  AuthVarType                 Verify against PK, KEK database, 
private database or certificate in data payload.
+  @param[in]  OrgTimeStamp                Pointer to original time stamp,
+                                          original variable is not found if 
NULL.
+  @param[out]  VarPayloadPtr              Pointer to variable payload address.
+  @param[out]  VarPayloadSize             Pointer to variable payload size.
+
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval EFI_SECURITY_VIOLATION          The variable does NOT pass the 
validation
+                                          check carried out by the firmware.
+  @retval EFI_OUT_OF_RESOURCES            Failed to process variable due to 
lack
+                                          of resources.
+  @retval EFI_SUCCESS                     Variable pass validation 
successfully.
+
+**/
+EFI_STATUS
+VerifyTimeBasedPayload (
+  IN     CHAR16                             *VariableName,
+  IN     EFI_GUID                           *VendorGuid,
+  IN     VOID                               *Data,
+  IN     UINTN                              DataSize,
+  IN     UINT32                             Attributes,
+  IN     AUTHVAR_TYPE                       AuthVarType,
+  IN     EFI_TIME                           *OrgTimeStamp,
+  OUT    UINT8                              **VarPayloadPtr,
+  OUT    UINTN                              *VarPayloadSize
+  )
+{
+  EFI_VARIABLE_AUTHENTICATION_2    *CertData;
+  UINT8                            *SigData;
+  UINT32                           SigDataSize;
+  UINT8                            *PayloadPtr;
+  UINTN                            PayloadSize;
+  UINT32                           Attr;
+  BOOLEAN                          VerifyStatus;
+  EFI_STATUS                       Status;
+  EFI_SIGNATURE_LIST               *CertList;
+  EFI_SIGNATURE_DATA               *Cert;
+  UINTN                            Index;
+  UINTN                            CertCount;
+  UINT32                           KekDataSize;
+  UINT8                            *NewData;
+  UINTN                            NewDataSize;
+  UINT8                            *Buffer;
+  UINTN                            Length;
+  UINT8                            *RootCert;
+  UINTN                            RootCertSize;
+  UINT8                            *SignerCerts;
+  UINTN                            CertStackSize;
+  UINT8                            *CertsInCertDb;
+  UINT32                           CertsSizeinDb;
+
+  VerifyStatus           = FALSE;
+  CertData               = NULL;
+  NewData                = NULL;
+  Attr                   = Attributes;
+  SignerCerts            = NULL;
+  RootCert               = NULL;
+  CertsInCertDb          = NULL;
+
+  //
+  // When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is
+  // set, then the Data buffer shall begin with an instance of a complete (and 
serialized)
+  // EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be 
followed by the new
+  // variable value and DataSize shall reflect the combined size of the 
descriptor and the new
+  // variable value. The authentication descriptor is not part of the variable 
data and is not
+  // returned by subsequent calls to GetVariable().
+  //
+  CertData = (EFI_VARIABLE_AUTHENTICATION_2 *) Data;
+
+  //
+  // Verify that Pad1, Nanosecond, TimeZone, Daylight and Pad2 components of 
the
+  // TimeStamp value are set to zero.
+  //
+  if ((CertData->TimeStamp.Pad1 != 0) ||
+      (CertData->TimeStamp.Nanosecond != 0) ||
+      (CertData->TimeStamp.TimeZone != 0) ||
+      (CertData->TimeStamp.Daylight != 0) ||
+      (CertData->TimeStamp.Pad2 != 0)) {
+    return EFI_SECURITY_VIOLATION;
+  }
+
+  if ((OrgTimeStamp != NULL) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 
0)) {
+    if (AuthServiceInternalCompareTimeStamp (&CertData->TimeStamp, 
OrgTimeStamp)) {
+      //
+      // TimeStamp check fail, suspicious replay attack, return 
EFI_SECURITY_VIOLATION.
+      //
+      return EFI_SECURITY_VIOLATION;
+    }
+  }
+
+  //
+  // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
+  // Cert type should be EFI_CERT_TYPE_PKCS7_GUID.
+  //
+  if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||
+      !CompareGuid (&CertData->AuthInfo.CertType, &gEfiCertPkcs7Guid)) {
+    //
+    // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
+    //
+    return EFI_SECURITY_VIOLATION;
+  }
+
+  //
+  // Find out Pkcs7 SignedData which follows the EFI_VARIABLE_AUTHENTICATION_2 
descriptor.
+  // AuthInfo.Hdr.dwLength is the length of the entire certificate, including 
the length of the header.
+  //
+  SigData = CertData->AuthInfo.CertData;
+  SigDataSize = CertData->AuthInfo.Hdr.dwLength - (UINT32) (OFFSET_OF 
(WIN_CERTIFICATE_UEFI_GUID, CertData));
+
+  //
+  // Find out the new data payload which follows Pkcs7 SignedData directly.
+  //
+  PayloadPtr = SigData + SigDataSize;
+  PayloadSize = DataSize - OFFSET_OF_AUTHINFO2_CERT_DATA - (UINTN) SigDataSize;
+
+  //
+  // Construct a serialization buffer of the values of the VariableName, 
VendorGuid and Attributes
+  // parameters of the SetVariable() call and the TimeStamp component of the
+  // EFI_VARIABLE_AUTHENTICATION_2 descriptor followed by the variable's new 
value
+  // i.e. (VariableName, VendorGuid, Attributes, TimeStamp, Data)
+  //
+  NewDataSize = PayloadSize + sizeof (EFI_TIME) + sizeof (UINT32) +
+                sizeof (EFI_GUID) + StrSize (VariableName) - sizeof (CHAR16);
+
+  //
+  // Here is to reuse scratch data area(at the end of volatile variable store)
+  // to reduce SMRAM consumption for SMM variable driver.
+  // The scratch buffer is enough to hold the serialized data and safe to use,
+  // because it is only used at here to do verification temporarily first
+  // and then used in UpdateVariable() for a time based auth variable set.
+  //
+  Status = mAuthVarLibContextIn->GetScratchBuffer (&NewDataSize, (VOID **) 
&NewData);
+  if (EFI_ERROR (Status)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Buffer = NewData;
+  Length = StrLen (VariableName) * sizeof (CHAR16);
+  CopyMem (Buffer, VariableName, Length);
+  Buffer += Length;
+
+  Length = sizeof (EFI_GUID);
+  CopyMem (Buffer, VendorGuid, Length);
+  Buffer += Length;
+
+  Length = sizeof (UINT32);
+  CopyMem (Buffer, &Attr, Length);
+  Buffer += Length;
+
+  Length = sizeof (EFI_TIME);
+  CopyMem (Buffer, &CertData->TimeStamp, Length);
+  Buffer += Length;
+
+  CopyMem (Buffer, PayloadPtr, PayloadSize);
+
+  if (AuthVarType == AuthVarTypePk) {
+    //
+    // Verify that the signature has been made with the current Platform Key 
(no chaining for PK).
+    // First, get signer's certificates from SignedData.
+    //
+    VerifyStatus = Pkcs7GetSigners (
+                     SigData,
+                     SigDataSize,
+                     &SignerCerts,
+                     &CertStackSize,
+                     &RootCert,
+                     &RootCertSize
+                     );
+    if (!VerifyStatus) {
+      goto Exit;
+    }
+
+    //
+    // Second, get the current platform key from variable. Check whether it's 
identical with signer's certificates
+    // in SignedData. If not, return error immediately.
+    //
+    Status = AuthServiceInternalFindVariable (
+               EFI_PLATFORM_KEY_NAME,
+               &gEfiGlobalVariableGuid,
+               &Data,
+               &DataSize
+               );
+    if (EFI_ERROR (Status)) {
+      VerifyStatus = FALSE;
+      goto Exit;
+    }
+    CertList = (EFI_SIGNATURE_LIST *) Data;
+    Cert     = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof 
(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+    if ((RootCertSize != (CertList->SignatureSize - (sizeof 
(EFI_SIGNATURE_DATA) - 1))) ||
+        (CompareMem (Cert->SignatureData, RootCert, RootCertSize) != 0)) {
+      VerifyStatus = FALSE;
+      goto Exit;
+    }
+
+    //
+    // Verify Pkcs7 SignedData via Pkcs7Verify library.
+    //
+    VerifyStatus = Pkcs7Verify (
+                     SigData,
+                     SigDataSize,
+                     RootCert,
+                     RootCertSize,
+                     NewData,
+                     NewDataSize
+                     );
+
+  } else if (AuthVarType == AuthVarTypeKek) {
+
+    //
+    // Get KEK database from variable.
+    //
+    Status = AuthServiceInternalFindVariable (
+               EFI_KEY_EXCHANGE_KEY_NAME,
+               &gEfiGlobalVariableGuid,
+               &Data,
+               &DataSize
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Ready to verify Pkcs7 SignedData. Go through KEK Signature Database to 
find out X.509 CertList.
+    //
+    KekDataSize      = (UINT32) DataSize;
+    CertList         = (EFI_SIGNATURE_LIST *) Data;
+    while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
+      if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
+        Cert       = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof 
(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+        CertCount  = (CertList->SignatureListSize - sizeof 
(EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+        for (Index = 0; Index < CertCount; Index++) {
+          //
+          // Iterate each Signature Data Node within this CertList for a verify
+          //
+          RootCert      = Cert->SignatureData;
+          RootCertSize  = CertList->SignatureSize - (sizeof 
(EFI_SIGNATURE_DATA) - 1);
+
+          //
+          // Verify Pkcs7 SignedData via Pkcs7Verify library.
+          //
+          VerifyStatus = Pkcs7Verify (
+                           SigData,
+                           SigDataSize,
+                           RootCert,
+                           RootCertSize,
+                           NewData,
+                           NewDataSize
+                           );
+          if (VerifyStatus) {
+            goto Exit;
+          }
+          Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + 
CertList->SignatureSize);
+        }
+      }
+      KekDataSize -= CertList->SignatureListSize;
+      CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + 
CertList->SignatureListSize);
+    }
+  } else if (AuthVarType == AuthVarTypePriv) {
+
+    //
+    // Process common authenticated variable except PK/KEK/DB/DBX/DBT.
+    // Get signer's certificates from SignedData.
+    //
+    VerifyStatus = Pkcs7GetSigners (
+                     SigData,
+                     SigDataSize,
+                     &SignerCerts,
+                     &CertStackSize,
+                     &RootCert,
+                     &RootCertSize
+                     );
+    if (!VerifyStatus) {
+      goto Exit;
+    }
+
+    //
+    // Get previously stored signer's certificates from certdb for existing
+    // variable. Check whether they are identical with signer's certificates
+    // in SignedData. If not, return error immediately.
+    //
+    if (OrgTimeStamp != NULL) {
+      VerifyStatus = FALSE;
+
+      Status = GetCertsFromDb (VariableName, VendorGuid, &CertsInCertDb, 
&CertsSizeinDb);
+      if (EFI_ERROR (Status)) {
+        goto Exit;
+      }
+
+      if ((CertStackSize != CertsSizeinDb) ||
+          (CompareMem (SignerCerts, CertsInCertDb, CertsSizeinDb) != 0)) {
+        goto Exit;
+      }
+    }
+
+    VerifyStatus = Pkcs7Verify (
+                     SigData,
+                     SigDataSize,
+                     RootCert,
+                     RootCertSize,
+                     NewData,
+                     NewDataSize
+                     );
+    if (!VerifyStatus) {
+      goto Exit;
+    }
+
+    //
+    // Delete signer's certificates when delete the common authenticated 
variable.
+    //
+    if ((PayloadSize == 0) && (OrgTimeStamp != NULL) && ((Attributes & 
EFI_VARIABLE_APPEND_WRITE) == 0)) {
+      Status = DeleteCertsFromDb (VariableName, VendorGuid);
+      if (EFI_ERROR (Status)) {
+        VerifyStatus = FALSE;
+        goto Exit;
+      }
+    } else if ((OrgTimeStamp == NULL) && (PayloadSize != 0)) {
+      //
+      // Insert signer's certificates when adding a new common authenticated 
variable.
+      //
+      Status = InsertCertsToDb (VariableName, VendorGuid, SignerCerts, 
CertStackSize);
+      if (EFI_ERROR (Status)) {
+        VerifyStatus = FALSE;
+        goto Exit;
+      }
+    }
+  } else if (AuthVarType == AuthVarTypePayload) {
+    CertList = (EFI_SIGNATURE_LIST *) PayloadPtr;
+    Cert     = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof 
(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+    RootCert      = Cert->SignatureData;
+    RootCertSize  = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 
1);
+    //
+    // Verify Pkcs7 SignedData via Pkcs7Verify library.
+    //
+    VerifyStatus = Pkcs7Verify (
+                     SigData,
+                     SigDataSize,
+                     RootCert,
+                     RootCertSize,
+                     NewData,
+                     NewDataSize
+                     );
+  } else {
+    return EFI_SECURITY_VIOLATION;
+  }
+
+Exit:
+
+  if (AuthVarType == AuthVarTypePk || AuthVarType == AuthVarTypePriv) {
+    Pkcs7FreeSigners (RootCert);
+    Pkcs7FreeSigners (SignerCerts);
+  }
+
+  if (!VerifyStatus) {
+    return EFI_SECURITY_VIOLATION;
+  }
+
+  Status = CheckSignatureListFormat(VariableName, VendorGuid, PayloadPtr, 
PayloadSize);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *VarPayloadPtr = PayloadPtr;
+  *VarPayloadSize = PayloadSize;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode, and datasize and data are external 
input.
+  This function will do basic validation, before parse the data.
+  This function will parse the authentication carefully to avoid security 
issues, like
+  buffer overflow, integer overflow.
+
+  @param[in]  VariableName                Name of Variable to be found.
+  @param[in]  VendorGuid                  Variable vendor GUID.
+  @param[in]  Data                        Data pointer.
+  @param[in]  DataSize                    Size of Data found. If size is less 
than the
+                                          data, this value contains the 
required size.
+  @param[in]  Attributes                  Attribute value of the variable.
+  @param[in]  AuthVarType                 Verify against PK, KEK database, 
private database or certificate in data payload.
+  @param[out] VarDel                      Delete the variable or not.
+
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval EFI_SECURITY_VIOLATION          The variable does NOT pass the 
validation
+                                          check carried out by the firmware.
+  @retval EFI_OUT_OF_RESOURCES            Failed to process variable due to 
lack
+                                          of resources.
+  @retval EFI_SUCCESS                     Variable pass validation 
successfully.
+
+**/
+EFI_STATUS
+VerifyTimeBasedPayloadAndUpdate (
+  IN     CHAR16                             *VariableName,
+  IN     EFI_GUID                           *VendorGuid,
+  IN     VOID                               *Data,
+  IN     UINTN                              DataSize,
+  IN     UINT32                             Attributes,
+  IN     AUTHVAR_TYPE                       AuthVarType,
+  OUT    BOOLEAN                            *VarDel
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_STATUS                       FindStatus;
+  UINT8                            *PayloadPtr;
+  UINTN                            PayloadSize;
+  EFI_VARIABLE_AUTHENTICATION_2    *CertData;
+  AUTH_VARIABLE_INFO               OrgVariableInfo;
+
+  ZeroMem (&OrgVariableInfo, sizeof (OrgVariableInfo));
+  FindStatus = mAuthVarLibContextIn->FindVariable (
+             VariableName,
+             VendorGuid,
+             &OrgVariableInfo
+             );
+
+  Status = VerifyTimeBasedPayload (
+             VariableName,
+             VendorGuid,
+             Data,
+             DataSize,
+             Attributes,
+             AuthVarType,
+             (!EFI_ERROR (FindStatus)) ? OrgVariableInfo.TimeStamp : NULL,
+             &PayloadPtr,
+             &PayloadSize
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if ((PayloadSize == 0) && (VarDel != NULL)) {
+    *VarDel = TRUE;
+  }
+
+  CertData = (EFI_VARIABLE_AUTHENTICATION_2 *) Data;
+
+  //
+  // Final step: Update/Append Variable if it pass Pkcs7Verify
+  //
+  return AuthServiceInternalUpdateVariableWithTimeStamp (
+           VariableName,
+           VendorGuid,
+           PayloadPtr,
+           PayloadSize,
+           Attributes,
+           &CertData->TimeStamp
+           );
+}
diff --git a/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h 
b/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h
new file mode 100644
index 0000000..19ea123
--- /dev/null
+++ b/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h
@@ -0,0 +1,411 @@
+/** @file
+  The internal header file includes the common header files, defines
+  internal structure and functions used by AuthService module.
+
+  Caution: This module requires additional review when modified.
+  This driver will have external input - variable data. It may be input in SMM 
mode.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+  Variable attribute should also be checked to avoid authentication bypass.
+     The whole SMM authentication variable design relies on the integrity of 
flash part and SMM.
+  which is assumed to be protected by platform.  All variable code and 
metadata in flash/SMM Memory
+  may not be modified without authorization. If platform fails to protect 
these resources, 
+  the authentication service provided in this driver will be broken, and the 
behavior is undefined.
+
+Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _AUTHSERVICE_INTERNAL_H_
+#define _AUTHSERVICE_INTERNAL_H_
+
+#include <Library/AuthVariableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseCryptLib.h>
+#include <Library/PlatformSecureLib.h>
+
+#include <Guid/AuthenticatedVariableFormat.h>
+#include <Guid/ImageAuthentication.h>
+
+///
+/// Struct to record signature requirement defined by UEFI spec.
+/// For SigHeaderSize and SigDataSize, ((UINT32) ~0) means NO exact length 
requirement for this field.
+///
+typedef struct {
+  EFI_GUID    SigType;
+  // Expected SignatureHeader size in Bytes.
+  UINT32      SigHeaderSize;
+  // Expected SignatureData size in Bytes.
+  UINT32      SigDataSize;
+} EFI_SIGNATURE_ITEM;
+
+typedef enum {
+  AuthVarTypePk,
+  AuthVarTypeKek,
+  AuthVarTypePriv,
+  AuthVarTypePayload
+} AUTHVAR_TYPE;
+
+///
+/// "AuthVarKeyDatabase" variable for the Public Key store
+/// of variables with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
+///
+/// GUID: gEfiAuthenticatedVariableGuid
+///
+/// We need maintain atomicity.
+///
+/// Format:
+/// +----------------------------+
+/// | AUTHVAR_KEY_DB_DATA        | <-- First AuthVarKey
+/// +----------------------------+
+/// | ......                     |
+/// +----------------------------+
+/// | AUTHVAR_KEY_DB_DATA        | <-- Last AuthKey
+/// +----------------------------+
+///
+#define AUTHVAR_KEYDB_NAME      L"AuthVarKeyDatabase"
+
+#define EFI_CERT_TYPE_RSA2048_SHA256_SIZE 256
+#define EFI_CERT_TYPE_RSA2048_SIZE        256
+
+#pragma pack(1)
+typedef struct {
+  UINT32    KeyIndex;
+  UINT8     KeyData[EFI_CERT_TYPE_RSA2048_SIZE];
+} AUTHVAR_KEY_DB_DATA;
+#pragma pack()
+
+///
+/// "certdb" variable stores the signer's certificates for non PK/KEK/DB/DBX
+/// variables with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.
+///
+/// GUID: gEfiCertDbGuid
+///
+/// We need maintain atomicity.
+///
+/// Format:
+/// +----------------------------+
+/// | UINT32                     | <-- CertDbListSize, including this UINT32
+/// +----------------------------+
+/// | AUTH_CERT_DB_DATA          | <-- First CERT
+/// +----------------------------+
+/// | ........                   |
+/// +----------------------------+
+/// | AUTH_CERT_DB_DATA          | <-- Last CERT
+/// +----------------------------+
+///
+#define EFI_CERT_DB_NAME        L"certdb"
+
+#pragma pack(1)
+typedef struct {
+  EFI_GUID    VendorGuid;
+  UINT32      CertNodeSize;
+  UINT32      NameSize;
+  UINT32      CertDataSize;
+  /// CHAR16  VariableName[NameSize];
+  /// UINT8   CertData[CertDataSize];
+} AUTH_CERT_DB_DATA;
+#pragma pack()
+
+extern UINT8    *mPubKeyStore;
+extern UINT32   mPubKeyNumber;
+extern UINT32   mMaxKeyNumber;
+extern UINT32   mMaxKeyDbSize;
+extern UINT8    *mCertDbStore;
+extern UINT32   mMaxCertDbSize;
+extern UINT32   mPlatformMode;
+extern UINT8    mVendorKeyState;
+
+extern VOID     *mHashCtx;
+
+extern AUTH_VAR_LIB_CONTEXT_IN *mAuthVarLibContextIn;
+
+/**
+  Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode, and datasize and data are external 
input.
+  This function will do basic validation, before parse the data.
+  This function will parse the authentication carefully to avoid security 
issues, like
+  buffer overflow, integer overflow.
+
+  @param[in]  VariableName                Name of Variable to be found.
+  @param[in]  VendorGuid                  Variable vendor GUID.
+  @param[in]  Data                        Data pointer.
+  @param[in]  DataSize                    Size of Data found. If size is less 
than the
+                                          data, this value contains the 
required size.
+  @param[in]  Attributes                  Attribute value of the variable.
+  @param[in]  AuthVarType                 Verify against PK, KEK database, 
private database or certificate in data payload.
+  @param[out] VarDel                      Delete the variable or not.
+
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval EFI_SECURITY_VIOLATION          The variable does NOT pass the 
validation
+                                          check carried out by the firmware.
+  @retval EFI_OUT_OF_RESOURCES            Failed to process variable due to 
lack
+                                          of resources.
+  @retval EFI_SUCCESS                     Variable pass validation 
successfully.
+
+**/
+EFI_STATUS
+VerifyTimeBasedPayloadAndUpdate (
+  IN     CHAR16                             *VariableName,
+  IN     EFI_GUID                           *VendorGuid,
+  IN     VOID                               *Data,
+  IN     UINTN                              DataSize,
+  IN     UINT32                             Attributes,
+  IN     AUTHVAR_TYPE                       AuthVarType,
+  OUT    BOOLEAN                            *VarDel
+  );
+
+/**
+  Delete matching signer's certificates when deleting common authenticated
+  variable by corresponding VariableName and VendorGuid from "certdb".
+
+  @param[in]  VariableName   Name of authenticated Variable.
+  @param[in]  VendorGuid     Vendor GUID of authenticated Variable.
+
+  @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.
+  @retval  EFI_NOT_FOUND         Fail to find "certdb" or matching certs.
+  @retval  EFI_OUT_OF_RESOURCES  The operation is failed due to lack of 
resources.
+  @retval  EFI_SUCCESS           The operation is completed successfully.
+
+**/
+EFI_STATUS
+DeleteCertsFromDb (
+  IN     CHAR16           *VariableName,
+  IN     EFI_GUID         *VendorGuid
+  );
+
+/**
+  Filter out the duplicated EFI_SIGNATURE_DATA from the new data by comparing 
to the original data.
+
+  @param[in]        Data          Pointer to original EFI_SIGNATURE_LIST.
+  @param[in]        DataSize      Size of Data buffer.
+  @param[in, out]   NewData       Pointer to new EFI_SIGNATURE_LIST.
+  @param[in, out]   NewDataSize   Size of NewData buffer.
+
+**/
+EFI_STATUS
+FilterSignatureList (
+  IN     VOID       *Data,
+  IN     UINTN      DataSize,
+  IN OUT VOID       *NewData,
+  IN OUT UINTN      *NewDataSize
+  );
+
+/**
+  Process variable with platform key for verification.
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode, and datasize and data are external 
input.
+  This function will do basic validation, before parse the data.
+  This function will parse the authentication carefully to avoid security 
issues, like
+  buffer overflow, integer overflow.
+  This function will check attribute carefully to avoid authentication bypass.
+
+  @param[in]  VariableName                Name of Variable to be found.
+  @param[in]  VendorGuid                  Variable vendor GUID.
+  @param[in]  Data                        Data pointer.
+  @param[in]  DataSize                    Size of Data found. If size is less 
than the
+                                          data, this value contains the 
required size.
+  @param[in]  Attributes                  Attribute value of the variable
+  @param[in]  IsPk                        Indicate whether it is to process pk.
+
+  @return EFI_INVALID_PARAMETER           Invalid parameter.
+  @return EFI_SECURITY_VIOLATION          The variable does NOT pass the 
validation.
+                                          check carried out by the firmware.
+  @return EFI_SUCCESS                     Variable passed validation 
successfully.
+
+**/
+EFI_STATUS
+ProcessVarWithPk (
+  IN  CHAR16                    *VariableName,
+  IN  EFI_GUID                  *VendorGuid,
+  IN  VOID                      *Data,
+  IN  UINTN                     DataSize,
+  IN  UINT32                    Attributes OPTIONAL,
+  IN  BOOLEAN                   IsPk
+  );
+
+/**
+  Process variable with key exchange key for verification.
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode, and datasize and data are external 
input.
+  This function will do basic validation, before parse the data.
+  This function will parse the authentication carefully to avoid security 
issues, like
+  buffer overflow, integer overflow.
+  This function will check attribute carefully to avoid authentication bypass.
+
+  @param[in]  VariableName                Name of Variable to be found.
+  @param[in]  VendorGuid                  Variable vendor GUID.
+  @param[in]  Data                        Data pointer.
+  @param[in]  DataSize                    Size of Data found. If size is less 
than the
+                                          data, this value contains the 
required size.
+  @param[in]  Attributes                  Attribute value of the variable.
+
+  @return EFI_INVALID_PARAMETER           Invalid parameter.
+  @return EFI_SECURITY_VIOLATION          The variable does NOT pass the 
validation
+                                          check carried out by the firmware.
+  @return EFI_SUCCESS                     Variable pass validation 
successfully.
+
+**/
+EFI_STATUS
+ProcessVarWithKek (
+  IN  CHAR16                               *VariableName,
+  IN  EFI_GUID                             *VendorGuid,
+  IN  VOID                                 *Data,
+  IN  UINTN                                DataSize,
+  IN  UINT32                               Attributes OPTIONAL
+  );
+
+/**
+  Process variable with 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
 set
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode, and datasize and data are external 
input.
+  This function will do basic validation, before parse the data.
+  This function will parse the authentication carefully to avoid security 
issues, like
+  buffer overflow, integer overflow.
+  This function will check attribute carefully to avoid authentication bypass.
+
+  @param[in]  VariableName                Name of the variable.
+  @param[in]  VendorGuid                  Variable vendor GUID.
+  @param[in]  Data                        Data pointer.
+  @param[in]  DataSize                    Size of Data.
+  @param[in]  Attributes                  Attribute value of the variable.
+
+  @return EFI_INVALID_PARAMETER           Invalid parameter.
+  @return EFI_WRITE_PROTECTED             Variable is write-protected and 
needs authentication with
+                                          
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
+  @return EFI_OUT_OF_RESOURCES            The Database to save the public key 
is full.
+  @return EFI_SECURITY_VIOLATION          The variable is with 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
+                                          set, but the AuthInfo does NOT pass 
the validation
+                                          check carried out by the firmware.
+  @return EFI_SUCCESS                     Variable is not write-protected or 
pass validation successfully.
+
+**/
+EFI_STATUS
+ProcessVariable (
+  IN     CHAR16                             *VariableName,
+  IN     EFI_GUID                           *VendorGuid,
+  IN     VOID                               *Data,
+  IN     UINTN                              DataSize,
+  IN     UINT32                             Attributes OPTIONAL
+  );
+
+/**
+  Finds variable in storage blocks of volatile and non-volatile storage areas.
+
+  This code finds variable in storage blocks of volatile and non-volatile 
storage areas.
+  If VariableName is an empty string, then we just return the first
+  qualified variable without comparing VariableName and VendorGuid.
+
+  @param[in]  VariableName          Name of the variable to be found.
+  @param[in]  VendorGuid            Variable vendor GUID to be found.
+  @param[out] Data                  Pointer to data address.
+  @param[out] DataSize              Pointer to data size.
+
+  @retval EFI_INVALID_PARAMETER     If VariableName is not an empty string,
+                                    while VendorGuid is NULL.
+  @retval EFI_SUCCESS               Variable successfully found.
+  @retval EFI_NOT_FOUND             Variable not found
+
+**/
+EFI_STATUS
+AuthServiceInternalFindVariable (
+  IN  CHAR16        *VariableName,
+  IN  EFI_GUID      *VendorGuid,
+  OUT VOID          **Data,
+  OUT UINTN         *DataSize
+  );
+
+/**
+  Update the variable region with Variable information.
+
+  @param[in] VariableName           Name of variable.
+  @param[in] VendorGuid             Guid of variable.
+  @param[in] Data                   Data pointer.
+  @param[in] DataSize               Size of Data.
+  @param[in] Attributes             Attribute value of the variable.
+
+  @retval EFI_SUCCESS               The update operation is success.
+  @retval EFI_INVALID_PARAMETER     Invalid parameter.
+  @retval EFI_WRITE_PROTECTED       Variable is write-protected.
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.
+
+**/
+EFI_STATUS
+AuthServiceInternalUpdateVariable (
+  IN CHAR16         *VariableName,
+  IN EFI_GUID       *VendorGuid,
+  IN VOID           *Data,
+  IN UINTN          DataSize,
+  IN UINT32         Attributes
+  );
+
+/**
+  Update the variable region with Variable information.
+
+  @param[in] VariableName           Name of variable.
+  @param[in] VendorGuid             Guid of variable.
+  @param[in] Data                   Data pointer.
+  @param[in] DataSize               Size of Data.
+  @param[in] Attributes             Attribute value of the variable.
+  @param[in] KeyIndex               Index of associated public key.
+  @param[in] MonotonicCount         Value of associated monotonic count.
+
+  @retval EFI_SUCCESS               The update operation is success.
+  @retval EFI_INVALID_PARAMETER     Invalid parameter.
+  @retval EFI_WRITE_PROTECTED       Variable is write-protected.
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.
+
+**/
+EFI_STATUS
+AuthServiceInternalUpdateVariableWithMonotonicCount (
+  IN CHAR16         *VariableName,
+  IN EFI_GUID       *VendorGuid,
+  IN VOID           *Data,
+  IN UINTN          DataSize,
+  IN UINT32         Attributes,
+  IN UINT32         KeyIndex,
+  IN UINT64         MonotonicCount
+  );
+
+/**
+  Update the variable region with Variable information.
+
+  @param[in] VariableName           Name of variable.
+  @param[in] VendorGuid             Guid of variable.
+  @param[in] Data                   Data pointer.
+  @param[in] DataSize               Size of Data.
+  @param[in] Attributes             Attribute value of the variable.
+  @param[in] TimeStamp              Value of associated TimeStamp.
+
+  @retval EFI_SUCCESS               The update operation is success.
+  @retval EFI_INVALID_PARAMETER     Invalid parameter.
+  @retval EFI_WRITE_PROTECTED       Variable is write-protected.
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.
+
+**/
+EFI_STATUS
+AuthServiceInternalUpdateVariableWithTimeStamp (
+  IN CHAR16         *VariableName,
+  IN EFI_GUID       *VendorGuid,
+  IN VOID           *Data,
+  IN UINTN          DataSize,
+  IN UINT32         Attributes,
+  IN EFI_TIME       *TimeStamp
+  );
+
+#endif
diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c 
b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c
new file mode 100644
index 0000000..22d664b
--- /dev/null
+++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c
@@ -0,0 +1,460 @@
+/** @file
+  Implement authentication services for the authenticated variables.
+
+  Caution: This module requires additional review when modified.
+  This driver will have external input - variable data. It may be input in SMM 
mode.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+  Variable attribute should also be checked to avoid authentication bypass.
+     The whole SMM authentication variable design relies on the integrity of 
flash part and SMM.
+  which is assumed to be protected by platform.  All variable code and 
metadata in flash/SMM Memory
+  may not be modified without authorization. If platform fails to protect 
these resources,
+  the authentication service provided in this driver will be broken, and the 
behavior is undefined.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "AuthServiceInternal.h"
+
+///
+/// Global database array for scratch
+///
+UINT8    *mPubKeyStore;
+UINT32   mPubKeyNumber;
+UINT32   mMaxKeyNumber;
+UINT32   mMaxKeyDbSize;
+UINT8    *mCertDbStore;
+UINT32   mMaxCertDbSize;
+UINT32   mPlatformMode;
+UINT8    mVendorKeyState;
+
+EFI_GUID mSignatureSupport[] = {EFI_CERT_SHA1_GUID, EFI_CERT_SHA256_GUID, 
EFI_CERT_RSA2048_GUID, EFI_CERT_X509_GUID};
+
+//
+// Hash context pointer
+//
+VOID  *mHashCtx = NULL;
+
+VARIABLE_ENTRY_PROPERTY mAuthVarEntry[] = {
+  {
+    &gEfiSecureBootEnableDisableGuid,
+    EFI_SECURE_BOOT_ENABLE_NAME,
+    {
+      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
+      0,
+      VARIABLE_ATTRIBUTE_NV_BS,
+      sizeof (UINT8),
+      sizeof (UINT8)
+    }
+  },
+  {
+    &gEfiCustomModeEnableGuid,
+    EFI_CUSTOM_MODE_NAME,
+    {
+      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
+      0,
+      VARIABLE_ATTRIBUTE_NV_BS,
+      sizeof (UINT8),
+      sizeof (UINT8)
+    }
+  },
+  {
+    &gEfiVendorKeysNvGuid,
+    EFI_VENDOR_KEYS_NV_VARIABLE_NAME,
+    {
+      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
+      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
+      VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
+      sizeof (UINT8),
+      sizeof (UINT8)
+    }
+  },
+  {
+    &gEfiAuthenticatedVariableGuid,
+    AUTHVAR_KEYDB_NAME,
+    {
+      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
+      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
+      VARIABLE_ATTRIBUTE_NV_BS_RT_AW,
+      sizeof (UINT8),
+      MAX_UINTN
+    }
+  },
+  {
+    &gEfiCertDbGuid,
+    EFI_CERT_DB_NAME,
+    {
+      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
+      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
+      VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
+      sizeof (UINT32),
+      MAX_UINTN
+    }
+  },
+};
+
+VOID *mAddressPointer[3];
+
+AUTH_VAR_LIB_CONTEXT_IN *mAuthVarLibContextIn = NULL;
+
+/**
+  Initialization for authenticated varibale services.
+  If this initialization returns error status, other APIs will not work
+  and expect to be not called then.
+
+  @param[in]  AuthVarLibContextIn   Pointer to input auth variable lib context.
+  @param[out] AuthVarLibContextOut  Pointer to output auth variable lib 
context.
+
+  @retval EFI_SUCCESS               Function successfully executed.
+  @retval EFI_INVALID_PARAMETER     If AuthVarLibContextIn == NULL or 
AuthVarLibContextOut == NULL.
+  @retval EFI_OUT_OF_RESOURCES      Fail to allocate enough resource.
+  @retval EFI_UNSUPPORTED           Unsupported to process authenticated 
variable.
+
+**/
+EFI_STATUS
+EFIAPI
+AuthVariableLibInitialize (
+  IN  AUTH_VAR_LIB_CONTEXT_IN   *AuthVarLibContextIn,
+  OUT AUTH_VAR_LIB_CONTEXT_OUT  *AuthVarLibContextOut
+  )
+{
+  EFI_STATUS            Status;
+  UINT8                 VarValue;
+  UINT32                VarAttr;
+  UINT8                 *Data;
+  UINTN                 DataSize;
+  UINTN                 CtxSize;
+  UINT8                 SecureBootMode;
+  UINT8                 SecureBootEnable;
+  UINT8                 CustomMode;
+  UINT32                ListSize;
+
+  if ((AuthVarLibContextIn == NULL) || (AuthVarLibContextOut == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  mAuthVarLibContextIn = AuthVarLibContextIn;
+
+  //
+  // Initialize hash context.
+  //
+  CtxSize   = Sha256GetContextSize ();
+  mHashCtx  = AllocateRuntimePool (CtxSize);
+  if (mHashCtx == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Reserve runtime buffer for public key database. The size excludes 
variable header and name size.
+  //
+  mMaxKeyDbSize = (UINT32) (mAuthVarLibContextIn->MaxAuthVariableSize - sizeof 
(AUTHVAR_KEYDB_NAME));
+  mMaxKeyNumber = mMaxKeyDbSize / sizeof (AUTHVAR_KEY_DB_DATA);
+  mPubKeyStore  = AllocateRuntimePool (mMaxKeyDbSize);
+  if (mPubKeyStore == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Reserve runtime buffer for certificate database. The size excludes 
variable header and name size.
+  //
+  mMaxCertDbSize = (UINT32) (mAuthVarLibContextIn->MaxAuthVariableSize - 
sizeof (EFI_CERT_DB_NAME));
+  mCertDbStore   = AllocateRuntimePool (mMaxCertDbSize);
+  if (mCertDbStore == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Check "AuthVarKeyDatabase" variable's existence.
+  // If it doesn't exist, create a new one with initial value of 0 and 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
+  //
+  Status = AuthServiceInternalFindVariable (
+             AUTHVAR_KEYDB_NAME,
+             &gEfiAuthenticatedVariableGuid,
+             (VOID **) &Data,
+             &DataSize
+             );
+  if (EFI_ERROR (Status)) {
+    VarAttr       = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | 
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
+    VarValue      = 0;
+    mPubKeyNumber = 0;
+    Status        = AuthServiceInternalUpdateVariable (
+                      AUTHVAR_KEYDB_NAME,
+                      &gEfiAuthenticatedVariableGuid,
+                      &VarValue,
+                      sizeof(UINT8),
+                      VarAttr
+                      );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  } else {
+    //
+    // Load database in global variable for cache.
+    //
+    ASSERT ((DataSize != 0) && (Data != NULL));
+    //
+    // "AuthVarKeyDatabase" is an internal variable. Its DataSize is always 
ensured not to exceed mPubKeyStore buffer size(See definition before)
+    //  Therefore, there is no memory overflow in underlying CopyMem.
+    //
+    CopyMem (mPubKeyStore, (UINT8 *) Data, DataSize);
+    mPubKeyNumber = (UINT32) (DataSize / sizeof (AUTHVAR_KEY_DB_DATA));
+  }
+
+  Status = AuthServiceInternalFindVariable (EFI_PLATFORM_KEY_NAME, 
&gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", 
EFI_PLATFORM_KEY_NAME));
+  } else {
+    DEBUG ((EFI_D_INFO, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME));
+  }
+
+  //
+  // Create "SetupMode" variable with BS+RT attribute set.
+  //
+  if (EFI_ERROR (Status)) {
+    mPlatformMode = SETUP_MODE;
+  } else {
+    mPlatformMode = USER_MODE;
+  }
+  Status = AuthServiceInternalUpdateVariable (
+             EFI_SETUP_MODE_NAME,
+             &gEfiGlobalVariableGuid,
+             &mPlatformMode,
+             sizeof(UINT8),
+             EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Create "SignatureSupport" variable with BS+RT attribute set.
+  //
+  Status  = AuthServiceInternalUpdateVariable (
+              EFI_SIGNATURE_SUPPORT_NAME,
+              &gEfiGlobalVariableGuid,
+              mSignatureSupport,
+              sizeof(mSignatureSupport),
+              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
+              );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // If "SecureBootEnable" variable exists, then update "SecureBoot" variable.
+  // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in USER_MODE, 
Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.
+  // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" 
variable to SECURE_BOOT_MODE_DISABLE.
+  //
+  SecureBootEnable = SECURE_BOOT_DISABLE;
+  Status = AuthServiceInternalFindVariable (EFI_SECURE_BOOT_ENABLE_NAME, 
&gEfiSecureBootEnableDisableGuid, (VOID **) &Data, &DataSize);
+  if (!EFI_ERROR (Status)) {
+    if (mPlatformMode == SETUP_MODE){
+      //
+      // PK is cleared in runtime. "SecureBootMode" is not updated before 
reboot 
+      // Delete "SecureBootMode" in SetupMode
+      //
+      Status = AuthServiceInternalUpdateVariable (
+                 EFI_SECURE_BOOT_ENABLE_NAME,
+                 &gEfiSecureBootEnableDisableGuid,
+                 &SecureBootEnable,
+                 0,
+                 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS
+                 );
+    } else {
+      SecureBootEnable = *(UINT8 *) Data;
+    }
+  } else if (mPlatformMode == USER_MODE) {
+    //
+    // "SecureBootEnable" not exist, initialize it in USER_MODE.
+    //
+    SecureBootEnable = SECURE_BOOT_ENABLE;
+    Status = AuthServiceInternalUpdateVariable (
+               EFI_SECURE_BOOT_ENABLE_NAME,
+               &gEfiSecureBootEnableDisableGuid,
+               &SecureBootEnable,
+               sizeof (UINT8),
+               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  //
+  // Create "SecureBoot" variable with BS+RT attribute set.
+  //
+  if (SecureBootEnable == SECURE_BOOT_ENABLE && mPlatformMode == USER_MODE) {
+    SecureBootMode = SECURE_BOOT_MODE_ENABLE;
+  } else {
+    SecureBootMode = SECURE_BOOT_MODE_DISABLE;
+  }
+  Status = AuthServiceInternalUpdateVariable (
+             EFI_SECURE_BOOT_MODE_NAME,
+             &gEfiGlobalVariableGuid,
+             &SecureBootMode,
+             sizeof (UINT8),
+             EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SETUP_MODE_NAME, 
mPlatformMode));
+  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME, 
SecureBootMode));
+  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, 
SecureBootEnable));
+
+  //
+  // Initialize "CustomMode" in STANDARD_SECURE_BOOT_MODE state.
+  //
+  CustomMode = STANDARD_SECURE_BOOT_MODE;
+  Status = AuthServiceInternalUpdateVariable (
+             EFI_CUSTOM_MODE_NAME,
+             &gEfiCustomModeEnableGuid,
+             &CustomMode,
+             sizeof (UINT8),
+             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_CUSTOM_MODE_NAME, 
CustomMode));
+
+  //
+  // Check "certdb" variable's existence.
+  // If it doesn't exist, then create a new one with
+  // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.
+  //
+  Status = AuthServiceInternalFindVariable (
+             EFI_CERT_DB_NAME,
+             &gEfiCertDbGuid,
+             (VOID **) &Data,
+             &DataSize
+             );
+  if (EFI_ERROR (Status)) {
+    VarAttr  = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | 
EFI_VARIABLE_BOOTSERVICE_ACCESS | 
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+    ListSize = sizeof (UINT32);
+    Status   = AuthServiceInternalUpdateVariable (
+                 EFI_CERT_DB_NAME,
+                 &gEfiCertDbGuid,
+                 &ListSize,
+                 sizeof (UINT32),
+                 VarAttr
+                 );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  //
+  // Check "VendorKeysNv" variable's existence and create "VendorKeys" 
variable accordingly.
+  //
+  Status = AuthServiceInternalFindVariable (EFI_VENDOR_KEYS_NV_VARIABLE_NAME, 
&gEfiVendorKeysNvGuid, (VOID **) &Data, &DataSize);
+  if (!EFI_ERROR (Status)) {
+    mVendorKeyState = *(UINT8 *)Data;
+  } else {
+    //
+    // "VendorKeysNv" not exist, initialize it in VENDOR_KEYS_VALID state.
+    //
+    mVendorKeyState = VENDOR_KEYS_VALID;
+    Status = AuthServiceInternalUpdateVariable (
+               EFI_VENDOR_KEYS_NV_VARIABLE_NAME,
+               &gEfiVendorKeysNvGuid,
+               &mVendorKeyState,
+               sizeof (UINT8),
+               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | 
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  //
+  // Create "VendorKeys" variable with BS+RT attribute set.
+  //
+  Status = AuthServiceInternalUpdateVariable (
+             EFI_VENDOR_KEYS_VARIABLE_NAME,
+             &gEfiGlobalVariableGuid,
+             &mVendorKeyState,
+             sizeof (UINT8),
+             EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_VENDOR_KEYS_VARIABLE_NAME, 
mVendorKeyState));
+
+  AuthVarLibContextOut->StructVersion = 
AUTH_VAR_LIB_CONTEXT_OUT_STRUCT_VERSION;
+  AuthVarLibContextOut->StructSize = sizeof (AUTH_VAR_LIB_CONTEXT_OUT);
+  AuthVarLibContextOut->AuthVarEntry = mAuthVarEntry;
+  AuthVarLibContextOut->AuthVarEntryCount = sizeof (mAuthVarEntry) / sizeof 
(mAuthVarEntry[0]);
+  mAddressPointer[0] = mHashCtx;
+  mAddressPointer[1] = mPubKeyStore;
+  mAddressPointer[2] = mCertDbStore;
+  AuthVarLibContextOut->AddressPointer = mAddressPointer;
+  AuthVarLibContextOut->AddressPointerCount = sizeof (mAddressPointer) / 
sizeof (mAddressPointer[0]);
+
+  return Status;
+}
+
+/**
+  Process variable with 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
 set.
+
+  @param[in] VariableName           Name of the variable.
+  @param[in] VendorGuid             Variable vendor GUID.
+  @param[in] Data                   Data pointer.
+  @param[in] DataSize               Size of Data.
+  @param[in] Attributes             Attribute value of the variable.
+
+  @retval EFI_SUCCESS               The firmware has successfully stored the 
variable and its data as
+                                    defined by the Attributes.
+  @retval EFI_INVALID_PARAMETER     Invalid parameter.
+  @retval EFI_WRITE_PROTECTED       Variable is write-protected.
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.
+  @retval EFI_SECURITY_VIOLATION    The variable is with 
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
+                                    or 
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS
+                                    set, but the AuthInfo does NOT pass the 
validation
+                                    check carried out by the firmware.
+  @retval EFI_UNSUPPORTED           Unsupported to process authenticated 
variable.
+
+**/
+EFI_STATUS
+EFIAPI
+AuthVariableLibProcessVariable (
+  IN CHAR16         *VariableName,
+  IN EFI_GUID       *VendorGuid,
+  IN VOID           *Data,
+  IN UINTN          DataSize,
+  IN UINT32         Attributes
+  )
+{
+  EFI_STATUS        Status;
+
+  if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp 
(VariableName, EFI_PLATFORM_KEY_NAME) == 0)){
+    Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, 
Attributes, TRUE);
+  } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp 
(VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) {
+    Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, 
Attributes, FALSE);
+  } else if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
+             ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE)  == 0) ||
+              (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) ||
+              (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0)
+             )) {
+    Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, 
Attributes, FALSE);
+    if (EFI_ERROR (Status)) {
+      Status = ProcessVarWithKek (VariableName, VendorGuid, Data, DataSize, 
Attributes);
+    }
+  } else {
+    Status = ProcessVariable (VariableName, VendorGuid, Data, DataSize, 
Attributes);
+  }
+
+  return Status;
+}
diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf 
b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
new file mode 100644
index 0000000..5033085
--- /dev/null
+++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
@@ -0,0 +1,86 @@
+## @file
+#  Provides authenticated variable services.
+#
+#  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions
+#  of the BSD License which accompanies this distribution.  The
+#  full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = AuthVariableLib
+  MODULE_UNI_FILE                = AuthVariableLib.uni
+  FILE_GUID                      = B23CF5FB-6FCC-4422-B145-D855DBC05457
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = AuthVariableLib|DXE_RUNTIME_DRIVER 
DXE_SMM_DRIVER
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 
+#
+
+[Sources]
+  AuthVariableLib.c
+  AuthService.c
+  AuthServiceInternal.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  BaseCryptLib
+  PlatformSecureLib
+
+[Guids]
+  ## CONSUMES            ## Variable:L"SetupMode"
+  ## PRODUCES            ## Variable:L"SetupMode"
+  ## SOMETIMES_CONSUMES  ## Variable:L"PK"
+  ## SOMETIMES_CONSUMES  ## Variable:L"KEK"
+  ## CONSUMES            ## Variable:L"SecureBoot"
+  ## PRODUCES            ## Variable:L"SecureBoot"
+  ## CONSUMES            ## Variable:L"SignatureSupport"
+  ## PRODUCES            ## Variable:L"SignatureSupport"  
+  ## PRODUCES            ## Variable:L"VendorKeys"
+  gEfiGlobalVariableGuid
+
+  ## SOMETIMES_CONSUMES  ## Variable:L"DB"
+  ## SOMETIMES_CONSUMES  ## Variable:L"DBX"
+  ## SOMETIMES_CONSUMES  ## Variable:L"DBT"
+  gEfiImageSecurityDatabaseGuid
+
+  ## CONSUMES            ## Variable:L"SecureBootEnable"
+  ## PRODUCES            ## Variable:L"SecureBootEnable"
+  gEfiSecureBootEnableDisableGuid
+
+  ## CONSUMES            ## Variable:L"CustomMode"
+  ## PRODUCES            ## Variable:L"CustomMode"
+  gEfiCustomModeEnableGuid
+
+  ## CONSUMES            ## Variable:L"certdb"
+  ## PRODUCES            ## Variable:L"certdb"
+  gEfiCertDbGuid
+
+  ## CONSUMES            ## Variable:L"VendorKeysNv"
+  ## PRODUCES            ## Variable:L"VendorKeysNv"
+  gEfiVendorKeysNvGuid
+
+  gEfiCertTypeRsa2048Sha256Guid  ## SOMETIMES_CONSUMES   ## GUID  # Unique ID 
for the type of the certificate.
+  gEfiCertPkcs7Guid              ## SOMETIMES_CONSUMES   ## GUID  # Unique ID 
for the type of the certificate.
+  gEfiCertX509Guid               ## SOMETIMES_CONSUMES   ## GUID  # Unique ID 
for the type of the signature.
diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.uni 
b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.uni
new file mode 100644
index 
0000000000000000000000000000000000000000..2f72288eea5162efd067ba91a8c54801da2d431b
GIT binary patch
literal 1670
zcmchXPjAye5XI+=#CNdL3!v5kBrXUc5^BH#>L_tkI92)A)>4QgCuzx-2Yzq1v1uq0
z2UJ=1?#|A>dGlu0KYz5XZ4vJip2*(VxfM3InLV@zShd%)%1XP!KE=MmGO~@W?UL1k
zv9Jl2HLEFmSIjGHBO5zT#EBUeouBymxW>NU7;nj9X<KJ^0sA#<AHnG{<8ymz&+LUA
zGEY6L8SEp|nTk{TD#wD^!eVwh?8`&B1~e&Cd4?fh=@Hv2>ssGl-;r|;hr;z-a;^kL
zF}{H^B8IdK8f!h_DcM{4-j;I<{39$u`Jnh5v_@0aVTR8fZz;d<N(gs{uhXijEUKF-
z-_&j6ER;*bL{+Yc8oD5`6f@0=S|9C}bW(G!YXduG{pl8$hU>L!G2#1XwgoYTC^dp!
zinU^`tjFGqO<km_GCIc|DkRR|@!scjTbH2a7O(Nm`4WVXp)_u|s&m#<;-%jY^;FPS
z{*@~olYK>f+I!lsu#90owWGbA7?exiCQ5D}EP+jr?#b*u-;RA|ouXufmKt-cDg8BM
zmbkt{J7G+)N7w>FqkT$0CwL4TIb)_i*0;qdT%ooYyS~=y@HbAU><cyXh>@M*)puqm
z*i%r2k$Ln!D{+@iF>`$7qo~2_9lnbGmGL7xVy^p_+(ZdkB=)7oY0y)&=+RAzdCV=_
z>9!jq|DUzpE}Pzix@W@O3HqIZlz}k>EwM8gNiQkeL9HA<e|rx6wg_v(t-0{7Q70UM
lC8jMH{@*`mtIp@&a#1G?$U<GxtJS|NpZm`xMxR|}egR0x2Co1B

literal 0
HcmV?d00001

diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 35a7a51..fd74ec1 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -175,7 +175,9 @@
   #
   
SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.inf
   
SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.inf
-  
+
+  SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+
 [Components.IA32, Components.X64, Components.IPF]
 #  
SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderDxe.inf
 #  
SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderDxe.inf
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h 
b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
index 4a4595f..20f60d4 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
@@ -122,12 +122,6 @@ typedef struct {
 } VARIABLE_MODULE_GLOBAL;
 
 typedef struct {
-  EFI_GUID    *Guid;
-  CHAR16      *Name;
-  UINTN       VariableSize;
-} VARIABLE_ENTRY_CONSISTENCY;
-
-typedef struct {
   LIST_ENTRY  Link;
   EFI_GUID    Guid;
   //CHAR16      *Name;
-- 
1.9.5.msysgit.0


------------------------------------------------------------------------------
Monitor 25 network devices or servers for free with OpManager!
OpManager is web-based network management software that monitors 
network devices and physical & virtual servers, alerts via email & sms 
for fault. Monitor 25 devices for free with no restriction. Download now
http://ad.doubleclick.net/ddm/clk/292181274;119417398;o
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to