mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
OcBootManagementLib: Initial privilege/password support
This commit is contained in:
parent
eedf63f106
commit
f2a92fff9b
@ -305,6 +305,24 @@ typedef struct {
|
||||
CONST CHAR8 *Arguments;
|
||||
} OC_PICKER_ENTRY;
|
||||
|
||||
/**
|
||||
Privilege levels to escalate to
|
||||
**/
|
||||
typedef enum {
|
||||
OcPrivilegeUnauthorized = 0,
|
||||
OcPrivilegeAuthorized = 1
|
||||
} OC_PRIVILEGE_LEVEL;
|
||||
|
||||
/**
|
||||
Request a privilege escalation, for example by prompting for a password.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *OC_REQ_PRIVILEGE)(
|
||||
IN VOID *Context,
|
||||
IN OC_PRIVILEGE_LEVEL Level
|
||||
);
|
||||
|
||||
/**
|
||||
Picker behaviour action.
|
||||
**/
|
||||
@ -358,6 +376,14 @@ typedef struct {
|
||||
//
|
||||
EFI_HANDLE ExcludeHandle;
|
||||
//
|
||||
// Privilege escalation requesting routine.
|
||||
//
|
||||
OC_REQ_PRIVILEGE RequestPrivilege;
|
||||
//
|
||||
// Context to pass to RequestPrivilege, optional.
|
||||
//
|
||||
VOID *PrivilegeContext;
|
||||
//
|
||||
// Enable polling boot arguments.
|
||||
//
|
||||
BOOLEAN PollAppleHotKeys;
|
||||
@ -473,6 +499,31 @@ OcGetDefaultBootEntry (
|
||||
IN UINTN NumBootEntries
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
OC_PRIVILEGE_LEVEL CurrentLevel;
|
||||
CONST UINT8 *Salt;
|
||||
UINT32 SaltSize;
|
||||
CONST UINT8 *Hash;
|
||||
} OC_PRIVILEGE_CONTEXT;
|
||||
|
||||
/**
|
||||
Show simple password prompt and return verification status.
|
||||
|
||||
@param[in] Context Privilege context.
|
||||
@param[in] Level The privilege level to request escalating to.
|
||||
|
||||
@retval EFI_SUCCESS The privilege level has been escalated successfully.
|
||||
@retval EFI_ABORTED The privilege escalation has been aborted.
|
||||
@retval other The system must be considered compromised.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
OcShowSimplePasswordRequest (
|
||||
IN VOID *Context,
|
||||
IN OC_PRIVILEGE_LEVEL Level
|
||||
);
|
||||
|
||||
/**
|
||||
Show simple boot entry selection menu and return chosen entry.
|
||||
|
||||
@ -697,6 +748,7 @@ OcRemoveArgumentFromCmd (
|
||||
/**
|
||||
Append argument to command line without deduplication.
|
||||
|
||||
@param[in, out] Context Picker context. NULL, if a privilege escalation is not required.
|
||||
@param[in, out] CommandLine Argument command line of BOOT_LINE_LENGTH bytes.
|
||||
@param[in] Argument Argument, e.g. -v, slide=0, debug=0x100, etc.
|
||||
@param[in] ArgumentLength Argument length, e.g. L_STR_LEN ("-v").
|
||||
@ -705,9 +757,10 @@ OcRemoveArgumentFromCmd (
|
||||
**/
|
||||
BOOLEAN
|
||||
OcAppendArgumentToCmd (
|
||||
IN OUT CHAR8 *CommandLine,
|
||||
IN CONST CHAR8 *Argument,
|
||||
IN CONST UINTN ArgumentLength
|
||||
IN OUT OC_PICKER_CONTEXT *Context OPTIONAL,
|
||||
IN OUT CHAR8 *CommandLine,
|
||||
IN CONST CHAR8 *Argument,
|
||||
IN CONST UINTN ArgumentLength
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@ -272,12 +272,15 @@
|
||||
#define OCS_EXPOSE_VERSION 2U
|
||||
|
||||
#define OC_MISC_SECURITY_FIELDS(_, __) \
|
||||
_(UINT32 , ScanPolicy , , OC_SCAN_DEFAULT_POLICY , ()) \
|
||||
_(BOOLEAN , AllowNvramReset , , FALSE , ()) \
|
||||
_(BOOLEAN , ExposeSensitiveData , , OCS_EXPOSE_VERSION , ()) \
|
||||
_(BOOLEAN , RequireVault , , TRUE , ()) \
|
||||
_(BOOLEAN , RequireSignature , , TRUE , ()) \
|
||||
_(UINT64 , HaltLevel , , 0x80000000 , ())
|
||||
_(UINT32 , ScanPolicy , , OC_SCAN_DEFAULT_POLICY , ()) \
|
||||
_(BOOLEAN , AllowNvramReset , , FALSE , ()) \
|
||||
_(BOOLEAN , ExposeSensitiveData , , OCS_EXPOSE_VERSION , ()) \
|
||||
_(BOOLEAN , EnablePassword , , FALSE , ()) \
|
||||
_(UINT8 , PasswordHash , [64] , {0} , ()) \
|
||||
_(OC_DATA , PasswordSalt , , OC_EDATA_CONSTR (_, __) , OC_DESTR (OC_DATA)) \
|
||||
_(BOOLEAN , RequireVault , , TRUE , ()) \
|
||||
_(BOOLEAN , RequireSignature , , TRUE , ()) \
|
||||
_(UINT64 , HaltLevel , , 0x80000000 , ())
|
||||
OC_DECLARE (OC_MISC_SECURITY)
|
||||
|
||||
#define OC_MISC_TOOLS_ENTRY_FIELDS(_, __) \
|
||||
|
||||
@ -499,7 +499,7 @@ GetVariableBootArgs (
|
||||
//
|
||||
AsciiSPrint (SlideArgument, ARRAY_SIZE (SlideArgument), "slide=%-03d", Slide);
|
||||
|
||||
if (!OcAppendArgumentToCmd (SlideSupport->BootArgs, SlideArgument, SlideArgumentLength)) {
|
||||
if (!OcAppendArgumentToCmd (NULL, SlideSupport->BootArgs, SlideArgument, SlideArgumentLength)) {
|
||||
//
|
||||
// Broken boot-args, try to overwrite.
|
||||
//
|
||||
|
||||
@ -131,12 +131,29 @@ OcRemoveArgumentFromCmd (
|
||||
|
||||
BOOLEAN
|
||||
OcAppendArgumentToCmd (
|
||||
IN OUT CHAR8 *CommandLine,
|
||||
IN CONST CHAR8 *Argument,
|
||||
IN CONST UINTN ArgumentLength
|
||||
IN OUT OC_PICKER_CONTEXT *Context OPTIONAL,
|
||||
IN OUT CHAR8 *CommandLine,
|
||||
IN CONST CHAR8 *Argument,
|
||||
IN CONST UINTN ArgumentLength
|
||||
)
|
||||
{
|
||||
UINTN Len = AsciiStrLen (CommandLine);
|
||||
EFI_STATUS Status;
|
||||
UINTN Len = AsciiStrLen (CommandLine);
|
||||
|
||||
if (Context != NULL) {
|
||||
Status = Context->RequestPrivilege (
|
||||
Context->PrivilegeContext,
|
||||
OcPrivilegeAuthorized
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
if (Status != EFI_ABORTED) {
|
||||
ASSERT (FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Account for extra space.
|
||||
|
||||
@ -961,7 +961,7 @@ OcWaitForAppleKeyIndex (
|
||||
if (HasShift) {
|
||||
if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-x", L_STR_LEN ("-x")) == NULL) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: Shift means -x\n"));
|
||||
OcAppendArgumentToCmd (Context->AppleBootArgs, "-x", L_STR_LEN ("-x"));
|
||||
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-x", L_STR_LEN ("-x"));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -972,7 +972,7 @@ OcWaitForAppleKeyIndex (
|
||||
if (HasCommand && HasKeyV) {
|
||||
if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-v", L_STR_LEN ("-v")) == NULL) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: CMD+V means -v\n"));
|
||||
OcAppendArgumentToCmd (Context->AppleBootArgs, "-v", L_STR_LEN ("-v"));
|
||||
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-v", L_STR_LEN ("-v"));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -983,7 +983,7 @@ OcWaitForAppleKeyIndex (
|
||||
if (HasCommand && HasKeyC && HasKeyMinus) {
|
||||
if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-no_compat_check", L_STR_LEN ("-no_compat_check")) == NULL) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: CMD+C+MINUS means -no_compat_check\n"));
|
||||
OcAppendArgumentToCmd (Context->AppleBootArgs, "-no_compat_check", L_STR_LEN ("-no_compat_check"));
|
||||
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-no_compat_check", L_STR_LEN ("-no_compat_check"));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -994,7 +994,7 @@ OcWaitForAppleKeyIndex (
|
||||
if (HasCommand && HasKeyK) {
|
||||
if (AsciiStrStr (Context->AppleBootArgs, "kcsuffix=release") == NULL) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: CMD+K means kcsuffix=release\n"));
|
||||
OcAppendArgumentToCmd (Context->AppleBootArgs, "kcsuffix=release", L_STR_LEN ("kcsuffix=release"));
|
||||
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "kcsuffix=release", L_STR_LEN ("kcsuffix=release"));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -1028,11 +1028,11 @@ OcWaitForAppleKeyIndex (
|
||||
if (WantsZeroSlide) {
|
||||
if (AsciiStrStr (Context->AppleBootArgs, "slide=0") == NULL) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: CMD+S+MINUS means slide=0\n"));
|
||||
OcAppendArgumentToCmd (Context->AppleBootArgs, "slide=0", L_STR_LEN ("slide=0"));
|
||||
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "slide=0", L_STR_LEN ("slide=0"));
|
||||
}
|
||||
} else if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-s", L_STR_LEN ("-s")) == NULL) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: CMD+S means -s\n"));
|
||||
OcAppendArgumentToCmd (Context->AppleBootArgs, "-s", L_STR_LEN ("-s"));
|
||||
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-s", L_STR_LEN ("-s"));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -1062,6 +1062,140 @@ OcWaitForAppleKeyIndex (
|
||||
return OC_INPUT_TIMEOUT;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
OcShowSimplePasswordRequest (
|
||||
IN VOID *Context,
|
||||
IN OC_PRIVILEGE_LEVEL Level
|
||||
)
|
||||
{
|
||||
OC_PRIVILEGE_CONTEXT *Privilege;
|
||||
|
||||
BOOLEAN Result;
|
||||
|
||||
UINT8 Password[32];
|
||||
UINT32 PwIndex;
|
||||
|
||||
UINT8 Index;
|
||||
EFI_STATUS Status;
|
||||
EFI_INPUT_KEY Key;
|
||||
|
||||
if (Context == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Privilege = (OC_PRIVILEGE_CONTEXT *)Context;
|
||||
|
||||
if (Privilege->CurrentLevel >= Level) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
gST->ConOut->ClearScreen (gST->ConOut);
|
||||
|
||||
for (Index = 0; Index < 3; ++Index) {
|
||||
PwIndex = 0;
|
||||
//
|
||||
// Skip previously pressed characters.
|
||||
//
|
||||
do {
|
||||
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
|
||||
} while (!EFI_ERROR (Status));
|
||||
|
||||
gST->ConOut->OutputString (gST->ConOut, L"Password: ");
|
||||
|
||||
while (TRUE) {
|
||||
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
|
||||
if (Status == EFI_NOT_READY) {
|
||||
continue;
|
||||
} else if (EFI_ERROR (Status)) {
|
||||
gST->ConOut->ClearScreen (gST->ConOut);
|
||||
ZeroMem (Password, PwIndex);
|
||||
ZeroMem (&Key.UnicodeChar, sizeof (Key.UnicodeChar));
|
||||
|
||||
DEBUG ((DEBUG_ERROR, "Input device error\r\n"));
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
if (Key.ScanCode == SCAN_ESC) {
|
||||
gST->ConOut->ClearScreen (gST->ConOut);
|
||||
ZeroMem (Password, PwIndex);
|
||||
//
|
||||
// ESC aborts the input.
|
||||
//
|
||||
return EFI_ABORTED;
|
||||
} else if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
||||
gST->ConOut->ClearScreen (gST->ConOut);
|
||||
//
|
||||
// RETURN finalizes the input.
|
||||
//
|
||||
break;
|
||||
} else if (Key.UnicodeChar == CHAR_BACKSPACE) {
|
||||
//
|
||||
// Delete the last entered character, if such exists.
|
||||
//
|
||||
if (PwIndex != 0) {
|
||||
--PwIndex;
|
||||
Password[PwIndex] = 0;
|
||||
//
|
||||
// Overwrite current character with a space.
|
||||
//
|
||||
gST->ConOut->SetCursorPosition (
|
||||
gST->ConOut,
|
||||
gST->ConOut->Mode->CursorColumn - 1,
|
||||
gST->ConOut->Mode->CursorRow
|
||||
);
|
||||
gST->ConOut->OutputString (gST->ConOut, L" ");
|
||||
gST->ConOut->SetCursorPosition (
|
||||
gST->ConOut,
|
||||
gST->ConOut->Mode->CursorColumn - 1,
|
||||
gST->ConOut->Mode->CursorRow
|
||||
);
|
||||
}
|
||||
|
||||
continue;
|
||||
} else if (Key.UnicodeChar == CHAR_NULL
|
||||
|| (UINT8)Key.UnicodeChar != Key.UnicodeChar) {
|
||||
//
|
||||
// Only ASCII characters are supported.
|
||||
//
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PwIndex == ARRAY_SIZE (Password)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
gST->ConOut->OutputString (gST->ConOut, L"*");
|
||||
|
||||
Password[PwIndex] = (UINT8)Key.UnicodeChar;
|
||||
++PwIndex;
|
||||
}
|
||||
|
||||
Result = OcVerifyPasswordSha512 (
|
||||
Password,
|
||||
PwIndex,
|
||||
Privilege->Salt,
|
||||
Privilege->SaltSize,
|
||||
Privilege->Hash
|
||||
);
|
||||
|
||||
ZeroMem (Password, PwIndex);
|
||||
|
||||
if (Result) {
|
||||
gST->ConOut->ClearScreen (gST->ConOut);
|
||||
Privilege->CurrentLevel = Level;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
gST->ConOut->ClearScreen (gST->ConOut);
|
||||
DEBUG ((DEBUG_WARN, "Password retry limit exceeded.\r\n"));
|
||||
|
||||
gBS->Stall (5000000);
|
||||
gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
OcRunSimpleBootPicker (
|
||||
IN OC_PICKER_CONTEXT *Context
|
||||
@ -1080,6 +1214,21 @@ OcRunSimpleBootPicker (
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (Context->PickerCommand != OcPickerDefault) {
|
||||
Status = Context->RequestPrivilege (
|
||||
Context->PrivilegeContext,
|
||||
OcPrivilegeAuthorized
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
if (Status != EFI_ABORTED) {
|
||||
ASSERT (FALSE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Context->PickerCommand = OcPickerDefault;
|
||||
}
|
||||
}
|
||||
|
||||
while (TRUE) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: Performing OcScanForBootEntries...\n"));
|
||||
|
||||
|
||||
@ -321,8 +321,11 @@ STATIC
|
||||
OC_SCHEMA
|
||||
mMiscConfigurationSecuritySchema[] = {
|
||||
OC_SCHEMA_BOOLEAN_IN ("AllowNvramReset", OC_GLOBAL_CONFIG, Misc.Security.AllowNvramReset),
|
||||
OC_SCHEMA_BOOLEAN_IN ("EnablePassword", OC_GLOBAL_CONFIG, Misc.Security.EnablePassword),
|
||||
OC_SCHEMA_INTEGER_IN ("ExposeSensitiveData", OC_GLOBAL_CONFIG, Misc.Security.ExposeSensitiveData),
|
||||
OC_SCHEMA_INTEGER_IN ("HaltLevel", OC_GLOBAL_CONFIG, Misc.Security.HaltLevel),
|
||||
OC_SCHEMA_DATAF_IN ("PasswordHash", OC_GLOBAL_CONFIG, Misc.Security.PasswordHash),
|
||||
OC_SCHEMA_DATA_IN ("PasswordSalt", OC_GLOBAL_CONFIG, Misc.Security.PasswordSalt),
|
||||
OC_SCHEMA_BOOLEAN_IN ("RequireSignature", OC_GLOBAL_CONFIG, Misc.Security.RequireSignature),
|
||||
OC_SCHEMA_BOOLEAN_IN ("RequireVault", OC_GLOBAL_CONFIG, Misc.Security.RequireVault),
|
||||
OC_SCHEMA_INTEGER_IN ("ScanPolicy", OC_GLOBAL_CONFIG, Misc.Security.ScanPolicy),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user