Example #1
0
/**
  This code gets the pointer to the next variable header.

  @param  StoreInfo         Pointer to variable store info structure.
  @param  Variable          Pointer to the Variable Header.
  @param  VariableHeader    Pointer to the Variable Header that has consecutive content.

  @return  A VARIABLE_HEADER* pointer to next variable header.

**/
VARIABLE_HEADER *
GetNextVariablePtr (
  IN  VARIABLE_STORE_INFO   *StoreInfo,
  IN  VARIABLE_HEADER       *Variable,
  IN  VARIABLE_HEADER       *VariableHeader
  )
{
  EFI_PHYSICAL_ADDRESS  TargetAddress;
  EFI_PHYSICAL_ADDRESS  SpareAddress;
  UINTN                 Value;

  Value =  (UINTN) GetVariableDataPtr (Variable, VariableHeader, StoreInfo->AuthFlag);
  Value += DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag);
  Value += GET_PAD_SIZE (DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag));
  //
  // Be careful about pad size for alignment
  //
  Value = HEADER_ALIGN (Value);

  if (StoreInfo->FtwLastWriteData != NULL) {
    TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
    SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
    if (((UINTN) Variable < (UINTN) TargetAddress) && (Value >= (UINTN) TargetAddress)) {
      //
      // Next variable is in spare block.
      //
      Value = (UINTN) SpareAddress + (Value - (UINTN) TargetAddress);
    }
  }

  return (VARIABLE_HEADER *) Value;
}
Example #2
0
/**
  This service retrieves a variable's value using its name and GUID.

  Read the specified variable from the UEFI variable store. If the Data
  buffer is too small to hold the contents of the variable, the error
  EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer
  size to obtain the data.

  @param  This                  A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
  @param  VariableName          A pointer to a null-terminated string that is the variable's name.
  @param  VariableGuid          A pointer to an EFI_GUID that is the variable's GUID. The combination of
                                VariableGuid and VariableName must be unique.
  @param  Attributes            If non-NULL, on return, points to the variable's attributes.
  @param  DataSize              On entry, points to the size in bytes of the Data buffer.
                                On return, points to the size of the data returned in Data.
  @param  Data                  Points to the buffer which will hold the returned variable value.

  @retval EFI_SUCCESS           The variable was read successfully.
  @retval EFI_NOT_FOUND         The variable could not be found.
  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the resulting data.
                                DataSize is updated with the size required for
                                the specified variable.
  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.
  @retval EFI_DEVICE_ERROR      The variable could not be retrieved because of a device error.

**/
EFI_STATUS
EFIAPI
PeiGetVariable (
  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
  IN CONST  CHAR16                          *VariableName,
  IN CONST  EFI_GUID                        *VariableGuid,
  OUT       UINT32                          *Attributes,
  IN OUT    UINTN                           *DataSize,
  OUT       VOID                            *Data
  )
{
  VARIABLE_POINTER_TRACK  Variable;
  UINTN                   VarDataSize;
  EFI_STATUS              Status;
  VARIABLE_STORE_INFO     StoreInfo;
  VARIABLE_HEADER         *VariableHeader;

  if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  VariableHeader = NULL;

  //
  // Find existing variable
  //
  Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);

  //
  // Get data size
  //
  VarDataSize = DataSizeOfVariable (VariableHeader, StoreInfo.AuthFlag);
  if (*DataSize >= VarDataSize) {
    if (Data == NULL) {
      return EFI_INVALID_PARAMETER;
    }

    GetVariableNameOrData (&StoreInfo, GetVariableDataPtr (Variable.CurrPtr, VariableHeader, StoreInfo.AuthFlag), VarDataSize, Data);

    if (Attributes != NULL) {
      *Attributes = VariableHeader->Attributes;
    }

    *DataSize = VarDataSize;
    return EFI_SUCCESS;
  } else {
    *DataSize = VarDataSize;
    return EFI_BUFFER_TOO_SMALL;
  }
}
Example #3
0
/**
  Finds next variable in storage blocks of volatile and non-volatile storage areas.

  This code finds next 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] AuthVariableInfo      Pointer to AUTH_VARIABLE_INFO structure for
                                    output of the next variable.

  @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
EFIAPI
VariableExLibFindNextVariable (
  IN  CHAR16                *VariableName,
  IN  EFI_GUID              *VendorGuid,
  OUT AUTH_VARIABLE_INFO    *AuthVariableInfo
  )
{
  EFI_STATUS                    Status;
  VARIABLE_HEADER               *VariablePtr;
  AUTHENTICATED_VARIABLE_HEADER *AuthVariablePtr;

  Status = VariableServiceGetNextVariableInternal (
             VariableName,
             VendorGuid,
             &VariablePtr
             );
  if (EFI_ERROR (Status)) {
    AuthVariableInfo->VariableName = NULL;
    AuthVariableInfo->VendorGuid = NULL;
    AuthVariableInfo->Data = NULL;
    AuthVariableInfo->DataSize = 0;
    AuthVariableInfo->Attributes = 0;
    AuthVariableInfo->PubKeyIndex = 0;
    AuthVariableInfo->MonotonicCount = 0;
    AuthVariableInfo->TimeStamp = NULL;
    return Status;
  }

  AuthVariableInfo->VariableName    = GetVariableNamePtr (VariablePtr);
  AuthVariableInfo->VendorGuid      = GetVendorGuidPtr (VariablePtr);
  AuthVariableInfo->DataSize        = DataSizeOfVariable (VariablePtr);
  AuthVariableInfo->Data            = GetVariableDataPtr (VariablePtr);
  AuthVariableInfo->Attributes      = VariablePtr->Attributes;
  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
    AuthVariablePtr = (AUTHENTICATED_VARIABLE_HEADER *) VariablePtr;
    AuthVariableInfo->PubKeyIndex     = AuthVariablePtr->PubKeyIndex;
    AuthVariableInfo->MonotonicCount  = AuthVariablePtr->MonotonicCount;
    AuthVariableInfo->TimeStamp       = &AuthVariablePtr->TimeStamp;
  }

  return EFI_SUCCESS;
}
Example #4
0
/**
  This code gets the pointer to the next variable header.

  @param  Variable  Pointer to the Variable Header.

  @return  A VARIABLE_HEADER* pointer to next variable header.

**/
VARIABLE_HEADER *
GetNextVariablePtr (
    IN  VARIABLE_HEADER   *Variable
)
{
    UINTN Value;

    if (!IsValidVariableHeader (Variable)) {
        return NULL;
    }

    Value =  (UINTN) GetVariableDataPtr (Variable);
    Value += DataSizeOfVariable (Variable);
    Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));

    //
    // Be careful about pad size for alignment
    //
    return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
}
Example #5
0
/**
  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] AuthVariableInfo      Pointer to AUTH_VARIABLE_INFO structure for
                                    output of the variable found.

  @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
EFIAPI
VariableExLibFindVariable (
  IN  CHAR16                *VariableName,
  IN  EFI_GUID              *VendorGuid,
  OUT AUTH_VARIABLE_INFO    *AuthVariableInfo
  )
{
  EFI_STATUS                    Status;
  VARIABLE_POINTER_TRACK        Variable;
  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;

  Status = FindVariable (
             VariableName,
             VendorGuid,
             &Variable,
             &mVariableModuleGlobal->VariableGlobal,
             FALSE
             );
  if (EFI_ERROR (Status)) {
    AuthVariableInfo->Data = NULL;
    AuthVariableInfo->DataSize = 0;
    AuthVariableInfo->Attributes = 0;
    AuthVariableInfo->PubKeyIndex = 0;
    AuthVariableInfo->MonotonicCount = 0;
    AuthVariableInfo->TimeStamp = NULL;
    return Status;
  }

  AuthVariableInfo->DataSize        = DataSizeOfVariable (Variable.CurrPtr);
  AuthVariableInfo->Data            = GetVariableDataPtr (Variable.CurrPtr);
  AuthVariableInfo->Attributes      = Variable.CurrPtr->Attributes;
  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
    AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable.CurrPtr;
    AuthVariableInfo->PubKeyIndex     = AuthVariable->PubKeyIndex;
    AuthVariableInfo->MonotonicCount  = AuthVariable->MonotonicCount;
    AuthVariableInfo->TimeStamp       = &AuthVariable->TimeStamp;
  }

  return EFI_SUCCESS;
}
Example #6
0
/**
  Process variable with key exchange key for verification.

  @param[in]  VariableName                The name of Variable to be found.
  @param[in]  VendorGuid                  The variable vendor GUID.
  @param[in]  Data                        The data pointer.
  @param[in]  DataSize                    The size of Data found. If size is less than the
                                          data, this value contains the required size.
  @param[in]  VirtualMode                 The current calling mode for this function.
  @param[in]  Global                      The context of this Extended SAL Variable Services Class call.
  @param[in]  Variable                    The variable information which is used to keep track of variable usage.
  @param[in]  Attributes                  The attribute value of the variable.

  @retval EFI_INVALID_PARAMETER           Invalid parameter.
  @retval EFI_SECURITY_VIOLATION          The variable did NOT pass the validation 
                                          check carried out by the firmware. 
  @retval EFI_SUCCESS                     The variable passed validation successfully.

**/
EFI_STATUS
ProcessVarWithKek (
  IN  CHAR16                               *VariableName,
  IN  EFI_GUID                             *VendorGuid,
  IN  VOID                                 *Data,
  IN  UINTN                                DataSize,
  IN  BOOLEAN                              VirtualMode,
  IN  ESAL_VARIABLE_GLOBAL                 *Global,
  IN  VARIABLE_POINTER_TRACK               *Variable,
  IN  UINT32                               Attributes OPTIONAL
  )
{
  EFI_STATUS                      Status;
  VARIABLE_POINTER_TRACK          KekVariable;
  EFI_SIGNATURE_LIST              *KekList;
  EFI_SIGNATURE_DATA              *KekItem;
  UINT32                          KekCount;
  EFI_VARIABLE_AUTHENTICATION     *CertData;
  EFI_CERT_BLOCK_RSA_2048_SHA256  *CertBlock;
  BOOLEAN                         IsFound;
  UINT32                          Index;
  VARIABLE_HEADER                 VariableHeader;
  BOOLEAN                         Valid;

  KekList = NULL;
  ZeroMem (&VariableHeader, sizeof (VARIABLE_HEADER));

  if (mPlatformMode == USER_MODE) {
    if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
      //
      // In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.
      //
      return EFI_INVALID_PARAMETER;
    }

    CertData  = (EFI_VARIABLE_AUTHENTICATION *) Data;
    CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
    if (Variable->CurrPtr != 0x0) {
      Valid = IsValidVariableHeader (
                Variable->CurrPtr, 
                Variable->Volatile, 
                &Global->VariableGlobal[VirtualMode], 
                Global->FvbInstance, 
                &VariableHeader
                );
      ASSERT (Valid);

      if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) {
        //
        // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
        //
        return EFI_SECURITY_VIOLATION;
      }
    }
    //
    // Get KEK database from variable.
    //
    Status = FindVariable (
               Global->VariableName[VirtualMode][VAR_KEY_EXCHANGE_KEY], 
               Global->GlobalVariableGuid[VirtualMode], 
               &KekVariable, 
               &Global->VariableGlobal[VirtualMode],
               Global->FvbInstance
               );
    ASSERT_EFI_ERROR (Status);

    ZeroMem (Global->KeyList, MAX_KEYDB_SIZE);
    GetVariableDataPtr (
      KekVariable.CurrPtr,
      KekVariable.Volatile,
      &Global->VariableGlobal[VirtualMode],
      Global->FvbInstance,
      (CHAR16 *) Global->KeyList
      );
    //
    // Enumerate all Kek items in this list to verify the variable certificate data.
    // If anyone is authenticated successfully, it means the variable is correct!
    //
    KekList   = (EFI_SIGNATURE_LIST *) Global->KeyList;
    IsFound   = FALSE;
    KekCount  = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;
    KekItem   = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);
    for (Index = 0; Index < KekCount; Index++) {
      if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
        IsFound = TRUE;
        break;
      }
      KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);
    }

    if (!IsFound) {
      return EFI_SECURITY_VIOLATION;
    }

    Status = VerifyDataPayload (VirtualMode, Global, Data, DataSize, CertBlock->PublicKey);
    if (!EFI_ERROR (Status)) {
      Status = UpdateVariable (
                 VariableName, 
                 VendorGuid, 
                 (UINT8*)Data + AUTHINFO_SIZE, 
                 DataSize - AUTHINFO_SIZE, 
                 Attributes, 
                 0, 
                 CertData->MonotonicCount, 
                 VirtualMode,
                 Global,
                 Variable
                 );
    }
  } else {
    //
    // If in setup mode, no authentication needed.
    //
    Status = UpdateVariable (
               VariableName, 
               VendorGuid, 
               Data, 
               DataSize, 
               Attributes, 
               0, 
               0, 
               VirtualMode,
               Global,
               Variable
               );
  }

  return Status;
}
Example #7
0
/**
  Process variable with platform key for verification.

  @param[in]  VariableName                The name of Variable to be found.
  @param[in]  VendorGuid                  The variable vendor GUID.
  @param[in]  Data                        The data pointer.
  @param[in]  DataSize                    The size of Data found. If size is less than the
                                          data, this value contains the required size.
  @param[in]  VirtualMode                 The current calling mode for this function.
  @param[in]  Global                      The context of this Extended SAL Variable Services Class call.
  @param[in]  Variable                    The variable information which is used to keep track of variable usage.
  @param[in]  Attributes                  The attribute value of the variable.
  @param[in]  IsPk                        Indicates whether to process pk.

  @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_SUCCESS                     The variable passed validation successfully.

**/
EFI_STATUS
ProcessVarWithPk (
  IN  CHAR16                    *VariableName,
  IN  EFI_GUID                  *VendorGuid,
  IN  VOID                      *Data,
  IN  UINTN                     DataSize,
  IN  BOOLEAN                   VirtualMode,
  IN  ESAL_VARIABLE_GLOBAL      *Global,
  IN  VARIABLE_POINTER_TRACK    *Variable,
  IN  UINT32                    Attributes OPTIONAL,
  IN  BOOLEAN                   IsPk
  )
{
  EFI_STATUS                  Status;
  VARIABLE_POINTER_TRACK      PkVariable;
  EFI_SIGNATURE_LIST          *OldPkList;
  EFI_SIGNATURE_DATA          *OldPkData;
  EFI_VARIABLE_AUTHENTICATION *CertData;
  VARIABLE_HEADER             VariableHeader;
  BOOLEAN                     Valid;

  OldPkList = NULL;
  ZeroMem (&VariableHeader, sizeof (VARIABLE_HEADER));

  if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
    //
    // PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute.
    //
    return EFI_INVALID_PARAMETER;
  }

  if (mPlatformMode == USER_MODE) {
    if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
      //
      // In user mode, PK and KEK should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.
      //
      return EFI_INVALID_PARAMETER;
    }

    CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;

    if (Variable->CurrPtr != 0x0) {
      Valid = IsValidVariableHeader (
                Variable->CurrPtr, 
                Variable->Volatile, 
                &Global->VariableGlobal[VirtualMode], 
                Global->FvbInstance, 
                &VariableHeader
                );
      ASSERT (Valid);

      if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) {
        //
        // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
        //
        return EFI_SECURITY_VIOLATION;
      }
    }
    //
    // Get platform key from variable.
    //
    Status = FindVariable (
               Global->VariableName[VirtualMode][VAR_PLATFORM_KEY], 
               Global->GlobalVariableGuid[VirtualMode], 
               &PkVariable, 
               &Global->VariableGlobal[VirtualMode],
               Global->FvbInstance
               );
    ASSERT_EFI_ERROR (Status);

    ZeroMem (Global->KeyList, MAX_KEYDB_SIZE);
    GetVariableDataPtr (
      PkVariable.CurrPtr,
      PkVariable.Volatile,
      &Global->VariableGlobal[VirtualMode],
      Global->FvbInstance,
      (CHAR16 *) Global->KeyList
      );

    OldPkList = (EFI_SIGNATURE_LIST *) Global->KeyList;
    OldPkData = (EFI_SIGNATURE_DATA *) ((UINT8 *) OldPkList + sizeof (EFI_SIGNATURE_LIST) + OldPkList->SignatureHeaderSize);
    Status    = VerifyDataPayload (VirtualMode, Global, Data, DataSize, OldPkData->SignatureData);
    if (!EFI_ERROR (Status)) {
      Status = UpdateVariable (
                 VariableName, 
                 VendorGuid, 
                 (UINT8*)Data + AUTHINFO_SIZE, 
                 DataSize - AUTHINFO_SIZE, 
                 Attributes, 
                 0, 
                 CertData->MonotonicCount, 
                 VirtualMode, 
                 Global,
                 Variable
                 );

      if (!EFI_ERROR (Status)) {
        //
        // If delete PK in user mode, need change to setup mode.
        //
        if ((DataSize == AUTHINFO_SIZE) && IsPk) {
          UpdatePlatformMode (VirtualMode, Global, SETUP_MODE);
        }
      }
    }
  } else {
    Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, 0, 0, VirtualMode, Global, Variable);
    //
    // If enroll PK in setup mode, need change to user mode.
    //
    if ((DataSize != 0) && IsPk) {
      UpdatePlatformMode (VirtualMode, Global, USER_MODE);
    }
  }

  return Status;
}
Example #8
0
/**
  Initializes for authenticated varibale service.

  @retval EFI_SUCCESS           The function successfully executed.
  @retval EFI_OUT_OF_RESOURCES  Failed to allocate enough memory resources.

**/
EFI_STATUS
AutenticatedVariableServiceInitialize (
  VOID
  )
{
  EFI_STATUS              Status;
  VARIABLE_POINTER_TRACK  Variable;
  UINT8                   VarValue;
  UINT32                  VarAttr;
  UINTN                   DataSize;
  UINTN                   CtxSize;
  VARIABLE_HEADER         VariableHeader;
  BOOLEAN                 Valid;

  ZeroMem (&VariableHeader, sizeof (VARIABLE_HEADER));

  mVariableModuleGlobal->AuthenticatedVariableGuid[Physical] = &gEfiAuthenticatedVariableGuid;
  mVariableModuleGlobal->CertRsa2048Sha256Guid[Physical]     = &gEfiCertRsa2048Sha256Guid;
  mVariableModuleGlobal->ImageSecurityDatabaseGuid[Physical] = &gEfiImageSecurityDatabaseGuid;

  //
  // Initialize hash context.
  //
  CtxSize   = Sha256GetContextSize ();
  mVariableModuleGlobal->HashContext[Physical] = AllocateRuntimePool (CtxSize);
  ASSERT (mVariableModuleGlobal->HashContext[Physical] != NULL);
  //
  // 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 = FindVariable (
             mVariableModuleGlobal->VariableName[Physical][VAR_AUTH_KEY_DB], 
             &gEfiAuthenticatedVariableGuid, 
             &Variable, 
             &mVariableModuleGlobal->VariableGlobal[Physical],
             mVariableModuleGlobal->FvbInstance
             );

  if (Variable.CurrPtr == 0x0) {
    VarAttr       = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
    VarValue      = 0;
    mPubKeyNumber = 0;
    Status        = UpdateVariable (
                      mVariableModuleGlobal->VariableName[Physical][VAR_AUTH_KEY_DB],
                      &gEfiAuthenticatedVariableGuid,
                      &VarValue,
                      sizeof(UINT8),
                      VarAttr,
                      0,
                      0,
                      FALSE,
                      mVariableModuleGlobal,
                      &Variable
                      );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  } else {
    //
    // Load database in global variable for cache.
    //
    Valid = IsValidVariableHeader (
              Variable.CurrPtr, 
              Variable.Volatile, 
              &mVariableModuleGlobal->VariableGlobal[Physical], 
              mVariableModuleGlobal->FvbInstance, 
              &VariableHeader
              );
    ASSERT (Valid);

    DataSize  = DataSizeOfVariable (&VariableHeader);
    ASSERT (DataSize <= MAX_KEYDB_SIZE);
    GetVariableDataPtr (
      Variable.CurrPtr,
      Variable.Volatile,
      &mVariableModuleGlobal->VariableGlobal[Physical],
      mVariableModuleGlobal->FvbInstance,
      (CHAR16 *) mVariableModuleGlobal->PubKeyStore
      );

    mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);
  }
  //
  // Check "SetupMode" variable's existence. 
  // If it doesn't exist, check PK database's existence to determine the value.
  // Then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set. 
  //
  Status = FindVariable (
             mVariableModuleGlobal->VariableName[Physical][VAR_SETUP_MODE], 
             &gEfiGlobalVariableGuid, 
             &Variable, 
             &mVariableModuleGlobal->VariableGlobal[Physical],
             mVariableModuleGlobal->FvbInstance
             );

  if (Variable.CurrPtr == 0x0) {
    Status = FindVariable (
               mVariableModuleGlobal->VariableName[Physical][VAR_PLATFORM_KEY], 
               &gEfiGlobalVariableGuid, 
               &Variable, 
               &mVariableModuleGlobal->VariableGlobal[Physical],
               mVariableModuleGlobal->FvbInstance
               );
    if (Variable.CurrPtr == 0x0) {
      mPlatformMode = SETUP_MODE;
    } else {
      mPlatformMode = USER_MODE;
    }

    VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
    Status  = UpdateVariable (
                mVariableModuleGlobal->VariableName[Physical][VAR_SETUP_MODE],
                &gEfiGlobalVariableGuid,
                &mPlatformMode,
                sizeof(UINT8),
                VarAttr,
                0,
                0,
                FALSE,
                mVariableModuleGlobal,
                &Variable
                );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  } else {
    GetVariableDataPtr (
      Variable.CurrPtr,
      Variable.Volatile,
      &mVariableModuleGlobal->VariableGlobal[Physical],
      mVariableModuleGlobal->FvbInstance,
      (CHAR16 *) &mPlatformMode
      );
  }
  //
  // Check "SignatureSupport" variable's existence. 
  // If it doesn't exist, then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set. 
  //
  Status = FindVariable (
             EFI_SIGNATURE_SUPPORT_NAME, 
             &gEfiGlobalVariableGuid, 
             &Variable, 
             &mVariableModuleGlobal->VariableGlobal[Physical],
             mVariableModuleGlobal->FvbInstance
             );

  if (Variable.CurrPtr == 0x0) {
    VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
    Status  = UpdateVariable (
                EFI_SIGNATURE_SUPPORT_NAME,
                &gEfiGlobalVariableGuid,
                mSignatureSupport,
                SIGSUPPORT_NUM * sizeof(EFI_GUID),
                VarAttr,
                0,
                0,
                FALSE,
                mVariableModuleGlobal,
                &Variable
                );
  }

  return Status;
}