alder_lake_bios/Insyde/InsydeModulePkg/Universal/Variable/VariableRuntimeDxe/InsydeSecureVariable.c

999 lines
32 KiB
C

/** @file
Provide support functions for insyde secure variable.
;******************************************************************************
;* Copyright (c) 2012 - 2018, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "InsydeSecureVariable.h"
#include "AuthService.h"
#include "VarDefault.h"
#include <Protocol/Bds.h>
EFI_BDS_ENTRY mOriginalBdsEntry;
/**
Check the input Insyde variable password size is correct.
@param[in] Data Pointer to a buffer of the variable contents.
@param[in] DataSize Size of Data buffer.
@retval TRUE The password size is correct.
@retval FALSE The password size is incorrect.
**/
STATIC
BOOLEAN
IsPasswordSizeCorrect (
IN CONST UINT8 *Data,
IN UINTN DataSize
)
{
UINT8 PasswordLen;
if (Data == NULL) {
return FALSE;
}
PasswordLen = *(Data + INSYDE_VARIABLE_PASSWORD_HEADER_SIZE);
if (INSYDE_VARIABLE_PASSWORD_HEADER_SIZE + sizeof (UINT8) + PasswordLen + sizeof (UINT8) != DataSize) {
return FALSE;
}
return TRUE;
}
/**
Check Insyde password state is locked or unlocked.
@retval TRUE Insyde password is in locked state.
@retval FALSE Insyde password is in unlocked state.
**/
STATIC
BOOLEAN
IsInsydePasswordLocked (
VOID
)
{
if (mSmst == NULL) {
return mVariableModuleGlobal->InsydeSecureVariableLocked;
} else {
return mSmmVariableGlobal->ProtectedModeVariableModuleGlobal->InsydeSecureVariableLocked;
}
}
/**
Change the Insyde password state to unlocked state.
@retval EFI_SUCCESS Change Insyde variable state to unlocked state.
@retval EFI_ALREADY_STARTED The password state is already in unlocked state.
**/
STATIC
EFI_STATUS
UnlockInsydePassword (
VOID
)
{
if (!IsInsydePasswordLocked ()) {
return EFI_ALREADY_STARTED;
}
if (mSmst == NULL) {
mVariableModuleGlobal->InsydeSecureVariableLocked = FALSE;
} else {
mSmmVariableGlobal->ProtectedModeVariableModuleGlobal->InsydeSecureVariableLocked = FALSE;
}
return EFI_SUCCESS;
}
/**
Change the Insyde password state to locked state.
@retval EFI_SUCCESS Change Insyde variable state to locked state.
@retval EFI_ALREADY_STARTED The password state is already in locked state.
**/
STATIC
EFI_STATUS
LockInsydePassword (
VOID
)
{
if (IsInsydePasswordLocked ()) {
return EFI_ALREADY_STARTED;
}
if (mSmst == NULL) {
mVariableModuleGlobal->InsydeSecureVariableLocked = TRUE;
} else {
mSmmVariableGlobal->ProtectedModeVariableModuleGlobal->InsydeSecureVariableLocked = TRUE;
}
return EFI_SUCCESS;
}
/**
This function uses input data to calculate encrypted hash data. User need allocate buffer
for EncryptedHashData buffer before invoking this function.
@param[in] Data Pointer to input original data buffer.
@param[out] EncryptedHashData Pointer to output encrypted hash data buffer.
@retval EFI_SUCCESS The hash data is same as the content of AdminPassword.
@retval EFI_UNSUPPORTED System doesn't support hash protocol.
@retval EFI_INVALID_PARAMETER Data or EncryptedHashData is NULL.
**/
STATIC
EFI_STATUS
GetEncryptedHashData (
IN VOID *Data,
OUT VOID *EncryptedHashData
)
{
EFI_STATUS Status;
EFI_HASH_OUTPUT Digest;
UINTN PasswordLen;
UINT8 *WorkingData;
CHAR8 CombinedData[CERT_DATA_SIZE];
if (Data == NULL || EncryptedHashData == NULL) {
return EFI_INVALID_PARAMETER;
}
if (mHash == NULL) {
return EFI_UNSUPPORTED;
}
WorkingData = (UINT8 *) Data;
PasswordLen = (UINTN) *WorkingData;
ZeroMem (CombinedData, CERT_DATA_SIZE);
GetCombinedData (WorkingData, PasswordLen + 1, CombinedData);
Digest.Sha256Hash = (EFI_SHA256_HASH *) EncryptedHashData;
if (PasswordLen + 1 > CERT_DATA_SIZE) {
Status = mHash->Hash (
mHash,
&gEfiHashAlgorithmSha256Guid,
FALSE,
(UINT8 *)CombinedData,
CERT_DATA_SIZE,
(EFI_HASH_OUTPUT *) &Digest
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = mHash->Hash (
mHash,
&gEfiHashAlgorithmSha256Guid,
TRUE,
&WorkingData[CERT_DATA_SIZE],
PasswordLen + 1 - CERT_DATA_SIZE,
(EFI_HASH_OUTPUT *) &Digest
);
} else {
Status = mHash->Hash (
mHash,
&gEfiHashAlgorithmSha256Guid,
FALSE,
(UINT8 *)CombinedData,
CERT_DATA_SIZE,
(EFI_HASH_OUTPUT *) &Digest
);
}
return Status;
}
/**
This function uses to hash input data to compare with hash data which saved in AdminPassword
variable. If AdminPassword doesn't exit, return EFI_SUCCESS directly.
@param[in] Data Pointer to data buffer.
@retval EFI_SUCCESS The hash data is same as the content of AdminPassword.
@retval EFI_UNSUPPORTED System doesn't support hash protocol.
@retval EFI_SECURITY_VIOLATION The hash data isn't same as the content of AdminPassword.
**/
STATIC
EFI_STATUS
CheckWithAdminPassword (
IN VOID *Data
)
{
EFI_STATUS Status;
UINTN VariableCount;
VARIABLE_GLOBAL *Global;
VARIABLE_POINTER_TRACK Variable;
VariableCount = 0;
Global = &mVariableModuleGlobal->VariableBase;
Status = FindVariableByLifetimeInAllRegions (EFI_ADMIN_PASSWORD_NAME, &gInsydeSecureFirmwarePasswordGuid, &Variable, &VariableCount, Global);
if (Variable.CurrPtr == NULL) {
Status = EFI_SUCCESS;
} else {
Status = GetEncryptedHashData (Data, mSha256Hash);
if (!EFI_ERROR (Status)) {
if (CompareMem (GetVariableDataPtr (Variable.CurrPtr), mSha256Hash, SHA256_DIGEST_SIZE) != 0) {
Status = EFI_SECURITY_VIOLATION;
}
}
}
return Status;
}
/**
This function uses to execute unlock admin password process.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Attributes Attribute value of the variable found.
@param[in] DataSize Size of Data buffer.
@param[in] Data Pointer to a buffer of the variable contents.
@retval EFI_SUCCESS System changes admin password state to unlocked successful.
@retval EFI_INVALID_PARAMETER Any input parameter is NULL.
@retval EFI_UNSUPPORTED The input data isn't a valid unlock admin password variable.
**/
STATIC
EFI_STATUS
ExecuteUnlockPasswordProcess (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN CONST VOID *Data
)
{
EFI_STATUS Status;
EFI_VARIABLE_AUTHENTICATION *CertData;
if (VariableName == NULL || VendorGuid == NULL || Data == NULL) {
return EFI_INVALID_PARAMETER;
}
if (!IsUnlockPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
return EFI_UNSUPPORTED;
}
CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
Status = CheckWithAdminPassword ((VOID *) &CertData->AuthInfo.CertData);
if (!EFI_ERROR (Status)) {
Status = UnlockInsydePassword ();
}
return Status;
}
/**
This function uses to update the contents of admin password.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Data Pointer to a buffer of the variable contents.
@param[in] DataSize Size of Data buffer.
@param[in] Variable The variable information which is used to keep track of variable usage.
@param[in] Attributes Attribute value of the variable found.
@param[in] Global Pointer to VARIABLE_GLOBAL instance.
@retval EFI_SUCCESS System updates admin password successful.
@retval EFI_INVALID_PARAMETER Any input parameter is NULL.
@retval EFI_UNSUPPORTED The input data isn't a valid admin password variable.
**/
STATIC
EFI_STATUS
UpdateAdminPassword (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN CONST VOID *Data,
IN UINTN DataSize,
IN VARIABLE_POINTER_TRACK *Variable,
IN UINT32 Attributes,
IN VARIABLE_GLOBAL *Global
)
{
EFI_VARIABLE_AUTHENTICATION *CertData;
EFI_STATUS Status;
EFI_TIME TimeStamp;
UINTN UpdateDatasize;
if (VariableName == NULL || VendorGuid == NULL || Data == NULL ||
Variable == NULL || Global == NULL) {
return EFI_INVALID_PARAMETER;
}
if (!IsValidAdminPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
return EFI_UNSUPPORTED;
}
CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
Status = GetEncryptedHashData (&CertData->AuthInfo.CertData, mSha256Hash);
if (EFI_ERROR (Status)) {
return Status;
}
UpdateDatasize = SHA256_DIGEST_SIZE;
if (IsDeleteAdminPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
//
// Set DataSize to 0 to delete original variable.
//
UpdateDatasize = 0;
}
//
// Set all of byte to 0xFF in EFI_TIME in variable header to indicate this is a insyde secure variable.
//
SetMem (&TimeStamp, sizeof (EFI_TIME), 0xFF);
Status = UpdateVariable (
VariableName,
VendorGuid,
(VOID *) mSha256Hash,
UpdateDatasize,
Attributes,
0,
0,
Variable,
&TimeStamp,
Global
);
return Status;
}
/**
This function uses to update normal Insyde secure variable.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Data Pointer to a buffer of the variable contents.
@param[in] DataSize Size of Data buffer.
@param[in] Variable The variable information which is used to keep track of variable usage.
@param[in] Attributes Attribute value of the variable found.
@param[in] Global Pointer to VARIABLE_GLOBAL instance.
@retval EFI_SUCCESS System updates normal Insyde secure variable successful.
@retval EFI_INVALID_PARAMETER Any input parameter is NULL.
@retval EFI_UNSUPPORTED The input contents isn't a valid normal Insyde secure variable.
**/
STATIC
EFI_STATUS
UpdateNormalInsydeVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN CONST VOID *Data,
IN UINTN DataSize,
IN VARIABLE_POINTER_TRACK *Variable,
IN UINT32 Attributes,
IN VARIABLE_GLOBAL *Global
)
{
EFI_TIME TimeStamp;
UINTN UpdateDatasize;
UINT8 *UpdateData;
EFI_STATUS Status;
if (VariableName == NULL || VendorGuid == NULL || Data == NULL ||
Variable == NULL || Global == NULL) {
return EFI_INVALID_PARAMETER;
}
if (!IsNormalInsydeSecureVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
return EFI_UNSUPPORTED;
}
UpdateDatasize = DataSize - INSYDE_VARIABLE_HEADER_SIZE;
UpdateData = (UINT8 *) Data;
UpdateData += INSYDE_VARIABLE_HEADER_SIZE;
//
// Set all of byte to 0xFF in EFI_TIME in variable header to indicate this is a insyde secure variable.
//
SetMem (&TimeStamp, sizeof (EFI_TIME), 0xFF);
Status = UpdateVariable (
VariableName,
VendorGuid,
UpdateData,
UpdateDatasize,
Attributes,
0,
0,
Variable,
&TimeStamp,
Global
);
return Status;
}
/**
This function uses to check the variable is whether a valid Insyde secure variable.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Attributes Attribute value of the variable found.
@param[in] DataSize Size of Data buffer.
@param[in] Data Pointer to a buffer of the variable contents.
@retval TRUE System updates normal Insyde secure variable successful.
@retval FALSE Any input parameter is NULL.
**/
BOOLEAN
IsValidInsydeSecureVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN CONST VOID *Data
)
{
if (IsValidCheckAdminPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data) ||
IsValidAdminPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data) ||
IsNormalInsydeSecureVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
return TRUE;
}
return FALSE;
}
/**
This function uses to check the variable is whether a valid check admin password variable.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Attributes Attribute value of the variable found.
@param[in] DataSize Size of Data buffer.
@param[in] Data Pointer to a buffer of the variable contents.
@retval TRUE This is a valid check admin password variable.
@retval FALSE This isn't a valid check admin password variable.
**/
BOOLEAN
IsValidCheckAdminPasswordVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN CONST VOID *Data
)
{
if (IsUnlockPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data) ||
IsLockPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
return TRUE;
}
return FALSE;
}
/**
This function uses to check the variable is whether an unlock check admin password variable.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Attributes Attribute value of the variable found.
@param[in] DataSize Size of Data buffer.
@param[in] Data Pointer to a buffer of the variable contents.
@retval TRUE This is an unlock check admin password variable.
@retval FALSE This isn't an unlock check admin password variable.
**/
BOOLEAN
IsUnlockPasswordVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN CONST VOID *Data
)
{
UINT8 *Action;
if (VariableName == NULL || VendorGuid == NULL || Data == NULL) {
return FALSE;
}
if (!IsCheckAdminPasswordVariable (VariableName, VendorGuid)) {
return FALSE;
}
if (IsPasswordSizeCorrect (Data, DataSize)) {
Action = (UINT8 *) Data;
Action += (DataSize - sizeof (UINT8));
if (IsInsydeSecureVariable (Attributes, DataSize, Data) && *Action == UNLOCK_SECURE_VARIABLE) {
return TRUE;
}
}
return FALSE;
}
/**
This function uses to check the variable is whether a lock check admin password variable.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Attributes Attribute value of the variable found.
@param[in] DataSize Size of Data buffer.
@param[in] Data Pointer to a buffer of the variable contents.
@retval TRUE This is a lock check admin password variable.
@retval FALSE This isn't a lock check admin password variable.
**/
BOOLEAN
IsLockPasswordVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN CONST VOID *Data
)
{
UINT8 *Action;
if (VariableName == NULL || VendorGuid == NULL || Data == NULL) {
return FALSE;
}
if (!IsCheckAdminPasswordVariable (VariableName, VendorGuid)) {
return FALSE;
}
if (DataSize == LOCK_PASSWORD_VARIABLE_SIZE) {
Action = (UINT8 *) Data;
Action += (LOCK_PASSWORD_VARIABLE_SIZE - sizeof (UINT8));
if (IsInsydeSecureVariable (Attributes, DataSize, Data) && *Action == LOCK_SECURE_VARIABLE) {
return TRUE;
}
}
return FALSE;
}
/**
According to variable name and variable to check this variable is whether a CheckAdminPassword variable.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@retval TRUE This is a CheckAdminPassword variable.
@retval FALSE This isn't a CheckAdminPassword variable.
**/
BOOLEAN
IsCheckAdminPasswordVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid
)
{
if (VariableName != NULL && VendorGuid != NULL) {
if (StrCmp (VariableName, EFI_CHECK_ADMIN_PASSWORD_NAME) == 0 && CompareGuid (VendorGuid, &gInsydeSecureFirmwarePasswordGuid)) {
return TRUE;
}
}
return FALSE;
}
/**
Check the data contents and attributes to determine this is whether a insyde secure variable.
@param[in] Attributes Attribute value of the variable found.
@param[in] DataSize Size of Data buffer.
@param[in] Data Pointer to a buffer of the variable contents.
@retval TRUE This is a AdminPassword variable.
@retval FALSE This isn't a AdminPassword variable.
**/
BOOLEAN
IsInsydeSecureVariable (
IN UINT32 Attributes,
IN UINTN DataSize,
IN CONST VOID *Data
)
{
if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS &&
IsInsydeSecureType (DataSize, Data)) {
return TRUE;
}
return FALSE;
}
/**
Using the data contents to check this is whether a Insyde secure type.
@param[in] DataSize Size of Data buffer.
@param[in] Data Pointer to a buffer of the variable contents.
@retval TRUE This is Insyde secure type.
@retval FALSE This isn't Insyde secure type.
**/
BOOLEAN
IsInsydeSecureType (
IN UINTN DataSize,
IN CONST VOID *Data
)
{
EFI_VARIABLE_AUTHENTICATION *CertData;
if (Data == NULL) {
return FALSE;
}
if (DataSize >= INSYDE_VARIABLE_PASSWORD_HEADER_SIZE + sizeof (UINT8)) {
CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
if (CertData->AuthInfo.Hdr.wCertificateType == WIN_CERT_TYPE_EFI_GUID &&
CompareGuid (&CertData->AuthInfo.CertType, &gIbvCertTypeInsydeSecureGuid)) {
return TRUE;
}
}
return FALSE;
}
/**
This function uses to check the variable is whether a valid admin password variable.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Attributes Attribute value of the variable found.
@param[in] DataSize Size of Data buffer.
@param[in] Data Pointer to a buffer of the variable contents.
@retval TRUE This is a valid admin password variable.
@retval FALSE This isn't a valid admin password variable.
**/
BOOLEAN
IsValidAdminPasswordVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN CONST VOID *Data
)
{
if (IsDeleteAdminPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data) ||
IsReplaceAdminPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
return TRUE;
}
return FALSE;
}
/**
This function uses to check the variable is whether a delete admin password variable.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Attributes Attribute value of the variable found.
@param[in] DataSize Size of Data buffer.
@param[in] Data Pointer to a buffer of the variable contents.
@retval TRUE This is a delete admin password variable.
@retval FALSE This isn't a delete admin password variable.
**/
BOOLEAN
IsDeleteAdminPasswordVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN CONST VOID *Data
)
{
if (VariableName == NULL || VendorGuid == NULL || Data == NULL) {
return FALSE;
}
if (!IsAdminPasswordVariable (VariableName, VendorGuid)) {
return FALSE;
}
if (IsInsydeSecureVariable (Attributes, DataSize, Data) && DataSize == DELETE_PASSWORD_VARIABLE_SIZE) {
return TRUE;
}
return FALSE;
}
/**
This function uses to check the variable is whether a replace admin password variable.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Attributes Attribute value of the variable found.
@param[in] DataSize Size of Data buffer.
@param[in] Data Pointer to a buffer of the variable contents.
@retval TRUE This is a replace admin password variable.
@retval FALSE This isn't a replace admin password variable.
**/
BOOLEAN
IsReplaceAdminPasswordVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN CONST VOID *Data
)
{
UINT8 *WorkingPtr;
if (VariableName == NULL || VendorGuid == NULL || Data == NULL) {
return FALSE;
}
if (!IsAdminPasswordVariable (VariableName, VendorGuid)) {
return FALSE;
}
WorkingPtr = (UINT8 *) Data;
if (IsInsydeSecureVariable (Attributes, DataSize, Data) && IsPasswordSizeCorrect (Data, DataSize) &&
WorkingPtr[DataSize - 1] == REPLACE_ADMIN_PASSWORD) {
return TRUE;
}
return FALSE;
}
/**
According to variable name and variable to check this variable is whether a AdminPassword variable.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@retval TRUE This is a AdminPassword variable.
@retval FALSE This isn't a AdminPassword variable.
**/
BOOLEAN
IsAdminPasswordVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid
)
{
if (VariableName != NULL && VendorGuid != NULL) {
if (StrCmp (VariableName, EFI_ADMIN_PASSWORD_NAME) == 0 && CompareGuid (VendorGuid, &gInsydeSecureFirmwarePasswordGuid)) {
return TRUE;
}
}
return FALSE;
}
/**
This function uses to check the variable is whether a valid admin password variable.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Attributes Attribute value of the variable found.
@param[in] DataSize Size of Data buffer.
@param[in] Data Pointer to a buffer of the variable contents.
@retval TRUE This is a valid admin password variable.
@retval FALSE This isn't a valid admin password variable.
**/
BOOLEAN
IsNormalInsydeSecureVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN CONST VOID *Data
)
{
if (VariableName == NULL || VendorGuid == NULL || Data == NULL) {
return FALSE;
}
if (IsInsydeSecureVariable (Attributes, DataSize, Data) && !IsCheckAdminPasswordVariable (VariableName, VendorGuid) &&
!IsAdminPasswordVariable (VariableName, VendorGuid)) {
return TRUE;
}
return FALSE;
}
/**
This function uses to process Insyde secure variables.
@param[in] VariableName A CHAR16 string of variable name.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Data Pointer to a buffer of the variable contents.
@param[in] DataSize Size of Data buffer.
@param[in] Variable The variable information which is used to keep track of variable usage.
@param[in] Attributes Attribute value of the variable found.
@param[in] Global Pointer to VARIABLE_GLOBAL instance.
@retval EFI_SUCCESS Change Insyde variable state to unlocked state.
@retval EFI_INVALID_PARAMETER Any input parameter is NULL.
@retval EFI_WRITE_PROTECTED Udpate any insyde secure variable except for Unlock password state
when the insyde secure variable state is locked.
**/
EFI_STATUS
ProcessInsydeSecureVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
IN CONST VOID *Data,
IN UINTN DataSize,
IN VARIABLE_POINTER_TRACK *Variable,
IN UINT32 Attributes,
IN VARIABLE_GLOBAL *Global
)
{
EFI_STATUS Status;
if (VariableName == NULL || VendorGuid == NULL || Data == NULL ||
Variable == NULL || Global == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// TODO:
// Normal functionality for Insyde Secure variable has been tested.
// But we don't do sufficient for Insyde secure variable test if Insyde secure variable is
// Stored in variable default store. Need do this once customer need use this feature.
//
if (Variable->CurrPtr != NULL && !IsExistingInsydeSecureVariable (Variable)) {
//
// If caller attempts to change attributes from Insyde secure variable to other attributes, just return
// EFI_WRITE_PROTECTED directly.
//
return EFI_WRITE_PROTECTED;
}
if (!IsValidInsydeSecureVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
return EFI_UNSUPPORTED;
}
if (IsInsydePasswordLocked () &&
!IsUnlockPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
return EFI_WRITE_PROTECTED;
}
if (IsUnlockPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
Status = ExecuteUnlockPasswordProcess (VariableName, VendorGuid, Attributes, DataSize, Data);
} else if (IsLockPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
Status = LockInsydePassword ();
} else if (IsValidAdminPasswordVariable (VariableName, VendorGuid, Attributes, DataSize, Data)) {
Status = UpdateAdminPassword (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, Global);
} else {
Status = UpdateNormalInsydeVariable (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, Global);
}
return Status;
}
/**
This function uses VARIABLE_POINTER_TRACK to check this variable is whether an existing insyde secure variable.
@param[in] Variable The variable information which is used to keep track of variable usage.
@retval TRUE The variable is an existing Insyde secure variable.
@retval FALSE The variable isn't an existing Insyde secure variable.
**/
BOOLEAN
IsExistingInsydeSecureVariable (
IN CONST VARIABLE_POINTER_TRACK *Variable
)
{
EFI_TIME TimeStamp;
if (Variable == NULL || Variable->CurrPtr == NULL) {
return FALSE;
}
//
// If define Insyde secure variable in variable default store, return TRUE directly.
//
if (AddressInVariableDefaultRegion ((EFI_PHYSICAL_ADDRESS) (UINTN) Variable->CurrPtr) &&
(Variable->CurrPtr->Attributes & EFI_VARIABLE_INSYDE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_INSYDE_AUTHENTICATED_WRITE_ACCESS) {
return TRUE;
}
SetMem (&TimeStamp, sizeof (EFI_TIME), 0xFF);
if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0 ||
CompareMem (&TimeStamp, &Variable->CurrPtr->TimeStamp, sizeof (EFI_TIME)) != 0) {
return FALSE;
}
return TRUE;
}
/**
BdsEntry hook function. This function uses to set Insyde variable state to locked
and then enter original BdsEntry ().
@param[in] This The EFI_BDS_ARCH_PROTOCOL instance.
**/
STATIC
VOID
EFIAPI
BdsEntry (
IN EFI_BDS_ARCH_PROTOCOL *This
)
{
mVariableModuleGlobal->InsydeSecureVariableLocked = TRUE;
mOriginalBdsEntry (This);
}
/**
This function uses to hook original BdsEntry ().
@param[in] Event Event whose notification function is being invoked.
@param[in] Event Pointer to the notification function's context.
**/
STATIC
VOID
EFIAPI
BdsCallback (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
EFI_BDS_ARCH_PROTOCOL *Bds;
Status = gBS->LocateProtocol (
&gEfiBdsArchProtocolGuid,
NULL,
(VOID **) &Bds
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
return;
}
mOriginalBdsEntry = Bds->Entry;
Bds->Entry = BdsEntry;
return;
}
/**
Initializes variable store area for non-volatile and volatile variable.
@retval EFI_SUCCESS Hook BdsEntry () successful or register callback () successful.
@retval EFI_OUT_OF_RESOURCES Register callback() for gEfiBdsArchProtocolGuid failed.
**/
EFI_STATUS
InitializeInsydeVariableLockedState (
VOID
)
{
EFI_STATUS Status;
EFI_BDS_ARCH_PROTOCOL *Bds;
EFI_EVENT Event;
VOID *Registration;
Status = gBS->LocateProtocol (
&gEfiBdsArchProtocolGuid,
NULL,
(VOID **) &Bds
);
if (!EFI_ERROR (Status)) {
mOriginalBdsEntry = Bds->Entry;
Bds->Entry = BdsEntry;
} else {
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
BdsCallback,
NULL,
&Event
);
ASSERT_EFI_ERROR (Status);
//
// Register for protocol notifications on this event
//
Status = gBS->RegisterProtocolNotify (
&gEfiBdsArchProtocolGuid,
Event,
&Registration
);
ASSERT_EFI_ERROR (Status);
}
return Status;
}