This module adds Variable Hook and check MemoryOverwriteRequestControlLock.\r
\r
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) Microsoft Corporation.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include <Library/DebugLib.h>\r
#include <Library/BaseLib.h>\r
#include <Library/BaseMemoryLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
#include "Variable.h"\r
\r
+#include <Protocol/VariablePolicy.h>\r
+#include <Library/VariablePolicyHelperLib.h>\r
+#include <Library/VariablePolicyLib.h>\r
+\r
typedef struct {\r
- CHAR16 *VariableName;\r
- EFI_GUID *VendorGuid;\r
+ CHAR16 *VariableName;\r
+ EFI_GUID *VendorGuid;\r
} VARIABLE_TYPE;\r
\r
VARIABLE_TYPE mMorVariableType[] = {\r
- {MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, &gEfiMemoryOverwriteControlDataGuid},\r
- {MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, &gEfiMemoryOverwriteRequestControlLockGuid},\r
+ { MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, &gEfiMemoryOverwriteControlDataGuid },\r
+ { MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, &gEfiMemoryOverwriteRequestControlLockGuid },\r
};\r
\r
-BOOLEAN mMorPassThru = FALSE;\r
+BOOLEAN mMorPassThru = FALSE;\r
\r
-#define MOR_LOCK_DATA_UNLOCKED 0x0\r
-#define MOR_LOCK_DATA_LOCKED_WITHOUT_KEY 0x1\r
-#define MOR_LOCK_DATA_LOCKED_WITH_KEY 0x2\r
+#define MOR_LOCK_DATA_UNLOCKED 0x0\r
+#define MOR_LOCK_DATA_LOCKED_WITHOUT_KEY 0x1\r
+#define MOR_LOCK_DATA_LOCKED_WITH_KEY 0x2\r
\r
#define MOR_LOCK_V1_SIZE 1\r
#define MOR_LOCK_V2_KEY_SIZE 8\r
\r
typedef enum {\r
MorLockStateUnlocked = 0,\r
- MorLockStateLocked = 1,\r
+ MorLockStateLocked = 1,\r
} MOR_LOCK_STATE;\r
\r
BOOLEAN mMorLockInitializationRequired = FALSE;\r
UINT8 mMorLockKey[MOR_LOCK_V2_KEY_SIZE];\r
BOOLEAN mMorLockKeyEmpty = TRUE;\r
BOOLEAN mMorLockPassThru = FALSE;\r
-MOR_LOCK_STATE mMorLockState = MorLockStateUnlocked;\r
+MOR_LOCK_STATE mMorLockState = MorLockStateUnlocked;\r
\r
/**\r
Returns if this is MOR related variable.\r
**/\r
BOOLEAN\r
IsAnyMorVariable (\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID *VendorGuid\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid\r
)\r
{\r
- UINTN Index;\r
+ UINTN Index;\r
\r
- for (Index = 0; Index < sizeof(mMorVariableType)/sizeof(mMorVariableType[0]); Index++) {\r
+ for (Index = 0; Index < sizeof (mMorVariableType)/sizeof (mMorVariableType[0]); Index++) {\r
if ((StrCmp (VariableName, mMorVariableType[Index].VariableName) == 0) &&\r
- (CompareGuid (VendorGuid, mMorVariableType[Index].VendorGuid))) {\r
+ (CompareGuid (VendorGuid, mMorVariableType[Index].VendorGuid)))\r
+ {\r
return TRUE;\r
}\r
}\r
+\r
return FALSE;\r
}\r
\r
**/\r
BOOLEAN\r
IsMorLockVariable (\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID *VendorGuid\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid\r
)\r
{\r
if ((StrCmp (VariableName, MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME) == 0) &&\r
- (CompareGuid (VendorGuid, &gEfiMemoryOverwriteRequestControlLockGuid))) {\r
+ (CompareGuid (VendorGuid, &gEfiMemoryOverwriteRequestControlLockGuid)))\r
+ {\r
return TRUE;\r
}\r
+\r
return FALSE;\r
}\r
\r
EFI_STATUS Status;\r
\r
mMorLockPassThru = TRUE;\r
- Status = VariableServiceSetVariable (\r
- MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,\r
- &gEfiMemoryOverwriteRequestControlLockGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- sizeof(Data),\r
- &Data\r
- );\r
+ Status = VariableServiceSetVariable (\r
+ MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,\r
+ &gEfiMemoryOverwriteRequestControlLockGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ sizeof (Data),\r
+ &Data\r
+ );\r
mMorLockPassThru = FALSE;\r
return Status;\r
}\r
**/\r
EFI_STATUS\r
SetVariableCheckHandlerMorLock (\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID *VendorGuid,\r
- IN UINT32 Attributes,\r
- IN UINTN DataSize,\r
- IN VOID *Data\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN UINT32 Attributes,\r
+ IN UINTN DataSize,\r
+ IN VOID *Data\r
)\r
{\r
EFI_STATUS Status;\r
//\r
// Basic Check\r
//\r
- if (Attributes == 0 || DataSize == 0 || Data == NULL) {\r
+ if ((Attributes == 0) || (DataSize == 0) || (Data == NULL)) {\r
//\r
// Permit deletion for passthru request, deny it otherwise.\r
//\r
}\r
\r
if ((Attributes != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) ||\r
- ((DataSize != MOR_LOCK_V1_SIZE) && (DataSize != MOR_LOCK_V2_KEY_SIZE))) {\r
+ ((DataSize != MOR_LOCK_V1_SIZE) && (DataSize != MOR_LOCK_V2_KEY_SIZE)))\r
+ {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
// Need set here because the data value on flash is different\r
//\r
Status = SetMorLockVariable (MOR_LOCK_DATA_LOCKED_WITH_KEY);\r
- if (EFI_ERROR(Status)) {\r
+ if (EFI_ERROR (Status)) {\r
//\r
// SetVar fail, do not provision the key\r
//\r
if (mMorLockKeyEmpty || (DataSize != MOR_LOCK_V2_KEY_SIZE)) {\r
return EFI_ACCESS_DENIED;\r
}\r
+\r
if ((CompareMem (Data, mMorLockKey, MOR_LOCK_V2_KEY_SIZE) == 0)) {\r
//\r
// Key match - unlock\r
//\r
// Unlock Success\r
//\r
- mMorLockState = MorLockStateUnlocked;\r
+ mMorLockState = MorLockStateUnlocked;\r
mMorLockKeyEmpty = TRUE;\r
- ZeroMem (mMorLockKey, sizeof(mMorLockKey));\r
+ ZeroMem (mMorLockKey, sizeof (mMorLockKey));\r
//\r
// return EFI_ALREADY_STARTED to skip variable set.\r
//\r
//\r
// Key mismatch - Prevent Dictionary Attack\r
//\r
- mMorLockState = MorLockStateLocked;\r
+ mMorLockState = MorLockStateLocked;\r
mMorLockKeyEmpty = TRUE;\r
- ZeroMem (mMorLockKey, sizeof(mMorLockKey));\r
+ ZeroMem (mMorLockKey, sizeof (mMorLockKey));\r
return EFI_ACCESS_DENIED;\r
}\r
}\r
**/\r
EFI_STATUS\r
SetVariableCheckHandlerMor (\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID *VendorGuid,\r
- IN UINT32 Attributes,\r
- IN UINTN DataSize,\r
- IN VOID *Data\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN UINT32 Attributes,\r
+ IN UINTN DataSize,\r
+ IN VOID *Data\r
)\r
{\r
//\r
return EFI_SUCCESS;\r
}\r
\r
+ // Permit deletion when policy is disabled.\r
+ if (!IsVariablePolicyEnabled () && ((Attributes == 0) || (DataSize == 0))) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
//\r
// MorLock variable\r
//\r
// Basic Check\r
//\r
if ((Attributes != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) ||\r
- (DataSize != sizeof(UINT8)) ||\r
- (Data == NULL)) {\r
+ (DataSize != sizeof (UINT8)) ||\r
+ (Data == NULL))\r
+ {\r
return EFI_INVALID_PARAMETER;\r
}\r
+\r
if (mMorLockState == MorLockStateLocked) {\r
//\r
// If lock, deny access\r
//\r
return EFI_ACCESS_DENIED;\r
}\r
+\r
//\r
// grant access\r
//\r
VOID\r
)\r
{\r
- UINTN MorSize;\r
- EFI_STATUS MorStatus;\r
- EFI_STATUS TcgStatus;\r
- VOID *TcgInterface;\r
+ UINTN MorSize;\r
+ EFI_STATUS MorStatus;\r
+ EFI_STATUS Status;\r
+ VARIABLE_POLICY_ENTRY *NewPolicy;\r
\r
if (!mMorLockInitializationRequired) {\r
//\r
//\r
// Check if the MOR variable exists.\r
//\r
- MorSize = 0;\r
+ MorSize = 0;\r
MorStatus = VariableServiceGetVariable (\r
MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
&gEfiMemoryOverwriteControlDataGuid,\r
// can be deduced from the absence of the TCG / TCG2 protocols, as edk2's\r
// MOR implementation depends on (one of) those protocols.\r
//\r
- TcgStatus = gBS->LocateProtocol (\r
- &gEfiTcg2ProtocolGuid,\r
- NULL, // Registration\r
- &TcgInterface\r
- );\r
- if (EFI_ERROR (TcgStatus)) {\r
- TcgStatus = gBS->LocateProtocol (\r
- &gEfiTcgProtocolGuid,\r
- NULL, // Registration\r
- &TcgInterface\r
- );\r
- }\r
-\r
- if (!EFI_ERROR (TcgStatus)) {\r
+ if (VariableHaveTcgProtocols ()) {\r
//\r
// The MOR variable originates from the platform firmware; set the MOR\r
// Control Lock variable to report the locking capability to the OS.\r
// The MOR variable is absent; the platform firmware does not support it.\r
// Lock the variable so that no other module may create it.\r
//\r
- VariableLockRequestToLock (\r
- NULL, // This\r
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
- &gEfiMemoryOverwriteControlDataGuid\r
- );\r
+ NewPolicy = NULL;\r
+ Status = CreateBasicVariablePolicy (\r
+ &gEfiMemoryOverwriteControlDataGuid,\r
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+ VARIABLE_POLICY_NO_MIN_SIZE,\r
+ VARIABLE_POLICY_NO_MAX_SIZE,\r
+ VARIABLE_POLICY_NO_MUST_ATTR,\r
+ VARIABLE_POLICY_NO_CANT_ATTR,\r
+ VARIABLE_POLICY_TYPE_LOCK_NOW,\r
+ &NewPolicy\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = RegisterVariablePolicy (NewPolicy);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, Status));\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ if (NewPolicy != NULL) {\r
+ FreePool (NewPolicy);\r
+ }\r
\r
//\r
// Delete the MOR Control Lock variable too (should it exists for some\r
);\r
mMorLockPassThru = FALSE;\r
\r
- VariableLockRequestToLock (\r
- NULL, // This\r
- MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,\r
- &gEfiMemoryOverwriteRequestControlLockGuid\r
- );\r
+ NewPolicy = NULL;\r
+ Status = CreateBasicVariablePolicy (\r
+ &gEfiMemoryOverwriteRequestControlLockGuid,\r
+ MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,\r
+ VARIABLE_POLICY_NO_MIN_SIZE,\r
+ VARIABLE_POLICY_NO_MAX_SIZE,\r
+ VARIABLE_POLICY_NO_MUST_ATTR,\r
+ VARIABLE_POLICY_NO_CANT_ATTR,\r
+ VARIABLE_POLICY_TYPE_LOCK_NOW,\r
+ &NewPolicy\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = RegisterVariablePolicy (NewPolicy);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, Status));\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ if (NewPolicy != NULL) {\r
+ FreePool (NewPolicy);\r
+ }\r
}\r